/* Собран из design/derived_*.py командой build_ui_derived.py.
   Руками не правится: правка уедет при первой пересборке.
   Область [data-style="derived"] — леса перехода, см. docs/contract-d0.1.md. */


/* ── Правка денег: нижняя полоса, график траншей, полоса версии.

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

   Правил здесь меньше, чем было. Первый подход к сборке экономики показывал
   закупочную в строке, долю маржи и отклонение от шаблона отдела прямо на
   поле; он отвергнут 26–27.08 вместе с закупочной и маржой, и его правила
   (`.cost`, `.pl--bad`, `.pl__mg--bad`, `.dev`, `.plg__d`, `.chg`,
   `.why--stop`) снесены следом. Правило без разметки переживает решение, его
   отменившее, и следующий строитель строит по нему заново.

   Хозяин оставшегося — правка котировки (`derived_money.quote`), единственная
   форма правки денег с 27.08. */
[data-style="derived"] .edbar { position: sticky; bottom: 0; z-index: 5; display: flex; align-items: center;
  gap: var(--s4); padding: var(--s3) var(--s4); background: var(--panel); border-top: 1px solid var(--line);
  box-shadow: 0 -6px 18px rgba(20,40,70,.07); }
[data-style="derived"] .edbar__g { display: flex; flex-direction: column; gap: 2px; }
[data-style="derived"] .edbar__l { font-size: var(--t1); color: var(--muted); }
[data-style="derived"] .edbar__v { font-size: var(--t4); font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .edbar__v--warn { color: var(--high); }
[data-style="derived"] .edbar__act { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }

/* Сверка графика с итогом. Слово рядом с числом: «сходится» само по себе
   ничего не говорит, «расходится на 12,4 млн» говорит, что делать. */
[data-style="derived"] .tally { display: flex; align-items: center; gap: var(--s2); font-size: var(--t2); padding: var(--s2) var(--s3);
  border-radius: var(--r2); }
[data-style="derived"] .tally--ok { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .tally--off { background: var(--high-bg); color: var(--high); }

/* Транш правится строкой: доля, дата, сумма. Сумма считается из доли и не
   вводится руками — два входа в одно число расходятся на первой правке. */
[data-style="derived"] .tranche { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .tranche:last-child { border-bottom: 0; }
[data-style="derived"] .tranche__n { flex: 0 0 20px; height: 20px; border-radius: 50%; background: var(--panel2);
  border: 1px solid var(--line); display: flex; align-items: center; justify-content: center;
  font-size: var(--t1); color: var(--muted); }
[data-style="derived"] .tranche__s { flex: 1; min-width: 0; font-size: 13px; }
[data-style="derived"] .tranche__v { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Причина скидки встаёт рядом со строкой, а не окном поверх: окно закрывает
   то, ради чего причину и пишут. */
[data-style="derived"] .why { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3) var(--s2) var(--s6);
  background: var(--medium-bg); font-size: var(--t2); color: var(--ink2); }
[data-style="derived"] .why input { flex: 1; min-width: 0; }

/* Клавиши названы там, где ими работают: массовый ввод чисел мышью — мучение,
   но узнать о Tab неоткуда, если об этом не сказать на экране. */
[data-style="derived"] .kbd { font-family: "IBM Plex Mono", monospace; font-size: 11px; color: var(--muted); }

/* Итог «было → стало»: правка без прежнего числа не показывает своей цены. */
[data-style="derived"] .edbar__was { display: block; font-size: var(--t1); font-weight: 400; color: var(--muted);
  font-style: normal; }

/* Полоса версии — до правки, а не после сохранения. */
[data-style="derived"] .verbar { display: flex; align-items: center; gap: var(--s2); margin: 0 0 var(--s3);
  padding: var(--s2) var(--s3); background: var(--medium-bg); border-radius: var(--r3);
  font-size: 13px; color: var(--ink2); }
[data-style="derived"] .verbar b { color: var(--ink); }

/* ── Строка правки и её разбор: простое по умолчанию.

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

   Правила заводились под «Экономику · сборку», а с 27.08 стоят в правке
   котировки (`derived_money.quote`): две формы правили одни и те же деньги, и
   визионер выбрал котировочную. Имена оставлены как были — переименование
   ради переименования развело бы `ui/derived.css` с разметкой ради слова. */
[data-style="derived"] .sl { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .sl:last-of-type { border-bottom: 0; }
[data-style="derived"] .sl--on { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .sl--bad { background: var(--high-bg); box-shadow: inset 2px 0 0 var(--high); }
[data-style="derived"] .sl__n { flex: 1; min-width: 0; font-size: var(--t2); display: flex; align-items: center;
  gap: var(--s2); }
[data-style="derived"] .sl__w { display: inline-flex; align-items: center; gap: var(--s1); font-size: var(--t1);
  color: var(--high); white-space: nowrap; }
[data-style="derived"] .sl__q, [data-style="derived"] .sl__p { display: flex; align-items: center; gap: var(--s1); }
[data-style="derived"] .sl__q u, [data-style="derived"] .sl__p u { font-size: var(--t1); color: var(--muted); font-style: normal; }
[data-style="derived"] .sl__t { flex: 0 0 88px; text-align: right; font-size: var(--t2); font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .inp--q { width: 48px; text-align: right; }
[data-style="derived"] .inp--p { width: 66px; text-align: right; }

/* Заголовок группы: свернуть и итог. Ничего больше — массовые действия живут
   в меню группы, а не занимают строку постоянно. */
[data-style="derived"] .sl__g { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  background: var(--panel2); border-bottom: 1px solid var(--line2);
  font-size: var(--t2); color: var(--muted); }
[data-style="derived"] .sl__g b { color: var(--ink2); font-size: 13px; }
[data-style="derived"] .sl__g span:last-child { margin-left: auto; font-weight: 600; color: var(--ink2);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .sl__gx { display: inline-flex; cursor: pointer; }
[data-style="derived"] .sl__add { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  border-top: 1px solid var(--line2); font-size: var(--t2); color: var(--muted);
  cursor: pointer; }

/* Переключатели колонок: скидки, закупочная, валюта. */
[data-style="derived"] .sw { display: flex; align-items: center; gap: var(--s1); margin-left: var(--s3); }
[data-style="derived"] .sw__b { font-size: var(--t1); color: var(--muted); padding: var(--s1) var(--s2); border-radius: var(--rp);
  border: 1px solid var(--line); cursor: pointer; }
[data-style="derived"] .sw__b--on { background: var(--mass-bg); color: var(--mass-work); border-color: var(--mass-work); }

/* Правая панель по выделению. */
[data-style="derived"] .side { display: flex; flex-direction: column; border: 1px solid var(--line);
  border-radius: var(--r3); background: var(--panel); overflow: hidden; align-self: start; }
[data-style="derived"] .side__h { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line); font-size: var(--t2); }
[data-style="derived"] .side__b { padding: var(--s1) var(--s4) var(--s3); }
[data-style="derived"] .side__ask { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3) var(--s4);
  background: var(--medium-bg); font-size: var(--t2); color: var(--ink2); }
[data-style="derived"] .side__was { padding: var(--s3) var(--s4); border-top: 1px solid var(--line); }
[data-style="derived"] .side__wh { font-size: var(--t1); color: var(--muted); margin-bottom: var(--s2); }
[data-style="derived"] .side__wr { display: flex; align-items: baseline; justify-content: space-between;
  padding: var(--s1) 0; font-size: var(--t2); color: var(--ink2); }
[data-style="derived"] .side__wr b { font-variant-numeric: tabular-nums; }
[data-style="derived"] .side__wn { margin-top: var(--s2); font-size: var(--t2); color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .over { color: var(--high); }

/* Условия и график свёрнуты в две строки: развёрнутыми они занимали правую
   колонку целиком, а трогают их раз в сделку, а не раз в минуту. */
[data-style="derived"] .rowfold { display: flex; flex-direction: column; border: 1px solid var(--line);
  border-radius: var(--r3); background: var(--panel); overflow: hidden; }
[data-style="derived"] .rowfold__i { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) var(--s4);
  font-size: 13px; color: var(--ink2); cursor: pointer; }
[data-style="derived"] .rowfold__i + .rowfold__i { border-top: 1px solid var(--line2); }
[data-style="derived"] .rowfold__i span { color: var(--muted); font-size: var(--t2); }
[data-style="derived"] .rowfold__i svg:last-child { margin-left: auto; color: var(--muted); }
[data-style="derived"] .rowfold__w { font-style: normal; font-size: var(--t1); color: var(--medium);
  background: var(--medium-bg); padding: 2px var(--s2); border-radius: var(--r2); }
[data-style="derived"] .rowfold__b { font-style: normal; font-size: var(--t1); color: var(--high);
  background: var(--high-bg); padding: 2px var(--s2); border-radius: var(--r2); }

/* Спокойная полоса: два числа вместо пяти и одна строка помех вместо счёта. */
[data-style="derived"] .edbar--calm .edbar__g { flex: 0 0 auto; }
[data-style="derived"] .edbar__stop { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  border-radius: var(--r2); background: var(--high-bg); color: var(--high); font-size: var(--t2); }


/* ── Полоса-ответ. Первое, что читает глаз: не «Сделки», а что делать.
   Правило 1. Экран, который начинается с существительного, оставляет
   вывод человеку; экран, который начинается с глагола, его уже сделал. */
[data-style="derived"] .answer { display: flex; align-items: center; gap: var(--s4); padding: var(--s4);
  background: var(--mass-bg); border: 1px solid var(--mass-work); border-radius: var(--r3); }
[data-style="derived"] .answer__i { flex: 0 0 var(--s6); height: var(--s6); border-radius: 50%; background: var(--mass-work);
  color: #fff; display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .answer__t { font-size: var(--t3); font-weight: 600; }
[data-style="derived"] .answer__s { font-size: 13px; color: var(--ink2); margin-top: var(--s1); }
[data-style="derived"] .answer .btn { margin-left: auto; }


/* ── Очереди дня. Три, не одна: «горит», «сегодня», «мяч у клиента» —
   разные обязательства, и складывать их в общий список значит прятать
   срочное между несрочным. */
[data-style="derived"] .queues { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); min-height: 0; }
[data-style="derived"] .queue { display: flex; flex-direction: column; min-height: 0;
  border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel); }
[data-style="derived"] .queue__h { display: flex; align-items: center; gap: var(--s2); padding: var(--s3);
  border-bottom: 1px solid var(--line); }
[data-style="derived"] .queue__h .u { font-size: 13px; }
[data-style="derived"] .queue__n { margin-left: auto; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .queue--hot .queue__h { color: var(--high); }
[data-style="derived"] .queue--hot .queue__n { color: var(--high); }
[data-style="derived"] .queue__b { padding: var(--s2); display: flex; flex-direction: column; gap: var(--s2); overflow: hidden; }


/* Дело. Три строки жёстко: что сделать · по чему · почему всплыло.
   Третья строка — причина. Без неё система командует, с ней объясняет. */
[data-style="derived"] .todo { border: 1px solid var(--line); border-radius: var(--r3); padding: var(--s3); background: var(--panel); }
[data-style="derived"] .todo:hover { border-color: var(--muted); }
[data-style="derived"] .todo__t { display: flex; align-items: baseline; gap: var(--s2); font-size: 15px; font-weight: 600; }

/* Заголовок дела обрезается, а не переносится: карточка в колонке шириной в треть
   экрана, и перенос ломает три строки в шесть — очередь перестаёт читаться сверху
   вниз одним движением глаза. Срок справа не сжимается никогда: он и есть причина,
   по которой дело попало в эту очередь. */
[data-style="derived"] .todo__t > span:first-of-type { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
[data-style="derived"] .todo__when { margin-left: auto; font-size: 13px; color: var(--muted); font-weight: 400;
  white-space: nowrap; flex-shrink: 0; }
[data-style="derived"] .todo__when--late { color: var(--high); font-weight: 600; }
[data-style="derived"] .todo__d { font-size: 13px; color: var(--ink2); margin-top: var(--s1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .todo__d b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .todo__why { font-size: 13px; color: var(--muted); margin-top: var(--s1);
  padding-left: var(--s2); border-left: 2px solid var(--line); }
[data-style="derived"] .todo__act { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2); }


/* ── Лента «пока вас не было». Правило 9: изменения не ищутся глазами. */
[data-style="derived"] .since { display: flex; flex-direction: column; min-height: 0; }
[data-style="derived"] .ev { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .ev:last-child { border-bottom: 0; }
[data-style="derived"] .ev__i { flex: 0 0 var(--s5); height: var(--s5); border-radius: 50%; background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .ev__i--ok { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .ev__i--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .ev__b { min-width: 0; }
[data-style="derived"] .ev__t { font-size: 13px; }
[data-style="derived"] .ev__b { overflow: hidden; }
[data-style="derived"] .ev__t, [data-style="derived"] .ev__m { overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .ev__t b { font-weight: 600; }
[data-style="derived"] .ev__m { font-size: 13px; color: var(--muted); margin-top: var(--s1); }


/* ── Месяц. План, факт, разрыв — и прямо названо, чем разрыв закрыть.
   Правило 1 на числах: полоса без вывода это по-прежнему выписка. */
[data-style="derived"] .month { display: flex; align-items: center; gap: var(--s4); }
[data-style="derived"] .month__n { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
[data-style="derived"] .month__l { font-size: 13px; color: var(--muted); }
[data-style="derived"] .meter { flex: 1; height: 8px; border-radius: var(--rp); background: var(--line2); overflow: hidden; display: flex; }
[data-style="derived"] .meter i { display: block; height: 100%; }
[data-style="derived"] .meter .done { background: var(--mass); }
[data-style="derived"] .meter .near { background: var(--medium); }


/* ── Стадия: буква в круге плюс подпись. Правило 8.
   Цвет несёт скорость, буква несёт смысл. При дейтераномалии остаётся буква,
   на плохом проекторе остаётся буква, в чёрно-белой печати остаётся буква. */
[data-style="derived"] .stg { display: inline-flex; align-items: center; gap: var(--s2); white-space: nowrap; }
[data-style="derived"] .stg__c { flex: 0 0 20px; width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; }
[data-style="derived"] .stg--new .stg__c { background: var(--low-bg); color: var(--low); }
[data-style="derived"] .stg--qual .stg__c { background: var(--low-bg); color: var(--ink2); }
[data-style="derived"] .stg--offer .stg__c { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .stg--appr .stg__c { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .stg--deal .stg__c { background: var(--mass-bg); color: var(--mass-work); }


/* ── Раскладка списка сделок. Ширины заданы, а не выведены из содержимого.
   Причина: девять колонок с запретом переноса дают 1437px при 1192 доступных —
   таблица уезжала за панель, и «Прогноз» с «Молчим» пропадали именно у тех,
   кому они нужны. Фиксированная раскладка режет длинное имя многоточием и
   держит правый край на месте: колонка, которая иногда есть, а иногда нет,
   хуже короткой колонки. */
[data-style="derived"] .tbl--deals { table-layout: fixed; }

/* Многоточие только на текстовых колонках. Обрезанный бейдж и обрезанная
   иконка выглядят как дефект, а не как сокращение: у них нет продолжения,
   которое многоточие обещает. */
[data-style="derived"] .tbl--deals td { overflow: hidden; }
[data-style="derived"] .tbl--deals td:nth-child(3), [data-style="derived"] .tbl--deals td:nth-child(7) { text-overflow: ellipsis; }


/* ── Следующий шаг в строке таблицы. Правило 2.
   Просрочка несёт три знака сразу: иконку, слово и цвет. */
[data-style="derived"] .step { display: inline-flex; align-items: center; gap: var(--s2); white-space: nowrap; }
[data-style="derived"] .step__w { color: var(--muted); font-variant-numeric: tabular-nums; }
[data-style="derived"] .step--late { color: var(--high); font-weight: 600; }
[data-style="derived"] .step--late .step__w { color: var(--high); }
[data-style="derived"] .step--none { color: var(--medium); font-weight: 600; }



/* ── Состав сделки. Продукт в строке списка: не «что назвали», а «что продаём».
   Пропуск в составе — метка рядом, потому что отсутствие позиции это факт
   такой же силы, как её наличие, и именно он объясняет двухпроцентный attach. */
/* Метка пропуска не сжимается и не обрезается никогда: обрежется она — и
   колонка теряет смысл, ради которого заведена. Режется состав, он описателен. */
[data-style="derived"] .parts-cell { display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .parts { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .parts__gap { flex-shrink: 0; }

/* Касание: сколько дней молчим. Молчание — это факт, а не отсутствие факта. */
[data-style="derived"] .touch { font-variant-numeric: tabular-nums; color: var(--muted); }
[data-style="derived"] .touch--cold { color: var(--high); font-weight: 600; }


/* ── Прогноз с уликой. Правило 6: бейдж, который нельзя раскрыть,
   требует верить на слово. */
[data-style="derived"] .why { margin-top: var(--s2); padding: var(--s2) var(--s3); background: var(--panel2);
  border: 1px solid var(--line); border-radius: var(--r3); font-size: 13px; color: var(--ink2); }
[data-style="derived"] .why b { font-weight: 600; }
[data-style="derived"] .why__h { display: flex; align-items: center; gap: var(--s2); font-weight: 600;
  color: var(--ink); margin-bottom: var(--s1); }
[data-style="derived"] .why ul { margin: 0; padding-left: var(--s4); }
[data-style="derived"] .why li { margin: 2px 0; }


/* ── Закреплённый итог таблицы. Сумма видимого и сумма выбранного —
   разные числа, и оба нужны в поле зрения, а не после прокрутки. */
[data-style="derived"] .tfoot { display: flex; align-items: center; gap: var(--s4); padding: var(--s3);
  border-top: 1px solid var(--line); background: var(--panel2); font-size: 13px; }
[data-style="derived"] .tfoot b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .tfoot .r { margin-left: auto; }


/* ── Полоса отмены. Правило 4: действие уже сделано, откат под рукой. */
[data-style="derived"] .undo { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  background: var(--ink); color: var(--panel); border-radius: var(--r3); font-size: 13px; }
[data-style="derived"] .undo b { font-weight: 600; }
[data-style="derived"] .undo__t { margin-left: auto; font-variant-numeric: tabular-nums; opacity: .7; }
[data-style="derived"] .undo .btn { background: transparent; border-color: rgba(255,255,255,.35); color: var(--panel); }


/* ── Подсказки клавиш. Правило 3: показаны, а не спрятаны в справку.
   Оператор учится за смену тому, что видит каждый день. */
[data-style="derived"] .keys { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  font-size: 13px; color: var(--muted); }
[data-style="derived"] .keys span { display: inline-flex; align-items: center; gap: var(--s1); }
[data-style="derived"] .keys kbd { font: 500 13px/1 "IBM Plex Mono", monospace; color: var(--ink2);
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--r1); padding: var(--s1); }


/* ── Переключатель плотности. Правило 7. */
[data-style="derived"] .dens { display: inline-flex; padding: 2px; gap: 2px; border: 1px solid var(--line);
  border-radius: var(--r2); background: var(--panel2); }
[data-style="derived"] .dens b { font: 600 13px/1 inherit; padding: var(--s1) var(--s2); border-radius: var(--r2); color: var(--muted); }
[data-style="derived"] .dens b.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-sm); }


/* ── Карточка сделки ────────────────────────────────────────────────────── */
[data-style="derived"] .dhead { display: flex; align-items: flex-start; gap: var(--s4); padding: var(--s4);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .dhead h1 { margin: 0 0 var(--s1); font-size: var(--t5); font-weight: 600; letter-spacing: -.01em; }

/* Направление записи в её шапке. Стоит первым и приглушённо: оно рамка, в
   которой читаются остальные числа, а не число само по себе. */
[data-style="derived"] .dir { display: inline-flex; align-items: center; gap: var(--s1); padding: 2px var(--s2);
  border-radius: var(--r2); background: var(--panel2); border: 1px solid var(--line);
  color: var(--ink2); font-weight: 600; font-size: var(--t2); }
[data-style="derived"] .dhead__m { display: flex; align-items: center; gap: var(--s3); font-size: 13px; color: var(--muted); flex-wrap: wrap; }
[data-style="derived"] .dhead__m b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .dhead__act { margin-left: auto; display: flex; align-items: center; gap: var(--s2); flex-shrink: 0; }


/* Полоса стадий. Пройденное, текущее и «сколько тут стоим» — застревание
   это состояние, а не отсутствие событий. */
[data-style="derived"] .pipe { display: flex; border: 1px solid var(--line); border-radius: var(--r3); overflow: hidden; }
[data-style="derived"] .pipe__s { flex: 1; padding: var(--s3); border-right: 1px solid var(--line); background: var(--panel); }
[data-style="derived"] .pipe__s:last-child { border-right: 0; }
[data-style="derived"] .pipe__s b { display: block; font-size: 13px; font-weight: 600; }
[data-style="derived"] .pipe__s span { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .pipe__s--done { background: var(--panel2); }
[data-style="derived"] .pipe__s--now { background: var(--medium-bg); }
[data-style="derived"] .pipe__s--now b { color: var(--medium); }
[data-style="derived"] .pipe__s--now span { color: var(--medium); }
[data-style="derived"] .pipe__s--next b { color: var(--muted); font-weight: 400; }


/* Следующий шаг крупно, отдельной полосой: он же главная кнопка экрана. */
[data-style="derived"] .next { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  background: var(--high-bg); border: 1px solid var(--high); border-radius: var(--r3); }
[data-style="derived"] .next__i { flex: 0 0 32px; height: 32px; border-radius: 50%; background: var(--high);
  color: #fff; display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .next__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .next__s { font-size: 13px; color: var(--ink2); margin-top: 2px; }
[data-style="derived"] .next__act { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .cols3 { display: grid; grid-template-columns: 340px 1fr 360px; gap: var(--s3); min-height: 0; }
[data-style="derived"] .fld { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .fld:last-child { border-bottom: 0; }
[data-style="derived"] .fld__k { flex: 0 0 118px; color: var(--muted); }
[data-style="derived"] .fld__v { min-width: 0; }
[data-style="derived"] .fld__v b { font-weight: 600; }
[data-style="derived"] .fld__e { margin-left: auto; color: var(--muted); opacity: 0; flex-shrink: 0; }
[data-style="derived"] .fld:hover .fld__e { opacity: 1; }


/* Находка слоя смысла. Улика обязательна: утверждение без улики —
   это мнение машины, и продавец правильно сделает, что не поверит. */
[data-style="derived"] .find { padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); margin-bottom: var(--s2); }
[data-style="derived"] .find--hot { border-color: var(--high); background: var(--high-bg); }
[data-style="derived"] .find__t { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .find__e { font-size: 13px; color: var(--ink2); margin-top: var(--s1);
  padding-left: var(--s2); border-left: 2px solid var(--line); }
[data-style="derived"] .find__a { margin-top: var(--s2); }
[data-style="derived"] .health { display: flex; align-items: baseline; gap: var(--s3); }
[data-style="derived"] .health__n { font-size: 28px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
[data-style="derived"] .health__d { font-size: 13px; color: var(--high); font-weight: 600; white-space: nowrap; }
[data-style="derived"] .health__l { font-size: 13px; color: var(--muted); }


/* Лента событий карточки: тип события несёт иконку, не только текст. */
[data-style="derived"] .feed { display: flex; flex-direction: column; }
[data-style="derived"] .fe { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .fe:last-child { border-bottom: 0; }
[data-style="derived"] .fe__i { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .fe__i--mass { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .fe__i--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .fe__b { min-width: 0; flex: 1; }
[data-style="derived"] .fe__t { font-size: 13px; }
[data-style="derived"] .fe__t b { font-weight: 600; }
[data-style="derived"] .fe__q { font-size: 13px; color: var(--ink2); margin-top: var(--s1); padding: var(--s2);
  background: var(--panel2); border-radius: var(--r2); }
[data-style="derived"] .fe__m { font-size: 13px; color: var(--muted); margin-top: var(--s1); }


/* ── Числа-опоры в шапке карточки. Отношение с клиентом длиной в годы
   не описывается одной суммой сделки: сколько принесли за всё время,
   сколько должны сейчас, сколько лет вместе — это разные вопросы,
   и все три задают до того, как открыть сделку. */
[data-style="derived"] .stats { display: flex; align-items: flex-start; gap: var(--s5); flex-wrap: wrap; }
[data-style="derived"] .stat__n { font-size: var(--t5); font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; white-space: nowrap; }
[data-style="derived"] .stat__n small { font-size: 13px; font-weight: 400; color: var(--muted); }
[data-style="derived"] .stat__l { font-size: 13px; color: var(--muted); margin-top: var(--s1); }
[data-style="derived"] .stat--hot .stat__n { color: var(--high); }


/* ── Доля. Attach — это не отчёт раз в квартал, а свойство продукта,
   которое видно там же, где продукт. */
[data-style="derived"] .share { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0; }
[data-style="derived"] .share__l { flex: 0 0 190px; font-size: 13px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .share__b { flex: 1; height: 8px; border-radius: var(--rp); background: var(--line2); }
[data-style="derived"] .share__b i { display: block; height: 100%; border-radius: var(--rp); background: var(--mass); }
[data-style="derived"] .share--low .share__b i { background: var(--high); }
[data-style="derived"] .share__n { flex: 0 0 54px; text-align: right; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .share--low .share__n { color: var(--high); }


/* ── Установленная база. Главная таблица карточки клиента: то, что у них
   стоит, переживает любую сделку. Состояние — словом и цветом, как везде. */
[data-style="derived"] .tbl--ib { table-layout: fixed; }
[data-style="derived"] .tbl--ib td { overflow: hidden; }
[data-style="derived"] .tbl--ib td:nth-child(1) { text-overflow: ellipsis; }
[data-style="derived"] .tbl--ib .name { font-weight: 600; }
[data-style="derived"] .tag { display: inline-flex; align-items: center; gap: var(--s1); font-size: 13px;
  font-weight: 600; padding: var(--s1) var(--s2); border-radius: var(--rp);
  background: var(--low-bg); color: var(--ink2); white-space: nowrap; }
[data-style="derived"] .tag--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .tag--warn { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .tag--ok { background: var(--mass-bg); color: var(--mass-work); }


/* ── Открытое: обращения, наряды, проекты. Это долги перед клиентом,
   и они старше любой сделки в работе. */
[data-style="derived"] .open { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .open:last-child { border-bottom: 0; }
[data-style="derived"] .open__i { flex: 0 0 var(--s5); height: var(--s5); border-radius: 50%; background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .open__i--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .open__b { min-width: 0; flex: 1; }
[data-style="derived"] .open__t { font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .open__m { font-size: 13px; color: var(--muted); margin-top: var(--s1); }
[data-style="derived"] .open__r { margin-left: auto; text-align: right; flex-shrink: 0; }


/* ── Люди клиента. Роль в решении — не должность: «решает», «влияет»,
   «пользуется» отвечают на другой вопрос, чем «директор по ИТ». */
/* Знак человека стоит на уровне имени, а не посередине блока: строка выросла
   до трёх ярусов (имя, должность, улика), и по центру знак оказывался напротив
   должности — читалось так, будто он к ней и относится. */
[data-style="derived"] .who { display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--s2) var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .who:last-child { border-bottom: 0; }
[data-style="derived"] .who__b { min-width: 140px; flex: 1; }
[data-style="derived"] .who__n { font-size: 13px; font-weight: 600; }
[data-style="derived"] .who__m { font-size: 13px; color: var(--muted); }

/* Улика под должностью отдельной строкой, а не через точку в той же.
   В колонке 296 точек «главный бухгалтер · вёл 3 договора, подписал 0» рвалось
   где придётся — «договора, подписал 0» уезжало третьей строкой, и связка
   «должность и чем она доказана» разваливалась ровно посередине.
   Строка ломается только на границе смысла. */
[data-style="derived"] .who__e { font-size: var(--t1); color: var(--muted); margin-top: 2px; }

/* Метка роли стоит внутри блока человека, а не рядом с ним: снаружи её сносило
   переносом к левому краю, под знак, и она читалась отдельным элементом.
   Внутри зазор родителя на неё не действует — отступ свой. */
[data-style="derived"] .who__b .tag { margin-top: var(--s2); }


/* ── Годы отношения. Полоса лет с суммой: история клиента читается
   как история, а не как список записей по убыванию даты. */
/* Высота держит три яруса: число над столбиком, сам столбик, подпись года.
   До 28.08 ярусов было два и число не показывалось вовсе — график давал форму
   без масштаба. */
[data-style="derived"] .years { display: flex; align-items: flex-end; gap: var(--s1); height: 92px; }
[data-style="derived"] .year__v { font-size: var(--t1); font-style: normal; color: var(--muted);
  line-height: 1; }
[data-style="derived"] .year { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--s1); }
[data-style="derived"] .year i { display: block; width: 100%; border-radius: var(--r1) var(--r1) 0 0; background: var(--mass); }
[data-style="derived"] .year--dim i { background: var(--line); }
[data-style="derived"] .year span { font-size: var(--t1); color: var(--muted); }


/* ── Реквизиты. Справочная половина карточки: её открывают не каждый день,
   но в тот день, когда выставляют счёт или подписывают договор, без неё
   карточка бесполезна. Узкая пара «ключ — значение», ключ не растёт.
   Версия и источник названы: реквизиты меняются, и старый счёт остаётся
   верным для старого платежа. */
[data-style="derived"] .fld--tight .fld__k { flex: 0 0 96px; }
[data-style="derived"] .fld--tight { padding: var(--s2) 0; align-items: flex-start; }
[data-style="derived"] .fld--tight .fld__v { word-break: break-word; white-space: normal; }


/* ── Лист досье. Горизонтальный, а не вертикальный: в столбце шириной 540
   справочная половина вытягивалась на 1385 пикселей и требовала прокрутки там,
   где нужен один взгляд. Четыре колонки кладут то же самое в один экран —
   реквизиты читают не подряд, а выхватывают нужную строку.

   Лист не закрывает рельс и верхнюю полосу: карточка остаётся на месте, и
   видно, откуда пришёл. Уход на отдельный экран рвал бы контекст ради справки. */
/* Подложка и окно держатся экрана, а не документа.
   `absolute` привязывает к странице целиком: в артборде это незаметно — кадр
   ровно в экран, — а в живом интерфейсе страница прокручивается, и окно
   осталось бы в девяноста точках от начала документа. Визионер нажал
   «Подобрать предмет» внизу карточки лида, а окно открылось где-то наверху,
   вне поля зрения. */
[data-style="derived"] .scrim { position: fixed; inset: 0; z-index: 40; background: rgba(20, 18, 16, .32); }

/* Окно держится экрана вместе с подложкой, а не документа: `absolute`
   оставлял его в девяноста точках от начала страницы, и на прокрутке оно
   уезжало из поля зрения вслед за ней.

   `transform: none` и `width: auto` снимают правила рамы (`ui/style.css`),
   которые здесь не отменялись ничем: рама кладёт окно серединой экрана
   (`left: 50%` плюс сдвиг на половину своей ширины) и назначает ему ширину.
   Ширина побеждала пару «слева—справа», а сдвиг на половину уводил окно за
   левый край: визионер нажимал «Выиграна», и форма исхода вставала на
   отрицательной координате — кнопка «Закрыть сделку» оказывалась на x = -305
   при экране 1280. Отменять правило рамы надо здесь, потому что здесь
   назначены и левая, и правая границы. */
[data-style="derived"] .sheet { position: fixed; left: 240px; right: 28px; top: 92px;
  transform: none; width: auto; max-height: calc(100vh - 120px); z-index: 41;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r3);
  box-shadow: 0 24px 64px rgba(20, 18, 16, .22);
  display: flex; flex-direction: column; overflow: hidden; }
[data-style="derived"] .sheet__h { display: flex; align-items: center; gap: var(--s3); padding: var(--s4);
  border-bottom: 1px solid var(--line); flex-shrink: 0; }
[data-style="derived"] .sheet__h h2 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .sheet__h .u { font-size: 13px; }
[data-style="derived"] .sheet__cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0; flex: 1; min-height: 0; }
[data-style="derived"] .sheet__c { padding: var(--s4); border-right: 1px solid var(--line2); overflow: hidden; }
[data-style="derived"] .sheet__c:last-child { border-right: 0; }
[data-style="derived"] .sheet__s { padding-bottom: var(--s4); }
[data-style="derived"] .sheet__s > h3 { margin: 0 0 var(--s2); font-size: 13px; font-weight: 600;
  color: var(--muted); }


/* Компактные реквизиты на самой карточке: три строки, которые называют вслух
   и диктуют по телефону. Остальное — под кликом. */
[data-style="derived"] .req { display: flex; flex-direction: column; }
[data-style="derived"] .req__r { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .req__r:last-of-type { border-bottom: 0; }
[data-style="derived"] .req__k { flex: 0 0 96px; color: var(--muted); }
[data-style="derived"] .req__v { min-width: 0; font-weight: 600; }
[data-style="derived"] .req__more { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2);
  font-size: 13px; font-weight: 600; color: var(--mass-work); cursor: pointer; }


/* Таблица владения данными снята вместе со слоем 1С (`docs/rejected.md`), её
   раскрой доживал в сроках цепочки — экран снесён 27.08. Осталась одна строка:
   `.own__k` стоит в поле кабинета клиента (`ui/src/org.rs`), куда его взяли
   взаймы. Правило держится ради этого зова; уйдёт, когда поле назовут своим
   именем. */
[data-style="derived"] .own__k { flex: 1; min-width: 0; }


/* ── Предмет сделки. Центр карточки, и не список строк котировки.
   Строки котировки отвечают на «сколько выставили». Предмет отвечает на
   «что клиент получит и что у него после этого изменится» — а это другой
   вопрос, и на него нельзя ответить, не сверившись с установленной базой.
   Отсюда сверка прямо в блоке: мест в предмете против мест по факту. */
[data-style="derived"] .subj__v { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  border-bottom: 1px solid var(--line2); font-size: 13px; color: var(--muted); }
[data-style="derived"] .subj__v b { color: var(--ink); font-weight: 600; }
[data-style="derived"] .subj__b { display: grid; grid-template-columns: minmax(0, 1fr) 276px; }

/* Разделитель рисует боковая колонка, а не список: список кончается там, где
   кончились строки, а линия должна идти до низа панели. */
[data-style="derived"] .subj__lines { padding: var(--s1) 0 var(--s2); align-self: start; }
[data-style="derived"] .subj__side { border-left: 1px solid var(--line2); }
[data-style="derived"] .subj__side { padding: var(--s3) var(--s4); }
[data-style="derived"] .sl__g { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) var(--s4) var(--s1);
  font-size: 13px; font-weight: 600; color: var(--muted); }
[data-style="derived"] .sl__g span { margin-left: auto; font-variant-numeric: tabular-nums; }
[data-style="derived"] .sl__r { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s2) var(--s4);
  font-size: 15px; }
[data-style="derived"] .sl__r:hover { background: var(--panel2); }
[data-style="derived"] .sl__n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .sl__q { flex: 0 0 74px; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
[data-style="derived"] .sl__p { flex: 0 0 96px; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
[data-style="derived"] .sl__s { flex: 0 0 92px; text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .sl__m { flex: 0 0 52px; text-align: right; font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .tot { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s2) 0;
  font-size: 13px; }
[data-style="derived"] .tot__l { flex: 1; color: var(--muted); }
[data-style="derived"] .tot__v { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .tot--big { padding-top: var(--s3); margin-top: var(--s2); border-top: 1px solid var(--line); }
[data-style="derived"] .tot--big .tot__l { color: var(--ink); font-weight: 600; font-size: 15px; }
[data-style="derived"] .tot--big .tot__v { font-size: 22px; letter-spacing: -.01em; }


/* Сверка предмета с установленной базой. Единственное место, где сделка,
   клиент и продукт встречаются в одной строке — и где расхождение видно
   до того, как счёт уйдёт клиенту. */
[data-style="derived"] .check { display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4); background: var(--medium-bg);
  border-top: 1px solid var(--medium); border-bottom: 1px solid var(--medium); }
[data-style="derived"] .check__i { flex: 0 0 22px; height: 22px; border-radius: 50%; background: var(--medium);
  color: #fff; display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .check__t { font-size: 13px; font-weight: 600; color: var(--medium); }
[data-style="derived"] .check__d { font-size: 13px; color: var(--ink2); margin-top: 2px; }
[data-style="derived"] .check__a { margin-left: auto; flex-shrink: 0; }


/* Что изменится у клиента: до и после в одной строке. Сделка перестаёт быть
   суммой и становится переходом установленной базы из состояния в состояние. */
[data-style="derived"] .delta { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--line); }
[data-style="derived"] .delta__c { padding: var(--s3) var(--s4); border-right: 1px solid var(--line2); }
[data-style="derived"] .delta__c:last-child { border-right: 0; }
[data-style="derived"] .delta__k { font-size: 13px; color: var(--muted); }
[data-style="derived"] .delta__v { font-size: 13px; margin-top: var(--s1); display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .delta__was { color: var(--muted); text-decoration: line-through; }
[data-style="derived"] .delta__now { font-weight: 600; }


/* Лента компактно: три последних события одной строкой каждое. Полная лента
   открывается окном — она нужна редко и целиком, а не всё время и урывками. */
[data-style="derived"] .fe--mini { padding: var(--s2) 0; }
[data-style="derived"] .fe--mini .fe__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .modal { position: fixed; z-index: 41; left: 50%; top: 90px; transform: translateX(-50%);
  width: 760px; max-height: calc(100vh - 140px);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r3); box-shadow: 0 24px 64px rgba(20, 18, 16, .22);
  display: flex; flex-direction: column; overflow: hidden; }
[data-style="derived"] .modal__h { display: flex; align-items: center; gap: var(--s3); padding: var(--s4);
  border-bottom: 1px solid var(--line); flex-shrink: 0; }
[data-style="derived"] .modal__h h2 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -.01em; }

/* Прокрутка внутри тела, а не всего окна: шапка с поиском и подвал со счётом
   обязаны стоять на месте, пока перебирают длинный список. */
[data-style="derived"] .modal__b { padding: var(--s1) var(--s4) var(--s4); overflow-y: auto;
  min-height: 0; flex: 1; }


/* ── Правка предмета. Три решения, и каждое отвечает на «как это редактируют».

   Первое: правят на месте. Количество, цена и скидка меняются в строке, без
   модального окна: итог справа пересчитывается на глазах, и человек видит, что
   делает его правка с маржой, пока он её делает, а не после «Сохранить».

   Второе: правка рождает черновик редакции. Клиент продолжает видеть принятую
   редакцию 3, пока продавец собирает четвёртую. Иначе принятая котировка
   меняется под клиентом, и «сумма не менялась с 19.08» перестаёт быть правдой.

   Третье: цена приходит из прайса, а не из головы. Изменённая руками помечена,
   и пометка переживает сохранение — иначе не отличить скидку от опечатки. */
[data-style="derived"] .ed { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  background: var(--medium-bg); border-bottom: 1px solid var(--medium); font-size: 13px; }
[data-style="derived"] .ed b { font-weight: 600; }
[data-style="derived"] .ed__act { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .sl__r--ed { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .stp { display: inline-flex; align-items: center; border: 1px solid #939392;
  border-radius: var(--r1); overflow: hidden; background: var(--panel); }
[data-style="derived"] .stp b { padding: 0 var(--s2); font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
  min-width: 46px; text-align: center; }
[data-style="derived"] .stp i { display: flex; align-items: center; justify-content: center; width: 24px; height: 26px;
  color: var(--muted); font-style: normal; font-size: 15px; }
[data-style="derived"] .stp i:hover { background: var(--line2); color: var(--ink); }

/* Цвет текста поля назван явно: браузер красит содержимое `input` своим
   чёрным, а фон поле берёт из темы — в тёмной ветке набранное число тонуло
   в подложке. */
[data-style="derived"] .inp { display: inline-flex; align-items: center; justify-content: flex-end;
  height: 28px; padding: 0 var(--s2); border: 1px solid #939392; border-radius: var(--r1);
  background: var(--panel); color: var(--ink);
  font-variant-numeric: tabular-nums; font-weight: 600; }
[data-style="derived"] .inp--on { border-color: var(--mass-work); box-shadow: 0 0 0 3px var(--mass-bg); }
[data-style="derived"] .psrc { font-size: 13px; color: var(--muted); white-space: nowrap; }
[data-style="derived"] .psrc--hand { color: var(--medium); font-weight: 600; }


/* Кнопка добавления стоит под строками с воздухом, а не пунктирной полосой
   впритык: впритык она читается как ещё одна строка предмета. Подбор она не
   вставляет между строками и итогом, а открывает панель внизу — там ему
   хватает ширины на четыре предложения в ряд вместо двух в колонке. */
[data-style="derived"] .addbar { display: flex; align-items: center; gap: var(--s3); padding: var(--s4); }
[data-style="derived"] .addbar kbd { font: 500 13px/1 "IBM Plex Mono", monospace; color: var(--ink2);
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--r1);
  padding: var(--s1); }


/* ── Подбор. Первая дверь — установленная база клиента, а не каталог.
   У партнёра 1С большинство продаж это доп. места, продление и обновление
   того, что уже стоит: каталог первым экраном заставляет искать то, что
   система и так знает. Каждое предложение объясняет, почему оно здесь. */
[data-style="derived"] .pick { border-top: 1px solid var(--mass-work); background: var(--panel2); flex-shrink: 0; }
[data-style="derived"] .pick__h { display: flex; align-items: center; gap: var(--s1); padding: var(--s3) var(--s4) 0; }
[data-style="derived"] .pick__t { padding: var(--s2) var(--s3); border-radius: var(--r1); font-size: 15px; font-weight: 600;
  color: var(--muted); white-space: nowrap; }
[data-style="derived"] .pick__t--on { background: var(--mass-work); color: #fff; }
[data-style="derived"] .pick__s { margin-left: auto; display: flex; align-items: center; gap: var(--s2);
  flex: 0 0 236px; height: 30px; padding: 0 var(--s3); border: 1px solid #939392;
  border-radius: var(--r1); background: var(--panel); color: var(--muted); font-size: 13px;
  white-space: nowrap; }
[data-style="derived"] .pick__b { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2);
  padding: var(--s3) var(--s4) var(--s4); }
[data-style="derived"] .pick__i { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r1); }
[data-style="derived"] .pick__i:hover { border-color: var(--mass-work); }
[data-style="derived"] .pick__ic { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--mass-bg);
  color: var(--mass-work); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .pick__n { font-size: 15px; font-weight: 600; }
[data-style="derived"] .pick__w { font-size: 13px; color: var(--ink2); margin-top: var(--s1); }

/* Цена отдельной строкой под причиной, а не в конкуренции с именем: в карточке
   шириной 240 имя и число в одной строке ломают имя на три. */
[data-style="derived"] .pick__p { display: flex; align-items: baseline; gap: var(--s2); margin-top: var(--s2);
  padding-top: var(--s2); border-top: 1px solid var(--line2); }
[data-style="derived"] .pick__p b { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .pick__p span { font-size: 13px; color: var(--muted); }


/* ── Живые проверки. Правило, которое срабатывает после сохранения, ловит
   ошибку тогда, когда её уже увидел клиент. Здесь они считаются на каждое
   изменение и делятся на три силы: держит согласование, предупреждает,
   подтверждает. */
[data-style="derived"] .rule { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .rule:last-child { border-bottom: 0; }
[data-style="derived"] .rule__i { flex: 0 0 22px; height: 22px; border-radius: 50%; display: flex;
  align-items: center; justify-content: center; }
[data-style="derived"] .rule--stop .rule__i { background: var(--high); color: #fff; }
[data-style="derived"] .rule--warn .rule__i { background: var(--medium); color: #fff; }
[data-style="derived"] .rule--ok .rule__i { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .rule__t { font-size: 13px; font-weight: 600; }
[data-style="derived"] .rule--stop .rule__t { color: var(--high); }
[data-style="derived"] .rule--warn .rule__t { color: var(--medium); }
[data-style="derived"] .rule__d { font-size: 13px; color: var(--ink2); margin-top: 2px; }


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

   Что несёт строка и в каком порядке. Знак типа: лицензия, подписка, час и
   доработка живут по разным законам, и тип виден раньше, чем прочитано имя.
   Знак нейтрального тона — цвет в этой системе занят состоянием, и отдавать
   его типу значит потерять состояние. Дальше имя, под ним источник или
   оговорка. Затем количество, цена, сумма — тремя выровненными колонками.
   Последней маржа полоской: число рядом с числом не сравнивается взглядом,
   полоска сравнивается сразу и сверху вниз. */
[data-style="derived"] .plg { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s2) var(--s4);
  background: var(--panel2); border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line); }
[data-style="derived"] .plg b { font-size: 13px; font-weight: 600; color: var(--muted); }
[data-style="derived"] .plg u { text-decoration: none; font-size: 13px; color: var(--muted); }
[data-style="derived"] .plg span { margin-left: auto; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .pl { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .pl:hover { background: var(--panel2); }
[data-style="derived"] .pl--ed { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .pl__g { flex: 0 0 var(--s6); height: var(--s6); border-radius: var(--r2); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .pl__m { min-width: 0; flex: 1; }
[data-style="derived"] .pl__n { display: block; font-size: var(--t3); font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .pl__s { display: block; font-size: 13px; color: var(--muted); margin-top: var(--s1); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .pl__s--warn { color: var(--medium); font-weight: 600; }
[data-style="derived"] .pl__q { flex: 0 0 92px; text-align: right; color: var(--ink2);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
[data-style="derived"] .pl__q u { text-decoration: none; color: var(--muted); }
[data-style="derived"] .pl__p { flex: 0 0 96px; text-align: right; color: var(--muted);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .pl__t { flex: 0 0 100px; text-align: right; font-size: var(--t3); font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .pl__mg { flex: 0 0 58px; }
[data-style="derived"] .pl__mg b { display: block; text-align: right; font-size: 13px; color: var(--muted);
  font-weight: 400; font-variant-numeric: tabular-nums; }
[data-style="derived"] .pl__mg i { display: block; height: 4px; border-radius: var(--r1); background: var(--line);
  margin-top: var(--s1); overflow: hidden; }
[data-style="derived"] .pl__mg i u { display: block; height: 100%; background: var(--ink2); }
[data-style="derived"] .pl__x { flex: 0 0 24px; text-align: right; color: var(--muted); }
[data-style="derived"] .pl__tag { flex: 0 0 auto; }


/* Документ цепочки. Документа либо нет, либо он есть и где-то лежит —
   третьего состояния «наверное, Ш. отправила» быть не должно. */
[data-style="derived"] .doc { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .doc:last-child { border-bottom: 0; }
[data-style="derived"] .doc__i { flex: 0 0 26px; height: 26px; border-radius: var(--r2); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .doc__i--none { background: transparent; border: 1px dashed var(--line); color: var(--muted); }
[data-style="derived"] .doc__m { min-width: 0; flex: 1; }
[data-style="derived"] .doc__n { font-size: 13px; font-weight: 600; }
[data-style="derived"] .doc__s { font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .doc__r { margin-left: auto; flex-shrink: 0; }


/* Пин-код лицензии. Единственное место, где CRM держит то, что нельзя
   потерять: регистрационный номер и пин-коды приходят от вендора один раз. */
[data-style="derived"] .pin { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3);
  background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r2);
  margin-bottom: var(--s2); }
[data-style="derived"] .pin__k { flex: 0 0 150px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .pin__v { font-family: "IBM Plex Mono", monospace; font-size: 13px; font-weight: 500;
  letter-spacing: .04em; }
[data-style="derived"] .pin__r { margin-left: auto; }


/* ── Окно подбора. Полосой внизу подбор упирался в ширину карточки и в
   четыре предложения; окно даёт список, выбор нескольких сразу и бегущий
   итог. Подбор — это набор, а не по одной позиции: продлить подписку и
   добавить места идут вместе, потому что и повод у них один. */
[data-style="derived"] .oi { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .oi:last-child { border-bottom: 0; }
[data-style="derived"] .oi:hover { background: var(--panel2); }
[data-style="derived"] .oi--on { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .oi__g { flex: 0 0 30px; height: 30px; border-radius: var(--r2); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .oi__m { min-width: 0; flex: 1; }
[data-style="derived"] .oi__n { display: block; font-size: 15px; font-weight: 600; }
[data-style="derived"] .oi__w { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .oi__q { flex: 0 0 96px; text-align: right; color: var(--muted);
  font-variant-numeric: tabular-nums; font-size: 13px; }
[data-style="derived"] .oi__p { flex: 0 0 100px; text-align: right; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .oi__b { flex: 0 0 104px; text-align: right; }
[data-style="derived"] .modal__f { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line); background: var(--panel2); flex-shrink: 0; }
[data-style="derived"] .modal__f b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .modal__f .btn { margin-left: 0; }
[data-style="derived"] .modal__f .r { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }


/* ── Два вида карточки сделки. Карточка пухла, потому что отвечала на два
   разных вопроса сразу: «где мы в работе» и «что и на каких условиях продаём».
   Это разные вопросы, к ним приходят разные люди в разное время — продавец
   в работе и финансовый контроль на согласовании — и держать их на одном
   полотне значит мешать обоим.

   Вид переключается там же, где виды списка: одна идиома на весь интерфейс. */
[data-style="derived"] .terms { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s4); }
[data-style="derived"] .term { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .term__k { flex: 0 0 148px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .term__v { min-width: 0; font-size: 13px; }
[data-style="derived"] .term__v b { font-weight: 600; }
[data-style="derived"] .term__v u { text-decoration: none; color: var(--medium); font-weight: 600; }


/* Транши. График платежей — часть предмета, а не приложение к нему:
   от него зависит, когда деньги увидит компания, а не только сколько. */
[data-style="derived"] .tr { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .tr:last-child { border-bottom: 0; }
[data-style="derived"] .tr__i { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; }
[data-style="derived"] .tr__m { flex: 1; min-width: 0; }
[data-style="derived"] .tr__n { display: block; font-size: 13px; font-weight: 600; }
[data-style="derived"] .tr__d { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .tr__s { text-align: right; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }



/* ── Полотно. Вторая и последняя рама приложения.

   Экранов два рода. Запись — у неё есть контекст, который не меняется, и вид,
   который переключается: этим занимается `.rec`. Полотно — список, верстак,
   рабочая область: у него нет постоянного контекста, есть колонки или полосы
   работы. Раньше полотна собирались из россыпи панелей ядра, и получалось
   лоскутное одеяло — то же, что мы разбирали на карточке сделки, только
   рассыпанное по девяти экранам.

   Обе рамы устроены одинаково: один борт снаружи, разделы волосяной линией
   внутри, никаких вложенных карточек с собственной тенью. Отличаются только
   тем, что внутри: у записи контекст и вид, у полотна колонки. */
[data-style="derived"] .board { border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel);
  overflow: hidden; display: flex; flex-direction: column; flex: 1; min-height: 0; }
[data-style="derived"] .board__h { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line); background: var(--panel2); flex-shrink: 0; }
[data-style="derived"] .board__h h2 { margin: 0; font-size: 15px; font-weight: 600; }
[data-style="derived"] .board__h .u { font-size: 13px; }
[data-style="derived"] .board__h .btn { margin-left: auto; }
[data-style="derived"] .board__b { flex: 1; min-height: 0; overflow: hidden; }
[data-style="derived"] .board__cols { display: grid; flex: 1; min-height: 0; }
[data-style="derived"] .board__c { border-right: 1px solid var(--line); min-width: 0; overflow: hidden;
  display: flex; flex-direction: column; }
[data-style="derived"] .board__c:last-child { border-right: 0; }


/* ── Карточка записи. Одна рама вместо двенадцати.

   Что было не так. Двенадцать отдельных коробок на экране, у каждой своя
   граница, радиус и тень: получается лоскутное одеяло, где всё одинаково
   важно, а значит ничего не важно. Плюс две полосы шагов сразу — воронка и
   цепочка исполнения, — которые наполовину показывают одно и то же:
   «Согласование» и «Договор» стоят в обеих.

   Что вместо. Одна рама, внутри неё две зоны. Слева контекст, который не
   меняется при переключении вида: кто клиент, кто решает, чья сделка, когда
   закрытие, сколько денег, здоровье. Справа зона вида. Разделы внутри
   отделяются волосяной линией, а не собственной рамкой с тенью, — порядок
   чтения задаётся ритмом, а не бортами.

   Полоса шагов осталась одна: цепочка от обращения до отгрузки. Стадия
   воронки и так стоит в шапке значком, повторять её строем из шести клеток
   значит показывать одно дважды. */
[data-style="derived"] .rec { border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel);
  overflow: hidden; display: flex; flex-direction: column; flex: 1; min-height: 0; }
[data-style="derived"] .rec__tabs { display: flex; align-items: center; gap: var(--s1); padding: 0 var(--s4);
  border-bottom: 1px solid var(--line); background: var(--panel2); }
[data-style="derived"] .rec__b { display: grid; grid-template-columns: 296px minmax(0, 1fr);
  flex: 1; min-height: 0; }

/* Полоса исполнения принадлежит объекту, а не виду: в правой зоне ей не
   хватало ширины и имена шагов резались до «Обр…». Под вкладками во всю
   ширину она читается целиком и одинаково видна из обоих видов. */
[data-style="derived"] .rec__chain { padding: var(--s3) var(--s4) var(--s4); border-bottom: 1px solid var(--line); }
[data-style="derived"] .rec__chain__h { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2); }
[data-style="derived"] .rec__chain__h .u { font-size: 13px; }
[data-style="derived"] .rec__ctx { border-right: 1px solid var(--line); background: var(--panel2);
  overflow: hidden; }
[data-style="derived"] .rec__view { overflow: hidden; display: flex; flex-direction: column; }
[data-style="derived"] .sec { padding: var(--s4); border-bottom: 1px solid var(--line2); }
[data-style="derived"] .sec:last-child { border-bottom: 0; }
[data-style="derived"] .sec--flush { padding: 0; }
[data-style="derived"] .sec--tight { padding: var(--s3) var(--s4); }
[data-style="derived"] .sec__h { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2); }
[data-style="derived"] .sec__h h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--muted); }
[data-style="derived"] .sec__h .u { font-size: 13px; }
[data-style="derived"] .sec__h .btn { margin-left: auto; }
[data-style="derived"] .sec--flush .sec__h { padding: var(--s4) var(--s4) var(--s3); margin-bottom: 0; }


/* Контекстная строка левой колонки: ключ узкий, значение живое. */
[data-style="derived"] .cx { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  font-size: 13px; }
[data-style="derived"] .cx__k { flex: 0 0 92px; color: var(--muted); }
[data-style="derived"] .cx__v { min-width: 0; }
[data-style="derived"] .cx__v b { font-weight: 600; }

/* Ссылка на связанный объект: знак идёт вплотную к тексту, а не в колонке
   ключа — у неё нет ключа, есть только куда. */
[data-style="derived"] .lnk { display: flex; align-items: flex-start; gap: var(--s2); padding: var(--s2) 0;
  font-size: 13px; color: var(--ink2); }
[data-style="derived"] .lnk b { font-weight: 600; color: var(--ink); }
[data-style="derived"] .lnk > svg { flex: 0 0 14px; margin-top: 2px; color: var(--muted); }


/* ── Обращение и лид ─────────────────────────────────────────────────────

   Тело обращения. То, что человек написал или сказал, показывается целиком и
   как есть: пересказ системы поверх исходника — это уже интерпретация, а на
   первом шаге интерпретировать рано. */
[data-style="derived"] .msg { padding: var(--s3) var(--s4); background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r2); font-size: 15px; line-height: var(--lh2); }
[data-style="derived"] .msg__m { display: flex; align-items: center; gap: var(--s2); font-size: 13px;
  color: var(--muted); margin-bottom: var(--s2); }
[data-style="derived"] .msg__m b { color: var(--ink); font-weight: 600; }


/* Узнавание. Главный вопрос первого шага не «что просят», а «кто это»:
   существующий клиент с историей и своя же поддержка ведут себя иначе, чем
   человек с улицы. Основание узнавания названо — по чему совпало. */
[data-style="derived"] .reco { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3) var(--s4);
  background: var(--mass-bg); border: 1px solid var(--mass-work); border-radius: var(--r2); }
[data-style="derived"] .reco__i { flex: 0 0 32px; height: 32px; border-radius: var(--r2); background: var(--mass-work);
  color: #fff; display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .reco__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .reco__d { font-size: 13px; color: var(--ink2); margin-top: var(--s1); }
[data-style="derived"] .reco__a { margin-left: auto; flex-shrink: 0; }


/* Маршрут. Куда это идёт и почему — с основанием, а не одной кнопкой:
   выбор между продажей и поддержкой стоит денег, и он должен быть объясним. */
[data-style="derived"] .route { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
[data-style="derived"] .route__c { padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--r2);
  background: var(--panel); }
[data-style="derived"] .route__c--on { border-color: var(--mass-work); background: var(--mass-bg); }
[data-style="derived"] .route__t { display: flex; align-items: center; gap: var(--s2); font-size: 15px; font-weight: 600; }
[data-style="derived"] .route__t .tag { margin-left: auto; }
[data-style="derived"] .route__w { font-size: 13px; color: var(--ink2); margin-top: var(--s2); }
[data-style="derived"] .route__a { margin-top: var(--s3); }


/* Квалификация уликой, а не полем. Поле «бюджет: да» ничего не значит: оно
   заполняется, чтобы закрыть форму. Улика — «сказал 2–3 млрд на звонке 14.06,
   запись есть» — проверяема, и по ней видно, чего нет. */
[data-style="derived"] .qz { display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--s3);
  padding: var(--s3) 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .qz:last-child { border-bottom: 0; }
[data-style="derived"] .qz__i { flex: 0 0 var(--s5); height: var(--s5); border-radius: 50%; display: flex;
  align-items: center; justify-content: center; }
[data-style="derived"] .qz--ok .qz__i { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .qz--no .qz__i { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .qz--part .qz__i { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .qz__m { min-width: 150px; flex: 1; }
[data-style="derived"] .qz__t { font-size: var(--t3); font-weight: 600; }
[data-style="derived"] .qz--no .qz__t { color: var(--high); }
[data-style="derived"] .qz__e { font-size: 13px; color: var(--ink2); margin-top: var(--s1);
  padding-left: var(--s2); border-left: 2px solid var(--line); }
[data-style="derived"] .qz__e--none { color: var(--high); border-left-color: var(--high); }
[data-style="derived"] .qz__r { margin-left: auto; flex-shrink: 0; }


/* Улика заводится там же, где названо, что её нет.

   Место справа занимал ярлык роли, и строка «улики нет» умела только упрекать:
   чтобы завести контакт или срок, надо было уйти с карточки. Справа теперь
   ввод, роль переехала в строку заголовка — она свойство проверки, а не
   отдельная колонка. Из трёх ролей выделена одна: «держит» сделку. Остальные
   две сказаны тихо, потому что не останавливают. Цвет ярлыка прежде повторял
   состояние строки, то есть красил роль в чужой смысл; состояние говорит
   значок слева, роль — слово.

   Ввод по роду улики: дата — маской и якорями из фактов карточки, число —
   полем с единицей и вилкой, человек — выбором из контактов клиента. Общего
   поля «впишите что-нибудь» здесь нет: оно и есть то поле, против которого
   написан весь экран. */
[data-style="derived"] .qz__role { font-size: var(--t2); color: var(--muted); font-weight: 400; }
[data-style="derived"] .qz__role::before { content: "·"; margin: 0 var(--s2); color: var(--line); }
[data-style="derived"] .qz__role--hold { color: var(--ink); font-weight: 600; }


/* Происхождение улики. Введённая рукой отличается от вынутой из разговора
   тем, что перепроверить её можно только повторным вопросом, — поэтому она
   названа цветом предупреждения, а не спрятана под общий серый. */
[data-style="derived"] .qz__src { display: inline-flex; align-items: center; gap: var(--s1); font-size: var(--t2);
  color: var(--muted); }
[data-style="derived"] .qz__src svg { flex: 0 0 12px; }
[data-style="derived"] .qz__src--hand { color: var(--medium); font-weight: 600; }
[data-style="derived"] .qz__foot { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s2); }
[data-style="derived"] .qz__foot .btn { margin-left: auto; }


/* Место ввода. Отделено подложкой, а не окном поверх: окно закрывает улики,
   ради сверки с которыми сюда и пришли. */
[data-style="derived"] .qz__in { margin-top: var(--s2); padding: var(--s3); background: var(--panel2);
  border: 1px solid var(--line); border-radius: var(--r2); }
[data-style="derived"] .qz__f { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
[data-style="derived"] .qz__f u { font-size: var(--t2); color: var(--muted); font-style: normal; }
[data-style="derived"] .qz__or { font-size: var(--t2); color: var(--muted); }
[data-style="derived"] .qz__in .who:first-of-type { padding-top: 0; }
[data-style="derived"] .qz__in .who:last-of-type { border-bottom: 0; }

/* Следствие ввода — числом и сразу, пока рука на поле. Отказ при сохранении
   пришёл бы через минуту после того, как человек забыл, что вводил. */
[data-style="derived"] .qz__hint { font-size: var(--t2); color: var(--ink2); margin-top: var(--s2); }
[data-style="derived"] .qz__hint--bad { color: var(--high); }
[data-style="derived"] .inp--date { width: 108px; }
[data-style="derived"] .inp--sum { width: 88px; text-align: right; }
[data-style="derived"] .inp--bad { border-color: var(--high); box-shadow: 0 0 0 3px var(--high-bg); }


/* Счёт готовности. Он двигается правкой в строке, а не после сохранения:
   иначе связь между «дописал улику» и «лид готов» видна только тому, кто
   сравнил два экрана по памяти. Первое число — записанное, второе — что
   станет, когда набранное запишут. */
[data-style="derived"] .qzn { display: inline-flex; align-items: baseline; gap: var(--s1); font-size: 15px;
  font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .qzn i { font-style: normal; font-weight: 400; color: var(--muted); }
[data-style="derived"] .qzn b { color: var(--mass-work); }
[data-style="derived"] .qzn u { text-decoration: none; font-size: var(--t2); font-weight: 400; color: var(--muted); }
[data-style="derived"] .qzn svg { color: var(--muted); align-self: center; }
[data-style="derived"] .qzn__w { font-size: var(--t2); color: var(--medium); }


/* Вилка вместо суммы. На первом шаге число выглядело бы обещанием, которого
   никто не давал: срок не назван, объём работ не оценён, места не сверены.
   Диапазон говорит ровно столько, сколько известно. */
[data-style="derived"] .guess__f { display: flex; align-items: flex-start; gap: var(--s5); margin-top: var(--s3);
  padding: var(--s3) var(--s4); background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r2); }
[data-style="derived"] .guess__n { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; white-space: nowrap; }
[data-style="derived"] .guess__n span { font-size: 13px; font-weight: 400; color: var(--muted); }
[data-style="derived"] .guess__l { font-size: 13px; color: var(--muted); margin-top: 2px; max-width: 260px; }
[data-style="derived"] .guess__w { flex: 1; font-size: 13px; color: var(--ink2); padding-left: var(--s4);
  border-left: 1px solid var(--line); }


/* ── Реплика оператора. Колл-центр не разбирается в продукте и не должен:
   у него секунды, а не минуты, и одна задача — не потерять и передать по
   адресу. Готовая фраза снимает с него необходимость соображать вслух,
   а с компании — риск, что он пообещает лишнего. */
[data-style="derived"] .say { display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line2); }
[data-style="derived"] .say:last-child { border-bottom: 0; }
[data-style="derived"] .say__i { flex: 0 0 24px; height: 24px; border-radius: 50%; background: var(--mass-bg);
  color: var(--mass-work); display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; }
[data-style="derived"] .say__t { font-size: 15px; }
[data-style="derived"] .say__w { font-size: 13px; color: var(--muted); margin-top: var(--s1); }
[data-style="derived"] .say__r { margin-left: auto; flex-shrink: 0; }


/* Таймер ответа. Единственное число, которое оператор держит в голове. */
[data-style="derived"] .sla { display: flex; align-items: baseline; gap: var(--s2); }
[data-style="derived"] .sla__n { font-size: 28px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.02em; color: var(--high); }
[data-style="derived"] .sla__l { font-size: 13px; color: var(--muted); }


/* Свёрнутое. То, что нужно не этому человеку, не удаляется — оно называется
   и уезжает туда, где им пользуются. Строка говорит, что внутри и куда уйдёт. */
[data-style="derived"] .fold { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
  border: 1px dashed var(--line); border-radius: var(--r2); font-size: 13px;
  color: var(--muted); }
[data-style="derived"] .fold b { color: var(--ink2); font-weight: 600; }
[data-style="derived"] .fold__r { margin-left: auto; }


/* Поле пометки оператора. */
[data-style="derived"] .note { padding: var(--s3) var(--s4); border: 1px solid #939392; border-radius: var(--r2);
  background: var(--panel); color: var(--muted); font-size: 15px; }


/* ── Продукт обращения. Он же ключ маршрутизации, а не украшение карточки.
   Обращение без продукта — это «кто-то звонил»: его некуда деть и не по чему
   считать. Продукт отвечает сразу на два вопроса: о чём разговор и кому
   передавать. Поэтому у каждой строки списка справа написано, куда она ведёт,
   и оператор видит правило, а не запоминает его.

   Правила ровно четыре. Продукт у клиента не стоит — интерес к покупке,
   аккаунт-менеджеру. Стоит и по нему идёт проект — проектному менеджеру.
   Подписка — в ИТС. Стоит, но вопрос коммерческий — снова аккаунт-менеджеру. */
[data-style="derived"] .pr { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .pr:last-child { border-bottom: 0; }
[data-style="derived"] .pr:hover { background: var(--panel2); }
[data-style="derived"] .pr--on { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .pr__g { flex: 0 0 28px; height: 28px; border-radius: var(--r2); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .pr__m { min-width: 0; flex: 1; }
[data-style="derived"] .pr__n { display: block; font-size: 15px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .pr__s { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .pr__to { flex: 0 0 232px; display: flex; align-items: center; gap: var(--s2);
  font-size: 13px; color: var(--muted); }
[data-style="derived"] .pr__to b { font-weight: 600; color: var(--ink2); }
[data-style="derived"] .pr--on .pr__to b { color: var(--mass-work); }


/* Куда ушло. Одна карточка, а не выбор из трёх равных: маршрут уже выведен
   из продукта, и человеку остаётся согласиться или поправить. */
/* Полоса передачи. Кнопки стоят сверху, потому что ими работа заканчивается:
   внизу они заставляли бы прокручивать экран, который для того и сделан, чтобы
   его не читать целиком. Слева — основание выбранной кнопки одной строкой;
   отдельной карточкой «куда уходит» маршрут повторял бы то, что уже написано
   справа у каждой строки списка продуктов. */
[data-style="derived"] .handoff { display: flex; align-items: center; gap: var(--s4); padding: var(--s3) var(--s4);
  background: var(--mass-bg); border: 1px solid var(--mass-work); border-radius: var(--r3); }
[data-style="derived"] .handoff__m { min-width: 0; }
[data-style="derived"] .handoff__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .handoff__s { font-size: 13px; color: var(--ink2); margin-top: 2px; }
[data-style="derived"] .handoff__a { margin-left: auto; display: flex; align-items: center; gap: var(--s2);
  flex-shrink: 0; }


/* ── Карточка продукта. Место, где мы обгоняем.

   У Salesforce объект продукта — это имя, код, семейство и запись в прайс-листе.
   Он ничего не знает о своём парке: сколько клиентов на какой редакции, у скольких
   истекает подписка, у скольких нет внедрённых часов, что у них после продажи
   ломается. Всё это там собирается отчётами, то есть раз в квартал и руками.

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

   Распределение по редакциям. Список из шестидесяти четырёх клиентов ничего не
   говорит — распределение говорит сразу: где масса, где хвост, где снятое с
   поддержки. */
[data-style="derived"] .dist { display: flex; height: 34px; border-radius: var(--r2); overflow: hidden;
  border: 1px solid var(--line); }
[data-style="derived"] .dist__s { display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; }

/* Полоса распределения несёт число внутри сегмента, то есть это не чистая
   графика: белая цифра на светло-голубом давала 2.47 при норме 4.5 и просто
   не читалась. Ступени сведены к тем, под которыми белое читается. */
[data-style="derived"] .dist__s--now { background: var(--mass-work); }
[data-style="derived"] .dist__s--near { background: #46739F; }
[data-style="derived"] .dist__s--old { background: var(--medium); }
[data-style="derived"] .dist__s--dead { background: var(--high); }
[data-style="derived"] .dist__l { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  margin-top: var(--s3); }
[data-style="derived"] .dist__i { display: flex; align-items: center; gap: var(--s2); font-size: 13px; }
[data-style="derived"] .dist__i i { width: var(--s3); height: var(--s3); border-radius: var(--r1); display: inline-block; }
[data-style="derived"] .dist__i b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .dist__i span { color: var(--muted); }


/* Календарь окончаний. Подписка — обязательство с датой, и деньги продления
   лежат по месяцам, а не общей кучей. */
[data-style="derived"] .cal { display: flex; gap: var(--s2); align-items: flex-end; min-height: 118px; }
[data-style="derived"] .cal__m { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--s2); }
[data-style="derived"] .cal__m i { display: block; width: 100%; border-radius: var(--r1) var(--r1) 0 0; background: var(--mass); }
[data-style="derived"] .cal__m--hot i { background: var(--high); }
[data-style="derived"] .cal__m b { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .cal__m span { font-size: 13px; color: var(--muted); }


/* Покрытие. Продукт продан — а что к нему прикреплено? Дробь показывает
   и долю, и абсолют: 27 из 64 читается иначе, чем 42%. */
[data-style="derived"] .cov { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .cov:last-child { border-bottom: 0; }
[data-style="derived"] .cov__n { flex: 0 0 210px; font-size: 13px; }
[data-style="derived"] .cov__b { flex: 1; height: 8px; border-radius: var(--rp); background: var(--line2); overflow: hidden; }
[data-style="derived"] .cov__b i { display: block; height: 100%; border-radius: var(--rp); background: var(--mass); }
[data-style="derived"] .cov--low .cov__b i { background: var(--high); }
[data-style="derived"] .cov__v { flex: 0 0 96px; text-align: right; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .cov--low .cov__v { color: var(--high); }


/* Неподобранное. Каждая дыра — это сумма и кнопка, а не наблюдение.
   Отчёт говорит «31 истекает»; здесь написано, сколько это денег и что нажать. */
[data-style="derived"] .gap { display: flex; align-items: center; gap: var(--s4); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .gap:last-child { border-bottom: 0; }
[data-style="derived"] .gap__i { flex: 0 0 32px; height: 32px; border-radius: var(--r2); display: flex;
  align-items: center; justify-content: center; background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .gap__i--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .gap__m { min-width: 0; flex: 1; }
[data-style="derived"] .gap__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .gap__w { font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .gap__s { flex: 0 0 auto; min-width: 96px; max-width: 140px; text-align: right; }

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

   Поэтому предел, а не размер: в широкой колонке ведёт себя как прежде, в
   узкой отдаёт место тексту, ради которого строка и стоит. */
[data-style="derived"] .gap__s b { display: block; font-size: 18px; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
[data-style="derived"] .gap__s span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .gap__a { flex: 0 0 auto; }


/* Связь редакции и нагрузки. Главная мысль карточки: обращения не размазаны
   по парку ровно, они сидят на старых редакциях. */
[data-style="derived"] .load { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .load:last-child { border-bottom: 0; }
[data-style="derived"] .load__v { flex: 0 0 116px; font-family: "IBM Plex Mono", monospace; font-size: 13px; }
[data-style="derived"] .load__b { flex: 1; height: 20px; display: flex; align-items: center; }
[data-style="derived"] .load__b i { display: block; height: 12px; border-radius: var(--r1); background: var(--high); }
[data-style="derived"] .load__n { flex: 0 0 150px; text-align: right; font-size: 13px; }
[data-style="derived"] .load__n b { font-weight: 600; font-variant-numeric: tabular-nums; }


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

   «В скольких сделках» — мост от состава к воронке. Продукт называют на
   обращении, позиции подбирают позже в сделке, и без этой колонки список
   позиций и путь записи лежали бы на карточке рядом, ничего друг о друге не
   говоря. Ширина прибита: числа сравниваются столбиком, а не ищутся глазом.

   Признак «наш код» стоит колонкой, а не четвёртым знаком рода. Знак рода
   сказал бы, что доработка — отдельный род; она работа, у которой мы автор. */
[data-style="derived"] .pl__use { flex: 0 0 118px; text-align: right; font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
[data-style="derived"] .pl__use b { font-weight: 600; color: var(--ink2); }
[data-style="derived"] .pl__mark { flex: 0 0 92px; text-align: right; }


/* ── Шаг с указанием. Взято у Salesforce: их Path показывает не только «где мы»,
   но и «что здесь сделать» — Key Fields, которые правятся на месте, и Guidance
   for Success, который админ пишет для продавцов. Полоса перестаёт быть
   индикатором и становится инструкцией.

   Наше отличие от них в двух вещах. Указание не пишется админом руками, а
   собирается из состояния сделки — иначе оно устаревает в тот день, когда его
   написали. И к указанию добавлено то, чего у них нет вовсе: что держит
   переход дальше, названное поимённо. */
[data-style="derived"] .guide { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 0;
  border: 1px solid var(--line); border-radius: var(--r3); overflow: hidden;
  background: var(--panel); }
[data-style="derived"] .guide__m { padding: var(--s3) var(--s4); }
[data-style="derived"] .guide__h { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s2); }
[data-style="derived"] .guide__h b { font-size: 15px; font-weight: 600; }
[data-style="derived"] .guide__h span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .guide__l { margin: 0; padding-left: var(--s4); font-size: 13px; color: var(--ink2); }
[data-style="derived"] .guide__l li { margin: var(--s1) 0; }
[data-style="derived"] .guide__k { padding: var(--s3) var(--s4); border-left: 1px solid var(--line2);
  background: var(--panel2); }
[data-style="derived"] .guide__kh { font-size: 13px; font-weight: 600; color: var(--muted);
  margin-bottom: var(--s2); }
[data-style="derived"] .kf { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .kf:last-of-type { border-bottom: 0; }
[data-style="derived"] .kf__k { flex: 0 0 96px; color: var(--muted); }
[data-style="derived"] .kf__v { min-width: 0; flex: 1; font-weight: 600; }

/* Период под именем, а не через точку в той же строке: в колонке 296 точек
   «Д. Саидов · с 08.04.2022» рвалось между предлогом и датой, и «с» оставалось
   висеть в конце строки одно. */
[data-style="derived"] .kf__p { display: block; margin-top: 2px; font-size: var(--t1); font-style: normal;
  font-weight: 400; color: var(--muted); }
[data-style="derived"] .kf__v--none { color: var(--high); font-weight: 600; }

/* Колонка внутри сетки страницы. Ставилась классом `colc`, которого нет ни в
   ядре, ни здесь: без правила колонки не складывались вовсе, и правая панель
   уезжала под левую. Поймано при сверке соседнего экрана, а не глазом. */
[data-style="derived"] .col { display: flex; flex-direction: column; gap: var(--s3); min-width: 0; min-height: 0; }

/* Величина уступки. Подписывалась классом `kf__e` — а он карандаш правки по
   наведению, с `opacity: 0`: главное число решения было невидимо, пока не
   наведёшь мышью. Значение обязано стоять само по себе. */
[data-style="derived"] .kf__d { font-weight: 600; color: var(--medium); background: var(--medium-bg);
  padding: 2px var(--s2); border-radius: var(--r2); font-size: var(--t2); }
[data-style="derived"] .kf__e { color: var(--muted); opacity: 0; }
[data-style="derived"] .kf:hover .kf__e { opacity: 1; }


/* ── Сравнение двух половин парка. Attach у нас мерился долей: «часы
   прикрепляются в 2%». Доля говорит, что случилось, и молчит, почему это
   важно. Две колонки рядом отвечают: клиент с внедрением приносит вдвое,
   пишет в поддержку втрое реже и продлевает почти всегда. */
[data-style="derived"] .vs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
  border: 1px solid var(--line); border-radius: var(--r3); overflow: hidden; }
[data-style="derived"] .vs__c { padding: var(--s4); border-right: 1px solid var(--line2); }
[data-style="derived"] .vs__c:last-child { border-right: 0; }
[data-style="derived"] .vs__c--good { background: var(--mass-bg); }
[data-style="derived"] .vs__c--bad { background: var(--high-bg); }
[data-style="derived"] .vs__h { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s3); }
[data-style="derived"] .vs__h b { font-size: 15px; font-weight: 600; }
[data-style="derived"] .vs__h span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .vs__r { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .vs__r:last-child { border-bottom: 0; }
[data-style="derived"] .vs__k { flex: 1; font-size: 13px; color: var(--ink2); }
[data-style="derived"] .vs__v { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; }
[data-style="derived"] .vs__v small { font-size: 13px; font-weight: 400; color: var(--muted); }


/* Строка выручки по годам жизни клиента: первая продажа и всё, что после. */
[data-style="derived"] .ltv { display: flex; align-items: flex-end; gap: var(--s2); min-height: 118px; }
[data-style="derived"] .ltv__y { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--s2); }
[data-style="derived"] .ltv__y i { display: block; width: 100%; border-radius: var(--r1) var(--r1) 0 0; background: var(--mass); }
[data-style="derived"] .ltv__y--first i { background: var(--ink2); }
[data-style="derived"] .ltv__y b { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .ltv__y span { font-size: 13px; color: var(--muted); }


/* ── Оболочка: скрытое меню и приборная панель ────────────────────────────

   Постоянный рельс занимал 184 пикселя из 1440 всё время и был нужен три раза
   за смену: перейти в другой раздел. Остальные восемь часов человек работает
   внутри одного экрана, а рельс продолжает стоять и отнимать ширину у таблицы,
   ради которой пришёл.

   Меню уезжает под кнопку слева сверху и открывается поверх. Освободившееся
   место занимает приборная панель — полоса чисел, которые смотрят весь день:
   сколько дел, что горит, где разрыв по месяцу. Набор личный: продавцу нужны
   свои цифры, руководителю отдела свои, а один общий набор не подходит никому.

   Панель не украшение: каждая плитка это фильтр, за которым стоит список.
   Число, по которому нельзя кликнуть, — это плакат. */
[data-style="derived"] .shell { display: flex; flex-direction: column; height: 100%; }

/* ── Облик B (решение визионера 23.09) ─────────────────────────────────

   Верх в две строки, как в Salesforce. Первая — знак слева, поиск по центру,
   справа «Создать» и аватар. Вторая — строка приложения: кнопка-сетка «Все
   разделы», имя приложения и вкладки разделов, справа открытые записи.

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

   Колокольчика нет: входа, который отдавал бы уведомления, у сервера нет, и
   кнопка без двери была бы обещанием.

   Поиск стоит по центру строки, а не у правого края: сетка из трёх колонок
   держит его посередине окна, сколько бы ни весила правая группа. */
[data-style="derived"] .top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 560px) minmax(0, 1fr);
  align-items: center; gap: var(--s4); height: 52px; flex: 0 0 52px; padding: 0 var(--s5);
  background: var(--panel); border-bottom: 1px solid var(--line2); }
[data-style="derived"] .top__logo { justify-self: start; width: 32px; height: 32px; border-radius: var(--r2);
  object-fit: contain; }

/* Поиск — кнопка, открывающая командную строку. Правило названо целиком: имя
   `.search` занято и старой таблицей, и её свойства иначе доехали бы до строки
   (`docs/style-leak.py`). Плейсхолдер короче поля — «Поиск» (правило 15). */
[data-style="derived"] .top .search { justify-self: stretch; display: flex; align-items: center; gap: var(--s2);
  flex: none; width: auto; height: 36px; margin-left: 0; padding: 0 var(--s3);
  border: 1px solid var(--line); border-color: var(--line); border-radius: var(--r2);
  background: var(--panel2); color: var(--muted); font-family: inherit; font-size: 13px;
  line-height: var(--lh1); text-align: left; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; cursor: pointer; }
[data-style="derived"] .top .search:hover { border-color: var(--muted); }
[data-style="derived"] .top__end { justify-self: end; display: flex; align-items: center; gap: var(--s3); }


/* Строка приложения: сетка, имя приложения, вкладки разделов, справа
   открытые записи. Вкладка — имя раздела и черта под текущим, без чисел:
   строка отвечает на «где я», а числа «7 горят · 23 молчат» продавцу ничего
   не говорили. */
[data-style="derived"] .crmbar { display: flex; align-items: stretch; height: 48px; flex: 0 0 48px;
  padding: 0 var(--s5) 0 var(--s3); background: var(--panel); border-bottom: 1px solid var(--line); }

/* Сетка — иконка без подложки (правило 5): квадрат под ней не несёт статуса.
   Кнопка держит хит-зону 36 точек, хром браузера и старой таблицы снят. */
[data-style="derived"] .crmbar__grid { appearance: none; align-self: center; display: inline-flex; align-items: center; flex: 0 0 36px;
  justify-content: center; width: 36px; height: 36px; padding: 0; border: 0;
  border-radius: var(--r2); background: none; color: var(--ink2); cursor: pointer; }
[data-style="derived"] .crmbar__grid:hover { color: var(--ink); }
[data-style="derived"] .crmbar__grid:focus { outline: none; }
[data-style="derived"] .crmbar__grid:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* Имя приложения — заголовок, а не вкладка: выбирать не из чего (правило 13). */
[data-style="derived"] .crmbar__app { align-self: center; margin: 0 var(--s5) 0 var(--s2); font-size: 18px;
  font-weight: 600; color: var(--ink); white-space: nowrap; }
[data-style="derived"] .crmbar__tabs { display: flex; flex-shrink: 0; align-items: stretch; gap: var(--s5); }

/* Вкладка — ссылка: раздел открывают и в соседней вкладке браузера. Правило
   ядра красит каждую `a` акцентом и подчёркивает под мышью; вкладка остаётся
   словом цвета текста, и подсветка у неё одна — черта. Селектор с тегом
   держит вес правила ядра `.app a`, иначе на артборде, где область не
   приписана, вкладка ушла бы в акцент. */
[data-style="derived"] a.crmbar__t, [data-style="derived"] a.crmbar__t:hover { display: flex; align-items: center; height: auto;
  padding: 0 var(--s1); border: 0; border-bottom: 2px solid transparent; border-radius: 0;
  margin-bottom: -1px; background: none; font-family: inherit; font-size: 15px;
  font-weight: 400; color: var(--ink); text-decoration: none; white-space: nowrap;
  cursor: pointer; }
[data-style="derived"] a.crmbar__t:hover { border-bottom-color: var(--line); }

/* Текущая вкладка — одна черта снизу, и больше ничего: ни цвета, ни веса, ни
   подложки (`docs/design/no-ai-look.md`, правила 1 и 2). Фокус рисуется
   только с клавиатуры и внутрь, по краю вкладки: щелчок мышью рамки не
   оставляет. */
[data-style="derived"] a.crmbar__t--on, [data-style="derived"] a.crmbar__t--on:hover { border-bottom-color: var(--mass); }
[data-style="derived"] .crmbar__t:focus { outline: none; }
[data-style="derived"] .crmbar__t:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }


/* Аватар вошедшего в конце верхней строки. Под ним то, что человек
   настраивает под себя: тема, плотность, выход. */
[data-style="derived"] .face { position: relative; flex-shrink: 0; }
[data-style="derived"] .face__b { appearance: none; display: inline-flex; height: auto; padding: 0; border: 0;
  border-radius: var(--rp); background: none; cursor: pointer; }
[data-style="derived"] .face .ava { width: 36px; height: 36px; flex-basis: 36px; background: var(--mass-bg);
  color: var(--mass-work); font-size: 13px; }
[data-style="derived"] .face__menu { position: absolute; top: 100%; right: 0; margin-top: var(--s2); z-index: 30;
  min-width: 260px; padding: var(--s2); display: flex; flex-direction: column; gap: var(--s1);
  border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel);
  box-shadow: var(--shadow); }
[data-style="derived"] .face__who { display: flex; flex-direction: column; gap: 2px;
  padding: var(--s1) var(--s2) var(--s2); border-bottom: 1px solid var(--line2); }
[data-style="derived"] .face__who b { font-size: 13px; font-weight: 600; }
[data-style="derived"] .face__who span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .face__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s2); }
[data-style="derived"] .face__menu .mk__i { display: flex; align-items: center; gap: var(--s2); }



/* ── Вкладки открытых записей. Правая половина панели.

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

   Три свойства, без которых это просто вкладки браузера.

   Состояние точкой. Красная — просрочен шаг, янтарная — открыта давно и ничего
   не менялось, серая — мяч у клиента, синяя — ждёт вашего хода. Полоса вкладок
   становится маленькой очередью, а не рядом одинаковых имён.

   Память. Вкладка помнит вид, прокрутку и выделение: возврат точный, а не
   «открылось начало карточки».

   Предел не числом, а местом. Когда вкладки перестают помещаться в полосу,
   их слишком много — это и есть сигнал. Ограничение «не больше десяти»
   произвольно, ограничение шириной честно. */
[data-style="derived"] .tabs { display: flex; align-items: stretch; gap: var(--s1); margin-left: auto;
  padding: 0 var(--s3) 0 var(--s4); border-left: 1px solid var(--line); min-width: 0; }

/* Сумма показывается только у активной вкладки и только у записи, у которой
   она есть: у остальных важно имя и точка состояния, а у лида суммы нет вовсе.

   Вкладка записи говорит «открыта» тем же языком, что вкладка раздела слева:
   чертой 2px снизу. Коробка с синей рамкой, заливкой и тенью разом — три
   подсветки одного состояния (`docs/design/no-ai-look.md`, правило 1). */
[data-style="derived"] .tab { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s3);
  border: 0; border-bottom: 2px solid transparent; border-radius: 0; margin-bottom: -1px;
  background: none; min-width: 0; max-width: 210px; flex-shrink: 1; cursor: pointer;
  height: auto; color: var(--ink2); font-size: 13px; }
[data-style="derived"] .tab:hover { border-bottom-color: var(--line); }

/* Текущая — одной чертой: старая таблица красила её ещё и серым фоном, и
   вкладка несла две подсветки разом (docs/design/no-ai-look.md, п.1). */
[data-style="derived"] .tab--on, [data-style="derived"] .tab--on:hover { border-bottom-color: var(--mass); background: none;
  color: var(--ink); font-weight: 600; }
[data-style="derived"] .tab__d { flex: 0 0 var(--s2); width: var(--s2); height: var(--s2); border-radius: 50%;
  background: var(--low); }
[data-style="derived"] .tab__d--act { background: var(--mass); }
[data-style="derived"] .tab__d--late { background: var(--high); }
[data-style="derived"] .tab__d--stale { background: var(--medium); }
[data-style="derived"] .tab__n { font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .tab__s { font-size: 13px; color: var(--muted); white-space: nowrap; }
[data-style="derived"] .tab__x { color: var(--muted); opacity: 0; flex-shrink: 0; }
[data-style="derived"] .tab:hover .tab__x, [data-style="derived"] .tab--on .tab__x { opacity: 1; }

/* Приколотую метит флажок цветом закрепления, а не рамка: рамка спорила бы с
   чертой открытой вкладки за одно место. */
[data-style="derived"] .tab--pin .tab__p { color: var(--medium); }
[data-style="derived"] .tabs__more { align-self: center; font-size: 13px; color: var(--muted); white-space: nowrap;
  padding: 0 var(--s2); cursor: pointer; }


/* ── Меню «Все разделы» — как App Launcher в Salesforce.

   Выезжает слева поверх страницы по сетке во второй строке верха; закрытое
   не занимает места. Тень законна: ящик всплывает (правило 7).

   Знака в шапке ящика нет: он стоит в верхней строке, а ящик закрывает её
   собой, и второй знак рядом с первым читался бы украшением. Шапка — поле
   «Найти раздел»: кто помнит имя, набирает и жмёт Enter. Ниже
   «Часто нужное» — шесть дверей, куда ходят каждый день, крупно, по три в ряд.
   Затем весь список по группам в две колонки, простыми строками: без значков,
   без чисел, без слов-оценок. Меню отвечает «куда пойти», а не «как дела».

   Текущий раздел — тон строки списка, и больше ничего (правило 1): плитка
   того же раздела не светится, иначе одно «где я» горело бы дважды. Строка,
   выбранная стрелками, — обводка внутрь: это второе состояние, не вторая
   подсветка первого. Плитка — без рамки и подложки под значком (правила 4
   и 5): ящик одна поверхность, плитки на ней — места, а не карточки. */
[data-style="derived"] .navdrawer { position: absolute; top: 0; left: 0; bottom: 0; width: 560px; max-width: 100%;
  z-index: 41; display: flex; flex-direction: column; background: var(--panel);
  border-right: 1px solid var(--line); box-shadow: var(--shadow-side); }
[data-style="derived"] .navdrawer__h { display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); }
[data-style="derived"] .navdrawer__find { flex: 1 1 auto; display: flex; align-items: center; gap: var(--s2);
  height: 40px; padding: 0 var(--s3); border: 1px solid var(--line); border-radius: var(--r1);
  background: var(--panel2); color: var(--muted); cursor: text; }
[data-style="derived"] .navdrawer__find:focus-within { border-color: var(--focus); }
[data-style="derived"] .navdrawer__find input { flex: 1 1 auto; min-width: 0; height: 100%; padding: 0; border: 0;
  border-radius: 0; background: none; box-shadow: none; outline: none; color: var(--ink);
  font-family: inherit; font-size: 15px; }
[data-style="derived"] .navdrawer__x { flex: 0 0 auto; }
[data-style="derived"] .navdrawer__body { position: relative; flex: 1 1 auto; overflow-y: auto;
  padding: 0 var(--s4) var(--s5); }
[data-style="derived"] .navdrawer__t { margin: var(--s4) 0 var(--s2); padding: 0 var(--s2); font-size: 15px;
  font-weight: 600; color: var(--ink); }
[data-style="derived"] .navdrawer__tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s1); }
[data-style="derived"] .navdrawer__tile { appearance: none; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: var(--s2); height: 80px; padding: var(--s2); border: 0;
  border-radius: var(--r3); background: none; color: var(--ink); font-family: inherit;
  font-size: 15px; font-weight: 400; text-align: center; cursor: pointer; }
[data-style="derived"] .navdrawer__tile svg { color: var(--muted); }
[data-style="derived"] .navdrawer__tile:hover { background: var(--line2); }
[data-style="derived"] .navdrawer__g { margin-top: var(--s3); }
[data-style="derived"] .navdrawer__gl { margin: 0 0 var(--s1); padding: 0 var(--s2); font-size: 13px;
  font-weight: 600; color: var(--muted); }

/* Две колонки читаются сверху вниз, как столбцы оглавления: строка за
   строкой вбок глаз прыгает через ящик на каждом пункте. */
[data-style="derived"] .navdrawer__list { columns: 2; column-gap: var(--s4); }
[data-style="derived"] .navdrawer__i { appearance: none; display: flex; width: 100%; break-inside: avoid; align-items: center; height: 32px; min-width: 0;
  padding: 0 var(--s2); border: 0; border-radius: var(--r1); background: none; color: var(--ink);
  font-family: inherit; font-size: 15px; font-weight: 400; text-align: left; cursor: pointer;
  white-space: nowrap; }
[data-style="derived"] .navdrawer__i:hover { background: var(--line2); }
[data-style="derived"] .navdrawer__i--on, [data-style="derived"] .navdrawer__i--on:hover { background: var(--mass-bg); }
[data-style="derived"] .navdrawer__tile:focus, [data-style="derived"] .navdrawer__i:focus { outline: none; }
[data-style="derived"] .navdrawer__pick, [data-style="derived"] .navdrawer__tile:focus-visible, [data-style="derived"] .navdrawer__i:focus-visible {
  outline: 2px solid var(--focus); outline-offset: -2px; }
[data-style="derived"] .navdrawer__none { margin: var(--s4) var(--s2); font-size: 15px; color: var(--muted); }


/* Переключатель арендатора под аватаром — только у администратора. Из меню
   разделов он ушёл: там он читался пунктом навигации. */
[data-style="derived"] .face__tenant { display: flex; gap: var(--s2); padding: var(--s1) var(--s2) var(--s2);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .face__tenant input { flex: 1 1 auto; min-width: 0; }


/* Уведомления в Telegram под аватаром (ступень а0.5). Пункт своего, как тема:
   подключает сам человек. Состояние одним словом справа от заголовка, без
   пилюли и цвета: «подключено» не статус записи, а настройка. Кнопка
   «Открыть бота» — ссылка в Telegram, выглядит кнопкой, потому что ведёт
   к действию, а не к чтению. */
[data-style="derived"] .face__tg { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s2);
  border-top: 1px solid var(--line2); }
[data-style="derived"] .face__tg-h { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s2); font-size: 13px; }
[data-style="derived"] .face__tg-h b { font-weight: 600; }
[data-style="derived"] .face__tg-h span { color: var(--muted); }
[data-style="derived"] .face__tg p { margin: 0; font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .face__tg-go { display: flex; flex-wrap: wrap; gap: var(--s2); }
[data-style="derived"] .face__tg-go a.btn { text-decoration: none; }
[data-style="derived"] .face__tg p.face__tg-fail { color: var(--high); }
[data-style="derived"] .face__pw { width: 100%; min-height: var(--btn-h); padding: 0 var(--s2); border: 1px solid var(--line2);
  border-radius: var(--r-button); background: var(--bg-page); color: var(--text-primary); font: inherit; font-size: 13px; }


/* ── Путь в два уровня. По схеме визионера от 25.08.

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

   Теперь верхний уровень — три объекта арки, нижний — шаги внутри текущего.
   Пройденные объекты свёрнуты: у закрытого обращения его три шага уже не читают.

   Под аркой — то, что не принадлежит ни одному объекту и тянется через все:
   коммуникация, история изменений, продукт. Продукт здесь особенно: сейчас он
   заводится трижды — оператор указывает, лид пересобирает, сделка собирает
   заново. Сквозным он станет тогда, когда появится установленная база,
   которой в модели нет (см. `docs/state.md`, расхождение от 25.08). */
[data-style="derived"] .arc { display: flex; align-items: stretch; gap: 0; border: 1px solid var(--line);
  border-radius: var(--r3); overflow: hidden; background: var(--panel); }
[data-style="derived"] .arc__o { display: flex; flex-direction: column; justify-content: center;
  padding: var(--s3) var(--s4); border-right: 1px solid var(--line); min-width: 0; }
[data-style="derived"] .arc__o:last-child { border-right: 0; }
[data-style="derived"] .arc__o--done { background: var(--panel2); flex: 0 0 auto; }
[data-style="derived"] .arc__o--on { flex: 1; min-width: 0; }
[data-style="derived"] .arc__t { display: flex; align-items: center; gap: var(--s2); font-size: 15px; font-weight: 600;
  white-space: nowrap; }
[data-style="derived"] .arc__o--done .arc__t { color: var(--muted); font-weight: 400; }
[data-style="derived"] .arc__o--done .arc__t b { color: var(--ink2); font-weight: 600; }

/* Точка вкладки, чья запись ведётся не смотрящим. Класс стоял в описи вкладок
   без правила: «серая намеренно» была неотличима от «забыли покрасить».
   В интерфейсе правило завели раньше (`ui/shell.css`), здесь его не было —
   дизайн и код разошлись в ту сторону, куда обычно расходится код. */
[data-style="derived"] .tab__d--grey { background: var(--low); }

/* Звено пути, до которого запись ещё не дошла. Приглушено, но видно: путь
   показывает не только пройденное, иначе он был бы историей, а не путём. */
[data-style="derived"] .arc__o--next .arc__t { color: var(--muted); }
[data-style="derived"] .arc__o--next .arc__d { opacity: .7; }
[data-style="derived"] .arc__d { font-size: 13px; color: var(--muted); margin-top: var(--s1); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .arc__ok { flex: 0 0 17px; height: 17px; border-radius: 50%; background: var(--mass-bg);
  color: var(--mass-work); display: inline-flex; align-items: center; justify-content: center; }


/* Мини-путь внутри текущего объекта. */
[data-style="derived"] .mini { display: flex; gap: var(--s1); margin-top: var(--s2); }
[data-style="derived"] .mini__s { flex: 1; min-width: 0; padding: var(--s1) var(--s2); border-radius: var(--r1);
  background: var(--line2); }
[data-style="derived"] .mini__n { font-size: 13px; font-weight: 600; color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .mini__d { font-size: 13px; color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .mini__s--done { background: var(--mass-bg); }
[data-style="derived"] .mini__s--done .mini__n { color: var(--mass-work); }
[data-style="derived"] .mini__s--now { background: var(--medium-bg); }
[data-style="derived"] .mini__s--now .mini__n, [data-style="derived"] .mini__s--now .mini__d { color: var(--medium); }


/* Действие шага внутри ячейки мини-пути.

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

   Причина под кнопкой («держит оценка») переносится тем же правилом: в
   ячейке этой ширины она обрывалась многоточием на втором слове.

   Ячейка с действием шире прочих. Шесть равных ячеек дают по девяносто семь
   точек, а «номенклатуру» одним словом занимает восемьдесят восемь: слово
   переносить некуда, и хвост вылезал из кнопки. Ширину берёт ровно та
   ячейка, в которой есть что нажать, — шаг, на котором стоят, и есть тот, в
   котором работают. */
[data-style="derived"] .mini__s:has(.mini__a) { flex: 2.2; }
[data-style="derived"] .mini__a { width: 100%; }
[data-style="derived"] .mini__a .btn { display: flex; width: 100%; height: auto; min-height: 28px;
  padding: 5px 8px; white-space: normal; overflow-wrap: anywhere;
  text-align: center; line-height: 1.3; }
[data-style="derived"] .mini__a .mini__d { white-space: normal; overflow: visible; text-overflow: clip; }


/* Засечки вместо подписанных шагов — для узкого слота панели. */
[data-style="derived"] .ticks { display: flex; gap: var(--s1); margin: var(--s2) 0 var(--s1); }
[data-style="derived"] .tick { flex: 1; height: 5px; border-radius: var(--r1); background: var(--line2); }
[data-style="derived"] .tick--done { background: var(--mass); }
[data-style="derived"] .tick--now { background: var(--medium); }


/* Сквозное под аркой. */
/* Минус пиксель сверху — не отступ, а наложение на рамку соседа: две
   однопиксельные линии встык дали бы двухпиксельную. */
[data-style="derived"] .cross { display: flex; align-items: center; gap: 0; margin-top: -1px;
  border: 1px solid var(--line); border-radius: 0 0 var(--r3) var(--r3); background: var(--panel2); }
[data-style="derived"] .cross__i { flex: 1; display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  border-right: 1px solid var(--line2); min-width: 0; font-size: 13px; }
[data-style="derived"] .cross__i:last-child { border-right: 0; }
[data-style="derived"] .cross__i b { font-weight: 600; }
[data-style="derived"] .cross__i span { color: var(--muted); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
[data-style="derived"] .cross__i > svg { flex: 0 0 14px; color: var(--muted); }


/* ── Рабочая область. Колоннада панелей вместо страницы.

   Панель НЕ рисует свою рамку. Рамка принадлежит области, панели занимают слоты
   и отделяются волосяной линией. Десять панелей с собственными бортами дают
   лоскутное одеяло — ровно то, что мы сегодня разбирали на карточке сделки,
   и ровно то, чем болеет Lightning App Builder.

   У каждой панели видна её природа: источник, вид и привязка. Это не отладочная
   подпись — это то, что человек меняет, когда настраивает область под себя.
   Панель без объявленной привязки выглядит самостоятельной, а она не такая:
   карточка справа существует только потому, что слева что-то выделено. */
[data-style="derived"] .wsbar { display: flex; align-items: center; gap: 2px; padding: 0 var(--s4);
  background: var(--panel2); border-bottom: 1px solid var(--line); }
[data-style="derived"] .ws { padding: var(--s3); font-size: 15px; color: var(--muted); cursor: pointer;
  /* Минус пиксель снизу — не отступ, а посадка подчёркивания на рамку
     полосы: иначе активная вкладка встала бы на пиксель выше линии. */
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
[data-style="derived"] .ws:hover { color: var(--ink); }
[data-style="derived"] .ws--on { color: var(--ink); font-weight: 600; border-bottom-color: var(--mass-work); }
[data-style="derived"] .ws__n { font-size: 13px; color: var(--muted); margin-left: var(--s2); }
[data-style="derived"] .cols { display: grid; flex: 1; min-height: 0; }
[data-style="derived"] .pan { border-right: 1px solid var(--line); display: flex; flex-direction: column;
  min-width: 0; overflow: hidden; }
[data-style="derived"] .pan:last-child { border-right: 0; }
[data-style="derived"] .pan__h { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line); flex-shrink: 0; }
[data-style="derived"] .pan__n { font-size: 15px; font-weight: 600; white-space: nowrap; }
[data-style="derived"] .pan__src { font-size: 13px; color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .pan__bind { flex-shrink: 0; display: inline-flex; align-items: center; gap: var(--s1);
  font-size: 13px; font-weight: 600; padding: 2px var(--s2); border-radius: var(--rp);
  background: var(--mass-bg); color: var(--mass-work); white-space: nowrap; }
[data-style="derived"] .pan__bind--pin { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .pan__a { margin-left: auto; display: flex; align-items: center; gap: var(--s2);
  flex-shrink: 0; }
[data-style="derived"] .pan__b { overflow: hidden; flex: 1; min-height: 0; }
[data-style="derived"] .pan__b--pad { padding: var(--s3) var(--s4); }


/* Строка списка внутри панели: та же, что в большой таблице, но без колонок,
   которые в узком слоте нечитаемы. Одна строка — одна сделка. */
[data-style="derived"] .pr__row { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4);
  border-bottom: 1px solid var(--line2); cursor: pointer; }
[data-style="derived"] .pr__row:hover { background: var(--panel2); }
[data-style="derived"] .pr__row--on { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .pr__row__m { min-width: 0; flex: 1; }
[data-style="derived"] .pr__row__n { font-size: 15px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .pr__row__d { font-size: 13px; color: var(--muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .pr__row__s { text-align: right; flex-shrink: 0; }
[data-style="derived"] .pr__row__s b { display: block; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .pr__row__s span { font-size: 13px; color: var(--muted); }


/* ── Итоги полосой, а не колонкой. В зоне шириной 880 боковая колонка итогов
   съедала 276, и на имя товара оставалось сто семьдесят: «1С:ERP Управлени…».
   Горизонтальная полоса стоит столько же информации и не отнимает у списка
   ширину, ради которой список существует. */
[data-style="derived"] .totbar { display: flex; align-items: stretch; border-top: 1px solid var(--line);
  background: var(--panel2); }
[data-style="derived"] .totbar__c { flex: 1; min-width: 0; padding: var(--s3) var(--s4);
  border-right: 1px solid var(--line2); }
[data-style="derived"] .totbar__c:last-child { border-right: 0; }
[data-style="derived"] .totbar__c--sum { flex: 0 0 224px; background: var(--panel); }
[data-style="derived"] .totbar__k { font-size: 13px; color: var(--muted); }
[data-style="derived"] .totbar__v { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
  margin-top: 2px; display: flex; align-items: baseline; gap: var(--s2); }
[data-style="derived"] .totbar__s { font-size: 13px; color: var(--muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .totbar__c--sum .totbar__v { font-size: 22px; letter-spacing: -.01em; }



/* ── Куда ходит правка и что там станет.

   Главная часть контура настройки. Порог, вес, право и условие живут не в
   одном месте: сорок дней тишины стоят и в шве, и во вкладе балла; сто
   миллионов — в двух швах и вкладе; «править чужое» — у одного человека,
   который этим живёт. Экран, показывающий такую правку одной строкой,
   выглядит настройкой и работает миной.

   Строка называет место, прежнее число и то, что станет. Итог снизу —
   отдельной строкой и жирнее: он и есть ответ на «нажимать ли». */
[data-style="derived"] .spread { margin-top: 12px; border: 1px solid var(--line); border-radius: var(--r3);
  overflow: hidden; background: var(--panel2); }
[data-style="derived"] .spread--stop { border-color: var(--high); }
[data-style="derived"] .spread__h { display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-bottom: 1px solid var(--line); font-size: 13px; font-weight: 600; }
[data-style="derived"] .spread__h svg { color: var(--medium); }
[data-style="derived"] .spread--stop .spread__h svg { color: var(--high); }
[data-style="derived"] .spread__h u { margin-left: auto; text-decoration: none; font-weight: 400;
  color: var(--muted); font-size: 13px; }
[data-style="derived"] .spread__r { display: flex; align-items: baseline; gap: 12px; padding: 8px 12px;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .spread__r:last-child { border-bottom: 0; }
[data-style="derived"] .spread__w { flex: 1; min-width: 0; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .spread__w b { font-weight: 600; color: var(--ink); }
[data-style="derived"] .spread__n { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 600;
  white-space: nowrap; }
[data-style="derived"] .spread__n s { text-decoration: line-through; color: var(--muted); font-weight: 400;
  margin-right: var(--s2); }
[data-style="derived"] .spread__n--up { color: var(--high); }
[data-style="derived"] .spread__n--down { color: var(--mass-work); }
[data-style="derived"] .spread__t { display: flex; align-items: baseline; gap: 12px; padding: 8px 12px;
  background: var(--panel); border-top: 1px solid var(--line); font-size: 13px;
  line-height: var(--lh2); }
[data-style="derived"] .spread__t b { font-weight: 600; font-variant-numeric: tabular-nums; }


/* ── Строка сущности настройки: правило, роль, маршрут, канал, поле.

   Одна форма на десять экранов: знак, имя, что она значит словами, и число
   справа — не «сколько её», а сколько работы она производит. Мёртвая
   сущность (ни одного срабатывания за квартал) отличается формой, а не
   только цветом: у неё пунктирная рамка. */
[data-style="derived"] .ent { display: flex; align-items: flex-start; gap: 12px; padding: 8px 12px;
  border-radius: var(--r3); border: 1px solid transparent; }
[data-style="derived"] .ent + .ent { margin-top: 4px; }
[data-style="derived"] .ent--on { background: var(--mass-bg); border-color: var(--mass-work); }
[data-style="derived"] .ent--dead { border-style: dashed; border-color: var(--line); }
[data-style="derived"] .ent__i { flex: 0 0 26px; height: 26px; border-radius: var(--r2); display: flex;
  align-items: center; justify-content: center; background: var(--low-bg);
  color: var(--ink2); }
[data-style="derived"] .ent--on .ent__i { background: var(--mass-work); color: #fff; }
[data-style="derived"] .ent--dead .ent__i { background: transparent; color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--line); }
[data-style="derived"] .ent__m { flex: 1; min-width: 0; }
[data-style="derived"] .ent__t { font-size: 13px; font-weight: 600; line-height: var(--lh1); }
[data-style="derived"] .ent__s { font-size: 13px; color: var(--muted); margin-top: 2px; line-height: var(--lh2); }
[data-style="derived"] .ent__n { flex: 0 0 auto; text-align: right; font-size: 13px; color: var(--muted); }
[data-style="derived"] .ent__n b { display: block; font-size: 15px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .ent__n--hot b { color: var(--high); }


/* ── Матрица, у которой в клетке число, а не галочка.

   Прежняя матрица прав отвечала «что можно» и молчала о том, чем
   пользуются. Право с нулём обращений за квартал и право с сорока одним
   обращением в месяц выглядели одной галочкой, и снять их предлагалось
   вслепую. Клетка несёт частоту; форма клетки несёт род доступа, чтобы
   различие переживало проектор с плохой цветопередачей. */
[data-style="derived"] .mtx { width: 100%; border-collapse: collapse; font-size: 13px; }
[data-style="derived"] .mtx th { text-align: center; padding: 0 8px var(--s2); font-size: 13px; font-weight: 600;
  color: var(--muted);
  border-bottom: 1px solid var(--line); white-space: nowrap; }
[data-style="derived"] .mtx th:first-child, [data-style="derived"] .mtx td:first-child { text-align: left; }
[data-style="derived"] .mtx td { padding: var(--s1) 8px; border-bottom: 1px solid var(--line2); text-align: center; }
[data-style="derived"] .mtx td:first-child { font-weight: 600; white-space: nowrap; }
[data-style="derived"] .mtx tr:last-child td { border-bottom: 0; }
[data-style="derived"] .mtx__c { display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 62px; padding: 4px var(--s2); border-radius: var(--r2); background: var(--mass-bg);
  color: var(--mass-work); }
[data-style="derived"] .mtx__c b { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .mtx__c span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .mtx__c--own { background: transparent; color: var(--medium);
  box-shadow: inset 0 0 0 1.5px var(--medium); }
[data-style="derived"] .mtx__c--no { background: var(--line2); color: var(--muted); }
[data-style="derived"] .mtx__c--dead { background: transparent; color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--line); }
[data-style="derived"] .mtx__l { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; font-size: 13px;
  color: var(--muted); }
[data-style="derived"] .mtx__l i { display: inline-block; width: 10px; height: 10px; border-radius: var(--r1);
  margin-right: var(--s2); vertical-align: -1px; }


/* ── Вклад в балл: две стороны одного признака.

   Разбор — не пояснение к баллу, а его определение: база плюс сумма вкладов
   равна баллу. Значит вклад показывается обеими сторонами сразу: сколько он
   даёт, когда признак есть, и сколько отнимает, когда его нет. Одна сторона
   без другой превращает вес в загадку — непонятно, чем платят за незнание. */
[data-style="derived"] .wgt { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .wgt:last-child { border-bottom: 0; }
[data-style="derived"] .wgt--limit { background: var(--panel2); margin: 0 -12px; padding: 8px 12px;
  border-radius: var(--r2); border-bottom: 0; }
[data-style="derived"] .wgt__m { flex: 1; min-width: 0; }
[data-style="derived"] .wgt__t { font-size: 13px; font-weight: 600; }
[data-style="derived"] .wgt__s { font-size: 13px; color: var(--muted); margin-top: 2px; line-height: var(--lh2); }
[data-style="derived"] .wgt__p, [data-style="derived"] .wgt__mn { flex: 0 0 52px; text-align: right; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .wgt__p { color: var(--mass-work); }
[data-style="derived"] .wgt__mn { color: var(--high); }
[data-style="derived"] .wgt__n { flex: 0 0 84px; text-align: right; font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums; }


/* ── Схема процесса: узел знает, сколько живых на нём стоит.

   Прежний холст рисовал устройство. Вопрос, ради которого на него смотрят,
   другой: где процесс стоит сейчас и что случится с живыми, если схему
   поменять. Число живых стоит на узле кружком, а не в панели сбоку. */
[data-style="derived"] .bp { position: relative; background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r3); height: 100%; min-height: 0; overflow: hidden;
  background-image: radial-gradient(circle, var(--line) 1px, transparent 1px);
  background-size: 22px 22px; }
[data-style="derived"] .bpn { position: absolute; background: var(--panel); border: 1.5px solid var(--line);
  border-radius: var(--r3); padding: 8px 12px; width: 176px; box-shadow: var(--shadow-sm); }
[data-style="derived"] .bpn__t { display: block; font-size: 13px; font-weight: 600; }
[data-style="derived"] .bpn__s { display: block; font-size: 13px; color: var(--muted); margin-top: 4px;
  line-height: var(--lh1); }
[data-style="derived"] .bpn__n { position: absolute; top: -11px; right: -11px; min-width: 24px; height: 24px;
  padding: 0 var(--s2); border-radius: var(--rp); background: var(--medium); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
  font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .bpn__n--hot { background: var(--high); }
[data-style="derived"] .bpn--start, [data-style="derived"] .bpn--end { width: 132px; text-align: center; border-radius: var(--rp); }
[data-style="derived"] .bpn--start { border-color: var(--mass); }
[data-style="derived"] .bpn--end { border-color: var(--mass); border-width: 2px; }
[data-style="derived"] .bpn--auto { border-color: var(--mass); }
[data-style="derived"] .bpn--user { border-color: var(--medium); background: var(--medium-bg); }
[data-style="derived"] .bpn--comp { border-style: dashed; border-color: var(--high); }
[data-style="derived"] .bpn--gate { width: 78px; height: 78px; transform: rotate(45deg); display: flex;
  align-items: center; justify-content: center; padding: 0; border-color: var(--medium); }
[data-style="derived"] .bpn--gate .bpn__t { transform: rotate(-45deg); font-size: 13px; line-height: var(--lh1); }
[data-style="derived"] .bpl { position: absolute; height: 1.5px; background: var(--line); }
[data-style="derived"] .bpl::after { content: ""; position: absolute; right: -1px; top: -3px;
  border: 4px solid transparent; border-left-color: var(--line); }
[data-style="derived"] .bpl--v { width: 1.5px; height: auto; }
[data-style="derived"] .bpl--v::after { display: none; }
[data-style="derived"] .bpc { position: absolute; font-size: 13px; color: var(--muted);
  background: var(--panel2); padding: 0 var(--s1); }


/* ── Канал связи: что через него прошло и что уже теряется.

   Канал, который «просто подключён», — украшение. Строка называет, во что
   превращается его событие внутри системы, и, если он молчит, — цену
   молчания с датой, после которой потеря станет невозвратной. */
[data-style="derived"] .chn { display: flex; align-items: flex-start; gap: 12px; padding: 12px;
  border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel); }
[data-style="derived"] .chn + .chn { margin-top: 8px; }
[data-style="derived"] .chn--broke { border-color: var(--high); }
[data-style="derived"] .chn__i { flex: 0 0 36px; height: 36px; border-radius: var(--r3); background: var(--panel2);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .chn--broke .chn__i { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .chn__m { flex: 1; min-width: 0; }
[data-style="derived"] .chn__n { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600; }
[data-style="derived"] .chn__s { font-size: 13px; color: var(--muted); margin-top: 4px; line-height: var(--lh2); }
[data-style="derived"] .chn__f { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-top: 8px;
  font-size: 13px; color: var(--muted); }
[data-style="derived"] .chn__f b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .chn__a { flex: 0 0 auto; display: flex; flex-direction: column; gap: var(--s2); align-items: flex-end; }


/* ── Словарь системы: наше слово, что значит, чем меряется.

   Синонимы чужих систем сняты вместе со слоем 1С (свод отменённого). Осталось
   то, что словарь и должен делать: объяснять наши слова и называть, где
   каждое живёт, — иначе «шов» и «находка» остаются двумя словами про одно. */
[data-style="derived"] .dict { display: grid; grid-template-columns: 154px minmax(0, 1fr) 156px; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--line2); font-size: 13px;
  align-items: baseline; }
[data-style="derived"] .dict:last-child { border-bottom: 0; }
[data-style="derived"] .dict__t { font-weight: 600; }
[data-style="derived"] .dict__s { color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .dict__m { color: var(--muted); text-align: right; line-height: var(--lh2); }


/* ── Столбцы отчёта.

   Ядерная `.bar` умеет одну долю в строке; отчёту нужен ряд столбцов с
   долями внутри каждого. Подпись под столбцом — месяц, число над ним не
   ставится: шесть чисел над шестью столбцами читаются как таблица, ради
   которой столбцы и не рисуют. */
[data-style="derived"] .bars { display: flex; align-items: flex-end; gap: 16px; height: 208px; padding: 0 4px; }
[data-style="derived"] .bars__c { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--s2); }
[data-style="derived"] .bars__st { width: 100%; max-width: 82px; display: flex; flex-direction: column-reverse;
  border-radius: var(--r2) var(--r2) 0 0; overflow: hidden; }
[data-style="derived"] .bars__st i { display: block; }
[data-style="derived"] .bars__l { font-size: 13px; color: var(--muted); }


/* ── Версия модели, которой объясняют вчерашний балл. */
[data-style="derived"] .ver { display: flex; align-items: center; gap: 12px; padding: 8px 12px;
  border-radius: var(--r3); background: var(--panel2); border: 1px solid var(--line); }
[data-style="derived"] .ver__n { font-size: 13px; font-weight: 600; }
[data-style="derived"] .ver__s { font-size: 13px; color: var(--muted); line-height: var(--lh2); }


/* ── Строка настройки языка: три языка, которые часто путают за один.

   Язык интерфейса, язык документа клиенту и язык переписки — разные вещи, и
   на одном переключателе они дают документ на языке продавца, отправленный
   клиенту, который его не читает. */
[data-style="derived"] .bi { display: flex; align-items: baseline; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .bi:last-child { border-bottom: 0; }
[data-style="derived"] .bi__k { flex: 0 0 132px; color: var(--muted); }
[data-style="derived"] .bi__v { flex: 1; min-width: 0; font-weight: 600; }
[data-style="derived"] .bi__s { display: block; font-weight: 400; color: var(--muted); margin-top: 2px;
  line-height: var(--lh2); }


/* ── Узкая колонка в середине полотна.

   Поиск — единственный экран контура, у которого нет двух половин: он про
   одну строку и то, что она нашла. Растянутый на 1440 список результатов
   заставляет глаз бегать поперёк ради двух слов, и первая же строка теряется. */
[data-style="derived"] .wrapc { max-width: 880px; width: 100%; margin: 0 auto; }


/* ── Строка поиска во всю ширину колонки. */
[data-style="derived"] .qbig { display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 16px;
  background: var(--panel); border: 1.5px solid var(--mass-work); border-radius: var(--r4);
  box-shadow: var(--shadow); font-size: 18px; }
[data-style="derived"] .qbig kbd { margin-left: auto; font: 500 13px/var(--lh1) "IBM Plex Mono", monospace;
  color: var(--muted); border: 1px solid var(--line); border-radius: var(--r2); padding: 4px var(--s2); }


/* ── Найденное вместе с тем, чем оно совпало.

   Результат без объяснения совпадения заставляет проверять глазами: почему
   эта сделка выше той. Поле совпадения стоит справа от строки и делает
   порядок выдачи проверяемым. */
[data-style="derived"] .hit { display: flex; align-items: flex-start; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .hit:last-child { border-bottom: 0; }
[data-style="derived"] .hit__i { flex: 0 0 30px; height: 30px; border-radius: var(--r3); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .hit__m { flex: 1; min-width: 0; }
[data-style="derived"] .hit__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .hit__s { font-size: 13px; color: var(--muted); margin-top: 2px; line-height: var(--lh2); }
[data-style="derived"] .hit__w { flex: 0 0 auto; text-align: right; font-size: 13px; color: var(--muted);
  line-height: var(--lh2); max-width: 190px; }
[data-style="derived"] .hit__w b { display: block; color: var(--ink2); font-weight: 600; }


/* ── Переключатель языка на верхней полосе. */
[data-style="derived"] .lang { display: inline-flex; gap: 4px; padding: 4px; border-radius: var(--r3);
  background: var(--line2); }
[data-style="derived"] .lang span { padding: 4px 12px; border-radius: var(--r2); font-size: 13px; color: var(--muted); }
[data-style="derived"] .lang .on { background: var(--panel); color: var(--ink); font-weight: 600;
  box-shadow: var(--shadow-sm); }



/* ── Строка направления.

   Продукт — ось системы, и на клиенте она замыкается: обращение несёт продукт,
   лид наследует, сделка наследует от лида. Значит у клиента впервые можно
   поставить рядом четыре числа одного направления — что стоит, сколько раз
   приходили, чем кончилось, сколько денег.

   Три колонки, а не таблица с заголовками: счётчики называют себя словами
   («22 обращения · 4 лида»), и строка читается без шапки, к которой нужно
   возвращаться глазами. Направление без движения красится, но красится не
   одним цветом — рядом стоит слово (правило 7 свода). */
/* Имя `.dir` занято дважды: в `derived_pages` так называется метка направления
   в шапке записи — рамка со скруглением, подложкой и полукеглем 12.5. Правила
   идут в одном листе, наше ниже, и в нём переопределено только то, что мы
   объявили: подложка, рамка, скругление, начертание и кегль метки текли сюда
   молча. Два следа этого стояли рядом мёртвым кодом — `.dir:hover` красил
   подложкой, которая уже стояла на каждой строке, и `.dir__c b` требовал
   полужирного там, где полужирным было всё. Снято явно, а не переименованием:
   класс считает предикат `docs/screens-match.py`. */
[data-style="derived"] .dir { display: grid; grid-template-columns: 216px minmax(0, 1fr) 118px;
  gap: var(--s4); align-items: start; padding: var(--s3) var(--s4);
  background: transparent; border: 0; border-radius: 0;
  color: var(--ink); font-weight: 400; font-size: var(--t2);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .dir:last-child { border-bottom: 0; }
[data-style="derived"] .dir:hover { background: var(--panel2); }

/* Горит — истекает право; расхождение — направление, по которому мы молчим
   или молчат нам. Заливка помогает найти строку, слово объясняет, что с ней. */
[data-style="derived"] .dir--hot { background: var(--high-bg); }
[data-style="derived"] .dir--hot:hover { background: var(--high-bg); }
[data-style="derived"] .dir--gap { background: var(--medium-bg); }
[data-style="derived"] .dir--gap:hover { background: var(--medium-bg); }
[data-style="derived"] .dir__n { font-size: var(--t3); font-weight: 600; display: flex; align-items: center;
  gap: var(--s2); flex-wrap: wrap; }

/* Что по направлению стоит. Пусто — так и написано словами: «не стоит ничего»
   читается, пустая клетка нет. */
[data-style="derived"] .dir__s { display: block; margin-top: var(--s1); font-size: 13px; color: var(--muted);
  line-height: var(--lh2); }
[data-style="derived"] .dir__c { font-size: 13px; color: var(--ink2); line-height: var(--lh2);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .dir__c b { font-weight: 600; }
[data-style="derived"] .dir__c u { text-decoration: none; color: var(--muted); }

/* Улика под счётчиками: из чего они посчитаны. Число без метода на клиенте
   опаснее, чем в отчёте, — по нему звонят через минуту. */
[data-style="derived"] .dir__w { display: block; margin-top: var(--s1); font-size: 13px; color: var(--muted);
  line-height: var(--lh2); }
[data-style="derived"] .dir__t { text-align: right; font-size: var(--t3); font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .dir__t u { display: block; margin-top: var(--s1); text-decoration: none; font-size: 13px;
  font-weight: 400; color: var(--muted); }


/* ── Факт досье: значение вместе с тем, из чего оно взято.

   Реквизит выглядит одинаково свежим и через день, и через семь лет: строка
   «ОКЭД 06.20» ничем не отличается от строки «расчётный счёт», хотя первую
   сказали голосом в 2019 году, а вторую подтвердили сканом в феврале.

   Поэтому у факта два этажа: значение и улика — бумага, дата, человек. Улика
   не в подсказке: подсказку не открывают, а счёт выставляют. Несвежее и
   неизвестное различены не только цветом — у первого улика начинается словами
   «со слов», у второго на месте значения стоит вопрос. */
[data-style="derived"] .facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s5); }
[data-style="derived"] .fact { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .fact:last-child { border-bottom: 0; }
[data-style="derived"] .fact__k { flex: 0 0 132px; padding-top: 2px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .fact__m { flex: 1; min-width: 0; }
[data-style="derived"] .fact__v { font-size: 13px; font-weight: 600; }
[data-style="derived"] .fact__w { margin-top: var(--s1); font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .fact__r { flex: 0 0 auto; margin-left: auto; }

/* Улика есть, но опереться на неё нельзя: чья-то память или две бумаги,
   называющие разное. */
[data-style="derived"] .fact--stale .fact__w { color: var(--medium); font-weight: 600; }

/* Значения нет вовсе: на его месте вопрос, и он выделен как дыра. */
[data-style="derived"] .fact--none .fact__v { color: var(--high); }
[data-style="derived"] .fact--none .fact__w { color: var(--high); }



/* ── Довод в строке: утверждение и улика под ним.

   Единственный компонент, общий у четырёх списков. Утверждение системы о
   работе человека — «решающий не выявлен», «сползает третий квартал» — без
   улики читается как чья-то догадка, и единственный доступный ответ на него
   «неправда». Улика делает довод проверяемым, а разговор — возможным.

   Улики нет — на её месте вопрос, который её добудет, а не пустая клетка.
   Прочерк отправляет человека думать; вопрос называет следующий ход.

   Род довода различается не цветом: горящий начинается с флажка, а улика от
   вопроса отличается второй строкой — приглушённая говорит, откуда взято,
   тёмная говорит, что сделать. Дейтераномалия у каждого двадцатого мужчины,
   правило 7 свода. */
[data-style="derived"] .claim { display: block; font-size: 13px; font-weight: 600; line-height: var(--lh1); }
[data-style="derived"] .claim--hot { color: var(--high); }

/* Предупреждение и вопрос делят оттенок намеренно: оба означают «не горит, но
   требует хода», и разводит их не цвет, а вторая строка — улика против
   вопроса. Третий оттенок здесь дал бы палитру, которую никто не запомнит. */
[data-style="derived"] .claim--warn { color: var(--medium); }
[data-style="derived"] .claim--ask { color: var(--medium); }
[data-style="derived"] .claim--ok { color: var(--mass-work); }
[data-style="derived"] .claim__e { display: block; margin-top: 4px; font-size: 13px; font-weight: 400;
  color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .claim__q { display: block; margin-top: 4px; font-size: 13px; font-weight: 400;
  color: var(--ink2); line-height: var(--lh2); }


/* ── Мера сделки: когда закроется и почему так считаем.

   На этом месте стояла колонка «Прогноз» с тремя словами — обязательство,
   лучший случай, воронка. Слово ставит менеджер, оно меняется от настроения
   и не отвечает ни на один вопрос, который задаёт руководитель в конце
   квартала. Дата с методом отвечает: «12.09 — договор у клиента шесть дней
   при медиане три». Число переносов стоит там же: дата, которую двигали
   трижды, — не дата, а привычка. */
[data-style="derived"] .close { display: block; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .close--none { color: var(--medium); }
[data-style="derived"] .close__w { display: block; margin-top: 4px; font-size: 13px; font-weight: 400;
  color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .close__w b { font-weight: 600; color: var(--high); }


/* ── Мера лида: сколько ждёт первого касания.

   У лида нет ни суммы, ни стадии — есть время. Оно единственное необратимо:
   лид, которому не позвонили за сутки, уходит к тому, кто позвонил. Поэтому
   ожидание стоит числом, а не значком «новый», и норма названа рядом. */
[data-style="derived"] .age { display: block; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .age--hot { color: var(--high); }
[data-style="derived"] .age__w { display: block; margin-top: 2px; font-size: 13px; font-weight: 400;
  color: var(--muted); }


/* ── Вилка лида с методом.

   Одно число у лида было бы враньём: сделки ещё нет, есть похожие. Вилка
   отдаётся вместе с тем, по скольким сделкам она снята и чем те кончились.
   Похожих не нашлось — так и написано, а не выдана средняя по отделу. */
[data-style="derived"] .band { display: block; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .band--none { color: var(--muted); font-weight: 400; }
[data-style="derived"] .band__w { display: block; margin-top: 2px; font-size: 13px; font-weight: 400;
  color: var(--muted); line-height: var(--lh2); }


/* ── Мера обращения: часы, разложенные на чьи.

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

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

   Сегменты различимы не цветом, а подписью под полосой, где те же величины
   названы часами. */
[data-style="derived"] .hrs { display: block; }
[data-style="derived"] .hrs__n { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .hrs__n--hot { color: var(--high); }

/* Зазора между долями нет намеренно: доли складываются ровно в сто
   процентов, и любой зазор съел бы хвост последней — полоса врала бы тем
   больше, чем больше в ней сегментов. */
[data-style="derived"] .hrs__b { display: flex; height: 6px; margin-top: var(--s1); border-radius: var(--r1);
  overflow: hidden; background: var(--line2); }
[data-style="derived"] .hrs__s { display: block; height: 6px; }
[data-style="derived"] .hrs__s--us { background: var(--mass); }
[data-style="derived"] .hrs__s--them { background: var(--ink2); }
[data-style="derived"] .hrs__s--over { background: var(--high); }
[data-style="derived"] .hrs__s--free { background: var(--line); }
[data-style="derived"] .hrs__l { display: block; margin-top: 4px; font-size: 13px; color: var(--muted);
  line-height: var(--lh2); }


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

   То, чего нет у трёх остальных списков. Сделка живёт месяцами, обращение
   часами, лид сутками — у них истории нет. У клиента есть, и вопрос к нему
   один: он растёт или сползает. Пять столбиков отвечают быстрее любой
   колонки «сегмент».

   Незаполненный год и ноль — разные вещи: клиента тогда не было, и столбик
   не рисуется вовсе, а на его месте стоит засечка. Ноль означал бы «был и не
   купил», и это оговор. Текущий год помечен штриховой рамкой: он неполный, и
   сравнивать его с прошлым целиком нечестно. */
[data-style="derived"] .trend { display: flex; align-items: flex-end; gap: 4px; height: 38px; }
[data-style="derived"] .trend__y { flex: 1; display: flex; flex-direction: column; align-items: center;
  gap: 4px; }
[data-style="derived"] .trend__y i { display: block; width: 100%; border-radius: var(--r1) var(--r1) 0 0;
  background: var(--mass); }
[data-style="derived"] .trend__y span { font-size: 13px; color: var(--muted); line-height: var(--lh1); }

/* Три состояния столбика различаются формой, а не оттенком: залитый — год
   закрыт, штриховка — год идёт и сравнивать его целиком нечестно, пустая
   рамка в два пикселя — клиента тогда не было. Оттенком их развести нельзя:
   при высоте в два пикселя цвет неразличим даже у того, кто различает цвета. */
[data-style="derived"] .trend__y--now i { background: repeating-linear-gradient(135deg,
  var(--mass) 0 3px, var(--mass-bg) 3px 6px); }
[data-style="derived"] .trend__y--none i { height: 3px; background: transparent;
  box-shadow: inset 0 0 0 1px var(--line); }


/* ── Куда идёт клиент.

   Замена колонке «сегмент». Сегмент ставила чья-то рука, проверить его нечем,
   и он переживёт того, кто поставил. Движение выведено из ряда оплат и
   названо вместе со сравнением: «412 за прошлый год, 180 за восемь месяцев».

   Направление не только цветом — стрелкой и словом: «сползает», «ушли
   молча», «первый год». Первый год — законный ответ, а не пустое место:
   сравнивать не с чем, и вывод о движении здесь был бы выдумкой. */
[data-style="derived"] .drift { display: block; font-size: 13px; font-weight: 600; line-height: var(--lh1); }
[data-style="derived"] .drift--down { color: var(--high); }
[data-style="derived"] .drift--gone { color: var(--medium); }
[data-style="derived"] .drift--flat { color: var(--muted); }
[data-style="derived"] .drift__w { display: block; margin-top: 4px; font-size: 13px; font-weight: 400;
  color: var(--muted); line-height: var(--lh2); }


/* ── Ось отбора, названная на экране.

   Ряд видов сверху отвечает «по чему режем», строка под фильтрами — «почему
   режем по этому». Список, у которого сортировка не объяснена, читается как
   произвол: человек не знает, доверять ли первой строке. */
[data-style="derived"] .axis { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px;
  font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .axis b { color: var(--ink2); font-weight: 600; }
[data-style="derived"] .axis__i { flex: 0 0 auto; color: var(--muted); padding-top: 2px; }


/* ── Полка пустых состояний под списком.

   Три карточки вместе с таблицей не показываются: каждая занимает её место,
   когда список пуст. Стоят рядом потому, что решаются вместе со списком —
   иначе решаются после первого звонка в поддержку, а это уже не решение. */
[data-style="derived"] .void { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }


/* ── Телефон ссылкой tel: (контракт 3cx, звонок одним нажатием).

   Цветом текста, подчёркивание при наведении (no-ai-look, 16): номер стоит в
   каждой строке списка и карточки, и акцентный цвет рамы превратил бы таблицу
   в страницу ссылок. Цвет берётся у места, где номер стоит. */
[data-style="derived"] .tel { color: inherit; text-decoration: none; }
[data-style="derived"] .tel:hover { color: inherit; text-decoration: underline; text-underline-offset: 2px; }



/* ── Список облика A: сделки, лиды и все списки грани (приёмка 23.09).

   Шапка одной строкой — «Создать», быстрые отборы, поиск, вид; таблица
   плотная, шапка таблицы липкая; подвал — сколько показано и листание.
   Правила вида — docs/design/no-ai-look.md, номера в скобках — оттуда. */
[data-style="derived"] .roll { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  gap: var(--s3); }
[data-style="derived"] .roll__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
[data-style="derived"] .roll__bar > .btn { flex: 0 0 auto; }

/* Дверь «Создать» — ссылка: правило рамы `.app a` красит ссылки акцентом,
   и на залитой кнопке текст пропадал бы. */
[data-style="derived"] .roll__bar a.btn { text-decoration: none; }
[data-style="derived"] .roll__bar a.btn--p, [data-style="derived"] .roll__bar a.btn--p:hover { color: var(--panel); text-decoration: none; }


/* Быстрый отбор. Одна подсветка на состояние (1): выбранный залит светлым
   акцентом, без рамки и без смены веса. */
[data-style="derived"] .roll__chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
[data-style="derived"] .roll__chip { display: inline-flex; align-items: center; gap: var(--s2); height: 32px;
  padding: 0 var(--s2); border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); color: var(--ink2); font: inherit; font-size: 13px;
  line-height: 1; white-space: nowrap; cursor: pointer; }
[data-style="derived"] .roll__chip:hover { color: var(--ink); }
[data-style="derived"] .roll__chip--on { border-color: transparent; background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .roll__chip:focus { outline: none; }
[data-style="derived"] .roll__chip:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* Счётчик у отбора — приглушённое число, не кружок (9). */
[data-style="derived"] .roll__n { color: var(--muted); font-variant-numeric: tabular-nums; }
[data-style="derived"] .roll__chip--on .roll__n { color: var(--mass-work); }
[data-style="derived"] .roll__pick { height: 32px; max-width: 200px; padding: 0 var(--s2); border: 1px solid var(--line);
  border-radius: var(--r3); background: var(--panel); color: var(--ink); font: inherit;
  font-size: 13px; }
[data-style="derived"] .roll__pick:focus { outline: none; }
[data-style="derived"] .roll__pick:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }


/* Поиск по мере ввода: иконка внутри поля, плейсхолдер короткий (15). */
[data-style="derived"] .roll__find { display: flex; align-items: center; gap: var(--s2); flex: 1 1 96px; min-width: 96px;
  max-width: 320px; height: 32px; padding: 0 var(--s2); border: 1px solid var(--line);
  border-radius: var(--r3); background: var(--panel); color: var(--muted); }
[data-style="derived"] .roll__find input { flex: 1; width: 0; min-width: 0; height: 100%; border: 0; padding: 0; background: transparent;
  color: var(--ink); font: inherit; font-size: 13px; outline: none; }
[data-style="derived"] .roll__find:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: -2px; }
[data-style="derived"] .roll__find[aria-busy="true"] { color: var(--mass-work); }


/* Вид: «Канбан · Список» справа. Выбранный — светлая подложка, и всё. */
[data-style="derived"] .roll__seg { display: flex; margin-left: auto; padding: 2px; border-radius: var(--r3);
  background: var(--line2); }
[data-style="derived"] .roll__seg .roll__seg-i, [data-style="derived"] .roll__seg a.roll__seg-i { display: inline-flex; align-items: center; height: 28px; padding: 0 var(--s3);
  border-radius: var(--r1); color: var(--ink2); font-size: 13px; text-decoration: none;
  white-space: nowrap; }
[data-style="derived"] .roll__seg a.roll__seg-i:hover { color: var(--ink); text-decoration: none; }
[data-style="derived"] .roll__seg .roll__seg-i--on { background: var(--panel); color: var(--ink); }
[data-style="derived"] .roll__seg-i:focus { outline: none; }
[data-style="derived"] .roll__seg-i:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }


/* Полотно: одна поверхность (4), прокрутка внутри, шапка таблицы липкая. */
[data-style="derived"] .roll__sheet { flex: 0 1 auto; min-height: 0; overflow: auto; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .roll__tbl, [data-style="derived"] .roll__sheet table { width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: 13px; }
[data-style="derived"] .roll__tbl { table-layout: fixed; }
[data-style="derived"] .roll__tbl th, [data-style="derived"] .roll__sheet table th { position: sticky; top: 0; z-index: 2; height: 40px;
  padding: 0 var(--s3); background: var(--panel); border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 13px; font-weight: 600; text-align: left; white-space: nowrap; }
[data-style="derived"] .roll__tbl td, [data-style="derived"] .roll__sheet table td { height: 44px; padding: 0 var(--s3);
  border-bottom: 1px solid var(--line2); vertical-align: middle; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
[data-style="derived"] .roll__tbl tbody tr:last-child td, [data-style="derived"] .roll__sheet table tbody tr:last-child td { border-bottom: 0; }
[data-style="derived"] .roll__tbl .r, [data-style="derived"] .roll__sheet table .r { text-align: right; font-variant-numeric: tabular-nums; }
[data-style="derived"] .roll__tbl tbody tr, [data-style="derived"] .roll__sheet table tbody tr { position: relative; }
[data-style="derived"] .roll__tbl tbody tr:hover td, [data-style="derived"] .roll__sheet table tbody tr:hover td { background: var(--panel2); }
[data-style="derived"] .roll__tbl tbody tr:has(a) { cursor: pointer; }


/* Имя — цветом текста, жирно, подчёркивание при наведении (16). Ссылка
   настоящая; щелчок по строке нажимает её обработчиком полотна
   (kit/roll.rs, open_row). Невидимого слоя на всю строку нет: Safari не
   считает строку таблицы его границей, и слой накрывал полосу разделов. */
[data-style="derived"] .roll__tbl .roll__name a, [data-style="derived"] .roll__sheet table td.name a { color: var(--ink); font-weight: 600;
  text-decoration: none; display: inline-flex; align-items: center; min-height: 24px; }
[data-style="derived"] .roll__tbl .roll__name a:hover, [data-style="derived"] .roll__sheet table td.name a:hover { color: var(--ink);
  text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .roll__tbl .roll__name a:focus { outline: none; }
[data-style="derived"] .roll__tbl .roll__name a:focus-visible, [data-style="derived"] .roll__sheet table td.name a:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px; }
[data-style="derived"] .roll__sel, [data-style="derived"] .roll__tbl td button, [data-style="derived"] .roll__tbl td select, [data-style="derived"] .roll__sheet table td button, [data-style="derived"] .roll__sheet table td select, [data-style="derived"] .roll__sheet table td input { position: relative; z-index: 1; }
[data-style="derived"] .roll__sel { width: 44px; text-align: center; }

/* Зона нажатия 24px, видимый квадрат 16px: прозрачная рамка 4px вокруг и
   тонкая обводка внутри. Родной чекбокс в 16px мимо пола целей. */
[data-style="derived"] .roll__sel input { appearance: none; box-sizing: border-box; width: 24px; height: 24px; margin: 0;
  border: 4px solid transparent; border-radius: var(--r1); background: var(--panel) padding-box;
  box-shadow: inset 0 0 0 1px var(--muted); cursor: pointer; vertical-align: middle; }
[data-style="derived"] .roll__sel input:checked { background: var(--mass-work) padding-box;
  box-shadow: inset 0 0 0 1px var(--mass-work), inset 0 0 0 4px var(--panel); }
[data-style="derived"] .roll__sel input:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }


/* Длинное — многоточием, целиком в подсказке (14). */
[data-style="derived"] .roll__t { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  vertical-align: bottom; }
[data-style="derived"] .roll__sheet table .roll__t { max-width: 320px; }
[data-style="derived"] .roll__dim { color: var(--muted); }

/* Строка в беде — словом и цветом слова, без кромки и заливки (6). */
[data-style="derived"] .roll__late { color: var(--high); font-weight: 600; }


/* Статус — пилюля (9). */
[data-style="derived"] .roll__pill { display: inline-block; max-width: 100%; padding: 2px var(--s2);
  border-radius: var(--rp); background: var(--low-bg); color: var(--ink2); font-size: 13px;
  font-weight: 600; line-height: var(--lh1); overflow: hidden; text-overflow: ellipsis;
  vertical-align: middle; }
[data-style="derived"] .roll__pill--ok { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .roll__pill--off { background: var(--panel2); color: var(--muted); }


/* Ответственный: буква и имя. */
[data-style="derived"] .roll__who { display: inline-flex; align-items: center; gap: var(--s2); max-width: 100%;
  vertical-align: middle; }
[data-style="derived"] .roll__ini { flex: 0 0 24px; width: 24px; height: 24px; display: inline-flex; align-items: center;
  justify-content: center; border-radius: 50%; background: var(--mass-bg); color: var(--mass-work);
  font-size: 13px; font-weight: 600; }
[data-style="derived"] .roll__who .roll__t { min-width: 0; }


/* Подвал: сколько показано и листание — без слов о механике. */
[data-style="derived"] .roll__foot { display: flex; align-items: center; gap: var(--s3); color: var(--muted);
  font-size: 13px; }
[data-style="derived"] .roll__pager { display: flex; gap: var(--s2); margin-left: auto; }


/* Пусто по отбору — одной строкой с выходом. */
[data-style="derived"] .roll__none { padding: var(--s4) 0; color: var(--ink2); font-size: 15px; }
[data-style="derived"] .roll__reset { padding: 0; border: 0; border-radius: 0; background: transparent;
  color: var(--mass-work); font: inherit; cursor: pointer; }
[data-style="derived"] .roll__reset:hover { text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .roll__reset:focus { outline: none; }
[data-style="derived"] .roll__reset:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }


/* ── Заготовка на месте данных (`kit::Skeleton`, 23.09).

   Только до первого ответа: повторный вопрос строк не снимает, «идёт»
   говорит приглушение полотна ниже. Того же рода, что заставка приложения
   (`ui/index.html`, `.boot i`): серая плашка и мерцание прозрачностью за
   1,4 с. Ключевые кадры `boot-glow` объявлены там — здесь `@keyframes` и
   `@media` собрать нельзя: сборщик приписывает область каждому селектору и
   вложенные скобки ломает. По той же причине движение снимает не
   `prefers-reduced-motion` в листе, а ветка `bones--still`, которую ставит
   сама молекула, спросив браузер. Вне приложения (артборд) кадров нет, и
   плашка стоит неподвижной.

   Геометрию несёт настоящая разметка — полотно списка, строка карточки,
   доска, — здесь только плашки и то, что у заготовки двигаться не должно. */
[data-style="derived"] .bone { display: block; width: 72%; max-width: 100%; height: 12px; border-radius: var(--r1);
  background: var(--line2); animation: boot-glow 1.4s ease-in-out infinite; }
[data-style="derived"] .bones--still .bone { animation: none; }
[data-style="derived"] .bone--h { width: 48px; height: 10px; }
[data-style="derived"] .bone--k { width: 96px; }
[data-style="derived"] .bone--at { flex: 0 0 56px; width: 56px; margin-left: auto; }

/* Клетки разной ширины, строки через одну короче: ровная решётка плашек
   читается узором, а не будущей таблицей. */
[data-style="derived"] .bones td:nth-child(3n+2) .bone { width: 56%; }
[data-style="derived"] .bones td:nth-child(3n) .bone { width: 40%; }
[data-style="derived"] .bones tbody tr:nth-child(even) td:nth-child(odd) .bone { width: 60%; }
[data-style="derived"] .bones .lkc__k .bone { margin: 3px 0; }
[data-style="derived"] .bones .lkc__v .bone { height: 14px; margin: 4px 0; }
[data-style="derived"] .bones__line { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; }
[data-style="derived"] .bones__line + .bones__line { border-top: 1px solid var(--line2); }
[data-style="derived"] .bones__line .bone { height: 14px; margin: 4px 0; }
[data-style="derived"] .bones__line:nth-child(odd) .bone:first-child { width: 48%; }

/* Доска серой: полоса стадии не красится акцентом, карточка не берётся. */
[data-style="derived"] .bones .kb__h { border-top-color: var(--line2); }
[data-style="derived"] .bones .kb__h .bone { margin: 4px 0 8px; }
[data-style="derived"] .bones .kc, [data-style="derived"] .bones .kc:hover { border-color: var(--line); cursor: default; }
[data-style="derived"] .bones .kc .bone + .bone { margin-top: 8px; }


/* Повторный вопрос: строки стоят, полотно приглушено, пока не придёт ответ.
   Не спиннер и не заготовка — показанное не пропадает. */
[data-style="derived"] .roll__sheet[aria-busy="true"] tbody { opacity: .55; }


/* «Повторить» у отказа загрузки — рядом со словами сервера. */
[data-style="derived"] .err__again { margin-left: var(--s2); vertical-align: middle; }



/* ── Лист документа.

   Ни один выведенный экран до сих пор не рисовал то, что увидит клиент.
   Котировка, счёт и шаблон существуют ради выхода наружу, и проверять их
   набором полей — значит узнавать о пустом месте от клиента. Лист показан
   рядом с правкой, а не за кнопкой «предпросмотр»: кнопка превращает проверку
   в отдельное решение, которое в спешке не принимают. */
[data-style="derived"] .paper { border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel);
  padding: 20px 24px 16px; }
[data-style="derived"] .paper__h { display: flex; align-items: baseline; gap: 12px; padding-bottom: 12px;
  border-bottom: 1px solid var(--line); margin-bottom: 12px; }
[data-style="derived"] .paper__h b { font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .paper__h span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .paper__h u { text-decoration: none; margin-left: auto; font-size: 13px; color: var(--muted); }
[data-style="derived"] .paper__p { font-size: 13px; color: var(--ink2); line-height: var(--lh2); margin: 0 0 12px; }
[data-style="derived"] .paper__r { display: flex; align-items: baseline; gap: 12px; padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .paper__r:last-of-type { border-bottom: 0; }
[data-style="derived"] .paper__r > span:first-child { flex: 1; min-width: 0; }
[data-style="derived"] .paper__r > span + span { flex: 0 0 62px; text-align: right;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .paper__r--sum { border-top: 1px solid var(--line); border-bottom: 0;
  margin-top: 4px; padding-top: 8px; font-weight: 600; }
[data-style="derived"] .paper__f { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
  font-size: 13px; color: var(--muted); line-height: var(--lh2); }

/* Поле подстановки. Цвет несёт состояние данных, а не тип поля: заполнено,
   пусто у части записей, повторяется по строкам. Пустое поле называется
   пустым здесь, на листе, — иначе оно называется пустым у клиента. */
[data-style="derived"] .tok { padding: 2px var(--s1); border-radius: var(--r1); background: var(--mass-bg);
  color: var(--mass-work); font-weight: 500; white-space: nowrap; }
[data-style="derived"] .tok--none { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .tok--rep { background: var(--medium-bg); color: var(--medium); }


/* ── Отрезок срока.

   `dist` рисует, как долг распался на доли. Здесь нужно другое: где мы стоим
   между «выставлен» и «срок», и что об этом говорит поведение плательщика.
   Одна засечка — сегодня, вторая — ожидаемая дата платежа по прошлым семи
   счетам. Пока это были два числа в разных углах экрана, никто их не
   сопоставлял. */
[data-style="derived"] .due { display: flex; flex-direction: column; gap: 8px; }
[data-style="derived"] .due__b { position: relative; height: 10px; border-radius: var(--rp); background: var(--line2); }
[data-style="derived"] .due__b i { position: absolute; top: 0; left: 0; height: 100%; border-radius: var(--rp);
  background: var(--mass); }
[data-style="derived"] .due__b i.late { background: var(--high); }
[data-style="derived"] .due__b u { position: absolute; top: -5px; width: 2px; height: 20px;
  background: var(--ink2); border-radius: var(--r1); }
[data-style="derived"] .due__b u.soft { background: var(--medium); }

/* Подпись стоит под своей засечкой, а не в своей трети полосы: подпись
   «сегодня 26.08» посреди отрезка, когда сегодня — шестой день из пятидесяти
   шести, врёт ровно тем, ради чего шкалу и рисуют. */
[data-style="derived"] .due__l { position: relative; height: 17px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .due__l span { position: absolute; white-space: nowrap; }
[data-style="derived"] .due__m { font-size: 13px; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .due__m b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .due__m--hot b { color: var(--high); }
[data-style="derived"] .lfh { display: grid; gap: var(--s1); min-width: 0; }
[data-style="derived"] .lfh__back { font-size: 13px; line-height: var(--lh2); }
[data-style="derived"] .lfh__back a { color: var(--muted); text-decoration: none; }
[data-style="derived"] .lfh__back a:hover { color: var(--ink2); text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .lfh__back a:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
[data-style="derived"] .lfh__row { display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--s3) var(--s4);
  min-width: 0; }
[data-style="derived"] .lfh__id { flex: 1 1 320px; min-width: 0; }
[data-style="derived"] .lfh h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -.01em;
  line-height: var(--lh1); overflow-wrap: anywhere; }

/* Подпись объявления и факты — одной строкой под именем, через точку. */
[data-style="derived"] .lfh__sub { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3);
  margin-top: var(--s1); font-size: 13px; line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .lfh__sub > div { margin: 0; font-size: 13px; color: var(--muted); }
[data-style="derived"] .lfh__f { display: inline-flex; align-items: baseline; gap: var(--s1); min-width: 0;
  overflow-wrap: anywhere; }
[data-style="derived"] .lfh__k { color: var(--muted); }
[data-style="derived"] .lfh__f a { color: var(--ink); text-decoration: none; }
[data-style="derived"] .lfh__f a:hover { text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .lfh__a { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-left: auto; }

/* Дверь-ссылка в облике кнопки: цвет ссылки рамы (`.app a`) сильнее кнопки
   ядра, и текст основной ушёл бы в цвет её заливки. */
[data-style="derived"] .lfh__a a.btn { color: var(--ink); text-decoration: none; }
[data-style="derived"] .lfh__a a.btn--p, [data-style="derived"] .lfh__a a.btn--p:hover { color: var(--panel); }

/* Дела записи в шапке — обычного роста, как «Позвонить» рядом: малая кнопка
   рядом с обычной читается второстепенной. */
[data-style="derived"] .lfh__a .btn--s { height: 32px; padding: 0 12px; font-size: 13px; }


/* Две колонки. Слева 440 px — число карточки лида: столько держит подпись
   в 160 px и значение в две строки. Узкое окно складывает колонки одну под
   другую, поля первыми, — переносом флекса: правил под ширину окна
   выведенный слой не держит. */
[data-style="derived"] .lfg { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s4); min-width: 0; }
[data-style="derived"] .lfg__l { flex: 1 1 440px; max-width: 440px; min-width: 0; }
[data-style="derived"] .lfg__r { flex: 1 1 480px; min-width: 0; }
[data-style="derived"] .lfg--one .lfg__r { flex-basis: 100%; }

/* Колонка — панель ядра, по ней кадр сверяется с объявлением; облика у неё
   нет: ни рамки, ни отступа (старая таблица даёт ей 14 px), рамку несёт
   каждый раздел. Селектор — по месту, а не по имени панели: имя занято
   старой таблицей, и названное здесь, оно тянуло бы её свойства
   (`docs/style-leak.py`). */
[data-style="derived"] .lfg__l > div, [data-style="derived"] .lfg__r > div, [data-style="derived"] .lfg__l > div > div, [data-style="derived"] .lfg__r > div > div { min-width: 0;
  padding: 0; background: transparent; border: 0; border-radius: 0; box-shadow: none; }
[data-style="derived"] .lfg__l > div > div, [data-style="derived"] .lfg__r > div > div { display: grid; gap: var(--s4); }


/* Блок: одна рамка, без тени. Раздел грани и блок второго ответа — одного
   вида: у человека одна карточка, а не две системы блоков. */
[data-style="derived"] .lfg .sec, [data-style="derived"] .lff { min-width: 0; padding: var(--s4) var(--s5); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r3); box-shadow: none; }
[data-style="derived"] .lfg .sec:last-child { border-bottom: 1px solid var(--line); }
[data-style="derived"] .lfg .sec--flush { padding: var(--s4) var(--s5) var(--s2); overflow-x: auto; }
[data-style="derived"] .lfg .sec__h, [data-style="derived"] .lfg .sec--flush .sec__h, [data-style="derived"] .lff__h { display: flex; align-items: baseline;
  gap: var(--s2); margin: 0 0 var(--s2); padding: 0; }
[data-style="derived"] .lfg .sec__h h3, [data-style="derived"] .lff__h h3 { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }

/* Счётчик у заголовка — приглушённое число, не кружок. */
[data-style="derived"] .lff__n { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }


/* Поле: подпись 160 px слева, значение справа, строки через линию. */
[data-style="derived"] .lfg .fld { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line2); font-size: 15px;
  line-height: var(--lh2); }
[data-style="derived"] .lfg .fld:last-child { border-bottom: 0; }
[data-style="derived"] .lfg .fld__k { flex: none; padding-top: 2px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .lfg .fld__v { min-width: 0; overflow-wrap: anywhere; }


/* Связанный список — строки внутри рамки блока, а не таблица в своей рамке:
   шапка приглушённой подписью, строки через линию, без подсветки. */
[data-style="derived"] .lfg table { font-size: 15px; }
[data-style="derived"] .lfg th { height: auto; padding: 0 var(--s3) var(--s1) 0; font-size: 13px; font-weight: 400;
  color: var(--muted); border-bottom: 1px solid var(--line2); }
[data-style="derived"] .lfg td { height: auto; padding: var(--s2) var(--s3) var(--s2) 0; line-height: var(--lh2);
  border-bottom: 1px solid var(--line2); white-space: normal; }
[data-style="derived"] .lfg th:last-child, [data-style="derived"] .lfg td:last-child { padding-right: 0; }
[data-style="derived"] .lfg tbody tr:last-child td { border-bottom: 0; }
[data-style="derived"] .lfg tr:hover td { background: transparent; }
[data-style="derived"] .lfg td:first-child a { color: var(--ink); font-weight: 600; text-decoration: none; }
[data-style="derived"] .lfg td:first-child a:hover { text-decoration: underline; text-underline-offset: 2px; }

/* Выбор в строке — роста кнопки строки: обычный выбор рядом с «Снять»
   читался главным действием карточки. */
[data-style="derived"] .lfg td select { height: 28px; max-width: 150px; padding: 0 var(--s2); font-size: 13px; }


/* Пусто в разделе — строкой внутри той же рамки, а не пунктирной коробкой
   в ней (4). */
[data-style="derived"] .lfg .empty { display: block; padding: 0; border: 0; border-radius: 0; text-align: left;
  font-size: 13px; line-height: var(--lh2); color: var(--muted); }
[data-style="derived"] .lfg .empty b { display: block; margin: 0; font-weight: 600; color: var(--ink2); }
[data-style="derived"] .lfg .empty span { display: block; max-width: none; margin: 0; }


/* Строки второго ответа: главное слово, пояснение, справа время или сумма. */
[data-style="derived"] .lfl { display: grid; margin: 0; padding: 0; list-style: none; }
[data-style="derived"] .lfl__i { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3);
  min-width: 0; padding: var(--s2) 0; border-top: 1px solid var(--line2); font-size: 15px;
  line-height: var(--lh2); }
[data-style="derived"] .lfl__i:first-child { border-top: 0; }
[data-style="derived"] .lfl__t { min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
[data-style="derived"] .lfl__t a { color: var(--ink); text-decoration: none; }
[data-style="derived"] .lfl__t a:hover { text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .lfl__t a:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
[data-style="derived"] .lfl__m { font-size: 13px; color: var(--muted); }
[data-style="derived"] .lfl__at { margin-left: auto; font-size: 13px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .lfl__at--ok { color: var(--low); font-weight: 600; }
[data-style="derived"] .lfl__at--warn { color: var(--medium); font-weight: 600; }
[data-style="derived"] .lfl__at--hot { color: var(--high); font-weight: 600; }
[data-style="derived"] .lfl__none { margin: 0; padding: var(--s1) 0; font-size: 13px; line-height: var(--lh2);
  color: var(--muted); }
[data-style="derived"] .lff .btn { margin-top: var(--s2); }


/* Ответ сверки — строкой между шапкой и колонками, через линии, без плашки. */
[data-style="derived"] .lfv { display: grid; gap: var(--s1); padding: var(--s2) 0; border-top: 1px solid var(--line2);
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .lfv__w { margin: 0; font-size: 15px; line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .lfv__w b { font-weight: 600; color: var(--ink); }
[data-style="derived"] .lfv .lfl__i { font-size: 13px; }
[data-style="derived"] .lfv .lfl__t { font-weight: 600; }



/* ── Повод в строке списка клиентов.

   Список клиентов был выпиской из справочника: ИНН, регион, сегмент, число
   контактов. Ни одна из этих колонок не говорит, что делать сегодня. Повод
   говорит — и вместе с уликой, из которой выведен: «ИТС истекает через 23 дня»
   рядом с «оплачена 17.09.2025, продлевали шесть лет подряд». Повода нет —
   стоит вопрос, который его добудет, а не пустая клетка. */
[data-style="derived"] .rsn { display: block; font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .rsn--hot { color: var(--high); }
[data-style="derived"] .rsn--ask { color: var(--medium); }
[data-style="derived"] .rsn__w { display: block; margin-top: 2px; font-size: 13px; font-weight: 400;
  color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* ── Канал связи с долей ответов.

   У человека каналов несколько, и у каждого своя судьба. Галочка «Telegram
   подтверждён» не отвечает на вопрос, которым сюда приходят: чем писать, чтобы
   ответили. Отвечает доля — «17 из 20 писем, средний ответ за 4 часа» — и она
   же показывает мёртвый канал числом, а не серым цветом. */
[data-style="derived"] .ch { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .ch:last-child { border-bottom: 0; }
[data-style="derived"] .ch__i { flex: 0 0 26px; height: 26px; border-radius: var(--r2); background: var(--low-bg);
  color: var(--ink2); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .ch__m { flex: 1; min-width: 0; }
[data-style="derived"] .ch__v { font-size: 13px; font-weight: 600; }
[data-style="derived"] .ch__w { font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .ch__r { flex: 0 0 auto; text-align: right; }
[data-style="derived"] .ch__n { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .ch__n--none { color: var(--high); }
[data-style="derived"] .ch__l { font-size: 13px; color: var(--muted); }


/* ── Цитата-источник прямо в тексте.

   Находка без цитаты в карточку не попадает вовсе, поэтому цитата должна быть
   видна в исходнике, а не пересказана рядом. Подсветка держится не только
   цветом: снизу линия — правило 7 свода. */
[data-style="derived"] .mark { background: var(--high-bg); box-shadow: inset 0 -1.5px 0 var(--high);
  padding: 2px 4px; border-radius: var(--r1); }


/* ── Очередь долга вместо папок ящика.

   «Входящие 12» считают непрочитанное. Долг — другое: письмо можно прочесть и
   не ответить, и именно такие письма стоят денег. Поэтому слева не папки, а
   три состояния хода: за нами ответ, ждём клиента, ничего не требует. */
[data-style="derived"] .box { display: flex; align-items: flex-start; gap: 8px; padding: 8px 12px;
  border-radius: var(--r2); font-size: 13px; color: var(--ink2); }
[data-style="derived"] .box--on { background: var(--mass-bg); color: var(--mass-work); font-weight: 600; }
[data-style="derived"] .box--hot .box__n { color: var(--high); }
[data-style="derived"] .box__m { flex: 1; min-width: 0; }
[data-style="derived"] .box__n { flex: 0 0 auto; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .box__w { display: block; margin-top: 2px; font-size: 13px; font-weight: 400;
  color: var(--muted); line-height: var(--lh2); }


/* ── Письмо строкой.

   Слева полоса состояния: красная — мы обещали срок и он идёт, прозрачная —
   ход не наш. Срок стоит строкой внизу вместе с тем, откуда он взялся: срок
   без источника через день читается как чья-то придумка. */
[data-style="derived"] .ml { display: block; padding: 12px; border-bottom: 1px solid var(--line2);
  border-left: 3px solid transparent; }
[data-style="derived"] .ml:last-child { border-bottom: 0; }
[data-style="derived"] .ml--on { background: var(--mass-bg); border-left-color: var(--mass-work); }
[data-style="derived"] .ml--due { border-left-color: var(--high); }
[data-style="derived"] .ml__h { display: flex; align-items: baseline; gap: 8px; }
[data-style="derived"] .ml__f { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .ml__at { font-size: 13px; color: var(--muted); white-space: nowrap; }
[data-style="derived"] .ml__s { margin-top: 4px; font-size: 13px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
[data-style="derived"] .ml__p { margin-top: 2px; font-size: 13px; color: var(--muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .ml__d { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2); font-size: 13px;
  font-weight: 600; color: var(--high); }
[data-style="derived"] .ml__d--calm { color: var(--muted); font-weight: 400; }


/* ── Тело письма. Читается целиком, поэтому кегль и строка крупнее списка. */
[data-style="derived"] .letter { font-size: 15px; line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .letter p { margin: 0 0 12px; }
[data-style="derived"] .letter p:last-child { margin-bottom: 0; }


/* ── Ответ на месте.

   Отдельная страница «написать» уводит от письма, ради которого пишут: цитата,
   срок и вопрос клиента остаются на предыдущем экране, и половина ответов
   уходит мимо них. Поле стоит под письмом, ответ уходит в ту же переписку. */
[data-style="derived"] .reply { border: 1px solid var(--mass-work); border-radius: var(--r3); background: var(--panel);
  box-shadow: 0 0 0 3px var(--mass-bg); }
[data-style="derived"] .reply__b { padding: 12px 16px; font-size: 15px; line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .reply__f { display: flex; align-items: center; gap: 8px; padding: 8px 16px;
  border-top: 1px solid var(--line2); background: var(--panel2);
  border-radius: 0 0 var(--r2) var(--r2); }
[data-style="derived"] .reply__w { font-size: 13px; color: var(--muted); }


/* ── Дорожка записи.

   Не украшение: столбик — это секунда, к которой ведёт цитата находки. Речь
   наша и речь клиента разведены заливкой, отметки — там, где сказано то, из
   чего находка выведена. */
[data-style="derived"] .wave { display: flex; align-items: center; gap: 2px; height: 56px; }
[data-style="derived"] .wave i { flex: 1; border-radius: var(--r1); background: var(--line); }
[data-style="derived"] .wave i.k-us { background: var(--mass); }
[data-style="derived"] .wave i.k-them { background: var(--ink2); }
[data-style="derived"] .wave i.k-mark { background: var(--high); }
[data-style="derived"] .play { display: flex; align-items: center; gap: 12px; }
[data-style="derived"] .play__b { flex: 0 0 38px; height: 38px; border-radius: 50%; background: var(--mass-work);
  color: var(--panel); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .play__m { flex: 1; min-width: 0; }
[data-style="derived"] .play__l { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; font-size: 13px;
  color: var(--muted); }
[data-style="derived"] .play__l b { color: var(--ink2); font-weight: 600; font-variant-numeric: tabular-nums; }


/* ── Строка расшифровки.

   Расшифровка — исходник, по которому спорят, поэтому она не переписывается и
   не сокращается. Реплика на узбекском стоит как сказана, перевод — под ней:
   перевод вместо оригинала уже не улика. Реплика, из которой вышла находка,
   помечена не только цветом — полосой слева. */
[data-style="derived"] .tx { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .tx:last-child { border-bottom: 0; }
[data-style="derived"] .tx__t { flex: 0 0 46px; font-family: "IBM Plex Mono", monospace; font-size: 13px;
  color: var(--muted); padding-top: 4px; }
[data-style="derived"] .tx__w { flex: 0 0 98px; font-size: 13px; font-weight: 600; }
[data-style="derived"] .tx--them .tx__w { color: var(--ink2); }
[data-style="derived"] .tx__b { flex: 1; min-width: 0; font-size: 15px; line-height: var(--lh2); }
[data-style="derived"] .tx__o { font-style: italic; color: var(--ink2); }
[data-style="derived"] .tx__r { margin-top: 4px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .tx--key { margin: 0 -12px; padding-left: 12px; padding-right: 12px;
  background: var(--high-bg); box-shadow: inset 3px 0 0 var(--high); }


/* ── Полоса входящего звонка.

   Раньше это было окно поверх затемнённого экрана. Затемнение стоило дороже,
   чем казалось: под ним лежало то, что человек и собирался сказать в трубку, —
   срок обращения, сумма счёта, чем кончился прошлый разговор. Полоса встаёт
   сверху и не закрывает ничего. */
[data-style="derived"] .ring { display: flex; align-items: center; gap: 16px; padding: 12px 16px;
  border: 1px solid var(--mass-work); border-radius: var(--r3); background: var(--mass-bg); }
[data-style="derived"] .ring__i { flex: 0 0 40px; height: 40px; border-radius: 50%; background: var(--mass-work);
  color: var(--panel); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .ring__m { flex: 1; min-width: 0; }
[data-style="derived"] .ring__n { font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .ring__s { margin-top: 4px; font-size: 15px; color: var(--ink2); }
[data-style="derived"] .ring__c { flex: 0 0 auto; text-align: right; }
[data-style="derived"] .ring__t { font-size: 28px; font-weight: 600; line-height: var(--lh1); color: var(--mass-work);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .ring__l { margin-top: 4px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .ring__a { flex: 0 0 auto; display: flex; gap: 8px; }


/* ── Часы срока: где они шли, а где стояли.

   Просрочка одним числом врёт в обе стороны. Обращение висит девятый день, но
   пять из них мы ждали ответа клиента — и эти пять в срок не считаются.
   Полоса показывает часы отрезками с подписью внутри: состояние читается и без
   цвета. */
[data-style="derived"] .clk { display: flex; height: 28px; border-radius: var(--r2); overflow: hidden; }
[data-style="derived"] .clk i { display: flex; align-items: center; justify-content: center; font-style: normal;
  font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--muted); background: var(--line2); }
[data-style="derived"] .clk .k-run { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .clk .k-hold { background: var(--panel2); color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--line); }
[data-style="derived"] .clk .k-late { background: var(--high); color: var(--panel); }
[data-style="derived"] .clk__l { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; font-size: 13px;
  color: var(--muted); }
[data-style="derived"] .clk__l i { display: inline-block; width: 10px; height: 10px; border-radius: var(--r1);
  margin-right: var(--s2); vertical-align: -1px; }
[data-style="derived"] .clk__l b { color: var(--ink2); font-weight: 600; font-variant-numeric: tabular-nums; }


/* ── Схема подразделений: блок-схема, а не список с отступами.

   Число людей в узле не решает ничего: подразделение с двадцатью тремя людьми
   и без руководителя опаснее, чем с шестью и с ним. В узле стоит дыра — то,
   из-за чего он не работает. Целый узел говорит числом людей и молчит обо
   всём остальном.

   Связи нарисованы CSS, а не SVG, и это решение о переезде в Leptos. Линия
   SVG живёт в координатах: чтобы провести её от узла к узлу, надо знать, где
   эти узлы стоят, — то есть измерить их в браузере скриптом либо вбить
   пиксели в генератор. Первого в статическом артборде нет вовсе; второе
   ломается на первом же имени, ушедшем во вторую строку, и на плотном режиме
   (`--row`, `--pad` меняют высоту коробки). Псевдоэлемент прибит к самой
   коробке и едет вместе с ней: гребёнка `::before`/`::after` рисуется на
   колонке, спина ветви — рамкой контейнера. Ничего не считается во время
   показа, поэтому артборд показывает ровно то, что покажет Leptos, а разметка
   переносится в компонент как есть.

   Граница у этого выбора есть, и она честная: CSS хватает, пока рёбра не
   пересекаются — каждый ребёнок висит под своим родителем. Пунктирная связь
   ко второму начальнику или матричное подчинение пересечёт колонки, и вот там
   считать координаты придётся — это работа SVG, а не гребёнки. */
[data-style="derived"] .og { display: block; }
[data-style="derived"] .og__top { position: relative; display: flex; justify-content: center; padding-bottom: 16px; }

/* `-.5px` — не отступ ритма, а половина ширины волоса: линия в 1px, стоящая
   от `left: 50%`, без него сдвинута вправо на полпикселя. Шкала шага четыре
   сюда не применяется, число связано с шириной, а не с воздухом. */
[data-style="derived"] .og__top::after { content: ""; position: absolute; left: 50%; bottom: 0; width: 1px; height: 18px;
  margin-left: -.5px; background: var(--line); }

/* Шесть колонок без зазора: перекладина гребёнки идёт через границы колонок
   непрерывно, а воздух между узлами даёт внутренний отступ самой колонки. */
[data-style="derived"] .og__row { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
[data-style="derived"] .og__br { position: relative; padding: 16px var(--s2) 0; }
[data-style="derived"] .og__br::before, [data-style="derived"] .og__br::after { content: ""; position: absolute; top: 0; height: 18px; width: 50%; }
[data-style="derived"] .og__br::before { right: 50%; border-top: 1px solid var(--line); }
[data-style="derived"] .og__br::after { left: 50%; border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
[data-style="derived"] .og__br:first-child::before { border-top-color: transparent; }
[data-style="derived"] .og__br:last-child::after { border-top-color: transparent; }


/* Дети встают друг под другом, а не в ряд: колонка шириной под двести
   пикселей делит два узла в ряд до неразборчивого. Спина ветви — левая рамка
   контейнера, поэтому она начинается ровно у нижнего края родителя и не
   требует ни одного вычисленного числа. Хвост спины ниже последнего ребёнка
   закрашивается панелью: единственный способ оборвать рамку там, где кончился
   список, не зная высоты его последнего узла. */
[data-style="derived"] .og__kids { position: relative; margin-left: 16px; padding: 12px 0 0 16px;
  border-left: 1px solid var(--line); }
[data-style="derived"] .og__kids > * { position: relative; }
[data-style="derived"] .og__kids > * + * { margin-top: 8px; }
[data-style="derived"] .og__kids > *::before { content: ""; position: absolute; left: -17px; top: 23px; width: 17px;
  height: 1px; background: var(--line); }
[data-style="derived"] .og__kids > *:last-child::after { content: ""; position: absolute; left: -18px; top: 23px;
  bottom: -1px; width: 3px; background: var(--panel); }


/* Узел. Три состояния речи, и все три читаются без цвета: дырявый называет
   дыру словом, целый — числом людей, свёрнутая ветвь — тем, что в ней лежит. */
[data-style="derived"] .ogn { position: relative; padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); font-size: 13px; }
[data-style="derived"] .ogn__n { display: flex; align-items: center; gap: var(--s2); font-weight: 600; }
[data-style="derived"] .ogn__n > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
[data-style="derived"] .ogn__q { margin-top: 4px; font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .ogn__g { margin-top: 4px; font-size: 13px; font-weight: 600; color: var(--high); line-height: var(--lh1); }
[data-style="derived"] .ogn__w { margin-top: 2px; font-size: 13px; color: var(--ink2); line-height: var(--lh1); }
[data-style="derived"] .ogn__a { margin-top: 8px; width: 100%; justify-content: center; }
[data-style="derived"] .ogn--hole { border-color: var(--high); }

/* Выбранный узел и узел-цель перевода разведены не оттенком, а формой обводки:
   сплошное кольцо — «отсюда», пунктир — «сюда». */
[data-style="derived"] .ogn--on { box-shadow: 0 0 0 3px var(--mass-bg); border-color: var(--mass-work); }
[data-style="derived"] .ogn--to { box-shadow: 0 0 0 3px var(--mass-bg); border-style: dashed; border-color: var(--mass-work); }
[data-style="derived"] .ogn__to { display: inline-block; margin-bottom: var(--s1); padding: 2px var(--s2); border-radius: var(--rp);
  background: var(--mass-work); color: #fff; font-size: var(--t1); font-weight: 600; line-height: var(--lh2); }
[data-style="derived"] .ogn--root { min-width: 264px; text-align: center; }

/* Свёрнутая ветвь. Плитка ниже узла и без рамки: целое не спорит за внимание.
   Имена спрятанных узлов стоят в ней прямо — иначе «Внедрение / ERP» из
   заведения списком проверить по схеме нечем. */
[data-style="derived"] .ogn--fold { background: var(--panel2); border-color: transparent; }
[data-style="derived"] .ogn__c { flex: 0 0 auto; color: var(--muted); }

/* «Без подразделения» — не узел структуры, а честный остаток, и рамка у него
   пунктирная по той же причине, по какой он вообще нарисован: заводить его
   подразделением нельзя, а прятать — значит потерять шесть человек. */
[data-style="derived"] .ogn--out { border-style: dashed; }


/* Полоса действия схемы. Перевод людей выбирается узлом, а не перетаскиванием,
   и полоса называет последствие до нажатия — включая то, ради которого перевод
   стоит отложить. */
[data-style="derived"] .ogbar { display: flex; align-items: flex-start; gap: 12px; margin-top: 16px; padding: 12px;
  border: 1px solid var(--medium); border-radius: var(--r3); background: var(--medium-bg); }
[data-style="derived"] .ogbar__i { flex: 0 0 28px; height: 28px; border-radius: var(--r2); background: var(--medium);
  color: #fff; display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .ogbar__m { flex: 1; min-width: 0; }
[data-style="derived"] .ogbar__t { font-size: 13px; font-weight: 600; color: var(--medium); }
[data-style="derived"] .ogbar__w { margin-top: 4px; font-size: 13px; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .ogbar__a { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }


/* Отметка человека в списке: перевод берёт людей отсюда, а цель — со схемы. */
[data-style="derived"] .pk { flex: 0 0 16px; height: 16px; border: 1px solid var(--line); border-radius: var(--r1);
  background: var(--panel); }
[data-style="derived"] .pk--on { border-color: var(--mass-work); background: var(--mass-work); color: #fff; display: flex;
  align-items: center; justify-content: center; }
[data-style="derived"] .who--pick { margin: 0 -8px; padding-left: 8px; padding-right: 8px; border-radius: var(--r2);
  background: var(--mass-bg); }


/* ── Заведение списком и построчный разбор.

   Сто сорок четыре человека вводят один раз. Отклонённая строка называет
   причину и остаётся на месте: «часть не прошла» без имён означает искать
   вручную. Причина названа до нажатия «завести», а не после. */
[data-style="derived"] .paste { padding: 12px; background: var(--panel2); border: 1px dashed var(--line);
  border-radius: var(--r3); color: var(--ink2); white-space: pre-wrap;
  font: 400 13px/var(--lh2) "IBM Plex Mono", monospace; }
[data-style="derived"] .rl { display: flex; align-items: flex-start; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .rl:last-child { border-bottom: 0; }
[data-style="derived"] .rl__n { flex: 0 0 24px; color: var(--muted); font-variant-numeric: tabular-nums; }
[data-style="derived"] .rl__m { flex: 1; min-width: 0; }
[data-style="derived"] .rl__q { display: block; margin-top: 4px; color: var(--high); font-weight: 600; }
[data-style="derived"] .rl__a { flex: 0 0 auto; }



/* ── Облик A: рама карточки ──────────────────────────────────────────────
   Страница рамы не прокручивается сама (у `.page` ядра overflow: hidden),
   и карточка облика прокручивает себя: шапка с лентой едет вместе с
   содержимым, как у Битрикса, а не висит поверх. */
[data-style="derived"] .lk { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column;
  gap: var(--s4); }
[data-style="derived"] .lk__top { display: grid; gap: var(--s3); padding: var(--s4) var(--s5) 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .lkone { max-width: 100%; }

/* У лида вкладок нет, и панель шапки кончается лентой либо просьбой под ней:
   отступ снизу даёт им тот же воздух, что вкладки дают сделке. */
[data-style="derived"] .lk__top > :last-child:not(.lktabs) { margin-bottom: var(--s4); }


/* Строка пути над именем: обращение › лид › сделка. Мелко и приглушённо,
   как крошки, а не вторая шапка: соседние звенья — ссылки цветом текста с
   подчёркиванием при наведении, своё — чуть темнее и без ссылки. Несколько
   сделок лида — списком родного `<details>`; меню всплывает и потому одно
   здесь носит тень (`docs/design/no-ai-look.md`, 7). */
[data-style="derived"] .lkp { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2);
  min-width: 0; font-size: 13px; line-height: var(--lh2); color: var(--muted); }
[data-style="derived"] .lkp a, [data-style="derived"] .lkp summary { display: inline-flex; align-items: center; min-height: 24px; color: var(--muted);
  text-decoration: none; cursor: pointer; }
[data-style="derived"] .lkp a:hover, [data-style="derived"] .lkp summary:hover { color: var(--ink2); text-decoration: underline; }
[data-style="derived"] .lkp a:focus-visible, [data-style="derived"] .lkp summary:focus-visible { outline: 2px solid var(--focus);
  outline-offset: 2px; }
[data-style="derived"] .lkp__sep { color: var(--muted); }
[data-style="derived"] .lkp__here { color: var(--ink2); }
[data-style="derived"] .lkp__more { position: relative; }
[data-style="derived"] .lkp__more summary { list-style: none; }
[data-style="derived"] .lkp__more summary::-webkit-details-marker { display: none; }
[data-style="derived"] .lkp__menu { position: absolute; top: 100%; left: 0; z-index: 10; min-width: 240px;
  margin: var(--s1) 0 0; padding: var(--s1) 0; list-style: none; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r1); box-shadow: var(--shadow-sm); }
[data-style="derived"] .lkp__menu a { display: block; padding: var(--s1) var(--s3); color: var(--ink); }


/* Шапка: имя, сумма простым текстом, двери справа. Пилюля — только статус
   (`docs/design/no-ai-look.md`, 9): сумма в рамке читалась меткой. */
[data-style="derived"] .lkh { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s4); min-width: 0; }
[data-style="derived"] .lkh__t { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -.01em;
  line-height: var(--lh1); min-width: 0; }
[data-style="derived"] .lkh__sum { font-size: 18px; font-weight: 400; font-variant-numeric: tabular-nums;
  color: var(--ink2); white-space: nowrap; }

/* Под темой обращения — номер и кто обратился: суммы у обращения нет, и
   строка приглушена, чтобы тема читалась первой. */
[data-style="derived"] .lkh__by { font-size: 15px; color: var(--ink2); min-width: 0; overflow-wrap: anywhere; }
[data-style="derived"] .lkh__a { align-self: center; }
[data-style="derived"] .lkh__a { display: flex; align-items: center; gap: var(--s2); margin-left: auto; }

/* «Позвонить» — ссылка `tel:` в облике кнопки. Цвет ссылки рамы
   (`.app a`) сильнее кнопки ядра, и текст ушёл бы в цвет её заливки. */
[data-style="derived"] .lkh__a a.btn { text-decoration: none; }
[data-style="derived"] .lkh__a a.btn--p, [data-style="derived"] .lkh__a a.btn--p:hover { color: var(--panel); }
[data-style="derived"] .lkh__q a { display: inline-flex; align-items: center; min-height: 24px; }
[data-style="derived"] .lkh__q { display: inline-flex; align-items: center; height: 32px; padding: 0 var(--s3);
  border: 1px solid var(--line); border-radius: var(--r1); font-size: 13px; font-weight: 600; }


/* ── Лента стадий ────────────────────────────────────────────────────────── */
[data-style="derived"] .rib { display: flex; gap: 2px; min-width: 0; }

/* Имя стадии переносится на вторую строку, а не режется многоточием
   (`docs/design/no-ai-look.md`, 14): «Оценка проектного офиса» и
   «Коммерческое предложение» на шести звеньях в одну строку не входят.
   Звено — флекс по центру, имя — строчный блок внутри, обрезанный только на
   третьей строке, и тогда полное имя стоит в `title`. Поля ужаты до того,
   что съедает скос шеврона. */
[data-style="derived"] .rib__s { flex: 1 1 0; min-width: 0; height: 40px; display: flex; align-items: center;
  justify-content: center; text-align: center;
  padding: 0 var(--s3) 0 var(--s4); border: 0; border-radius: 0;
  font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.2;
  background: var(--bg); color: var(--ink);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%, 12px 50%); }
[data-style="derived"] .rib__w { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere; hyphens: auto; }
[data-style="derived"] .rib__s:first-child { padding-left: var(--s3);
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%); }
[data-style="derived"] .rib__s:last-child { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 12px 50%); }
[data-style="derived"] button.rib__s { cursor: pointer; }
[data-style="derived"] button.rib__s:hover:not(:disabled) { background: var(--mass-bg); }
[data-style="derived"] button.rib__s:focus { outline: none; }
[data-style="derived"] button.rib__s:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
[data-style="derived"] button.rib__s:disabled { opacity: 1; cursor: default; }
[data-style="derived"] .rib__s--done { background: var(--mass); color: var(--panel); }
[data-style="derived"] .rib__s--now { background: var(--ink); color: var(--bg); }

/* Звено исхода: глагол, а не стадия. Текст Blue отличает его от стадий
   впереди, не заводя четвёртой заливки. */
[data-style="derived"] .rib__s--end { color: var(--mass-work); }
[data-style="derived"] .rib__s--end.rib__s--now { color: var(--bg); }


/* Отказ переноса: словами продавца, иначе словами сервера и полями. Беду
   говорит слово и его цвет, а не розовая заливка (`no-ai-look.md`, 6). */
[data-style="derived"] .rib__no { color: var(--ink); font-size: 13px; }
[data-style="derived"] .rib__nw { margin: 0; font-weight: 600; color: var(--high); }
[data-style="derived"] .rib__nf { display: flex; gap: var(--s2); margin-top: var(--s1); }
[data-style="derived"] .rib__nf ul { margin: 0; padding-left: var(--s4); }


/* Развилка исхода — частью шапки через линию, а не второй рамкой в ней. */
[data-style="derived"] .lkx { display: grid; gap: var(--s2); padding: var(--s3) 0 0; border-top: 1px solid var(--line2); }
[data-style="derived"] .lkx__w { margin: 0; font-size: 13px; color: var(--ink2); }
[data-style="derived"] .lkx__a { display: flex; flex-wrap: wrap; gap: var(--s2); }


/* Выбор сделки клиента для хода «В сделку» (а0.3): строки одного списка
   через линию, выбор — родной переключатель, одна подсветка на состояние
   (`no-ai-look.md`, 1 и 4). Сумма простым текстом при стадии, не пилюлей. */
[data-style="derived"] .lkx__deals { display: grid; margin: var(--s2) 0 0; }
[data-style="derived"] .lkx__deal { display: grid; grid-template-columns: 16px minmax(0, 1fr); column-gap: var(--s2);
  align-items: baseline; padding: var(--s2) 0; border-top: 1px solid var(--line2); cursor: pointer; }
[data-style="derived"] .lkx__deal:first-child { border-top: 0; }
[data-style="derived"] .lkx__deal input { margin: 0; }
[data-style="derived"] .lkx__dt { min-width: 0; font-size: 15px; color: var(--ink); }
[data-style="derived"] .lkx__dm { grid-column: 2; font-size: 13px; color: var(--muted); }
[data-style="derived"] .lkx__who { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: var(--s2); }


/* ── Вкладки записи ──────────────────────────────────────────────────────── */
[data-style="derived"] .lktabs { display: flex; gap: var(--s5); margin: 0 calc(-1 * var(--s5)); padding: 0 var(--s5);
  border-top: 1px solid var(--line); overflow-x: auto; }

/* Выбранную вкладку отличает одна черта 2px снизу с прямыми концами — без
   фона, рамки, заливки и смены веса (`docs/design/no-ai-look.md`, 1).
   Старая таблица скругляет всякий `button` на 7px, и черта под скруглённой
   кнопкой загибалась концами: радиус снят здесь. Фокус — только с клавиатуры
   и внутрь, клик мышью рамки не оставляет (там же, 2). */
[data-style="derived"] .lktab { display: inline-flex; align-items: center; gap: var(--s2); height: 44px; padding: 0;
  border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: transparent;
  font-family: inherit; font-size: 15px; font-weight: 400; color: var(--ink2); cursor: pointer;
  white-space: nowrap; }
[data-style="derived"] .lktab:hover { color: var(--ink); }
[data-style="derived"] .lktab:focus { outline: none; }
[data-style="derived"] .lktab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
[data-style="derived"] .lktab--on { color: var(--ink); border-bottom-color: var(--mass); }

/* Счётчик — приглушённое число, не кружок (там же, 9). */
[data-style="derived"] .lktab__n { font-size: 13px; font-weight: 400; color: var(--muted);
  font-variant-numeric: tabular-nums; }


/* ── Две колонки «Общего» ────────────────────────────────────────────────
   Слева 440 px полей — число из контракта, а не вкус: столько держит
   подпись в 160 px и значение в две строки. Узкий экран складывает колонки
   одну под другую, поля первыми. */
[data-style="derived"] .lkg { display: grid; grid-template-columns: 440px minmax(0, 1fr); gap: var(--s4);
  align-items: start; }
[data-style="derived"] .lkg__l, [data-style="derived"] .lkg__r { display: grid; gap: var(--s4); min-width: 0; }


/* Карточка полей: одна рамка на блок, строки внутри — линиями, теней нет
   (`docs/design/no-ai-look.md`, 4 и 7). */
[data-style="derived"] .lkc { min-width: 0; padding: var(--s4) var(--s5); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r3); box-shadow: none; }
[data-style="derived"] .lkc__h { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s2); }
[data-style="derived"] .lkc__h h2 { margin: 0; font-size: 15px; font-weight: 600; }
[data-style="derived"] .lkc__h .btn { margin-left: auto; }
[data-style="derived"] .lkc__v a { display: inline-flex; align-items: center; min-height: 24px; }
[data-style="derived"] .lkc__e { margin-left: auto; padding: 0; border: 0; background: transparent; font-family: inherit;
  display: inline-flex; align-items: center; min-height: 24px;
  font-size: 13px; font-weight: 600; color: var(--mass-work); cursor: pointer; text-decoration: none; }
[data-style="derived"] .lkc__e:hover { text-decoration: underline; }
[data-style="derived"] .lkc__r { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line2); font-size: 15px;
  line-height: var(--lh2); }
[data-style="derived"] .lkc__r:last-child { border-bottom: 0; }
[data-style="derived"] .lkc__k { color: var(--muted); font-size: 13px; padding-top: 2px; }
[data-style="derived"] .lkc__v { min-width: 0; overflow-wrap: anywhere; }
[data-style="derived"] .lkc__rows { min-width: 0; }
[data-style="derived"] .lkc__p { margin: 0; font-size: 15px; line-height: var(--lh2); }
[data-style="derived"] .lkc__none { margin: 0 0 var(--s2); font-size: 13px; color: var(--muted); }

/* Незаполненное обязательное поле — тем же тоном, что предупреждение
   (там же, 12). */
[data-style="derived"] .lkc__need { color: var(--medium); font-weight: 600; }


/* ── Композер ──────────────────────────────────────────────────────────────
   Вход один — «Комментарий», и он заголовок, а не вкладка: выбирать не из
   чего (`docs/design/no-ai-look.md`, 13). */
[data-style="derived"] .lkm { display: grid; gap: var(--s3); padding: var(--s4) var(--s5); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .lkm__h { margin: 0; font-size: 15px; font-weight: 600; }
[data-style="derived"] .lkm__t { width: 100%; box-sizing: border-box; min-height: 48px; padding: var(--s3);
  border: 1px solid var(--line); border-radius: var(--r1); background: var(--panel);
  color: var(--ink); font-family: inherit; font-size: 15px; line-height: var(--lh2); resize: vertical; }
[data-style="derived"] .lkm__t:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }
[data-style="derived"] .lkm__a { display: flex; justify-content: flex-end; }

/* Отключённая кнопка карточки — нейтральная серая, а не бледная копия
   основной: бледно-синяя читается «грузится», а не «нельзя» (там же, 3).
   Старая таблица гасит `button:disabled` прозрачностью — она снята. */
[data-style="derived"] .lk .btn:disabled, [data-style="derived"] .lk .btn--p:disabled { opacity: 1; filter: none; cursor: default;
  background: var(--line2); border-color: var(--line2); color: var(--muted); }


/* ── Лента: запланированное и история ────────────────────────────────────
   Одна поверхность на блок, события — строки одного списка через линии, а
   не стопка рамок; знак стоит сам, приглушённым цветом, без кружка под ним
   (`docs/design/no-ai-look.md`, 4 и 5). Вид события говорит знак, цвет под
   вид завёл бы палитру мимо Venkon. */
[data-style="derived"] .lkf { display: grid; min-width: 0; padding: var(--s3) var(--s5) var(--s2); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .lkf__lab { margin: 0 0 var(--s1); font-size: 15px; font-weight: 600; color: var(--ink); }
[data-style="derived"] .lkf__l { display: grid; margin: 0; padding: 0; list-style: none; }
[data-style="derived"] .lkf__i { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: var(--s3);
  align-items: start; padding: var(--s3) 0; border-top: 1px solid var(--line2); }
[data-style="derived"] .lkf__i:first-child { border-top: 0; }
[data-style="derived"] .lkf__o { display: inline-flex; align-items: center; justify-content: center; width: 16px;
  height: 20px; color: var(--muted); }
[data-style="derived"] .lkf__b { min-width: 0; }
[data-style="derived"] .lkf__h { display: flex; align-items: baseline; gap: var(--s3); font-size: 15px; }
[data-style="derived"] .lkf__h b { min-width: 0; font-weight: 600; }
[data-style="derived"] .lkf__at { margin-left: auto; font-size: 13px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .lkf__at--late { color: var(--high); font-weight: 600; }
[data-style="derived"] .lkf__w { margin: var(--s1) 0 0; font-size: 15px; line-height: var(--lh2); color: var(--ink2);
  overflow-wrap: anywhere; }
[data-style="derived"] .lkf__act { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s2); }
[data-style="derived"] .lkf__act .lkf__at { margin-left: 0; white-space: normal; }
[data-style="derived"] .lkf__none { margin: 0; padding: var(--s2) 0 var(--s3); font-size: 13px; color: var(--muted); }
[data-style="derived"] .lkf__more { display: flex; justify-content: center; padding: var(--s2) 0; }

/* «Повторить» у отказа ленты — словом в строке, цветом ссылки, без рамки. */
[data-style="derived"] .lkf__again { padding: 0; border: 0; border-radius: 0; background: transparent;
  font: inherit; color: var(--mass-work); cursor: pointer; }
[data-style="derived"] .lkf__again:hover { text-decoration: underline; text-underline-offset: 2px; }
[data-style="derived"] .lkf__again:focus { outline: none; }
[data-style="derived"] .lkf__again:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }


/* ── Таблица товаров и бумаг ─────────────────────────────────────────────
   Числа вправо и цифрами одной ширины: столбец сумм читается по разрядам. */
[data-style="derived"] .lkt { width: 100%; border-collapse: collapse; font-size: 15px; }
[data-style="derived"] .lkt th { padding: var(--s2) var(--s3); background: var(--panel2); border-bottom: 1px solid var(--line);
  font-size: 13px; font-weight: 600; color: var(--muted); text-align: left; white-space: nowrap; }
[data-style="derived"] .lkt td { padding: var(--s3); border-bottom: 1px solid var(--line2); vertical-align: top; }
[data-style="derived"] .lkt__n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
[data-style="derived"] th.lkt__n { text-align: right; }
[data-style="derived"] .lkt__i { display: inline-block; min-width: 24px; color: var(--muted); font-size: 13px; }
[data-style="derived"] .lkt__note { margin: 0 0 var(--s3); font-size: 13px; color: var(--muted); }
[data-style="derived"] .lkt__sum { display: grid; gap: var(--s1); width: 340px; max-width: 100%; margin: var(--s3) 0 0 auto;
  font-size: 15px; }
[data-style="derived"] .lkt__r { display: flex; justify-content: space-between; gap: var(--s4);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .lkt__r--all { padding-top: var(--s2); border-top: 1px solid var(--line); font-size: 18px;
  font-weight: 600; }


/* Вкладка вида у обращения — кнопка с ролью с 23.09. Старая таблица снимает
   с `button.view` рамку целиком, а вместе с ней и черту под выбранной
   вкладкой; здесь черта возвращается, специфичностью выше обоих правил. */
[data-style="derived"] button.view { border: 0; border-bottom: 2px solid transparent; background: transparent;
  font-family: inherit; font-weight: 400; }
[data-style="derived"] button.view.view--on { border-bottom-color: var(--mass); font-weight: 600; }
[data-style="derived"] button.view:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }



/* ── Путь двумя уровнями ──────────────────────────────────────────────────

   Верхний уровень — звенья: обращение, лид, сделка. Каждое либо пройдено
   (галочка и номер), либо здесь (рамка с меткой слева), либо не рождено
   (пунктир и слова вместо номера). Три состояния различены не только цветом:
   у пройденного знак, у текущего толщина, у нерождённого штрих (правило 7
   свода — дейтераномалия у ~5% мужчин).

   Стрелка между звеньями нарисована знаком, а не буквой: буква «›» цветом
   линии не набирает контраста ни на одном фоне, и текстом её ставить нельзя.
   Знак контрастом не меряется — он не текст. */
[data-style="derived"] .way { display: flex; align-items: stretch; flex-wrap: wrap; }
[data-style="derived"] .way__lab { margin-bottom: var(--s2); font-size: 11px; font-weight: 600; color: var(--muted); }
[data-style="derived"] .way__lab--on { color: var(--mass-work); }
[data-style="derived"] .way__arr { display: flex; align-items: center; padding: 0 var(--s2); color: var(--muted); }
[data-style="derived"] .wlink { display: grid; align-content: center; gap: 2px; min-width: 188px;
  padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--r2);
  background: var(--panel); }
[data-style="derived"] .wlink__n { display: flex; align-items: center; gap: var(--s1); font-size: 13px; font-weight: 600; }
[data-style="derived"] .wlink__s { font-size: 11px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .wlink__ok { display: inline-flex; color: var(--mass-work); }

/* Текущее звено. Метка слева, а не заливка: заливка спорила бы с подложкой
   шагов, которая лежит прямо под ним и означает то же самое — «мы здесь». */
[data-style="derived"] .wlink--now { border-color: var(--mass); box-shadow: inset 3px 0 0 var(--mass); }

/* Нерождённое. Прозрачный фон намеренно: карточка со своим фоном выглядит
   заведённой записью, а её ещё нет. */
[data-style="derived"] .wlink--none { border-style: dashed; background: transparent; }
[data-style="derived"] .wlink--none .wlink__n { font-weight: 400; color: var(--muted); }


/* Нижний уровень — шаги текущего звена. Подтонированная подложка отделяет их
   от звеньев без второй рамки: два уровня различаются фоном, а не бортом.
   Дорожка проходит под точками светлой линией — точка ложится поверх, и
   пройденное от предстоящего отличает цвет самой точки, а не длина линии. */
[data-style="derived"] .wsteps { margin-top: var(--s4); padding: var(--s3) var(--s4) var(--s4);
  background: var(--mass-bg); border-radius: var(--r3); overflow-x: auto; }

/* Шагов у записи столько, сколько обязательств дал ей справочник: у лида три,
   у обращения шесть, у сделки — сколько прошло по условиям воронки. Число
   колонок поэтому не набирается, а растёт из числа шагов.

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

   Нижняя граница колонки — 132 пикселя: ниже имя шага рассыпается по слогам.
   Дойдя до неё, дорожка уезжает за край и прокручивается внутри своей
   подложки, а не жмёт шаги до нечитаемого. */
[data-style="derived"] .wtl { position: relative; display: grid; grid-auto-flow: column;
  grid-auto-columns: minmax(132px, 1fr); }
[data-style="derived"] .wtl::before { content: ""; position: absolute; left: 4px; right: 4px; top: 4px; height: 4px;
  background: var(--panel); border-radius: var(--rp); }
[data-style="derived"] .wstep { position: relative; padding-right: var(--s4); }
[data-style="derived"] .wstep__d { position: relative; display: block; width: 12px; height: 12px; margin-bottom: var(--s2);
  border-radius: 50%; background: var(--mass-work); }
[data-style="derived"] .wstep--now .wstep__d { background: var(--medium); }
[data-style="derived"] .wstep--wait .wstep__d { background: var(--low); }
[data-style="derived"] .wstep__n { display: block; font-size: 13px; font-weight: 600; line-height: var(--lh1); }
[data-style="derived"] .wstep--wait .wstep__n { font-weight: 400; color: var(--ink2); }
[data-style="derived"] .wstep__s { display: block; margin-top: 2px; font-size: 11px; color: var(--ink2);
  line-height: var(--lh2); }


/* Тонкая полоса пути — для вида «Работа». Та же вещь, что выше, свёрнутая до
   справки: где мы в цепочке, сколько шагов и какой идёт. Имена шагов здесь
   сняты намеренно — читать их некогда, работа стоит ниже. */
[data-style="derived"] .wthin { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3);
  padding: var(--s3) var(--s5); background: var(--panel2);
  border-bottom: 1px solid var(--line); font-size: 11px; color: var(--muted); }
[data-style="derived"] .wthin b { color: var(--ink); font-weight: 600; }
[data-style="derived"] .wthin__t { display: flex; flex: 1; min-width: 160px; gap: var(--s1); }
[data-style="derived"] .wthin__i { flex: 1; height: 4px; background: var(--line2); border-radius: var(--rp); }
[data-style="derived"] .wthin__i--done { background: var(--mass-work); }
[data-style="derived"] .wthin__i--now { background: var(--medium); }


/* ── Обзор: сетка блоков и блок с вопросом ────────────────────────────────

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

   Блок без вопроса в шапке не существует. Вопрос длиннее ярлыка и потому
   набран строкой, а не заголовком: заголовок такой длины спорил бы с именем
   записи в шапке. */
[data-style="derived"] .qgrid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }
[data-style="derived"] .qcol { display: grid; align-content: start; gap: var(--s5); min-width: 0; padding: var(--s5); }
[data-style="derived"] .qcol--side { background: var(--panel2); border-left: 1px solid var(--line); }

/* Блок и полоса денег внутри него — дети сетки, и `min-width: 0` им не
   украшение: без него длинное число или неразрывная строка растягивают колонку
   сетки сверх её доли, и правая колонка уезжает под левую. */
[data-style="derived"] .qsec { min-width: 0; }
[data-style="derived"] .qsec__q { margin: 0 0 var(--s3); font-size: 13px; font-weight: 600; color: var(--ink2); }

/* Ответ, который не влез в свою молекулу: строка под блоком, объясняющая
   пустоту или границу. Пустой блок без такой строки неотличим от сломанного. */
[data-style="derived"] .qsec__w { margin-top: var(--s2); font-size: 11px; color: var(--muted); line-height: var(--lh2); }


/* ── Цитата клиента ───────────────────────────────────────────────────────

   То, что человек сказал, стоит целиком и как есть. Пересказ системы поверх
   исходника — уже интерпретация, а на обзоре интерпретировать нечего: обзор
   показывает, а решает шаг. Под цитатой имя, роль, кто записал и откуда она
   приехала: цитата без происхождения — это слух. */
[data-style="derived"] .said { padding-left: var(--s4); border-left: 2px solid var(--mass); }
[data-style="derived"] .said__t { font-size: 15px; line-height: var(--lh2); }
[data-style="derived"] .said__w { margin-top: var(--s1); font-size: 11px; color: var(--muted); line-height: var(--lh2); }


/* ── Полоса денег и бумаги под ней ────────────────────────────────────────

   Шкала отвечает на «чем подтверждено» одним взглядом: доля суммы, закрытая
   бумагами, и доля, которую никто не подтверждал. Числа под ней приезжают
   минорными единицами и складываются сервером — деление на экране запрещено
   предикатом, и правильно запрещено: две арифметики над одними деньгами
   расходятся молча.

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

   Строки бумаг отделены волосяной линией, а не собственной рамкой у каждой.
   Три одинаковые коробки подряд говорят «три разные вещи», а это одна вещь в
   трёх состояниях; то же правило держит рама записи, и заводить рядом второе
   значило бы разойтись с ней на первой правке. */
/* Раскрой объявлен явно, хотя у `div` он такой по умолчанию. Имя `.pay`
   занято старой таблицей (`ui/style.css`, строка платежа), и та делает
   блок гибкой строкой: дорожка шкалы теряет ширину и схлопывается в ноль.
   Найдено 11.09 глазами на стенде — полоса стояла в разметке высотой 8 и
   шириной 0, а числа под ней читались верно, поэтому ни один предикат не
   краснел. Артборд этого не показывает: он старой таблицы не грузит.
   Имён, занятых в обеих таблицах, сто; это первое, где чужое правило
   доехало до экрана. */
[data-style="derived"] .pay { min-width: 0; display: block; }
[data-style="derived"] .pay__scale { display: flex; height: 8px; overflow: hidden; background: var(--line2);
  border-radius: var(--rp); }
[data-style="derived"] .pay__part { height: 100%; }
[data-style="derived"] .pay__part--paid { background: var(--mass-work); }
[data-style="derived"] .pay__part--due { background: var(--medium); }
[data-style="derived"] .pay__leg { display: flex; flex-wrap: wrap; gap: var(--s4); margin-top: var(--s2);
  font-size: 11px; color: var(--muted); }
[data-style="derived"] .pay__leg b { font-size: 13px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .pdocs { display: grid; margin-top: var(--s3); }
[data-style="derived"] .pdoc { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .pdoc:last-child { border-bottom: 0; }
[data-style="derived"] .pdoc__n { min-width: 64px; font-size: 13px; font-weight: 600; }
[data-style="derived"] .pdoc__w { font-size: 11px; color: var(--muted); }
[data-style="derived"] .pdoc__v { margin-left: auto; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums; }


/* ── Плитки клиента ───────────────────────────────────────────────────────

   Четыре числа, за которыми обычно проваливаются в карточку клиента. Число
   крупное, подпись под ним словами и с оговоркой — «2 обращения, оба
   закрыты» отвечает на вопрос, а «2» отправляет проверять.

   Рамки у плитки нет: она лежит на подтонированной колонке, и белого фона
   довольно, чтобы плитка читалась плиткой. Борт поверх контраста фона —
   второй способ сказать то же самое, и на четырёх плитках подряд он даёт
   решётку, от которой эта ступень и уходит. */
[data-style="derived"] .ptiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
[data-style="derived"] .ptile { padding: var(--s2) var(--s3); background: var(--panel); border-radius: var(--r2); }
[data-style="derived"] .ptile__v { display: block; font-size: 22px; font-weight: 600; line-height: var(--lh1);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .ptile__k { font-size: 11px; color: var(--muted); line-height: var(--lh2); }


/* ── Список риска: род, вес и одна дверь ──────────────────────────────────

   Находка приходит правилом слоя смысла, а не соседством чисел на экране:
   вёрстка может подсказать, какое правило завести, но сама находкой не
   служит. У строки поэтому четыре части — о ком она, что нашли, из чего это
   следует и сколько весит.

   **Список один, а не два, и это решение, а не умолчание.** Находку о клиенте
   можно было поставить в блок клиента, а о записи оставить здесь — тогда
   каждая стояла бы там, где её предмет. Развилка решена вопросом, который
   человек задаёт: «чем рискуем» спрашивают один раз и ждут полного ответа.
   Разложенные по двум блокам находки отвечают на него наполовину — тот, кто
   нашёл одну, решит, что она и есть всё, а обзор заведён ровно затем, чтобы
   не смотреть в двух местах.

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

   Род сказан словом (`about_kind`), а не выведен из заголовка. До правки формы
   11.09 «половина суммы без бумаги» и «у клиента не назначен владелец»
   отличались только текстом, и развести их вёрстка могла бы лишь разбором
   слов — то есть догадкой о том, что сервер знает точно.

   Вес — три ступени домена (`low`, `normal`, `high`) на той же лестнице
   цветов, какой размечено остальное: спокойное, предупреждение, тревога.
   Второго ряда цветов под них не заводится, и слово стоит рядом с заливкой —
   заливка говорит «тревога», насколько именно, говорит только слово.

   Рамки у строки нет: заливка уже отделяет её от соседей, а борт поверх
   заливки — второй способ сказать то же самое. */
[data-style="derived"] .risks { display: grid; gap: var(--s2); }
[data-style="derived"] .risk { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3);
  background: var(--low-bg); border-radius: var(--r2); }
[data-style="derived"] .risk--low { background: var(--low-bg); }
[data-style="derived"] .risk--normal { background: var(--medium-bg); }
[data-style="derived"] .risk--high { background: var(--high-bg); }
[data-style="derived"] .risk__i { flex: 0 0 8px; height: 8px; margin-top: 4px; border-radius: 50%; background: var(--low); }
[data-style="derived"] .risk--normal .risk__i { background: var(--medium); }
[data-style="derived"] .risk--high .risk__i { background: var(--high); }
[data-style="derived"] .risk__m { min-width: 0; }
[data-style="derived"] .risk__t { font-size: 13px; font-weight: 600; }
[data-style="derived"] .risk--normal .risk__t { color: var(--medium); }
[data-style="derived"] .risk--high .risk__t { color: var(--high); }
[data-style="derived"] .risk__w { margin-top: 2px; font-size: 13px; color: var(--ink2); line-height: var(--lh2); }

/* Правый столбик строки: род сверху, вес под ним. Род набран спокойно —
   он отвечает «о ком», а не «насколько плохо», и кричать ему нечем. Цвет у
   него не приглушённый: `--muted` на заливке тревоги даёт 4,51 при норме
   4,5, и запаса в одну сотую хватит до первой правки токена. */
[data-style="derived"] .risk__r { flex: 0 0 auto; margin-left: auto; display: grid; justify-items: end; gap: 2px;
  text-align: right; }
[data-style="derived"] .risk__a { font-size: 11px; color: var(--ink2); }
[data-style="derived"] .risk__g { font-size: 11px; font-weight: 600; color: var(--low); }
[data-style="derived"] .risk--normal .risk__g { color: var(--medium); }
[data-style="derived"] .risk--high .risk__g { color: var(--high); }
[data-style="derived"] .risk--high .risk__g { color: var(--high); }
[data-style="derived"] .risk--med .risk__g { color: var(--medium); }


/* ── Исход: чем запись кончилась и чем её кончают ──────────────────────────

   Закрытие — исход, а не шаг, и поэтому оно стоит здесь, а не на виде
   «Работа». Шаг двигает запись вперёд и закрывается тем, что случилось;
   исход её останавливает, и решают его, глядя на всю запись целиком, а не на
   один пункт плана. До этой ступени закрытие было кнопкой карточки, вместе с
   карточкой ушло и не появилось нигде — сделку с причиной стало негде
   закрыть.

   Место блока — последним в левой колонке. Колонка читается сверху вниз как
   история записи: что сказали, сколько денег, ждут ли смежные, чем кончилось.
   Конец истории стоит в конце, а не первым: наверх его просит только закрытая
   запись, а открытых на всяком экране больше.

   Три состояния, и все три отвечают на один вопрос шапки. Путь пройден, а
   исхода нет — строка о том, что записи осталось, и двери. Запись идёт —
   строка о том, чем она кончится сама, и дверь остановки. Запись закрыта —
   слово исхода, причина и когда; дверей у неё нет, потому что переоткрытия в
   ступени нет (`sales::check_patch`, `check_ticket_close`).

   Причина не набирается прямо в блоке ни в одном из трёх случаев: у сделки и
   лида она приезжает справочником арендатора (`/v1/reasons`), у обращения —
   словами в отдельной просьбе. Поле причины внутри блока сделало бы обзор
   формой, а обзор отвечает, а не спрашивает.

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

   Четвёртая строка живёт в коде, а не на картинке: открытое обращение
   артборд не рисует (он рисует закрытое, третий случай блока), и слова его
   записаны здесь, чтобы не потерялись, — «Ещё ничем: обращение в работе.
   Либо оно станет лидом или нарядом — назначение ждёт на вкладке «Работа», —
   либо его закрывают отказом отсюда».

   Хвостовая строка говорит человеку, откуда берётся причина, и на этом
   кончается. Истории экрана в ней нет, доводов устройства — тоже. Первым
   ушло «карточка предлагала только проигрыш» (правка строителя экранов
   11.09), следом — вся остальная кладка того же рода: почему справочник, а
   не поле; почему у лида нет кнопки конверсии; как устроены три исхода
   обращения. Всё это отвечает тому, кто экран строит, а перед экраном стоит
   тот, кто им работает. У закрытого обращения хвоста не осталось вовсе:
   строки блока уже назвали исход, причину и время, и добавить к ним нечего.
   Место доводов — примечание реестра (`docs/design/screens.toml`) и этот
   комментарий, где их читает тот, кто их ищет.

   Своей рамки у блока нет, как и у соседей по колонке: борт поверх общего
   фона был бы вторым способом сказать «это отдельная вещь».

   Расстояние между частями держит корень (`.end`), а не части поодиночке.
   Дети, каждый со своим отступом, — это два места, решающие одно расстояние,
   и расходятся они на первой правке одного из двух. Строки «ключ —
   значение» у закрытой записи стоят при этом вплотную: они пара, и шаг
   решётки между ними развёл бы причину и время в две разные вещи. */
[data-style="derived"] .end { display: grid; gap: var(--s3); }
[data-style="derived"] .end__w { margin: 0; font-size: 15px; line-height: var(--lh2); }
[data-style="derived"] .end__act { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }

/* Слово исхода крупнее строки и стоит рядом с меткой: слово отвечает «чем
   кончилось», метка — «кончилось ли вообще». Одно без другого читается
   наполовину: «стало лидом» без метки можно принять за пересказ шага. */
[data-style="derived"] .end__o { display: flex; align-items: center; gap: var(--s3); }
[data-style="derived"] .end__v { font-size: 18px; font-weight: 600; line-height: var(--lh1); }


/* ── Вид «Работа»: шаг и его улики ────────────────────────────────────────

   Заголовок — что от вас нужно, глаголом. Одно предложение под ним — зачем и
   что родится. Дальше кнопка тем же глаголом: если кнопка называется иначе,
   чем заголовок, человек ищет третью.

   Улики шага стоят под чертой и отвечают на вопросы, которые задают перед
   нажатием: с кем разговариваем, куда звонить, о чём речь, сколько денег.
   Больше ничего здесь нет намеренно — всё прочее во вкладке рядом, и нижняя
   строка говорит об этом словами, чтобы отсутствие не читалось пропажей. */
[data-style="derived"] .job { padding: var(--s5); }
[data-style="derived"] .job__h { margin: 0 0 var(--s2); font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .job__w { margin: 0; max-width: 56ch; font-size: 15px; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .job__act { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s4); }
[data-style="derived"] .job__due { font-size: 13px; color: var(--muted); }
[data-style="derived"] .job__more { margin-top: var(--s5); padding-top: var(--s3); border-top: 1px solid var(--line2);
  font-size: 11px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .clues { display: flex; flex-wrap: wrap; gap: var(--s5); margin-top: var(--s5);
  padding-top: var(--s4); border-top: 1px solid var(--line2); }
[data-style="derived"] .clue { min-width: 150px; }
[data-style="derived"] .clue__k { display: block; margin-bottom: 2px; font-size: 11px; color: var(--muted); }
[data-style="derived"] .clue__v { font-size: 13px; font-weight: 600; }



/* ── Рама кабинета.

   Кабинет партнёра и кабинет клиента — единственные экраны системы, которые
   открывает не наш сотрудник. Рама приложения им не годится и не потому, что
   некрасива: в ней меню на тридцать восемь разделов, полоса закреплённых
   разделов с чужими числами и вкладки открытых записей. Всё это — рабочее
   место, а гость приходит за своим и уходит. Поэтому одна полоса, пять
   пунктов и имя того, чей это кабинет: без него человек, ведущий два ИНН,
   не знает, в чей кабинет вошёл. */
[data-style="derived"] .cab { display: flex; flex-direction: column; flex: 1; min-width: 0; }
[data-style="derived"] .cab__t { height: 56px; flex: 0 0 56px; display: flex; align-items: center; gap: 12px;
  padding: 0 24px; background: var(--panel); border-bottom: 1px solid var(--line); }
[data-style="derived"] .cab__b { display: flex; align-items: center; gap: 8px; }
[data-style="derived"] .cab__vk { width: 22px; height: 22px; object-fit: contain; }
[data-style="derived"] .cab__n { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .cab__nav { display: flex; align-items: center; gap: 2px; margin-left: 16px; }
[data-style="derived"] .cab__i { display: flex; align-items: center; gap: var(--s2); height: 34px; padding: 0 12px;
  border-radius: var(--r2); font-size: 13px; color: var(--muted); white-space: nowrap; }
[data-style="derived"] .cab__i--on { background: var(--mass-bg); color: var(--mass-work); font-weight: 600; }
[data-style="derived"] .cab__me { margin-left: auto; display: flex; align-items: center; gap: 12px;
  font-size: 13px; color: var(--muted); }
[data-style="derived"] .cab__p { flex: 1; overflow: hidden; padding: 20px 24px 24px;
  display: flex; flex-direction: column; gap: 12px; }

/* Заголовок кабинета: имя того, кто вошёл, и кто ему отвечает с той стороны.
   Телефон куратора стоит на экране, а не в разделе «Контакты»: человек,
   который дошёл до кабинета, чтобы позвонить, уже потратил на это минуту. */
[data-style="derived"] .cab__h { display: flex; align-items: flex-start; gap: 16px; }
[data-style="derived"] .cab__h h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -.015em; }

/* Подпись кабинета. Ядерная `.u` не годится: она заведена под прописной
   ярлык раздела, а здесь строка обстоятельств в две-три фразы. Переопределять
   `.u` в этом месте значило бы завести второе значение одному имени. */
[data-style="derived"] .cab__s { display: block; margin-top: 4px; font-size: 13px; color: var(--muted);
  line-height: var(--lh2); }
[data-style="derived"] .cab__a { margin-left: auto; display: flex; gap: 8px; flex-shrink: 0; }


/* ── Переписка кабинета.

   Отличается от ленты событий (`fe`) тем, чего у ленты нет: у реплики есть
   автор с той или другой стороны, и это единственное, что человек читает
   первым. `fe` рисует «что случилось», `talk` — «кто сказал». Слить их
   значило бы получить ленту, в которой ответ инженера неотличим от отметки
   системы о смене статуса.

   Вопрос инженера выделен отдельно, потому что он — единственное место
   переписки, где мяч у клиента, и ответ вводится тут же строкой. Кнопка
   «ответить», открывающая окно, добавляет два действия к тому, ради чего
   человек и открыл экран. */
[data-style="derived"] .talk { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .talk:last-of-type { border-bottom: 0; }
[data-style="derived"] .talk__m { flex: 1; min-width: 0; }
[data-style="derived"] .talk__h { display: flex; align-items: baseline; gap: 8px; }
[data-style="derived"] .talk__h b { font-size: 13px; font-weight: 600; }
[data-style="derived"] .talk__h span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .talk__at { margin-left: auto; font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .talk__b { font-size: 13px; color: var(--ink2); margin-top: 4px; line-height: var(--lh2); }
[data-style="derived"] .talk--us .ava { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .talk__ask { margin-top: 8px; padding: 8px 12px; border-radius: var(--r2);
  background: var(--medium-bg); color: var(--medium); font-size: 13px; line-height: var(--lh2); }
[data-style="derived"] .talk__ask b { font-weight: 600; }


/* ── Поле правки на месте.

   Одна форма на четыре экрана: ответ инженеру, причина отказа, что запомнить
   о проигрыше, возражение по фактору. Везде это текст, который человек пишет
   в той же строке, где родилась причина, — и именно поэтому поле, а не окно.
   Ядерная `.inp` прижимает содержимое вправо: она заведена под числа. */
[data-style="derived"] .tx { flex: 1; min-width: 0; min-height: 34px; display: flex; align-items: center;
  padding: 8px 12px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r2); font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .tx--on { border-color: var(--mass-work); box-shadow: 0 0 0 3px var(--mass-bg); color: var(--ink); }
[data-style="derived"] .tx--tall { min-height: 62px; align-items: flex-start; }
[data-style="derived"] .tx__r { display: flex; align-items: center; gap: 8px; }


/* ── Причина одним нажатием.

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

   Выбранное залито, а не обведено: обводка на чипе высотой тридцать пикселей
   у каждого двадцатого мужчины сливается с рамкой соседа. */
[data-style="derived"] .rsn { display: flex; flex-wrap: wrap; gap: var(--s2); }
[data-style="derived"] .rsn__o { display: inline-flex; align-items: center; height: 30px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: var(--r4); background: var(--panel);
  font-size: 13px; color: var(--ink2); white-space: nowrap; }
[data-style="derived"] .rsn__o--on { background: var(--high); border-color: var(--high); color: #fff; font-weight: 600; }


/* ── Ступени партнёрской программы.

   Не список условий, а лестница, на которой партнёр где-то стоит. Прежде
   уровни печатались четырьмя равными строками, и по ним нельзя было понять
   ни где партнёр сейчас, ни сколько до следующей. Текущая ступень залита,
   у каждой стоит порог входа — то самое число, ради которого лестницу и
   читают. */
[data-style="derived"] .lvl { display: flex; flex-direction: column; }
[data-style="derived"] .lvl__r { display: flex; align-items: baseline; gap: 12px; padding: 8px 12px;
  margin: 0 -12px; border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .lvl__r:last-child { border-bottom: 0; }
[data-style="derived"] .lvl__r--on { background: var(--mass-bg); box-shadow: inset 2px 0 0 var(--mass-work); }
[data-style="derived"] .lvl__n { flex: 0 0 118px; font-weight: 600; }
[data-style="derived"] .lvl__c { flex: 0 0 52px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .lvl__w { flex: 1; min-width: 0; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .lvl__w b { color: var(--ink2); font-weight: 600; font-variant-numeric: tabular-nums; }


/* ── Балл крупно.

   Ядерная `.health` показывает здоровье сделки строкой в карточке — там оно
   одно из двадцати чисел. Здесь балл и есть предмет экрана, и рядом с ним
   обязаны стоять три вещи, которых у строки нет: из чего сложился, когда
   пересчитан и по какой шкале читается. Шкала подписана по краям и в
   середине, потому что «54» без якорей не отличается от «54 из 200». */
[data-style="derived"] .score { display: flex; align-items: center; gap: 20px; }

/* 46px — намеренный выход за шкалу кеглей (--t6 = 28px): балл здесь предмет
   экрана, а не строка в карточке, и на верхней ступени шкалы он читался бы
   как обычный заголовок. Единственное такое место в файле. */
[data-style="derived"] .score__v { flex: 0 0 auto; font-size: 46px; font-weight: 600; line-height: var(--lh1);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--medium); }
[data-style="derived"] .score__m { flex: 1; min-width: 0; }
[data-style="derived"] .score__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .score__ax { display: flex; justify-content: space-between; margin-top: var(--s2);
  font-size: 13px; color: var(--muted); }


/* ── Фактор балла.

   Строка, которая обязана нести четыре вещи непустыми: заголовок, причину,
   улику и вклад. Прежде фактор печатался как «Экономический покупатель ·
   не назван · −12», и оспорить его было нечем: неизвестно, откуда система
   взяла, что не назван. Улика — четвёртое поле, и без неё строка не
   собирается.

   Возражение живёт под строкой того фактора, к которому относится, а не в
   общем списке замечаний: замечание, оторванное от факта, разбирать так же
   нечем, как факт без улики. */
[data-style="derived"] .fac { padding: 12px 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .fac:last-of-type { border-bottom: 0; }
[data-style="derived"] .fac__r { display: grid; grid-template-columns: 196px minmax(0,1fr) 112px 56px 96px;
  gap: 12px; align-items: center; }
[data-style="derived"] .fac__t { font-size: 13px; font-weight: 600; }
[data-style="derived"] .fac__w { font-size: 13px; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .fac__e { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .fac__b { position: relative; height: 8px; border-radius: var(--r1); background: var(--line2); }
[data-style="derived"] .fac__b i { position: absolute; top: 0; bottom: 0; border-radius: var(--r1); }
[data-style="derived"] .fac__z { position: absolute; top: -4px; bottom: -4px; width: 1.5px; background: var(--muted); }
[data-style="derived"] .fac__v { text-align: right; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .fac--plus .fac__v { color: var(--mass-work); }
[data-style="derived"] .fac--minus .fac__v { color: var(--high); }
[data-style="derived"] .fac--plus .fac__b i { background: var(--mass); }
[data-style="derived"] .fac--minus .fac__b i { background: var(--high); }
[data-style="derived"] .fac__a { text-align: right; }
[data-style="derived"] .fac__o { margin: 8px 0 2px 208px; padding: 8px 12px; border-left: 2px solid var(--medium);
  background: var(--panel2); border-radius: 0 var(--r2) var(--r2) 0; font-size: 13px;
  color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .fac__o b { font-weight: 600; }
[data-style="derived"] .fac__o u { text-decoration: none; color: var(--medium); font-weight: 600; }



/* ── Улика под утверждением.

   Находка без улики — мнение. На обзоре, в журнале и в находках дня под
   каждым утверждением стоит то, из чего оно выведено: фраза клиента, письмо,
   протокол встречи. В ленте сделки такая цитата уже есть (`.fe__q`), но она
   часть ленты и живёт внутри `.fe`. Улика на этих экранах стоит вне ленты, у
   неё есть свой источник с датой, и растить её из ленточного класса значит
   снова получить имя, которое врёт о месте. */
[data-style="derived"] .quo { margin-top: var(--s2); padding: var(--s2) 12px; border-left: 2px solid var(--line);
  background: var(--panel2); border-radius: 0 var(--r2) var(--r2) 0; font-size: 13px;
  color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .quo b { font-weight: 600; color: var(--ink); }
[data-style="derived"] .quo u { display: block; text-decoration: none; color: var(--muted); margin-top: 4px; }


/* ── Движение по стадии.

   Сумма на стадии — это фотография склада. Она одинаковая у воронки, которая
   работает, и у воронки, которая стоит. Разводит их только движение: сколько
   вошло за неделю, сколько вышло и сколько простояло дольше, чем стадия
   обычно длится. Полоса показывает долю застрявшего внутри стадии, потому что
   вопрос звучит «какая часть этих денег мёртвая», а не «сколько тут всего».

   Ядерная `.bar` умеет одну долю и не умеет назвать вторую часть цветом
   тревоги; `.cov` умеет имя, полосу и одно значение, а здесь значений четыре
   и три из них — счётчики разной природы. */
[data-style="derived"] .mv { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .mv:last-child { border-bottom: 0; }
[data-style="derived"] .mv__n { flex: 0 0 138px; font-weight: 600; }
[data-style="derived"] .mv__n span { display: block; font-weight: 400; color: var(--muted);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .mv__b { flex: 1; height: 10px; border-radius: var(--rp); background: var(--line2);
  display: flex; overflow: hidden; }
[data-style="derived"] .mv__b i { display: block; height: 100%; background: var(--mass); }
[data-style="derived"] .mv__b i.stuck { background: var(--medium); }
[data-style="derived"] .mv--jam .mv__b i.stuck { background: var(--high); }
[data-style="derived"] .mv__f { flex: 0 0 104px; display: flex; gap: 12px; justify-content: flex-end;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .mv__in { color: var(--mass-work); font-weight: 600; }
[data-style="derived"] .mv__out { color: var(--muted); font-weight: 600; }
[data-style="derived"] .mv__age { flex: 0 0 178px; text-align: right; color: var(--muted); }
[data-style="derived"] .mv__age b { font-weight: 600; color: var(--ink2); font-variant-numeric: tabular-nums; }
[data-style="derived"] .mv--jam .mv__n { color: var(--high); }
[data-style="derived"] .mv--jam .mv__age b { color: var(--high); }


/* ── Прогноз в двух весах.

   Одна строка на категорию, и в ней оба веса рядом: тот, что стоит в
   настройке, и тот, что вышел по сделкам, дошедшим до решения за восемнадцать
   месяцев.
   Разница — не украшение таблицы, она и есть ответ экрана: категория, где
   объявленный вес втрое выше исторического, держит прогноз на плаву в
   одиночку. Сетка, а не флексы: пять колонок обязаны стоять столбиком,
   иначе взглядом не сравнить вес с весом. */
[data-style="derived"] .fc { display: grid; grid-template-columns: minmax(0,1fr) 92px 62px 62px 96px;
  gap: 12px; align-items: baseline; padding: 8px 0;
  border-bottom: 1px solid var(--line2); font-size: 13px; }
[data-style="derived"] .fc:last-of-type { border-bottom: 0; }
[data-style="derived"] .fc--h { color: var(--muted); font-size: var(--t2); font-weight: 600;
  border-bottom-color: var(--line); }
[data-style="derived"] .fc__k { color: var(--ink2); min-width: 0; }
[data-style="derived"] .fc__v, [data-style="derived"] .fc__w, [data-style="derived"] .fc__r { text-align: right; font-variant-numeric: tabular-nums; }
[data-style="derived"] .fc__w { color: var(--muted); }
[data-style="derived"] .fc__w--was { text-decoration: line-through; }
[data-style="derived"] .fc__r { font-weight: 600; }
[data-style="derived"] .fc--drop .fc__r { color: var(--high); }
[data-style="derived"] .fc--h .fc__v, [data-style="derived"] .fc--h .fc__w, [data-style="derived"] .fc--h .fc__r { color: var(--muted); }


/* ── Верх канбана: создать, воронка, отбор, вид.

   Одна строка вместо шапки со сводкой. Сводка воронки — числа руководителя
   («в работе», «медиана цикла») — ушла в отчёты вместе с аналитикой колонок
   (контракт a0.1, раздел 4). Переключатель вида рисует только те виды, что
   открываются: «Дела» и «Календарь» макета не построены, и кнопки к ним были
   бы обещанием без двери. */
[data-style="derived"] .kbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 16px 24px 12px; }
[data-style="derived"] .kbar__pipe { display: inline-flex; align-items: center; gap: 8px; height: 36px;
  padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); font-size: 15px; color: var(--ink2); }
[data-style="derived"] .kbar__pipe select { border: 0; background: transparent; font: inherit; font-weight: 600;
  color: var(--ink); height: 32px; padding: 0; }
[data-style="derived"] .kbar__find { flex: 1 1 320px; max-width: 480px; display: flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); color: var(--muted); }
[data-style="derived"] .kbar__find:focus-within { border-color: var(--focus); }
[data-style="derived"] .kbar__find input { flex: 1; min-width: 0; height: 32px; padding: 0; border: 0;
  background: transparent; font: inherit; font-size: 15px; color: var(--ink); }
[data-style="derived"] .kbar__mine { flex: none; height: 24px; padding: 0 8px; border: 0; border-radius: var(--r1);
  background: transparent; font: inherit; font-size: 13px; color: var(--muted); cursor: pointer; }
[data-style="derived"] .kbar__mine--on { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .kbar__views { margin-left: auto; display: inline-flex; gap: 4px; padding: 4px;
  border-radius: var(--r3); background: var(--line2); }
[data-style="derived"] .kbar__v { height: 28px; padding: 0 12px; border: 0; border-radius: var(--r1);
  background: transparent; font: inherit; font-size: 15px; color: var(--ink); cursor: pointer; }

/* Текущий вид — подложкой, и только ею: вес и цвет у видов одни
   (`docs/design/no-ai-look.md`, правило 1). */
[data-style="derived"] .kbar__v--on { background: var(--panel); }


/* ── Колонка канбана.

   Шапка несёт полосу-акцент, имя, число и сумму — то, что видно глазом.
   Полоса у всех колонок одна, синяя: разноцветные полосы макета — цвета не из
   палитры Venkon. Колонка, над которой держат карточку, подсвечивается
   подложкой акцента: куда упадёт карточка, видно до того, как её отпустили.

   Шапка — не коробка: полоса прямая, без скругления, и под ней текст, а не
   ещё одна рамка над рамками карточек (`docs/design/no-ai-look.md`, 4 и 8).
   Пустая колонка суммы не называет — «—» вместо «0 сум». «Быстрая сделка» —
   кнопка-строка без пунктира: пунктир читался как «перетащите сюда».

   Имена своей семьи `kb`, а не `.board*` из `derived_pages`: та доска общая
   с днём, обзором и состояниями, и перетаскивание в её правилах сказалось бы
   на трёх экранах, где карточки не двигаются. */
[data-style="derived"] .kb { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(248px, 1fr);
  gap: 12px; align-items: start; padding: 0 24px 24px; overflow-x: auto; }
[data-style="derived"] .kb__col { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 4px;
  border-radius: var(--r3); }
[data-style="derived"] .kb__col--over { background: var(--mass-bg); }
[data-style="derived"] .kb__h { padding: 8px 8px 4px; border-top: 4px solid var(--mass); border-radius: 0; }
[data-style="derived"] .kb__n { display: flex; align-items: baseline; gap: 8px; font-size: 15px; }
[data-style="derived"] .kb__n b { min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
[data-style="derived"] .kb__c { margin-left: auto; font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .kb__s { margin-top: 4px; font-size: 13px; color: var(--ink2); font-variant-numeric: tabular-nums; }
[data-style="derived"] .kb__add { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 8px;
  border: 0; border-radius: var(--r1); background: transparent;
  font: inherit; font-size: 13px; font-weight: 400; color: var(--ink2); cursor: pointer; }
[data-style="derived"] .kb__add:hover { background: var(--line2); color: var(--ink); }
[data-style="derived"] .kb__list { display: flex; flex-direction: column; gap: 8px; min-height: 48px; }
[data-style="derived"] .kb__more { padding: 4px 0; text-align: center; font-size: 13px; color: var(--muted); }

/* Повторный вопрос (отбор, поиск, перенос): карточки стоят на местах,
   колонки приглушены до ответа — не спиннер и не заготовка. */
[data-style="derived"] .kb[aria-busy="true"] .kb__list { opacity: .55; }


/* ── Карточка сделки на канбане.

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

   Название — кнопка, а не щелчок по коробке: открыть сделку можно с
   клавиатуры. Там же кнопка «Перенести в…» раскрывает стадии списком — тот же
   перенос, что перетаскиванием, для тех, у кого мыши нет. Отказ раскрывается
   под карточкой (`kc__why`) словами продавца — «Сначала подпишите договор», —
   и говорит о себе словом и его цветом: без красной рамки вокруг карточки и
   розовой плашки под словами (`docs/design/no-ai-look.md`, 6 и 17). */
[data-style="derived"] .kc { padding: 12px; border: 1px solid var(--line); border-radius: var(--r3);
  background: var(--panel); cursor: grab; }
[data-style="derived"] .kc:hover { border-color: var(--mass); }
[data-style="derived"] .kc--drag { opacity: .5; }
[data-style="derived"] .kc--busy { opacity: .6; cursor: progress; }
[data-style="derived"] .kc__t { display: block; width: 100%; min-height: 24px; padding: 2px 0; border: 0; background: transparent;
  text-align: left; font: inherit; font-size: 15px; font-weight: 600; line-height: var(--lh1);
  color: var(--ink); cursor: pointer; }
[data-style="derived"] .kc__t:hover { color: var(--mass-work); }
[data-style="derived"] .kc__o { margin-top: 4px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .kc__a { margin-top: 8px; font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .kc__d { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px; font-size: 13px;
  line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .kc__d svg { flex: none; margin-top: 4px; }
[data-style="derived"] .kc__d--late { color: var(--high); }
[data-style="derived"] .kc__d--none { color: var(--high); font-weight: 600; }
[data-style="derived"] .kc__f { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding-top: 8px;
  border-top: 1px solid var(--line2); font-size: 13px; color: var(--muted); }
[data-style="derived"] .kc__w { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-style="derived"] .kc__mv { flex: none; width: 24px; height: 24px; display: inline-flex; align-items: center;
  justify-content: center; padding: 0; border: 0; border-radius: var(--r1);
  background: transparent; color: var(--muted); cursor: pointer; }
[data-style="derived"] .kc__mv:hover { background: var(--line2); color: var(--ink); }
[data-style="derived"] .kc__ava { flex: none; width: 24px; height: 24px; display: inline-flex; align-items: center;
  justify-content: center; border-radius: var(--rp); background: var(--mass-bg);
  color: var(--mass-work); font-size: 13px; font-weight: 600; }
[data-style="derived"] .kc__menu { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; padding: 4px;
  border: 1px solid var(--line); border-radius: var(--r3); background: var(--panel2); }
[data-style="derived"] .kc__to { height: 32px; padding: 0 8px; border: 0; border-radius: var(--r1);
  background: transparent; text-align: left; font: inherit; font-size: 13px; color: var(--ink);
  cursor: pointer; }
[data-style="derived"] .kc__to:hover, [data-style="derived"] .kc__to:focus-visible { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .kc__why { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line2);
  font-size: 13px; line-height: var(--lh2); color: var(--ink2); }
[data-style="derived"] .kc__why b { display: block; font-weight: 600; color: var(--high); }


/* ── Быстрая сделка в колонке.

   Четыре поля, без которых сервер сделку не заводит: название, клиент,
   направление и сумма. Стадия берётся у колонки, воронка — у доски: их не
   переспрашивают. Клиент подбирается молекулой подбора (`kq__pick`), а не
   ключом. */
[data-style="derived"] .kq { display: flex; flex-direction: column; gap: 8px; padding: 12px;
  border: 1px solid var(--mass); border-radius: var(--r3); background: var(--panel); }
[data-style="derived"] .kq__in, [data-style="derived"] .kq__pick input { width: 100%; min-width: 0; height: 32px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: var(--r1); background: var(--panel);
  font: inherit; font-size: 13px; color: var(--ink); }
[data-style="derived"] .kq__pick { min-width: 0; }
[data-style="derived"] .kq__act { display: flex; justify-content: flex-end; gap: 8px; }
[data-style="derived"] .kq__err { font-size: 13px; line-height: var(--lh2); color: var(--high); }


/* ── Пустое место, которое объясняет себя.

   Три рода, и это главное, что часть добавляет к старому кадру. Пусто,
   потому что нечего показать, — норма, и у неё есть время последнего прогона.
   Пусто, потому что не положено видеть, — запрет, и у него есть, кем стать,
   чтобы увидеть. Пусто, потому что не доехало, — поломка, и у неё есть время
   отказа и кнопка «повторить». Одинаковая серая карточка на все три и есть
   причина, по которой в поддержку звонят с двумя из них зря.

   Строка «что это не значит» — не вежливость. Пустая дебиторка значит «долгов
   нет», а читается как «не загрузилось»; сказать это прямо дешевле, чем
   отвечать на звонок. */
[data-style="derived"] .es { border: 1px solid var(--line); border-radius: var(--r3); overflow: hidden;
  background: var(--panel); display: flex; flex-direction: column; }
[data-style="derived"] .es--stop { border-color: var(--medium); }
[data-style="derived"] .es--broke { border-color: var(--high); }
[data-style="derived"] .es__w { padding: var(--s2) 12px; background: var(--panel2); border-bottom: 1px solid var(--line);
  font-size: var(--t2); font-weight: 600; color: var(--muted); }
[data-style="derived"] .es__b { padding: 12px; display: flex; gap: 12px; }
[data-style="derived"] .es__i { flex: 0 0 30px; height: 30px; border-radius: var(--r3); background: var(--low-bg);
  color: var(--muted); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .es--stop .es__i { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .es--broke .es__i { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .es__m { min-width: 0; flex: 1; }
[data-style="derived"] .es__t { font-size: 13px; font-weight: 600; }
[data-style="derived"] .es--stop .es__t { color: var(--medium); }
[data-style="derived"] .es--broke .es__t { color: var(--high); }
[data-style="derived"] .es__s { font-size: 13px; color: var(--ink2); margin-top: 4px; line-height: var(--lh2); }
[data-style="derived"] .es__s b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .es__no { font-size: 13px; color: var(--muted); margin-top: var(--s1); line-height: var(--lh2); }
[data-style="derived"] .es__a { margin-top: 8px; display: flex; gap: var(--s2); flex-wrap: wrap; }


/* ── Счётчик со своим методом.

   Три части, и все три обязательны: имя, число и то, что число считает.
   `.term` даёт две и красит ключ в приглушённый — имя счётчика перестаёт быть
   именем; `.kf` даёт две и не оставляет места кнопке «пересчитать». А кнопка
   здесь — половина смысла: у счётчика, который нельзя воспроизвести списком,
   нет способа доказать, что он не врёт. */
[data-style="derived"] .cn { display: grid; grid-template-columns: 150px minmax(0,1fr) auto; gap: 12px;
  align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .cn:last-child { border-bottom: 0; }
[data-style="derived"] .cn__n { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: var(--s2); }
[data-style="derived"] .cn__v { background: var(--line2); border-radius: var(--r3); padding: 2px 8px; font-size: var(--t2);
  font-weight: 600; color: var(--ink2); font-variant-numeric: tabular-nums; }
[data-style="derived"] .cn__v--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .cn__v--zero { background: transparent; color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--line); }
[data-style="derived"] .cn__m { font-size: 13px; color: var(--ink2); line-height: var(--lh2); }
[data-style="derived"] .cn__m u { text-decoration: none; color: var(--muted); }
[data-style="derived"] .cn__m b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .cn__a { justify-self: end; align-self: center; }


/* ── Запись журнала.

   Лента «пока вас не было» (`.ev`) отвечает на «что я пропустил» и живёт
   одной строкой. Журнал — машинная истина, и ему нужны сразу четыре слоя:
   время с миллисекундами, человеческое имя события, машинный ключ с
   идентификатором и следствие. Дописывать эти четыре слоя в `.ev__*` значило
   бы утяжелить ленту дня ради экрана настройки, который открывают раз в
   месяц. Разные экраны, разная плотность, разные части.

   Свёрнутая группа — та же мысль, что «простое по умолчанию»: человек ищет
   причину, а следствий у неё бывает двести восемнадцать. */
[data-style="derived"] .jr { display: flex; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--line2); }
[data-style="derived"] .jr:last-child { border-bottom: 0; }
[data-style="derived"] .jr--fold { background: var(--panel2); }
[data-style="derived"] .jr__at { flex: 0 0 116px; font-size: 13px; color: var(--muted); padding-top: 4px; }
[data-style="derived"] .jr__i { flex: 0 0 26px; height: 26px; border-radius: 50%; background: var(--low-bg);
  color: var(--muted); display: flex; align-items: center; justify-content: center; }
[data-style="derived"] .jr__i--hand { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .jr__i--warn { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .jr__b { flex: 1; min-width: 0; }
[data-style="derived"] .jr__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .jr__t span { font-size: 13px; font-weight: 400; color: var(--muted); }
[data-style="derived"] .jr__c { font-size: 13px; color: var(--ink2); margin-top: 4px; line-height: var(--lh2); }
[data-style="derived"] .jr__c b { font-weight: 600; }
[data-style="derived"] .jr__k { font-size: 13px; color: var(--muted); margin-top: var(--s2);
  display: flex; flex-wrap: wrap; gap: 12px; }
[data-style="derived"] .jr__n { display: inline-flex; align-items: center; gap: var(--s2); margin-top: 8px;
  font-size: 13px; font-weight: 600; color: var(--mass-work); }
[data-style="derived"] .jr__r { margin-left: auto; flex-shrink: 0; display: flex; gap: var(--s2); align-items: flex-start; }


/* ── Правило со своими находками.

   Группа — это правило, а не тема: заголовок несёт ключ, число находок,
   деньги под ними и точность. Точность здесь — не украшение: правило, находки
   которого снимают четыре раза из пяти, производит не работу, а шум, и
   выключать его надо там же, где видно его мусор.

   Строка снятия с причиной стоит внутри группы: снятие без причины не
   улучшает правило и превращает экран в место, где молча гасят лампочки. */
[data-style="derived"] .rg { border: 1px solid var(--line); border-radius: var(--r3); overflow: hidden;
  background: var(--panel); }
[data-style="derived"] .rg + .rg { margin-top: 12px; }
[data-style="derived"] .rg--bad { border-color: var(--medium); }
[data-style="derived"] .rg__h { display: flex; align-items: baseline; gap: 12px; padding: 12px;
  background: var(--panel2); border-bottom: 1px solid var(--line); }
[data-style="derived"] .rg__t { font-size: 13px; font-weight: 600; min-width: 0; }
[data-style="derived"] .rg__k { font-size: 13px; color: var(--muted); }
[data-style="derived"] .rg__n { margin-left: auto; font-size: 13px; font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .rg__q { font-size: 13px; font-weight: 600; white-space: nowrap; color: var(--mass-work); }
[data-style="derived"] .rg--bad .rg__q { color: var(--medium); }
[data-style="derived"] .rg__b { padding: 12px; display: flex; flex-direction: column; gap: 8px; }
[data-style="derived"] .rg__f { padding: 8px 12px; border-top: 1px solid var(--line2); display: flex;
  align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
[data-style="derived"] .rg__f .btn { margin-left: auto; }
[data-style="derived"] .rg__why { display: flex; align-items: center; gap: 8px; margin-top: 8px;
  padding: 8px 12px; border-radius: var(--r2); background: var(--medium-bg);
  color: var(--medium); font-size: 13px; }
[data-style="derived"] .rg__why u { flex: 1; min-width: 0; height: 27px; display: flex; align-items: center;
  padding: 0 8px; border-radius: var(--r2); text-decoration: none; background: var(--panel);
  color: var(--muted); box-shadow: inset 0 0 0 1px var(--medium); }



/* ── Метод под числом.

   Правило «число отдаётся вместе с методом» на этих экранах срабатывает
   двадцать с лишним раз: маржа, оплачиваемость, прогноз даты, оценка
   удовлетворённости. Раньше такая подпись бралась чужим классом из блока
   месяца — имя врало о назначении. Здесь у неё своё имя и одна работа:
   сказать, из чего сложилось число и с чем его сравнивают. */
[data-style="derived"] .how { font-size: 13px; color: var(--muted); line-height: var(--lh2); }
[data-style="derived"] .how b { color: var(--ink2); font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .how + .how { margin-top: var(--s1); }


/* ── Проверка, сработавшая в момент ввода.

   Стоит под полем и называет число, а не отказ. Два веса: предупреждение
   (действие пройдёт, но за ним потянется согласование) и запрет (действие
   не пройдёт, и сказано почему). Различаются не только цветом — у запрета
   знак залит, у предупреждения обведён (правило 7 свода). */
[data-style="derived"] .catch { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px;
  padding: 8px 12px; border: 1px solid transparent; border-radius: var(--r2);
  font-size: 13px; line-height: var(--lh2); }
[data-style="derived"] .catch b { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .catch > svg { flex: 0 0 14px; margin-top: 2px; }

/* Тень снята: плашка статична — она не поднята над полем и не нажимается,
   а поднятое тенью читается как нажимаемое. Три веса различают фон, цвет
   текста и цвет рамки; рамка стала настоящей, а не подделкой из тени. */
[data-style="derived"] .catch--warn { background: var(--medium-bg); color: var(--medium);
  border-color: var(--medium); }
[data-style="derived"] .catch--stop { background: var(--high); color: #fff; }
[data-style="derived"] .catch--ok { background: var(--mass-bg); color: var(--mass-work); }


/* ── План против факта с порогом.

   Ядерная `.bar` умеет одну долю и не умеет двух вещей, без которых у работ
   она бессмысленна: перебор за сто процентов и засечку порога, на котором
   включается согласование. Человек смотрит сюда ради одного вопроса —
   далеко ли до того места, где придётся идти к руководителю. */
[data-style="derived"] .gg { position: relative; height: 12px; border-radius: var(--rp); background: var(--line2);
  display: flex; overflow: visible; }
[data-style="derived"] .gg i { display: block; height: 100%; }
[data-style="derived"] .gg i:first-child { border-radius: var(--rp) 0 0 var(--rp); }
[data-style="derived"] .gg i:last-of-type { border-radius: 0 var(--rp) var(--rp) 0; }
[data-style="derived"] .gg .k-plan { background: var(--mass); }
[data-style="derived"] .gg .k-warn { background: var(--medium); }
[data-style="derived"] .gg .k-over { background: var(--high); }
[data-style="derived"] .gg__t { position: absolute; top: -5px; bottom: -5px; width: 2px; border-radius: var(--r1);
  background: var(--ink); }
[data-style="derived"] .gg__c { position: absolute; top: -24px; transform: translateX(-50%); white-space: nowrap;
  font-size: 13px; color: var(--ink2); font-weight: 600; }
[data-style="derived"] .gg__l { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; font-size: 13px;
  color: var(--muted); }
[data-style="derived"] .gg__l i { display: inline-block; width: 10px; height: 10px; border-radius: var(--r1);
  margin-right: var(--s2); vertical-align: -1px; }
[data-style="derived"] .gg__l b { color: var(--ink2); font-weight: 600; font-variant-numeric: tabular-nums; }


/* ── Строка списанного времени.

   Час без следа не попадает ни в акт, ни в себестоимость, ни в маржу — и
   именно поэтому строка правится на месте: чем дальше списание от работы,
   тем чаще его не делают вовсе. Последняя строка списка — не кнопка
   «добавить», а готовое поле ввода: лишний щелчок перед делом, которое
   делают по десять раз в день, стоит дороже, чем строка на экране. */
[data-style="derived"] .wl { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .wl:last-child { border-bottom: 0; }
[data-style="derived"] .wl__m { flex: 1; min-width: 0; }
[data-style="derived"] .wl__n { font-size: 13px; font-weight: 600; }
[data-style="derived"] .wl__d { font-size: 13px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .wl__h { flex: 0 0 66px; text-align: right; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .wl__h--over { color: var(--high); }
[data-style="derived"] .wl__x { flex: 0 0 16px; color: var(--muted); opacity: 0; cursor: pointer; }
[data-style="derived"] .wl:hover .wl__x { opacity: 1; }
[data-style="derived"] .wl--new { border-bottom: 0; margin: 4px -12px 0; padding: 12px;
  background: var(--mass-bg); border-radius: var(--r2);
  box-shadow: inset 2px 0 0 var(--mass-work); flex-wrap: wrap; }
[data-style="derived"] .wl__f { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
[data-style="derived"] .wl__in { flex: 1; min-width: 0; height: 30px; display: flex; align-items: center;
  padding: 0 12px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r2); font-size: 13px; color: var(--muted); }
[data-style="derived"] .wl__in--on { border-color: var(--mass-work); box-shadow: 0 0 0 3px var(--mass-bg); color: var(--ink); }
[data-style="derived"] .wl__hh { flex: 0 0 74px; height: 30px; display: flex; align-items: center;
  justify-content: flex-end; padding: 0 12px; background: var(--panel);
  border: 1px solid var(--mass-work); border-radius: var(--r2); font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums; box-shadow: 0 0 0 3px var(--mass-bg); }


/* ── Неделя одного человека клетками.

   Пять клеток вместо числа «38,5». Число говорит, сколько всего; клетки
   говорят, как это лежало: восемь-восемь-восемь-восемь-шесть и ноль-ноль-
   четыре-ноль-девять — это разная неделя при одной сумме, и вторую надо
   чинить. Заливка — форма занятости, цифра внутри — часы: состояние читается
   и без цвета. */
[data-style="derived"] .tape { display: flex; gap: 4px; }
[data-style="derived"] .tape i { flex: 1; height: 26px; border-radius: var(--r1); display: flex; align-items: center;
  justify-content: center; font: 600 13px/1 inherit; font-style: normal;
  font-variant-numeric: tabular-nums; background: var(--line2); color: var(--muted); }
[data-style="derived"] .tape .k-full { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .tape .k-part { background: var(--medium-bg); color: var(--medium); }
[data-style="derived"] .tape .k-thin { background: var(--high-bg); color: var(--high);
  box-shadow: inset 0 0 0 1.5px var(--high); }


/* ── Доска диспетчера.

   Полоса «не назначено» шире остальных и стоит первой: это единственная
   очередь, где бездействие диспетчера стоит денег. Остальные три сжаты в
   сводку — они отвечают «как идёт», а не «что делать». */
[data-style="derived"] .lanes { display: grid; gap: 12px; min-height: 0; }
[data-style="derived"] .lane { display: flex; flex-direction: column; min-height: 0; background: var(--panel2);
  border: 1px solid var(--line); border-radius: var(--r3); }
[data-style="derived"] .lane--hot { border-color: var(--high); }
[data-style="derived"] .lane__h { display: flex; align-items: center; gap: 8px; padding: 12px;
  border-bottom: 1px solid var(--line); }
[data-style="derived"] .lane__h b { font-size: 15px; font-weight: 600; }
[data-style="derived"] .lane__n { margin-left: auto; font-size: 18px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .lane--hot .lane__h b, [data-style="derived"] .lane--hot .lane__n { color: var(--high); }
[data-style="derived"] .lane__b { padding: 12px; display: flex; flex-direction: column; gap: 8px; overflow: hidden; }
[data-style="derived"] .tk { background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--low);
  border-radius: var(--r2); padding: 12px; }
[data-style="derived"] .tk--hot { border-left-color: var(--high); }
[data-style="derived"] .tk--warn { border-left-color: var(--medium); }
[data-style="derived"] .tk__t { font-size: 15px; font-weight: 600; line-height: var(--lh1); }
[data-style="derived"] .tk__c { font-size: 13px; color: var(--muted); margin-top: 4px; }
[data-style="derived"] .tk__sla { display: flex; align-items: baseline; gap: var(--s2); margin-top: 8px; }
[data-style="derived"] .tk__sla b { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; }
[data-style="derived"] .tk__sla span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .tk--hot .tk__sla b { color: var(--high); }
[data-style="derived"] .tk__who { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line2); }
[data-style="derived"] .tk__wm { flex: 1; min-width: 0; }
[data-style="derived"] .tk__wn { font-size: 13px; font-weight: 600; }
[data-style="derived"] .tk__ww { font-size: 13px; color: var(--muted); line-height: var(--lh2); margin-top: 2px; }


/* ── Загрузка, развёрнутая на карточке.

   Кому отдать — вторая половина снесённого экрана «Загрузка». Она открывается
   нажатием «Другому» и живёт внутри карточки, а не панелью рядом: диспетчер
   соглашается с предложенным именем в девяти случаях из десяти, и постоянная
   панель платит за эти девять шириной доски.

   Блок отбит фоном и рамкой, а не одним отступом: раскрытое должно читаться
   как часть этой карточки, иначе на доске из четырёх карточек непонятно, к
   какой из них относятся кандидаты. Строки человека берут общий `.who` —
   тот же, что в панели «Кто чем занят»: одна раскладка на оба места, чтобы
   имя и часы стояли одинаково там и там. */
[data-style="derived"] .tk__alt { margin-top: 12px; padding: 12px; border: 1px solid var(--line);
  border-radius: var(--r2); background: var(--bg); }
[data-style="derived"] .tk__alt .who { padding: var(--s2) 0; }
[data-style="derived"] .tk__alt .catch { margin-top: var(--s2); }
[data-style="derived"] .tk__alt .how { margin-top: 8px; }


/* Нажатая кнопка раскрытия. Без неё раскрытый блок висит без причины: видно
   что открылось, не видно чем. */
[data-style="derived"] .btn--on { background: var(--line2); border-color: var(--line); }


/* ── Цепочка зависимостей.

   Работы поставки и этапы проекта — не список дел, а очередь, где каждое
   звено держит следующее. Чек-лист этого не показывает: в нём восемь строк
   выглядят восемью независимыми задачами, и человек берётся за ту, что
   проще, вместо той, что держит дату. Линия слева говорит, что звенья
   связаны; строка «держит» называет, кого именно ждут. */
[data-style="derived"] .dep { display: flex; flex-direction: column; }
[data-style="derived"] .dep__r { display: flex; gap: 12px; padding: 12px 0; }
[data-style="derived"] .dep__i { position: relative; flex: 0 0 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
  font-weight: 600; background: var(--low-bg); color: var(--muted); }
[data-style="derived"] .dep__i--done { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .dep__i--now { background: var(--medium); color: #fff; }
[data-style="derived"] .dep__r:not(:last-child) .dep__i::after { content: ""; position: absolute; left: 50%;
  /* Полпикселя влево — не отступ, а центровка однопиксельной нити под
     кружком: шаг четыре её бы сдвинул с оси. */
  top: 28px; width: 1px; height: 26px; margin-left: -.5px; background: var(--line); }
[data-style="derived"] .dep__m { flex: 1; min-width: 0; }
[data-style="derived"] .dep__t { font-size: 15px; font-weight: 600; }
[data-style="derived"] .dep__r--wait .dep__t { font-weight: 400; color: var(--muted); }
[data-style="derived"] .dep__s { font-size: 13px; color: var(--muted); margin-top: 4px; line-height: var(--lh2); }
[data-style="derived"] .dep__w { display: inline-flex; align-items: center; gap: var(--s2); margin-top: var(--s2);
  font-size: 13px; font-weight: 600; color: var(--high); }
[data-style="derived"] .dep__d { flex: 0 0 132px; text-align: right; }
[data-style="derived"] .dep__d b { display: block; font-size: 15px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; }
[data-style="derived"] .dep__d span { font-size: 13px; color: var(--muted); }
[data-style="derived"] .dep__d--over b { color: var(--high); }


/* ── Серия касаний.

   Пять засечек года. Сделанное — на подложке, текущее — обведено, пропущенное
   залито: три состояния различаются формой, и внутри каждого стоит номер
   касания. Точка одним цветом здесь не годится — это ровно то место свода,
   где ядро правило 7 не держит. */
[data-style="derived"] .ser { display: inline-flex; align-items: center; gap: 4px; }
[data-style="derived"] .ser i { width: 22px; height: 22px; border-radius: var(--r2); display: flex; align-items: center;
  justify-content: center; font: 600 13px/1 inherit; font-style: normal;
  background: var(--line2); color: var(--muted); }
[data-style="derived"] .ser .k-ok { background: var(--mass-bg); color: var(--mass-work); }
[data-style="derived"] .ser .k-now { background: transparent; color: var(--medium);
  box-shadow: inset 0 0 0 1.5px var(--medium); }
[data-style="derived"] .ser .k-miss { background: var(--high); color: #fff; }


/* ── Режим «издали».

   Экран инженера и экран диспетчера открыты весь рабочий день и стоят не под
   носом: инженер смотрит в них от стола, диспетчер — от двери и через плечо.
   Кегль поднят по шкале на ступень (заголовок — на две), строка и кнопка
   выросли под правило 4 свода. Это не тема и не отдельный дизайн — надстройка над теми же токенами
   поверх той же разметки, поэтому переключение ветки продолжает работать. */
[data-style="derived"] .far { font-size: 18px; }
[data-style="derived"] .far .dhead h1 { font-size: 28px; }
[data-style="derived"] .far .panel__h h2 { font-size: 18px; }
[data-style="derived"] .far .u { font-size: 15px; }
[data-style="derived"] .far .btn { height: 36px; font-size: 15px; }
[data-style="derived"] .far .btn--s { height: 31px; font-size: 15px; }
[data-style="derived"] .far .cx, [data-style="derived"] .far .cx__k, [data-style="derived"] .far .how { font-size: 15px; }


/* ── Текущая работа инженера.

   Одна на экране и крупнее всего остального: пока она идёт, все прочие
   строки — не выбор, а фон. Таймер и кнопка остановки стоят вместе, потому
   что это одно действие, разорванное по разным углам старого экрана. */
[data-style="derived"] .now { display: flex; align-items: center; gap: 16px; padding: 16px 20px;
  border: 1px solid var(--mass-work); border-radius: var(--r3); background: var(--mass-bg); }
[data-style="derived"] .now__m { flex: 1; min-width: 0; }
[data-style="derived"] .now__t { font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
[data-style="derived"] .now__s { font-size: 15px; color: var(--ink2); margin-top: 4px; }
[data-style="derived"] .now__c { flex: 0 0 auto; text-align: right; }

/* Сорок — намеренный выход за шкалу кеглей: таймер текущей работы читают
   от двери, и верхняя ступень (28) с этой дистанции уже не берётся. */
[data-style="derived"] .now__n { font-size: 40px; font-weight: 600; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1; color: var(--mass); }
[data-style="derived"] .now__l { font-size: 13px; color: var(--muted); margin-top: var(--s1); }
[data-style="derived"] .now__a { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; }


/* ── Строка очереди на рабочем месте.

   Одна следующая названа, остальные идут строкой. Срок — единственное, что
   стоит справа: на рабочем месте не выбирают из шести дел, а берут
   ближайшее по сроку и делают. */
[data-style="derived"] .q { display: flex; align-items: center; gap: 12px; padding: 12px 0;
  border-bottom: 1px solid var(--line2); }
[data-style="derived"] .q:last-child { border-bottom: 0; }
[data-style="derived"] .q__i { flex: 0 0 32px; height: 32px; border-radius: var(--r3); display: flex; align-items: center;
  justify-content: center; background: var(--low-bg); color: var(--ink2); }
[data-style="derived"] .q__i--hot { background: var(--high-bg); color: var(--high); }
[data-style="derived"] .q__m { flex: 1; min-width: 0; }
[data-style="derived"] .q__t { font-size: 18px; font-weight: 600; }
[data-style="derived"] .q__s { font-size: 15px; color: var(--muted); margin-top: 2px; }
[data-style="derived"] .q__r { flex: 0 0 auto; text-align: right; font-size: 15px; }
[data-style="derived"] .q__r b { display: block; font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }
[data-style="derived"] .q__r--hot b { color: var(--high); }


/* Полоса отмены. Действие уже произошло, десять секунд на возврат. */
[data-style="derived"] .undoline { display: flex; align-items: center; gap: 12px; padding: 12px 16px;
  border-radius: var(--r3); background: var(--ink); color: var(--panel); font-size: 13px; }
[data-style="derived"] .undoline b { font-weight: 600; }
[data-style="derived"] .undoline__t { margin-left: auto; font-variant-numeric: tabular-nums; opacity: .7; }
[data-style="derived"] .undoline .btn { background: transparent; border-color: var(--muted); color: var(--panel); }
