/* Надстройка шелла tvz-crm над дизайн-системой Works Light.
   Только геометрия и только токены: своих цветов здесь нет, все значения —
   var(--c-*) из design.css.

   Зачем файл вообще: Works Light рассчитана на десктоп (сайдбар 252px),
   а ТЗ §8 требует равноправия мобильного и десктопа. Ниже — адаптация
   каркаса под телефон; правки самой системы делаются в апстриме.

   Одно исключение из «цвета не трогаем» — блок читаемости тёмной темы в
   конце файла. Это не новый цвет и не вкус: на тёмном фоне мелкий текст,
   набранный самым приглушённым токеном (--c-tx-4), выцветал до нечитаемого —
   «серое на тёмном выцвело почти в невидимое, подсветите чуть» (симуляция
   001-А). Правка меняет не палитру, а ВЫБОР токена: тот же мелкий текст
   берёт токен на ступень контрастнее. Менять сами значения токенов нельзя —
   они живут в апстриме. */

/* --- Мера ширины и плотность (проход «UI прибрать», 29.07.2026) ------------

   Владелец посмотрел форму внесения на большом мониторе: «UI прибрать». Три
   беды разом, и все три — про то, как экран распоряжается местом.

   1. Колонка контента тянулась во всю ширину монитора. Поле «Имя» шириной
      1600 px нелепо и читается плохо: глаз теряет начало строки.
   2. Воздуха между блоками больше, чем самих блоков: форма из трёх полей
      занимала два экрана.
   3. Пара «подпись — значение» разъезжалась по краям карточки — «читаю через
      провал» (двойник Забелиной, симуляция 001-А).

   Меры берутся из самой дизайн-системы, а не из вкуса:

   * `--crm-col` 1080 px — ширина самой широкой СОБСТВЕННОЙ коробки Works
     Light: `.tvz-mm` в design.css (`width:1080px`). Больше неё система не
     растягивает ничего, и колонка контента — не исключение;
   * `--crm-col-form` 560 px — узкая колонка системы: `.tvz-placeholder`
     (`max-width:560px`); рядом `.tvz-pal__box` 580 и `.tvz-modal` от 440.
     Форма — это модалка, вынесенная на страницу, и шириной она модалке равна;
   * плотность — сетка контролов: высота `--ctl-h` (40), шаг `--gap` (10).
     Те же токены, которыми живут кнопки и поля.

   Значения токенов не трогаются (они в апстриме, ADR-0002): здесь только
   геометрия и выбор уже существующих токенов, как во всём остальном файле. */
:root {
  --crm-col: 1080px;
  --crm-col-form: 560px;
}

/* Колонка контента. Не по центру: заголовок страницы стоит в шапке слева, и
   уезжающий от него текст читался бы как другая страница.

   Мера висит на ПРЯМЫХ детях области контента, а не на `.tvz-page`: карточки
   контакта и клиента открываются из «Моего участка» прямо в неё, минуя
   каркас страницы, — и без этого правила расползались бы во всю ширину. */
.tvz-content > * {
  max-width: var(--crm-col);
}

/* Экраны, которым ширина ИДЁТ НА ПОЛЬЗУ, колонкой не ограничены: доска
   сделок показывает больше этапов без прокрутки вбок, таблицы — больше
   колонок целиком, карточка сделки разводит деньги и участников по краям
   вместо тесной середины. Текстовые формы и списки остаются в колонке:
   строка во весь монитор не читается (слово владельца 04.08 — «контент не
   тянется на страницу»). */
.tvz-content > .tvz-page:has(.tvz-kan),
.tvz-content > .tvz-page:has(.tvz-stable),
.tvz-content > .tvz-page:has(.tvz-dealpage),
/* Карточка звонка (П-91) — двухколонная, разговору ширина идёт на пользу
   (владелец, 06.08: «во весь экран», дважды — потолок был и у ленты). */
.tvz-content > .tvz-page:has(.tvz-call),
.tvz-content > .tvz-page--search,
.tvz-content > .tvz-ccard-page,
.tvz-content > .tvz-dealpage {
  max-width: none;
}

.tvz-page {
  gap: var(--gap);
}

.tvz-page__body {
  gap: var(--gap);
}

/* Переключатель темы на экране входа: система рисует карточку по центру и
   про кнопку в углу ничего не знает. Только геометрия — цвета у кнопки свои
   из design.css. Экран входа тоже открывают ночью. */
.tvz-login__theme {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 1;
}

/* Шапка карточки входа — по центру (слово владельца 05.08): бренд и
   подпись, прижатые влево над центрированной формой, читались криво.
   design.css вендорный (ADR-0002) — потому надстройкой здесь. */
.tvz-login__brand {
  justify-content: center;
}

.tvz-login__sub {
  text-align: center;
}

/* Действия строки таблицы прижаты вправо: ряд кнопок в ячейку не помещается,
   поэтому там «⋯»-меню системы, а здесь только его выравнивание. */
.tvz-row-acts {
  display: flex;
  justify-content: flex-end;
}

/* --- Экран поиска (П-4а) --------------------------------------------------
   Выдача — список строк, а не таблица: у строки четыре этажа (название,
   цепочка, каналы связи, роли с уровнями охвата), и в ячейку таблицы это
   ложится только горизонтальной прокруткой. На телефоне менеджер работает
   в 90% случаев, поэтому список.

   Строка объекта — кнопка: палец должен попадать по всей строке, а не по
   ссылке в тексте. Только геометрия; цвета — токены дизайн-системы. */
.tvz-hits {
  display: flex;
  flex-direction: column;
}

.tvz-hit {
  display: flex;
  gap: var(--gap);
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-bottom: 1px solid var(--c-bd2);
  border-radius: var(--rad);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-hit--plain {
  cursor: default;
}

.tvz-hits > .tvz-hit:last-child {
  border-bottom: 0;
}

.tvz-hit:hover {
  background: var(--c-hover);
}

.tvz-hit--plain:hover {
  background: transparent;
}

.tvz-hit__main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* Подсказка «что понимает поиск» — строкой под полем, а не экраном вместо
   базы (решение владельца 29.07.2026). Полезна первые дни, места не стоит. */
.tvz-hint {
  margin: 0;
  color: var(--c-tx-4);
  font-size: var(--fz-sm);
}

.tvz-hit__name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: var(--c-tx);
}

.tvz-hit__sub {
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
}

.tvz-hit__tags,
.tvz-hit__side {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}

.tvz-hit__side {
  justify-content: flex-end;
  flex: none;
}

.tvz-hit__tags {
  margin-top: 2px;
}

/* Чем совпала строка выдачи (П-8в, B-38). Отдельная строка, а не бейдж:
   объяснение читают глазами и целиком — «фамилия „Балашов", клиент „ООО
   «Терраком»"», — а бейджи в строке уже заняты ролью, уровнем охвата и
   свежестью. Тон приглушённый: это объяснение, а не предупреждение.
   Без него нечёткий поиск читается как сбой: на «Домодедово» приходил
   клиент «Лесной Дом», и понять почему было нельзя. */
.tvz-hit__why {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
}

.tvz-hit__why b {
  font-weight: 600;
  color: var(--c-tx-2);
}

/* Вид найденного объекта словом (B-30): `id=1` бывает и клиентом, и юрлицом,
   и площадкой. Плашка перед названием, чтобы тип читался раньше имени. */
.tvz-kind {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border: 1px solid var(--c-bd);
  border-radius: var(--r-sm);
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
  text-transform: lowercase;
  flex: none;
}

/* Пометка «через партнёра» с именем партнёра. Не бейдж системы намеренно:
   бейджи в строке заняты ролью, уровнем охвата и свежестью, а эта пометка
   обязана читаться раньше их всех — менеджер звонит не человеку клиента,
   и узнать об этом он должен ДО набора номера (поправка №2 к ТЗ).
   Только геометрия; цвет — акцентные токены дизайн-системы. */
.tvz-partner {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad-pill);
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
  font-size: var(--fz-micro);
  font-weight: 600;
  white-space: nowrap;
}

/* Заголовок уровня охвата: без него выдача теряет главное — понимание,
   откуда человек отвечает за площадку. */
.tvz-level {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

.tvz-level__t {
  font-size: 16px;
  font-weight: 700;
}

.tvz-level__n {
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
}

/* Ряда фильтров у поиска больше нет: узкое поле должности и кнопка сброса
   уехали в поповер «Фильтры» и в чипы снятия (хендофф поиска). Их правила
   сняты вместе с ними — мёртвый CSS живёт дольше мёртвой разметки и однажды
   попадает на чужой класс. */

/* --- Карточки (П-4б) ------------------------------------------------------
   Только геометрия: цвета, радиусы и высоты — токены дизайн-системы.
   Шапка карточки: имя крупно, пометки под ним, владелец отношений — справа
   отдельным блоком (ТЗ §3 требует его «крупно», и в потоке текста он
   теряется). */
.tvz-crumbs {
  display: flex;
  gap: var(--gap);
  align-items: center;
}

/* Строка фильтров на время карточки прячется. Атрибут `hidden` сам по себе
   не справляется: у строки задан `display:flex`, и он сильнее правила
   браузера для скрытых элементов. */
.tvz-page__bar[hidden] {
  display: none;
}

.tvz-head {
  display: flex;
  gap: var(--gap);
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
}

.tvz-head__main {
  min-width: 0;
}

.tvz-head__name {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.tvz-head__sub {
  color: var(--c-mut);
  margin-top: 2px;
}

.tvz-head__tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 8px;
}

/* ОДИН вердикт шапки (макет 1c): обёртка нужна проверке «вердикт ровно
   один», бейдж внутри остаётся обычным элементом ряда тегов. */
.tvz-head__verdict {
  display: contents;
}

/* Владелец отношений — «крупно» из ТЗ §3: не бейдж и не строка таблицы. */
.tvz-owner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 14px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad-lg);
  background: var(--c-ac-tint);
}

.tvz-owner__l {
  color: var(--c-mut);
  font-size: var(--fz-micro);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.tvz-owner__v {
  color: var(--c-ac-d);
  font-size: 17px;
  font-weight: 700;
}

/* Ряд действий: «позвонить», «написать», «скопировать» — каждое в один тап,
   на телефоне переносится, а не режется. */
.tvz-acts {
  display: flex;
  gap: var(--gap);
  flex-wrap: wrap;
  margin-top: var(--gap);
  /* Сам ряд обязан сжиматься наравне со своим содержимым. Внутри всё для
     этого уже есть: `.tvz-act`, `.tvz-copy` и `.tvz-copy__v` несут
     `min-width:0`, и реквизит в кнопке обрезается многоточием. Но у
     флекс-элемента свой минимум — по максимальной ширине содержимого, и РЯД,
     стоя флекс-элементом в чужой строке, держал эту ширину силой: дети
     сжаться готовы, а места им никто не давал.

     Ловилось на маршруте «идти через партнёра» в плашке запрета: там ряд
     стоит в `.tvz-route__r` рядом с именем партнёра, и за столом (точный
     указатель, D-46) реквизит печатается ВНУТРИ кнопки — колонка уезжала
     вбок на 83 px при ширине 375. Пальцем не воспроизводилось: там в кнопке
     короткое «Скопировать», а номер уносит соседняя ссылка звонка.

     Правится в основании, а не по месту: `.tvz-find__row .tvz-acts` уже
     чинил ровно это у себя в строке выдачи — та же беда и тот же
     `min-width:0`, просто пойманные одним экраном раньше. */
  min-width: 0;
}

.tvz-act {
  display: inline-flex;
  gap: 2px;
  align-items: center;
  /* Реквизит внутри кнопки бывает длинным (почта в две трети строки), а
     `min-width:auto` у флекс-элемента не даёт ему сжаться — пара уезжает
     за край карточки. Сжиматься разрешено; обрезает многоточием кнопка. */
  min-width: 0;
  max-width: 100%;
}

/* Метка канала на кнопке связи: чем телефон отличается от почты и мессенджера,
   видно до чтения самого реквизита.

   Владелец 31.07: «раз письма, два телефон, два телефон… и все они одного
   цвета, ориентироваться, за что отвечают, трудно». За столом ряд правда
   собирается из одинаковых кнопок «Скопировать» — позвонить с мыши нечем,
   и глагола на кнопке нет.

   Различают ДВА признака сразу, а не один: слово («Телефон», «Второй телефон»,
   «Почта», «MAX») и цвет семьи — звонок, письмо, переписка. Цветом одним
   шесть каналов не развести: непроверочных оттенков в палитре ADR-0002 ровно
   три, остальные заняты смыслом «ок / внимание / отказ», и телефон в зелёном
   читался бы как вердикт о записи. Своих цветов нет — только токены. */
.tvz-act--ch {
  /* Метка встаёт первой строкой, когда кнопка с реквизитом занимает всю
     ширину: на 390 px «Телефон» и длинный номер в одну строку не помещаются,
     а резать номер нельзя — по нему и попадают. */
  flex-wrap: wrap;
  gap: 6px;
}

.tvz-act__ch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  padding: 2px 8px;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-mut);
  font-size: var(--fz-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}

.tvz-act--call .tvz-act__ch {
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
}

.tvz-act--mail .tvz-act__ch {
  background: var(--c-cyanbg);
  color: var(--c-cyan);
}

.tvz-act--chat .tvz-act__ch {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

/* Копирование реквизита — главное действие там, где позвонить нельзя (D-46).
   Значок без подписи главным действием быть не может: он не называет себя и
   не даёт по себе попасть. Здесь у кнопки сам реквизит слева, подпись
   действия справа — и кликается она целиком, а не иконкой.
   Только геометрия; цвета и высота — токены дизайн-системы. */
.tvz-copy {
  gap: 10px;
  max-width: 100%;
  min-width: 0;
}

.tvz-copy__v {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Подпись действия — приглушённее реквизита, но не до вида отключённой
   кнопки: это главное действие десктопа, а не пояснение к нему. */
.tvz-copy__a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  color: var(--c-tx-2);
  font-size: var(--fz-sm);
}

/* Отклик на месте действия: копирование ничего на экране не меняет, и без
   ответа непонятно, сработало ли. Цвет — семантический токен «получилось». */
.tvz-copy.is-done .tvz-copy__a,
.tvz-copy.is-done .tvz-copy__a .tvz-icon {
  color: var(--c-ok);
}

/* Копирование одной иконкой (`iconCopyButton`, people.js) — реквизит уже
   стоит текстом рядом, подписывать действие второй раз нечем (карточка
   клиента, README «Иконка копирования»). */
.tvz-icon-copy {
  flex: none;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: none;
  border-radius: 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-mut);
  cursor: pointer;
}
.tvz-icon-copy:hover {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}
.tvz-icon-copy.is-done {
  background: var(--c-okbg);
  color: var(--c-ok-d);
}
.tvz-icon-copy.is-disabled {
  color: var(--c-bd);
  cursor: not-allowed;
  background: none;
}

/* Запрет прямого общения (поправка №2): читается раньше телефона, поэтому
   стоит отдельной плашкой над карточкой, а не бейджем в ряду пометок. */
.tvz-warnbox {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--c-err-bd);
  border-radius: var(--rad-lg);
  background: var(--c-errbg);
  color: var(--c-tx);
}

.tvz-warnbox__i {
  color: var(--c-err);
  display: flex;
  flex: none;
}

.tvz-warnbox__b {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

/* НАХОДКА — не предупреждение. Тот же короб, что у `warnbox`, но акцентным
   тоном: справочник нашёл организацию по ИНН, и это хорошая новость, а
   красный фон читается как «поймали ошибку» (слово владельца 10.08:
   «почему красный фон? как будто словили баг»). Тон тот же, каким находку
   уже рисует визард (`.tvz-cw__found`) — двух правд о находке в продукте
   быть не должно.

   Тревожное внутри находки остаётся тревожным: статус «организация
   ликвидирована» печатается `<b>` и красным (`__warn` ниже) — цвет несёт
   ровно то, что и должен, а не окрашивает всю плашку заодно. */
.tvz-findbox {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad-lg);
  background: var(--c-ac-tint);
  color: var(--c-tx);
}
.tvz-findbox__i { color: var(--c-ac); display: flex; flex: none; }
.tvz-findbox__b { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.tvz-findbox__warn { color: var(--c-err); font-weight: 700; }

/* Маршрут «идти через партнёра»: запрет без адреса, куда идти вместо, работу
   не останавливает — он уводит её в обход системы. Кнопки здесь рабочие,
   это единственные рабочие кнопки связи на закрытом клиенте. */
.tvz-route {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
  padding: 10px 12px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
}

.tvz-route__t {
  font-weight: 700;
}

.tvz-route__r {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
}

.tvz-route__n {
  font-weight: 600;
}

.tvz-route__p {
  color: var(--c-tx-2);
  font-size: var(--fz-sm);
}

.tvz-route .tvz-acts {
  margin-top: 0;
  margin-left: auto;
}

/* «Связь только через партнёра» — там, где стоял бы телефон. Не бейдж:
   бейджи в строке заняты ролью, уровнем и доверием, а эта пометка про то,
   чего делать НЕЛЬЗЯ, и обязана читаться раньше их всех. */
.tvz-blocked {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border: 1px solid var(--c-err-bd);
  border-radius: var(--rad-pill);
  background: var(--c-errbg);
  color: var(--c-err);
  font-size: var(--fz-micro);
  font-weight: 600;
}

.tvz-blocked--wide {
  padding: 8px 12px;
  border-radius: var(--rad);
  font-size: var(--fz-sm);
}

/* Пустое важное поле, названное вслух: молчание не отличить от «совпадает
   с фактическим», и оригинал уезжает в никуда. */
.tvz-missing {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--c-warn);
  font-weight: 600;
}

/* Служебная учётка вместо человека: «Система — это никто, спросить не с кого». */
.tvz-nohuman {
  color: var(--c-tx-2);
  font-style: italic;
}

/* Единственный вердикт о доверии: плашка и пояснение к ней в одной строке. */
.tvz-verdict {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

/* Почему он первый — строка под ответом (П-8а, B-64). Без неё выбор
   неотличим от угадывания: система показала одного, а почему этого —
   неизвестно. Тон приглушённый: это объяснение, а не предупреждение. */
.tvz-why {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 0;
  color: var(--c-tx-2);
  font-size: var(--fz-sm);
}

/* «Ещё варианты» внутри карточки ответа: свёрнутая строка без своей рамки —
   она часть ответа, а не вторая карточка рядом с ним. */
.tvz-answer-more {
  margin-top: 8px;
  padding: 0;
  border-top: 1px solid var(--c-bd);
}

.tvz-answer-more > h3 {
  margin: 8px 0 0;
  font-size: var(--fz-sm);
}

.tvz-answer-more.is-open > h3 {
  margin-bottom: 8px;
}

/* «Ещё варианты» открываются порциями, и рядом стоит счёт показанного. На
   узком экране строка не влезает втроём — заголовок переносит её целиком,
   а само число не рвётся по слову: «показано 5 из / 20» читается обрывком. */
.tvz-answer-more > h3 {
  flex-wrap: wrap;
}

.tvz-answer-more > h3 .tvz-level__n {
  white-space: nowrap;
}

/* Оглавление ролей: «нужен акт сверки» — одно нажатие, а не прокрутка
   через 221 человека. */
.tvz-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.tvz-toc__note {
  margin-top: 8px;
  font-size: var(--fz-micro);
}

.tvz-groups {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Пустая выдача: сообщение, а не половина экрана под ним. Система рассчитана
   на страницу-заглушку целиком, здесь же это одна из карточек страницы. */
.tvz-page__body .tvz-placeholder {
  margin: 24px auto;
}

/* Свёрнутая карточка: служебное открывается по нажатию, а не занимает экран. */
.tvz-fold .tvz-fold__b {
  display: none;
}

.tvz-fold.is-open .tvz-fold__b {
  display: block;
}

/* Свёрнутая — это СТРОКА, а не пустая секция. Блок дополнений на внесении
   занимал целую карточку ради одной кнопки «Показать»; то же было со
   «Служебным» на карточке клиента. Карточка остаётся карточкой — исчезает
   пустота внутри. */
.tvz-fold:not(.is-open) {
  padding: 5px 12px;
}

.tvz-fold:not(.is-open) > h3 {
  margin: 0;
}

/* Кнопка в заголовке карточки (например «Заметка» у хроники). */
.tvz-card h3:has(.tvz-card__act) {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-card__act {
  margin-left: auto;
}

/* Значок события хроники: система рисует круг, цвет берём тоном акцента. */
.tvz-ev-ico {
  background: var(--c-chip);
  color: var(--c-mut);
}

/* Лента правок. Не таблица: на телефоне три колонки не помещаются, а
   история обязана читаться и там. */
.tvz-hlist {
  display: flex;
  flex-direction: column;
}

.tvz-hrow {
  display: grid;
  grid-template-columns: 128px 1fr 180px;
  gap: var(--gap);
  padding: 8px 0;
  border-bottom: 1px solid var(--c-bd2);
  align-items: baseline;
}

.tvz-hrow:last-child {
  border-bottom: 0;
}

.tvz-hrow__t {
  color: var(--c-tx-4);
  font-family: var(--font-mono);
  font-size: var(--fz-micro);
}

.tvz-hrow__w s {
  color: var(--c-tx-4);
}

.tvz-hrow__a {
  color: var(--c-mut);
  font-size: var(--fz-sm);
  text-align: right;
}

@media (max-width: 900px) {
  .tvz-hrow {
    grid-template-columns: 1fr;
    gap: 2px;
  }

  .tvz-hrow__a {
    text-align: left;
  }

  .tvz-owner {
    width: 100%;
  }

  .tvz-acts .tvz-act,
  .tvz-acts .tvz-btn {
    flex: 1 1 auto;
  }
}

@media (max-width: 900px) {
  .tvz-hit {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }

  .tvz-hit__side {
    justify-content: flex-start;
  }

  .tvz-search--narrow {
    max-width: none;
  }
}

@media (max-width: 900px) {
  .tvz-app {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
    height: 100dvh;
  }

  /* Мобильный режим шелла (B-113, аудит 5e). Раньше сайдбар рисовался
     БЛОКОМ СВЕРХУ: бренд, меню в 22vh и подвал с профилем съедали треть
     экрана 390×844 — «первый экран телефона отдан делу, а не меню»
     (симуляция 001-А) оставалось словами. Теперь сайдбар — узкая полоса:
     бренд и профиль в одну строку, разделы — горизонтальная лента под ней.
     Разделы остаются на экране и в один тап (лента прокручивается вбок,
     как этапы на канбане) — прячется только высота. */
  .tvz-side {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    margin: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .tvz-side__brand {
    grid-row: 1;
    grid-column: 1;
    padding: 6px 12px;
    font-size: 15px;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
  }

  .tvz-side__foot {
    grid-row: 1;
    grid-column: 2;
    min-width: 0;
  }

  .tvz-nav {
    grid-row: 2;
    grid-column: 1 / -1;
    display: flex;
    gap: 4px;
    max-height: none;
    padding: 0 8px 8px;
    overflow-x: auto;
    overflow-y: hidden;
  }

  .tvz-nav__group {
    margin-top: 0;
  }

  .tvz-nav__group:has(.tvz-nav__empty) {
    display: none;
  }

  /* Заголовки групп в горизонтальной ленте не живут: слово «разделы» стоило
     бы места, которое здесь принадлежит самим разделам. */
  .tvz-nav__gt {
    display: none;
  }

  .tvz-nav__items {
    flex-direction: row;
    gap: 4px;
  }

  .tvz-nav__item {
    flex: none;
    height: 34px;
    padding: 0 10px;
  }

  .tvz-top {
    padding: 6px 12px;
  }

  .tvz-content {
    padding: 12px;
  }

  /* Контролы фильтров на узком экране тянутся на всю ширину, а не режутся.
     Главное поле — во всю строку, второстепенные фильтры парами: пять
     контролов столбиком съедали первый экран целиком, а список базы обязан
     начинаться строками, а не шапкой. */
  .tvz-page__bar,
  .tvz-page__filters {
    width: 100%;
  }

  .tvz-page__filters {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--gap);
  }

  .tvz-page__filters > *:first-child {
    grid-column: 1 / -1;
  }

  .tvz-page__filters .tvz-search,
  .tvz-page__filters > * {
    min-width: 0;
    width: 100%;
  }

  /* Подсказка «что понимает поиск» на телефоне уступает место строкам. */
  .tvz-hint {
    display: none;
  }

  .tvz-page__tools {
    margin-left: 0;
  }

  /* Пары «ключ — значение» на телефоне читаются в две строки, а не в обрез:
     мера ширины подписи с десктопа здесь только мешает. */
  .tvz-kv {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }

  .tvz-kv > span {
    min-width: 0;
  }

  /* Телефонные размеры формы внесения живут НЕ здесь, а в медиа-блоке ПОСЛЕ
     базовых правил `.tvz-entry` (ниже по файлу): при равной специфичности
     базовые правила перебивали бы этот блок, и «поля 46px» существовали бы
     только в файле — ровно так умерли прежние 44px (аудит 5e, B-113; тот же
     класс дефекта, что у каркаса — см. комментарий у @media (min-width)). */

  /* Таблицы админки шире экрана телефона: прокручиваем их, а не режем.
     Прокрутка живёт внутри карточки — страница по горизонтали не едет.
     `flex: none` обязателен: карточка с прокруткой перестаёт быть «не ниже
     своего содержимого» и в колонке-флексе схлопывается до одной строки. */
  .tvz-card:has(> .tvz-table) {
    overflow-x: auto;
    flex: none;
  }

  .tvz-table {
    min-width: 640px;
  }

  /* Шапка на телефоне: заголовок ужимается первым, имя обрезается вторым,
     а кнопки темы и выхода остаются на экране всегда — иначе выйти и
     переключить тему с телефона нельзя. Роли из чипа уходят: место дороже,
     а роли видны в админке. */
  .tvz-top__title {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }

  /* Кнопки правого блока НЕ сжимаются — сжимаются заголовок и поиск.
     Прежнее «разрешаем сжатие» плющило сами кнопки: колокол ужимался до
     18px и был недостижим пальцем (находка волны П-27а). Заголовок при
     этом не сжимался вовсе — в базе у него flex:none, и стоявшие здесь
     ellipsis-правила были мертвы. */
  .tvz-top__right {
    flex: none;
  }

  .tvz-top__title {
    flex: 0 1 auto;
  }

  .tvz-top__find {
    min-width: 0;
  }

  /* Прежняя заплатка «пустой слот не растягивает шапку» жила здесь и лечила
     только телефон. С П-54 та же беда снята для всех ширин сразу
     (`.tvz-top__slot:empty { display: none }` в блоке «шапка» ниже). */

  /* Имя и кнопка выхода — в одну строку: перенос ломает шапку на три этажа. */
  .tvz-top__actions {
    flex-wrap: nowrap;
    gap: 2px;
    min-width: 0;
  }

  .tvz-user__role {
    display: none;
  }

  .tvz-user {
    padding: 4px 4px 4px 2px;
    min-width: 0;
  }

  .tvz-user__name {
    display: block;
    max-width: 34vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/* --- Читаемость тёмной темы (симуляция 001-А) ------------------------------
   «Включила бы — вечером свет режет. Только серое на тёмном выцвело почти
   в невидимое, подсветите чуть. Крупное читается хорошо.»

   Диагноз точный: страдает не палитра, а мелкий текст, набранный самым
   приглушённым токеном. На светлом фоне --c-tx-4 читается, на тёмном —
   почти сливается с карточкой, и вместе с ним пропадают ровно те вещи,
   по которым принимают решение: подписи под именем, числа в счётчиках,
   даты в ленте правок.

   Правится ВЫБОРОМ токена, а не значением: тот же текст берёт токен на
   ступень контрастнее (--c-tx-2 вместо --c-tx-4, --c-tx-2 вместо --c-mut).
   Своих цветов здесь нет и быть не может — значения токенов живут
   в апстриме (ADR-0002). */
html[data-theme="dark"] .tvz-hit__why,
html[data-theme="dark"] .tvz-kind,
html[data-theme="dark"] .tvz-hit__sub,
html[data-theme="dark"] .tvz-level__n,
html[data-theme="dark"] .tvz-hrow__t,
html[data-theme="dark"] .tvz-hrow__w s,
html[data-theme="dark"] .tvz-toc__note,
html[data-theme="dark"] .tvz-owner__l {
  color: var(--c-tx-2);
}

/* Подписи полей и приглушённые пояснения: их читают как часть данных,
   а не как оформление. */
html[data-theme="dark"] .tvz-kv > span,
html[data-theme="dark"] .tvz-mut,
html[data-theme="dark"] .tvz-dash-ev__who {
  color: var(--c-tx-2);
}

/* Плашки счётчиков: «сотрудников на площадке: 0» и «отвечают: 3» — числа,
   а не подпись. Нейтральный бейдж на тёмном терял и текст, и фон. */
html[data-theme="dark"] .tvz-badge--mut {
  background: var(--c-chip);
  color: var(--c-tx);
}

/* Служебная учётка и пустое поле остаются заметными: обе пометки говорят
   «здесь чего-то нет», и выцветать им нельзя тем более. */
html[data-theme="dark"] .tvz-nohuman {
  color: var(--c-tx-2);
}

/* --- Внесение, уведомления, «Мой участок» (П-5) ----------------------------

   Три экрана правил команды. Геометрия своя, цвета — только токены: значения
   палитры живут в апстриме (ADR-0002). */

/* Форма внесения. Мобильный — главный режим: Маргарита 90% времени в полях,
   и проверялась форма в первую очередь на телефоне. Поля идут столбцом,
   крупные: попасть пальцем в узкое поле «на ходу, в каске» нельзя.

   Ширина формы — узкая колонка системы (`--crm-col-form`): на мониторе поле
   во всю ширину не «удобнее», а хуже — набранное имя теряется в его левом
   углу. Шаг между полями — шаг сетки контролов. */
/* --- Экран внесения 8a: одна разметка с модалкой (хендофф 8a, П-95) --------

   Разметку экрана, окна 6d и телефонной шторки собирает ОДИН код
   (`buildEntryCard`, entry.js) — карточной ветки (`.tvz-cc-*`) и флага
   `packed` больше нет. Различает контейнеры только CSS:

   · окно  — `.tvz-modal--pack …` (блок форм-фактора ниже по файлу, поля 36);
   · экран — `.tvz-entry-page …` (этот блок, поля 40 и липкий подвал);
   · шторка — общая база `.tvz-entry …` без надстроек, одной колонкой.

   Базовые правила стоят на `.tvz-entry` и НАМЕРЕННО не спорят с окном:
   всё, что окно задаёт по-своему (высоты, отступы), живёт здесь либо
   в общих значениях, либо под `.tvz-entry-page`, куда `.tvz-modal--pack`
   не достаёт по определению.

   Экран живёт в одну высоту без прокрутки страницы — тем же приёмом, что
   карточка клиента (`.tvz-ccard-page`): `.tvz-content` перестаёт скроллиться,
   пока внутри стоит `.tvz-entry-page`, а прокручивается тело формы. Иначе
   липкий подвал ловил бы прокрутку страницы и уезжал вместе с ней. */
.tvz-content:has(.tvz-entry-page) {
  overflow: hidden;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.tvz-content:has(.tvz-entry-page) > * {
  max-width: none;
}

.tvz-page:has(.tvz-entry-page),
.tvz-page__body:has(.tvz-entry-page) {
  flex: 1;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  gap: 0;
}

.tvz-entry-page {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.tvz-entry-page__body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 18px 20px;
}

/* Подвал «Отмена · Сохранить» — как в окнах: прижат вправо, приписка о
   последствии слева. Кнопка активна всегда — что не заполнено, говорит
   отказ у поля, а погашенная кнопка без объяснения читается «сломалось». */
.tvz-entry-page__foot {
  flex: none;
  height: 64px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  /* Этаж НАД телом — границей и поверхностью, тем же приёмом, что подвал
     окна форм-фактора (`.tvz-modal--pack .tvz-modal__foot`). Макет 8a рисует
     здесь ещё и мягкую тень вверх, но своего цвета подвал завести не вправе:
     цвета берутся только из токенов, а тени в системе светят вниз (`--e1`).
     Граница отвечает на тот же вопрос — где кончается форма. */
  border-top: 1px solid var(--c-bd);
  background: var(--c-surface);
}

.tvz-entry-page__after {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-entry-page__acts {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

/* Приписка шапки экрана («обязательных полей три…») — в общем слоте
   страницы, рядом с названием, а не отдельной полосой над формой: полосу
   ради одной строки владелец уже снимал однажды (П-41). */
.tvz-top__slot:has(.tvz-entry__topnote) {
  margin-left: 0;
  justify-content: flex-start;
  flex: 1;
}

.tvz-entry__topnote {
  font-size: 12.5px;
  color: var(--c-tx-4);
}

/* --- Колонки формы --------------------------------------------------------

   База — одна колонка: так форма ложится в шторку телефона и в узкое окно,
   и никакого «если телефон» в коде для этого не нужно. Две колонки даёт
   контейнер, у которого на них есть ширина. */
.tvz-entry__cols {
  display: grid;
  gap: 14px;
  align-items: start;
}

.tvz-entry__col {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

/* Левая колонка фиксированной ширины: там короткие поля, растягивать их не
   нужно. Правая тянется — названия ролей многословные, и на 1fr/1fr самая
   длинная группа переносится некрасиво (замер П-74). */
.tvz-entry-page .tvz-entry__cols {
  grid-template-columns: 520px minmax(0, 1fr);
}

.tvz-entry-page .tvz-entry__col {
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  box-shadow: var(--e1);
  padding: 16px 18px 18px;
}

/* Узкое окно: колонки складываются в одну, карточки остаются карточками. */
@media (max-width: 900px) {
  .tvz-entry-page .tvz-entry__cols {
    grid-template-columns: 1fr;
  }
}

.tvz-entry__coltitle {
  font-size: 14px;
  font-weight: 700;
  display: none;
}

/* Заголовок колонки нужен ровно там, где над формой нет своей шапки с
   подзаголовком, — на экране. В окне и в шторке то же самое уже сказано
   их собственной шапкой. */
.tvz-entry-page .tvz-entry__coltitle {
  display: block;
}

/* --- Поля -----------------------------------------------------------------

   Метка 12/600, необязательность — вторым словом 11px у самой метки (правило
   текста: «можно пусто» пишется У МЕТКИ, а не абзацем под полем). */
.tvz-entry .tvz-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.tvz-entry .tvz-field__lbl {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.tvz-entry .tvz-field__name {
  font-size: var(--fz-sm);
  font-weight: 600;
  color: var(--c-tx-2);
}

.tvz-entry .tvz-field__opt {
  font-size: var(--fz-micro);
  font-weight: 400;
  color: var(--c-tx-4);
}

/* Ход в строке метки («+ Новый клиент») — справа, ссылкой: кнопка НАД комбо
   накрывалась его же выпадающим списком (класс B-96). */
.tvz-entry .tvz-field__lbl .tvz-btn--link {
  margin-left: auto;
  height: 24px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--rad-sm);
  background: none;
  color: var(--c-ac);
  font-size: 11.5px;
  font-weight: 600;
}

.tvz-entry .tvz-field__lbl .tvz-btn--link:hover {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-entry .tvz-field__lbl .tvz-btn--link .tvz-icon {
  width: 13px;
  height: 13px;
}

/* Поле со значком слева (канал связи): значок стоит В поле, а не рядом, —
   иначе он съедает ширину у самого поля. */
.tvz-entry .tvz-field__ico {
  position: relative;
  display: block;
}

.tvz-entry .tvz-field__ico > .tvz-icon {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--c-tx-4);
  pointer-events: none;
}

.tvz-entry .tvz-field__ico > input {
  padding-left: 34px;
}

/* Экран: поля 40 (мера хендоффа 8a) — и комбобокс клиента, и обычные поля,
   и памятка. В окне те же поля 36; ни одно правило отсюда туда не достаёт. */
.tvz-entry-page .tvz-entry__col input,
.tvz-entry-page .tvz-entry__col .tvz-combo__in {
  width: 100%;
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  border-radius: var(--rad);
}

.tvz-entry-page .tvz-entry__col .tvz-combo {
  width: 100%;
}

/* Имя и клиент — 600: это то, ради чего экран открыт. */
.tvz-entry__name,
.tvz-entry .tvz-combo__in {
  font-weight: 600;
}

/* Якорь отказа по имени — своей раскладки не несёт (`.tvz-entry__dup` уже
   даёт отступ), класс только для точного места в разметке: за него держатся
   проверки формы. */
.tvz-entry__name-refusal {
  order: initial;
}

.tvz-entry__org {
  min-width: 0;
}

/* Название новой организации подменяет собой комбобокс клиента («+ Новый
   клиент»): своей рамки не заводит, ширину берёт у соседей по колонке. */
.tvz-entry__neworg {
  width: 100%;
}

/* Должность — обычное поле, а не заголовок: 600 в этой форме носят только
   клиент и имя, ради которых её и открыли. До П-95 должность была мелкой
   строкой в мете «как на карточке» — и без метки было не понять, что это
   она (первая находка хендоффа 8a). */
.tvz-entry__position {
  font-weight: 400;
}

/* --- Канал связи ----------------------------------------------------------

   Значение — мономиром (номер читается цифра к цифре), под полем строка
   «распознали: <бейдж>» и «+ Ещё канал» у правого края. */
.tvz-entry__ch-input.mono {
  font-family: var(--font-mono);
}

.tvz-entry__ch-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-entry__ch-hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fz-sm);
}

.tvz-entry__ch-hint:empty {
  display: none;
}

.tvz-entry__ch-said {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* «+ Ещё канал» прижат вправо, но только когда слева уже что-то сказано:
   у пустой строки он остаётся на месте, а не прыгает. */
.tvz-entry__ch-row .tvz-entry__addch {
  margin-left: auto;
}

/* Граница обязательного и остального — линией, а не словами. */
.tvz-entry__sep {
  height: 1px;
  background: var(--c-bd2);
  margin: 2px 0;
}

/* Выбор роли группами (D-52). Шестнадцать плашек подряд — «та же стена,
   только разложенная»: держат её заголовки групп, поэтому раскрыта одна,
   остальные свёрнуты строками. Своих цветов здесь нет — только токены. */
.tvz-roles {
  display: block;
  margin-top: var(--gap);
}

.tvz-roles__sum {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 6px 0 8px;
  min-height: var(--ctl-h-sm);
  font-size: var(--fz-sm);
}

.tvz-roles__gs {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tvz-roles__g {
  padding: 5px 10px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-bg);
}

.tvz-roles__g > h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: var(--fz-sm);
}

.tvz-roles__g.is-open > h3 {
  margin-bottom: 8px;
}

.tvz-roles__cs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding-bottom: 6px;
}

/* Плашка роли — цель для пальца: «я на ходу, в каске». */
.tvz-roles__c {
  min-height: var(--ctl-h);
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: var(--fz-sm);
  cursor: pointer;
}

.tvz-roles__c:hover {
  border-color: var(--c-ac);
}

.tvz-roles__c.is-on {
  border-color: var(--c-ac);
  background: var(--c-chip);
  color: var(--c-ac);
  font-weight: 600;
}

/* «Пока не знаю» нажата: ответ виден так же, как выбранная роль. */
.tvz-roles .tvz-btn.is-on {
  border-color: var(--c-warn);
  color: var(--c-warn);
}

.tvz-entry__hint {
  display: block;
  margin-top: 5px;
  font-size: var(--fz-sm);
  color: var(--c-tx-2);
}

.tvz-entry__hint:empty {
  display: none;
}

.tvz-entry__row {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

/* Площадки при внесении (B-79): необязательно, появляется только когда
   у выбранного клиента есть площадки. Тело — готовый компонент tagfilter
   (core/ui.js), здесь только отступ поля и место под подсказку. */
.tvz-entry__sites {
  display: block;
}

.tvz-entry__sites-body {
  margin-top: 4px;
}

/* Предложение связать вместо второй карточки — сразу под полями, а не после
   нажатия «Сохранить»: отказ по факту сделанной работы люди обходят. */
.tvz-entry__dup:not(:empty) {
  margin-top: var(--gap);
}

/* Поле, получившее отказ сервера, подсвечено у самого входа (B-114): плашка
   отказа объясняет словами, кромка показывает, КОТОРОЕ поле не ответило.
   Токен ошибки системный (--c-err), своего цвета здесь нет. */
.tvz-field.is-refused .tvz-combo__in,
.tvz-field.is-refused > input {
  border-color: var(--c-err);
}

/* --- Памятка, отметка проверки, площадка ----------------------------------

   Памятка низкая и не тянется: растянутая, она съедала бы колонку, а две
   строки — ровно то, ради чего поле заведено («звонить после трёх»). */
.tvz-entry__memo {
  height: 58px;
  min-height: 58px;
  resize: none;
  font-family: var(--font-ui);
}

.tvz-entry-page .tvz-entry__col textarea {
  width: 100%;
}

.tvz-entry__check {
  align-items: flex-start;
  gap: 8px;
  font-size: var(--fz-sm);
  color: var(--c-tx-2);
  line-height: 1.35;
}

/* Экран: поля 40, поиск роли 36 (мера хендоффа 8a). Своей ширины поиску
   не нужно — он занимает колонку целиком (правка владельца 05.08). */
.tvz-entry-page .tvz-entry__col .tvz-search {
  height: 36px;
  min-height: 36px;
  min-width: 0;
}

.tvz-entry-page .tvz-entry__sitesbtn {
  height: var(--ctl-h);
}

/* Поиск роли: лупа ОДНА — та, что дизайн-система рисует фоном `.tvz-search`
   (правка владельца 05.08, «две лупы в инпуте»); своей второй иконки поверх
   неё форма не ставит. Ступень специфичности здесь не украшение: сборщик
   роли — сам `.tvz-field`, и `.tvz-modal--pack .tvz-field input` бьёт
   `.tvz-search` элементом в селекторе — плейсхолдер уезжал под лупу. */
.tvz-entry .tvz-entry__rolefind .tvz-search {
  width: 100%;
  padding-left: 34px;
  background-position: left 11px center;
}

/* Тёмная тема: палитра групп фиксированно светлая (см. `roleGroupTintStyle`),
   и на тёмной поверхности пилюля роли получала тёмный текст группы на тёмном
   фоне — название читалось только выбранное. Невыбранная пилюля берёт
   обычные тёмные токены, выбранная остаётся тонированной: цвет группы
   в тёмной теме несут шапка доски и её тело, а не каждая пилюля. */
html[data-theme="dark"] .tvz-entry__roles--board .tvz-roles__c {
  background: var(--c-surface);
  border-color: var(--c-line-strong);
  color: var(--c-tx);
}

html[data-theme="dark"] .tvz-entry__roles--board .tvz-roles__c.is-on {
  background: var(--tint-hd, var(--c-chip));
  border-color: var(--tint-tx, var(--c-ac));
  color: var(--tint-tx, var(--c-tx));
}

/* Счётчик ролей в шапке доски — у правого края и цветом группы, мономиром
   (макет 8a). Общий `--c-mut` на тонированной шапке в тёмной теме давал
   светло-серое по светло-синему: число переставало читаться, а число —
   это данные, по которым решают, лезть ли в группу. */
.tvz-entry__roles--board .tvz-roles__g > h3 .tvz-mut {
  margin-left: auto;
  color: inherit;
  font-family: var(--font-mono);
  font-size: var(--fz-micro);
  font-weight: 700;
}

/* Пустая коробка отказа не ест шаг колонки: до первого отказа её на экране
   нет вовсе, а место она занимала наравне с полем. */
.tvz-entry .tvz-entry__dup:empty {
  display: none;
}

/* --- Телефон: та же форма пальцем (B-113, хендофф 5e) ----------------------

   Блок стоит ПОСЛЕ базовых правил `.tvz-entry` сознательно: при равной
   специфичности побеждает то, что ниже по файлу, и медиа-блок «телефон»
   в начале файла эти правила не перебил бы. Прежние 44px так и умерли:
   правило было написано, но не действовало ни одного дня (аудит 5e).

   Размеры — мера хендоффа, а не вкус: база 14px, поля 46px, роли 44px,
   кнопки подвала ≥50px. В поле 40px палец «на ходу, в каске» не попадает,
   а 13px мелкого текста на вытянутой руке не читаются. */
@media (max-width: 900px) {
  .tvz-entry {
    font-size: 14px;
  }

  .tvz-entry .tvz-field > input,
  .tvz-entry .tvz-field > textarea,
  .tvz-entry .tvz-field__ico > input,
  .tvz-entry .tvz-combo,
  .tvz-entry .tvz-combo__in,
  .tvz-entry .tvz-entry__memo,
  .tvz-entry .tvz-entry__name {
    min-height: 46px;
    height: auto;
    font-size: 14px;
  }

  /* Плашка роли — цель для пальца, и доска ролей не имеет права сжать её
     до 24px «как в окне»: правило доски стоит ниже по файлу, поэтому здесь
     ему нужна лишняя ступень специфичности (`.tvz-entry` вокруг), иначе оно
     снова окажется написанным и не действующим. */
  .tvz-entry .tvz-entry__roles--board .tvz-roles__c {
    min-height: 44px;
    height: auto;
    padding: 0 14px;
    font-size: 13px;
  }

  /* Подвал экрана: приписка уступает место кнопкам — подвал в два этажа
     съедал бы строку формы (макет 5e: в подвале только кнопки). */
  .tvz-entry-page__body {
    padding: 12px 14px;
  }

  .tvz-entry-page__foot {
    height: auto;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  }

  .tvz-entry-page__after {
    display: none;
  }

  .tvz-entry-page__acts {
    width: 100%;
    gap: 10px;
  }

  .tvz-entry-page__acts .tvz-btn {
    flex: 1;
    min-height: 50px;
  }
}

/* --- Узкая шапка телефонного экрана (5e, эталонное расхождение №1) ---------

   Экран, объявивший `phone` в pageLayout, на телефоне получает шапку 44px
   «← заголовок» ВМЕСТО шелл-хрома: бренд, лента разделов и топбар съедали
   треть экрана 390×844 над формой внесения, заголовок резался до «Внест…»,
   а кнопки «Назад» не было вовсе (макет 5e, «Телефон — главный режим»).

   Узкий режим — свойство ЭКРАНА, а не имени раздела: здесь нет ни одного
   селектора вида «если открыто внесение». Шапка лежит в разметке самого
   экрана, шелл-хром прячет `:has(.tvz-phead)` — другой экран стёр host,
   и хром вернулся сам, никакого состояния и снятия классов.

   База (`display:none`) стоит НАРОЧНО до медиа-блока: на широком экране
   шапки нет, там заголовок живёт в топбаре. Порядок с медиа-блоком здесь
   безопасен — включает шапку сам медиа-блок, а не база; но правило
   «телефонные правила стоят ПОСЛЕ базовых» (аудит 5e, B-113) соблюдено. */

.tvz-phead {
  display: none;
}

@media (max-width: 900px) {
  /* Бренд-хедер с меню и топбар на экране с узкой шапкой не рисуются:
     «первый экран телефона отдан делу, а не меню» (симуляция 001-А). */
  .tvz-app:has(.tvz-phead) .tvz-side,
  .tvz-app:has(.tvz-phead) .tvz-top {
    display: none;
  }

  /* Шапка начинается У КРОМКИ экрана, поэтому верхнее поле контента снимает
     сам экран с узкой шапкой. Снять его отрицательным полем шапки нельзя:
     порог sticky (`top: 0`) стоит у КРАЯ ПОЛЯ прокрутки, и прижатая полем
     к нулю шапка тут же выталкивалась бы порогом обратно на 12px вниз —
     ловилось только живым замером, в файле оба правила выглядят верными. */
  .tvz-app:has(.tvz-phead) .tvz-content {
    padding-top: 0;
  }

  /* Ряд навигации из макета: стрелка 20px + заголовок 16px/700, разделён
     от тела `--c-bd`. Sticky: пока форму прокручивают, возврат и заголовок
     остаются под пальцем — как закреплённый подвал «Сохранить», только
     сверху. Отрицательные поля выводят шапку на края экрана: линия-граница
     обязана идти от кромки до кромки, а не висеть в полях контента. */
  .tvz-phead {
    display: flex;
    align-items: center;
    gap: 4px;
    min-height: 44px;
    margin: 0 -12px;
    padding: 0 10px 0 2px;
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--c-surface);
    border-bottom: 1px solid var(--c-bd);
  }

  /* Возврат — цель в палец (44px), как плашки ролей ниже по форме. */
  .tvz-phead__back {
    flex: none;
    width: 44px;
    height: 44px;
    color: var(--c-tx-2);
  }

  .tvz-phead__back .tvz-icon {
    width: 20px;
    height: 20px;
  }

  /* Заголовок — полный, а не «Внест…»: узкой шапке он и принадлежит. */
  .tvz-phead__t {
    font-size: 16px;
    font-weight: 700;
    color: var(--c-tx);
    min-width: 0;
    white-space: nowrap;
  }
}

/* Колокол с числом непрочитанного. Бейдж прижат к углу кнопки и виден при
   каждом входе — требование двух персон разом (US-R1). */
.tvz-bell {
  position: relative;
}

/* Счётчик непрочитанного — крупный (владелец: «сделай крупную цифру»):
   вендорные 9px читались как пылинка, а число про то, сколько тебя ждёт.
   Но прижат он ВНУТРЬ кнопки, а не вынесен за её угол: шапка ужата до
   40px, и трёх пикселей над кнопкой попросту нет — цифра выходила за
   кромку и выглядела срезанной («иконка не влазит», 04.08).

   Кружок с фоном акцента и белой обводкой — чтобы число отделялось от
   самого колокола, раз оно теперь лежит на нём. */
.tvz-bell .tvz-cnt-badge {
  position: absolute;
  top: 1px;
  right: 1px;
  font-size: 11px;
  line-height: 16px;
  min-width: 16px;
  padding: 0 4px;
  text-align: center;
  background: var(--c-ac);
  color: var(--c-surface);
  box-shadow: 0 0 0 2px var(--c-surface);
}

/* Центр уведомлений (П-74, хендофф 04.08, id 6f): строки во всю ширину тела
   вместо синих карточек. Признак непрочитанного — один: бейдж «новое» справа
   (ширина 64, чтобы дата в мономире не гуляла при его появлении/исчезновении).
   Заливка строки снята этой волной вместе с самими карточками — бейдж не
   спорит с ней за внимание, потому что она больше не существует.

   Тело модалки теряет свои базовые 18px 20px: иначе бордер-низ строки не
   доходил бы до бордера шапки/подвала (border рисуется по краю бокса,
   а не по краю padding). Правило целится узко — только когда тело держит
   именно `.tvz-notif` — семь остальных окон волны работают формой и их
   padding не трогает. */
.tvz-modal--pack .tvz-modal__body:has(> .tvz-notif) {
  padding: 0;
}

.tvz-notif {
  padding: 4px 0;
}

.tvz-notif__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 20px;
  border-bottom: 1px solid var(--c-bd2);
}

/* Точка-статус: срочность есть только у напоминаний о задаче (П-10) —
   err просрочена, warn на сегодня. Остальным видам касания (завели/
   поправили контакт, скопировали канал, заметка, приглашение на встречу)
   срочность не идёт — точка тише, тем же приёмом, что .tvz-day__dot.is-mut. */
.tvz-notif__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--c-tx-4);
}
.tvz-notif__dot.is-err {
  background: var(--c-err);
}
.tvz-notif__dot.is-warn {
  background: var(--c-warn);
}
/* Появилось новое, чего не было: контакт завели, на встречу позвали. */
.tvz-notif__dot.is-ac {
  background: var(--c-ac);
}
/* Коснулись существующего: поправили, скопировали канал, заметка. */
.tvz-notif__dot.is-mut {
  background: var(--c-mut);
}

/* Непрочитанное отличается ВСЕЙ строкой, а не только бейджем в конце ряда:
   по ленте бегут слева, и бейдж 64px справа глаз находит последним. */
.tvz-notif__row.is-unread {
  background: var(--c-sel);
}
.tvz-notif__row.is-unread .tvz-notif__title {
  font-weight: 700;
}

.tvz-notif__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.tvz-notif__title {
  font-size: 13px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-notif__meta {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-notif__date {
  flex: none;
  width: 130px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-notif__badge {
  flex: none;
  width: 64px;
  display: flex;
  justify-content: flex-end;
}

.tvz-notif__empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--c-mut);
  font-size: var(--fz-sm);
}

/* «И ещё N» (B-149) — тише самих строк: не запись, а счёт того, что не
   поместилось. Центрировано и без точки-статуса — строку с этим ничто не
   перепутает с уведомлением. */
.tvz-notif__more {
  padding: 10px 0 2px;
  text-align: center;
  color: var(--c-tx-4);
  font-size: 11.5px;
}

/* Плитки «Моего участка» переносятся на телефоне: четыре в ряд на десктопе,
   две — на узком экране. Отступ снизу не нужен: шаг между блоками страницы
   задаёт `.tvz-page__body`, и второй отступ поверх него — двойной воздух. */
.tvz-dash5__totals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--gap);
  margin: 0;
}

/* Тёмная тема: подписи плиток и подсказки формы — часть данных, а не
   оформление, и выцветать им нельзя (находка S-1a-13). */
html[data-theme="dark"] .tvz-entry__hint,
html[data-theme="dark"] .tvz-entry-page__after,
html[data-theme="dark"] .tvz-dash-tile__s,
html[data-theme="dark"] .tvz-dash-tile__k {
  color: var(--c-tx-2);
}

/* Строка «роль → вердикт» на телефоне в один ряд не помещается: у роли
   длинное имя, у вердикта — целая фраза. Без переноса бейдж уезжает за край
   карточки, и вердикт читается наполовину — то есть не читается вовсе. */
.tvz-level,
.tvz-kv {
  flex-wrap: wrap;
}

/* «Читаю через провал» (двойник Забелиной): подпись у левого края, значение —
   у правого, между ними полметра пустоты. На мониторе 1900 px пара перестаёт
   читаться как пара: глаз ведёт по пустому месту и теряет строку.
   Значение встаёт СРАЗУ за подписью; подписи выравниваются по общей мере,
   а длинная подпись просто отодвигает своё значение — но не бросает его. */
.tvz-kv {
  justify-content: flex-start;
  gap: var(--gap);
  padding: 6px 0;
}

.tvz-kv > span {
  flex: 0 1 auto;
  min-width: 220px;
}

.tvz-kv > b {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
}

/* Модалка на телефоне: дизайн-система рассчитана на десктоп, и на 390 точках
   её ширина выходит за экран — текст обрезается с обеих сторон. Ширину
   ограничиваем окном, значения токенов при этом не трогаются (ADR-0002). */
@media (max-width: 560px) {
  .tvz-modal {
    width: calc(100vw - 20px);
    max-width: calc(100vw - 20px);
    min-width: 0;
  }

  .tvz-modal__body {
    padding-inline: 14px;
  }
}

/* Полка «Неразобранное» (П-8б).
   Текст касания — это чужая речь, записанная как есть: переносы строк в нём
   значимы («звонил Пётр» / «просил перезвонить после трёх»), и схлопывать их
   нельзя. Ширина ограничена по той же причине, что у любого текста: строка в
   полтора экрана не читается, а её и читают — ради неё касание и записали. */
.tvz-shelf__text {
  margin: var(--gap) 0 0;
  white-space: pre-wrap;
  max-width: 74ch;
  color: var(--c-tx);
}

/* Разбор живёт в самой строке касания: поле клиента и две кнопки в один ряд.
   На узком экране ряд переносится, а не режется — «это наш» на телефоне
   обязано быть видно без горизонтальной прокрутки. */
.tvz-shelf__pick {
  display: flex;
  gap: var(--gap);
  flex-wrap: wrap;
  align-items: center;
  margin-top: var(--gap);
}

.tvz-shelf__pick .tvz-combo {
  flex: 1 1 260px;
  min-width: 0;
}

/* Форма «Записать обращение» в форм-факторе П-74 (хендофф 04.08). «Что
   сказали» — единственное обязательное поле, на всю ширину и высотой 150:
   фиксированная, а не `resize: vertical` из базового `.tvz-field textarea`,
   иначе перетаскивание рушит проверяемое условие «тело ≤520 без прокрутки».
   Ниже — ряд 260/1fr: канал и пунктирный ход «+ Зацепки», который раскрывает
   пять полей вниз (решение владельца: зацепки свёрнуты по умолчанию, набор
   и порядок полей не меняются — `HINTS` в inbox.js). */
.tvz-modal--pack .tvz-shelf-form__text textarea {
  /* `min-height`, а не только `height`: общее правило полей форм-фактора
     («textarea тянется по содержимому») объявлено НИЖЕ по файлу с той же
     весомостью селектора и побеждало порядком — поле выходило 117.5 вместо
     обещанных 150. min-height бьёт height при любом порядке. */
  min-height: 150px;
  height: 150px;
  resize: none;
}

.tvz-modal--pack .tvz-shelf-form__row {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 14px;
  align-items: end;
}

.tvz-modal--pack .tvz-shelf-form__hints {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Специфичность правила выше `[hidden]` в UA-таблице стилей (класс бьёт
   атрибут) — без явного правила блок оставался видимым даже со свёрнутым
   состоянием, и пять «обязательных на вид» полей возвращались незаметно. */
.tvz-modal--pack .tvz-shelf-form__hints[hidden] {
  display: none;
}

/* --- Сделки и задачи (П-10) ------------------------------------------------

   Список сделок — главный экран продажника, и его геометрия подчинена одному
   правилу: в строке ровно четыре вещи, и все четыре видны СРАЗУ, без
   прокрутки и без раскрытия. Клиент и следующая задача стоят слева столбиком,
   этап и тишина — справа. Пятому месту здесь взяться неоткуда, и это
   намеренно: «много информации на экране — и она перестаёт видеть главное»
   (портрет Маргариты, вводная владельца 29.07).

   Телефонный сценарий — основной (90% времени вне офиса), поэтому строка
   собрана так, чтобы на узком экране разложиться в два этажа, а не уехать
   в горизонтальную прокрутку. Расширять её на широком мониторе нечем и
   незачем — урок D-50 ровно об этом.

   Только геометрия и только токены: своих цветов здесь нет. */
.tvz-deal {
  align-items: center;
  gap: 8px;
}

/* Открыть карточку можно нажатием по всей левой части строки, а не по имени:
   палец на ходу не попадает в текст. Кнопка внутри строки, а не строка-кнопка,
   потому что рядом стоит вторая кнопка — пилюля этапа. */
.tvz-deal__open {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-deal__next {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--c-mut);
  font-size: var(--fz-sm);
}

/* Просроченная задача красится сама, а не заводит рядом пятый элемент строки. */
.tvz-deal__next.is-overdue {
  color: var(--c-err);
}

/* Этап — пилюля с выпадающим списком: смена одним нажатием прямо из строки.
   Не сжимается: название этапа («КП на рассмотрении») обязано читаться
   целиком, иначе нажимать не на что. */
.tvz-deal__stage {
  flex: none;
}

/* Чем двинут этап — правило 3 решения D-75, «видно, чем двинут этап».

   В строке на это отведён ТОН самой пилюли, а не пятый элемент: в строке
   ровно четыре вещи (клиент · этап · тишина · следующая задача), и пятая
   отправляет её из экрана. Тот же приём, которым красится просроченная
   задача выше. Этап, приехавший фактом из смежной системы, стоит в тоне
   подтверждения со значком связи; этап, отмеченный человеком, остаётся
   обычной пилюлей — это состояние по умолчанию и большинство этапов.
   Слова к обоим — в подсказке пилюли, в шапке её меню и в карточке. */
.tvz-deal__stage.is-fact {
  background: var(--c-okbg);
  border-color: var(--c-ok);
  color: var(--c-ok-d);
}

.tvz-deal__stage.is-fact .tvz-icon {
  color: var(--c-ok-d);
}

/* Закрытая сделка: пилюля остаётся на месте (этап читается), но списка
   не открывает — переоткрытие это новая сделка, а не правка старой. */
.tvz-deal__stage:disabled {
  cursor: default;
  opacity: .75;
}

/* Список выпадашки этапа — карта воронки (П-72, решение владельца 04.08).
   Точка перед подписью несёт тот же токен положения (`--stage-tint`, П-50),
   которым уже красится колонка канбана (`.tvz-kan__head` выше) и полоса
   воронки карточки (`.tvz-funnel__seg` ниже) — третий потребитель одного
   механизма, своей палитры здесь нет. */
/* Шире базового `.tvz-menu` (200px): строка текущего этапа несёт хвостовой
   тег «сейчас здесь», который в узкой колонке налезал бы на название. */
.tvz-stagemenu {
  min-width: 240px;
}

.tvz-stagemenu__it {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-stagemenu__dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--stage-tint, var(--c-bd));
}

/* Строка текущего этапа несёт подпись справа — тег, а не цифра, читается
   без расшифровки. */
.tvz-stagemenu__now {
  margin-left: auto;
  flex: none;
  font-size: 11px;
  font-weight: 600;
  color: var(--c-ac);
  white-space: nowrap;
}

/* Текущий этап отмечен готовым модификатором дизайн-системы
   (`.tvz-menu__it.is-active`, design.css) — тон уже выверен на обеих темах,
   вторую подсветку не изобретаем. Но строкой он не кнопка (тот же приём,
   что у пилюли закрытой сделки, B-104): курсор и ховер не обещают ход,
   которого нет — переход туда, где уже стоишь, не переход. */
.tvz-stagemenu__row--current {
  cursor: default;
}

.tvz-stagemenu__row--current:hover {
  background: var(--c-ac-tint);
}

/* Та же мысль на карточке, но развёрнуто: там места хватает и недосказанность
   ни к чему. Строка идёт под пилюлей этапа, отдельным этажом. */
.tvz-deal__source {
  margin: 8px 0 0;
  color: var(--c-mut);
  font-size: var(--fz-sm);
  line-height: 1.4;
}

.tvz-deal__source b {
  color: var(--c-tx-2);
  font-weight: 600;
}

.tvz-deal__source[data-source="fact"] b {
  color: var(--c-ok-d);
}

.tvz-deal__silent {
  white-space: nowrap;
}

/* Переключатель воронок и счётчики этапов в ряду фильтров. На широком экране
   это сегментированный контрол из трёх воронок; на узком — две пилюли
   с выпадающими списками (см. `pipelineChooser` и `stageCounters`). */
.tvz-deals__pipes,
.tvz-deals__stages {
  display: flex;
  min-width: 0;
}

.tvz-task .tvz-hit__side {
  gap: 6px;
}

@media (max-width: 900px) {
  /* Два этажа: клиент с задачей сверху, этап и тишина — строкой под ними.
     `.tvz-hit` на телефоне уже раскладывается в колонку, здесь остаётся
     только не дать правой части растянуться на всю ширину. */
  .tvz-deal__open {
    width: 100%;
  }

  /* Дело БЕЗ сделки (задача по клиенту, B-114) — не кнопка, а `.tvz-hit__main`,
     и правило ширины ему нужно то же: колонка `.tvz-hit` выравнивает детей по
     началу, и без явной ширины строка ужималась до текста — узкое дело среди
     полноширинных читалось как сломанное. */
  .tvz-day__row .tvz-hit__main {
    width: 100%;
  }

  .tvz-deal .tvz-hit__side {
    flex-wrap: wrap;
    gap: 6px;
  }

  /* Первый экран телефона принадлежит делу, а не управлению (B-86, D-72).

     Ряд фильтров страницы на узком экране раскладывается сеткой в две
     колонки, где первый контрол занимает всю строку. Для формы поиска это
     верно — там первый контрол главный и длинный. Здесь у экрана два
     коротких контрола (воронка и этапы, оба пилюлями), и сетка растащила бы
     их на два ряда, каждый из которых стоит одной видимой сделки. Ставим их
     в одну строку и разрешаем перенос — ряд занимает ровно столько, сколько
     нужно.

     Правило висит на `:has` с классом ЭТОГО экрана: соседние страницы со
     своими фильтрами продолжают жить общей сеткой. */
  .tvz-page__filters:has(.tvz-deals__pipes) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
  }

  .tvz-page__filters:has(.tvz-deals__pipes) > * {
    width: auto;
  }
}

/* Читаемость тёмной темы — по той же причине и тем же приёмом, что и в блоке
   выше: мелкий текст берёт токен на ступень контрастнее, значения токенов не
   трогаются (ADR-0002). Следующая задача в строке — это данные, а не подпись:
   выцветать ей нельзя. */
html[data-theme="dark"] .tvz-deal__next {
  color: var(--c-tx-2);
}

/* Просроченная задача остаётся красной и на тёмном: правило выше по
   специфичности перебивало её, и строка «позвонить надо было пять дней
   назад» переставала отличаться от любой другой. */
html[data-theme="dark"] .tvz-deal__next.is-overdue {
  color: var(--c-err);
}

/* --- Шелл редизайна (П-15а, хендофф владельца 31.07.2026) -----------------

   Владелец переработал интерфейсы и прислал макеты на наших же токенах.
   Каркас — общий для всех принятых экранов (1a, 1b, 5a…5e), поэтому он идёт
   первой волной: иначе каждый следующий экран тащил бы его за собой.

   Что меняется в каркасе и почему:

   1. Сайдбар **232** вместо 252 и без карточки — плоская колонка с одной
      линией справа. Отыгранные 20 px и поля карточки уходят содержимому;
      на канбане это половина ширины столбца.
   2. Профиль уезжает из шапки в **подвал сайдбара**. Шапка освобождается под
      главное действие экрана — глобальный поиск, — а профиль перестаёт
      соседствовать с рабочими кнопками: его трогают раз в день.
   3. **Поиск перестаёт быть разделом** и становится полем в шапке. Путь
      до контакта был три клика и один из них тратился на выбор раздела
      (US-P1); теперь поиск доступен с любого экрана, не уводя с него.

   Значения токенов не трогаются: здесь только геометрия и выбор токена. */

/* Каркас переопределяется ТОЛЬКО на широком экране, и это не осторожность,
   а починка: правила ниже по файлу перебивают медиа-блок «телефон» выше при
   равной специфичности. Без рамки `min-width` сайдбар оставался колонкой
   в 232 px на экране в 375 и съедал две трети места — контент уезжал за край.
   Тот же класс дефекта, что B-96 и B-98: обе половины верны, неверен шов. */
@media (min-width: 901px) {
  .tvz-app {
    grid-template-columns: 232px 1fr;
  }

  .tvz-side {
    margin: 0;
    border: 0;
    border-right: 1px solid var(--c-bd);
    border-radius: 0;
    box-shadow: none;
  }
}

/* Навигация: строка 38, счётчик пилюлей справа. Число в строке меню — это
   «сколько меня ждёт», и оно обязано читаться раньше подписи, поэтому
   моноширинным и жирным. */
.tvz-nav__item {
  height: 38px;
  border-radius: 8px;
}

.tvz-nav__count {
  margin-left: auto;
  min-width: 20px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* У активной строки подложка счётчика — цвет поверхности, а не белый:
   в тёмной теме белое пятно на тёмной строке кричало бы громче самой
   строки. Токен переворачивается вместе с темой, жёсткий белый — нет. */
.tvz-nav__item.is-active .tvz-nav__count {
  background: var(--c-surface);
}

/* Подвал сайдбара: профиль и выход. Прижат книзу — `margin-top:auto` вместо
   абсолютного позиционирования, иначе он наезжал бы на список разделов,
   когда тот длиннее экрана. */
.tvz-side__foot {
  margin-top: auto;
  padding: 10px 12px;
  border-top: 1px solid var(--c-bd);
  display: flex;
  align-items: center;
  gap: 9px;
}

.tvz-side__ava {
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 999px;
  background: var(--c-mut);
  /* Текст на инвертированной подложке — токеном поверхности: в светлой теме
     это белый, в тёмной — тёмный на светло-сером. Оба раза читаемо, тогда
     как жёстко заданный белый читаем ровно один раз. */
  color: var(--c-surface);
  font-size: 11.5px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tvz-side__who {
  min-width: 0;
  flex: 1;
  line-height: 1.25;
}

.tvz-side__nm {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-side__ro {
  font-size: 11px;
  color: var(--c-tx-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* «Назад» шапки (`setShellBack`, core/ui.js; П-41) — компактная icon-only
   кнопка ПЕРЕД заголовком экрана. Скрыта по умолчанию (инлайновый
   `style="display:none"` в разметке `layout()`, app.js); показывающий её
   экран отвечает и за то, чтобы её снять. */
.tvz-top__back {
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--rad-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-mut);
  cursor: pointer;
}
.tvz-top__back:hover {
  background: var(--c-hover);
  color: var(--c-tx);
}

/* Глобальный поиск в шапке. Ширина ограничена: поле во весь монитор читается
   как поле ввода документа, а не как поиск. */
.tvz-top__find {
  /* Поиск стоит СПРАВА, после имени страницы (порядок шапки, 02.08), и
     тянется остатком строки — но не во весь монитор: поле шире 520px
     читается как поле ввода документа, а не как поиск. */
  flex: 1;
  max-width: 520px;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  /* Поле на белой шапке ТЕРЯЛОСЬ: фон `--c-bg` почти совпадает с шапкой,
     рамка `--c-bd` — самая светлая линия системы, и поиск читался как
     пустое место (владелец 02.08: «инпут поиска теряется, надо решить
     цвет»). Берём поверхность на тон глубже фона шапки и рамку-разделитель
     `--c-line-strong` — тот же приём, что у полей форм; новых цветов нет. */
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  background: var(--c-chip);
  color: var(--c-tx-2);
  font: inherit;
  font-size: var(--fz-sm);
  cursor: pointer;
  text-align: left;
  transition: background .12s, border-color .12s, box-shadow .12s;
}

.tvz-top__find:hover {
  background: var(--c-surface);
  border-color: var(--c-ac-bd);
  color: var(--c-tx);
}

/* Клавиатурный фокус виден так же, как у полей ввода: поиск — вход в работу,
   и добираться до него табом обязано быть заметно. */
.tvz-top__find:focus-visible {
  outline: none;
  border-color: var(--c-ac);
  background: var(--c-surface);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

.tvz-top__find .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

/* Подсказка в одну строку. На телефоне «Клиент, площадка, фамилия, телефон…»
   переносилась в четыре строки и налезала на содержимое — а видно её на
   КАЖДОМ экране, потому что поиск живёт в шапке шелла. Обрезка многоточием
   честнее переноса: длина подсказки не должна двигать чужую вёрстку. */
.tvz-top__find > span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  min-width: 0;
}

.tvz-top__find kbd {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 1px 6px;
  border: 1px solid var(--c-bd);
  border-radius: 6px;
  background: var(--c-surface);
  color: var(--c-mut);
}

@media (max-width: 900px) {
  /* На телефоне сайдбар лежит сверху узкой полосой (B-113) — профиль встаёт
     в ОДНУ строку с брендом, а не отдельным этажом: этаж стоил бы видимой
     строки списка. Раскладку полосы задаёт грид-блок выше по файлу. */
  .tvz-side {
    border-right: 0;
    border-bottom: 1px solid var(--c-bd);
  }

  .tvz-side__foot {
    margin: 0;
    border-top: 0;
    padding: 2px 10px 2px 0;
  }

  /* Имя в строке с брендом ужимается многоточием, а не двигает бренд:
     28vw хватает на «Фамилия И.», а бренду — на полное «Техновизор CRM». */
  .tvz-side__nm {
    max-width: 28vw;
  }

  /* Подпись роли на узком экране не нужна: имя и так рядом, а место
     принадлежит делу (B-86). */
  .tvz-side__ro {
    display: none;
  }

  .tvz-top__find kbd {
    display: none;
  }
}

/* Тёмная тема: подпись роли в подвале и подсказка в поле поиска берут токен
   на ступень контрастнее — тот же приём, что и для остального мелкого
   текста выше. */
html[data-theme="dark"] .tvz-side__ro,
html[data-theme="dark"] .tvz-top__find {
  /* На тёмной `--c-chip` глубже фона шапки так же, как на светлой, — поле
     видно, но не светится. Рамка чуть ярче разделителя: на тёмном фоне
     тонкая линия читается хуже, чем на светлом. */
  color: var(--c-tx-2);
  background: var(--c-chip);
  border-color: var(--c-line-strong);
}

html[data-theme="dark"] .tvz-top__find:hover {
  background: var(--c-hover);
  border-color: var(--c-ac-bd);
  color: var(--c-tx);
}

/* --- Воронка доской (П-15в, макет 1a) -------------------------------------

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

   Горизонтальная прокрутка обязательна и не считается недостатком: число
   этапов приходит справочником и у разных воронок разное (D-74). Ужимать
   столбцы под экран значило бы обещать, что этапов всегда семь. */

.tvz-kan {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 4px;
  align-items: flex-start;
}

.tvz-kan__col {
  flex: none;
  width: 252px;
  display: flex;
  flex-direction: column;
  min-height: 120px;
  border-radius: var(--rad);
  padding: 2px;
}

/* Столбец под курсором с карточкой подсвечивается — иначе перенос вслепую:
   человек отпускает кнопку, не зная, куда попадёт. */
.tvz-kan__col.is-over {
  background: var(--c-ac-tint);
  outline: 1px dashed var(--c-ac-bd);
}

/* Подчёркивание колонки — тон этапа (П-50): доска и полоса воронки на
   карточке зовут один этап одним цветом. Не назвали тон — линия остаётся
   нейтральной, как была. */
.tvz-kan__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 4px 4px;
  border-bottom: 2px solid var(--stage-tint, var(--c-line-strong));
}

.tvz-kan__t {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--c-tx-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-kan__n {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--c-tx);
}

/* Подпись чужого набора на столбце (B-125): сделка чужого набора не
   исчезает с доски, а стоит в колонке СВОЕГО набора — и две колонки
   «Не состоялась» без подписи, чей это набор, читались бы как дубль. */
.tvz-kan__set {
  padding: 4px 4px 0;
  font-size: 11px;
  color: var(--c-tx-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Деньги столбца и подпись «приезжает сам» стоят на одном месте: это ответ
   на один вопрос — «что за этим этапом». Пусто здесь законно: столбец без
   единой цены молчит, а не пишет «0 ₽» (П-15в). */
.tvz-kan__sub {
  min-height: 16px;
  padding: 5px 4px 0;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-kan__col.is-fact .tvz-kan__sub {
  font-family: var(--font-ui);
}

.tvz-kan__body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 8px;
  overflow-y: auto;
  max-height: calc(100vh - 240px);
}

.tvz-kan__card {
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-left: 3px solid var(--c-line-strong);
  border-radius: var(--rad);
  box-shadow: var(--shadow-e1);
  cursor: grab;
}

.tvz-kan__card.is-warn {
  border-left-color: var(--c-warn);
}

.tvz-kan__card.is-err {
  border-left-color: var(--c-err);
}

.tvz-kan__card.is-drag {
  opacity: .5;
  cursor: grabbing;
}

.tvz-kan__open {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 100%;
  padding: 10px 11px;
  border: 0;
  border-radius: inherit;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-kan__open:hover {
  background: var(--c-hover);
}

.tvz-kan__cl {
  font-size: 13px;
  font-weight: 600;
  color: var(--c-tx);
  /* Две строки, а не одна: имя сделки по умолчанию — «Клиент · Площадка»,
     и однострочная обрезка съедала ровно различающую часть («ГК «Меридиан»
     · Автопарк Пер…»). Сто сделок сети снова стали бы на ощупь (D-86). */
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Бейдж тишины не тянется по ширине карточки: в колонке flex растянул бы
   его на всю строку, и плашка перестала бы читаться как плашка. */
.tvz-kan__sil {
  align-self: flex-start;
}

.tvz-kan__next {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-kan__next.is-overdue {
  color: var(--c-err);
}

/* Пустой столбец говорит вслух. Пропавший блок читается как «всё в порядке»,
   а пустой этап — это не порядок, а факт (урок S-5). */
.tvz-kan__empty {
  border: 1px dashed var(--c-bd);
  border-radius: var(--rad);
  padding: 14px 10px;
  text-align: center;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* Тёмная тема: подпись под столбцом и следующая задача берут токен на
   ступень контрастнее — то же правило, что для остального мелкого текста. */
html[data-theme="dark"] .tvz-kan__sub,
html[data-theme="dark"] .tvz-kan__next {
  color: var(--c-tx-2);
}

html[data-theme="dark"] .tvz-kan__next.is-overdue {
  color: var(--c-err);
}

/* --- Поиск оверлеем (П-15б, макет 5a) -------------------------------------

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

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

/* Подложка приходит системной `.tvz-modal-back` — здесь только геометрия:
   панель прижата к 70 px сверху, а не к 8vh, чтобы поле ввода встало туда,
   где только что стояло поле шапки. Цвет и размытие живут в апстриме. */
.tvz-find-back {
  padding: 70px 16px 16px;
}

.tvz-find {
  width: min(760px, 100%);
  max-height: min(760px, calc(100vh - 100px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  box-shadow: var(--shadow-e2);
}

.tvz-find__top {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 56px;
  padding: 0 16px;
  border-bottom: 1px solid var(--c-bd);
  flex: none;
}

.tvz-find__top > .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

/* Поле без рамки: рамка внутри панели рисовала бы коробку в коробке. */
.tvz-find__in {
  flex: 1;
  min-width: 0;
  height: 40px;
  border: 0;
  background: transparent;
  font-size: 17px;
  color: var(--c-tx);
}

.tvz-find__in:focus {
  outline: none;
  box-shadow: none;
}

.tvz-find__x {
  flex: none;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: var(--rad);
  background: transparent;
  color: var(--c-tx-4);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.tvz-find__x:hover {
  background: var(--c-hover);
  color: var(--c-tx);
}

/* Ряд «Сузить:» (макет 5a): чипы 26px, радиус 999. Доступный — пунктир без
   значения, действующий — заливка `--c-ac-tint` со значением и крестиком. */
.tvz-find__chips {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 10px 16px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-find__cl {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-find__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border: 1px dashed var(--c-bd);
  border-radius: 999px;
  background: transparent;
  color: var(--c-tx-4);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

.tvz-find__chip.is-active {
  border: 1px solid var(--c-ac-bd);
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-find__chipx {
  opacity: .7;
  font-size: 13px;
  line-height: 1;
}

.tvz-find__chipin {
  height: 26px;
  padding: 0 10px;
  border: 1px solid var(--c-ac);
  border-radius: 999px;
  background: var(--c-surface);
  color: var(--c-tx);
  font-size: 11.5px;
}

.tvz-find__chipin:focus {
  outline: none;
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

.tvz-find__cnote {
  margin-left: auto;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-find__body {
  flex: 1;
  overflow-y: auto;
  min-height: 80px;
}

.tvz-find__idle {
  padding: 22px 16px;
  color: var(--c-tx-4);
  font-size: var(--fz-sm);
  line-height: 1.5;
}

.tvz-find__gt {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 16px 5px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
}

.tvz-find__gt span {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: 11px;
}

.tvz-find__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 16px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-find__row:hover {
  background: var(--c-hover);
}

/* Строка открывает карточку, кнопка рядом звонит — поэтому кликабельна
   именно эта часть, а не вся строка: иначе нажатие «позвонить» уводило бы
   с экрана заодно. */
.tvz-find__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  cursor: pointer;
}

.tvz-find__nm {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--c-tx);
}

.tvz-find__sub {
  font-size: 11.5px;
  color: var(--c-tx-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Состояние записи — колонкой 150px справа (макет 5a): бейджи стоят в ряд,
   и глаз ловит «пора проверить» по всей выдаче, не читая каждую строку. */
.tvz-find__trust {
  flex: none;
  width: 150px;
  display: flex;
  justify-content: flex-end;
}

/* Запрет прямого общения в строке — живьём лучше макета, и остаётся. Но без
   предела ширины плашка давила имя в столбик по букве; переносится она,
   а не главная колонка. */
.tvz-find__row .tvz-acts {
  min-width: 0;
  max-width: 45%;
}

.tvz-find__foot {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-top: 1px solid var(--c-bd);
  background: var(--c-bg);
}

.tvz-find__hint {
  flex: 1;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* Условие — то же, что у модалок (П-59, раздел 3): узкое окно И ГРУБЫЙ
   УКАЗАТЕЛЬ. Раньше здесь стоял один `max-width: 900px`, и оверлей поиска
   разворачивался во весь экран по ШИРИНЕ — то есть и в узком окне за столом,
   где половина мобильных решений вредна и откуда нельзя позвонить. Канон
   ветки делит раскладки по указателю (`docs/UI-MOBILE.md`), и два оверлея
   были последними, кто делил по ширине. */
@media (max-width: 900px) and (pointer: coarse) {
  /* На телефоне панель занимает экран целиком: оверлей в 760 px там был бы
     тем же экраном, только с полями по краям. */
  .tvz-find-back {
    padding: 8px;
  }

  .tvz-find {
    max-height: calc(100vh - 16px);
  }

  .tvz-find__hint {
    display: none;
  }

  /* На телефоне жёсткая колонка 150px отбирала бы половину строки, а
     приписка про правило повторяет пустое состояние — её можно не держать. */
  .tvz-find__trust {
    width: auto;
  }

  .tvz-find__cnote {
    display: none;
  }
}

/* Мелкий текст на тёмном приглушается на шаг мягче (правило shell.css про
   --c-tx-4 → --c-tx-2 — хендофф 5a распространяет его на новые элементы). */
html[data-theme="dark"] .tvz-find__sub,
html[data-theme="dark"] .tvz-find__idle,
html[data-theme="dark"] .tvz-find__hint,
html[data-theme="dark"] .tvz-find__cl,
html[data-theme="dark"] .tvz-find__cnote,
html[data-theme="dark"] .tvz-find__chip:not(.is-active) {
  color: var(--c-tx-2);
}

/* Воронка доской и «Мой день» занимают ВСЮ ширину — слово владельца 31.07
   («воронка должна быть на всю ширину», «тут тоже проблема с шириной,
   не тянется»), и мера 1080 px им действительно не подходит.

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

   У «Моего дня» причина та же, но своя: у него две колонки — очередь
   и справка. В 1080 px правая колонка в 340 отъедала треть у очереди,
   и строка действия начинала переноситься по словам. Мера, поставленная
   ради читаемости строки, ломала именно строку.

   Правило висит на `:has(...)` — то есть ровно на этих двух страницах;
   список сделок на узком экране и все остальные меру сохраняют. */
.tvz-content > .tvz-page:has(.tvz-kan),
.tvz-content > .tvz-page:has(.tvz-day) {
  max-width: none;
}

/* Клиент подписью под названием сделки (D-86): сделка — своя сущность, а не
   компания. У сетевого клиента их бывает сто, и различать их надо глазом,
   а не на ощупь. Подпись приглушена: главное в строке — сама сделка. */
.tvz-kan__of,
.tvz-deal__of {
  display: block;
  font-size: 11px;
  font-weight: 400;
  color: var(--c-tx-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-deal__of {
  display: inline;
  margin-left: 6px;
}

/* Владелец чужой сделки — подписью в той же колонке, не пятым элементом
   (П-31: правило четырёх вещей в строке держится). Появляется только там,
   где сделка не моя, — в срезе «переданные мной»: в mine все сделки мои,
   и имя зрителя в каждой строке было бы шумом. Тон приглушён тем же
   классом причин, что подпись клиента: это справка «у кого теперь»,
   а не вторая тишина. */
.tvz-deal__owner {
  display: block;
  font-size: 11px;
  font-weight: 400;
  color: var(--c-tx-4);
}

html[data-theme="dark"] .tvz-kan__of,
html[data-theme="dark"] .tvz-deal__of,
html[data-theme="dark"] .tvz-deal__owner {
  color: var(--c-tx-2);
}

/* --- «Мой день» (П-15г, макет 1b, D-84) -----------------------------------

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

.tvz-day__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.tvz-day__head h2 {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.tvz-day__head span {
  font-size: var(--fz-sm);
  color: var(--c-tx-4);
}

.tvz-day {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px;
  align-items: start;
}

.tvz-day__queue,
.tvz-day__side {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.tvz-day__grp {
  padding: 0;
  overflow: hidden;
}

.tvz-day__gh {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-day__dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}

.tvz-day__dot.is-err {
  background: var(--c-err);
}

.tvz-day__dot.is-warn {
  background: var(--c-warn);
}

/* Полоса «Дальше» — свой квадратик, серый (слово владельца 04.08). Без
   него заголовок стоял без метки, и полоса читалась как обрывок соседней:
   у всех остальных метка есть, а у этой нет. Серый, а не сигнальный тон:
   «дальше» — это не состояние, это «просто есть». */
.tvz-day__dot.is-mut {
  background: var(--c-tx-4);
}

.tvz-day__gt {
  flex: 1;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--c-tx-2);
}

.tvz-day__gn {
  /* Счётчик группы — ЕДИНСТВЕННОЕ место, где живёт число дел (02.08:
     пересказ из заголовка снят). Значит он обязан читаться с одного
     взгляда: прежние 13px обычного текста рядом с крупной шапкой группы
     читались как сноска — владелец назвал их «плоховато читаются».
     Размер как у имени группы, цифры моноширинные: столбик чисел
     в трёх группах подряд должен стоять ровно. */
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 700;
  line-height: 1;
  color: var(--c-tx);
  font-variant-numeric: tabular-nums;
}

/* Число ГОРИТ тем же цветом, что точка группы: «просрочено» и «молчат»
   красным, «на сегодня» янтарным. Цвет берётся у соседней точки, а не
   задаётся заново, — вердикт один, источник один. */
.tvz-day__gh:has(.tvz-day__dot.is-err) .tvz-day__gn {
  color: var(--c-err);
}

.tvz-day__gh:has(.tvz-day__dot.is-warn) .tvz-day__gn {
  color: var(--c-warn);
}

/* Строка очереди: действие слева, клиент с этапом посередине, срок и одно
   нажатие справа. Клиент занимает фиксированную ширину — иначе колонка
   пляшет от длины названия и глаз ищет её заново в каждой строке. */
.tvz-day__row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-day__row:last-child {
  border-bottom: 0;
}

.tvz-day__main {
  flex: 1;
  min-width: 0;
}

.tvz-day__act {
  font-size: 13px;
  font-weight: 600;
  color: var(--c-tx);
}

.tvz-day__why {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-day__who {
  width: 190px;
  flex: none;
  min-width: 0;
}

.tvz-day__cl {
  font-size: 12px;
  color: var(--c-tx-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-day__st {
  font-size: 11px;
  color: var(--c-tx-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Колонки очереди выровнены по СТОЛБЦАМ, а не по содержимому.

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

   Поэтому у бейджа своя фиксированная колонка с прижимом вправо: ширина
   его содержимого меняется, а место — нет. */
.tvz-day__mark {
  width: 104px;
  flex: none;
  display: flex;
  justify-content: flex-end;
}

.tvz-day__go {
  flex: none;
}

/* Пустая группа говорит вслух: пропавший блок читается как «всё в порядке»,
   а это другое сообщение (урок S-5). */
.tvz-day__none {
  padding: 12px 14px;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-day__aside h3 {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 700;
}

.tvz-day__srow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--c-bd2);
  font-size: 12.5px;
}

.tvz-day__srow:last-of-type {
  border-bottom: 0;
}

.tvz-day__srow i {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: var(--c-tx-4);
}

/* Воронка полосами: доля от самого населённого этапа. Это справка «где
   я стою», а не счёт — точное число стоит рядом цифрой. */
.tvz-day__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
}

.tvz-day__bt {
  width: 132px;
  flex: none;
  font-size: 12px;
  color: var(--c-tx-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-day__bl {
  flex: 1;
  height: 10px;
  border-radius: var(--rad-pill);
  background: var(--c-bd2);
  overflow: hidden;
}

.tvz-day__bl i {
  display: block;
  height: 100%;
  background: var(--c-ac);
}

.tvz-day__bn {
  width: 22px;
  flex: none;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
}

@media (max-width: 900px) {
  /* На телефоне справка уходит под очередь: контекст ниже работы, а не
     рядом с ней — двух колонок на 390 px не бывает. */
  .tvz-day {
    grid-template-columns: 1fr;
  }

  /* Клиент и этап встают под действие: в строку шириной 390 px три колонки
     не помещаются, и первой начинает резаться самая нужная — действие. */
  .tvz-day__row {
    flex-wrap: wrap;
    gap: 8px;
    /* Просьба волны «Мой день»: базовое центрирование перебивало телефонный
       `flex-start` ряда дизайн-системы, и блок «бейдж + кнопка» вставал
       по центру, а не от края (замер: x=77 при строке от x=13). */
    align-items: flex-start;
  }

  .tvz-day__who,
  .tvz-day__mark {
    width: auto;
  }
}

html[data-theme="dark"] .tvz-day__why,
html[data-theme="dark"] .tvz-day__st,
html[data-theme="dark"] .tvz-day__none,
html[data-theme="dark"] .tvz-day__head span {
  color: var(--c-tx-2);
}

/* Причины закрытия записи — готовыми плашками (макет 5d). Выбранная
   отмечается заливкой: галочка сбоку в ряду из шести плашек читается хуже,
   чем сама плашка, ставшая цветной. */
.tvz-reasons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tvz-reasons .tvz-btn.is-active {
  border-color: var(--c-err);
  background: var(--c-errbg);
  color: var(--c-err);
}

/* «Своя формулировка» — выход из закрытого списка, и он подписан пунктиром:
   готовые ответы читаются первыми, выход не притворяется одним из них. */
.tvz-reasons .tvz-btn.is-own {
  border-style: dashed;
  color: var(--c-tx-4);
}

/* Поле своих слов появляется только под «Своей формулировкой» — отступ
   отделяет его от ряда плашек, иначе оно читается как подпись к последней. */
.tvz-reasons__own {
  margin-top: 4px;
}

.tvz-reasons__own.is-off {
  display: none;
}

/* --------------------------------------------------------------------------
   Чеклист подтверждения (макет 5d, П-15ж).

   Подтверждение перестало быть одной кнопкой «ок»: по строке на утверждение,
   и каждую отмечает человек. Урок B-14 — «проверено человеком» оказалось
   неправдой в двух третях базы, потому что подтверждали не глядя, — держится
   не текстом на экране, а тем, что отметить строку можно только нажатием.
   -------------------------------------------------------------------------- */
.tvz-check {
  display: grid;
  gap: 4px;
}

.tvz-check__lead {
  margin: 0 0 8px;
  color: var(--c-tx-2);
  line-height: 1.45;
}

.tvz-check__list {
  display: grid;
  gap: 8px;
}

.tvz-check__r {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
  cursor: pointer;
}

.tvz-check__r:hover {
  background: var(--c-hover);
}

/* Отмеченная строка видна целиком, а не одной галочкой: пересчитать «3 из 4»
   глазами человек должен по строкам, а не по мелким квадратам. */
.tvz-check__r.is-on {
  border-color: var(--c-ac-bd);
  background: var(--c-ac-tint);
}

/* Пустое поле отмечать нечем: строка не нажимается и говорит об этом словами,
   а не отсутствием. Курсор обычный — обещать нажатие, которого нет, нельзя. */
.tvz-check__r.is-off,
.tvz-check__r.is-off:hover {
  background: var(--c-surface);
  cursor: default;
}

/* Настоящий чекбокс живёт под квадратом: клавиатура, пробел и доступность
   достаются даром, а рисуем мы свой квадрат. */
.tvz-check__i {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.tvz-check__b {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: var(--rad-sm);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: transparent;
}

.tvz-check__r.is-on .tvz-check__b {
  border-color: var(--c-ac);
  background: var(--c-ac);
  /* Знак на залитом квадрате — токеном поверхности: в тёмной теме жёстко
     заданный белый перестал бы читаться (тот же приём, что у аватаров). */
  color: var(--c-surface);
}

.tvz-check__i:focus-visible + .tvz-check__b {
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

.tvz-check__m {
  min-width: 0;
  flex: 1;
  display: grid;
  gap: 1px;
}

.tvz-check__k {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-tx-4);
}

.tvz-check__v {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx);
  overflow-wrap: anywhere;
}

.tvz-check__fix {
  flex: none;
}

/* Что встанет в карточку — сказано до нажатия и ровно то, что встанет:
   имя и дата. Подтверждение — слово человека, а не факт системы. */
.tvz-check__note {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-bg);
  font-size: 12px;
  color: var(--c-tx-2);
  line-height: 1.4;
}

.tvz-check__note .tvz-icon {
  flex: none;
  color: var(--c-tx-4);
}

/* Развилка стоит слева и не в ряду с «Отмена»: «здесь больше не работает» —
   не отмена подтверждения, а другой ответ на тот же вопрос. */
.tvz-check__gone {
  margin-right: auto;
}


/* Диалог одного решения — 520 px, как в макете. Без этого модалка тянется до
   92vw: ряд плашек причин расползается на весь экран, и строка объяснения
   становится длиной в полтора метра. На телефоне ширину задаёт своё правило
   выше, поэтому здесь — только от 561 px. */
@media (min-width: 561px) {
  .tvz-modal--ask {
    width: 520px;
  }
}

@media (max-width: 560px) {
  /* Телефон: подпись пункта и кнопка ответа не делят строку с текстом —
     иначе значение режется, а режется первым как раз то, что проверяют. */
  .tvz-check__r {
    flex-wrap: wrap;
  }

  .tvz-check__fix {
    margin-left: 31px;
  }

  /* Три кнопки в строку 375 px не встают, и первой обрезается развилка —
     нашлось взглядом на снимке, а не прогоном. Подвал переносится только
     здесь: на десктопе ряд обязан остаться одной строкой, как в макете. */
  .tvz-modal__foot--fork {
    flex-wrap: wrap;
  }

  /* Развилка уходит на свою строку и ПОД действия: на телефоне она читается
     последней — сначала «подтвердить», и только потом «его здесь нет». */
  .tvz-check__gone {
    order: 2;
    margin-right: 0;
    width: 100%;
    justify-content: center;
  }
}

html[data-theme="dark"] .tvz-check__k,
html[data-theme="dark"] .tvz-check__note,
html[data-theme="dark"] .tvz-check__note .tvz-icon,
html[data-theme="dark"] .tvz-reasons .tvz-btn.is-own {
  /* Мелкий текст на тёмном: `--c-tx-4` уходит в фон (правило шелла). */
  color: var(--c-tx-2);
}

/* Полоса выбора потока на «Моём дне» (П-15г, вводная владельца 31.07). */
.tvz-day__flows {
  min-width: 0;
  max-width: 100%;
}

@media (max-width: 900px) {
  /* Сегментированный контрол на телефоне прокручивается ВНУТРИ СЕБЯ, а не
     тянет вбок всю колонку содержимого.

     Нашёл обход экранов (D-89) — и нашёл сразу два места: новый выбор потока
     на «Моём дне» переполнял колонку на 522 px (очередь ужималась до трети,
     заголовок задачи ломался по слову в строку), а пять вкладок «Моего
     участка» — на 146 px, и «Дубли в базе» не было видно вовсе. Второй
     дефект стоял в продукте давно и не был замечен ни разу.

     Приём тот же, что у широких таблиц админки: прокрутка живёт внутри
     своей полосы — страница по горизонтали не едет. */
  .tvz-seg {
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tvz-seg::-webkit-scrollbar {
    display: none;
  }

  .tvz-seg__b {
    white-space: nowrap;
    flex: none;
  }

  .tvz-day__flows {
    width: 100%;
  }
}

/* ===================== Воронки в Администрировании (П-13б) =====================
   Настройка наборов этапов: состав в списке одной полосой и редактор состава
   в форме. Своих цветов нет — только токены; вид этапа читается заливкой,
   потому что в ряду из шести подписей слово «закрыта» теряется. */

.tvz-stagestrip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.tvz-stagestrip__it {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--rad-pill);
  font-size: var(--fz-sm);
  white-space: nowrap;
}

/* Рабочий этап нейтрален, исходы окрашены: «закрыта» и «не состоялась» — это
   то, на чём держатся счётчики и запрет двигать законченную сделку, и
   перепутать их в списке дороже, чем перепутать два рабочих. */
.tvz-stagestrip__it--work {
  background: var(--c-chip);
  color: var(--c-tx-2);
}

.tvz-stagestrip__it--won {
  background: var(--c-okbg);
  color: var(--c-ok);
}

.tvz-stagestrip__it--lost {
  background: var(--c-errbg);
  color: var(--c-err);
}

/* Сколько сделок стоит на этапе. Цифра рядом с подписью, а не отдельной
   колонкой: вопрос «что я сломаю, убрав этот этап» задаётся про этап. */
.tvz-stagestrip__n {
  font-family: var(--font-mono);
  font-size: var(--fz-micro);
  font-weight: 700;
}

/* --- редактор состава в форме воронки --- */

.tvz-stages {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-stages__h {
  font-size: var(--fz-sm);
  font-weight: 700;
}

.tvz-stages__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tvz-stages__empty {
  padding: 12px;
  border: 1px dashed var(--c-bd);
  border-radius: var(--rad);
  color: var(--c-mut);
  font-size: var(--fz-sm);
}

.tvz-stages__row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
}

/* Порядок этапов — список, а не граф: две стрелки вместо перетаскивания,
   которое на телефоне не работает вовсе. */
.tvz-stages__ord {
  display: flex;
  flex-direction: column;
  flex: none;
  gap: 2px;
}

.tvz-stages__up {
  transform: rotate(180deg);
}

.tvz-stages__main {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.tvz-stages__top {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}

.tvz-stages__t {
  flex: 1 1 200px;
  min-width: 140px;
}

.tvz-stages__k,
.tvz-stages__s {
  flex: none;
  width: 132px;
}

/* Вторая строка — то, что ПОКАЗЫВАЕТСЯ и не правится: код, счётчик сделок,
   подключённость факта. Рядом с ними единственный переключатель, который
   тут законен, — «спрашивать причину проигрыша». */
.tvz-stages__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: var(--fz-sm);
}

.tvz-stages__code {
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
}

.tvz-stages__acts {
  flex: none;
}

.tvz-stages__moves:empty {
  display: none;
}

/* Кнопка по содержимому, а не во всю колонку: во всю ширину она читается
   как поле следующего этапа, а не как действие. */
.tvz-stages__add {
  align-self: flex-start;
}

@media (max-width: 700px) {
  /* На телефоне название занимает строку целиком, а вид и источник встают
     под ним ПАРОЙ: три контрола в ряд на 390 px не помещаются, а разложенные
     по одному растягивают строку этапа на пол-экрана. */
  .tvz-stages__t {
    flex: 1 1 100%;
  }

  .tvz-stages__k,
  .tvz-stages__s {
    width: auto;
    min-width: 0;
    flex: 1 1 40%;
  }
}

/* Пятая вкладка Администрирования («Воронки») переполнила линию вкладок на
   390 px — и потянула вбок весь экран. Приём тот же, что уже применён к
   сегментированному контролу и к широким таблицам (D-89): прокрутка живёт
   ВНУТРИ своей полосы, страница по горизонтали не едет.

   Здесь это не косметика: пятая вкладка появилась вместе с этой волной, и без
   правила «Импорт» просто уезжал бы за край — ровно так же, как когда-то
   «Дубли в базе» на «Моём участке», чего не заметили ни разу. */
@media (max-width: 900px) {
  .tvz-tabs {
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tvz-tabs::-webkit-scrollbar {
    display: none;
  }

  .tvz-tab {
    white-space: nowrap;
    flex: none;
  }
}

/* ===========================================================================
   Карточка контакта (П-42): шапка одной строкой меты, каналы блоками,
   правка на месте под «Поправить» (наследие П-15д/П-15е, макеты 5b/5c).

   Только геометрия и уже существующие токены.

   Общий узор блока (кроме верхней карточки шапки) — `.tvz-blk__*`: заголовок
   14.5/700 на тонированной плашке `--c-hover`, тихий счётчик рядом, действие
   справа. Он НЕ переиспользует `.tvz-panel__*` — тем классом рисует себя
   «За что отвечает» (`zonesCard`, другая волна её не трогает) и сетка правки
   на месте (`factsCard`, режим «Поправить»): смена значений `.tvz-panel__*`
   задним числом перекрасила бы и их, хотя обе остаются нарочно старыми.
   =========================================================================== */

/* Крошки — только путь: клиент (ссылка) и имя. «Назад» переехал в шапку
   оболочки готовым узором `setShellBack` (core/ui.js) — своей кнопки
   возврата и своего «⋯» с редкими действиями карточка больше не заводит. */
.tvz-crumbs__here {
  color: var(--c-tx-2);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.tvz-crumbs__sep {
  display: inline-flex;
  color: var(--c-tx-4);
}

/* Карточка без внутренних полей: шапка и строки идут от кромки до кромки.
   Обычная `.tvz-card` для этого не годится — её padding режет разделители
   на полосы с проплешинами по краям. */
.tvz-card--flat {
  padding: 0;
  overflow: hidden;
  /* `overflow` не `visible` обнуляет `min-height:auto` у флекс-элемента — и
     карточка, стоящая в колонке страницы, схлопывается в ноль высоты, а её
     содержимое остаётся видимым, но некликабельным: нажатие уходит в саму
     карточку. Поймано браузерной проверкой, глазами такое не отличить от
     нормы. Сжиматься карточке незачем — высоту ей задаёт содержимое. */
  flex: none;
}

.tvz-cols2 {
  flex: none;
}

.tvz-panel__h {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 13px 16px;
  border-bottom: 1px solid var(--c-bd);
}

.tvz-panel__t {
  font-size: 14px;
  font-weight: 700;
}

.tvz-panel__n {
  color: var(--c-tx-4);
  font-size: var(--fz-micro);
  min-width: 0;
}

.tvz-panel__end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-panel__none {
  color: var(--c-mut);
  padding: 12px 16px;
  margin: 0;
}

/* Две колонки там, где место есть. Порог — по МЕСТУ: на телефоне и в узком
   окне колонки встают одна под другой, а не сжимаются до нечитаемых.
   `align-items:stretch` (README §«Каркас»): «Где работает» растягивается
   до высоты соседней карточки — грид сам выравнивает обе без правки их
   собственной высоты. */
.tvz-cols2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  align-items: stretch;
}

/* --- шапка контакта (§1) --------------------------------------------------
   Одна карточка: имя, одна строка меты, каналы связи. Аватар и два блока
   верификации старой версии убраны — статус и авторство свёрнуты в мету. */

.tvz-cc-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
}

.tvz-cc-head {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  flex-wrap: wrap;
}

.tvz-cc-id {
  min-width: 0;
  flex: 1 1 220px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tvz-cc-nm {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

/* Одна строка меты (§1.1): должность · клиент-ссылка | статус проверки —
   тихим текстом, а не пилюлей. Течёт текстом с переносом по словам, а не
   строгим флексом: разделители не должны повисать в конце строки одни. */
.tvz-cc-meta {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--c-mut);
}

.tvz-cc-meta__sep {
  color: var(--c-line-strong);
}

.tvz-cc-meta__org {
  font-weight: 500;
}

/* Статус проверки: текст, не пилюля. Тон приходит с сервера (`trust.tone`,
   B-112) — экран его печатает, а не выбирает. `ok`/`mut` не подсвечиваются
   вовсе (тот же приём, что у ленты участия карточки клиента, README §148:
   «цвет должен означать ровно одно — пора подтвердить»). Право есть —
   элемент кнопка: клик открывает полный чеклист подтверждения (макет 5d,
   `confirmDialog`), где отмечают, ЧТО именно проверили. */
.tvz-cc-verdict {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-mut);
  white-space: nowrap;
}

button.tvz-cc-verdict {
  cursor: pointer;
}

button.tvz-cc-verdict:hover {
  text-decoration: underline;
}

.tvz-cc-verdict--warn {
  color: var(--c-warn);
}

.tvz-cc-verdict--err {
  color: var(--c-err);
}

/* Кто подтвердил, внёс и правил последним — в `title` статуса (README §1.1),
   не отдельной строкой на экране: `verdictTitle` в cards.js. */

/* «отметить как актуальные» — текстовая кнопка, а не пилюля, и стоит только
   когда данные устарели (`card.is_stale`): сбрасывает дату без чеклиста. */
.tvz-cc-confirm {
  font-size: 11.5px;
}

.tvz-cc-head__end {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
}

/* --- каналы связи (§1.2) --------------------------------------------------
   Только заведённые — блоками со значением моноширинным и копированием
   (`channelBlock`, people.js); незаведённые — одной тихой строкой с
   текстовой кнопкой «добавить», а не тремя мёртвыми кнопками. */
.tvz-cc-chrow {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-top: 10px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-cc-ch {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 9px 0 10px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 9px;
  min-width: 0;
  max-width: 100%;
}

.tvz-cc-ch__i {
  flex: none;
  display: flex;
  color: var(--c-tx-4);
}

.tvz-cc-ch__v {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
}

a.tvz-cc-ch__v:hover {
  text-decoration: underline;
}

/* «Блок для письма» (`letterBlockButton`, people.js) — обычная ghost-кнопка,
   только пониже, чтобы не выбиваться из ряда блоков связи высотой 34px. */
.tvz-cc-chrow > .tvz-btn {
  height: 34px;
}

.tvz-cc-ch-missing {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--c-tx-4);
  flex-wrap: wrap;
}

/* «добавить» наследует размер строки — у `.tvz-linkbtn` свой (12.5px). */
.tvz-cc-ch-missing .tvz-linkbtn {
  font-size: inherit;
}

/* --- «За что отвечает» (хендофф контакта §2, П-42) ------------------------ */

/* Раздел справочника — своя цветная полоса-заголовок и тонированное тело
   (палитра `ROLE_GROUP_TINTS`, та же, что у карточки клиента, — переменные
   `--tint-*` только ЧИТАЮТСЯ здесь, см. врезку у `.tvz-ccard__group`).
   `.tvz-card--flat` уже несёт `overflow:hidden` — тонированный фон последней
   группы не вылезет за скругление карточки прямыми углами. */
.tvz-rrow__g {
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-rrow__g:last-child {
  border-bottom: none;
}
.tvz-rrow__gh {
  padding: 6px 14px;
  background: var(--tint-hd, var(--c-chip));
  border-top: 1px solid var(--tint-bd, var(--c-bd2));
  border-bottom: 1px solid var(--tint-bd, var(--c-bd2));
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tint-tx, var(--c-tx-2));
}
.tvz-rrow__gb {
  background: var(--tint-bg, transparent);
}
/* Тёмная тема: тела разделов красят фиксированный светлый `--tint-bg`
   (палитра не меняется по теме, см. врезку у `.tvz-ccard__group`), а имя
   роли — обычный `--c-tx`, который в тёмной теме светлеет. Светлый текст на
   светлой подложке нечитаем — живая находка при проверке тёмной темы.
   Полоса заголовка тон не теряет (у неё `--tint-tx` — свой фиксированный
   тёмный акцент, паре есть с чем контрастировать в любой теме), а тело
   в тёмной теме падает на обычный `--c-hover` вместо тонированной заливки. */
html[data-theme="dark"] .tvz-rrow__gb {
  background: var(--c-hover);
}

.tvz-rrow {
  padding: 7px 14px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22px;
  align-items: center;
  gap: 4px 10px;
}
.tvz-rrow:hover {
  background: var(--c-hover);
}
.tvz-rrow__n {
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Границы — второй строкой под названием роли (README §2): пилюля здесь
   была и убрана — не влезала в узкую колонку и обрезалась. */
.tvz-rrow__s {
  grid-row: 2;
  grid-column: 1;
  display: block;
  max-width: 100%;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--c-tx-4);
}
/* «По всей компании» — самый широкий охват, отмечен цветом (README §2). */
.tvz-rrow__s--company {
  color: var(--c-purple);
}
.tvz-rrow__x {
  width: 22px;
  height: 22px;
  border: none;
  background: none;
  border-radius: var(--rad-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-tx-4);
  cursor: pointer;
}
.tvz-rrow__x:hover {
  background: var(--c-errbg);
  color: var(--c-err);
}

/* --- модалка «Роли» (хендофф контакта §6, П-42) --------------------------- */
/* Своя подложка, а не системная `.tvz-modal-back`: у окна нет заголовка —
   поиск стоит прямо в шапке, а низ несёт сводку черновика вместо простого
   «Отмена/Сохранить» generic-модалки (README §6, «была на весь экран —
   ужата»). */
/* Модификатор вендорной подложки: цвет затемнения и позиционирование берутся
   у `.tvz-modal-back` дизайн-системы — своего rgba здесь быть не должно
   (ADR-0002, правило «цвета только из токенов»). Отличается лишь отступ:
   окно ролей высокое и прижимается ближе к верху. */
.tvz-rmodal-back {
  padding: 40px 16px;
  padding-top: 40px;
  overflow: auto;
}
.tvz-rmodal {
  width: 100%;
  max-width: 540px;
  background: var(--c-surface);
  border-radius: 14px;
  box-shadow: var(--shadow-e3);
  display: flex;
  flex-direction: column;
  color: var(--c-tx);
}

.tvz-rmodal__head {
  padding: 10px 12px;
  border-bottom: 1px solid var(--c-bd2);
  display: flex;
  align-items: center;
  gap: 8px;
}
.tvz-rmodal__searchbox {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 9px;
  color: var(--c-tx-4);
}
.tvz-rmodal__search {
  flex: 1;
  min-width: 0;
  height: auto;
  border: none;
  background: none;
  padding: 0;
  font-size: 12.5px;
  color: var(--c-tx);
  outline: none;
}
.tvz-rmodal__x {
  flex: none;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  border-radius: var(--rad-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-tx-4);
  cursor: pointer;
}
.tvz-rmodal__x:hover {
  background: var(--c-chip);
  color: var(--c-tx);
}

.tvz-rmodal__bounds {
  padding: 7px 12px;
  background: var(--c-hover);
  border-bottom: 1px solid var(--c-bd2);
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}
.tvz-rmodal__bl {
  flex: none;
  font-size: 11px;
  color: var(--c-tx-4);
}
.tvz-rmodal__seg {
  flex: none;
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--c-chip);
  border-radius: var(--rad);
}
.tvz-rmodal__segb {
  height: 24px;
  padding: 0 9px;
  border: none;
  border-radius: var(--rad-sm);
  cursor: pointer;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  background: transparent;
  color: var(--c-mut);
}
.tvz-rmodal__segb.is-active {
  background: var(--c-surface);
  color: var(--c-ac);
  box-shadow: var(--shadow-e1);
}
.tvz-rmodal__which {
  flex: 1;
  min-width: 150px;
  height: 26px;
  padding: 0 6px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 7px;
  font-size: 11.5px;
  color: var(--c-tx);
  outline: none;
}

/* Погашенный уровень границ (П-100). Гаснет он там, где выбирать НЕ ИЗ ЧЕГО:
   в окне «Новый клиент» площадок и юрлиц может не быть вовсе, потому что их
   заводят соседним шагом. Курсор при этом остаётся обычным, а не
   «запрещающим»: нажатие законно — оно называет причину. */
.tvz-rmodal__segb.is-off,
.tvz-rmodal__segb.is-off:hover {
  opacity: .45;
  color: var(--c-mut);
  background: transparent;
  box-shadow: none;
}
/* Причина словами, а не только подсказкой под курсором: на телефоне курсора
   нет вовсе, и погашенное без объяснения читается как «сломалось» (тот же
   довод, что у гейта визарда и у `fieldRefusal`). Пустая строка не занимает
   ни пикселя — в окне карточки гаснуть нечему. */
.tvz-rmodal__offwhy:not(:empty) {
  padding: 6px 12px;
  font-size: 11px;
  color: var(--c-tx-4);
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-rmodal__seatnote {
  padding: 6px 12px;
  font-size: 11px;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-rmodal__targetwarn:not(:empty) {
  padding: 8px 12px 0;
}

.tvz-rmodal__list {
  padding: 8px 8px 10px;
  max-height: 58vh;
  overflow: auto;
}
.tvz-rmodal__group {
  margin-top: 8px;
}
.tvz-rmodal__group:first-child {
  margin-top: 0;
}
.tvz-rmodal__grouphd {
  padding: 6px 9px;
  border-radius: 7px 7px 0 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  background: var(--tint-hd, var(--c-chip));
  color: var(--tint-tx, var(--c-tx-2));
}
.tvz-rmodal__groupbd {
  padding: 6px;
  border-radius: 0 0 8px 8px;
  background: var(--tint-bg, transparent);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(224px, 1fr));
  gap: 5px;
}
/* Тёмная тема: та же поправка контраста, что у `.tvz-rrow__gb` — не
   выбранная роль печатает обычный `--c-tx` (в тёмной теме — светлый) поверх
   фиксированно-светлой заливки `--tint-bg`, и без переопределения текст
   пропадает. `.is-on`/`.is-inherited` не затронуты: у них цвет и рамка —
   тот же `--tint-tx`, что и у заливки, пара всегда контрастна. */
html[data-theme="dark"] .tvz-rmodal__groupbd {
  background: var(--c-hover);
}
.tvz-rmodal__item {
  width: 100%;
  min-height: 30px;
  padding: 0 10px;
  border-radius: 8px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  color: var(--c-tx);
}
.tvz-rmodal__item:hover {
  background: var(--c-hover);
}
/* Выбрана в текущих границах — залита тоном раздела (README §6.3). */
.tvz-rmodal__item.is-on {
  border-color: var(--tint-tx, var(--c-ac));
  background: var(--tint-hd, var(--c-ac-tint));
  color: var(--tint-tx, var(--c-ac));
  font-weight: 600;
}
.tvz-rmodal__item.is-on:hover {
  background: var(--tint-hd, var(--c-ac-tint));
}
/* Досталась сверху — пунктир, не кликается (§6, п. 5: главное правило волны).
   Фона нет намеренно: залитая рамка спорила бы с «выбрана здесь». */
.tvz-rmodal__item.is-inherited {
  border-style: dashed;
  border-color: var(--tint-tx, var(--c-mut));
  color: var(--tint-tx, var(--c-mut));
  font-weight: 600;
  opacity: .75;
  cursor: default;
  background: transparent;
}
/* Отметка и подпись источника едут в разметке всегда (`roleBoard`), но за
   столом их работу делают заливка строки и подсказка под курсором — здесь
   они лишние. Гасим тут, включаем в шторке телефона (П-59, §5): раскладок
   две, разметка одна. */
.tvz-rmodal__box,
.tvz-rmodal__from {
  display: none;
}
/* Название — отдельный узел, но за столом остаётся строчным: обрезка
   многоточием держится на самой кнопке, и лишний блок её бы сломал
   (грабля §5: `text-overflow` не работает на flex-контейнере). */
.tvz-rmodal__nm {
  display: inline;
}

.tvz-rmodal__foot {
  padding: 9px 12px;
  border-top: 1px solid var(--c-bd2);
  background: var(--c-hover);
  border-radius: 0 0 14px 14px;
  display: flex;
  align-items: center;
  gap: 9px;
}
.tvz-rmodal__sum {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  color: var(--c-mut);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Высоты кнопок этого низа — 30px (README «Design Tokens»), не типовые 40. */
.tvz-rmodal__foot .tvz-btn {
  height: 30px;
  padding: 0 12px;
  font-size: 12.5px;
}
.tvz-rmodal__err {
  margin-bottom: 8px;
}

/* --- плотная сетка реквизитов (и она же — правка на месте) ---------------- */

.tvz-facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1px;
  background: var(--c-bd2);
}

.tvz-facts__c {
  background: var(--c-surface);
  padding: 9px 16px;
  min-width: 0;
}

.tvz-facts__c--wide {
  grid-column: 1 / -1;
}

.tvz-facts__k {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
  font-weight: 700;
}

.tvz-facts__v {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.tvz-facts__n {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--c-tx-2);
  overflow-wrap: anywhere;
}

/* Пустое поле в режиме правки — приглашение, а не ошибка: здесь это действие. */
.tvz-facts__e {
  color: var(--c-tx-4);
  font-weight: 500;
}

.tvz-facts__pen {
  flex: none;
  color: var(--c-tx-4);
  display: inline-flex;
}

/* Клетка, которую можно нажать, ВЫГЛЯДИТ нажимаемой.

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

   Обводка стоит ПОСТОЯННО у каждой правимой клетки, карандаш взят акцентным
   токеном, курсор — «нажать», а не «набрать текст»: набирать в закрытой
   клетке нечего, она открывается нажатием. Ринг внутренней тенью, а не
   `border`: рамка сдвинула бы содержимое на пиксель и разъехалась бы с
   соседями по сетке. */
.tvz-facts__c.is-edit {
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--c-ac-bd);
}

.tvz-facts__c.is-edit .tvz-facts__pen {
  color: var(--c-ac);
}

.tvz-facts__c.is-edit:hover,
.tvz-facts__c.is-edit:focus-visible {
  background: var(--c-ac-tint);
  box-shadow: inset 0 0 0 1px var(--c-ac);
  outline: none;
}

/* Шапка сетки в режиме правки — та же тональность, что у плашки режима:
   плашка обещает «нажмите на обведённое поле», и глаз обязан связать её
   с местом, где эти поля стоят. */
.tvz-card--flat.is-editing .tvz-panel__h {
  background: var(--c-ac-tint);
  border-bottom-color: var(--c-ac-bd);
}

.tvz-card--flat.is-editing .tvz-panel__t {
  color: var(--c-ac-d);
}

.tvz-facts__c.is-open {
  background: var(--c-sel);
  padding: 12px 16px;
}

.tvz-facts__ed {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 5px;
  flex-wrap: wrap;
}

.tvz-facts__in {
  flex: 1 1 200px;
  min-width: 0;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--c-ac);
  border-radius: var(--rad);
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  outline: none;
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

textarea.tvz-facts__in {
  height: auto;
  padding: 8px 12px;
  resize: vertical;
}

.tvz-facts__ed .tvz-btn {
  height: 36px;
  flex: none;
}

/* Плашка режима правки: меняете вы — видит вся команда. */
.tvz-editbar {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 10px 14px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad);
  background: var(--c-ac-tint);
}

.tvz-editbar .tvz-icon {
  flex: none;
  color: var(--c-ac);
}

.tvz-editbar__t {
  color: var(--c-ac-d);
  font-weight: 600;
}

/* Плашка говорит, что теперь можно, и текста в ней стало больше одной строки:
   без права занять строку целиком она сжималась бы в столбик из двух слов,
   а кнопка выхода уезжала бы за край. */
.tvz-editbar__n {
  color: var(--c-tx-2);
  font-size: var(--fz-sm);
  min-width: 0;
  flex: 1 1 320px;
}

.tvz-editbar__exit {
  margin-left: auto;
}

/* --- узор блока (кроме верхней карточки шапки), README §«Каркас» ---------- */

.tvz-blk__h {
  display: flex;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 9px 14px;
  background: var(--c-hover);
  border-bottom: 1px solid var(--c-bd);
}

.tvz-blk__t {
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.tvz-blk__n {
  color: var(--c-tx-4);
  font-size: 11.5px;
  min-width: 0;
}

.tvz-blk__end {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-blk__none {
  color: var(--c-mut);
  padding: 16px 14px 18px;
  margin: 0;
  text-align: center;
}

/* --- «Где работает» (§3) --------------------------------------------------
   Пары «подпись — значение», а не сетка правки: каналы сюда не едут (уже
   блоками в шапке), а «что важно помнить» растягивается до низа карточки,
   чтобы обе карточки ряда были равной высоты (`.tvz-cols2` — stretch). */
.tvz-cc-where {
  display: flex;
  flex-direction: column;
}

.tvz-cc-where__b {
  flex: 1;
  min-height: 0;
  padding: 6px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tvz-cc-fact {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  align-items: baseline;
  gap: 12px;
  padding: 6px 0;
  border-top: 1px solid var(--c-chip);
}

.tvz-cc-fact__l {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}

.tvz-cc-fact__v {
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.tvz-cc-memo-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-top: 8px;
  border-top: 1px solid var(--c-chip);
}

.tvz-cc-memo__l {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}

.tvz-cc-memo {
  width: 100%;
  flex: 1;
  min-height: 52px;
  padding: 7px 9px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 9px;
  font: inherit;
  font-size: var(--fz-sm);
  line-height: 1.45;
  color: var(--c-tx);
  outline: none;
  resize: vertical;
}

.tvz-cc-memo:focus {
  border-color: var(--c-ac);
  background: var(--c-surface);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

.tvz-cc-memo[readonly] {
  color: var(--c-tx-2);
  cursor: default;
}

/* --- «Участие в сделках» (§4) ---------------------------------------------
   Роль контакта В СДЕЛКЕ (пилюля `.tvz-badge`) — не роль из справочника:
   `главное лицо`/`участник`. Этап — та же пилюля, моноширинным. */
.tvz-deal-row {
  padding: 8px 14px;
  display: grid;
  /* Колонки бейджей — ФИКСИРОВАННОЙ ширины (слово владельца 05.08:
     «выровняй баджи столбиками»): auto давал рваные края — каждая строка
     мерила свои бейджи сама, и «участник» плясал вслед за длиной этапа.
     Ширины: роль до «представитель», этап до «Договор на рассмотрении». */
  grid-template-columns: minmax(0, 1fr) 118px 182px;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  border-top: 1px solid var(--c-bd2);
}

/* Бейдж занимает свою колонку целиком — ровные столбики, текст по центру. */
.tvz-deal-row > .tvz-badge {
  justify-self: stretch;
  justify-content: center;
}

.tvz-deal-row:hover {
  background: var(--c-hover);
}

.tvz-deal-row__main {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.tvz-deal-row__t {
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-deal-row__sub {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-badge--mono {
  font-family: var(--font-mono);
  font-size: 10px;
}

/* --- «История» (§5): разговоры, заметки и правки одной лентой ------------- */

.tvz-feed__r {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 14px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-feed__i {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--c-chip);
  color: var(--c-mut);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Значок ленты по типу записи (§5): звонок — акцентный тон, заметка —
   фиолетовый, правка — нейтральный (тот же нейтральный, что и база). */
.tvz-feed__i--talk {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-feed__i--note {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

.tvz-feed__b {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tvz-feed__top {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-feed__x {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx);
  line-height: 1.3;
}

.tvz-feed__at {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}

.tvz-feed__w {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}

.tvz-feed__body {
  font-size: var(--fz-sm);
  color: var(--c-tx-2);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

/* Узко — лента складывается, а не уезжает вбок: горизонтальной прокрутки
   на телефоне быть не должно, на этом уже ловили дважды. */
@media (max-width: 900px) {
  .tvz-cols2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

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

  .tvz-cc-nm {
    font-size: 17px;
  }

  .tvz-deal-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
  }

  .tvz-editbar__exit {
    margin-left: 0;
  }
}

/* Читаемость тёмной темы — по правилу файла: мелкий текст берёт токен на
   ступень контрастнее. Значения токенов не трогаются. */
html[data-theme="dark"] .tvz-feed__w,
html[data-theme="dark"] .tvz-feed__at,
html[data-theme="dark"] .tvz-zrow__n,
html[data-theme="dark"] .tvz-panel__n,
html[data-theme="dark"] .tvz-blk__n,
html[data-theme="dark"] .tvz-cc-fact__l,
html[data-theme="dark"] .tvz-cc-memo__l,
html[data-theme="dark"] .tvz-deal-row__sub,
html[data-theme="dark"] .tvz-cc-ch-missing,
html[data-theme="dark"] .tvz-facts__e {
  color: var(--c-tx-2);
}

/* ===========================================================================
   Карточка клиента 1c (П-15и): вид словами сервера, устройство плитками,
   матрица «роль × место». Вид (compact/dense) считает СЕРВЕР — экран печатает
   `view.label` и `view.reason` как есть и не решает сам.
   ======================================================================== */

/* Строка «какой это вид и почему» — печатается в обоих видах. */
.tvz-viewnote {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--c-tx-4);
}

/* --------------------------- Устройство клиента (плитки под юрлицом) ---- */

.tvz-struct__hint {
  margin: -8px 0 0;
  font-size: 12px;
  color: var(--c-tx-4);
}

/* Юрлицо — строка-разделитель: под ней лежат его площадки. */
.tvz-struct__le {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 0;
  margin-top: 14px;
  border-bottom: 1px solid var(--c-line-strong);
}

.tvz-struct__le .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

.tvz-struct__le-n {
  font-weight: 700;
  font-size: 14px;
}

.tvz-struct__inn {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-struct__sign {
  margin-left: auto;
  font-size: 11.5px;
  color: var(--c-tx-2);
}

.tvz-struct__sign .tvz-missing {
  font-size: 11.5px;
}

/* Плитки площадок: четыре в ряд — это и есть порог компактного вида. */
.tvz-tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-top: 10px;
}

.tvz-tile {
  border: 1px solid var(--c-bd);
  border-top: 3px solid var(--c-line-strong);
  border-radius: var(--rad);
  padding: 11px 12px;
  background: var(--c-bg);
  min-width: 0;
}

.tvz-tile--ok { border-top-color: var(--c-ok); }
.tvz-tile--warn { border-top-color: var(--c-warn); }
.tvz-tile--err { border-top-color: var(--c-err); }

.tvz-tile__t {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.tvz-tile__t .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

.tvz-tile__nm {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-tile__r {
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-tile__nrow {
  margin-top: 8px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.tvz-tile__n {
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 700;
  color: var(--c-tx);
}

.tvz-tile__nl {
  font-size: 11.5px;
  color: var(--c-tx-2);
}

.tvz-tile__orig {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  min-width: 0;
}

.tvz-tile__orig .tvz-badge {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ------------------------------------- матрица «роль × место» ----------- */

/* Шапка матрицы: пояснение слева, легенда справа. */
.tvz-mx-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: -6px 0 12px;
}

.tvz-mx-head__n {
  font-size: 12px;
  color: var(--c-tx-4);
  min-width: 0;
}

/* Поиск по матрице (B-124): строка над таблицей. Контейнер узкий нарочно —
   поле не растягивается на всю карточку и не спорит с легендой выше. */
.tvz-mx-find {
  margin: 0 0 8px;
}

.tvz-mx-find .tvz-search {
  max-width: 420px;
}

/* Счётчик «показано строк N из M» и пустой результат, называющий запрос
   (класс B-105): молчаливое сужение хуже отсутствия поиска. */
.tvz-mx-note {
  font-size: 12px;
  margin: 0 0 8px;
}

.tvz-mx-note:empty {
  display: none;
}

/* Легенда: три состояния клетки, слова из README 1c. */
.tvz-legend {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  font-size: 11.5px;
  color: var(--c-tx-4);
  margin-left: auto;
}

.tvz-legend__it {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}

.tvz-legend__sq {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  display: inline-block;
  flex: none;
}

.tvz-legend__sq--ok { background: var(--c-ok); }
.tvz-legend__sq--warn { background: var(--c-warn); }
.tvz-legend__sq--err { background: var(--c-err); }

/* Широкая сетка прокручивается ВНУТРИ себя: сама страница на телефоне
   вбок не ездит — на этом уже ловили. */
.tvz-mx-wrap {
  overflow-x: auto;
  margin-top: 4px;
}

/* Просветы фона = линии сетки; число столбцов приходит осью с сервера,
   поэтому колонки задаются переменной, а не отдельным классом на число. */
.tvz-mx {
  display: grid;
  grid-template-columns: 200px repeat(var(--mx-cols, 4), minmax(150px, 1fr));
  gap: 1px;
  background: var(--c-bd);
  border: 1px solid var(--c-bd);
  min-width: min-content;
}

.tvz-mx__h {
  background: var(--c-head);
  padding: 9px 10px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mx__rh {
  background: var(--c-surface);
  padding: 10px;
  min-width: 0;
}

.tvz-mx__rh--key {
  box-shadow: inset 3px 0 0 var(--c-ac);
}

.tvz-mx__role {
  font-weight: 600;
  font-size: 12.5px;
}

.tvz-mx__note {
  display: block;
  font-size: 11px;
  color: var(--c-tx-4);
  margin-top: 1px;
}

.tvz-mx__c {
  background: var(--c-surface);
  padding: 9px 10px;
  min-width: 0;
  display: flex;
  align-items: center;
}

.tvz-mx__c--gap {
  background: var(--c-errbg);
}

/* Клетка с человеком — кнопка (Гр-7): ведёт к его строке в «Людях по ролям».
   Сброс — только того, что дорисовывает элемент button; сама клетка обязана
   выглядеть как соседние, отличаясь лишь откликом на курсор и фокус. */
.tvz-mx__c--btn {
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-mx__c--btn:hover,
.tvz-mx__c--btn:focus-visible {
  background: var(--c-head);
}

.tvz-mx__p {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.tvz-mx__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  display: inline-block;
  background: var(--c-line-strong);
}

.tvz-mx__dot--ok { background: var(--c-ok); }
.tvz-mx__dot--warn { background: var(--c-warn); }
.tvz-mx__dot--err { background: var(--c-err); }

.tvz-mx__pm {
  min-width: 0;
}

.tvz-mx__nm {
  display: block;
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mx__ph {
  display: block;
  font-size: 10.5px;
  color: var(--c-tx-4);
  font-family: var(--font-mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mx__gap {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--c-err);
  font-size: 11.5px;
  font-weight: 600;
}

.tvz-mx__gap .tvz-icon {
  flex: none;
}

.tvz-mx__dash {
  color: var(--c-tx-4);
  font-size: 11.5px;
}

/* ------------------- оглавление-якоря плотного вида (находка Осиповой) --- */

/* До «Юрлиц» на длинной карточке не долистывают: блок стоял на одиннадцатой
   тысяче пикселей. Плотному виду — якоря сверху, компактному это чинят
   плитки. Сами кнопки — те же .tvz-pill, что в оглавлении ролей. */
.tvz-anchors {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-top: 10px;
}

.tvz-anchors__l {
  font-size: 11.5px;
  color: var(--c-tx-4);
  margin-right: 2px;
}

/* Телефон: плитки в два столбца, матрица прокручивается внутри себя. */
@media (max-width: 900px) {
  .tvz-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .tvz-struct__sign {
    margin-left: 0;
    flex: 1 1 100%;
  }
}

/* Тёмная тема: мелкий текст на ступень контрастнее — правило файла. */
html[data-theme="dark"] .tvz-viewnote,
html[data-theme="dark"] .tvz-tile__r,
html[data-theme="dark"] .tvz-tile__nl,
html[data-theme="dark"] .tvz-struct__hint,
html[data-theme="dark"] .tvz-struct__inn,
html[data-theme="dark"] .tvz-mx__ph,
html[data-theme="dark"] .tvz-mx__note,
html[data-theme="dark"] .tvz-mx-head__n,
html[data-theme="dark"] .tvz-mx__dash,
html[data-theme="dark"] .tvz-legend,
html[data-theme="dark"] .tvz-anchors__l {
  color: var(--c-tx-2);
}


/* ============================================================================
   Роли и права (Н-4): двухпанельный конструктор в Администрировании.
   Только токены; на телефоне (≤720) колонки складываются в столбец.
   ============================================================================ */
.tvz-rp{display:grid;grid-template-columns:minmax(240px,320px) 1fr;gap:var(--gap);align-items:start}
.tvz-rp__list{display:flex;flex-direction:column;gap:6px;min-width:0}
.tvz-rp__role{display:flex;align-items:flex-start;gap:6px;padding:10px 12px;border:1px solid var(--c-bd);border-radius:var(--rad-lg);background:var(--c-surface);cursor:pointer}
.tvz-rp__role:hover{background:var(--c-hover)}
.tvz-rp__role.is-active{border-color:var(--c-ac-bd);background:var(--c-sel)}
.tvz-rp__role-main{flex:1;min-width:0}
.tvz-rp__role-name{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.tvz-rp__role-sub{font-size:var(--fz-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tvz-rp__role-acts{flex:none}
.tvz-rp__new{margin-top:4px}
.tvz-rp__editor{border:1px solid var(--c-bd);border-radius:var(--rad-lg);background:var(--c-surface);padding:14px;display:flex;flex-direction:column;gap:12px;min-width:0}
.tvz-rp__head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.tvz-rp__sum{font-size:var(--fz-sm);white-space:nowrap}
.tvz-rp__bar{display:flex;align-items:center;gap:var(--gap);flex-wrap:wrap}
.tvz-rp__bar .tvz-search{flex:1;min-width:160px}
.tvz-rp__copy{display:flex;align-items:center;gap:var(--gap);flex-wrap:wrap}
.tvz-rp__copy .tvz-select{min-width:180px}
.tvz-rp__groups{display:flex;flex-direction:column;gap:10px}
.tvz-rp__group{border:1px solid var(--c-bd2);border-radius:var(--rad);padding:10px 12px}
.tvz-rp__group-h{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.tvz-rp__cnt{font-size:var(--fz-sm)}
.tvz-rp__group-acts{margin-left:auto;display:flex;gap:4px}
.tvz-rp__items{display:flex;flex-direction:column;gap:8px}
.tvz-rp__foot{display:flex;justify-content:flex-end}
@media (max-width:720px){
  .tvz-rp{grid-template-columns:1fr}
}

/* ============================================================================
   Справка (П-33, D-84): руководство пользователя из шапки.
   Тот же узор, что оверлей поиска: подложка системная `.tvz-modal-back`,
   свой класс добавляет геометрию. Только токены; телефон — во всю ширину.
   ============================================================================ */
.tvz-help-back{padding:70px 16px 16px}
.tvz-help{width:min(760px,100%);max-height:min(860px,calc(100vh - 100px));display:flex;flex-direction:column;overflow:hidden;background:var(--c-surface);border:1px solid var(--c-bd);border-radius:var(--rad-lg);box-shadow:var(--shadow-e2)}
.tvz-help__top{display:flex;align-items:center;gap:10px;height:56px;padding:0 16px;border-bottom:1px solid var(--c-bd);flex:none}
.tvz-help__top>.tvz-icon{color:var(--c-tx-4);flex:none}
.tvz-help__ttl{flex:1;font-weight:700;font-size:15px;color:var(--c-tx)}
.tvz-help__x{flex:none;width:28px;height:28px;border:0;border-radius:var(--rad);background:transparent;color:var(--c-tx-4);font-size:20px;line-height:1;cursor:pointer}
.tvz-help__x:hover{background:var(--c-hover);color:var(--c-tx)}
/* Разделы — пилюлями в одну прокручиваемую строку: на телефоне список
   разделов не должен съедать высоту, отведённую тексту. */
.tvz-help__nav{padding:10px 16px;border-bottom:1px solid var(--c-bd2);flex:none;overflow-x:auto}
.tvz-help__nav .tvz-pills{flex-wrap:nowrap;width:max-content}
.tvz-help__body{flex:1;overflow-y:auto;padding:4px 20px 20px}
.tvz-help__idle{padding:22px 0;color:var(--c-tx-4);font-size:var(--fz-sm);line-height:1.5}
/* Текст руководства. Кегль крупнее интерфейсного: справку ЧИТАЮТ, а не
   сканируют, и на телефоне 13px для сплошного текста мелковаты. */
.tvz-help__md{font-size:14px;line-height:1.6;color:var(--c-tx);max-width:640px}
.tvz-help__md h1{font-size:19px;margin:16px 0 6px}
.tvz-help__md h2{font-size:15px;margin:18px 0 6px}
.tvz-help__md h3{font-size:14px;margin:14px 0 4px}
.tvz-help__md p{margin:8px 0}
.tvz-help__md ul,.tvz-help__md ol{margin:8px 0;padding-left:22px}
.tvz-help__md li{margin:4px 0}
.tvz-help__md code{font-family:var(--font-mono);font-size:12px;background:var(--c-chip);border-radius:4px;padding:1px 5px}
/* Врезка «Кстати» — заметная, но не тревожная: это фишка, а не ошибка.
   Тихая карточка системным узором (тонкая рамка + подложка-тинт), без
   толстого цветного канта сбоку. */
.tvz-help__aside{margin:12px 0;padding:10px 14px;border:1px solid var(--c-ac-bd);border-radius:var(--rad);background:var(--c-ac-tint);color:var(--c-tx)}
/* Условие приведено к канону ветки (П-59, раздел 3): узкое окно И ГРУБЫЙ
   УКАЗАТЕЛЬ — то же, по чему делятся модалки и оверлей поиска. Раньше стоял
   один `max-width: 720px`, и справка занимала весь экран по ШИРИНЕ: узкое
   окно за столом теряло и рамку окна, и способ закрыть его щелчком мимо. */
@media (max-width: 900px) and (pointer: coarse){
  .tvz-help-back{padding:0}
  .tvz-help{width:100%;max-height:100vh;height:100vh;border-radius:0;border:0}
}

/* ---------------------------------------------------------------- шапка */
/* Шапка убрана в высоту (слово владельца 02.08: «прибери шапку, сделай
   компактней»). Она стоит НА КАЖДОМ экране и ничего не рассказывает —
   каждый её лишний пиксель отнят у списка дел, ради которого экран открыт.
   Правки только размерные: состав, порядок и цвета остаются как есть. */
.tvz-top {
  /* `min-height` вендорной системы (48px) перебивается здесь намеренно:
     высоту задаёт содержимое, а не круглое число из общего каркаса.
     Вендор-файл не правим (ADR-0002). */
  min-height: 0;
  height: 40px;
  padding: 0 16px;
  gap: 8px;
}

/* Действия — у правого края. Держало их там растянутое поле поиска, а когда
   поле убрали (04.08), группа съехала вплотную к названию страницы: полоса
   читалась как сбитая в левый угол. Теперь её прижимает своё автополе, и от
   соседей это больше не зависит. */
.tvz-top__right {
  margin-left: auto;
}

.tvz-top__title {
  font-size: 15px;
}

/* Пустой слот страницы не занимает ширины (П-54, владелец 04.08: «шапка
   раздута, там много воздуха»).

   Дефект был не в высоте — её убрали 02.08, — а в раскладке. Слот
   (`#tvz-top-slot`) держит в дизайн-системе `flex: 1` и `margin-left: auto`,
   и, пока в него никто ничего не положил, он всё равно растягивал середину:
   на 1280px пустое место посередине занимало 332px — треть полосы. Читалось
   это как разорванная шапка: название слева, поле у правого края, между ними
   ничьё поле.

   `display: none` вместо `flex: 0` — намеренно: слот с нулевым ростом всё
   равно участвует в `gap` полосы, и лишний шаг оставался бы виден. Правило
   отменяет прежнюю телефонную заплатку (`.tvz-top__slot:empty { flex: 0 }`
   в медиа-блоке выше) — она лечила ту же беду, но только на узком экране. */
.tvz-top__slot:empty {
  display: none;
}

/* Один ритм полосы: название слева, поиск по центру своей шириной, действия
   справа. Раньше поле несло `flex: 1` с `margin-left: auto` и жалось к
   правому краю, деля остаток строки с пустым слотом. Равные автополя ставят
   его по центру свободного места, а `flex-basis` даёт ему СВОЮ ширину:
   поле, растянутое во всю строку, читается как поле ввода документа, а не
   как поиск (потолок 420px остаётся с правки 02.08). */
.tvz-top__find {
  height: 30px;
  flex: 0 1 380px;
  max-width: 420px;
  margin-left: auto;
  margin-right: auto;
  padding: 0 10px;
  font-size: var(--fz-sm);
}

.tvz-top__find .tvz-icon {
  width: 15px;
  height: 15px;
}

/* Экран, у которого есть СВОЙ поиск, гасит глобальный (П-54, владелец 04.08:
   «вот это окно поиска, как будто оно не везде нужно, где-то оно
   дублируется»).

   На `/#/search` два поля стояли друг под другом с одной и той же подписью
   «Клиент, площадка, фамилия, телефон…», но вели себя по-разному: верхнее
   открывало оверлей поверх экрана, нижнее сужало выдачу под собой. Человек
   видит два одинаковых поля и не знает, в какое печатать.

   Экран говорит о себе САМ — никаких списков имён экранов и разбора адреса
   по регулярке. Признаков объявления два, и оба — разметка:

   * `.tvz-sfield` — собственное поле запроса ПО БАЗЕ (поиск, `search.js`).
     Локальные фильтры экранов сюда не входят и не должны: поле «ФИО,
     должность, телефон» на карточке клиента ищет внутри одного клиента,
     и глобальный поиск рядом с ним не дубль, а другой вопрос;
   * непустой слот шапки (`#tvz-top-slot`, `pageLayout({ search })`) — экран
     положил своё поле прямо в полосу.

   Состояния правило не несёт: ушли с экрана — разметка сменилась, поле
   вернулось само. Тот же приём, что у узкой телефонной шапки
   (`.tvz-app:has(.tvz-phead)` выше по файлу), и по той же причине —
   объявление, которое надо СНИМАТЬ, рано или поздно забудут снять. */
.tvz-main:has(.tvz-sfield) .tvz-top__find,
.tvz-top:has(.tvz-top__slot:not(:empty)) .tvz-top__find {
  display: none;
}

/* Заголовок дня — второй ярус той же шапки. 22px на «Сегодня» рядом с
   15px названия раздела спорили за первенство; теперь ярус один по весу,
   а размер отдан строке дел, которая и есть содержание экрана. */
.tvz-day__head h2 {
  font-size: 17px;
}

.tvz-day__head {
  gap: 8px;
}

/* Строка «что смотрим — что заводим» (02.08). Потоки слева, «Поставить
   задачу» прижата вправо: до правки кнопка занимала собственный ярус
   в тулбаре страницы, и между шапкой и первым делом шли три полосы
   подряд — шапка, кнопка, потоки. Теперь ярус один. */
.tvz-day__line {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  width: 100%;
}

.tvz-day__line .tvz-day__flows {
  flex: 0 1 auto;
  min-width: 0;
}

.tvz-day__add {
  margin-left: auto;
  flex: none;
}

/* На телефоне кнопка уходит под потоки во всю ширину: прижимать её вправо
   там, где строка и так переносится, значит спрятать её в угол. */
@media (max-width: 900px) {
  .tvz-day__add {
    margin-left: 0;
    width: 100%;
    justify-content: center;
  }
}

/* Выбор файла (П-36): настоящий <input type="file"> нужен для диалога
   выбора, но его вид системный и в дизайн-систему не ложится. Прячем сам
   элемент, нажатие по нему делает наша кнопка — то есть одно нажатие
   человека, а не два. Атрибут hidden здесь ненадёжен: правило вида для
   input в дизайн-системе перебивает его по специфичности. */
.tvz-hidden{display:none !important}
/* --- Выдача поиска сеткой карточек (хендофф владельца, «Клиенты и люди») ---

   Три беды одного экрана, названные владельцем на живом просмотре:

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

   Ответ: карточка в сетке (разная плотность — имя крупно, числа тихо), одна
   кнопка «Фильтры» со счётчиком и чипами снятия, масштаб клиента и ведущий
   менеджер прямо в карточке.

   Как везде в этом файле — только геометрия и ВЫБОР токена. Своих цветов
   нет: значения палитры живут в апстриме (ADR-0002), тени берутся готовыми
   (`--shadow-e1`…`--shadow-e3`), потому что записать тень своими руками —
   это записать своё `rgba`, то есть свой цвет. */

/* Колонка выдачи шире общей `--crm-col` (1080): сетка карточек шагает по
   316 px, и лишние 100 px — это не «воздуха побольше», а третья карточка
   в ряду на большом мониторе. Мера из хендоффа; остальным экранам общая
   колонка не меняется. */
.tvz-content > .tvz-page--search {
  max-width: 1180px;
}

/* Страница растёт вместе с выдачей, а тело её не зажато высотой экрана —
   и это не вкус, а условие липкой панели. `position:sticky` держится только
   внутри своего блока-контейнера: пока тело страницы было ростом с экран
   (`flex:1; min-height:0` каркаса), панель уезжала вверх на первом же
   экране прокрутки. Замер до правки: при прокрутке на 2010 px верх панели
   оказывался на −1430. Скроллит по-прежнему область контента целиком —
   своих скроллов у выдачи нет. */
.tvz-page--search {
  height: auto;
  min-height: 100%;
}

.tvz-page--search .tvz-page__body {
  flex: none;
}

/* --- панель запроса ------------------------------------------------------ */

/* Липкая: экран скроллится целиком (внутренних скроллов у выдачи нет), и
   поле с фильтрами обязано оставаться под рукой на любой глубине списка.
   Фон свой, непрозрачный — иначе карточки просвечивают сквозь панель. */
/* Верхнее поле области контента отдано самой панели. Пока поле оставалось
   у контейнера, между шапкой и приклеившейся панелью светилась полоса, и
   сквозь неё было видно уезжающие вверх карточки — панель выглядела как
   вырезанная из страницы. Отдать поле панели работает при любой ширине:
   у телефона поле контейнера другое, а «своё» у панели одно. */
.tvz-content:has(> .tvz-page--search) {
  padding-top: 0;
}

.tvz-sbar {
  position: sticky;
  top: 0;
  z-index: 15;
  background: var(--c-bg);
  padding-top: 12px;
  padding-bottom: 8px;
  flex: none;
}

.tvz-sbar__box {
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: 12px;
  box-shadow: var(--shadow-e1);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Ряд поля и кнопки фильтров. `overflow` тут не задаётся намеренно: поповер
   фильтров висит абсолютом от кнопки, и любое `hidden` его обрежет. */
.tvz-sbar__row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-sfield {
  flex: 1 1 240px;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  background: var(--c-hover);
  transition: border-color .12s, background .12s;
}

.tvz-sfield:focus-within {
  border-color: var(--c-ac);
  background: var(--c-surface);
}

.tvz-sfield > .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

/* Поле — общий `searchInput` (тот же дебаунс 250 мс, что и у оверлея), но
   рамка, фон и лупа у него теперь снаружи: два комплекта рамок в одном поле
   читались бы как поле внутри поля. */
.tvz-sfield__in.tvz-search {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  background-image: none;
  outline: none;
  font-size: 13.5px;
  color: var(--c-tx);
}

/* Кольцо фокуса у поля СНАРУЖИ, на рамке `.tvz-sfield`: своё кольцо инпута
   рисовало прямоугольник внутри прямоугольника — «поле в поле». */
.tvz-sfield__in.tvz-search:focus {
  box-shadow: none;
}

.tvz-sfield__b {
  flex: none;
  width: 20px;
  height: 20px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-sm);
  background: var(--c-surface);
  color: var(--c-tx-4);
  cursor: pointer;
}

.tvz-sfield__b:hover {
  color: var(--c-tx);
  border-color: var(--c-line-strong);
}

/* Крестик сброса запроса — заливкой без рамки: он снимает набранное, а не
   открывает что-то, и не должен читаться как вторая кнопка-«окошко». */
.tvz-sfield__x {
  border-color: transparent;
  background: var(--c-chip);
  color: var(--c-mut);
}

.tvz-sfield__x[hidden] {
  display: none;
}

/* --- кнопка «Фильтры» и её поповер --------------------------------------- */

.tvz-sflt {
  position: relative;
  flex: none;
}

.tvz-sflt__btn {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  background: var(--c-surface);
  color: var(--c-tx-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, border-color .12s, color .12s;
}

.tvz-sflt__btn:hover {
  border-color: var(--c-line-strong);
  color: var(--c-tx);
}

/* Включённые фильтры видны по самой кнопке — это половина ответа на B-105;
   вторая половина (какие именно) стоит чипами ниже. */
.tvz-sflt__btn.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-sflt__btn .tvz-icon {
  opacity: .7;
}

/* Счётчик. Пустой не рисуется вовсе: кружок с пустотой внутри читается как
   поломка, а не как «фильтров нет». */
.tvz-sflt__n {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--rad-pill);
  background: var(--c-ac);
  /* Текст на акцентной подложке — токеном поверхности: в светлой теме это
     белый, в тёмной — тёмный на светло-синем. Жёсткий белый читаем один раз
     из двух (тот же приём, что у аватара в подвале сайдбара). */
  color: var(--c-surface);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tvz-sflt__n:empty {
  display: none;
}

.tvz-sflt__pop {
  position: absolute;
  top: 44px;
  right: 0;
  z-index: 30;
  width: 330px;
  max-width: 88vw;
  background: var(--c-surface);
  border: 1px solid var(--c-line-strong);
  border-radius: 12px;
  box-shadow: var(--shadow-e3);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Тот же поповер на мобильной шапке (`mountMobile`): кнопка фильтров там
   40px, а не 38px, и стоит в первом ряду шапки — поповер садится чуть ниже. */
.tvz-sflt__pop--m {
  top: 48px;
}

.tvz-sflt__f {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.tvz-sflt__k {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}

/* Контрол поповера. `background-color`, а не сокращение `background`: у селекта
   стрелка нарисована фоновой картинкой самой дизайн-системы, и сокращение
   стирало её вместе с цветом — контрол переставал выглядеть выбором. */
.tvz-sflt__s {
  width: 100%;
  min-width: 0;
  height: 34px;
  padding-left: 8px;
  border: 1px solid var(--c-bd);
  border-radius: 9px;
  background-color: var(--c-hover);
  color: var(--c-tx);
  font-size: 12.5px;
}

/* Место под системную стрелку остаётся тем же, что у селектов везде. */
select.tvz-sflt__s {
  padding-right: 32px;
}

/* Должность — обычное поле: лупа общего `searchInput` тут лишняя, рядом
   и так стоит главное поле поиска со своей лупой. */
input.tvz-sflt__s {
  padding-right: 8px;
  background-image: none;
}

.tvz-sflt__acts {
  display: flex;
  gap: 8px;
  padding-top: 2px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-sflt__acts .tvz-btn {
  flex: 1;
  justify-content: center;
  height: 32px;
}

/* --- чипы включённых фильтров (B-105) ------------------------------------ */

.tvz-schips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}

.tvz-schips[hidden] {
  display: none;
}

.tvz-schip {
  height: 24px;
  padding: 0 6px 0 10px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad-pill);
  background: var(--c-ac-tint);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-ac);
  cursor: pointer;
  white-space: nowrap;
}

.tvz-schip:hover {
  border-color: var(--c-ac);
}

.tvz-schip__x {
  display: inline-flex;
  opacity: .7;
}

.tvz-schips__all {
  border: 0;
  background: none;
  padding: 0 4px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-mut);
  cursor: pointer;
}

.tvz-schips__all:hover {
  color: var(--c-tx);
  text-decoration: underline;
}

/* Подсказка «что понимает поиск» — за кнопкой, а не строкой навсегда. */
.tvz-shint {
  margin: 0;
  padding: 8px 10px;
  background: var(--c-hover);
  border: 1px solid var(--c-bd2);
  border-radius: 9px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--c-mut);
}

/* --- вкладки-пилюли ------------------------------------------------------ */

.tvz-stabs {
  display: flex;
}

/* Вариант общих вкладок, а не второй их экземпляр: разметка и счётчики
   остаются системными (`tabs()`), меняется только вид — пилюля вместо
   подчёркнутого таб-бара. */
.tvz-tabs--pill {
  width: 100%;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  border-bottom: 0;
}

.tvz-tabs--pill .tvz-tab {
  height: 30px;
  margin: 0;
  padding: 0 6px 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-pill);
  background: var(--c-surface);
  color: var(--c-tx-2);
  font-size: 12.5px;
}

.tvz-tabs--pill .tvz-tab.is-active {
  background: var(--c-ac);
  border-color: var(--c-ac);
  color: var(--c-surface);
}

.tvz-tabs--pill .tvz-tab__c {
  min-width: 22px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
}

.tvz-tabs--pill .tvz-tab.is-active .tvz-tab__c {
  background: var(--c-ac-d);
  color: var(--c-surface);
}

/* Счётчик показанного. Стоит в том же ряду, что вкладки: «сколько всего»
   говорит вкладка, «сколько видно» — эта подпись, и врозь они читаются
   как спор двух чисел. */
.tvz-sshown {
  margin-left: auto;
  padding-left: 8px;
  font-size: 11px;
  color: var(--c-tx-4);
  white-space: nowrap;
}

/* --- плашка частичного совпадения ---------------------------------------- */

.tvz-spartial {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--c-warn);
  border-radius: var(--rad-lg);
  background: var(--c-warnbg);
  color: var(--c-warn);
}

.tvz-spartial > .tvz-icon {
  flex: none;
  margin-top: 1px;
}

.tvz-spartial__t {
  flex: 1;
  font-size: 11.5px;
  line-height: 1.45;
}

.tvz-spartial .tvz-btn {
  flex: none;
}

/* --- сетка карточек ------------------------------------------------------ */

.tvz-sout {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  min-height: 0;
}

/* --- таблица выдачи (П-46) ------------------------------------------------ */
/*
   Владелец: «эти представления надо делать таблицей, потому что карточка —
   неудобно это визуально воспринимать. Таблица: есть сортировка, расписать
   подробности». Обёртка несёт `overflow-x: auto` как СТРАХОВКУ, а не как
   основной приём узкого экрана (правило 4 постановки): на узком экране часть
   колонок скрыта (см. `.tvz-col-*` ниже), и таблица целиком помещается без
   прокрутки на телефоне; прокрутка остаётся только на случай длинного имени
   или адреса, которые сама верстка не предвидит.
*/
.tvz-stable-wrap {
  overflow-x: auto;
}

.tvz-stable {
  /* `.tvz-table` вендора уже даёт рамку, скругление и hover на строке —
     здесь только то, что специфично для этой таблицы.

     `table-layout: fixed` — намеренно, и вместе с явной шириной у КАЖДОЙ
     колонки, кроме одной (имя): без явной ширины «Роли» или «Связь» —
     колонки с переменным числом тегов и длинными строками без пробелов
     (email) — при авто-раскладке браузер считает их «естественную» ширину
     по содержимому и в погоне за ней вытягивает таблицу за пределы окна.
     С фиксированной раскладкой колонка не может вырасти шире отведённого:
     содержимое переносится внутри неё (`overflow-wrap` ниже), а не толкает
     соседей и не наплывает на них. */
  table-layout: fixed;
}

/* Строка и шапка — 54 / 34px (хендофф поиска, правило 1): «долго искать
   глазами: длинные одинаковые строки» лечилось ровно этим числом, и высота
   держится ЯВНО — иначе двухстрочная ячейка масштаба или связи снова
   растянула бы строку, как было у карточек до этой волны. */
.tvz-stable th {
  height: 34px;
  padding: 0;
}

.tvz-stable td {
  height: 54px;
  padding: 0 12px;
  overflow: hidden;
  vertical-align: middle;
}

/* Разница между двумя таблицами выдачи («Клиенты» и «Контакты») живёт ЦЕЛИКОМ
   в именах колонок ниже: наборы не пересекаются ни одним именем, и ширина
   с порогом скрытия попадают ровно в свою таблицу сами. Модификатора на самом
   `<table>` (`.tvz-stable--clients` / `--people`) поэтому нет и не нужно:
   правил у него не было бы никаких, а класс без правил — тот самый молчаливо
   неоформленный кусок экрана, ради которого стоит conformance-тест
   «класс есть в разметке, но не объявлен» (найдено параллельной волной,
   fix-red-gate). Такой модификатор понадобится только в день, когда две
   таблицы разделят ИМЯ колонки при разной ширине.

   Колонки таблицы «Клиенты» (хендофф поиска, «Таблица клиентов»): «Клиент» —
   единственная без явной ширины, ей достаётся весь остаток (`table-layout:
   fixed` выше). Числовые колонки — в px, как в прототипе (150/140/96);
   «Регион» и «Ведёт» — в % от оставшейся ширины. */
.tvz-col-region { width: 24%; }
/* 150px у прототипа были тесны трём парам «число + подпись» разом (у клиента
   сети «человек» — трёхзначное число), и ширину подняли до 220px, чтобы
   подпись не резалась молча. Со значками вместо подписей (04.08) три пары
   влезают в 130px даже с трёхзначными числами — остаток отдан имени клиента,
   которому его всегда не хватало. */
.tvz-col-scale { width: 130px; }
.tvz-col-deals { width: 140px; }
.tvz-col-touch { width: 96px; }
.tvz-col-owner { width: 14%; }

/* Колонки таблицы «Контакты» (хендофф поиска, «Таблица контактов»):
   «Контакт» — единственная без явной ширины, и остаток достаётся ей.
   Остальным поэтому назначено ровно столько, сколько нужно им самим:
   имя человека — то, ради чего строку читают, и обрезанное «Балашов Борис
   Дмит…» делает всю строку бесполезной (слово владельца, 04.08). Роли и
   так свёрнуты до двух пилюль с «+N», клиенту хватает 18% на название с
   площадкой во второй строке. */
.tvz-col-client { width: 18%; }
.tvz-col-connection { width: 19%; }
.tvz-col-roles { width: 21%; }
.tvz-col-checked { width: 92px; }

/* «Роли» и «Связь» переносят содержимое внутри отведённой ширины, а не
   растягивают колонку: у контакта бывает пять ролей, а email — одно «слово»
   без пробелов, которое иначе раздвинуло бы колонку само по себе (безопасно
   ИМЕННО при фиксированной раскладке: под авто-раскладкой `anywhere`
   наоборот схлопывал бы колонку к ширине одного символа, гоняясь за
   минимальным содержимым, — эта ловушка и стояла здесь до фиксации). */
.tvz-col-roles,
.tvz-col-connection {
  overflow-wrap: anywhere;
}

.tvz-col-checked {
  text-align: right;
}

/* Кнопка-заголовок занимает всю ячейку: попадать нужно по всему `<th>`,
   а не по узкой подписи внутри него. Высота 34px — как у самой шапки: без
   неё кнопка держалась на паддинге и расходилась со строкой при переносе
   текста заголовка на телефоне (не здесь — там своя разметка, но приём
   общий для обеих таблиц экрана).
   ВАЖНО: `display:flex` здесь стоит на КНОПКЕ/СПАНЕ ВНУТРИ `<th>`, никогда на
   самом `<th>`/`<td>`: явный `display` поверх ячейки таблицы снимает с нег
   роль `table-cell`, и браузер вытесняет её из ряда — соседние заголовки
   съезжают друг на друга (ловилось на сверке: «Связь» и «Роли» встали
   одна над другой вместо соседних колонок). Ячейка остаётся обычным
   `table-cell`, а всю раскладку содержимого несёт этот внутренний элемент. */
.tvz-sth {
  width: 100%;
  height: 34px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 12px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--c-tx-4);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
}

/* Заголовок без сортировки — тот же СПАН-приём, что у кнопки сортировки
   (см. предупреждение выше): `<th>` остаётся `table-cell`, флекс и отступы —
   на `.tvz-th-plain` внутри него, теми же значениями, что у `.tvz-sth`,
   иначе подписи «Масштаб» и «Клиент» разъехались бы по горизонтали. */
.tvz-th-plain {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 12px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--c-tx-4);
  white-space: nowrap;
  overflow: hidden;
}

.tvz-sth:hover {
  color: var(--c-tx-2);
}

.tvz-sth.is-active {
  color: var(--c-ac);
}

.tvz-sth .tvz-icon {
  flex: none;
  opacity: .7;
}

.tvz-stable__gocol {
  width: 32px;
}

/* Тонкий заголовок группы («Мои» / «Остальные», Маргарита №2) в списке
   клиентов без запроса — своей строкой, но НЕ строкой клиента: ниже 54px
   и не кликабельна (`clientGroupRow`, search.js). Тот же язык, что у
   заголовка группы ролей карточки клиента (`.tvz-ccard__group-t`) — тихая
   капитель, а не абзац. */
.tvz-stable__grow td {
  height: 26px;
  padding: 0 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-tx-2);
  background: var(--c-chip);
}

/* Та же подпись в списке клиентов НА ТЕЛЕФОНЕ (М3-5): за столом её сделали,
   на карточках забыли — и на телефоне граница «мои/остальные» снова читалась
   перескоком алфавита. Слова и вес те же, что в таблице; фона нет — между
   карточками он читался бы ещё одной карточкой, а не подписью над ними. */
.tvz-mcards__grow {
  padding: 10px 2px 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-tx-2);
}

/* Строка — кнопка целиком (правило 3 постановки: клик по строке, не только
   по ссылке справа). Курсор и подсветка те же, что у карточки прежней волны. */
.tvz-srow {
  cursor: pointer;
  transition: background .12s;
}

.tvz-srow:hover {
  background: var(--c-hover);
}

.tvz-srow:focus-visible {
  outline: 2px solid var(--c-ac);
  outline-offset: -2px;
}

.tvz-stable__name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.tvz-stable__nmrow {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.tvz-stable__nm {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-stable__sub {
  font-size: 11.5px;
  color: var(--c-mut);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-stable__ownnote {
  align-self: flex-start;
}

/* Ноль людей — беда, а не размер (та же наука, что у прежней карточки). */
.tvz-stable__n--bad {
  color: var(--c-err);
  font-weight: 600;
}

.tvz-stable__go {
  color: var(--c-mut);
  text-align: center;
}

/* Узкий экран: таблица не режется слепой горизонтальной прокруткой (правило
   4 постановки). Решение — приоритетные колонки, а не строка-карточка:
   таблица остаётся таблицей на любой ширине, и сортировка (весь смысл этой
   волны) не пропадает вместе с колонками. Скрытые колонки не теряют слова —
   они переезжают в подсказку строки (`title`, см. `objectHint`/`personHint`
   в `search.js`), а не пропадают молча.
   Порог — тот же, что у формы одноколоночной сетки прежней волны (макет
   5b): ширина, на которой строка перестаёт умещать шесть колонок читаемо. */
/* Узких версий этой таблицы больше нет (волна П-53): ниже
   `$narrow-breakpoint` (см. `search.js`, `NARROW_BREAKPOINT`) экран целиком
   переходит на мобильный язык «Сделок на телефоне» — карточки вместо
   таблицы, свои классы (`.tvz-msearch-*` ниже). Таблица живёт только на
   широком экране, и резать её колонки медиазапросом больше незачем. */

/* Масштаб — числа со значками в ряд (хендофф поиска, колонка «Масштаб»). */
.tvz-col-scale {
  white-space: nowrap;
}

.tvz-scalenum {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-right: 9px;
  white-space: nowrap;
}

.tvz-scalenum__n {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -.01em;
}

/* Значок величины вместо слова («юрлиц», «площадок», «человек» ушли в
   `title` числа). Тон — тот же приглушённый, что был у подписи: значок
   объясняет число, а не спорит с ним за внимание. */
.tvz-scalenum__i {
  color: var(--c-tx-4);
  flex: none;
}

/* «В работе» — сделки в работе и сумма разово, друг под другом.
   ВАЖНО: флекс — на `.tvz-dealsblock`, СПАНЕ внутри `<td>`, не на самой ячейке
   (см. предупреждение у `.tvz-sth` про `display` поверх `table-cell`). */
.tvz-dealsblock {
  display: flex;
  flex-direction: column;
  gap: 0;
  justify-content: center;
  min-width: 0;
}

.tvz-dealsline {
  font-size: 12.5px;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-dealsline__sum {
  font-size: 11px;
  color: var(--c-tx-4);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* «Касались» — цвет ТОЛЬКО при проблеме (хендофф поиска): предупреждение
   от 14 дней, тревога от 30, иначе обычный приглушённый текст. */
.tvz-touch {
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--c-tx-4);
}

.tvz-touch--warn {
  color: var(--c-warn);
}

.tvz-touch--err {
  color: var(--c-err);
}

/* --- «Связь» (таблица контактов): телефон и почта — ДВЕ строки --------- */

/* Флекс — на `.tvz-connblock`, СПАНЕ внутри `<td>` (см. предупреждение у
   `.tvz-sth`), не на самой ячейке `.tvz-col-connection` (та несёт только
   ширину и перенос длинных строк без пробелов). */
.tvz-connblock {
  display: flex;
  flex-direction: column;
  gap: 0;
  justify-content: center;
  min-width: 0;
}

.tvz-connblock .mono {
  font-size: 12.5px;
  color: var(--c-tx-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-conn__mail {
  font-size: 11px !important;
  color: var(--c-tx-4) !important;
}

/* Заглушка словом — ОБЫЧНЫМ шрифтом (осторожность №2 постановки): моно
   только для цифр и адресов, иначе в колонке скачут шрифты между строками
   с номером и строками без него. */
.tvz-conn__missing {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-err);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-conn__partner {
  font-size: 11px;
  font-weight: 600;
  color: var(--c-warn);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Запрет прямого общения гасит ОБЕ строки колонки (не только вторую, как
   в дизайн-прототипе) — рабочий номер рядом с «нельзя» является приглашением
   его набрать (S-1a-1, симуляция 001-А). Единственное осознанное
   расхождение с прототипом в этой колонке. */
.tvz-conn__blocked {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-err);
  line-height: 1.3;
}

/* --- «Роли» (таблица контактов): до двух пилюль, цвет по группе --------- */

/* Флекс — на `.tvz-rolesblock`, СПАНЕ внутри `<td>` (см. предупреждение у
   `.tvz-sth`). `align-items:flex-start` — здесь, а не `stretch`: иначе
   первая пилюля растягивается на всю колонку и читается как баг (найдено
   при сверке с прототипом хендоффа). */
.tvz-rolesblock {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  max-width: 100%;
}

/* `display:block`, НЕ `inline-flex` — на flex-контейнере `text-overflow:
   ellipsis` не работает, и длинное название роли резалось бы мид-словом
   (найдено при сверке с прототипом хендоффа). */
.tvz-rolepill {
  max-width: 100%;
  height: 18px;
  padding: 0 8px;
  border-radius: var(--rad-pill);
  display: block;
  line-height: 18px;
  font-size: 10.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-rolepills__row2 {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  max-width: 100%;
}

.tvz-rolepills__row2 .tvz-rolepill {
  flex: 0 1 auto;
  min-width: 0;
}

.tvz-rolepill__more {
  flex: none;
  height: 18px;
  padding: 0 7px;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-mut);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
}

/* Цвет пилюли — по группе роли (та же палитра, что цвет вида объекта и
   плашка карточки клиента; закреплена за ключом группы, поэтому при
   фильтрации не «прыгает»). Токены — существующие пары фон/текст дизайн-
   системы (design.css — вендор, свой hex здесь не заводится); где прототип
   просит оттенок без готовой пары (площадка, партнёрские), используется
   ближайшая по смыслу существующая пара, а не новый цвет. */
/* Основа модификатора — сам по себе не встречается (пилюля всегда несёт
   конкретный оттенок), но разбор классов (`test_conformance
   .test_ui_uses_only_classes_that_exist_in_the_design_system`) видит его как
   отдельный токен: строка вида `tvz-rolepill--${r.tint}` после подстановки
   переменной читается как «tvz-rolepill--» + пробел. Объявлен явно, без
   своих правил — реальный цвет всегда несёт один из оттенков ниже. */
.tvz-rolepill-- {
}

.tvz-rolepill--site {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-rolepill--tech {
  background: var(--c-cyanbg);
  color: var(--c-cyan);
}

.tvz-rolepill--legal {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

.tvz-rolepill--acc {
  background: var(--c-okbg);
  color: var(--c-ok-d);
}

.tvz-rolepill--owner {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

/* --- «Проверено» (таблица контактов): слова домена, без формы бейджа ---- */

.tvz-col-checked {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-tx-4);
  line-height: 1.3;
  white-space: normal;
  overflow: hidden;
}

.tvz-checked--warn {
  color: var(--c-warn);
}

.tvz-checked--err {
  color: var(--c-err);
}

/* --- мобильный экран поиска (хендофф поиска, часть B; правила мобильной
   ветки — README «Сделки на телефоне» §7) ----------------------------------

   Не адаптив таблицы, а отдельный экран в своём языке: шапка в три ряда,
   лента чипов, карточки вместо таблицы (`search.js`, `mountMobile`,
   `objectCardMobile`/`personCardMobile`). Порог — `NARROW_BREAKPOINT` в
   `search.js` (900px), тот же, что у остального узкого экрана шелла
   (`.tvz-content{padding:12px}` здесь же, строка ~857) и у мобильных сделок
   (`deals.js`, `isNarrow`).

   Шапка бежит вровень с краями экрана (`margin` компенсирует боковой
   отступ `.tvz-content`) — тем же приёмом, каким узкая шапка карточки
   (`.tvz-phead`) уже бежит вровень в остальном приложении; верх компенсировать
   не нужно — `.tvz-content:has(> .tvz-page--search){padding-top:0}` уже
   обнулил его для этого экрана на любой ширине. */

.tvz-msearch {
  margin: 0 -12px 8px;
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-bd);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  z-index: 15;
}

.tvz-msearch__title {
  padding: 4px 12px 8px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.tvz-msearch__tcol {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.tvz-msearch__t {
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}

.tvz-msearch__shown {
  font-size: 11.5px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-msearch__fltwrap {
  position: relative;
  flex: none;
}

.tvz-msearch__fltbtn {
  position: relative;
  flex: none;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--rad-lg);
  background: var(--c-chip);
  color: var(--c-tx-2);
  cursor: pointer;
}

.tvz-msearch__fltbtn.is-active {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-msearch__fltn {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: var(--rad-pill);
  background: var(--c-ac);
  color: var(--c-surface);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-msearch__fltn[hidden] {
  display: none;
}

.tvz-msearch__searchrow {
  padding: 0 12px 8px;
}

.tvz-msearch__field {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  background: var(--c-hover);
  transition: border-color .12s, background .12s;
}

.tvz-msearch__field:focus-within {
  border-color: var(--c-ac);
  background: var(--c-surface);
}

.tvz-msearch__field > .tvz-icon {
  color: var(--c-tx-4);
  flex: none;
}

.tvz-msearch__in {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  background-image: none;
  outline: none;
  font-size: 14px;
  color: var(--c-tx);
}

.tvz-msearch__in:focus {
  box-shadow: none;
}

.tvz-msearch__x {
  flex: none;
  width: 24px;
  height: 24px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-mut);
  cursor: pointer;
}

.tvz-msearch__x[hidden] {
  display: none;
}

/* Лента чипов: вкладки и снятие фильтров в ОДНОЙ прокручиваемой строке
   (хендофф §B) — скроллбар спрятан тем же приёмом, что у мобильной ленты
   вкладок остальной части приложения. */
.tvz-mchips {
  display: flex;
  gap: 6px;
  padding: 0 12px 9px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tvz-mchips::-webkit-scrollbar {
  display: none;
}

.tvz-mtabs {
  display: contents;
}

.tvz-mtabs .tvz-tab {
  flex: none;
  height: 34px;
  margin: 0;
  padding: 0 8px 0 13px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-pill);
  background: var(--c-surface);
  color: var(--c-tx-2);
  font-size: 13px;
  white-space: nowrap;
}

.tvz-mtabs .tvz-tab.is-active {
  background: var(--c-ac);
  border-color: var(--c-ac);
  color: var(--c-surface);
}

.tvz-mtabs .tvz-tab__c {
  min-width: 20px;
  height: 18px;
  font-family: var(--font-mono);
  font-size: 11px;
}

.tvz-mtabs .tvz-tab.is-active .tvz-tab__c {
  /* Токен, не rgba: тот же приём, что у пилюль десктопа
     (`.tvz-tabs--pill .tvz-tab.is-active .tvz-tab__c`) — сплошной тёмный
     акцент вместо полупрозрачной заливки поверх него. */
  background: var(--c-ac-d);
  color: var(--c-surface);
}

.tvz-mchip {
  flex: none;
  height: 34px;
  padding: 0 8px 0 12px;
  border: 1px solid var(--c-ac-bd);
  border-radius: var(--rad-pill);
  background: var(--c-ac-tint);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-ac);
  cursor: pointer;
  white-space: nowrap;
}

.tvz-mchip__x {
  display: inline-flex;
  opacity: .7;
}

/* --- результаты: карточки вместо таблицы ---------------------------------- */

.tvz-mresults {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  min-height: 0;
}

.tvz-mcards {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tvz-mcard {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 14px;
  box-shadow: var(--shadow-e1);
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.tvz-mcard__top {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
}

.tvz-mcard__name {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mcard__chain {
  width: 100%;
  font-size: 11.5px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mcard__nums {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  width: 100%;
}

.tvz-mcard__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
  padding-top: 7px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-mcard__ini {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-tx-2);
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-mcard__owner {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--c-tx-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-mcard__dealspill {
  flex: none;
  height: 20px;
  padding: 0 9px;
  border-radius: var(--rad-pill);
  background: var(--c-okbg);
  color: var(--c-ok-d);
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.tvz-mcard__dealspill.is-empty {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

/* --- карточка контакта: верх (переход) + звонок/письмо -------------------- */

.tvz-mcard--contact {
  padding: 11px 12px 0;
  overflow: hidden;
  cursor: default;
}

.tvz-mcard__ctop {
  width: 100%;
  border: 0;
  background: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.tvz-mcard__toprow {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  min-width: 0;
}

.tvz-mcard__toprow .tvz-mcard__name {
  flex: 1;
}

.tvz-mcard__checked {
  flex: none;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--c-tx-4);
  white-space: nowrap;
}

.tvz-mcard__roles {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  min-width: 0;
}

.tvz-mcard__flags {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  width: 100%;
}

.tvz-mflag {
  flex: none;
  height: 20px;
  padding: 0 9px;
  border-radius: var(--rad-pill);
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
}

.tvz-mflag--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-mflag--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

/* Звонок и письмо — ДВЕ кнопки 44px во всю ширину карточки (осторожность
   №1 постановки: это осознанная разница с десктопом, там единственное
   действие строки — переход). `margin:0 -12px` бежит вровень с краями
   карточки (у неё самой `padding: 11px 12px 0`), разделитель — 1px между. */
.tvz-mconn {
  display: flex;
  margin: 0 -12px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-mconn__act {
  flex: 1;
  min-width: 0;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-ac);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
}

.tvz-mconn__act:not(:first-child) {
  color: var(--c-tx-2);
}

.tvz-mconn__act.is-disabled {
  color: var(--c-tx-4);
  pointer-events: none;
}

.tvz-mconn__act--warn {
  color: var(--c-warn);
}

.tvz-mconn__div {
  flex: none;
  width: 1px;
  background: var(--c-bd2);
}

.tvz-mconn__act--off {
  flex: 1;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx-4);
}

/* Вид объекта — плашкой перед названием в таблице «Клиенты» (B-30): `id=1`
   бывает и клиентом, и юрлицом, и площадкой, и различать их на глаз больше
   не нужно. Имя класса — из хендоффа поиска (П-38): таблица П-46 заменила
   разметку карточки, но не саму плашку вида, и заводить ей второе имя ради
   смены разметки вокруг значило бы плодить синонимы без причины. */
.tvz-scard__kind {
  flex: none;
  height: 19px;
  padding: 0 8px;
  border-radius: var(--rad-sm);
  display: inline-flex;
  align-items: center;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  background: var(--c-chip);
  color: var(--c-mut);
}

.tvz-scard__kind--client {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-scard__kind--legal {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

.tvz-scard__kind--site {
  background: var(--c-cyanbg);
  color: var(--c-cyan);
}

.tvz-smore {
  display: flex;
  justify-content: center;
}

/* --- пустая выдача -------------------------------------------------------- */

.tvz-sempty {
  padding: 44px 16px;
  text-align: center;
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: 12px;
}

.tvz-sempty__t {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 4px;
}

.tvz-sempty__p {
  max-width: 460px;
  margin: 0 auto;
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-mut);
}

.tvz-sempty .tvz-btn {
  margin-top: 12px;
}

/* Два хода разом (B-143): «Снять фильтр» и переход на соседнюю вкладку
   бывают нужны вместе — пустая вкладка под фильтром, у соседа не пусто.
   `.tvz-sempty .tvz-btn` выше уже даёт каждой кнопке свой отступ сверху,
   тут только ряд и просвет между ними. */
.tvz-sempty__acts {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
}

/* --- «Нашлось в хронике» -------------------------------------------------- */

.tvz-snotes {
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: 12px;
  overflow: hidden;
}

.tvz-snotes__h {
  width: 100%;
  padding: 9px 12px;
  border: 0;
  background: var(--c-surface);
  display: flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-snotes__h:hover {
  background: var(--c-hover);
}

.tvz-snotes__t {
  font-size: 12.5px;
  font-weight: 600;
}

.tvz-snotes__n {
  height: 18px;
  padding: 0 7px;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-mut);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
}

.tvz-snotes__go {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--c-ac);
}

.tvz-snotes__b {
  padding: 0 8px 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tvz-snotes__b[hidden] {
  display: none;
}

.tvz-snote {
  padding: 8px 10px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  background: var(--c-hover);
  display: flex;
  flex-direction: column;
  gap: 2px;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.tvz-snote:hover {
  background: var(--c-surface);
  border-color: var(--c-ac-bd);
}

.tvz-snote__h {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-snote__w {
  font-size: 12px;
  font-weight: 600;
}

.tvz-snote__at {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--c-tx-4);
}

.tvz-snote__b {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--c-tx-2);
}

/* Тёмная тема: тот же приём, что и для остального мелкого текста выше —
   выцветающий на тёмном фоне текст берёт токен на ступень контрастнее.
   Значения токенов не трогаются, меняется ВЫБОР. */
html[data-theme="dark"] .tvz-snote__at,
html[data-theme="dark"] .tvz-sshown,
html[data-theme="dark"] .tvz-shint,
html[data-theme="dark"] .tvz-sempty__p {
  color: var(--c-tx-2);
}

/* Плашка вида на тёмном: тинты семантики темнее фона карточки, и текст
   на них берёт светлый конец пары — иначе слово тонет в подложке. */
html[data-theme="dark"] .tvz-scard__kind {
  color: var(--c-tx);
}

/* Активная вкладка-пилюля: на тёмной теме `--c-surface` — почти чёрный,
   и белым по синему он быть перестаёт. Берём самый светлый текст темы. */
html[data-theme="dark"] .tvz-tabs--pill .tvz-tab.is-active,
html[data-theme="dark"] .tvz-tabs--pill .tvz-tab.is-active .tvz-tab__c,
html[data-theme="dark"] .tvz-sflt__n {
  color: var(--c-tx);
}

/* =========================================================================
   П-39 — карточка сделки: шапка, «Работа по сделке», нижний ряд.
   Довод перебивки вендор-зоны design.css: своих классов там нет — весь
   раздел ниже заведён здесь, токены везде var(--c-*), эмодзи нет.
   ========================================================================= */

/* ---------------------------------------------------------- 1. Шапка ---- */

/* Корень шапки: вертикальный шаг между тремя видимыми блоками (описание /
   цены / стороны, П-40 §1), рядом действий и полосой воронки. */
.tvz-dealhead {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px 14px;
}

/* Блок 1.1 «Описание»: название+бейджи+кому·где·что слева, пилюля источника
   денег справа. */
.tvz-dealhead__desc {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}

.tvz-dealhead__main {
  flex: 1 1 260px;
  min-width: 260px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.tvz-dealhead__titlerow {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
}

/* Бейдж тишины стоит РЯДОМ с названием (спека П-39, §1.1) — не этажом ниже,
   где его ставит .tvz-head__tags на прочих карточках (правило то же, отступ свой). */
.tvz-dealhead__titlerow .tvz-head__tags {
  margin-top: 0;
}

.tvz-dealhead__brief {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--c-tx-2);
}

.tvz-dealhead__client {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--c-ac);
}

.tvz-dealhead__client:hover {
  text-decoration: underline;
}

/* Стороны — своя карточка-блок (П-40, §1.3): своя рамка, а не строка внутри
   описания — владелец правил именно это («деньги важнее» → стороны ушли
   ниже цен, отдельным блоком, а не хвостом описания). */
.tvz-dealhead__sidesbox {
  display: flex;
  align-items: center;
  gap: 8px 16px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border: 1px solid var(--c-bd);
  border-radius: 11px;
  font-size: 12px;
  color: var(--c-mut);
}

/* Сторона сделки — «мы» или «клиент» (П-39). Класс НАЗЫВАЕТСЯ ПОЛНО
   (`tvz-dside`), а не `tvz-side`: коротким именем в оболочке зовётся сам
   сайдбар, и это правило, стоящее ниже по файлу, перебивало ему
   `display:grid` из мобильной ветки — на узком экране меню разъезжалось
   лентой шире экрана, логотип налезал на пункты, а «Мой участок»
   и «Справочники» уходили за край. Столкновение имён в общем
   пространстве классов — не мелочь, а поломка чужого экрана. */
.tvz-dside {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.tvz-dside b {
  font-weight: 600;
  color: var(--c-tx);
}

.tvz-dside__tag {
  height: 19px;
  padding: 0 8px;
  border-radius: var(--rad-pill);
  font-size: 10.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  flex: none;
  white-space: nowrap;
}

.tvz-dside__tag--we {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-dside__tag--client {
  background: var(--c-chip);
  color: var(--c-mut);
}

/* Блок цен шапки (П-40, §1.2) — своя карточка: тихая подпись валюты один
   раз, плоский ряд статей и справа две цветные плитки итогов. */
.tvz-dealhead__moneybox {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: 11px;
  box-shadow: var(--shadow-e1);
}

.tvz-dealhead__moneynote {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--c-tx-4);
}

.tvz-dealhead__moneyrow {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-money-items {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  gap: 4px 18px;
  flex-wrap: wrap;
}

.tvz-money-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.tvz-money-item__k {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--c-tx-4);
  white-space: nowrap;
}

.tvz-money-item__v {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--c-tx);
}

.tvz-money-totals {
  flex: none;
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-money-total {
  min-width: 0;
  padding: 6px 12px;
  border-radius: 9px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  border: 1px solid transparent;
}

.tvz-money-total--once {
  background: var(--c-ac-tint);
  border-color: var(--c-ac-bd);
}

.tvz-money-total--year {
  background: var(--c-okbg);
  border-color: var(--c-ok);
}

.tvz-money-total__k {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tvz-money-total--once .tvz-money-total__k,
.tvz-money-total--once .tvz-money-total__v {
  color: var(--c-ac);
}

.tvz-money-total--year .tvz-money-total__k,
.tvz-money-total--year .tvz-money-total__v {
  color: var(--c-ok-d);
}

.tvz-money-total__v {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Полоса воронки — тонкие сегменты, а не плитки с названиями (П-40, §1.5):
   на реальной воронке из 10 этапов названия обрезались. Название и
   длительность живут в `title`; читаемая подпись — рядом, текстом. */
.tvz-dealhead__funnelrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 2px;
}

.tvz-funnel {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: stretch;
  gap: 3px;
}

/* Цвет этапа (П-50). Сервер называет ПОЛОЖЕНИЕ этапа в воронке
   (`work-1`…`work-9`, `won`, `lost`), а какой это цвет — решает экран: тон
   считается по позиции, и вставка этапа в середину предсказуемо сдвигает
   хвост. Девять ступеней одного сине-фиолетового хода: чем дальше по
   воронке, тем насыщеннее. Исходы красятся не по счёту, а по смыслу —
   закрыта зелёным, не состоялась красным.

   Литералы здесь законны ровно потому, что получают ИМЯ: покрасить ими
   элемент по-прежнему нельзя (правило конформанса). Готового ряда из девяти
   различимых ступеней в палитре Works Light нет — она про сигналы, а не про
   шкалу, — и заводить его приходится здесь. */
:root {
  --c-stage-work-1: #5aa9dd;
  --c-stage-work-2: #3f8ed6;
  --c-stage-work-3: #3a6fd0;
  --c-stage-work-4: #4a56cc;
  --c-stage-work-5: #6446c8;
  --c-stage-work-6: #7f3fc4;
  --c-stage-work-7: #9a37bd;
  --c-stage-work-8: #b331ad;
  --c-stage-work-9: #c62d94;
  --c-stage-won: #2e9e6a;
  --c-stage-lost: #c63b2f;
}

html[data-theme="dark"] {
  /* Тот же ход, поднятый по светлоте: на тёмной подложке нижние ступени
     исходной шкалы сливались с фоном полосы. */
  --c-stage-work-1: #6fbcea;
  --c-stage-work-2: #5aa4e6;
  --c-stage-work-3: #6b8ee6;
  --c-stage-work-4: #7d7ee6;
  --c-stage-work-5: #8f74e6;
  --c-stage-work-6: #a56ee2;
  --c-stage-work-7: #bb68d8;
  --c-stage-work-8: #cf65c8;
  --c-stage-work-9: #de63ac;
  --c-stage-won: #4cbb87;
  --c-stage-lost: #e0685c;
}

.tvz-funnel__seg {
  flex: 1;
  min-width: 0;
  height: 6px;
  border-radius: var(--rad-pill);
  /* `--stage-tint` ставит разметка по токену сервера; не назвали — этап
     будущий, и полоса остаётся нейтральной. */
  background: var(--stage-tint, var(--c-bd));
}

.tvz-funnel__seg.is-passed {
  opacity: .45;
}

.tvz-funnel__note {
  flex: none;
  font-size: 11.5px;
  color: var(--c-mut);
  white-space: nowrap;
}

/* Поповер «Цена и затраты» (П-40, §5.2): сегмент-контрол авто/вручную,
   поле на статью, сноска. */
.tvz-pricepop {
  width: 300px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.tvz-pricepop__body {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

/* ---------------------------------------------- 2. «Работа по сделке» --- */

/* Карточка без своего паддинга: секции несут его сами и делятся 1px-чертой —
   так граница секции ложится край-в-край с карточкой, а не отступает. */
.tvz-work {
  padding: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.tvz-work__section {
  padding: 12px 14px;
}

.tvz-work__section + .tvz-work__section {
  border-top: 1px solid var(--c-bd2);
}

.tvz-work__filters {
  background: var(--c-hover);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.tvz-work__head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}

.tvz-work__k {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}

.tvz-work__head .tvz-btn {
  margin-left: auto;
}

/* 2.1 Задачи — точка-статус, название, срок, «Сделано» (та же кнопка
   у всех строк: разнобой синей/белой владелец назвал шумом). */
.tvz-work-task {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  padding: 5px 0;
}

.tvz-work-task + .tvz-work-task {
  border-top: 1px solid var(--c-chip);
}

.tvz-work-task__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: var(--rad-pill);
  background: var(--c-line-strong);
}

.tvz-work-task__dot.is-err {
  background: var(--c-err);
}

.tvz-work-task__dot.is-warn {
  background: var(--c-warn);
}

/* Название и вторая строка «кому и с чем» (П-60, п. 5) — колонкой: имя
   исполнителя и приложенный файл рядом с названием в одну нерасторжимую
   строку не влезают и выталкивали бы срок за край карточки. */
.tvz-work-task__main {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.tvz-work-task__name {
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-work-task.is-first .tvz-work-task__name {
  font-size: 14px;
}

/* Кому поставлена и что приложено. Пустая строка не занимает высоты:
   у задачи на себе без файла второй строке сказать нечего. */
.tvz-work-task__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  min-width: 0;
}

.tvz-work-task__meta:empty {
  display: none;
}

.tvz-work-task__whom {
  font-size: 12px;
  color: var(--c-mut);
}

.tvz-work-task__file {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  color: var(--c-ac);
  font-size: 12px;
  text-decoration: none;
}

.tvz-work-task__file > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-work-task__file:hover {
  text-decoration: underline;
}

.tvz-work-task__due {
  flex: none;
}

.tvz-work-task .tvz-btn {
  flex: none;
  margin-left: auto;
}

/* 2.2 Форма записи — заметная, всегда открытая. */
.tvz-chip-tab {
  height: 27px;
  padding: 0 11px;
  border-radius: var(--rad-pill);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

/* Заливка сплошным акцентом (как в прототипе) потребовала бы белого текста
   поверх токена --c-ac — а белого токена в дизайн-системе нет и не будет
   (правило «только токены», ADR-0002). Берём готовый паттерн активной
   пилюли из design.css (.tvz-fpill.is-active): тинт + акцентный текст —
   тот же приём, что везде на этом экране (фильтры ленты, чипы сторон). */
.tvz-chip-tab.is-active {
  border-color: var(--c-ac-bd);
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-composer {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tvz-composer__tabs {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}

.tvz-composer__box {
  border: 1px solid var(--c-ac-bd);
  background: var(--c-surface);
  border-radius: var(--rad-lg);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  box-shadow: var(--shadow-e1);
}

.tvz-composer__box:focus-within {
  border-color: var(--c-ac);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

.tvz-composer__box textarea {
  width: 100%;
  min-height: 64px;
  border: none;
  background: none;
  outline: none;
  resize: vertical;
  font: inherit;
  font-size: 13px;
  line-height: 1.5;
  color: var(--c-tx);
}

.tvz-composer__pending {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.tvz-composer__pending:empty {
  display: none;
}

.tvz-composer__chip {
  height: 26px;
  padding: 0 9px 0 7px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: var(--rad-sm);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--c-tx-2);
}

.tvz-composer__chip button {
  display: flex;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  color: var(--c-tx-4);
}

.tvz-composer__chip button:hover {
  color: var(--c-err);
}

.tvz-composer__foot {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.tvz-composer__foot .tvz-btn--primary {
  margin-left: auto;
}

/* 2.3 Фильтры ленты. */
.tvz-feed-filter {
  height: 26px;
  padding: 0 6px 0 10px;
  border-radius: var(--rad-pill);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

.tvz-feed-filter.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-feed-filter__n {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--c-tx-4);
}

.tvz-feed-filter.is-active .tvz-feed-filter__n {
  color: var(--c-ac);
}

.tvz-work__filters-note {
  margin-left: auto;
  font-size: 11px;
  color: var(--c-tx-4);
  white-space: nowrap;
}

/* 2.4 Лента — вертикальная линия времени. */
.tvz-timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.tvz-timeline__row {
  display: flex;
  gap: 10px;
  min-width: 0;
}

.tvz-timeline__rail {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 26px;
}

.tvz-timeline__ico {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: var(--rad-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-timeline__ico--comment { background: var(--c-chip); color: var(--c-mut); }
.tvz-timeline__ico--call { background: var(--c-okbg); color: var(--c-ok-d); }
.tvz-timeline__ico--email { background: var(--c-ac-tint); color: var(--c-ac); }
.tvz-timeline__ico--meeting { background: var(--c-purplebg); color: var(--c-purple); }
.tvz-timeline__ico--file { background: var(--c-cyanbg); color: var(--c-cyan); }
.tvz-timeline__ico--stage { background: var(--c-chip); color: var(--c-tx-4); }
.tvz-timeline__ico--task { background: var(--c-errbg); color: var(--c-err); }

.tvz-timeline__line {
  flex: 1;
  width: 1px;
  background: var(--c-bd);
}

.tvz-timeline__line.is-last {
  background: transparent;
}

.tvz-timeline__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: 14px;
}

.tvz-timeline__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.tvz-timeline__title {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
}

.tvz-timeline__time {
  margin-left: auto;
  font-size: 10.5px;
  color: var(--c-tx-4);
  white-space: nowrap;
}

.tvz-timeline__text {
  font-size: 12.5px;
  color: var(--c-tx-2);
  line-height: 1.5;
}

.tvz-timeline__text--bubble {
  padding: 7px 10px;
  background: var(--c-hover);
  border: 1px solid var(--c-bd2);
  border-radius: var(--rad-sm);
}

.tvz-timeline__files {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.tvz-timeline__file {
  height: 26px;
  padding: 0 4px 0 7px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: var(--rad-sm);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--c-tx-2);
}

/* Файл в ленте (П-39-хвост): чипа сама — ссылка «скачать», рядом — крестик
   «снять». Карточки «Файлы» отдельным блоком больше нет — оба хода переехали
   сюда, к записи, которой файл принадлежит. */
.tvz-timeline__file-dl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: inherit;
  text-decoration: none;
}

.tvz-timeline__file-dl:hover {
  color: var(--c-ac);
}

.tvz-timeline__file-x {
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--c-tx-4);
  border-radius: var(--rad-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tvz-timeline__file-x:hover {
  background: var(--c-hover);
  color: var(--c-err);
}

.tvz-timeline__who {
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-work__more {
  width: 100%;
  height: 30px;
}

/* ------------------------------------------------------- 3. Нижний ряд --- */

/* Ряд из ДВУХ карточек (П-40, §3): варианты · круг. Было три (П-39) —
   Реквизиты ушли из ряда, полосой на всю ширину под ним (`.tvz-dealfacts`). */
.tvz-dealbottom {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 10px;
  align-items: stretch;
}

/* Реквизиты — полоса на всю ширину, пары в 2–3 колонки (П-40, §3.3),
   не одна колонка `.tvz-kv` подряд, как в ряду прежней тройки (П-39).
   Специфичность селектора обязана перебить `.tvz-fold.is-open .tvz-fold__b`
   (display:block, design.css) — три класса на якоре, а не два, иначе
   грид молча проигрывает более специфичному правилу вендора. */
.tvz-dealfacts.is-open .tvz-fold__b {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0 24px;
}

/* 3.1 Варианты предложения. */
.tvz-offers {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

/* Шапка блока с подписью и действием (владелец 03.08: «сделай нормальные
   зазоры между блоками»). Раньше заголовок, подпись и кнопка стояли одной
   переносимой строкой: в узкой колонке кнопка сваливалась вниз и висела
   у правого края, а высота шапки прыгала от блока к блоку — отсюда рваные
   зазоры. Теперь порядок задан, а не оставлен на волю переноса: заголовок
   и действие ВСЕГДА в первой строке (действие справа), подпись — своей
   строкой под ними. Строки разведены `row-gap`, одинаковым для всех
   блоков ряда. */
.tvz-offers h3,
.tvz-card > h3:has(.tvz-circle__note) {
  margin-bottom: 0;
  display: flex;
  align-items: center;
  gap: 4px 8px;
  flex-wrap: wrap;
}

.tvz-offers h3 > .tvz-card__act,
.tvz-card > h3:has(.tvz-circle__note) > .tvz-card__act {
  margin-left: auto;
  flex: none;
}

/* Подпись уходит на свою строку целиком: 100% основы — это и есть перенос
   «по решению», а не «когда не влезло».
 *
 * `margin-top` — СВОЙ отступ, а не только `row-gap` соседнего правила
 * (П-96, Маргарита №2: «кнопки наезжают на подпись»). У `.tvz-offers h3`
 * здесь стоял `gap: 4px 8px`, но более специфичное `.tvz-card
 * h3:has(.tvz-card__act) { gap: 8px }` (война специфичности `:has()` —
 * оно весит как класс) молча ПЕРЕБИВАЕТ его на КАЖДОЕ свойство, включая
 * `gap`, — сама подпись держалась зазором, который эта строка не
 * назначала. Числа совпали (0 8px = 8px), поэтому визуально было ровно,
 * но зазор был чужим и мог уехать в 0, стоило чужому правилу поменяться.
 * Свой `margin-top` не зависит от того спора. */
.tvz-offers__hint,
.tvz-circle__note {
  flex: 0 0 100%;
  order: 3;
  margin-top: 4px;
}

/* Подпись рядом с заголовком (П-40, §3.1): «отметьте, что входит в сделку» —
   сделка теперь собирается из нескольких КП, чекбоксы, а не радио. */
.tvz-offers__hint {
  font-size: 11px;
  font-weight: 400;
  color: var(--c-tx-4);
}

.tvz-offer {
  padding: 9px 11px;
  min-height: 74px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 6px;
  background: var(--c-surface);
}

.tvz-offer.is-included {
  border-color: var(--c-ac-bd);
  background: var(--c-sel);
}

.tvz-offer__row1 {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

/* Чекбокс «в расчёте» (П-40, §3.1) — сделка собирается из нескольких КП,
   поэтому не радио (один основной), а чекбокс: сколько угодно отмеченных,
   суммы складывает сервер. */
.tvz-offer__check {
  flex: none;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: var(--c-surface);
  border: 1.5px solid var(--c-line-strong);
}

/* Галочка светлее заливки в обеих темах — `--c-surface` тут не «фон
   карточки», а ближайший к белому/тёмному токен на своей стороне темы. */
.tvz-offer__check.is-active {
  background: var(--c-ac);
  border-color: var(--c-ac);
  color: var(--c-surface);
}

.tvz-offer__check:disabled {
  cursor: default;
}

.tvz-offer__name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-offer__row2 {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding-left: 27px;
}

.tvz-offer__chip {
  height: 21px;
  padding: 0 8px;
  border-radius: var(--rad-pill);
  font-size: 11px;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.tvz-offer__chip--term {
  font-weight: 600;
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-offer__chip--sum {
  font-weight: 500;
  background: var(--c-chip);
  color: var(--c-tx-2);
  font-family: var(--font-mono);
  font-size: 10.5px;
}

/* Серый бокс сумм + состава (П-40, §3.1, ярус 3) — во всю ширину карточки
   варианта, под условиями. */
.tvz-offer__box {
  padding: 9px 11px;
  margin-left: 27px;
  background: var(--c-hover);
  border: 1px solid var(--c-bd2);
  border-radius: 9px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tvz-offer__sums {
  display: flex;
  align-items: center;
  gap: 4px 12px;
  flex-wrap: wrap;
}

.tvz-offer__comp {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding-top: 8px;
  border-top: 1px solid var(--c-bd);
}

.tvz-offer__stat {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
}

.tvz-offer__stat-n {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -.02em;
}

.tvz-offer__stat-l {
  font-size: 11px;
  color: var(--c-mut);
}

.tvz-offer__row3 {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-left: 27px;
}

.tvz-offer__meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-offer__main-tag {
  height: 19px;
  padding: 0 8px;
  border-radius: var(--rad-pill);
  font-size: 10.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  background: var(--c-ac-tint);
  color: var(--c-ac);
  flex: none;
  white-space: nowrap;
}

.tvz-offer__acts {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Кнопка «Чат с агентом» становится акцентной, когда агент ответил
   (README §3.1, П-35): та же тонированная подложка, что у «определяет
   сделку» (`.tvz-offer__main-tag`), — второй пары токенов не заводим. */
.tvz-offer__chat-btn.is-unread {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

/* Модалка «Чат с агентом» (П-35, README §3.1): лента пузырями сверху,
   поле «Что поправить в КП?» и «Отправить» снизу — своя история на
   вариант, грузится при открытии, карточку сделки не тормозит (У-27). */
/* Прокручивается ТОЛЬКО лента: поле ввода и «Отправить» стоят на месте
   (слово владельца 12.08). Прежде лента имела свой предел в 60vh, а
   композер шёл следом обычным блоком — вместе они оказывались выше окна, и
   уезжало всё разом: чтобы написать ответ, приходилось сначала доскроллить
   до поля. Теперь высоту задаёт окно, лента забирает остаток и скроллит
   себя, а низ прижат. */
.tvz-chat {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  min-height: 0;
}

.tvz-chat__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* `flex: 1` вместо прежнего `max-height: 60vh`: предел в долях экрана не
     знал ни про шапку окна, ни про высоту композера — на коротком экране
     лента всё равно выталкивала ввод за край. Остаток считает сам браузер.
     `min-height: 0` обязателен: без него flex-элемент не сжимается ниже
     содержимого и скролл достаётся не ленте, а всему окну. */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 2px 4px;
}

/* Низ окна не участвует в прокрутке: ни строка «ждём агента», ни композер. */
.tvz-chat__waiting,
.tvz-chat > .tvz-chat__composer { flex: none; }

/* Прокрутка у чата ОДНА и принадлежит ленте. Тело модалки прокручивается
   само (`.tvz-modal__body` дизайн-системы: `overflow: auto`) — и без этой
   строки скроллов оказывалось два вложенных: колесо над лентой крутило
   ленту, на пиксель в сторону — всё окно вместе с полем ввода. Вендорный
   файл не трогаем (ADR-0002), надстройка наша и точечная: только у окна,
   внутри которого живёт чат. */
.tvz-modal__body:has(> .tvz-chat) { overflow: hidden; }

/* «Ждём агента…» (П-89 п.2) — честный дешёвый признак: последнее слово
   треда за менеджером и оно свежее ~5 минут. Пустая строка ничего не
   занимает — `.tvz-mut` уже даёт приглушённый цвет, здесь только отступы
   и убранный низ параграфа по умолчанию. */
.tvz-chat__waiting {
  margin: 0 2px 6px;
  font-size: 12px;
}

.tvz-chat__waiting:empty {
  display: none;
}

/* Пустой чат говорит вслух человеческой фразой (правило П-20), а не
   молчит пустым списком. */
.tvz-chat__empty {
  padding: 20px 6px;
  text-align: center;
  font-size: 12.5px;
  color: var(--c-tx-4);
}

.tvz-chat__msg {
  display: flex;
  flex-direction: column;
  gap: 3px;
  max-width: 84%;
}

/* Наши — справа заливкой; агент и система — слева, нейтрально (README §3.1). */
.tvz-chat__msg--mine {
  align-self: flex-end;
  align-items: flex-end;
}

.tvz-chat__msg--theirs {
  align-self: flex-start;
  align-items: flex-start;
}

.tvz-chat__bubble {
  padding: 8px 11px;
  border-radius: var(--rad-lg);
  font-size: 12.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.tvz-chat__msg--mine .tvz-chat__bubble {
  background: var(--c-ac);
  /* Текст на акцентной подложке — токеном поверхности: в светлой теме
     белый, в тёмной — тёмный на светло-синем (тот же приём, что у счётчика
     поиска, `.tvz-sflt__n`). */
  color: var(--c-surface);
}

.tvz-chat__msg--theirs .tvz-chat__bubble {
  background: var(--c-chip);
  color: var(--c-tx);
}

a.tvz-chat__file:hover { background: var(--c-ac-tint); color: var(--c-ac-d); }

/* Ссылки в тексте сообщения. Подчёркивание оставлено: в пузыре агента много
   текста, и без него адрес теряется среди строк. `break-all` — потому что
   адреса КП длинные и без переноса распирают пузырь на узком экране. */
.tvz-chat__bubble a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-all;
}
.tvz-chat__msg--theirs .tvz-chat__bubble a { color: var(--c-ac-d); }

.tvz-chat__files {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Файл — ССЫЛКА на скачивание, а не подпись: чип выглядел одинаково и до, и
   после того как стал нажимаемым, поэтому здесь добавлены только признаки
   нажимаемости (курсор, отклик на наведение) — вид намеренно тот же. */
.tvz-chat__file {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 9px;
  border-radius: var(--rad-pill);
  background: var(--c-chip);
  color: var(--c-tx-2);
  font-size: 11px;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}

/* «Кто · когда» под каждым пузырём (README §3.1). */
.tvz-chat__meta {
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-chat__composer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-chat__pending {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tvz-chat__input {
  width: 100%;
  min-height: 60px;
  padding: 9px 11px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-hover);
  color: var(--c-tx);
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
  outline: none;
}

.tvz-chat__input:focus {
  border-color: var(--c-ac);
  background: var(--c-surface);
}

.tvz-chat__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* Чат разработки (П-43): признак «агент работает / свободен» — карточка
   над лентой, не команда исполнителю, а печать его собственного сообщения
   о себе (см. докстринг DevAgentStatus).

   Шапка ОДНОЙ строкой с точкой состояния (владелец, 06.08: «оформи чат
   разработки так же, как в Works», со скрином чата Works — там голова
   читается точкой состояния: «готов · кто · когда», а не карточкой с
   иконкой чат-бота). */
.tvz-devchat__status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--c-tx-2);
}

.tvz-devchat__status.is-busy {
  border-color: var(--c-ac);
  color: var(--c-tx);
}

.tvz-devchat__dot {
  display: inline-flex;
  color: var(--c-mut);
}

.tvz-devchat__status.is-busy .tvz-devchat__dot {
  color: var(--c-ac);
}

/* ------------------------------------------------------------------------
   Экран «Чат разработки» — облик Works (владелец, 06.08, со скрином чата
   Works): пузыри с подписью (аватар-инициалы · имя · время · копировать),
   markdown тела, строка ввода отдельной панелью с круглыми кнопками.

   Свои классы `tvz-devchat__*`, а НЕ переиспользование `tvz-chat__*`: та
   ветка держит чат КП (deals.js `chatBubble`/`chatComposer`) — общий класс
   потянул бы правку облика в оба места разом, а владелец просил именно
   «Чат разработки». Наш продукт беднее Works по функциям (нет «Дифф» /
   «Отправить в clean» / «Сброс» — управление веткой здесь не показывается
   вовсе, волна фабрики остаётся на маке), поэтому переносится ОБЛИК и
   раскладка, а не чужие кнопки. */
.tvz-devchat {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.tvz-devchat__list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Тот же потолок, что был у прежней ленты (60vh, владелец 05.08): ответы
     агента — абзацы, и низкая лента заставляла скроллить на каждом. */
  max-height: 60vh;
  overflow-y: auto;
  padding: 2px 2px 4px;
}

/* Пустая лента говорит вслух (П-20), не молчит пустым списком. */
.tvz-devchat__empty {
  padding: 20px 6px;
  text-align: center;
  font-size: 12.5px;
  color: var(--c-tx-4);
}

.tvz-devchat__row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Свои — справа, СВЕТЛЫМ пузырём тинтом акцента (не сплошной заливкой, как
   у чата КП): на скрине Works своя реплика тоже тонирована, а не залита. */
.tvz-devchat__row--mine {
  align-self: flex-end;
  align-items: flex-end;
  max-width: 78%;
}

.tvz-devchat__row--mine .tvz-devchat__bubble {
  background: var(--c-ac-tint);
  border: 1px solid var(--c-ac-bd);
  color: var(--c-tx);
}

.tvz-devchat__row--mine .tvz-devchat__foot {
  flex-direction: row-reverse;
}

/* Агентские (и системные) — слева НА ВСЮ ШИРИНУ (владелец): длинный ответ
   агента читается абзацами полной строки, а не тесной колонкой. */
.tvz-devchat__row--theirs {
  align-self: stretch;
  align-items: flex-start;
  width: 100%;
}

.tvz-devchat__row--theirs .tvz-devchat__bubble {
  background: var(--c-chip);
  border: 1px solid var(--c-bd);
  color: var(--c-tx);
  width: 100%;
}

.tvz-devchat__bubble {
  padding: 10px 13px;
  border-radius: var(--rad-lg);
  font-size: 13px;
  line-height: 1.5;
  /* Ширина пузыря — потолок для содержимого: длинное слово без пробелов
     (путь, хэш) обязано перенестись, а не растянуть пузырь и ленту вширь. */
  max-width: 100%;
  min-width: 0;
}

.tvz-devchat__bubble p {
  margin: 0 0 8px;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
}

.tvz-devchat__bubble p:last-child {
  margin-bottom: 0;
}

.tvz-devchat__bubble strong {
  font-weight: 700;
}

/* `инлайн-код` моноширинным на плашке (владелец); перенос разрешён в
   любом месте слова — длинная техническая строка не рвёт вёрстку пузыря. */
.tvz-devchat__bubble code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--c-hover);
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-sm);
  padding: 1px 5px;
  word-break: break-word;
  overflow-wrap: anywhere;
}

/* Блок кода (тройные кавычки) — своя прокрутка ВБОК: трассировка в сто
   колонок не должна выталкивать пузырь и ленту за экран. */
.tvz-devchat__code {
  margin: 0 0 8px;
  padding: 8px 10px;
  background: var(--c-hover);
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  max-width: 100%;
  overflow-x: auto;
}

.tvz-devchat__code:last-child {
  margin-bottom: 0;
}

.tvz-devchat__code code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: none;
  border: none;
  padding: 0;
  white-space: pre;
}

/* Подпись под пузырём: аватар-инициалы · имя · время · копировать. */
.tvz-devchat__foot {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--c-tx-4);
  padding: 0 2px;
  max-width: 100%;
}

/* `.tvz-avatar` — из вендорной дизайн-системы (design.css); здесь только
   размер под мелкую подпись, геометрия, не цвет. */
.tvz-devchat__av {
  width: 20px;
  height: 20px;
  font-size: 9px;
}

.tvz-devchat__name {
  font-weight: 600;
  color: var(--c-tx-2);
}

.tvz-devchat__time {
  white-space: nowrap;
}

.tvz-devchat__copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  border: none;
  background: none;
  padding: 3px;
  color: var(--c-tx-4);
  cursor: pointer;
  border-radius: var(--rad-sm);
}

.tvz-devchat__copy:hover {
  color: var(--c-ac);
  background: var(--c-hover);
}

/* Строка ввода — отдельной панелью снизу: круглая «+» слева (вложение),
   поле «Сообщение…», круглая синяя отправка справа (владелец, облик
   Works). */
.tvz-devchat__composer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-devchat__pending {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tvz-devchat__pending:empty {
  display: none;
}

.tvz-devchat__field {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.tvz-devchat__input {
  flex: 1;
  min-width: 0;
  min-height: var(--ctl-h);
  max-height: 160px;
  padding: 9px 14px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  background: var(--c-hover);
  color: var(--c-tx);
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
  outline: none;
}

.tvz-devchat__input:focus {
  border-color: var(--c-ac);
  background: var(--c-surface);
}

/* Круглые кнопки строки ввода — своя геометрия поверх `.tvz-btn` (та
   рисует скруглённый прямоугольник фиксированной высоты): здесь нужен
   именно КРУГ, как на скрине Works. shell.css подключён ПОСЛЕ design.css
   (app.html), и при равной специфичности класса выигрывают эти правила. */
.tvz-devchat__round {
  flex: none;
  width: var(--ctl-h);
  height: var(--ctl-h);
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

/* «+» вложения — тот же круг, без варианта цвета (ghost, как в Works):
   явная запись НУЖНА даже без своих правил — гейт дизайн-системы требует
   объявления каждого класса разметки (`test_ui_uses_only_classes_...`). */
.tvz-devchat__round--attach {
  color: var(--c-tx-2);
}

.tvz-devchat__round--send {
  border-color: transparent;
  background: var(--c-ac);
  color: var(--c-on-ac);
}

.tvz-devchat__round--send:hover {
  background: var(--c-ac-d);
  border-color: transparent;
  color: var(--c-on-ac);
}

.tvz-devchat__round--send .tvz-icon {
  color: var(--c-on-ac);
}

/* 3.2 Круг участников. */
.tvz-circle__note {
  font-weight: 400;
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-circle-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 6px;
}

.tvz-circle-row {
  padding: 8px 10px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  background: var(--c-surface);
}

button.tvz-circle-row--open {
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}

.tvz-circle-row--open:hover {
  background: var(--c-hover);
  border-color: var(--c-line-strong);
}

.tvz-circle-row__top {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.tvz-circle-row__name {
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-circle-row__role {
  font-size: 11px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ===========================================================================
   Карточка клиента: дерево оргсхемы + люди узла
   (хендофф `_flow/handoff/client-card/`, вторая редакция — П-41, 03.08.2026)

   Прежний экран — плитки площадок под юрлицом да матрица «роль × место» — не
   читался у клиента с 10 юрлицами / 30 площадками / 221 контактом: до нужного
   человека докапывались, а не находили. Дерево-селектор слева и люди
   ВЫБРАННОГО узла справа решают ту же задачу, но масштабируются: узел
   раскрывается по требованию, а не печатается весь целиком.

   Вторая редакция (П-41, слово владельца «максимально повторить референс»)
   убрала горизонтальную шапку первой волны: теперь ДВЕ КАРТОЧКИ НА ВСЮ
   ВЫСОТУ (`grid-template-columns:352px minmax(0,1fr)`), шапка клиента живёт
   ВНУТРИ левой карточки, над оргсхемой, — а не отдельной полосой сверху.
   Довод владельца тот же, что и раньше: «до конкретного контакта дотянуться
   сложно» — вся ширина и высота отданы людям.

   Токены — из таблицы соответствия хендоффа (README «Fidelity»): все hex
   макета уже названы токенами `--c-*` дизайн-системы, литералов здесь нет
   (и вычисляемые цвета вроде color-mix или rgb тоже под тем же запретом,
   что и hex, — конформанс их тоже ловит). Промежуточные оттенки хендоффа,
   для которых готового токена нет (тусклый текст мельче `--c-tx-4`, грань
   светлее `--c-line-strong`, тёплая амбер-грань блока «унаследован» ровнее
   `--c-warn`), хендофф разрешает брать ближайшим — взяты `--c-tx-4` /
   `--c-line-strong` (те же, что несут этот смысл во всём shell.css) и сам
   `--c-warn` полным тоном на границу, тем же приёмом, что у `.tvz-tile--warn`.

   Высота в один экран без прокрутки страницы — только своим владением:
   `.tvz-content` перестаёт скроллиться, пока внутри стоит `.tvz-ccard-page`
   (тот же приём `:has()`, что уже несёт `.tvz-page--search` рядом); внутри
   скроллятся только сами колонки. Хроника/история/лента участия/юрлица
   (реквизиты подписанта) на этот экран не помещаются — они за кнопкой
   «Ещё о клиенте» (обычное модальное окно, странице скроллиться не надо). */

.tvz-content:has(.tvz-ccard-page) {
  overflow: hidden;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.tvz-content:has(.tvz-ccard-page) > * {
  max-width: none;
}
.tvz-page:has(.tvz-ccard-page),
.tvz-page__body:has(.tvz-ccard-page),
.tvz-page--search:has(.tvz-ccard-page) {
  flex: 1;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.tvz-page--search:has(.tvz-ccard-page) .tvz-page__body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.tvz-ccard-page {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.tvz-ccard-page > .tvz-crumbs,
.tvz-ccard-page > .tvz-warnbox {
  flex: none;
  margin: 12px 12px 0;
}

.tvz-ccard {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  /* Каркас — буквально из README «Каркас»: 352px + остальное, обе карточки
     `grid-row:1 / span 2` (задел на будущую полосу сверху, сейчас обе
     панели во всю высоту — см. правила `.tvz-ccard__tree`/`__people` ниже). */
  display: grid;
  grid-template-columns: 352px minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  gap: 12px;
  padding: 12px;
}

/* Обе панели — на всю высоту грида, каждая своей колонкой (README «Каркас»:
   `grid-row:1 / span 2` у обеих). */
.tvz-ccard__tree,
.tvz-ccard__people {
  grid-row: 1 / span 2;
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: var(--rad-lg);
  box-shadow: var(--shadow-e1);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.tvz-ccard__tree {
  grid-column: 1;
}
.tvz-ccard__people {
  grid-column: 2;
}

/* --- шапка клиента: ВНУТРИ левой карточки, над оргсхемой (README §1.1) --- */

.tvz-ccard__head {
  flex: none;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  border-bottom: 1px solid var(--c-bd2);
  min-width: 0;
}
.tvz-ccard__head-id {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.tvz-ccard__name {
  border: none;
  background: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
  color: var(--c-tx);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__name:hover {
  color: var(--c-ac);
}
/* Метки самого клиента — «ключевой», «партнёрская организация». Пришли на
   место строки масштаба, которая пересказывала дерево под собой (владелец
   04.08: «убери»). Эти два признака в дереве не видны ниоткуда, поэтому
   остались — но бейджами, а не строкой моноширинного текста. */
.tvz-ccard__marks {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
.tvz-ccard__verdict {
  margin-top: 2px;
}
.tvz-ccard__flex {
  flex: 1;
  min-width: 8px;
}
/* Строка «владелец» — своя граница сверху (README §1.1, кикер + имя). */
.tvz-ccard__owner {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--c-chip);
  min-width: 0;
}
.tvz-ccard__owner-l {
  flex: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}
.tvz-ccard__owner-v {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Действия шапки — только «Ещё о клиенте» осталось здесь (README §1.1):
   «Внести человека» уехало к списку людей, «Кто отвечает» сочли лишним —
   ответственный и так виден в правой панели. Переключатели «ключевой» и
   «запретить прямое общение» — не из референса (это добавка нашего
   продукта поверх дизайна), и в узкую 352px-шапку с одной тихой кнопкой не
   легли бы визуально — переехали в модалку «Ещё о клиенте» (см. ниже). */
.tvz-ccard__acts {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--c-chip);
  flex-wrap: wrap;
}
.tvz-ccard__acts .tvz-btn {
  height: 30px;
  padding: 0 9px;
  border: none;
  background: none;
  border-radius: var(--rad);
  font-size: 12px;
  font-weight: 500;
  color: var(--c-mut);
}
.tvz-ccard__acts .tvz-btn:hover {
  background: var(--c-hover);
  color: var(--c-tx);
}

.tvz-ccard__empty {
  padding: 28px 16px;
  text-align: center;
  color: var(--c-tx-4);
  font-size: 12px;
}

/* --- левая колонка: дерево оргсхемы ---------------------------------------- */

.tvz-ccard__tree-head {
  flex: none;
  height: 38px;
  padding: 0 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-ccard__seg {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--c-chip);
  border-radius: var(--rad);
  flex: none;
}
.tvz-ccard__seg-b {
  height: 22px;
  padding: 0 8px;
  border: none;
  border-radius: var(--rad-sm);
  background: none;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--c-mut);
  cursor: pointer;
}
.tvz-ccard__seg-b.is-active {
  background: var(--c-surface);
  color: var(--c-ac);
  box-shadow: var(--shadow-e1);
}
.tvz-ccard__tree-hint {
  font-size: 10px;
  color: var(--c-tx-4);
  white-space: nowrap;
}
.tvz-ccard__tree-search {
  flex: none;
  padding: 8px 10px;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-ccard__tree-search .tvz-search {
  width: 100%;
  height: 32px;
  min-width: 0;
}
.tvz-ccard__tree-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 6px 8px 12px 4px;
}
.tvz-ccard__tree-rows {
  display: flex;
  flex-direction: column;
}

.tvz-ccard__row {
  display: flex;
  align-items: center;
  gap: 5px;
  min-height: 30px;
  padding: 2px 8px 2px 2px;
  border-radius: 7px;
  cursor: pointer;
  user-select: none;
}
.tvz-ccard__row[data-kind="region"] {
  min-height: 24px;
}
.tvz-ccard__row[data-kind="site"] {
  min-height: 32px;
}
.tvz-ccard__row:hover {
  background: var(--c-hover);
}
.tvz-ccard__row.is-selected {
  background: var(--c-ac-tint);
}
.tvz-ccard__row.is-selected .tvz-ccard__row-nm {
  color: var(--c-ac);
}
.tvz-ccard__row-pad {
  flex: none;
}
.tvz-ccard__row-caret {
  flex: none;
  width: 12px;
  height: 16px;
  border: none;
  background: none;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-tx-4);
  cursor: pointer;
}
/* Иконка, не текстовый глиф (правило конформанса: пиктограммы запрещены в
   UI, README тоже просит заменить текстовые каретки хендоффа на icon-set
   проекта). Одна и та же `chevron` (смотрит вниз по умолчанию — раскрытая
   ветка), закрытая ветка повёрнута на -90deg (смотрит вбок). */
.tvz-ccard__row-caret svg {
  transition: transform .12s;
  transform: rotate(-90deg);
}
.tvz-ccard__row-caret.is-open svg {
  transform: rotate(0deg);
}
.tvz-ccard__row-caret.is-leaf {
  color: transparent;
  cursor: default;
}
.tvz-ccard__kind {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 700;
}
.tvz-ccard__kind--le {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}
.tvz-ccard__kind--region {
  background: var(--c-purplebg);
  color: var(--c-purple);
}
.tvz-ccard__kind--site {
  background: var(--c-chip);
  color: var(--c-mut);
}
.tvz-ccard__row-name {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.tvz-ccard__row[data-kind="le"] .tvz-ccard__row-nm {
  font-size: 12.5px;
  font-weight: 600;
}
.tvz-ccard__row[data-kind="region"] .tvz-ccard__row-nm {
  font-size: 12px;
  font-weight: 600;
  color: var(--c-tx-2);
}
.tvz-ccard__row[data-kind="site"] .tvz-ccard__row-nm {
  font-size: 12px;
  font-weight: 500;
}
.tvz-ccard__row-nm {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.3;
  color: var(--c-tx);
}
.tvz-ccard__row-sub {
  font-size: 10.5px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.3;
}
.tvz-ccard__row-alert {
  flex: none;
  color: var(--c-err);
  display: inline-flex;
}
.tvz-ccard__row[data-kind="le"] .tvz-ccard__row-alert {
  color: var(--c-warn);
}
/* «⋯» узла: правка дерева живёт в строке узла (П-94). В покое кнопка
   почти прозрачна — дерево читают чаще, чем правят, и ряд иконок вдоль
   всего списка спорил бы с именами узлов за внимание. Проявляется при
   наведении и у выбранной строки. */
.tvz-ccard__row-menu {
  flex: none;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  border-radius: var(--rad-sm);
  background: transparent;
  color: var(--c-tx-4);
  opacity: 0;
  cursor: pointer;
}
.tvz-ccard__row:hover .tvz-ccard__row-menu,
.tvz-ccard__row.is-selected .tvz-ccard__row-menu {
  opacity: 1;
}
.tvz-ccard__row-menu:hover {
  background: var(--c-hover);
  color: var(--c-tx);
}
/* Архивный узел (П-94) виден только в режиме «Архив» и приглушён: он не
   часть живой схемы, а строка, у которой одно назначение — вернуться. */
.tvz-ccard__row.is-archived .tvz-ccard__row-nm,
.tvz-ccard__row.is-archived .tvz-ccard__row-sub {
  color: var(--c-tx-4);
  font-style: italic;
}

.tvz-ccard__row-cnt {
  flex: none;
  min-width: 20px;
  text-align: right;
  font-size: 10.5px;
  font-family: var(--font-mono);
  color: var(--c-mut);
}
.tvz-ccard__row-cnt.is-zero {
  color: var(--c-line-strong);
}

/* --- правая колонка: люди узла --------------------------------------------- */

.tvz-ccard__scope-head {
  flex: none;
  padding: 9px 16px 10px;
  border-bottom: 1px solid var(--c-bd2);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tvz-ccard__crumbs {
  font-size: 11px;
  color: var(--c-tx-4);
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
}
.tvz-ccard__crumb-it {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.tvz-ccard__crumb {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--c-tx-4);
}
.tvz-ccard__crumb:hover {
  color: var(--c-ac);
  text-decoration: underline;
}
.tvz-ccard__crumb-sep {
  color: var(--c-line-strong);
}
.tvz-ccard__scope-title {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
}
.tvz-ccard__scope-kind {
  height: 18px;
  padding: 0 7px;
  border-radius: var(--rad-pill);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  flex: none;
  background: var(--c-chip);
  color: var(--c-mut);
}
.tvz-ccard__scope-kind.is-site {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}
.tvz-ccard__scope-nm {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.015em;
  line-height: 1.15;
}
.tvz-ccard__scope-facts {
  font-size: 11px;
  color: var(--c-tx-4);
  font-family: var(--font-mono);
}

.tvz-ccard__resp {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px 9px;
  border-radius: 9px;
  border: 1px solid var(--c-bd);
}
.tvz-ccard__resp.is-own {
  border-color: var(--c-ac-bd);
  background: var(--c-ac-tint);
}
.tvz-ccard__resp.is-inherited {
  /* Хендофф просит тёплую амбер-грань потоньше `--c-warn`, а готового
     полутона нет (см. врезку в начале раздела) — правило конформанса
     запрещает и вычисляемые цвета (color-mix там же, где rgb или hsl),
     не только литеральный hex. Берём сам токен `--c-warn`, тем же приёмом,
     что и `.tvz-tile--warn` рядом (граница в полный тон, заливка — bg). */
  border-color: var(--c-warn);
  background: var(--c-warnbg);
}
.tvz-ccard__resp-row1 {
  display: flex;
  align-items: center;
  gap: 7px;
}
.tvz-ccard__resp-id {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.tvz-ccard__resp-nm {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__resp-sub {
  font-size: 10.5px;
  color: var(--c-mut);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__resp-tag {
  flex: none;
  height: 17px;
  padding: 0 7px;
  border-radius: var(--rad-pill);
  display: inline-flex;
  align-items: center;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--c-surface);
  color: var(--c-ac);
}
.tvz-ccard__resp.is-inherited .tvz-ccard__resp-tag {
  color: var(--c-warn);
}
.tvz-ccard__resp .tvz-acts {
  gap: 4px;
}
.tvz-ccard__resp .tvz-btn {
  height: 24px;
  padding: 0 8px;
  font-size: 11px;
}

.tvz-ccard__filters {
  flex: none;
  padding: 8px 16px;
  border-bottom: 1px solid var(--c-bd2);
  display: flex;
  align-items: center;
  gap: 10px;
  /* README §113: РОДИТЕЛЬСКАЯ СТРОКА не должна нести `overflow:hidden` —
     панель «Вопроса» обрежется. Она и не несёт: попап (`core/popover.js`)
     портирует панель в `document.body`, так что даже добавь сюда
     `overflow:hidden` завтра по другой причине, дропдаун это не сломает —
     но явный `visible` документирует требование хендоффа на месте. */
  overflow: visible;
}
.tvz-ccard__filters .tvz-search {
  flex: 0 1 170px;
  min-width: 110px;
  height: 28px;
}
/* Распорка перед «+ Контакт» (README §2.2: поиск и «Вопрос» слева, кнопка
   прижата вправо) — своя, а не общий `.tvz-ccard__flex`: там min-width 8px,
   здесь по хендоффу 4px, и делить одну переменную под два разных места
   значило бы завтра поправить одно и молча сдвинуть другое. */
.tvz-ccard__filters-sp {
  flex: 1;
  min-width: 4px;
}
.tvz-ccard__add-btn {
  flex: none;
  height: 28px;
  padding: 0 9px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
/* На вкладке «Адреса» контролы людей гасятся атрибутом hidden (П-69,
   cards.js::renderFilters). Атрибут прячет через display:none БРАУЗЕРНОЙ
   таблицей стилей, и любой авторский display (.tvz-btn — inline-flex,
   .tvz-ccard__role-btn — flex) молча его перебивает: кнопка «Вопрос» стояла
   над списком адресов и обещала фильтр людей, которого там нет. Правило
   одно на всю строку фильтров, а не по кнопке: следующий контрол с своим
   display иначе повторил бы ту же поломку. */
.tvz-ccard__filters [hidden] {
  display: none;
}
.tvz-ccard__role-btn {
  flex: 0 1 330px;
  min-width: 0;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--c-bd);
  background: var(--c-bg);
  border-radius: var(--rad);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--c-tx);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
}
.tvz-ccard__role-btn:hover {
  border-color: var(--c-line-strong);
  background: var(--c-surface);
}
.tvz-ccard__role-btn svg {
  flex: none;
  margin-left: auto;
  color: var(--c-tx-4);
}
.tvz-ccard__role-btn-t {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__role-menu {
  width: 340px;
  max-width: 70vw;
}
.tvz-ccard__role-menu .tvz-menu__it {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 6px 0 8px;
  white-space: normal;
}
.tvz-ccard__role-opt-t {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__role-badge {
  flex: none;
  min-width: 26px;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--rad-pill);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
}
.tvz-ccard__role-badge--ok {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}
.tvz-ccard__role-badge--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}
.tvz-ccard__role-badge--err {
  background: var(--c-errbg);
  color: var(--c-err);
}
.tvz-ccard__role-hint {
  padding: 5px 8px 2px;
  font-size: 9.5px;
  color: var(--c-tx-4);
  line-height: 1.4;
}

.tvz-ccard__list {
  flex: 1;
  min-height: 0;
  overflow: auto;
}
.tvz-ccard__gaps {
  padding: 8px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-ccard__gaps-t {
  font-size: 11px;
  color: var(--c-err);
  font-weight: 600;
}
.tvz-ccard__gaps-l {
  font-size: 11px;
  color: var(--c-tx-2);
}
/* «Ещё не начали» (П-87, B-44/B-63): та же строка, спокойным тоном —
   тон, а не цвет пожара, ровно тем же приёмом, что у CLIENT_VERDICT_TONE
   в домене (`services/coverage_gaps.py`, ступень NOT_STARTED = info). */
.tvz-ccard__gaps.is-calm .tvz-ccard__gaps-t {
  color: var(--c-info);
  font-weight: 500;
}

.tvz-ccard__group {
  border-bottom: 1px solid var(--c-bd2);
}
/* Палитра шести оттенков (README §2.3) — БЕЗ модификаторов-классов и БЕЗ
   hex здесь: правило конформанса (`test_ui_uses_only_design_tokens`)
   запрещает литеральный цвет в не-вендорных файлах без исключений, и
   `.tvz-ccard`-переменная с hex-значением была бы тем же запрещённым
   литералом, просто в другом файле. Шесть цветов живут в вендорной
   `core/ui.js` (`ROLE_GROUP_TINTS`, тот же приём, что уже несёт `TAG_COLORS`
   там же) и приходят на `.tvz-ccard__group` ГОТОВОЙ строкой инлайновых
   `--tint-*` (`roleGroupTintStyle(index)`, cards.js) — здесь эти переменные
   только ЧИТАЮТСЯ, с нейтральным резервом для «Роль не указана» (вне
   справочника ролей — служебная категория поверх палитры, своего тона не
   несёт). Custom properties наследуются потомками сквозь любую вложенность,
   поэтому `.tvz-ccard__pcard` внутри `.tvz-ccard__cards` получает верный
   тон без собственного инлайна. */
.tvz-ccard__group-head {
  /* README §2.3: липкая шапка группы своим тоном — см. врезку выше. */
  padding: 8px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  background: var(--tint-hd, var(--c-chip));
  position: sticky;
  top: 0;
  z-index: 1;
  border-top: 1px solid var(--tint-bd, var(--c-bd2));
  border-bottom: 1px solid var(--tint-bd, var(--c-bd2));
}
.tvz-ccard__group-t {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tint-tx, var(--c-tx-2));
}
.tvz-ccard__group-more {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--c-ac);
  white-space: nowrap;
}
.tvz-ccard__group-more:hover {
  text-decoration: underline;
}
.tvz-ccard__group-n {
  font-size: 11px;
  color: var(--c-tx-4);
  white-space: nowrap;
}

/* `auto-fit`, а не `auto-fill` (Маргарита №2, «плитки режут фамилии при
   пустой половине экрана»): `auto-fill` держит на строке ПРИЗРАЧНЫЕ пустые
   колонки, пока хватает ширины на ещё одну дорожку 252px, — `1fr` делится
   между НИМИ тоже, и заполненным плиткам достаётся голый минимум (252px)
   даже когда справа пустует полэкрана. `auto-fit` схлопывает пустые дорожки,
   и та же ширина уходит живым плиткам — им есть куда тянуться. */
.tvz-ccard__cards {
  padding: 8px 16px 12px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(252px, 1fr));
  gap: 6px;
  background: var(--tint-bg, transparent);
}

/* Тело полосы потока на вкладке «Сделки» (B-142) — не сетка, а список: у
   строки сделки четыре вещи в один ряд (название, этап, задача, тишина), и
   в колонку 252px они не лягут. Отступ по бокам меньше, чем у сетки
   карточек: строка `.tvz-hit` несёт свой собственный (7px 8px), и складывать
   их значило бы отодвинуть список от полосы, под которой он стоит.

   Тон тела здесь НЕ ставится, в отличие от сетки карточек людей выше, и это
   не забывчивость, а тёмная тема. `--tint-bg` — светлая пастель, одна на обе
   темы (палитра живёт в `core/ui.js` и по теме не меняется); у людей она
   уцелела потому, что сверху её закрывают непрозрачные карточки
   (`.tvz-ccard__pcard`, `--c-surface`), а строка сделки прозрачна — и в
   тёмной теме светлое имя сделки вставало светлым по светлому. Поймано
   снимком приёмки, не глазами: на светлой теме всё было верно, и разницы не
   видно, пока не переключишь тему. Цвет потока держит сама полоса-заголовок
   — у неё свой фиксированный тёмный акцент (`--tint-tx`), которому есть
   с чем контрастировать в любой теме. */
.tvz-ccard__deals {
  padding: 2px 8px 8px;
}

/* Подпись под названием сделки (площадка · чья сделка) стоит ЭТАЖОМ, а не
   рядом с названием: в правой колонке карточки под название отведено вдвое
   меньше места, чем в разделе «Сделки», и отступ подписи от соседа слева
   там лишний — слева у неё край строки. Сам класс общий (`.tvz-deal__of`),
   правится только его отступ и потолок ширины. */
.tvz-ccard__deals .tvz-deal__of {
  margin-left: 0;
  max-width: 100%;
}

/* Название не жмётся пилюлей этапа до одного слова: строка складывается по
   высоте, а обрезается — подпись под ней, которой обрыв не мешает (у неё
   есть подсказка с полным текстом). */
.tvz-ccard__deals .tvz-hit__name {
  min-width: 0;
}

.tvz-ccard__pcard {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px 9px;
  border-radius: 9px;
  background: var(--c-surface);
  /* Тон группы по умолчанию (README §143); проблема (ниже) перебивает его —
     `.is-warn`/`.is-err` несут вторую перечисленную в правиле класс-ссылку
     на элемент и потому побеждают этот селектор по специфичности вне
     зависимости от порядка объявления. */
  border: 1px solid var(--tint-bd, var(--c-bd));
}
.tvz-ccard__pcard:hover {
  border-color: var(--c-line-strong);
}
.tvz-ccard__pcard.is-warn {
  border-color: var(--c-warn);
}
.tvz-ccard__pcard.is-err {
  border-color: var(--c-err-bd);
}
.tvz-ccard__pcard-head {
  display: flex;
  align-items: center;
  gap: 7px;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  text-align: left;
  width: 100%;
}
.tvz-ccard__pcard-id {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
/* Фамилия переносится, а не режется («Гурьев Антон Серг…», Маргарита №2):
   `auto-fit` рядом отдаёт плитке лишнюю ширину, но у длинного ФИО она
   рано или поздно кончается всё равно, и однострочный `ellipsis` тогда
   прячет ровно то слово, по которому человека ищут глазами — фамилию.
   Плитка — колонка (`.tvz-ccard__pcard-id`, `flex-direction: column`),
   вторая строка ей ничего не стоит. */
.tvz-ccard__pcard-nm {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--c-tx);
  overflow-wrap: break-word;
}
.tvz-ccard__pcard-head:hover .tvz-ccard__pcard-nm {
  color: var(--c-ac);
  text-decoration: underline;
}
.tvz-ccard__pcard-ttl {
  font-size: 10.5px;
  color: var(--c-tx-4);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__pcard-lvl {
  flex: none;
  height: 17px;
  padding: 0 6px;
  border-radius: var(--rad-pill);
  font-size: 10px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  max-width: 130px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--c-chip);
  color: var(--c-mut);
}
.tvz-ccard__pcard-lvl.is-own {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}
/* Ряды «телефон» / «почта + вердикт доверия» (README §143–148) — общий узкий
   контейнер (gap 2px, теснее общего gap:6px карточки), тем же кодом что и
   блок ответственного (`.tvz-ccard__resp .tvz-ccard__pcard-rows`) — два
   места, печатающие один и тот же факт о человеке, не должны разойтись
   вёрсткой (см. `pcardPhoneRow`/`pcardEmailRow`, cards.js). */
.tvz-ccard__pcard-rows {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.tvz-ccard__pcard-row {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}
.tvz-ccard__pcard-phone {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--c-tx-2);
}
.tvz-ccard__pcard-phone.is-missing {
  font-family: inherit;
  font-size: 10.5px;
  color: var(--c-err);
}
.tvz-ccard__pcard-email {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--c-mut);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-ccard__pcard-email.is-missing {
  font-family: inherit;
  color: var(--c-tx-4);
}
/* Вердикт доверия (README §148 «дата проверки») — СЛОВА ДОМЕНА
   (`person.trust.label`/`.tone`), не своя дата с порогом экрана: подряд
   два правила «пора проверить» на одной записи уже ловили (S-1a-2, B-14,
   `services/trust.py`). Цвет — по `trust.tone` сервера, а не по счёту дней
   на экране. */
.tvz-ccard__pcard-fresh {
  flex: none;
  font-size: 9.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--c-tx-4);
}
.tvz-ccard__pcard-fresh--warn {
  color: var(--c-warn);
}
.tvz-ccard__pcard-fresh--err {
  color: var(--c-err);
}
.tvz-ccard__pcard-ch .tvz-acts {
  gap: 4px;
  flex-wrap: wrap;
}
.tvz-ccard__pcard-ch .tvz-btn {
  height: 24px;
  padding: 0 7px;
  font-size: 10.5px;
}
.tvz-ccard__pcard-badges {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.tvz-ccard__pcard-badges .tvz-badge {
  height: 17px;
  padding: 0 6px;
  font-size: 10px;
}

/* Модалка «Ещё о клиенте» (П-74, хендофф 04.08): переключатели «ключевой
   клиент» и «запретить прямое общение», редкое право `catalogs.manage`, —
   не из референса (в хендоффе окна их нет вовсе), но у окна нет второго
   места рядом с именем клиента, где они были бы достижимы, и строка
   рисуется, только когда право есть — у обычного менеджера тело держит
   контракт волны без единого лишнего пикселя. */
.tvz-ccard-extras__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

/* ============================================================================
   «Ещё о клиенте» — тело формы-фактора (П-74, хендофф 04.08 «Модалки — один
   форм-фактор», окно 6g). Три блока сверху вниз, порядок как в
   `clientExtrasModal` (cards.js): другие названия · юрлица (подписант и
   оригиналы) · факты об организации. Классы префикса `tvz-xclient` — только
   этого окна, второй раз в продукте не встречаются.
   ============================================================================ */
.tvz-xclient {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.tvz-xclient__top {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tvz-xclient__facts-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Другие названия — чипы 26px вместо списка строк (было `.tvz-hit`). */
.tvz-xclient__chips {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  align-items: center;
}
.tvz-xclient__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border: none;
  border-radius: 6px;
  background: var(--c-chip);
  color: var(--c-tx);
  font-size: 12px;
  font-weight: 400;
}
/* Убираемый чип — кнопка (button()), а не строка: сброс базовых кнопочных
   отступов/бордера `.tvz-btn`, которые иначе перебивают высоту 26px. */
button.tvz-xclient__chip {
  cursor: pointer;
}
button.tvz-xclient__chip:hover {
  background: var(--c-hover);
}
button.tvz-xclient__chip .tvz-icon {
  width: 10px;
  height: 10px;
  color: var(--c-tx-4);
}
.tvz-xclient__chip--add {
  border: 1px dashed var(--c-line-strong);
  background: none;
  color: var(--c-ac);
  font-weight: 600;
}
.tvz-xclient__chip--add .tvz-icon {
  color: var(--c-ac);
}
.tvz-xclient__chips-empty {
  font-size: 12px;
  color: var(--c-tx-4);
}

/* Юрлица — две колонки, строка не рвётся между ними (`break-inside:avoid`). */
.tvz-xclient__ents {
  column-count: 2;
  column-gap: 22px;
}
.tvz-xclient__ent {
  break-inside: avoid;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-xclient__ent-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tvz-xclient__ent-name {
  font-size: 13px;
  font-weight: 700;
}
.tvz-xclient__ent-idn {
  font-size: 11.5px;
  color: var(--c-tx-4);
  font-family: var(--font-mono);
}
.tvz-xclient__ent-signer {
  font-size: 12px;
  color: var(--c-tx-2);
}
/* Адрес оригиналов БЕЗ префикса «Оригиналы:» — заголовок секции уже обещал
   его (правило текста №3 хендоффа).

   Одна строка с многоточием: адреса длинные («450095, Республика
   Башкортостан, г. Уфа, Промышленная улица, д. 106, корп. 2, помещение
   14»), в колонке 400px они переносились на две-три строки, и строка юрлица
   вырастала со 89 до 105+ — шесть таких строк разгоняли тело за 520. Целиком
   адрес читается тултипом строки и в правке юрлица. */
.tvz-xclient__ent-orig {
  font-size: 11.5px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Чего не хватает юрлицу до готовности — словами домена. Бейдж «не готов»
   без причины читается как прочерк: человек видит, что плохо, и не видит,
   что чинить. */
.tvz-xclient__ent-gap {
  font-size: 11.5px;
  line-height: 1.35;
}
.tvz-xclient__ent-side {
  flex: none;
}

/* Что за организация — сетка 168px/1fr, а не `.tvz-kv` (та кладёт значение
   space-between без фиксированной колонки метки, и длинный адрес прыгал бы
   влево-вправо от длины соседней строки). */
.tvz-xclient__facts {
  display: grid;
  grid-template-columns: 168px 1fr;
  font-size: 12.5px;
}
.tvz-xclient__facts > span {
  padding: 6px 0;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-xclient__facts > span:nth-last-child(-n+2) {
  border-bottom: none;
}
.tvz-xclient__facts-k {
  color: var(--c-tx-4);
}

@media (max-width: 900px) {
  .tvz-xclient__ents {
    column-count: 1;
  }
}

@media (max-width: 900px) {
  /* Дерево над людьми, обе половины ужаты в минимуме: на телефоне левая
     карточка (шапка клиента + оргсхема) сама держит сотню-другую пикселей.
     Пол людской половины (280px) — не круглое число: шапка узла (крошки +
     заголовок + факты) и строка фильтров («ФИО, должность, телефон, email»
     + «Вопрос» + «+ Контакт») вместе держат около 120–140px ДО единой
     карточки контакта — с полом 140px список получал ровно 0px (найдено
     проходом «глазами» этой же волны: первая карточка человека была
     недостижима — под ней стояли фильтры). */
  .tvz-ccard {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(110px, 28%) minmax(280px, 1fr);
    min-height: 420px;
    gap: 8px;
    padding: 8px;
  }
  .tvz-ccard__tree,
  .tvz-ccard__people {
    grid-column: 1;
  }
  .tvz-ccard__name {
    font-size: 15px;
  }
  .tvz-ccard-page > .tvz-crumbs,
  .tvz-ccard-page > .tvz-warnbox {
    margin: 8px 8px 0;
  }
  /* Пол `.tvz-ccard__list` (280px, выше) держит его для клиентов попроще,
     но у клиента с богатой шапкой узла (блок ответственного с рядом
     каналов связи + длинная строка фактов) сама шапка узла на 375px легко
     перевешивает 200+px — список тогда снова получал бы 0px, воюя с ней
     за общий remainder (`flex:1`). Вместо гонки за место — общая
     прокрутка: шапка узла, фильтры и список едут ОДНОЙ лентой внутри
     `.tvz-ccard__people`, и первая карточка человека остаётся достижимой
     скроллом, а не проигрывает соседям высоту молча. */
  .tvz-ccard__people {
    overflow-y: auto;
    overflow-x: hidden;
  }
  .tvz-ccard__scope-head,
  .tvz-ccard__filters {
    flex: none;
  }
  .tvz-ccard__list {
    flex: none;
    overflow: visible;
  }
}
/* П-40: блок цен — свой блок под описанием (не колонка сбоку), поэтому
   узкий экран больше не нуждается в отдельной правке ширины/черты —
   `.tvz-dealhead__moneybox` и так на всю ширину карточки на любом экране. */


/* Значок правки в ленте — нейтральный тон: правка данных не событие
   разговора, и подсвечивать её как звонок было бы враньём тоном. */
.tvz-feed__i--edit {
  background: var(--c-chip);
  color: var(--c-mut);
}

/* «Отмена» в модалке ролей — тихая кнопка слева от «Сохранить»; вид берётся
   у `tvz-btn--ghost`, здесь только место в ряду. */
.tvz-rmodal__cancel {
  margin-left: auto;
}

/* Список КП в поповере «Цена и затраты» (правка владельца 03.08: «показывай
   тут список КП и дай возможность выбрать несколько»). Отметка идёт той же
   ручкой, что чекбоксы блока «Варианты предложения», — вид тоже должен
   читаться как список выбора, а не как таблица. */
.tvz-pricepop__offers {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
}

.tvz-pricepop__offer {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
  cursor: pointer;
}

.tvz-pricepop__offer:hover {
  background: var(--c-hover);
}

.tvz-pricepop__offer-t {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fz-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pricepop__offer-s {
  flex: none;
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}


/* Выбор участников записи двумя сторонами (правка владельца 03.08: «в „кто
   участвовал“ два таба — со стороны клиента и с нашей стороны, и поиск»,
   плюс «продумай множественный выбор»). Базовый `tvz-tagpick` — общий
   список с отметками; здесь модификатор с вкладками, поиском и подвалом
   счётчика. */
.tvz-tagpick--sided {
  min-width: 300px;
  max-width: 380px;
}

.tvz-tagpick__tabs {
  display: flex;
  gap: 4px;
  padding: 6px 8px 0;
}

.tvz-tagpick__find {
  padding: 6px 8px;
}

.tvz-tagpick__find .tvz-search {
  width: 100%;
}

.tvz-tagpick__nm {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-tagpick__note {
  flex: none;
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Подвал: счёт выбранных и снятие всех — выбор копится между вкладками
   и поиском, поэтому счётчик обязан быть виден всегда. */
.tvz-tagpick__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-top: 1px solid var(--c-bd2);
  background: var(--c-hover);
}

.tvz-tagpick__count {
  flex: 1 1 auto;
  font-size: var(--fz-sm);
  color: var(--c-mut);
}

/* «Сохранить» в модалке ролей — главная кнопка ряда. */
.tvz-rmodal__save {
  flex: none;
}


/* Участники записи ленты (правка владельца 03.08: «мне не нравится, как тут
   отображаются участники… может быть, их цветом разделить — наши одним
   цветом, со стороны клиента другим… теряется фактура комментария»).

   Было: имена серой строкой через запятую, вперемешку с автором записи —
   пять фамилий подряд читались как продолжение подписи, а не как состав
   разговора. Стало: подпись автора отдельной строкой, состав — чипами
   стороны (те же тона, что у сторон сделки в шапке), с тихим кикером
   «с участием» слева. Фактура записи возвращается тем, что подпись,
   состав и текст перестали быть одной серой лентой. */
.tvz-timeline__parts {
  display: flex;
  align-items: center;
  gap: 4px 6px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.tvz-timeline__parts-l {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
  margin-right: 2px;
}

.tvz-timeline__part {
  font-size: var(--fz-micro);
}


/* Каркас страницы сделки (правка владельца 03.08: «сейчас все блоки
   слиплись»). Блоки лежали прямыми детьми области контента, а у неё нет
   вертикального зазора — шапка, модуль работы, нижний ряд и реквизиты
   стояли впритык, и граница между ними читалась только по тени.

   Зазор здесь ОДИН на все блоки и заметно крупнее внутреннего шага
   карточек (10px): расстояние между соседними блоками должно быть больше,
   чем между строками внутри блока, иначе глаз не отличает «другой раздел»
   от «следующая строка». */
.tvz-dealpage {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ============================================================================
   МОБИЛЬНАЯ ВЕТКА дизайн-системы, семейство `.tvz-pd*` (канон —
   `docs/UI-MOBILE.md`). Завела её П-49 «Сделки на телефоне» (хендофф
   `_flow/handoff/deals-mobile/`), с П-55 в ней живёт и карточка клиента:
   семейство одно на всю ветку, новые узоры заводятся В НЁМ и тем же
   словарём, а не своим — иначе мобильные экраны разъедутся, и сводить их
   обратно будет дороже, чем договориться сейчас.

   ОТДЕЛЬНАЯ раскладка, не адаптив `.tvz-deal`/`.tvz-kan` выше: включается
   по `isPhoneView()` (people.js) — ширина ≤900px И грубый указатель (тот
   же признак, что у `pointerCanDial`, D-46). Узкое окно за столом
   (`pointer:fine`) этих классов не получает и продолжает видеть десктоп.

   ---------------------------------------------------------------------
   ТОКЕНЫ ветки. Всё, чему в палитре Works Light не нашлось имени, названо
   ЗДЕСЬ и один раз — и дальше по файлу встречается только как `var(…)`.

   П-49 писала эти цвета литералами по месту (21 штука: белый на акценте,
   подложка шторки, две тени, рамка просроченной задачи), и гейт краснел
   на них с самого слияния волны. Дело не в упрямстве правила: UI-STANDARD
   и говорит «нужен цвет — заведи семантический токен», а правило
   конформанса запрещало литерал ВЕЗДЕ, включая само объявление токена, —
   то есть запрещало и выход, который само же предписывает. Правило
   уточнено (не ослаблено): литерал законен ровно там, где он превращается
   в имя, — в блоке `:root` / `html[data-theme]`. Покрасить им элемент
   по-прежнему нельзя.

   `--c-ac-soft-*` — мягкий тон уже принятого акцента для целой ПОЛОСЫ
   «На этой неделе» (не для кнопки): готового в палитре нет, хендофф
   просит завести рядом (§Fidelity, таблица цветов). */
:root {
  --c-ac-soft-bg: #e7eefa;
  --c-ac-soft-bd: #cfdcf0;
  --c-ac-soft-tx: #1e3c68;
  --c-ac-soft-dot: #4a72ab;
  /* Текст и значок НА акцентной заливке. Белый в обеих темах намеренно:
     `--c-ac` и там и там достаточно тёмен, а `--c-surface` (белый только
     в светлой) дал бы в тёмной тёмное на синем. */
  --c-on-ac: #ffffff;
  /* Плашка счётчика внутри активного чипа — «белый, но тише». */
  --c-on-ac-soft: rgba(255, 255, 255, 0.22);
  /* Подложка шторки. Роль тени шторка не имеет вовсе — её играет эта
     подложка, поэтому тон один на обе темы. */
  --c-scrim: rgba(16, 24, 40, 0.4);
  /* Тени ветки. Своя, а не `--shadow-e1`: у карточки телефона одна мягкая
     ступень, у круглой кнопки — цветная, от акцента. */
  --sh-pd-card: 0 1px 2px rgba(16, 24, 40, 0.05);
  --sh-pd-fab: 0 8px 20px rgba(43, 76, 126, 0.35);
  /* Рамка галочки на просроченной задаче: янтарный фон уже занят полосой,
     рамке нужен свой, более тихий тон того же семейства. */
  --c-warn-bd: #f0d7a8;
  /* Рамка и текст полосы «Сделано сегодня» (П-57). У красной и у синей полос
     рамка своя (`--c-err-bd`, `--c-ac-soft-bd`), у зелёной имени не было:
     `--c-ok` слишком звонок для кромки, `--c-bd` — не того семейства. */
  --c-ok-bd: #c9ead9;
  /* ПОТОКИ ВЫРУЧКИ — четыре полосы списка сделок на телефоне (П-65):
     новые продажи · повторные · расширение · подписка.

     Это ТА ЖЕ система, что у групп ролей (`.tvz-rolepill--*`: акцент, циан,
     фиолетовый, зелёный) — один набор семейств на продукт, второго не
     заводим. Своими именами, а не `--c-cyanbg`/`--c-purplebg` напрямую, по
     двум причинам. Первая: полоса во всю ширину экрана требует тона ГЛУБЖЕ,
     чем пилюля на белом, — тинты палитры на ней расплываются в белизну
     (тот же довод, что у `--c-ac-soft-*`, заведённого П-49 рядом с
     `--c-ac-tint`). Вторая: у полосы четыре роли — фон, кромка, текст и
     точка, — и у палитры Works Light для них есть только две.

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

     Янтарного среди них нет и быть не может (правило 8 канона): он занят
     просроченной задачей ВНУТРИ карточки, и полоса им читалась бы бедой. */
  --c-flow-new-bg: #dde8f6;
  --c-flow-new-bd: #c3d5ec;
  --c-flow-new-tx: #1e3c68;
  --c-flow-new-dot: #2b4c7e;
  --c-flow-repeat-bg: #d6f2e4;
  --c-flow-repeat-bd: #b3e3cc;
  --c-flow-repeat-tx: #046046;
  --c-flow-repeat-dot: #12b76a;
  --c-flow-expand-bg: #e9e1f9;
  --c-flow-expand-bd: #d5c6f0;
  --c-flow-expand-tx: #5a26bd;
  --c-flow-expand-dot: #7c3aed;
  --c-flow-sub-bg: #d5ecf5;
  --c-flow-sub-bd: #b6dcea;
  --c-flow-sub-tx: #0b5c74;
  --c-flow-sub-dot: #0e7490;
}

html[data-theme="dark"] {
  --c-ac-soft-bg: #1a2740;
  --c-ac-soft-bd: #2c3f5e;
  --c-ac-soft-tx: #b7cbe8;
  --c-ac-soft-dot: #7098d8;
  --c-warn-bd: #5c4a1f;
  --c-ok-bd: #1c5943;
  /* Потоки выручки в тёмной (П-65). Фон и кромка берут глубокие тона тех же
     четырёх семейств, что и в светлой; текст и точка светлеют — на тёмной
     полосе читаемым остаётся светлое, а не насыщенное. */
  --c-flow-new-bg: #1a2740;
  --c-flow-new-bd: #2c3f5e;
  --c-flow-new-tx: #b7cbe8;
  --c-flow-new-dot: #5b82c4;
  --c-flow-repeat-bg: #0c3a2e;
  --c-flow-repeat-bd: #1c5943;
  --c-flow-repeat-tx: #7fd8b4;
  --c-flow-repeat-dot: #34d399;
  --c-flow-expand-bg: #2a2140;
  --c-flow-expand-bd: #3d3060;
  --c-flow-expand-tx: #c7b6f5;
  --c-flow-expand-dot: #a78bfa;
  --c-flow-sub-bg: #12333d;
  --c-flow-sub-bd: #1d4c59;
  --c-flow-sub-tx: #8fd8e6;
  --c-flow-sub-dot: #38cbe0;
}

/* Шелл-хром (бренд, лента разделов, топбар) уступает экран целиком — тот же
   приём `:has(.tvz-phead)`, что у узкой шапки телефонной формы (выше по
   файлу): другой экран стирает host, и `:has()` перестаёт совпадать сам,
   никакого состояния и явного снятия классов. */
@media (max-width: 900px) {
  /* Оболочка уходит СРАЗУ, а не когда мобильный экран уже нарисован.
     Признак `is-phone` ставит `app.js` в момент сборки каркаса — до
     первого запроса к серверу. Прежнее условие `:has(.tvz-pd)` ждало,
     пока экран появится в DOM, и всё это время человек смотрел на
     десктопную шапку с лентой разделов: «сначала отображается старый
     интерфейс и потом перерисовывается новый» (владелец, 04.08).

     `:has(.tvz-pd)` остаётся рядом — на случай экрана, который поставит
     мобильную раскладку сам, не спросив каркас. */
  /* На телефоне сетка каркаса — ОДНА колонка во весь экран. Вендорная
     раскладка держит две (сайдбар 252px + рабочая часть) и высоту строки
     в экран; сайдбар мы прячем, но колонка под него остаётся, а рабочая
     часть перестаёт растягиваться на всю строку — она получала 593px из
     844. Отсюда и ехал низ: колонка экрана считала высоту по содержимому,
     и таб-бар прилипал к шапке, пока не приедут строки. */
  .tvz-app.is-phone,
  .tvz-app:has(.tvz-pd) {
    grid-template-columns: 1fr;
  }

  /* Высота задаётся ОКНОМ, а не сеткой каркаса. `height: 100%` наследуется
     от строки грида, а строка на этом экране считалась по содержимому и
     давала 593px из 844 — низ уезжал вверх ровно на недостающее. Окно про
     свою высоту знает всегда; `dvh` — потому что на телефоне часть экрана
     занимает адресная строка браузера, и она то есть, то нет. */
  .tvz-app.is-phone .tvz-main,
  .tvz-app:has(.tvz-pd) .tvz-main {
    height: 100dvh;
    max-height: 100dvh;
  }

  .tvz-app.is-phone .tvz-side,
  .tvz-app.is-phone .tvz-top,
  .tvz-app:has(.tvz-pd) .tvz-side,
  .tvz-app:has(.tvz-pd) .tvz-top {
    display: none;
  }

  .tvz-app.is-phone .tvz-content,
  .tvz-app:has(.tvz-pd) .tvz-content {
    padding: 0;
  }

  /* Мобильный поиск (П-53) уступает экран по тому же правилу и по той же
     причине. Своя шапка `.tvz-msearch` у него уже есть — а над ней стояли
     ещё два ряда шелла: бренд с именем человека и лента разделов. Канон
     мобильной ветки этого не допускает прямо: шапка максимум три ряда,
     логотипа и второй навигации в ней нет (docs/UI-MOBILE.md, правила 1
     и 2). На живом стенде до первого клиента приходилось прокручивать
     четверть экрана — ровно то, что хендофф и просил убрать. */
  .tvz-app:has(.tvz-msearch) .tvz-side,
  .tvz-app:has(.tvz-msearch) .tvz-top {
    display: none;
  }

  /* И та же колонка высотой в экран, что у списка сделок: шапка и таб-бар
     не сжимаются, прокручивается только выдача. Без неё список рос за
     высоту страницы, а таб-бар уезжал в самый её конец — уйти с экрана
     можно было, лишь долистав до последнего клиента. */
  .tvz-app:has(.tvz-msearch) .tvz-content,
  .tvz-app:has(.tvz-msearch) .tvz-page--search,
  .tvz-app:has(.tvz-msearch) .tvz-page--search .tvz-page__body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
  }

  .tvz-app:has(.tvz-msearch) .tvz-page--search,
  .tvz-app:has(.tvz-msearch) .tvz-page--search .tvz-page__body {
    flex: 1;
    height: auto;
  }

  .tvz-app:has(.tvz-msearch) .tvz-mresults {
    flex: 1;
    overflow-y: auto;
    /* Боковые поля выдачи. Правило «мобильный экран отдаёт себе всё» выше
       обнуляет отступ содержимого — оно писалось под список сделок, где
       поля держит сам список. У поиска их держало содержимое страницы, и
       после того как он получил тот же корень `.tvz-pd`, карточки встали
       вплотную к кромке экрана (слово владельца 04.08: «слишком маленькие
       отступы по краям, на других экранах нормально»). Двенадцать — та же
       мера, что у списка сделок и у карточек в канон-таблице ветки. */
    padding: 0 12px 12px;
  }

  /* Шапка поиска бежит вровень с кромкой (она липкая и во всю ширину), но
     компенсацию `margin: 0 -12px` ей теперь давать нечего — отступ снят у
     содержимого, а не у неё. */
  .tvz-app:has(.tvz-msearch) .tvz-msearch {
    margin: 0 0 8px;
    padding: 0 12px;
  }
}

.tvz-pd {
  display: flex;
  flex-direction: column;
  /* Обнуляет `gap` дизайн-системного `.tvz-page__body` (design.css/shell.css):
     этот корень нарочно несёт ОБА класса разом (см. deals_mobile.js — общий
     признак «тело страницы» для обхода всех экранов, D-89), а зазор между
     шапкой/списком/таб-баром здесь свой, нулевой — разметка экрана как в
     хендоффе, без воздуха дизайн-системной колонки. */
  gap: 0;
  height: 100%;
  min-height: 100dvh;
  overflow: hidden;
  background: var(--c-bg);
  position: relative;
}

.tvz-pd--err {
  padding: 16px;
  color: var(--c-err);
}

/* --- 1. Шапка (максимум три ряда, §7.1) ------------------------------------ */

.tvz-pd__head {
  flex: none;
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-bd);
}

.tvz-pd__title-row {
  padding: 8px 12px 8px;
  display: flex;
  align-items: center;
  gap: 10px;
}

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

.tvz-pd__title {
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--c-tx);
}

.tvz-pd__summary {
  font-size: 11.5px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Организация в шапке мобильной карточки контакта — ссылкой на карточку
   клиента (П-80): наследует размер строки `.tvz-pd__summary`, а не
   собственный 12.5px `.tvz-linkbtn` — сосед по строке молчит текстом,
   и разный размер читался бы как два разных сорта слов в одной мысли. */
.tvz-pd__org-link {
  font-size: inherit;
  color: var(--c-ac);
}

.tvz-pd__iconbtn {
  flex: none;
  width: 40px;
  height: 40px;
  border: none;
  background: var(--c-chip);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-tx-2);
  cursor: pointer;
}

.tvz-pd__iconbtn:hover {
  background: var(--c-bd);
}

.tvz-pd__avatar {
  flex: none;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 999px;
  background: var(--c-ac-d);
  color: var(--c-on-ac);
  font-size: 12.5px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* Ряд 2 шапки карточки клиента (П-55) — владелец отношений. Своего ряда
   у списка сделок нет: там второй строкой идёт итог по фильтру. Тихая
   пара «подпись — значение» в одну строку: кто отвечает за клиента,
   спрашивают первым, но акцент карточки — имя клиента, не фамилия
   менеджера (правило 6 ветки, один акцент). */
.tvz-pd__owner {
  display: flex;
  align-items: baseline;
  gap: 7px;
  padding: 0 12px 8px;
  min-width: 0;
}

.tvz-pd__owner-l {
  flex: none;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}

.tvz-pd__owner-v {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--c-tx-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__chips {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px 9px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tvz-pd__chips::-webkit-scrollbar {
  display: none;
}

.tvz-pd__chip {
  flex: none;
  height: 32px;
  padding: 0 6px 0 12px;
  border-radius: 999px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

.tvz-pd__chip.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac);
  color: var(--c-on-ac);
}

.tvz-pd__chip-n {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--c-chip);
  color: var(--c-mut);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
}

.tvz-pd__chip.is-active .tvz-pd__chip-n {
  background: var(--c-on-ac-soft);
  color: var(--c-on-ac);
}

.tvz-pd__chipsep {
  flex: none;
  width: 1px;
  height: 20px;
  margin: 0 3px;
  background: var(--c-bd);
}

/* «Мой день» несёт четыре фильтра, и на 390px («Все» · «Просрочены» ·
   «Сегодня» · «Без сделки») они шире одной строки — горизонтальная
   прокрутка базового узора упирала последний в правый край экрана без
   подсказки, что дальше можно свайпнуть (П-87, находка Маргариты 05.08:
   «Без сде…» — «я не знаю, что там дальше»). Перенос вместо прокрутки —
   все фильтры видны сразу, скроллить нечего. Область — только «Мой день»
   (`data-myday="mobile"`, myday_mobile.js): у карточки клиента и списка
   сделок та же лента чипов держит горизонтальную прокрутку намеренно
   (короткий набор, длинные подписи потоков) и здесь не тронута. */
[data-myday="mobile"] .tvz-pd__chips {
  flex-wrap: wrap;
  overflow-x: visible;
}

/* Липкий заголовок полосы не режет карточку тихо (П-87, находка Маргариты
   05.08): пальцем можно остановить прокрутку РОВНО там, где заголовок
   («НА СЕГОДНЯ» и т.п., `position: sticky; top: 0` у `.tvz-pd__section-hd`)
   наехал на середину карточки — видно «Сделано / Балашов», а что за
   задача, отрезано; читается как поломанная карточка, не как прокрутка.
   `scroll-snap-type: y proximity` мягко доводит точку покоя до целой
   карточки или целого заголовка — «proximity», а не «mandatory»: не дёргает
   палец при обычной прокрутке, включается только у естественной точки
   остановки. `scroll-margin-top` у карточки — высота липкого заголовка
   (замер на стенде: паддинг 7px×2 + строка ≈ 34px), чтобы снэп не подвёл
   карточку ПОД заголовок тем же способом, каким он её и резал. Область —
   только «Мой день» (`data-myday="mobile"`, myday_mobile.js): у списка
   сделок та же полоса живёт без снэпа намеренно (карточки одного тона
   подряд, резать нечего, П-49/П-65). */
[data-myday="mobile"] .tvz-pd__list {
  scroll-snap-type: y proximity;
}
[data-myday="mobile"] .tvz-pd__section-hd {
  scroll-snap-align: start;
}
[data-myday="mobile"] .tvz-pd__card {
  scroll-snap-align: start;
  scroll-margin-top: 34px;
}

.tvz-pd__sort {
  flex: none;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 999px;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx-2);
  cursor: pointer;
  white-space: nowrap;
}

/* --- 2. Список: полосы приоритета + карточки ------------------------------- */

.tvz-pd__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 0 84px;
}

/* Список сделок на телефоне несёт свой плавающий «+» (`.tvz-pd__fab`,
   П-49) — он висит НАД списком, а не рядом: замер на стенде (375×812)
   показал, что общих 84px хватает домотать до конца ровно впритык (69px
   нужно, чтобы разойтись с верхним краем кнопки, 15px запаса). Находка
   Маргариты №2 (06.08, «+ накрывает дату последней карточки») ловит
   кнопку не в покое, а НА ПРОКРУТКЕ — так ведёт себя любой плавающий
   «+», и это не чинится нижним отступом (он про КОНЕЦ списка). Отступ
   всё равно увеличен — с впритык на честный запас, — чтобы последняя
   карточка гарантированно расходилась с кнопкой даже на дребезге инерционной
   прокрутки iOS (`overscroll` может на миг обнажить хвост сверх
   `scrollHeight`, и 15px запаса это не переживут). */
[data-deals="mobile"] .tvz-pd__list {
  padding-bottom: 112px;
}

/* Обёртка полос и обёртка одной полосы. Объявлены явно, хотя своей геометрии
   почти не несут: класс в разметке без объявления в CSS — молчаливо
   неоформленный кусок экрана (правило конформанса). У `__section` роль
   несущая: липкий заголовок (`position: sticky`) прилипает к БЛИЖАЙШЕМУ
   скроллящемуся предку и уезжает, как только кончается его собственный
   короб, — без этой обёртки все три заголовка слиплись бы в стопку наверху
   списка. */
.tvz-pd__sections {
  display: flow-root;
}

.tvz-pd__section {
  display: flow-root;
}

.tvz-pd__section-hd {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 7px 14px;
  display: flex;
  align-items: center;
  gap: 7px;
  border-top: 1px solid transparent;
  border-bottom: 1px solid transparent;
}

.tvz-pd__section-hd--err {
  background: var(--c-errbg);
  border-color: var(--c-err-bd);
  color: var(--c-err);
}

.tvz-pd__section-hd--acsoft {
  background: var(--c-ac-tint);
  border-color: var(--c-ac-bd);
  color: var(--c-ac-d);
}

.tvz-pd__section-hd--mut {
  background: var(--c-hover);
  border-color: var(--c-bd);
  color: var(--c-mut);
}

.tvz-pd__section-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: currentColor;
}

.tvz-pd__section-hd--acsoft .tvz-pd__section-dot {
  background: var(--c-ac);
}

.tvz-pd__section-hd--err .tvz-pd__section-dot {
  background: var(--c-err);
}

/* Четыре полосы ПОТОКОВ ВЫРУЧКИ — список сделок на телефоне (П-65).

   Геометрия у них общая с полосами приоритета выше и своей не заводит:
   меняется вопрос, на который отвечает полоса, а не сама полоса. Тона —
   `--c-flow-*`, объявленные в блоке токенов ветки; система та же, что у
   групп ролей, один набор на продукт.

   Точка своя у каждой, а не `currentColor` (умолчание `.tvz-pd__section-dot`):
   в этой палитре текст приглушён до читаемого на заливке, а точка держит
   насыщенное семейство — её узнают краем глаза, не читая. */
.tvz-pd__section-hd--flow-new {
  background: var(--c-flow-new-bg);
  border-color: var(--c-flow-new-bd);
  color: var(--c-flow-new-tx);
}

.tvz-pd__section-hd--flow-new .tvz-pd__section-dot {
  background: var(--c-flow-new-dot);
}

.tvz-pd__section-hd--flow-repeat {
  background: var(--c-flow-repeat-bg);
  border-color: var(--c-flow-repeat-bd);
  color: var(--c-flow-repeat-tx);
}

.tvz-pd__section-hd--flow-repeat .tvz-pd__section-dot {
  background: var(--c-flow-repeat-dot);
}

.tvz-pd__section-hd--flow-expand {
  background: var(--c-flow-expand-bg);
  border-color: var(--c-flow-expand-bd);
  color: var(--c-flow-expand-tx);
}

.tvz-pd__section-hd--flow-expand .tvz-pd__section-dot {
  background: var(--c-flow-expand-dot);
}

.tvz-pd__section-hd--flow-sub {
  background: var(--c-flow-sub-bg);
  border-color: var(--c-flow-sub-bd);
  color: var(--c-flow-sub-tx);
}

.tvz-pd__section-hd--flow-sub .tvz-pd__section-dot {
  background: var(--c-flow-sub-dot);
}

.tvz-pd__section-t {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.tvz-pd__section-n {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
  opacity: 0.7;
}

/* Блоки, приезжающие в мобильный список готовыми из общих мест: плашка
   запрета прямого общения (`noDirectBanner`) и ряд «связи нет» внутри
   карточки человека (`channelActions`, ветка запрета). Слова у них общие с
   десктопом — переписывать их здесь значило бы завести второй экземпляр
   правила; мобильной раскладке нужны от них только поля. */
.tvz-pd__list > .tvz-warnbox {
  margin: 8px 12px 0;
}

.tvz-pd__card > .tvz-acts {
  padding: 9px 12px 11px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__tail {
  padding: 16px 12px 8px;
  text-align: center;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* --- 2.2 Карточка сделки: три яруса ----------------------------------------- */

.tvz-pd__card {
  margin: 8px 12px 0;
  border: 1px solid var(--c-bd);
  border-radius: 14px;
  background: var(--c-surface);
  box-shadow: var(--sh-pd-card);
  overflow: hidden;
}

.tvz-pd__body {
  width: 100%;
  border: none;
  background: none;
  padding: 11px 12px 9px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  text-align: left;
  cursor: pointer;
  color: inherit;
}

.tvz-pd__body:hover {
  background: var(--c-hover);
}

.tvz-pd__toprow {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
}

.tvz-pd__client {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__silence {
  flex: none;
  height: 20px;
  padding: 0 8px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.tvz-pd__silence--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__silence--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

.tvz-pd__silence--mut {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

.tvz-pd__name {
  width: 100%;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--c-tx);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tvz-pd__money {
  display: flex;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  flex-wrap: wrap;
}

.tvz-pd__money-item {
  display: flex;
  align-items: baseline;
  gap: 5px;
}

.tvz-pd__money-k {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.tvz-pd__money-k--once {
  color: var(--c-tx-4);
}

.tvz-pd__money-k--year {
  color: var(--c-ok-d);
}

.tvz-pd__money-v {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.tvz-pd__money-v--once {
  color: var(--c-tx);
}

.tvz-pd__money-v--once.is-zero {
  color: var(--c-tx-4);
}

.tvz-pd__money-v--year {
  color: var(--c-ok-d);
}

/* Карточка человека на карточке клиента (П-55): должность тихой строкой,
   роль пилюлей. Имя берёт готовый `.tvz-pd__name` (16/700) — один акцент на
   карточку, как у названия сделки.

   Пилюля роли НЕЙТРАЛЬНАЯ, в отличие от зелёной пилюли этапа выше: у ветки
   ровно три цвета-сигнала, и каждый значит одно (правило 8). Зелёный на роли
   читался бы как «в порядке», а роль ни о чём таком не сообщает. */
.tvz-pd__post {
  width: 100%;
  font-size: 12px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__role {
  align-self: flex-start;
  max-width: 100%;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  /* `inline-block`, а не `inline-flex`: у флексбокса голый текст становится
     анонимным элементом, и многоточие обрезки к нему не применяется — пилюля
     «Технические вопросы · Общий ответственный по клиенту» уезжала за край
     карточки без единого признака, что текст продолжается. */
  display: inline-block;
  line-height: 24px;
  font-size: 12px;
  font-weight: 600;
  background: var(--c-chip);
  color: var(--c-tx-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Пометка «через партнёра» в карточке человека. Ровно тот факт, из-за
   которого у этого человека кнопки РАБОЧИЕ, когда у остальных людей клиента
   они погашены: он и есть предписанный обход. Молчать о нём на телефоне
   нельзя — менеджер должен знать, кому звонит. */
.tvz-pd__body > .tvz-partner {
  align-self: flex-start;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Пробелы покрытия — карточкой над списком, а не полосой раздела: это не
   заголовок для чего-то следующего ниже, а самостоятельный факт о клиенте
   («роль не закрыта нигде»). Красный: «просело» — ровно то значение,
   которое за этим цветом закреплено. */
.tvz-pd__gaps {
  margin: 8px 12px 0;
  padding: 9px 12px;
  border: 1px solid var(--c-err-bd);
  border-radius: 14px;
  background: var(--c-errbg);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.tvz-pd__gaps-t {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-err);
}

.tvz-pd__gaps-l {
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--c-tx-2);
}

/* Поиск по людям и фильтр по структуре карточки клиента (П-83). Липкая
   панель над лентой — тем же узором поля/кнопки, что у мобильного поиска
   контактов (`.tvz-msearch__field/__in/__x`, `.tvz-msearch__fltbtn/__fltn`,
   выше в этом файле): второй узор искать не пришлось, свои здесь только
   обёртка и раскладка ряда. `z-index` на единицу выше заголовков разделов
   (`.tvz-pd__section-hd`, тоже липких) — панель обязана лежать НАД ними,
   когда лента прокручена и оба стоят у кромки одновременно. */
.tvz-pd__psearch {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--c-surface);
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-bottom: 1px solid var(--c-bd);
}

.tvz-pd__psearch-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-pd__psearch-field {
  flex: 1;
  min-width: 0;
}

.tvz-pd__pchiprow {
  display: flex;
  gap: 6px;
}

.tvz-pd__pchiprow[hidden] {
  display: none;
}

/* Обёртка пробелов/разделов/хвоста ленты людей — своя, не общий
   `.tvz-pd__sections` (deals_mobile.js/myday_mobile.js несут им только
   `.tvz-pd__section`, здесь ещё пробелы и хвост/пустая выдача). Перекраивается
   целиком на каждое изменение поиска/фильтра — `flow-root` тем же приёмом
   не даёт полям её содержимого схлопнуть отступ наружу. */
.tvz-pd__pfeed {
  display: flow-root;
}

/* Пустая выдача поиска/фильтра ленты людей — общий класс большого поиска
   (`.tvz-sempty`, выше в этом файле), своя только отбивка от кромок
   `.tvz-pd__list` (у него самого горизонтальных полей нет — их держит
   содержимое, тем же приёмом, что у `.tvz-pd__list > .tvz-warnbox`). */
.tvz-pd__fempty {
  margin: 8px 12px 0;
}

/* «Ещё не начали» (П-87, B-44/B-63): клиента только что завели, пробелов
   ещё не существует как факта — карточка обязана сказать это спокойным
   info-тоном, не красной простынёй (тот же приём, что у desktop-варианта
   `.tvz-ccard__gaps.is-calm`, cards.js). */
.tvz-pd__gaps.is-calm {
  border-color: var(--c-info);
  background: var(--c-infobg);
}
.tvz-pd__gaps.is-calm .tvz-pd__gaps-t {
  color: var(--c-info);
}
/* «Показать» простыни, свёрнутой B-141: та же ссылка-кнопка, что у
   desktop-аналога (`.tvz-ccard__group-more`, cards.js) — своя копия, а не
   общий класс, т.к. родитель здесь `flex-direction: column`, не строка. */
.tvz-pd__gaps-show {
  align-self: flex-start;
  border: none;
  background: none;
  padding: 0;
  margin-top: 1px;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--c-ac);
}
.tvz-pd__gaps-show:hover {
  text-decoration: underline;
}

.tvz-pd__stage {
  align-self: flex-start;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  background: var(--c-okbg);
  color: var(--c-ok-d);
}

/* Ярус 2 — следующий шаг: кнопка на всю ширину, ≥44px (касание, §7.5). */

.tvz-pd__task {
  min-height: 44px;
  padding: 7px 12px;
  display: flex;
  align-items: center;
  gap: 9px;
  border-top: 1px solid var(--c-bd2);
  cursor: pointer;
  background: var(--c-surface);
}

.tvz-pd__task:hover {
  background: var(--c-hover);
}

.tvz-pd__task--empty {
  background: var(--c-hover);
}

.tvz-pd__task--empty:hover {
  background: var(--c-bd2);
}

.tvz-pd__task--late {
  background: var(--c-warnbg);
}

.tvz-pd__task--late:hover {
  background: var(--c-warnbg);
}

.tvz-pd__task-ic {
  flex: none;
  display: flex;
  color: var(--c-tx-4);
}

.tvz-pd__task--empty .tvz-pd__task-ic {
  color: var(--c-ac);
}

.tvz-pd__task--late .tvz-pd__task-ic {
  color: var(--c-warn);
}

.tvz-pd__task-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.tvz-pd__task-text {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__task-text--accent {
  font-weight: 500;
  color: var(--c-ac);
}

.tvz-pd__task-when {
  font-size: 11px;
  font-weight: 600;
  color: var(--c-tx-4);
}

.tvz-pd__task-when--late {
  color: var(--c-warn);
}

.tvz-pd__task-done {
  flex: none;
  width: 34px;
  height: 34px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ok-d);
  cursor: pointer;
}

.tvz-pd__task--late .tvz-pd__task-done {
  border-color: var(--c-warn-bd);
}

/* Ярус 3 — действия. */

.tvz-pd__acts {
  display: flex;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__act {
  flex: 1;
  min-width: 0;
  height: 44px;
  border: none;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.tvz-pd__act--call {
  color: var(--c-ac);
}

.tvz-pd__act--call:hover {
  background: var(--c-ac-tint);
}

.tvz-pd__act--call.is-disabled {
  color: var(--c-tx-4);
  cursor: not-allowed;
}

.tvz-pd__act--note {
  color: var(--c-tx-2);
}

.tvz-pd__act--note:hover {
  background: var(--c-hover);
}

.tvz-pd__actsep {
  flex: none;
  width: 1px;
  background: var(--c-bd2);
}

/* --- 4. FAB «Завести сделку» ------------------------------------------------ */

.tvz-pd__fab {
  position: absolute;
  z-index: 20;
  right: 14px;
  bottom: 78px;
  width: 54px;
  height: 54px;
  border: none;
  background: var(--c-ac);
  border-radius: 999px;
  box-shadow: var(--sh-pd-fab);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-on-ac);
  cursor: pointer;
}

.tvz-pd__fab:hover {
  background: var(--c-ac-d);
}

/* --- 5. Таб-бар --------------------------------------------------------------- */

/* Стоит последним в колонке высотой в экран — и потому всегда на виду, без
   вывода из потока. Фиксировать его к окну нельзя: подложка шторки лежит
   внутри той же колонки (`inset: 0`), и выпавший из потока таб-бар отнимал
   у неё дно — лист переставал доставать до кромки экрана. Значит колонку
   обязан строить КАЖДЫЙ мобильный экран, а не только список сделок. */
/* ---- скелет загрузки мобильного экрана ----------------------------------
   Форма экрана без содержимого: шапка, полоса, три карточки. Пустой экран
   между входом и первым ответом читается как «не загрузилось», крутилка
   говорит «жди», но не говорит чего, — а скелет держит будущую раскладку,
   и приход дел не двигает страницу под пальцем.

   Мерцание тише привычного: экран открывается по входу, и бойкая анимация
   на первом же кадре читается как суета. */
.tvz-pd__skel-line,
.tvz-pd__skel-dot,
.tvz-pd__skel-band {
  background: var(--c-bd);
  border-radius: var(--rad-pill);
  animation: tvz-skel 1.4s ease-in-out infinite;
}

.tvz-pd__skel-line {
  height: 12px;
}

.tvz-pd__skel-line--title {
  height: 21px;
  width: 46%;
}

.tvz-pd__skel-line--sub {
  width: 62%;
  margin-top: 8px;
}

.tvz-pd__skel-line--name {
  height: 16px;
  width: 84%;
  margin-top: 8px;
}

.tvz-pd__skel-line--tag {
  width: 38%;
  margin-top: 10px;
}

.tvz-pd__skel-dot {
  width: 40px;
  height: 40px;
  border-radius: 999px;
  flex: none;
}

.tvz-pd__skel-band {
  height: 30px;
  border-radius: 0;
  margin-bottom: 8px;
}

.tvz-pd__skel-card {
  padding: 11px 12px 13px;
}

/* Заглушки строк выдачи поиска — та же шкура, что у настоящей карточки,
   иначе смена заглушки на строку двигала бы список. Контейнер объявлен
   отдельно: он нужен, чтобы отличать заглушку от настоящей выдачи при
   первой замене. */
.tvz-mcards--skel {
  pointer-events: none;
}

.tvz-mcard--skel {
  display: flex;
  flex-direction: column;
  gap: 2px;
  pointer-events: none;
}

.tvz-pd--skel {
  overflow: hidden;
}

@keyframes tvz-skel {
  0%, 100% { opacity: 1; }
  50% { opacity: .55; }
}

.tvz-pd__tabbar {
  flex: none;
  background: var(--c-surface);
  border-top: 1px solid var(--c-bd);
  padding: 6px 8px calc(8px + env(safe-area-inset-bottom));
  display: flex;
  align-items: stretch;
  gap: 2px;
}

/* Выдаче мобильного поиска — то же место под таб-баром, что у списка сделок:
   без него последняя карточка прячется под навигацией. */
.tvz-mresults {
  padding-bottom: 84px;
}

.tvz-pd__tab {
  flex: 1;
  min-width: 0;
  height: 48px;
  border: none;
  border-radius: 12px;
  background: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
  color: var(--c-tx-4);
}

.tvz-pd__tab.is-active {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__tab-lbl {
  font-size: 10.5px;
  font-weight: 600;
}

/* --- 3. Шторка «Следующий шаг» / «Запись в сделку» (bottom sheet) ----------- */

/* Кроет вендорную `.tvz-modal-back` (она стоит на элементе первой): затемнение
   общее с окнами за столом, здесь меняется только положение — шторка прижата
   ко дну экрана, а не к верху, и живёт внутри рамки телефона. */
/* Кроет ЭКРАН целиком, а не остаток колонки. `inset: 0` здесь несущий: без
   него подложка получала высоту оставшегося места между списком и таб-баром,
   и лист шторки не доставал до кромки экрана — снизу оставалась светлая
   полоса в полтораста пикселей. */
.tvz-pd__sheetback {
  position: absolute;
  inset: 0;
  z-index: 40;
  background: var(--c-scrim);
  display: flex;
  align-items: flex-end;
  outline: none;
}

.tvz-pd__sheet {
  width: 100%;
  max-height: 94%;
  background: var(--c-surface);
  border-radius: 20px 20px 24px 24px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.tvz-pd__sheet-handle {
  flex: none;
  margin: 8px auto 0;
  width: 36px;
  height: 4px;
  border-radius: 999px;
  background: var(--c-line-strong);
}

.tvz-pd__sheet-head {
  flex: none;
  padding: 8px 14px 10px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-pd__sheet-titles {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tvz-pd__sheet-title {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--c-tx);
}

.tvz-pd__sheet-sub {
  font-size: 12px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__sheet-close {
  flex: none;
  width: 32px;
  height: 32px;
  border: none;
  background: var(--c-chip);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-mut);
  cursor: pointer;
}

.tvz-pd__sheet-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.tvz-pd__lbl {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}

.tvz-pd__presets {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -14px;
  padding: 0 14px;
}

.tvz-pd__presets::-webkit-scrollbar {
  display: none;
}

.tvz-pd__preset {
  flex: none;
  height: 30px;
  padding: 0 11px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

.tvz-pd__preset.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-weight: 600;
}

.tvz-pd__textarea {
  width: 100%;
  min-height: 58px;
  padding: 10px 11px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 11px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--c-tx);
  outline: none;
  resize: none;
}

.tvz-pd__textarea:focus {
  border-color: var(--c-ac);
  background: var(--c-surface);
}

.tvz-pd__voice {
  display: flex;
  flex-direction: column;
}

.tvz-pd__rec {
  width: 100%;
  min-height: 52px;
  padding: 8px 11px 8px 8px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  border: 1px dashed var(--c-line-strong);
  background: var(--c-hover);
}

.tvz-pd__rec.is-recording {
  border: 1px solid var(--c-err-bd);
  background: var(--c-errbg);
}

.tvz-pd__rec-ic {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__rec.is-recording .tvz-pd__rec-ic {
  background: var(--c-err);
  color: var(--c-on-ac);
}

.tvz-pd__rec-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-align: left;
}

.tvz-pd__rec-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--c-tx);
}

.tvz-pd__rec-hint {
  font-size: 11px;
  color: var(--c-tx-4);
  line-height: 1.35;
}

.tvz-pd__rec-time {
  flex: none;
  font-size: 13px;
  font-weight: 600;
  color: var(--c-err);
}

.tvz-pd__player {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px 10px;
  border: 1px solid var(--c-ac-bd);
  background: var(--c-ac-tint);
  border-radius: 11px;
}

.tvz-pd__player-row {
  display: flex;
  align-items: center;
  gap: 9px;
}

.tvz-pd__player-play {
  flex: none;
  width: 32px;
  height: 32px;
  border: none;
  background: var(--c-ac);
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-on-ac);
  cursor: pointer;
}

.tvz-pd__wave {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 2px;
  height: 22px;
}

.tvz-pd__wave-bar {
  flex: 1;
  min-width: 2px;
  border-radius: 999px;
  background: var(--c-ac-l);
}

.tvz-pd__audio-len {
  flex: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--c-ac);
}

.tvz-pd__audio-drop {
  flex: none;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ac-l);
  cursor: pointer;
}

.tvz-pd__audio-drop:hover {
  background: var(--c-ac-bd);
  color: var(--c-ac);
}

.tvz-pd__agentnote {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-top: 7px;
  margin-top: 2px;
  border-top: 1px solid var(--c-ac-bd);
}

.tvz-pd__agentnote span:last-child {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  color: var(--c-ac);
  line-height: 1.35;
}

.tvz-pd__agentdot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--c-ac);
}

.tvz-pd__whens {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}

.tvz-pd__when {
  height: 46px;
  padding: 0 11px;
  border-radius: var(--rad-lg);
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx);
}

.tvz-pd__when span:first-child {
  flex: 1;
  min-width: 0;
}

.tvz-pd__when.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-weight: 600;
}

.tvz-pd__when-d {
  flex: none;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-tx-4);
}

.tvz-pd__when.is-active .tvz-pd__when-d {
  color: var(--c-ac);
}

.tvz-pd__dateinput {
  width: 100%;
}

/* ---------------------------------------------------------------------------
   Шторка «Записать касание» (П-66, B3)

   Своих правил здесь ровно столько, сколько у касания отличается от шторки
   задачи: плитки вида, чипы собеседников, вложение и галочка «поставить
   следующий шаг». Всё остальное — лист, кикеры, чипы формулировок, поле
   ввода, голос, кнопки низа — узоры П-49 выше по файлу, взятые как есть.
   Форма ОДНА на один жест: второй записи в ленту в продукте нет (B-80).
   --------------------------------------------------------------------------- */

/* «Что было» — сетка 2×2 тех же 44px, что «когда» у задачи: две формы одного
   вида на соседних экранах обязаны выглядеть одинаково. */
.tvz-pd__kinds {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}

.tvz-pd__kind {
  min-height: 44px;
  padding: 0 11px;
  border-radius: var(--rad-lg);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

.tvz-pd__kind-i {
  flex: none;
  display: flex;
}

.tvz-pd__kind-t {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__kind.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-weight: 600;
}

/* «С кем» — лента чипов 34px. Уезжает за край карточки теми же полями, что
   лента формулировок: чип, обрезанный кромкой листа, читается как «список
   кончился». */
.tvz-pd__mates {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -14px;
  padding: 0 14px;
}

.tvz-pd__mates::-webkit-scrollbar {
  display: none;
}

.tvz-pd__mate {
  flex: none;
  height: 34px;
  padding: 0 13px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

/* Выбранный собеседник залит акцентом, а не подцвечен: это ОДИН из списка,
   и мягкая подсветка на ленте чипов не отличается от наведения. */
.tvz-pd__mate.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac);
  color: var(--c-on-ac);
}

/* Вложение внутри шторки. Пунктирная рамка — «сюда можно положить», а не
   «здесь что-то есть»: сплошная читалась бы как уже приложенный файл. */
.tvz-pd__att {
  display: flex;
  flex-direction: column;
}

.tvz-pd__att-add {
  width: 100%;
  min-height: 48px;
  padding: 8px 11px 8px 8px;
  border: 1px dashed var(--c-line-strong);
  background: var(--c-hover);
  border-radius: var(--rad-lg);
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.tvz-pd__att-add:hover {
  background: var(--c-chip);
}

.tvz-pd__att-c {
  width: 100%;
  min-height: 48px;
  padding: 8px 8px 8px 8px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: var(--rad-lg);
  display: flex;
  align-items: center;
  gap: 10px;
}

.tvz-pd__att-i {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__att-b {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-align: left;
}

.tvz-pd__att-t {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__att-s {
  font-size: 11px;
  line-height: 1.35;
  color: var(--c-tx-4);
}

.tvz-pd__att-x {
  flex: none;
  width: 32px;
  height: 32px;
  border: none;
  background: none;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-mut);
  cursor: pointer;
}

.tvz-pd__att-x:hover {
  background: var(--c-chip);
}

/* «Поставить следующий шаг после сохранения». Включена по умолчанию — это и
   есть смысл строки: записал касание, тут же назначаешь, что дальше. Тон
   акцентный, потому что состояние несёт ЧЕКБОКС, а строка только объясняет,
   что произойдёт (тот же урок, что у окна ролей: заливка — не состояние). */
.tvz-pd__next {
  width: 100%;
  min-height: 44px;
  padding: 9px 10px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 11px;
  display: flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  text-align: left;
}

.tvz-pd__next.is-on {
  border-color: var(--c-ac-bd);
  background: var(--c-ac-tint);
}

.tvz-pd__next-box {
  flex: none;
  width: 20px;
  height: 20px;
  border: 1.5px solid var(--c-line-strong);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-surface);
  color: transparent;
}

.tvz-pd__next.is-on .tvz-pd__next-box {
  border-color: var(--c-ac);
  background: var(--c-ac);
  color: var(--c-on-ac);
}

.tvz-pd__next-t {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--c-tx-2);
}

.tvz-pd__next.is-on .tvz-pd__next-t {
  color: var(--c-ac);
}

.tvz-pd__timearea {
  display: flex;
}

.tvz-pd__addtime {
  align-self: flex-start;
  height: 32px;
  padding: 0 11px 0 9px;
  border: 1px dashed var(--c-line-strong);
  background: var(--c-hover);
  border-radius: 999px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx-2);
  cursor: pointer;
}

.tvz-pd__addtime:hover {
  background: var(--c-bd2);
  color: var(--c-tx);
}

.tvz-pd__timebox {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 10px;
  border: 1px solid var(--c-ac-bd);
  background: var(--c-ac-tint);
  border-radius: 11px;
}

.tvz-pd__timebox-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-pd__timebox-k {
  flex: 1;
  min-width: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--c-ac);
}

.tvz-pd__time-input {
  flex: none;
  width: 66px;
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--c-ac-bd);
  background: var(--c-surface);
  border-radius: 8px;
  font-size: 13.5px;
  font-weight: 600;
  text-align: center;
  color: var(--c-tx);
  outline: none;
}

.tvz-pd__time-input:focus {
  border-color: var(--c-ac);
}

.tvz-pd__time-drop {
  flex: none;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ac-l);
  cursor: pointer;
}

.tvz-pd__time-drop:hover {
  background: var(--c-ac-bd);
  color: var(--c-ac);
}

.tvz-pd__slots {
  display: flex;
  gap: 5px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tvz-pd__slots::-webkit-scrollbar {
  display: none;
}

.tvz-pd__slot {
  flex: none;
  height: 28px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--c-ac-bd);
  background: var(--c-surface);
  color: var(--c-ac);
}

.tvz-pd__slot.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac);
  color: var(--c-on-ac);
}

.tvz-pd__whos {
  display: flex;
  gap: 6px;
}

.tvz-pd__who {
  flex: 1;
  min-width: 0;
  height: 42px;
  padding: 0 10px;
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

.tvz-pd__who.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-weight: 600;
}

.tvz-pd__assignee {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tvz-pd__assignee-chip {
  height: 30px;
  padding: 0 11px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-tx-2);
}

.tvz-pd__assignee-chip.is-active {
  border-color: var(--c-ac);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-weight: 600;
}

.tvz-pd__mut {
  font-size: 12.5px;
  color: var(--c-tx-4);
}

.tvz-pd__sheet-foot {
  flex: none;
  padding: 10px 14px 16px;
  border-top: 1px solid var(--c-bd2);
  background: var(--c-surface);
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.tvz-pd__save {
  height: 48px;
  border-radius: 13px;
  font-size: 15px;
  font-weight: 600;
  border: 1px solid var(--c-bd);
  background: var(--c-chip);
  color: var(--c-tx-4);
  cursor: not-allowed;
}

.tvz-pd__save.is-ready {
  border-color: var(--c-ac);
  background: var(--c-ac);
  color: var(--c-on-ac);
  cursor: pointer;
}

.tvz-pd__cancel {
  height: 40px;
  border: none;
  background: none;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--c-mut);
  cursor: pointer;
}

/* ============================================================================
   Карточка контакта на телефоне — второй экран мобильной ветки (П-56).

   Своей вёрстки здесь ровно столько, сколько у контакта отличается от списка
   сделок: крупные действия связи, строки «подпись — значение», строка ленты
   и пилюли. Всё остальное — шапка, липкие разделы, карточки, лента чипов,
   таб-бар — это узоры П-49 выше по файлу, взятые как есть (`docs/UI-MOBILE.md`
   §3: новый мобильный экран берёт узоры оттуда, а не изобретает своё).

   Десктоп не задет ничем: правила ниже начинаются либо с `.tvz-pd--contact`
   (класс, который ставит только мобильная карточка), либо стоят в медиа-
   запросе `pointer: coarse`. Узкое окно за столом ни одного из них не видит.
   ============================================================================ */

/* Корень: та же колонка на весь экран, что у списка сделок. Объявлен явно —
   класс без объявления на экране ничего не делает и молчит об этом. */
.tvz-pd--contact {
  background: var(--c-bg);
}

/* --- 1. Шапка: имя, место работы, вердикт ---------------------------------- */

/* Вердикт стоит В ОДНОЙ строке с должностью, а не рядом с именем: на 390
   точках пилюля рядом с именем 21px съедала бы у фамилии половину места, и
   первая секунда карточки (правило П-42: человек видит имя) досталась бы
   многоточию. */
.tvz-pd__submeta {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

/* Место работы дописывается второй строкой, а не обрезается: §1 постановки
   просит «имя, должность, место работы», а в одну строку на 390 точках
   помещается должность и многоточие — организация пропадала целиком. */
.tvz-pd__submeta .tvz-pd__summary {
  flex: 1 1 auto;
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.3;
}

/* Вердикт о записи — бейдж, а не кнопка: мелкое на телефоне не кликается
   (правило 5), чек-лист проверки живёт в меню «ещё». Слова и тон приходят
   от домена (`trust.label`/`.tone`), здесь только их вид. */
/* `inline-block`, а не `inline-flex`: длинные слова вердикта («не проверяли
   ни разу») обязаны обрезаться многоточием, а у флекс-короба с анонимным
   текстом `text-overflow` не работает — надпись просто уезжала под кнопку
   «ещё». Высота держится `line-height`. */
.tvz-pd__trust {
  flex: none;
  height: 20px;
  max-width: 45%;
  padding: 0 8px;
  border-radius: 999px;
  display: inline-block;
  line-height: 20px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvz-pd__trust--ok {
  background: var(--c-okbg);
  color: var(--c-ok-d);
}

.tvz-pd__trust--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

.tvz-pd__trust--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__trust--mut {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

/* --- 2. Крупные действия связи (§1 постановки) ----------------------------- */

/* «Позвонить» и «Написать» — главное, зачем человека открывают с телефона,
   поэтому они стоят В ШАПКЕ, до всякого списка. Ряд собирает people.js
   (`channelBigActions`): под запретом прямого общения его нет вовсе.
   Кнопки делят ширину поровну — колонки равной меры читаются как один
   орган управления, а не как «главная и приделанные». */
.tvz-pd__bigacts {
  display: flex;
  gap: 8px;
  padding: 0 12px 10px;
}

/* Вид кнопки — дизайн-системный (`tvz-btn--primary`/`--soft`/`--ghost`),
   своя здесь только геометрия пальца: 48px и радиус 13 (токены ветки). */
.tvz-pd__bigact {
  flex: 1;
  min-width: 0;
  height: 48px;
  padding: 0 10px;
  border-radius: 13px;
  font-size: 14px;
  font-weight: 600;
  gap: 7px;
  text-decoration: none;
  justify-content: center;
}

/* «Позвонить» шире соседей: один акцент на экран (правило 6) — с телефона
   человека открывают ради звонка, и главное действие видно мерой, а не
   только цветом. */
.tvz-pd__bigact--call {
  flex: 1.35;
}

/* Канала нет — кнопка на месте, но не работает и говорит почему (в `title`):
   пропавшая кнопка читается как «звонить можно, просто не отсюда». */
.tvz-pd__bigact--off {
  color: var(--c-tx-4);
  border-style: dashed;
  cursor: not-allowed;
}

/* --- 3. Лента разделов ------------------------------------------------------ */

/* Запрет прямого общения читается ПЕРВЫМ и вместе с маршрутом: в карточку
   человека приходят из выдачи, минуя клиента (S-1a-1). */
.tvz-pd__banner {
  padding: 10px 12px 0;
}

/* Строка «подпись — значение»: подпись фиксированной мерой слева, значение
   занимает остальное. Высота — под палец (44), а не под текст. */
.tvz-pd__row {
  min-height: 44px;
  padding: 7px 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__row:first-child {
  border-top: none;
}

.tvz-pd__row-k {
  flex: none;
  width: 92px;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-pd__row-v {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  color: var(--c-tx);
  overflow-wrap: anywhere;
}

.tvz-pd__row-n {
  font-size: 11px;
  color: var(--c-tx-4);
}

/* Блок канала (`channelBlock`, people.js) занимает строку целиком: на телефоне
   значение — рабочая ссылка, и попадать по ней надо пальцем, а не курсором. */
.tvz-pd--contact .tvz-cc-ch {
  flex: 1;
  height: 36px;
  width: 100%;
}

.tvz-pd--contact .tvz-cc-ch__v {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
}

/* Пусто и подписи разделов — словами, а не прочерком (S-1a-5). */
.tvz-pd__none {
  padding: 12px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--c-tx-4);
}

.tvz-pd__note {
  padding: 10px 12px 0;
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* Подпись вне карточки — под липким заголовком раздела, а не внутри белого
   короба (счётчики сделок, итог среза ленты). */
.tvz-pd__note--free {
  padding: 8px 14px 0;
}

/* Кнопка в заголовке раздела («Роль», «Заметка») — мера чипа ленты фильтров
   (32px, токены ветки), чтобы шапка раздела не выросла в третий ряд. */
.tvz-pd__sect-act {
  flex: none;
  height: 32px;
  padding: 0 11px;
  border-radius: 999px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  color: var(--c-ac);
  font-size: 12.5px;
  font-weight: 600;
  gap: 5px;
}

/* Лента чипов внутри раздела (срез «Истории») — тот же узор, что у фильтров
   списка сделок, только с отступом от липкого заголовка. */
.tvz-pd--contact .tvz-pd__chips {
  padding: 8px 12px 2px;
}

/* Пилюля-пометка в карточке сделки: «главное лицо» / «участник». Не
   кликается — как и любой мелкий бейдж на телефоне (правило 5). */
.tvz-pd__flag {
  flex: none;
  height: 20px;
  padding: 0 8px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.tvz-pd__flag--info {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__flag--mut {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

/* Тон этапа — ПОЛОЖЕНИЕ сделки, а не её цвет (П-50): идёт (базовый зелёный
   `.tvz-pd__stage`), проиграна, закрыта иначе. */
.tvz-pd__stage--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__stage--mut {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

/* Роли: те же цветные разделы справочника, что за столом, только строка выше
   (палец) и кнопка снятия — настоящая кнопка, а не значок 22px. */
.tvz-pd--contact .tvz-rrow {
  min-height: 44px;
  grid-template-columns: minmax(0, 1fr) 40px;
  padding: 7px 12px;
}

.tvz-pd--contact .tvz-rrow__n {
  font-size: 13.5px;
}

.tvz-pd--contact .tvz-rrow__s {
  font-size: 11.5px;
}

.tvz-pd--contact .tvz-rrow__x {
  width: 40px;
  height: 40px;
  border-radius: 12px;
}

/* «Ещё N» — свёрнутый хвост длинного раздела. Список не обрезан молча: видно,
   сколько там осталось, и раскрывается он на месте. */
.tvz-pd__more {
  margin: 8px 12px 0;
  width: calc(100% - 24px);
  height: 44px;
  border-radius: 14px;
  border: 1px dashed var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-tx-2);
  font-size: 13px;
  font-weight: 600;
}

/* Строка ленты «История»: значок типа записи (тот же `.tvz-feed__i`, что за
   столом), заголовок, кто и когда, тело записи. */
.tvz-pd__ev {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__ev:first-child {
  border-top: none;
}

.tvz-pd__ev-b {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tvz-pd__ev-t {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-tx);
  overflow-wrap: anywhere;
}

.tvz-pd__ev-w {
  font-size: 11px;
  color: var(--c-tx-4);
}

.tvz-pd__ev-x {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--c-tx-2);
  overflow-wrap: anywhere;
}

/* ============================================================================
   «Мой день» на телефоне — третий экран мобильной ветки (П-57).

   Узоры взяты готовыми: шапка в три ряда, лента чипов, полоса приоритета,
   `.tvz-pd__card` с ярусом действий, круглая кнопка и таб-бар уже описаны
   выше и здесь НЕ переобъявляются. Своего у дня ровно три вещи, которых
   у списка сделок не было:

   1. четвёртая полоса — «Сделано сегодня»: у сделок исход не полоса, а
      хвост списка, зелёного заголовка в ветке до сих пор не существовало;
   2. пилюля СРОКА в карточке (у сделки на этом месте стоит пилюля тишины —
      другой факт и другие пороги, общего кода у них нет);
   3. ряд пометок задачи: сделка и исполнитель пилюлями 24px.
   ============================================================================ */

/* --- 1. Полоса «Сделано сегодня» -------------------------------------------- */

/* Зелёный — «в порядке/сделано», ровно то значение, которое за ним закреплено
   (правило 8). Янтарного среди заголовков нет и здесь: он занят просроченной
   задачей ВНУТРИ карточки. */
.tvz-pd__section-hd--ok {
  background: var(--c-okbg);
  border-color: var(--c-ok-bd);
  color: var(--c-ok-d);
}

.tvz-pd__section-hd--ok .tvz-pd__section-dot {
  background: var(--c-ok);
}

/* --- 2. Карточка дела ------------------------------------------------------- */

/* Дело без сделки никуда не ведёт — и не притворяется, что ведёт: тот же
   довод, что у десктопной строки дня (`.tvz-deal__open` надевается только
   там, где есть куда вести). Класс снимает у тела карточки обещание нажатия,
   геометрию оставляя общей. */
.tvz-pd__body--flat {
  cursor: default;
}

.tvz-pd__body--flat:hover {
  background: none;
}

/* Пилюля срока. Геометрия — та же 20px, что у пилюли тишины в карточке
   сделки: это одно место карточки и один размер на ветку. Своё имя, а не
   `.tvz-pd__silence`, потому что факт другой — срок задачи, а не молчание
   клиента, и пороги у них общего ничего не имеют. */
.tvz-pd__due {
  flex: none;
  height: 20px;
  padding: 0 8px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.tvz-pd__due--late {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__due--day {
  background: var(--c-chip);
  color: var(--c-mut);
}

/* «Без срока» — тише названного дня: это отсутствие ответа, а не ответ. */
.tvz-pd__due--none {
  background: var(--c-chip);
  color: var(--c-tx-4);
}

.tvz-pd__due--done {
  background: var(--c-okbg);
  color: var(--c-ok-d);
}

/* Пометки дела: чья сделка и на ком оно. Обе тише названия — один акцент на
   карточку (правило 6). */
.tvz-pd__tags {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  width: 100%;
}

.tvz-pd__tag {
  max-width: 100%;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  /* `inline-block` с `line-height`, а не флексбокс: у флекс-контейнера
     многоточие обрезки не применяется вовсе, и длинное имя сделки уезжало бы
     за край карточки без единого признака, что текст продолжается (та же
     грабля, что у пилюли роли выше, и она же названа в хендоффе). */
  display: inline-block;
  line-height: 24px;
  font-size: 12px;
  font-weight: 600;
  background: var(--c-chip);
  color: var(--c-tx-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Дело НЕ на вас — фиолетовым. Это не четвёртый цвет-сигнал: три сигнальных
   цвета говорят о состоянии дела (просело / просрочено / сделано), а здесь
   сказано, чьё оно, — факт другого рода, и красить его сигнальным цветом
   значило бы соврать о состоянии. */
.tvz-pd__tag--whose {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

/* --- 3. Ярус действий дела -------------------------------------------------- */

.tvz-pd__act--done {
  color: var(--c-ok-d);
}

.tvz-pd__act--done:hover {
  background: var(--c-okbg);
}

/* Второе нажатие той же кнопки — «Вернуть». Тише закрытия: возврат чинит
   промах, а не двигает работу. */
.tvz-pd__act--undone {
  color: var(--c-tx-4);
}

.tvz-pd__act--undone:hover {
  background: var(--c-hover);
}

/* --- 4. Выбор дня в ленте чипов --------------------------------------------- */

/* Календарь шапки открывает НЕ четвёртый ряд, а поле прямо в ленте чипов:
   рядов у шапки максимум три (правило 1), и день выбирается там же, где
   стоят остальные отборы. */
.tvz-pd__daypick {
  flex: none;
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--c-ac-bd);
  border-radius: 999px;
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-size: 13px;
  font-weight: 600;
}

/* ============================================================================
   «Ещё» на телефоне (П-59, раздел 3 хендоффа) — меню участка.

   За столом «Мой участок» — пять сегментов тулбара. На 390 точках они не
   помещаются и не нужны сразу: сюда приходят за ОДНИМ разделом. Поэтому
   меню строками, а каждая строка открывает свой раздел отдельным экраном.

   Узоры — те же, что у всей ветки: карточка 14px с тенью `--sh-pd-card`,
   касание не меньше 44px (строка здесь 56), счётчик пилюлей, кикер группы
   10.5/700 прописными. Своего цвета нет ни у одного правила: тона строк —
   те же четыре, которыми ветка говорит «просело / просрочено / это ссылка /
   тихо».

   Десктоп не задет: все правила начинаются с `.tvz-pd`, а этот корень
   ставит только мобильная раскладка.
   ============================================================================ */

.tvz-pd--desk {
  background: var(--c-bg);
}

/* Аватар шапки участка НИЧЕГО не открывает: справка, тема и выход стоят
   ниже строками группы «Прочее». Кружок с курсором-пальцем, за которым
   пусто, — обещание без исполнения, поэтому палец здесь снимается. */
.tvz-pd__avatar--flat {
  cursor: default;
}

/* Обёртка групп внутри скроллера. `flex:none` у групп обязателен: без него
   колонка сжимает карточку ниже её содержимого, а `overflow:hidden`
   (нужный ради скругления 14px) прячет остаток — и доскроллить нельзя,
   потому что переполнение до скроллера не доходит. Ловилось на проверке. */
.tvz-pd__menu-body {
  padding: 10px 12px 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tvz-pd__grp {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tvz-pd__grp-k {
  padding-left: 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-tx-4);
}

.tvz-pd__menu {
  flex: none;
  border: 1px solid var(--c-bd);
  border-radius: 14px;
  background: var(--c-surface);
  box-shadow: var(--sh-pd-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.tvz-pd__mrow {
  width: 100%;
  min-height: 56px;
  padding: 9px 12px;
  border: none;
  border-bottom: 1px solid var(--c-bd2);
  background: none;
  display: flex;
  align-items: center;
  gap: 11px;
  text-align: left;
  color: inherit;
  cursor: pointer;
}

.tvz-pd__mrow:last-child {
  border-bottom: none;
}

.tvz-pd__mrow:hover {
  background: var(--c-hover);
}

/* Выбранный вариант шторки фильтра (П-83, `filterOptionRow`): та же пилюльная
   акцентная заливка, что у активного чипа шапки (`.tvz-pd__chip.is-active`),
   не рамка — строка меню уже несёт нижнюю границу-разделитель, вторая
   акцентная линия рядом читалась бы двойным контуром. */
.tvz-pd__mrow.is-active {
  background: var(--c-ac-tint);
}

.tvz-pd__mrow.is-active .tvz-pd__mt {
  color: var(--c-ac-d);
}

.tvz-pd__mrow.is-active .tvz-pd__mch {
  color: var(--c-ac);
}

.tvz-pd__mico {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-pd__mico--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__mico--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

.tvz-pd__mico--ac {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__mico--mut {
  background: var(--c-chip);
  color: var(--c-mut);
}

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

.tvz-pd__mt {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Подпись строки — `display:block` с своей высотой строки, а не флекс:
   `text-overflow:ellipsis` на флекс-контейнере не работает вовсе, и длинная
   подпись резалась бы мид-словом (грабля хендоффа, п. 3). */
.tvz-pd__ms {
  display: block;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Счётчик — пилюля 22px, НЕ кликается (правило 5 ветки: мелкое не трогают
   пальцем). Пока числа нет, пилюли нет вовсе: пустое место у строки не
   отличить от честного нуля, а `hidden` на `inline-flex` сам по себе не
   работает — `display` перебивает атрибут. */
.tvz-pd__mn {
  flex: none;
  min-width: 22px;
  height: 22px;
  padding: 0 7px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tvz-pd__mn[hidden] {
  display: none;
}

.tvz-pd__mn--err {
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__mn--warn {
  background: var(--c-warnbg);
  color: var(--c-warn);
}

.tvz-pd__mn--ac {
  background: var(--c-ac);
  color: var(--c-on-ac);
}

.tvz-pd__mn--mut {
  background: var(--c-chip);
  color: var(--c-mut);
}

.tvz-pd__mch {
  flex: none;
  display: flex;
  color: var(--c-tx-4);
}

/* Раздел участка, открытый отдельным экраном: рама мобильная, содержимое —
   ТО ЖЕ, что за столом (плитки и строки уже переносятся сами). Своего
   отступа у списка нет — его даёт эта обёртка, а дно под таб-бар приходит
   от `.tvz-pd__list`. */
.tvz-pd__plain {
  padding: 10px 12px 0;
}

/* ============================================================================
   Карточка сделки на телефоне — третья карточка мобильной ветки (П-58).

   Своей вёрстки здесь ровно столько, сколько у сделки отличается от уже
   написанного: блок денег двумя ступенями, блок с шапкой (лента и варианты
   КП), строка варианта, низ тела с тремя действиями и шторка чата с агентом.
   Всё остальное — шапка, карточка, СТРОКА СЛЕДУЮЩЕГО ШАГА со всеми тремя
   состояниями, строка ленты, лист шторки, чипы формулировок, таб-бар — это
   узоры П-49 и П-56 выше по файлу, взятые как есть (`docs/UI-MOBILE.md` §3).

   Десктоп не задет ничем: каждое правило ниже начинается либо с
   `.tvz-pd--deal` (класс ставит только мобильная карточка), либо с имени,
   которого за столом нет вовсе. Узкое окно за столом их не видит.
   ============================================================================ */

/* Корень: та же колонка на весь экран. Объявлен явно — класс без объявления
   на экране ничего не делает и молчит об этом. */
.tvz-pd--deal {
  background: var(--c-bg);
}

/* Название сделки тише, чем название вкладки: 15.5/700 против 21/700. На 390
   точках имя сделки длиннее имени раздела в разы, и 21px обрезался бы на
   втором слове — а под ним стоит вторая строка «клиент · площадка», ради
   которой ряд и нужен. Слово владельца 05.08: название чуть меньше, акцент
   на имени клиента чуть больше — менеджер узнаёт сделку по клиенту. */
.tvz-pd--deal .tvz-pd__title {
  font-size: 15.5px;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Имя клиента в подстроке — главный опознавательный знак карточки: полный
   цвет и 13/600 против приглушённых 11.5 у площадки рядом. */
.tvz-pd--deal .tvz-pd__client-strong {
  font-size: 13px;
  font-weight: 600;
  color: var(--c-tx);
}

/* Тело — колонка карточек с одним зазором на все (правило отступов канона:
   между карточками 8px, поля 12px). Дна «под таб-бар» здесь БОЛЬШЕ НЕТ и
   быть не должно: с П-66 под скроллером стоят своими коробами панель
   главного действия и таб-бар, оба `flex: none`. Оставленные 84px дали бы
   пустую полосу высотой в полторы карточки — под панелью, которая её и
   закрывает. */
.tvz-pd--deal .tvz-pd__list {
  padding: 8px 12px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* `flex: none` здесь НЕСУЩИЙ, а не косметика (грабля, ловившаяся на проверке):
   без него колоночный скроллер сжимает карточку ниже её содержимого, а её
   собственный `overflow: hidden` — нужный ради скругления 14px — прячет
   остаток. Переполнение до скроллера не доходит вовсе, и доскроллить нельзя.
   Внешние поля берёт на себя тело, поэтому свой `margin` карточка теряет. */
.tvz-pd--deal .tvz-pd__card {
  flex: none;
  margin: 0;
}

/* Просроченный следующий шаг: янтарная рамка у всей карточки. Заливку даёт
   сама строка (`.tvz-pd__task--late`), рамке нужен свой, более тихий тон того
   же семейства — он и назван токеном `--c-warn-bd`. */
.tvz-pd__card--late {
  border-color: var(--c-warn-bd);
}

/* Строка следующего шага стоит в карточке ОДНА — верхняя граница, которой она
   отделялась от тела в списке, здесь отделяла бы её от пустоты. */
.tvz-pd--deal .tvz-pd__card > .tvz-pd__task {
  border-top: none;
}

/* --- Факты шапки: этап, тишина, «N КП в расчёте» (П-66, B5; правка П-84) ---
   Были пилюлями 32px с заливкой — и читались как КНОПКИ: по ним жали, и не
   происходило ничего. Пилюля в этом продукте уже значит «нажми» (чипы
   фильтров, чипы формулировок), и третьего смысла у неё быть не может.

   Стало: точка-индикатор с этапом, дальше через тонкие разделители тишина и
   счёт КП, всё 12px без фона; цвет несёт сигнал (правило 8), а не
   приглашение. **Одно намеренное исключение (П-84): этап — единственный
   факт, который снова нажимается** — открывает шторку смены этапа
   (`.tvz-pd__fact--tap` ниже, хвостовой шеврон отличает его на глаз).
   Тишина и счёт КП по-прежнему просто читаются. */
.tvz-pd__facts {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 12px 9px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tvz-pd__facts::-webkit-scrollbar {
  display: none;
}

.tvz-pd__fact {
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}

.tvz-pd__fact-dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--c-mut);
}

.tvz-pd__fact-dot--ok {
  background: var(--c-ok);
}

.tvz-pd__fact-dot--warn {
  background: var(--c-warn);
}

.tvz-pd__fact-dot--err {
  background: var(--c-err);
}

.tvz-pd__fact-t {
  font-size: 12px;
  color: var(--c-mut);
  white-space: nowrap;
}

.tvz-pd__fact-t--ok {
  font-weight: 600;
  color: var(--c-ok-d);
}

.tvz-pd__fact-t--warn {
  font-weight: 600;
  color: var(--c-warn);
}

.tvz-pd__fact-t--err {
  font-weight: 600;
  color: var(--c-err);
}

/* Волосяной разделитель. Ставится ПЕРЕД фактом, а не после, — иначе ряд
   заканчивается висящей палочкой на пустом месте. */
.tvz-pd__factsep {
  flex: none;
  width: 1px;
  height: 11px;
  background: var(--c-line-strong);
}

/* Факт-кнопка (П-84) — единственный нажимаемый факт в ряду (этап). Сбрасывает
   базовые стили `<button>`, чтобы остаться на вид фактом, а не пилюлей:
   тот же шрифт и та же геометрия, что у span-фактов рядом, — жест «это тоже
   можно нажать» несёт только хвостовой шеврон. */
.tvz-pd__fact--tap {
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
}

.tvz-pd__fact-chev {
  display: flex;
  color: var(--c-tx-4);
}

.tvz-pd__fact-chev svg {
  width: 9px;
  height: 9px;
}

/* --- Блок денег: две ступени ----------------------------------------------- */

/* Отступы сжаты (П-66, B4): блок стоит первым, и каждая лишняя точка его
   высоты — это строка ленты, которую не видно без прокрутки. */
.tvz-pd__mbox {
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.tvz-pd__mtop {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 16px;
}

/* Кикер и число — В СТРОКУ, а не двумя ступенями (П-66, B4): два столбца
   держали высоту блока за два ряда ради двух чисел. По базовой линии, чтобы
   9.5px кикер не «висел» относительно 16px суммы. */
.tvz-pd__mtotal {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.tvz-pd__mtotal-k {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tvz-pd__mtotal-k--once {
  color: var(--c-ac);
}

.tvz-pd__mtotal-k--year {
  color: var(--c-ok-d);
}

.tvz-pd__mtotal-v {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tvz-pd__mtotal-v--once {
  color: var(--c-ac);
}

.tvz-pd__mtotal-v--year {
  color: var(--c-ok-d);
}

/* Знак рубля один на весь блок — тихой подписью справа. Повторять его в
   каждой статье владелец запретил прямо (П-40, правило 4). */
.tvz-pd__mnote {
  margin-left: auto;
  align-self: flex-end;
  font-size: 9.5px;
  font-weight: 600;
  color: var(--c-tx-4);
  white-space: nowrap;
}

/* Составляющие — СЕТКА 2×2 (П-66, B4). В потоке числа «плавали»: каждое
   вставало на своё место, и сравнить их глазом было нельзя — хотя ровно за
   этим на них и смотрят. В сетке подпись слева, число прижато вправо, и с
   `tabular-nums` цифры выстраиваются в столбик. */
.tvz-pd__mparts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 16px;
  padding-top: 5px;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__mpart {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

/* Подпись жмётся и обрезается, число — нет: «аренда» важно прочитать до
   первых букв, а сумму — целиком. */
.tvz-pd__mpart-k {
  flex: 1;
  min-width: 0;
  font-size: 11px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__mpart-v {
  flex: none;
  text-align: right;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--c-tx);
}

.tvz-pd__mnone {
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* П-61. Пара «подпись — значение» на ленте «О клиенте». Своя, а не
   `tvz-pd__mpart`: там значение денежное и потому `nowrap`, а адрес
   с индексом и корпусом обязан переноситься, иначе он уедет за экран
   и человек прочитает половину. Подпись стоит НАД значением, а не слева:
   на 390 px «юридический адрес» и сам адрес в один ряд не встают. */
.tvz-pd__kv {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 0;
  border-bottom: 1px solid var(--c-bd2);
  min-width: 0;
}

.tvz-pd__kv:last-child {
  border-bottom: 0;
}

.tvz-pd__kv-l {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
}

.tvz-pd__kv-v {
  font-size: var(--fz-sm);
  color: var(--c-tx);
  overflow-wrap: anywhere;
}

/* --- Блок с шапкой: лента сделки и варианты предложения --------------------
   Два блока одного вида на одном экране обязаны выглядеть одинаково — иначе
   разница читается как смысл. */
.tvz-pd__blk {
  display: flex;
  flex-direction: column;
}

.tvz-pd__blk-hd {
  flex: none;
  padding: 9px 12px;
  background: var(--c-hover);
  border-bottom: 1px solid var(--c-bd);
  display: flex;
  align-items: center;
  gap: 8px;
}

.tvz-pd__blk-t {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--c-tx);
}

.tvz-pd__blk-n {
  flex: none;
  font-size: 11px;
  color: var(--c-tx-4);
}

/* «Ещё N записей» — касание 44px (правило 5): список не обрезан молча, он
   свёрнут, и видно, на сколько. */
.tvz-pd__blk-more {
  height: 44px;
  border: none;
  background: none;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-ac);
  cursor: pointer;
}

.tvz-pd__blk-more:hover {
  background: var(--c-ac-tint);
}

/* --- Строка ленты: круглый значок канала ----------------------------------- */

.tvz-pd__ev-i {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--c-chip);
  color: var(--c-mut);
}

.tvz-pd__ev-i--ac {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__ev-i--ok {
  background: var(--c-okbg);
  color: var(--c-ok-d);
}

.tvz-pd__ev-i--mut {
  background: var(--c-chip);
  color: var(--c-mut);
}

/* Текст записи в ленте сделки тише, чем в истории контакта: там строка —
   заголовок события с телом под ним, здесь — одна готовая фраза сервера. */
.tvz-pd--deal .tvz-pd__ev {
  padding: 9px 12px;
  align-items: center;
  border-top: none;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-pd--deal .tvz-pd__ev-t {
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.35;
}

/* --- Строка варианта КП ---------------------------------------------------- */

.tvz-pd__of {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-pd__of:last-child {
  border-bottom: none;
}

/* Чекбокс «входит в расчёт сделки». Не радио: сделка собирается из нескольких
   КП по площадкам, и отмеченных сколько угодно (П-40, §3). */
.tvz-pd__of-box {
  flex: none;
  width: 20px;
  height: 20px;
  border: 1.5px solid var(--c-line-strong);
  background: var(--c-surface);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-on-ac);
  cursor: pointer;
  padding: 0;
}

.tvz-pd__of-box.is-on {
  border-color: var(--c-ac);
  background: var(--c-ac);
}

.tvz-pd__of-box:disabled {
  cursor: default;
}

.tvz-pd__of-b {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tvz-pd__of-t {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__of-s {
  font-size: 11px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Счётчик непрочитанного от агента. Не кликается (правило 5): нажимают
   кнопку чата рядом, а не цифру. */
.tvz-pd__of-n {
  flex: none;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--c-ac);
  color: var(--c-on-ac);
  font-size: 10.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tvz-pd__of-chat {
  flex: none;
  width: 34px;
  height: 34px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ac);
  cursor: pointer;
}

.tvz-pd__of-chat:hover {
  background: var(--c-ac-tint);
}

/* --- Блок «Кто в сделке» (П-66, B1) ----------------------------------------
   Кикер подгруппы: не подпись, а ГРАНИЦА между сторонами. Тон здесь несёт
   смысл «чей человек» — тот же приём, что у групп ролей в карточке клиента:
   акцент у клиента, фиолетовый у нас. Полоса во всю ширину карточки, потому
   что она делит список, а не украшает первую строку. */
.tvz-pd__peer-hd {
  display: block;
  padding: 6px 12px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tvz-pd__peer-hd--client {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__peer-hd--we {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

/* «+ Участник» в шапке блока: 26px и НЕ касание-действие в списке, а вход в
   объяснение. Меньше 44px намеренно — правило 5 канона про 44px стоит на
   действиях строки, а эта кнопка живёт в шапке рядом с заголовком, где
   промах уводит в тот же безобидный тост. */
.tvz-pd__peer-add {
  flex: none;
  height: 26px;
  padding: 0 9px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-ac);
  cursor: pointer;
}

.tvz-pd__peer-add:hover {
  background: var(--c-ac-tint);
}

.tvz-pd__peer {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--c-bd2);
}

.tvz-pd__peer:last-child {
  border-bottom: none;
}

.tvz-pd__peer-ava {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
}

.tvz-pd__peer-ava--client {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__peer-ava--we {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

.tvz-pd__peer-b {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tvz-pd__peer-l {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

.tvz-pd__peer-n {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Должность · зона ответственности. Обрезается многоточием: на 390 точках
   «Начальник склада · заявки на установку» не помещается, а первые слова
   отвечают на вопрос, ради которого строку читают. */
.tvz-pd__peer-s {
  font-size: 11px;
  color: var(--c-tx-4);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Метка роли В СДЕЛКЕ: «решает» / «ведёт». Не кликается (правило 5) — это
   факт, а не переключатель, и роль меняют за столом. */
.tvz-pd__peer-tag {
  flex: none;
  height: 18px;
  padding: 0 7px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  font-size: 10px;
  font-weight: 600;
  white-space: nowrap;
}

.tvz-pd__peer-tag--client {
  background: var(--c-ac-tint);
  color: var(--c-ac);
}

.tvz-pd__peer-tag--we {
  background: var(--c-purplebg);
  color: var(--c-purple);
}

.tvz-pd__peer-call {
  flex: none;
  position: relative;
  width: 38px;
  height: 38px;
  border: 1px solid var(--c-bd);
  background: var(--c-surface);
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ac);
  cursor: pointer;
  text-decoration: none;
}

/* Подпись кнопки остаётся В РАЗМЕТКЕ и прячется только с глаз: `display: none`
   унёс бы её и из дерева доступности, а безымянная кнопка не называет себя
   нигде. В строке человека на слово рядом со значком места нет. */
.tvz-pd__peer-call > span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.tvz-pd__peer-call:hover {
  background: var(--c-ac-tint);
}

/* Звонить некуда — кнопка гаснет и НЕ исчезает: пропавшее действие на узкой
   карточке читается как «здесь его и не бывает». Причина стоит в подсказке,
   а нажать нечего. */
.tvz-pd__peer-call.is-disabled,
.tvz-pd__peer-call:disabled {
  background: var(--c-hover);
  color: var(--c-tx-4);
  cursor: not-allowed;
}

/* --- Главное действие: панель НАД таб-баром (П-66, B2) ----------------------
   Стоит вне скроллера и потому не уезжает: «Записать касание» жили в потоке
   тела, и до кнопки приходилось доскроллить ленту — на экране, куда заходят
   именно затем, чтобы записать. Правило канона: главное действие экрана
   закрепляется панелью над таб-баром. */
.tvz-pd__pin {
  flex: none;
  padding: 8px 12px;
  background: var(--c-surface);
  border-top: 1px solid var(--c-bd);
}

.tvz-pd__pin-main {
  width: 100%;
  height: 48px;
  border: 1px solid var(--c-ac);
  background: var(--c-ac);
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 600;
  color: var(--c-on-ac);
  cursor: pointer;
}

.tvz-pd__pin-main:disabled {
  border-color: var(--c-bd);
  background: var(--c-chip);
  color: var(--c-tx-4);
  cursor: not-allowed;
}

/* --- Шторка «Чат с агентом по КП» (§4 хендоффа) ---------------------------- */

/* Круг с агентом в шапке листа: у переписки должно быть лицо, иначе шторка не
   отличается от формы записи, которая приезжает оттуда же. */
.tvz-pd__agent {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--c-ac-tint);
  color: var(--c-ac);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-pd__sheet--chat {
  max-height: 88%;
}

/* Тело листа здесь — сама переписка: колонка пузырей, прижатых к своим краям.
   Зазор 8px против 10px у форм: у пузырей есть своя подпись времени, и
   больший зазор рвал бы её от пузыря, к которому она относится. */
.tvz-pd__sheet--chat .tvz-pd__sheet-body {
  gap: 8px;
  padding: 10px 14px;
}

.tvz-pd__sheet--chat .tvz-pd__sheet-title {
  font-size: 15px;
}

.tvz-pd__sheet--chat .tvz-pd__sheet-sub {
  font-size: 11.5px;
}

.tvz-pd__sheet--chat .tvz-pd__sheet-close {
  border-radius: 999px;
}

.tvz-pd__sheet--chat .tvz-pd__sheet-foot {
  padding: 0;
  gap: 0;
}

.tvz-pd__sheet--chat .tvz-pd__presets {
  margin: 0;
  padding: 8px 14px;
}

/* Шторка этапа (П-84) — список занимает лист без своего второго отступа:
   `.tvz-pd__sheet-body` уже даёт 12/14px рамку, а меню (`.tvz-menu`) внутри
   растягивается на всю ширину сама, потому что она block-элемент. */
.tvz-pd__sheet--stage .tvz-pd__sheet-body {
  padding-top: 8px;
}

/* Пункты списка этапов — под палец, а не под курсор: базовые 8px/10px
   `.tvz-menu__it` (design.css) читаются на попапе стола, но на телефоне дают
   строку ниже 44px. Специфичность через предка-обёртку, не правка общего
   класса — десктопные поповеры (П-72) её не наследуют. */
.tvz-pd__stagelist.tvz-menu {
  width: 100%;
  padding: 2px 0;
  gap: 2px;
}

.tvz-pd__stagelist .tvz-menu__it {
  min-height: 44px;
  padding: 11px 12px;
  font-size: 14px;
}

.tvz-pd__stagelist .tvz-menu__lbl {
  padding: 10px 12px 4px;
}

.tvz-pd__bub {
  flex: none;
  max-width: 86%;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tvz-pd__bub--me {
  align-self: flex-end;
  align-items: flex-end;
}

.tvz-pd__bub--them {
  align-self: flex-start;
  align-items: flex-start;
}

.tvz-pd__bub-t {
  padding: 9px 11px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

/* Срезанный угол смотрит на своего автора: у нашего пузыря — правый нижний,
   у агента — левый. Это единственное, чем стороны различаются кроме цвета, и
   на нём держится чтение переписки боковым зрением. */
.tvz-pd__bub--me .tvz-pd__bub-t {
  background: var(--c-ac);
  color: var(--c-on-ac);
  border-bottom-right-radius: 6px;
}

.tvz-pd__bub--them .tvz-pd__bub-t {
  background: var(--c-chip);
  color: var(--c-tx);
  border-bottom-left-radius: 6px;
}

.tvz-pd__bub-at {
  font-size: 10.5px;
  color: var(--c-tx-4);
}

.tvz-pd__bub-f {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-surface);
  font-size: 11.5px;
  color: var(--c-tx-2);
}

/* --- Поле ввода шторки ----------------------------------------------------- */

.tvz-pd__say {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--c-bd2);
}

.tvz-pd__say-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 8px 14px 16px;
}

.tvz-pd__say-attach,
.tvz-pd__say-send {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.tvz-pd__say-attach {
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  color: var(--c-tx-2);
}

.tvz-pd__say-send {
  border: none;
  background: var(--c-chip);
  color: var(--c-tx-4);
  cursor: not-allowed;
}

.tvz-pd__say-send.is-ready {
  background: var(--c-ac);
  color: var(--c-on-ac);
  cursor: pointer;
}

.tvz-pd__say-field {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  background: var(--c-hover);
  border-radius: 13px;
}

.tvz-pd__say-input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  font-family: inherit;
  font-size: 14px;
  color: var(--c-tx);
}

/* Микрофон ВНУТРИ поля: голос — первоклассный способ ввода (правило 10), а не
   запасной, и рука ищет его там же, где текст. */
.tvz-pd__say-mic {
  flex: none;
  min-width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: none;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-mut);
  cursor: pointer;
}

.tvz-pd__say-mic.is-recording {
  padding: 0 8px;
  background: var(--c-errbg);
  color: var(--c-err);
}

.tvz-pd__say-time {
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --- Приложенный файл над полем -------------------------------------------- */

.tvz-pd__file {
  display: flex;
  flex-direction: column;
}

.tvz-pd__file-c {
  margin: 8px 14px 0;
  padding: 8px 10px;
  border: 1px solid var(--c-ac-bd);
  background: var(--c-ac-tint);
  border-radius: 12px;
  display: flex;
  align-items: center;
  gap: 9px;
}

.tvz-pd__file-i {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-ac);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tvz-pd__file-b {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.tvz-pd__file-t {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tvz-pd__file-s {
  font-size: 11px;
  color: var(--c-ac);
}

.tvz-pd__file-x {
  flex: none;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ac);
  cursor: pointer;
}

/* ============================================================================
   Модалок по центру на телефоне нет — они встают шторкой снизу.

   Правило 3 мобильной ветки (`docs/UI-MOBILE.md`): «всё, что требует ввода, —
   шторка снизу с ручкой; модалок по центру на телефоне нет: они
   перекрываются клавиатурой». П-49 выполнила его для своих двух форм СВОЕЙ
   вёрсткой (`.tvz-pd__sheet`), но формы карточки контакта — проверка записи,
   заметка, роли, «здесь больше не работает» — это уже написанные и обкатанные
   диалоги, и второй их экземпляр для телефона был бы ровно той бедой, ради
   которой заведены B-80 и общий `roleChooser`.

   Поэтому правило живёт ЗДЕСЬ, на уровне дизайн-системы, а не в коде экрана:
   форма остаётся одна, меняется контейнер. Отбор — тот же признак, что у всей
   ветки (`isPhoneView`): узкое окно И грубый указатель. За столом, в том числе
   в узком окне, модалки остаются модалками.
   ============================================================================ */

@media (max-width: 900px) and (pointer: coarse) {
  .tvz-modal-back {
    align-items: flex-end;
    padding-top: 0;
  }

  /* Полоса под «ручку» принадлежит ЛИСТУ, а не его шапке, и это несущее.

     Пока место под ручку выпрашивалось у шапки (`.tvz-modal__head` с
     `padding-top: 20px`), его отбирал любой, кто задавал шапке свою
     геометрию НИЖЕ по файлу: форм-фактор перепакованных окон
     (`.tvz-modal--pack .tvz-modal__head`, восемь боевых окон) и окно
     «Создать клиента» ставят шапке рост 60 и отбивку 0 — и серая полоска
     печаталась поверх заголовка, вплотную к слову (находка круга №4,
     08.08, кадры 36/38). Отбивка листа отобрана быть не может: своей
     геометрии `.tvz-modal` окна не задают, у них есть только ширина. */
  .tvz-modal {
    position: relative;
    width: 100%;
    max-width: 100%;
    max-height: 94%;
    border-radius: 20px 20px 0 0;
    padding-top: 14px;
  }

  /* «Ручка» шторки — та же полоска, что у листа П-49: она говорит, что лист
     тянется снизу, ещё до того, как человек его тронул. Псевдоэлементом,
     потому что разметку модалки собирает дизайн-система, а не экран. */
  .tvz-modal::before {
    content: "";
    position: absolute;
    top: 6px;
    left: calc(50% - 18px);
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: var(--c-line-strong);
  }

  /* ==========================================================================
     ОКНО РОЛЕЙ (§6 П-42) — та же шторка, с той же ручкой, но раскладка внутри
     своя (П-59, §5 хендоффа). Черновик, границы и наследование остаются
     собственными окна: второй формы здесь не заводится (то же правило, что
     у B-80 — «роль собирается в одном месте»), переписывается ТОЛЬКО то,
     как разложены уже собранные части.

     Что меняется против стола и почему:
     — поиск во всю ширину шапки, закрыть — круг 32px под палец;
     — «в границах» разворачивается в столбец: уровни лентой чипов 34px,
       список объектов отдельной строкой на всю ширину (в ряд они не влезают
       и переносились неровно);
     — группа получает ОБЩУЮ рамку на заголовок и тело (см. ниже);
     — строка роли — 44px с чекбоксом слева: заливка всей строки тоном на
       телефоне съедает читаемость названия, а отметка говорит то же самое.
     ========================================================================== */
  .tvz-rmodal__head {
    position: relative;
    padding: 20px 14px 10px;
    gap: 10px;
    flex: none;
  }

  .tvz-rmodal__head::before {
    content: "";
    position: absolute;
    top: 8px;
    left: calc(50% - 18px);
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: var(--c-line-strong);
  }

  .tvz-rmodal-back {
    align-items: flex-end;
    padding: 0;
  }

  .tvz-rmodal {
    max-width: 100%;
    max-height: 92%;
    border-radius: 20px 20px 0 0;
    overflow: hidden;
  }

  /* Грабля §«Грабли» п. 1: в колоночном скроллере растяжимая часть называет
     себя вслух — `flex:1; min-height:0`, — а всё остальное `flex:none`.
     Оговорка честности: сегодня без этих двух свойств лист тоже не ломается —
     `overflow-y:auto` сам приводит автоматический минимум к нулю, и список
     сжимается. Держим их не «на всякий случай», а потому что уберут прокрутку
     у списка (например, отдав её всему листу) — и минимум вернётся к
     содержательной высоте молча, а низ со «Сохранить» уедет под кромку. */
  .tvz-rmodal__list {
    flex: 1;
    min-height: 0;
    max-height: none;
    padding: 8px 10px 10px;
  }

  .tvz-rmodal__bounds,
  .tvz-rmodal__seatnote,
  .tvz-rmodal__targetwarn,
  .tvz-rmodal__foot {
    flex: none;
  }

  /* Полоса «в границах» — столбцом: кикер, лента уровней, список объектов.
     В ряд они не влезают на 390 точках и переносились неровно. */
  .tvz-rmodal__bounds {
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    gap: 7px;
    padding: 8px 14px;
  }

  /* Лента уровней — чипы, а не сегментированный переключатель: четыре
     слова с «вся компания» в начале за рамку 390 точек не помещаются,
     и лента уезжает вбок сама, вместо того чтобы жать буквы. */
  .tvz-rmodal__seg {
    display: flex;
    gap: 6px;
    padding: 0;
    background: none;
    border-radius: 0;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tvz-rmodal__seg::-webkit-scrollbar {
    display: none;
  }

  .tvz-rmodal__segb {
    flex: none;
    height: 34px;
    padding: 0 13px;
    border: 1px solid var(--c-bd);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-tx-2);
    font-size: 13px;
    white-space: nowrap;
  }

  .tvz-rmodal__segb.is-active {
    border-color: var(--c-ac);
    background: var(--c-ac);
    color: var(--c-on-ac);
    box-shadow: none;
  }

  .tvz-rmodal__which {
    flex: none;
    width: 100%;
    min-width: 0;
    height: 36px;
    padding: 0 10px;
    border-radius: 10px;
    font-size: 13px;
  }

  .tvz-rmodal__searchbox {
    height: 40px;
    padding: 0 12px;
    border-radius: 12px;
  }

  .tvz-rmodal__search {
    font-size: 14px;
  }

  .tvz-rmodal__x {
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: var(--c-chip);
    color: var(--c-mut);
  }

  /* ---- группа ролей: рамка ПО ВСЕЙ ГРУППЕ --------------------------------
     Заголовок и тело обведены общей рамкой одного тона — заголовок без низа,
     тело без верха. Если рамку дать одному телу (как за столом, где её нет
     вовсе), края заголовка и тела расходятся на пиксель и последняя строка
     группы читается обрезанной: это ловилось на проверке хендоффа и названо
     там граблями прямым текстом. */
  .tvz-rmodal__grouphd {
    padding: 7px 11px;
    font-size: 10.5px;
    border: 1px solid var(--tint-bd, var(--c-bd));
    border-bottom: none;
    border-radius: 12px 12px 0 0;
  }

  .tvz-rmodal__groupbd {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0;
    border: 1px solid var(--tint-bd, var(--c-bd));
    border-top: none;
    border-radius: 0 0 12px 12px;
    overflow: hidden;
  }

  /* ---- строка роли -------------------------------------------------------
     Состояние несёт чекбокс, а не заливка строки: залитая тоном строка на
     телефоне шириной во весь лист читается хуже названия, ради которого она
     и открыта. Разделитель — тот же тон рамки группы, у последней его нет. */
  .tvz-rmodal__item,
  .tvz-rmodal__item.is-on,
  .tvz-rmodal__item.is-inherited {
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 11px;
    font-size: 13.5px;
    border: none;
    border-bottom: 1px solid var(--tint-bd, var(--c-bd));
    border-radius: 0;
    background: transparent;
    opacity: 1;
  }

  .tvz-rmodal__item:last-child,
  .tvz-rmodal__item.is-on:last-child,
  .tvz-rmodal__item.is-inherited:last-child {
    border-bottom: none;
  }

  .tvz-rmodal__item.is-on {
    color: var(--c-tx);
    font-weight: 600;
  }

  .tvz-rmodal__item.is-inherited {
    color: var(--c-mut);
    font-weight: 500;
  }

  /* Подсветки под курсором на телефоне не бывает — а «залипшая» после тапа
     бывает, и тогда строка выглядит выбранной, не будучи ею. */
  .tvz-rmodal__item:hover,
  .tvz-rmodal__item.is-on:hover {
    background: transparent;
  }

  .tvz-rmodal__nm {
    flex: 1;
    min-width: 0;
    display: block;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .tvz-rmodal__box {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border: 1.5px solid var(--c-line-strong);
    border-radius: 6px;
    background: var(--c-surface);
    color: transparent;
  }

  .tvz-rmodal__item.is-on .tvz-rmodal__box {
    border-color: var(--tint-tx, var(--c-ac));
    background: var(--tint-tx, var(--c-ac));
    color: var(--c-on-ac);
  }

  /* Досталась сверху — пунктирная отметка и подпись источника: галочка стоит,
     но снять её отсюда нельзя, только там, где включили («не может быть, что
     отвечаю за всю компанию, кроме одной площадки»). Заливки у неё нет
     намеренно — залитая спорила бы с «выбрана здесь». */
  .tvz-rmodal__item.is-inherited .tvz-rmodal__box {
    border-style: dashed;
    border-color: var(--tint-tx, var(--c-mut));
    background: transparent;
    color: var(--tint-tx, var(--c-mut));
  }

  .tvz-rmodal__from {
    flex: none;
    display: block;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--c-tx-4);
    white-space: nowrap;
  }

  /* Низ: сводка черновика своей строкой, под ней «Отмена» по содержимому и
     «Сохранить» на остаток ширины — главное действие шире и правее, под
     большой палец. Черновик по разным границам копится и уезжает ОДНИМ
     сохранением: раскладка низа этого не меняет, но и не прячет сводку —
     по ней видно, сколько накопилось за все заходы. */
  .tvz-rmodal__foot {
    padding: 9px 14px calc(16px + env(safe-area-inset-bottom));
    flex-wrap: wrap;
    gap: 8px;
    border-radius: 0;
  }

  .tvz-rmodal__foot .tvz-btn {
    height: 48px;
    padding: 0 16px;
    border-radius: 13px;
    font-size: 15px;
  }

  .tvz-rmodal__foot .tvz-rmodal__cancel {
    flex: none;
  }

  .tvz-rmodal__foot .tvz-rmodal__save {
    flex: 1;
  }

  .tvz-rmodal__sum {
    flex: 1 0 100%;
  }
}

/* --- П-69: справочник адресов в правой колонке карточки клиента ---------
   Строка адреса — не «пара ключ-значение»: у неё четыре яруса (имя вида,
   само значение, пояснение «чем отличается от соседнего», кто и когда внёс)
   и ряд действий. Пара `tvz-kv` сложилась бы в две строки и потеряла бы
   пояснение — а именно оно отвечает на вопрос, из-за которого три адреса
   и путают. Цвета — только токены, как везде. */
.tvz-ccard__addrs {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.tvz-ccard__addr {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 0;
  border-bottom: 1px solid var(--c-bd2);
}
.tvz-ccard__addr:last-child {
  border-bottom: 0;
}
.tvz-ccard__addr-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.tvz-ccard__addr-t {
  font-size: var(--fz-micro);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--c-tx-2);
}
.tvz-ccard__addr-v {
  font-size: var(--fz);
  color: var(--c-tx);
  overflow-wrap: anywhere;
}
.tvz-ccard__addr-hint,
.tvz-ccard__addr-who {
  font-size: var(--fz-micro);
  color: var(--c-tx-3, var(--c-tx-2));
}
/* Последствие правки названо ДО нажатия и не тонет в сером: снятие
   почтового адреса площадки гасит готовность юрлица к договору. */
.tvz-ccard__addr-note {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fz-micro);
  color: var(--c-warn);
}
.tvz-ccard__addr-acts {
  display: flex;
  gap: var(--gap);
  padding-top: 4px;
}

/* ============================================================================
   ФОРМ-ФАКТОР ПЕРЕПАКОВАННЫХ ОКОН (П-74, хендофф 04.08 «Модалки — один
   форм-фактор»)

   Восемь боевых окон продукта — задача, сделка, обращение, контакт, КП,
   уведомления, «ещё о клиенте», круг — до этой волны жили каждое своей
   геометрией: одни 560 через параметр `width`, другие по содержимому от 440;
   шапки разной высоты, подвалы с приписками, тела с прокруткой. Человек,
   открывший два окна подряд, читал их как два разных продукта.

   Контракт один и живёт ЗДЕСЬ, а не в вызывающих файлах:

     ширина 860 · шапка 60 с чипом-иконкой 30 · тело 18/20, высота ≤520
     БЕЗ ПРОКРУТКИ · подвал 56 только с кнопками, прижатыми вправо.

   «Тело ≤520 без прокрутки» — не пожелание, а проверяемое условие
   (tests/ui/test_screen_modal_pack.py): не влезло — делится на две колонки
   (`.tvz-modal__cols`), а не растёт вниз. `max-height` при этом стоит
   вместе с `overflow:auto`, а не с `hidden`: плашка отказа (`fieldRefusal`)
   и вопрос «набранное пропадёт» дописываются в тело ПОСЛЕ отрисовки, и
   спрятать их обрезкой значило бы вернуть молчаливый отказ (П-20).

   Признак — класс от фабрики (`modal(..., { formFactor: true })`), а не
   всем модалкам разом: окна вне волны не перепаковывались, и растянуть их
   до 860 без единого взгляда на экран было бы той же слепой правкой.

   Цветов здесь нет ни одного своего — только токены, как во всём файле.
   ============================================================================ */

.tvz-modal--pack {
  width: 860px;
  min-width: 0;
  max-width: calc(100vw - 32px);
  border: 1px solid var(--c-bd);
  border-radius: 14px;
  box-shadow: var(--shadow-e3);
}

/* Шапка: чип-иконка → заголовок с подзаголовком → «×». Высота фиксирована,
   поэтому подзаголовок обязан быть ОДНОЙ строкой с многоточием: контекст
   («Комбинат «Каскад» · Учёт техники на трёх складах») бывает длиннее окна,
   и второй строкой он ломал бы 60px. */
.tvz-modal--pack .tvz-modal__head {
  height: 60px;
  min-height: 60px;
  padding: 0 20px;
  gap: 12px;
  border-bottom: 1px solid var(--c-bd);
}
.tvz-modal--pack .tvz-modal__ico {
  width: 30px;
  height: 30px;
  border-radius: var(--rad);
}
.tvz-modal--pack .tvz-modal__titles {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.tvz-modal--pack .tvz-modal__ttl {
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
}
.tvz-modal--pack .tvz-modal__sub {
  font-size: var(--fz-sm);
  color: var(--c-tx-4);
  font-weight: 400;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tvz-modal--pack .tvz-modal__x {
  font-size: 17px;
  color: var(--c-tx-4);
}

.tvz-modal--pack .tvz-modal__body {
  padding: 18px 20px;
  max-height: 520px;
  overflow: auto;
}

/* Подвал несёт ТОЛЬКО кнопки: «Отмена» призраком и действие глаголом,
   справа. Приписка о последствии (`footerInfo`) в этих окнах не живёт —
   последствие человек видит там, куда действие привело. */
.tvz-modal--pack .tvz-modal__foot {
  height: 56px;
  min-height: 56px;
  padding: 0 20px;
  gap: 12px;
  justify-content: flex-end;
  background: var(--c-bg);
  border-top: 1px solid var(--c-bd);
}
.tvz-modal--pack .tvz-modal__foot .tvz-btn {
  height: 36px;
  border-radius: var(--rad);
}
/* Одна кнопка в подвале — не призрак: без соседа-действия «Закрыть» без
   рамки читалось как подпись, а не как то, что нажимают. */
.tvz-modal--pack .tvz-modal__foot .tvz-btn--ghost:only-child {
  border-color: var(--c-line-strong);
}

/* Две колонки — ответ на «не влезло», а не украшение: тело, которому мало
   520 в один столбец, делится пополам. Колонка — столбик полей с шагом 14. */
.tvz-modal--pack .tvz-modal__cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 20px;
  align-items: start;
}
.tvz-modal--pack .tvz-modal__col {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

/* Секция внутри тела: заголовок-рубрика с линией под ним. */
.tvz-modal--pack .tvz-modal__sect {
  display: block;
  font-size: var(--fz-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--c-bd);
}

/* Метка со ВТОРЫМ СЛОВОМ (`fieldLabel`) — узор системы, а не свойство
   окон-форм-факторов. До П-102 он был объявлен только внутри `.tvz-entry`
   и `.tvz-modal--pack`, и первое же обычное окно, взявшее готовый сборщик,
   получило метку без просвета: «Разбирать звонки начиная с01.08.26».
   Базовое объявление стоит здесь; оба контекста ниже добавляют к нему
   своё (кегли, запрет переноса), а не повторяют его целиком. */
.tvz-field__lbl {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.tvz-field__opt {
  font-size: var(--fz-micro);
  font-weight: 400;
  color: var(--c-tx-4);
}

/* Поля. Метка 12/600; необязательность — вторым словом 11px у самой метки
   (правило текста №4: «можно пусто» пишется у метки, а не абзацем под
   полем). Строка метки не переносится: при 104px колонки «Время» перенос
   ронял выравнивание ряда на 15px — оттуда же и 126px в разметке окна. */
.tvz-modal--pack .tvz-field {
  gap: 5px;
  min-width: 0;
}
.tvz-modal--pack .tvz-field > span {
  font-size: var(--fz-sm);
  font-weight: 600;
  color: var(--c-tx-2);
}
.tvz-modal--pack .tvz-field__lbl {
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}
.tvz-modal--pack .tvz-field__name {
  font-weight: 600;
  color: var(--c-tx-2);
}
.tvz-modal--pack .tvz-field__opt {
  font-size: var(--fz-micro);
  font-weight: 400;
  color: var(--c-tx-4);
}
/* Ход в строке метки (напр. «+ Новый клиент») — справа, ссылкой, а не
   отдельной кнопкой над полем: кнопка над комбо накрывалась его же
   выпадающим списком (класс B-96). */
.tvz-modal--pack .tvz-field__lbl .tvz-btn--link {
  margin-left: auto;
  height: auto;
  padding: 0;
  border: none;
  background: none;
  color: var(--c-ac);
  font-size: var(--fz-sm);
  font-weight: 600;
}
.tvz-modal--pack .tvz-field__lbl .tvz-btn--link:hover {
  background: none;
  color: var(--c-ac-d);
}

.tvz-modal--pack .tvz-field input,
.tvz-modal--pack .tvz-field select,
.tvz-modal--pack .tvz-combo__in,
.tvz-modal--pack .tvz-search {
  height: 36px;
  padding: 0 11px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  font-size: var(--fz);
}
/* Поиску левое поле не отнимаем: значок лупы дизайн-система рисует фоном
   (`.tvz-search`, тот же контур, что `icon('search')`), и текст, набранный
   от 11px, лёг бы поверх него. */
.tvz-modal--pack .tvz-search {
  min-width: 0;
  padding-left: 34px;
  background-position: left 11px center;
}
.tvz-modal--pack .tvz-field textarea {
  height: auto;
  padding: 9px 11px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  font-size: var(--fz);
}
.tvz-modal--pack .tvz-field select {
  padding-right: 30px;
}
.tvz-modal--pack .tvz-field input:focus,
.tvz-modal--pack .tvz-field select:focus,
.tvz-modal--pack .tvz-field textarea:focus,
.tvz-modal--pack .tvz-combo__in:focus,
.tvz-modal--pack .tvz-search:focus {
  border: 1.5px solid var(--c-ac);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}
/* Поле с иконкой слева (поиск ролей, поиск по кругу, канал связи): иконка
   стоит В поле, а не рядом, — иначе она съедает ширину у самого поля. */
.tvz-modal--pack .tvz-field__ico {
  position: relative;
  display: block;
}
.tvz-modal--pack .tvz-field__ico > .tvz-icon {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--c-tx-4);
  pointer-events: none;
}
.tvz-modal--pack .tvz-field__ico > input {
  padding-left: 34px;
}

/* Пунктирная строка-ход: «+ Зацепки», «Выбрать файл», «+ Ещё канал».
   Одна строка 36px вместо развёрнутой простыни полей. */
.tvz-modal--pack .tvz-modal__more {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  height: 36px;
  padding: 0 12px;
  border: 1px dashed var(--c-line-strong);
  border-radius: var(--rad);
  background: none;
  font-size: 12.5px;
  color: var(--c-tx-4);
  text-align: left;
  cursor: pointer;
}
.tvz-modal--pack .tvz-modal__more:hover {
  background: var(--c-hover);
}
.tvz-modal--pack .tvz-modal__more b {
  font-weight: 600;
  color: var(--c-ac);
}

/* Плитка справки в теле (напр. «Уже есть по сделке» у КП): не абзац-пояснение,
   а данные, которые отвечают на вопрос вместо него. */
.tvz-modal--pack .tvz-modal__tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 11px 13px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-bg);
}
.tvz-modal--pack .tvz-modal__tile-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
}
.tvz-modal--pack .tvz-modal__tile-at {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--c-tx-4);
}

.tvz-modal--pack .tvz-modal__more .tvz-icon {
  width: 15px;
  height: 15px;
  color: var(--c-ac);
  flex: none;
}

/* Ряд «Когда · Время»: две даты в столбик читались как два разных срока.
   Колонка часа 126px, а не 104 — при 104 строка метки «Время · пусто»
   переносилась и роняла выравнивание ряда на 15px (замер хендоффа). */
.tvz-modal--pack .tvz-modal__when {
  display: grid;
  grid-template-columns: 1fr 126px;
  gap: 10px;
}

/* «Мелочи Маргариты №2» (06.08): подпись словами продукта у `<input
   type="date">` (П-87) переехала В МЕТКУ поля («Когда», вторым словом,
   через `fieldLabel`) — раньше своя строка под полем читалась как ВТОРАЯ
   дата рядом с первой, а не перевод одной. `.tvz-field__ru-date` больше
   нигде не используется, правило снято вместе с разметкой. */

/* Список-добор в три колонки (окно круга): строка не рвётся между колонками,
   а заголовок секции стоит над всеми тремя. */
.tvz-modal--pack .tvz-modal__cols3 {
  column-count: 3;
  column-gap: 22px;
}
.tvz-modal--pack .tvz-modal__cols3 .tvz-modal__sect {
  column-span: all;
  margin-bottom: 6px;
}
.tvz-modal--pack .tvz-modal__pick {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 5px 0;
  border: none;
  border-bottom: 1px solid var(--c-bd2);
  border-radius: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  break-inside: avoid;
}
.tvz-modal--pack .tvz-modal__pick:hover {
  background: var(--c-hover);
}
.tvz-modal--pack .tvz-modal__pick-plus {
  flex: none;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--rad-sm);
  background: var(--c-ac-tint);
  color: var(--c-ac);
  font-size: var(--fz);
  font-weight: 600;
  line-height: 1;
}
.tvz-modal--pack .tvz-modal__pick-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.tvz-modal--pack .tvz-modal__pick-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-modal--pack .tvz-modal__pick-sub {
  font-size: var(--fz-micro);
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Ряд поиска над списком: поле во всю ширину, счётчик показанного справа. */
.tvz-modal--pack .tvz-modal__seek {
  display: flex;
  align-items: center;
  gap: 10px;
}
.tvz-modal--pack .tvz-modal__seek .tvz-search {
  flex: 1 1 auto;
}
.tvz-modal--pack .tvz-modal__shown {
  flex: none;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* Поле имени в модалке внесения — ровно 36, как все поля форм-фактора.
   `.tvz-entry__name` переиспользован из шапки карточки контакта, где имя
   РЕДАКТИРУЕМО и может занять две строки, — оттуда безусловный
   `min-height: 40px`, который бил `height: 36px` при любом порядке правил.
   Кроем только в packed-контексте: сам класс трогать нельзя, им живут экран
   `/entry` и телефонная шторка. */
.tvz-modal--pack .tvz-entry__name {
  min-height: 36px;
  height: 36px;
  padding: 0 11px;
}

/* Памятка и отметка проверки в модалке внесения (6d): два поля модели,
   которые первая редакция форм-фактора теряла молча. Памятка низкая и не
   тянется — растянутая, она съедала бы запас левой колонки, а тело окна
   держит правая (доска ролей). */
.tvz-modal--pack .tvz-entry__memo {
  height: 58px;
  min-height: 58px;
  resize: none;
  font-family: var(--font-ui);
}
.tvz-modal--pack .tvz-entry__check {
  align-items: flex-start;
  gap: 8px;
  font-size: var(--fz-sm);
  color: var(--c-tx-2);
  line-height: 1.35;
}

/* Пустая коробка отказа не ест шаг колонки: до первого отказа её на экране
   нет вовсе, а место она занимала наравне с полем. */
.tvz-modal--pack .tvz-entry__dup:empty {
  display: none;
}

/* Разделителей у окна нет: линия «граница обязательного и остального» —
   мера ЭКРАНА, где колонка длинная (хендофф 8a). В окне тело держит потолок
   520, и две линии со своими шагами колонки стоили ему 38px из 528 —
   ровно то, ради чего у форм-фактора вообще есть потолок (замер П-95).
   Разметка при этом одна: линия в ней есть всегда, просто окну она
   не показывается. */
.tvz-modal--pack .tvz-entry__sep {
  display: none;
}

/* Сегментированный ряд («Что это», «Что продаём») — та же высота 36, что
   у полей рядом: 40 разрывало ряд и делало выбор тяжелее самого поля. */
.tvz-modal--pack .tvz-seg {
  height: 36px;
}

/* Выпадающий выбор («Кто ведёт», «Где идёт сделка») в форм-факторе выглядит
   ПОЛЕМ, а не фильтр-пилюлей: рядом с полями пилюля читалась как ярлык, по
   которому нечего нажимать. Поведение прежнее — тот же поповер со списком. */
.tvz-modal--pack .tvz-field .tvz-fpill {
  width: 100%;
  height: 36px;
  padding: 0 11px;
  justify-content: space-between;
  border-color: var(--c-line-strong);
}

/* «Кому»: выбранные — пилюли акцентного тона, добор — пунктирная пилюля.
   Ряд не прокручивается вбок и не режется по 320px: в колонке 410 он
   переносится, а прокрутка внутри окна прятала выбранных людей. */
.tvz-modal--pack .tvz-tagfilter {
  max-width: none;
  height: auto;
  min-height: 30px;
  flex-wrap: wrap;
  gap: 8px;
  overflow: visible;
  padding: 0;
}
.tvz-modal--pack .tvz-tagfilter .tvz-tag {
  height: 30px;
  padding: 0 10px;
  font-size: 12.5px;
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
}
.tvz-modal--pack .tvz-tagfilter .tvz-pill {
  height: 30px;
  padding: 0 12px;
  border: 1px dashed var(--c-line-strong);
  background: none;
  font-size: 12.5px;
}

/* Узкое окно и телефон: 860 туда не влезает, и делить тело на две колонки
   там нечем. Окно отдаёт ширину экрану, колонки схлопываются в одну, потолок
   тела снимается — на телефоне прокрутка листа законна (это уже шторка). */
@media (max-width: 900px) {
  .tvz-modal--pack .tvz-modal__cols {
    grid-template-columns: 1fr;
  }
  .tvz-modal--pack .tvz-modal__cols3 {
    column-count: 1;
  }
}
@media (max-width: 560px) {
  .tvz-modal--pack {
    width: calc(100vw - 20px);
    max-width: calc(100vw - 20px);
  }
  .tvz-modal--pack .tvz-modal__body {
    padding-inline: 14px;
    max-height: none;
  }
}
@media (max-width: 900px) and (pointer: coarse) {
  .tvz-modal--pack {
    width: 100%;
    max-width: 100%;
    border-radius: 20px 20px 0 0;
  }
  .tvz-modal--pack .tvz-modal__body {
    max-height: none;
  }
}

/* ============================================================================
   6d — «Внести контакт» модалкой (README хендоффа modals-2026-08-04 §6d, П-74)

   Разметка тела — та же, что у экрана `/entry` и телефонной шторки: один
   `buildEntryCard` (entry.js), обычные `.tvz-field` фабрики коротким
   столбцом слева, роль доской групп справа. С П-95 второй разметки нет
   вовсе (флаг `packed` и карточная ветка удалены), и правила ниже —
   не «разметка окна», а НАДСТРОЙКА окна над общей: они размечены
   `.tvz-modal--pack` и действуют только внутри него.

   Роль по-прежнему собирает `roleChooser` (people.js, B-80, второго сборщика
   нет) — здесь только СВОЯ раскраска и раскрытие: класс-модификатор
   `.tvz-entry__roles--board` добавлен поверх готового узла из entry.js,
   сама сборка (поиск, фильтр, выбор) не тронута ни строкой. Доска общая
   для всех трёх контейнеров — модификатор поэтому не носит имени окна.
   ============================================================================ */

/* «+ Ещё канал» (README §6d): маленькая пунктирная пилюля-ход, а не строка
   на всю ширину (`.tvz-modal__more` — для «+ Зацепки»/«Выбрать файл»). */
.tvz-entry__addch {
  display: inline-flex;
  align-items: center;
  height: 28px;
  width: fit-content;
  padding: 0 11px;
  border: 1px dashed var(--c-line-strong);
  border-radius: var(--rad);
  background: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--c-ac);
  cursor: pointer;
}
.tvz-entry__addch:hover {
  background: var(--c-hover);
}
.tvz-entry__ch-extra {
  margin-top: 8px;
}

/* Триггер площадок (README §6d): одна строка вместо чипов — «не выбрана»
   или список имён, шеврон справа. Открывает тот же попап-чек-лист
   (`.tvz-tagpick`), что и `multiSelect` (core/ui.js) на экране/шторке. */
.tvz-entry__sitesbtn {
  width: 100%;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 11px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  background: var(--c-surface);
  font-size: var(--fz);
  color: var(--c-tx);
  cursor: pointer;
}
.tvz-entry__sitesbtn .tvz-icon {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--c-tx-4);
}
.tvz-entry__sitesbtn-t {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-entry__sitesbtn-t.is-ph {
  color: var(--c-tx-4);
}

/* Правая колонка (роль) теснее левой — 10px против общих 14px `.tvz-modal__col`
   (макет 6d). */
.tvz-modal__col--tight {
  gap: 10px;
}

/* Роль шире полей слева: названия ролей многословные («Согласование визита
   установщика», «Оформление сервисных заявок») — на честных 1fr/1fr самая
   населённая группа («Работы на площадке», 6 ролей) переносила тело за
   порог 520 (измерено на стенде: 539px при потолке 520). Перевес отдаёт
   ширину туда, где текст её просит, а не растягивает окно вниз. */
.tvz-modal--pack .tvz-entry__cols--roles-wide {
  grid-template-columns: 0.82fr 1.18fr;
}

/* В узком окне — одна колонка, как у всех окон форм-фактора. Правило стоит
   ЗДЕСЬ, а не в общем медиа-блоке выше: там оно объявлено раньше по файлу
   и проигрывало этой пропорции порядком — доска ролей оставалась колонкой
   180px, а поля рядом ужимались до 125. */
@media (max-width: 900px) {
  .tvz-modal--pack .tvz-entry__cols--roles-wide {
    grid-template-columns: 1fr;
  }
}

/* Доска ролей форм-фактора: раздел справочника раскрыт ВСЕГДА — все три
   сразу, а не «раскрыта первая» (README §6d, «Что меняется в поведении»
   п.3). Фолд-разметка `roleChooser`-а (`.tvz-fold`, people.js) не трогается
   ни строкой: тело просто не прячется здесь, и своей кнопки
   «Показать/Свернуть» у пакованной доски нет.
   Цвет закреплён за ПОЗИЦИЕЙ группы в справочнике (README §2.3) — тот же
   приём, что у `.tvz-ccard__group` (cards.js): entry.js пишет готовую
   строку `--tint-*` (`roleGroupTintStyle(index)`) прямо на `.tvz-roles__g`,
   здесь эти переменные только ЧИТАЮТСЯ, своих hex нет ни одного. */
.tvz-entry__roles--board .tvz-roles__sum {
  display: none;
}
.tvz-entry__roles--board .tvz-roles__gs {
  gap: 8px;
}
.tvz-entry__roles--board .tvz-roles__g {
  padding: 0;
  border: 1px solid var(--tint-bd, var(--c-bd));
  border-radius: var(--rad);
  background: none;
  overflow: hidden;
}
.tvz-entry__roles--board .tvz-roles__g .tvz-fold__b {
  display: block;
}
.tvz-entry__roles--board .tvz-roles__g > h3 {
  margin: 0;
  height: 26px;
  padding: 0 10px;
  background: var(--tint-hd, var(--c-chip));
  color: var(--tint-tx, var(--c-tx-2));
  font-size: 11.5px;
  font-weight: 700;
}
.tvz-entry__roles--board .tvz-roles__g .tvz-card__act {
  display: none;
}
.tvz-entry__roles--board .tvz-roles__cs {
  padding: 8px 9px;
  background: var(--tint-bg, transparent);
  gap: 5px;
}
/* Тёмная тема: та же поправка контраста, что у `.tvz-rrow__gb`/
   `.tvz-rmodal__groupbd` — палитра не меняется по теме (фиксированно
   светлая), и тело раздела в тёмной теме падает на обычный `--c-hover`. */
html[data-theme="dark"] .tvz-entry__roles--board .tvz-roles__cs {
  background: var(--c-hover);
}
.tvz-entry__roles--board .tvz-roles__c {
  min-height: 24px;
  height: 24px;
  padding: 0 9px;
  border-radius: 999px;
  background: var(--c-surface);
  border-color: var(--tint-bd, var(--c-bd));
  color: var(--tint-tx, var(--c-tx));
  font-size: 11.5px;
}
.tvz-entry__roles--board .tvz-roles__c.is-on {
  background: var(--tint-hd, var(--c-chip));
  border-color: var(--tint-tx, var(--c-ac));
}

/* «Пока не знаю» форм-фактора: пунктирная пилюля вместо мягкой кнопки
   с иконкой (README §6d) — сама кнопка чужая (`roleChooser`), меняем
   только вид через класс, который entry.js вешает на её строку. */
.tvz-entry__roles-unknown-row .tvz-btn {
  height: 28px;
  padding: 0 11px;
  border: 1px dashed var(--c-line-strong);
  border-radius: 999px;
  background: none;
  color: var(--c-tx-2);
  font-weight: 600;
}
.tvz-entry__roles-unknown-row .tvz-btn .tvz-icon {
  display: none;
}
.tvz-entry__roles-unknown-row .tvz-btn.is-on {
  border-style: solid;
  border-color: var(--c-warn);
  color: var(--c-warn);
}

/* Значки «Масштаба» — три величины тремя тонами (слово владельца 05.08):
   юрлица — рабочий синий, площадки — зелёный, люди — графит. Ровно
   существующие токены, у числа тон прежний (ноль людей — красный как был). */
.tvz-scalenum__i--legal-entity { color: var(--c-ac); }
.tvz-scalenum__i--site { color: var(--c-ok-d); }
.tvz-scalenum__i--users { color: var(--c-tx-2); }

/* ============================================================================
   П-78 «Ожидание говорит» — молчащая пауза после нажатия обязана показать,
   что работа идёт. Три своих класса; фабрика (core/ui.js) решает, когда их
   ставить, здесь — только их вид.
   ============================================================================ */

/* --- занятая кнопка (button()/modal()/kebabMenu — core/ui.js) -------------- */
/* Появляется не сразу — таймер уже в JS (порог ~180мс, подсадка 5): здесь
   только то, что видно, когда он истёк. `disabled` уже даёт .5 непрозрачности
   (design.css, апстрим) — is-busy поверх неё чуть темнее и с крутилкой, чтобы
   «жду ответа» не путалось с «недоступно вообще» (расписание, чужой пул). */
.tvz-btn.is-busy,
.tvz-fpill.is-busy,
.tvz-menu__it.is-busy {
  opacity: .75;
  cursor: progress;
}
.tvz-btn__spin {
  display: inline-block;
  width: 13px;
  height: 13px;
  border-radius: 999px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: .7;
  animation: tvz-spin .7s linear infinite;
  flex: none;
}
@keyframes tvz-spin {
  to { transform: rotate(360deg); }
}

/* --- комбо-подсказки: «ищу…», пока источник ещё в пути -------------------- */
/* Тот же вид, что у «нет совпадений» (design.css) — разное СЛОВО, а не
   разный контейнер, иначе смена состояния сама по себе мигала бы местом. */
.tvz-combo__loading {
  padding: 10px;
  color: var(--c-mut);
  font-size: var(--fz-sm);
  text-align: center;
}

/* --- тонкая полоса прогресса сверху при переходе между разделами (app.js) - */
/* Тот же порог показа, что у занятой кнопки: мгновенный переход не мелькает
   полосой. Бежит поверх контента, а не толкает его — иначе сама полоса стала
   бы источником прыжка, с которым волна и борется. */
.tvz-main {
  position: relative;
}
.tvz-topload {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  z-index: 40;
  transition: opacity .12s ease;
}
.tvz-topload.is-on {
  opacity: 1;
}
.tvz-topload::after {
  content: '';
  position: absolute;
  top: 0;
  left: -35%;
  width: 35%;
  height: 100%;
  background: var(--c-ac);
  border-radius: var(--rad-pill);
  animation: tvz-topload-run 1.1s ease-in-out infinite;
}
@keyframes tvz-topload-run {
  0% { left: -35%; }
  60% { left: 100%; }
  100% { left: 100%; }
}
/* Тёмная тема (подсадка 4): полоса берёт тот же токен --c-ac — на тёмном фоне
   он уже проверен на контраст (используется в кнопках/пилюлях), второй
   палитры под неё заводить незачем. */

/* --- действия прежнего экрана заняты, пока едет переход (app.js) ---------- */
/* Дополнение владельца 05.08 по ходу волны: «один живой переход». Пока
   `#crm-content[data-loading]` стоит, прежний раздел ещё на экране (П-64
   держит его, чтобы не мигать) — но щёлкать по его кнопкам, когда он вот-вот
   исчезнет, отправляет ход не туда. Меню разделов (`#crm-nav`) вне этого
   поддерева и кликабельно всегда: им, наоборот, ОТМЕНЯЮТ текущий переход
   (клик по другому разделу) — правило именно про содержимое, не про навигацию. */
.tvz-content[data-loading] {
  pointer-events: none;
}

/* --- сцена перехода: раздел строится ЗДЕСЬ, пока прежний ещё на экране ---- */
/* М3-2 (гонка тела разделов): «нажал Клиенты, пока грузился Мой день —
   шапка новая, а тело от Моего дня». Каждый переход рисуется в свой узел
   (`contentStage`, app.js) и попадает на экран, только если он всё ещё
   последний. Узел стоит В ДОКУМЕНТЕ и той же геометрии, что займёт: экраны
   спрашивают `host.isConnected` и меряют себя при отрисовке — отсоединённому
   узлу они честно отвечают «человека здесь нет» и не рисуются вовсе.
   Не видно и не нажимается: прежний раздел до последнего мгновения остаётся
   единственным, с чем человек имеет дело (обещание П-64). `visibility:hidden`
   здесь не подходит — она отнимает у строящегося экрана фокус, а поле поиска
   его при отрисовке берёт. */
.tvz-content--stage {
  position: absolute;
  left: 0;
  right: 0;
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}

/* ============================================================================
   Дополнение владельца 05.08, по ходу волны П-78 — «открываю модалку, а
   скролл работает на фоновой странице». Фон заперт, пока на экране открыт
   любой полноэкранный оверлей (окно, лайтбокс, мобильная шторка).
   ============================================================================ */

/* --- окна и лайтбокс: класс ставит/снимает core/ui.js (счётчик вложенности,
   см. lockScroll/unlockScroll) --------------------------------------------- */
html.tvz-lock {
  overflow: hidden;
}

/* --- мобильные шторки: тот же замок, тем же классом — но БЕЗ хука из JS.
   Четыре места строят `.tvz-pd__sheetback` порознь (deal_card_mobile.js,
   deals_mobile.js, entry.js, more_sheet.js) вне владения этой волны, и
   общей точки открытия/закрытия у них нет — `lockScroll()` неоткуда
   позвать. `:has()` даёт ТОТ ЖЕ результат без права записи в эти файлы:
   пока в документе есть хоть одна подложка шторки, `<html>` заперт тем же
   правилом, что и у modal(); шторка исчезла — правило перестало совпадать
   само, без риска рассинхронить счётчик, которого здесь и нет. */
html:has(.tvz-pd__sheetback) {
  overflow: hidden;
}

/* --- скролл своего тела не утекает дальше — не в фон, не по цепочке ------- */
/* Докрутка до конца длинного списка модалки (6f) или колонки (6g) раньше
   передавала остаток прокрутки тому, что дальше по цепочке (в невидимый
   фон, до правки выше — в него самого). `contain` останавливает её на
   границе тела, дальше видимого края уже ничего не крутится. */
.tvz-modal__body,
.tvz-pd__sheet-body {
  overscroll-behavior: contain;
}

/* --- ширина страницы не дёргается при запирании ---------------------------- */
/* `.tvz-app{height:100vh;overflow:hidden}` (design.css) не даёт `html`/`body`
   держать свой скроллбар в обычной работе — дёргаться там нечему. Резерв
   всё равно объявлен: правило дешёвое, а в контуре с другой прокруткой
   (печать, увеличенный масштаб браузера) не даёт `overflow:hidden` сдвинуть
   контент на ширину скроллбара, который вот-вот исчезнет. */
html {
  scrollbar-gutter: stable;
}

/* Дышащие точки «Ждём агента» (слово владельца 05.08): ответ занимает
   1–2 минуты, статичное многоточие читалось как «зависло». Уважение к
   prefers-reduced-motion — точки просто стоят. */
.tvz-chat__dots { display: inline-flex; gap: 3px; margin-left: 4px; }
.tvz-chat__dots i {
  width: 4px; height: 4px; border-radius: 999px;
  background: var(--c-tx-4);
  animation: tvz-dot-breathe 1.2s ease-in-out infinite;
}
.tvz-chat__dots i:nth-child(2) { animation-delay: .2s; }
.tvz-chat__dots i:nth-child(3) { animation-delay: .4s; }
@keyframes tvz-dot-breathe {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .tvz-chat__dots i { animation: none; opacity: .6; }
}

/* Поиск роли в выборе ролей (владелец, 05.08): строке нужен зазор от доски
   групп, а полю — вся ширина колонки. Класс свой, а не правка общего
   .tvz-entry__row: строк этого класса в формах много, зазор нужен этой. */
.tvz-entry__rolefind {
  margin-bottom: 10px;
}

.tvz-entry__rolefind .tvz-search {
  width: 100%;
}

/* «Две лупы в инпуте» (владелец, 05.08): у input[type=search] WebKit рисует
   СВОЮ лупу рядом с нашей фоновой. Вендорный design.css гасит только крестик
   отмены — родную лупу и кнопки результатов гасим надстройкой. */
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
  display: none;
}
/* ============================================================================
   КАРТОЧКА ЗВОНКА В «НЕРАЗОБРАННОМ» (П-91, хендофф владельца 05.08)
   ----------------------------------------------------------------------------
   Геометрия — из хендоффа дословно: лента 1040, тело сеткой `1fr 512px`,
   подвал 56 только с кнопками. Правая колонка фиксирована намеренно: строки
   действий читаются как список одинаковых объектов, а не как резиновая
   форма; левая тянется — саммари бывает и в три предложения, и в пять.

   Своих цветов здесь нет ни одного: всё токенами `--c-*` из design.css,
   поэтому тёмная тема работает теми же правилами, без второго блока.
   ========================================================================== */

.tvz-call {
  width: 100%;
  /* Во весь экран (владелец, 06.08): у разговора слева места много не
     бывает, а правая колонка держит свои 456px хендоффа сама. */
  max-width: none;
  margin-bottom: 14px;
  background: var(--c-surface);
  border: 1px solid var(--c-bd);
  border-radius: 12px;
  box-shadow: var(--e1);
  color: var(--c-tx);
  overflow: hidden;
}

/* Принятое касание УХОДИТ ВИДИМО (слово владельца 12.08). Карточка,
   пропавшая в тот же кадр, оставляет вопрос «я нажал или промахнулся?», а
   следующая под ней прыгает на освободившееся место раньше, чем глаз
   успевает проследить движение.

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

   Полсекунды: заметно, но не мешает тому, кто разбирает десяток подряд. */
.tvz-call.is-accepted {
  overflow: hidden;
  transform: translateX(32px);
  opacity: 0;
  max-height: 0;
  margin-bottom: 0;
  border-width: 0;
  transition:
    transform .28s ease-in,
    opacity .28s ease-in,
    max-height .34s ease-in .06s,
    margin-bottom .34s ease-in .06s;
}
/* Высота нужна ОТКУДА-ТО ехать: `max-height` анимируется только между двумя
   значениями, и без исходного переход не запускается вовсе. Предел с запасом
   — карточка звонка длиннее 3000px не бывает даже с десятком договорённостей. */
.tvz-call { max-height: 3000px; }

@media (prefers-reduced-motion: reduce) {
  /* Движение отключено — карточка исчезает сразу, как раньше. Страховочный
     таймер в `call_intake.js` уберёт её и без события перехода. */
  .tvz-call.is-accepted { transition: none; }
}

/* --- шапка: откуда звонок, когда, сколько, с кем -------------------------- */
/* Шапка — ОДНОЙ строкой, `padding: 11px 18px` (референс владельца 06.08,
   раздел 1). Перенос (`flex-wrap`) оставлен намеренно и только ради телефона:
   на 390px строка из чипа, времени, имени и номера не помещается физически,
   и `nowrap` там срезал бы номер собеседника. На столе шапка в один ряд
   умещается сама — переносить нечего. */
.tvz-call__head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 11px 18px;
  border-bottom: 1px solid var(--c-bd);
}
.tvz-call__src {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: 6px;
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
  font-size: 11.5px;
  font-weight: 700;
}
.tvz-call__src.is-out {
  background: var(--c-chip);
  color: var(--c-tx-2);
}
.tvz-call__at { font-size: 13.5px; font-weight: 700; }
/* Метка пояса стоит ВПЛОТНУЮ ко времени: «15:55» без неё читается как своё
   местное, а пояс здесь — настройка проекта, а не браузера. */
.tvz-call__tz { font-size: 11px; color: var(--c-tx-4); margin-left: -4px; }
.tvz-call__dur { font-size: 12px; color: var(--c-tx-4); }
.tvz-call__sep { width: 1px; height: 16px; background: var(--c-line-strong); }
.tvz-call__who { font-size: 13px; font-weight: 600; }
.tvz-call__who.is-unknown { color: var(--c-warn); }
.tvz-call__tel { font-size: 12.5px; color: var(--c-tx-2); }
.tvz-call__owner { margin-left: auto; font-size: 12px; color: var(--c-tx-4); }
/* Плеер записи (B-136) — нативный `<audio>` в шапке, справа от бэклога.
   `margin-left: auto` стоит на «Бэклог: …»; если владельца у карточки нет,
   вправо уезжает плеер — иначе он прилипал бы к телефону собеседника. */
.tvz-call__play { display: inline-flex; align-items: center; gap: 6px; height: 26px; }
/* Пилюля 26px (референс владельца 06.08, раздел 1) — под остальные элементы
   шапки (чип типа 24, строка 13.5): нативный плеер по умолчанию 54px и
   раздувал бы шапку вдвое. Ширина 200 — столько занимают кнопка, полоса и
   время; больше здесь нечему расти, а шире шапка переносилась бы на второй
   ряд. Своей отрисовки пилюли (треугольник + моно-хронометраж, как в
   макете) здесь нет намеренно: плеер обязан остаться НАТИВНЫМ (B-136,
   раздел 7 референса) — своя обвязка отняла бы скорость, перемотку
   клавишами, вывод в наушники и «сохранить как». */
.tvz-call__audio { height: 26px; width: 200px; }
/* Своей отрисовки у нативного плеера нет — красить нечего и не нужно.
   Единственное, что мы просим у браузера, — цветовую схему: без неё
   светлый плеер стоит белым пятном в тёмной теме. */
[data-tvz="dark"] .tvz-call__audio { color-scheme: dark; }

/* --- тело: слева читают, справа решают ------------------------------------ */
/* Деление по ВОПРОСУ, а не по типу записи (хендофф v2): слева «что было и
   что из этого следует», справа «какие карточки заведём». Так колонки ещё и
   сходятся по высоте — прежняя раскладка оставляла слева пустоту. */
/* Разговору — всё, что не занято карточками (владелец, 06.08 «колонку
   с саммари шире — там больше контента»): правой хватает 400 — её
   мини-формы собраны на 360, хендоффные 456 были запасом, а не нуждой. */
.tvz-call__body { display: grid; grid-template-columns: 1fr 400px; }
.tvz-call__left {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px;
  border-right: 1px solid var(--c-bd);
}
/* Правая колонка НЕ тянется по карточке: высоту задаёт левая (референс
   владельца 06.08, раздел 2, п. 4). Правки справа на левую не влияют — под
   строками стоит слот постоянной высоты, и колонке нечем расти. */
.tvz-call__right {
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 16px 18px;
}
.tvz-call__sect { display: flex; flex-direction: column; gap: 6px; }
.tvz-call__cap {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
}
.tvz-call__sum { margin: 0; font-size: 13px; line-height: 1.55; text-wrap: pretty; }
.tvz-call__deal { display: flex; gap: 9px; align-items: flex-start; }
.tvz-call__dot {
  flex: none;
  width: 5px;
  height: 5px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--c-ac);
}
.tvz-call__deal span + span { font-size: 12.5px; line-height: 1.5; color: var(--c-tx-2); }
/* «Агент отметил» прижата к низу колонки: иначе под ней оставалось бы
   пустое место в половину карточки. */
.tvz-call__note {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 11px 12px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-bg);
}
.tvz-call__notet { font-size: 12.5px; line-height: 1.5; color: var(--c-tx-2); }
/* Метка ошибки плеера сама НЕинтерактивна — курсор не притворяется ссылкой.
   Путь назад даёт соседняя кнопка «Ещё раз» (`.tvz-call__rec-retry`,
   B-146), а не сама метка. */
.tvz-call__rec {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding-top: 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--c-tx-4);
}
/* Кнопка «Ещё раз» (B-146) встаёт в ту же пилюлю 26px, что и плеер —
   `.tvz-btn--xs` заметно выше и раздул бы шапку, поэтому высота задаётся
   здесь, а не берётся из базового класса. */
.tvz-call__rec-retry { height: 22px; }

/* --- блок «Поставим задачи»: под разговором, из которого они выросли ------ */
.tvz-call__todo { display: flex; flex-direction: column; gap: 6px; }

/* --- правая колонка: какие карточки заведём ------------------------------ */
.tvz-call__rcap { display: flex; align-items: baseline; gap: 8px; }
.tvz-call__hint { font-size: 11.5px; color: var(--c-tx-4); }
.tvz-call__cnt { margin-left: auto; font-size: 11.5px; color: var(--c-tx-4); }
.tvz-call__grp {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--c-tx-4);
}
.tvz-call__line { flex: 1; height: 1px; background: var(--c-bd); }

.tvz-call__row { border: 1px solid var(--c-bd); border-radius: 8px; overflow: hidden; }
/* Снятая строка гаснет, но остаётся читаемой: человек должен видеть, ЧТО
   именно он снял, а не потерять строку из виду. */
.tvz-call__row.is-off { opacity: .62; }
.tvz-call__row.is-picked { border-color: var(--c-ac); }
/* Свёрнутая строка — 40px одной строкой (референс владельца 06.08, раздел 3).
   `min-height`, а не `height`: длинное предзаполнение по-прежнему ПЕРЕНОСИТСЯ,
   а не обрезается многоточием (человек отвечает за то, что принимает), —
   типовая строка при этом ровно 40. */
.tvz-call__rh {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 40px;
  padding: 9px 11px;
}
/* В правой колонке строка одноэтажная — содержимое по центру. В левой она
   несёт текст задачи с чипами в два-три этажа, и там верх остаётся верхом. */
.tvz-call__rows .tvz-call__rh { align-items: center; }
.tvz-call__box {
  flex: none;
  width: 17px;
  height: 17px;
  margin-top: 1px;
  padding: 0;
  border: 1.5px solid var(--c-line-strong);
  border-radius: 4px;
  background: transparent;
  color: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tvz-call__box.is-on { background: var(--c-ac); border-color: var(--c-ac); color: var(--c-on-ac); }
/* Метка типа — только у карточек: в блоке задач всё задачи, и освободившиеся
   56px отданы тексту. Ширина 56 — из референса владельца 06.08 (раздел 3):
   «Контакт», «Клиент» и «Сделка» умещаются в неё все три. */
.tvz-call__type { flex: none; width: 56px; font-size: 12.5px; font-weight: 700; line-height: 1.42; }
.tvz-call__mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
/* Предзаполнение переносится, а не обрезается многоточием: менеджер отвечает
   за то, что принимает, и прочитать это он должен целиком. */
/* `break-word`, а НЕ `anywhere`. Разница не в том, где рвать строку, а в
   минимальной ширине блока: `anywhere` разрешает разрыв где угодно И тем
   самым позволяет flex-колонке схлопнуться до одного символа — название
   сделки вставало столбиком по букве, а чипы рядом переполняли строку
   (слово владельца 12.08: «корявая вёрстка»). `break-word` рвёт только то,
   что иначе не влезет, а на расчёт min-content не влияет: колонка остаётся
   шириной с самое длинное слово. Многоточие здесь по-прежнему не ставим —
   менеджер отвечает за то, что принимает, и прочитать это он должен
   целиком. */
.tvz-call__fill {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--c-tx-2);
  overflow-wrap: break-word;
  min-width: 0;
}
.tvz-call__edit {
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--c-tx-4);
  font: inherit;
  font-size: 12px;
  line-height: 1.48;
  cursor: pointer;
}
.tvz-call__edit:hover { color: var(--c-ac); }

/* --- мини-форма строки ---------------------------------------------------- */
.tvz-call__form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 2px 11px 11px;
  border-top: 1px dashed var(--c-bd);
}
.tvz-call__f { display: flex; flex-direction: column; gap: 4px; }
.tvz-call__f > span { font-size: 11px; font-weight: 600; color: var(--c-tx-4); }
.tvz-call__f input,
.tvz-call__f select,
.tvz-call__f textarea {
  width: 100%;
  min-height: 30px;
  padding: 5px 10px;
  border: 1px solid var(--c-line-strong);
  border-radius: 7px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: 12.5px;
}
/* Поле-простыня растёт под свой текст (`fitArea` в call_intake.js), поэтому
   ни своей полосы прокрутки, ни ручки размера у него нет: и то и другое
   спорило бы с подгонкой. Полоса — это второе прокручиваемое место внутри
   слота, из-за которого хвост формы и оказался недостижим (Р-4 п.1); ручка
   размера — высота, назначенная руками, которую первая же правка текста
   отменит. `min-height` остаётся: пустое поле — всё ещё три строки. */
.tvz-call__f textarea { min-height: 56px; resize: none; overflow-y: hidden; }
.tvz-call__f input:focus,
.tvz-call__f select:focus,
.tvz-call__f textarea:focus { outline: none; border-color: var(--c-ac); }

/* --- кандидаты: «завести новое» или «выбрать существующее» ---------------- */
.tvz-call__pick {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px 11px;
  border-top: 1px solid var(--c-bd);
}
.tvz-call__pcap { font-size: 12px; font-weight: 600; color: var(--c-ac-d); }
.tvz-call__opt {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  cursor: pointer;
}
.tvz-call__opt.is-on { border: 1.5px solid var(--c-ac); background: var(--c-sel); }
.tvz-call__radio {
  flex: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1.5px solid var(--c-line-strong);
  display: flex;
  align-items: center;
  justify-content: center;
}
.tvz-call__opt.is-on .tvz-call__radio { border-color: var(--c-ac); }
.tvz-call__opt.is-on .tvz-call__radio::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-ac);
}
.tvz-call__oname {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  font-size: 12.5px;
  font-weight: 600;
}
.tvz-call__otitle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Причина совпадения — несущая часть кандидата, а не украшение: выбирать
   между голыми именами человеку нечем. */
.tvz-call__owhy { font-size: 11.5px; font-weight: 400; color: var(--c-tx-4); }
.tvz-call__oin {
  flex: none;
  width: 212px;
  height: 30px;
  padding: 0 10px;
  border: 1px solid var(--c-line-strong);
  border-radius: 7px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: 12.5px;
}

/* --- чипы задачи: срок и исполнители ------------------------------------- */
.tvz-call__chips { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tvz-call__who-chips { display: contents; }
.tvz-call__chip {
  flex: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 8px;
  border: 0;
  border-radius: 6px;
  background: var(--c-chip);
  color: var(--c-tx-2);
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-call__chip.is-ac { background: var(--c-ac-tint); color: var(--c-ac-d); cursor: default; }
.tvz-call__chip.is-more { background: none; border: 1px dashed var(--c-line-strong); }
/* «Слежу» (П-99) — обводкой, а не заливкой: рядом стоят чипы исполнителей,
   и заливка того же тона читалась бы как ещё один исполнитель. Контроль —
   не работа, и выглядеть он обязан иначе. */
.tvz-call__chip.is-watch {
  background: none;
  border: 1px solid var(--c-ac-bd);
  color: var(--c-ac-d);
}
/* Ответ на молчание: строка без единого чипа исполнителя иначе читается
   как «задача уйдёт в никуда». */
.tvz-call__self { font-size: 11.5px; color: var(--c-tx-4); }

/* --- «агент ничего не предложил» — это норма, а не пустое состояние ------- */
.tvz-call__none {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 11px 12px;
  border: 1px dashed var(--c-line-strong);
  border-radius: 8px;
  background: var(--c-bg);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--c-tx-2);
}

/* --- «+ Клиент» / «+ Сделка»: строка, которой агент не предложил (Р-3) ----
   Стоит ПОД списком строк вместе со слотом — это не строка, а вход в неё, и
   путать её со списком того, что уже создастся, нельзя. Между строкой и её
   слотом она больше не встаёт: там она разрывала бы блок вопроса и ответа
   (Р-4). Слова приглушены: обычный
   разбор идёт мимо этой кнопки, а нужна она там, где агент честно промолчал
   (организация в разговоре не прозвучала).                                  */
.tvz-call__add { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tvz-call__addc { font-size: 11.5px; color: var(--c-tx-4); }
.tvz-call__addb {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 9px;
  border: 1px dashed var(--c-line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--c-tx-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.tvz-call__addb:hover { border-color: var(--c-ac); color: var(--c-ac); }
.tvz-call__addb:disabled { opacity: .5; cursor: default; }

/* --- подвал: только кнопки, прижатые вправо ------------------------------ */
.tvz-call__foot {
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 0 18px;
  border-top: 1px solid var(--c-bd);
  background: var(--c-bg);
}
/* Причины отказа больше не раскрываются в подвале: «Отклонить» срабатывает
   сразу, а «Вернуть» и пилюли причины живут в тосте (референс владельца
   06.08, раздел 5) — стили действий тоста ниже, у `.tvz-toast__act`. */

/* --- действия внутри тоста (`toast.act`) --------------------------------- */
/* Надстройка над вендорным design.css (ADR-0002: копию не правим): сам
   `.tvz-toast` про кнопки внутри себя ничего не знает. Тост с действиями
   шире обычного и переносит строку — «Вернуть» плюс три причины в 380px
   ужались бы до нечитаемых огрызков. */
.tvz-toast:has(.tvz-toast__act) { flex-wrap: wrap; max-width: 460px; }
/* Обводка и подпись — `currentColor`: фон у тоста свой на каждый вид (ok,
   err, info, warn), и любой названный цвет спорил бы с одним из четырёх.
   Своего цвета кнопка не заводит вовсе — берёт цвет текста тоста. */
.tvz-toast__act {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border: 1px solid currentColor;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  opacity: .85;
  cursor: pointer;
}
/* Возврат — главное из действий: оно отменяет уже случившееся, а причина
   всего лишь уточняет. Отсюда вывернутая пара — плашка цвета поверхности с
   тёмной подписью: на цветном фоне тоста это единственный способ выделить
   одну кнопку из четырёх, не заводя пятого цвета. */
.tvz-toast__act.is-strong {
  border-color: transparent;
  background: var(--c-surface);
  color: var(--c-tx);
  font-weight: 700;
  opacity: 1;
}
.tvz-toast__act:hover { opacity: 1; }

/* --- окно «Когда сделать» (7d) в общем форм-факторе окон ------------------ */
.tvz-due { display: grid; grid-template-columns: 196px 1fr 172px; gap: 20px; align-items: start; }
.tvz-due__col { display: flex; flex-direction: column; gap: 6px; }
.tvz-due__cap {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--c-bd);
}
.tvz-due__q {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 11px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--c-tx-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-due__q:hover { background: var(--c-hover); }
.tvz-due__q span { margin-left: auto; font-size: 11.5px; font-weight: 400; color: var(--c-tx-4); }
.tvz-due__mhead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--c-bd);
}
.tvz-due__month { font-size: 13px; font-weight: 700; }
.tvz-due__nav { margin-left: auto; display: flex; gap: 4px; }
.tvz-due__nav button {
  width: 26px;
  height: 26px;
  border: 1px solid var(--c-line-strong);
  border-radius: 7px;
  background: none;
  color: var(--c-tx-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.tvz-due__dow, .tvz-due__days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.tvz-due__dow span {
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-tx-4);
}
.tvz-due__day {
  height: 30px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--c-tx);
  font-family: var(--font-mono);
  font-size: 12px;
  cursor: pointer;
}
.tvz-due__day:hover { background: var(--c-hover); }
.tvz-due__day.is-out { opacity: .45; }
.tvz-due__day.is-today { background: var(--c-ac-tint); border-color: var(--c-ac-bd); color: var(--c-ac); font-weight: 700; }
.tvz-due__day.is-on { background: var(--c-ac); border-color: var(--c-ac); color: var(--c-on-ac); font-weight: 700; }
.tvz-due__time {
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--c-line-strong);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-family: var(--font-mono);
  font-size: 15px;
}
.tvz-due__time:focus { outline: none; border: 1.5px solid var(--c-ac); box-shadow: 0 0 0 3px var(--c-ac-tint); }
.tvz-due__hours { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }
.tvz-due__h {
  height: 30px;
  border: 1px solid var(--c-line-strong);
  border-radius: 7px;
  background: none;
  color: var(--c-tx-2);
  font: inherit;
  font-family: var(--font-mono);
  font-size: 12px;
  cursor: pointer;
}
.tvz-due__h:hover { border-color: var(--c-ac); color: var(--c-ac); }
/* Пояс назван там, где выбирают час: «17:30» без пояса читается как своё
   местное, а срок у команды один (П-92). */
.tvz-due__tz {
  margin-top: 2px;
  font-size: var(--fz-micro);
  line-height: 1.4;
  color: var(--c-tx-4);
}

/* --- окно «Кому эта задача» (14b/15a) ------------------------------------
   Список СЕТКОЙ, а не чипами в поповере: у карточки звонка выбирают по
   три-четыре человека подряд, и выпадашка на каждого стоила бы два клика
   за один ответ. Две колонки — форма ответа на «не влезло» из контракта
   форм-фактора (П-74): десяток коллег в столбик перерос бы 520 тела. */
.tvz-whom { display: flex; flex-direction: column; gap: 11px; }
.tvz-whom__find {
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: var(--fz);
}
.tvz-whom__find:focus {
  outline: none;
  border: 1.5px solid var(--c-ac);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}
.tvz-whom__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  /* Длинный список СКРОЛЛИТСЯ внутри окна, а не растит его вниз: тело
     форм-фактора держит 520 без прокрутки самого окна (П-74). */
  max-height: 264px;
  overflow: auto;
}
/* Одна колонка — для узкого места: в правой колонке «Поставить задачу»
   (форм-фактор П-74 делит тело пополам) на имя осталось бы 190px, и
   «Тимохин Максим Сергеевич» не поместился бы ни в одну из двух. Потолок
   ниже по той же причине, по какой список вообще раскрывается на месте
   (Р-4 п.3): он раздвигает соседей вниз, и тумблер «Слежу за исполнением»
   под ним обязан остаться в теле окна. */
.tvz-whom__grid--one { grid-template-columns: 1fr; max-height: 176px; }
/* Поле «Кому» в окне задачи: кнопка раскрытия, список, строка итога.
   Кнопка встаёт по своей ширине, список — во всю; свёрнутый прячется
   НАЗВАННЫМ правилом: `display: flex` у `.tvz-whom` иначе перебивает
   `[hidden]` браузера, и «спрятанный» список остался бы на экране. */
.tvz-whom__wrap { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.tvz-whom__wrap > .tvz-whom { align-self: stretch; }
.tvz-whom[hidden] { display: none; }
.tvz-whom__p {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--c-bd);
  border-radius: var(--rad);
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: var(--fz);
  text-align: left;
  cursor: pointer;
}
.tvz-whom__p:hover { background: var(--c-hover); }
.tvz-whom__p.is-on {
  border: 1.5px solid var(--c-ac);
  background: var(--c-sel);
  font-weight: 600;
}
.tvz-whom__box {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border: 1.5px solid var(--c-line-strong);
  border-radius: 4px;
  color: var(--c-on-ac);
}
.tvz-whom__p.is-on .tvz-whom__box {
  border-color: var(--c-ac);
  background: var(--c-ac);
}
.tvz-whom__n {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-whom__r { flex: none; font-size: var(--fz-sm); color: var(--c-mut); }
.tvz-whom__none { font-size: var(--fz-sm); color: var(--c-tx-4); }

/* Галочка контроля (П-99) — с последствием В МЕТКЕ, а не абзацем под ней
   (канон П-74). Видна только тогда, когда задача уходит другому: своя
   галочки не показывает — «у исполнителя нет функции контроля». */
.tvz-whom__watch {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 12px 13px;
  border: 1px solid var(--c-bd);
  border-radius: 9px;
  cursor: pointer;
}
.tvz-whom__watch.is-on {
  border: 1.5px solid var(--c-ac);
  background: var(--c-sel);
}
.tvz-whom__watch input { margin: 2px 0 0; accent-color: var(--c-ac); }
.tvz-whom__watchb { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tvz-whom__watcht { font-size: var(--fz); font-weight: 700; }
.tvz-whom__watchw { font-size: var(--fz-sm); line-height: 1.5; color: var(--c-tx-2); }
/* Итог словами стоит В ТЕЛЕ, а не в подвале: подвал окон форм-фактора несёт
   только кнопки, и приписка в нём проверяется сторожем (П-74). */
.tvz-whom__state { font-size: var(--fz-sm); color: var(--c-tx-4); }

/* --- узкий экран: колонки встают друг под друга -------------------------- */
/* Карточка звонка задумана десктопной (её читают за столом), но экран
   продукта равноправен на телефоне: 512-я колонка на 375px превратила бы
   карточку в горизонтальную прокрутку — худшее, что бывает со списком. */
@media (max-width: 900px) {
  .tvz-call__body { grid-template-columns: 1fr; }
  .tvz-call__left { border-right: 0; border-bottom: 1px solid var(--c-bd); }
  .tvz-due { grid-template-columns: 1fr; }
}

/* --- телефон: метка строки и её текст не делят строку (М3-10) ------------ */
/* `.tvz-call__type` держит фиксированные 64px метки, и на телефоне остаток
   доставался тексту — у «Заметки» это 2–3 слова в строке между переносами
   (снимок p04, круг двойника №3). Метка (вместе с чекбоксом и «Поправить»)
   встаёт на свою строку, текст — на следующую, во всю ширину: тот же приём,
   что у `.tvz-check__r` чуть выше по файлу. Брейкпоинт 560px — общий
   телефонный порог этого файла, не 900px строчной раскладки колонок. */
@media (max-width: 560px) {
  .tvz-call__rh { flex-wrap: wrap; }
  .tvz-call__type { order: 1; }
  .tvz-call__edit { order: 2; margin-left: auto; }
  .tvz-call__mid { order: 3; flex: 1 1 100%; }
}

/* --- слова о противоречии — У СТРОКИ, а не общей плашкой внизу ------------ */
/* Чинить надо здесь, и человек должен видеть где. Молча снять чужую галку
   нельзя: он нажал бы «Принять» и получил не то, что видел (матрица П-91). */
/* Цвет гейта — ошибочный, а не предупреждающий (референс владельца 06.08,
   раздел 3): непрозвучавшее и спорящие строки не «на всякий случай», а
   прямая причина, по которой «Принять отмеченное» погашено. */
.tvz-call__bad {
  padding: 0 11px 9px 38px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--c-err);
}
.tvz-call__row:has(.tvz-call__bad:not([style*="none"])) {
  border-color: var(--c-err-bd);
  background: var(--c-errbg);
}

/* --- строка, у которой решать больше нечего (клиент выбранной сделки) ----- */
/* Не «снятая галка молча», а информация: у сделки клиент уже есть, и
   спрашивать его второй раз не о чем (матрица П-91, п. 4). */
.tvz-call__row.is-locked { background: var(--c-bg); opacity: 1; }
.tvz-call__row.is-locked .tvz-call__box { visibility: hidden; }
.tvz-call__row.is-locked .tvz-call__edit { display: none; }
/* Правила «спрятать кандидатов у запертой строки» здесь больше нет: выбор
   живёт в слоте, а не внутри строки, и замок просто сворачивает её (см.
   `lock` в call_intake.js) — прятать чужую панель со стороны строки значило
   бы завести второе место, где строка знает про своё раскрытие. */

/* Редактор «О чём говорили» (владелец, 06.08): та же типографика, что у
   читаемого абзаца, — правка не должна выглядеть другим текстом. */
.tvz-call__sumfix { margin-left: 8px; font-size: 12px; }
.tvz-call__sumedit {
  width: 100%;
  font: inherit;
  font-size: 13px;
  line-height: 1.55;
  padding: 8px 10px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-tx);
  resize: vertical;
}

/* Галочка подтверждения текстового поля мини-формы (владелец, 06.08):
   поле и «готово» — одна строка, галочка того же роста, что контрол. */
.tvz-call__frow { display: flex; gap: 6px; align-items: stretch; }
.tvz-call__frow input, .tvz-call__frow textarea { flex: 1; min-width: 0; }
.tvz-call__fok {
  flex: none;
  width: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-ac);
  cursor: pointer;
}
.tvz-call__fok:hover { background: var(--c-ac-tint); border-color: var(--c-ac); }

/* ------------------------------------------------------------------------ */
/* Строка «Сделка»: второй ответ — «Прикрепить к существующей» (П-97, 9a/9b/9c)
   Геометрия дословно из хендоффа владельца 06.08: обводка раскрытой строки
   1.5px акцентом, шапка залита `--c-ac-tint`, сегмент 28px в контейнере с
   padding 3px, строки списка 8px 10px и радио 15×15 — тот же приём, что у
   кандидатов контакта и клиента в 7a.                                       */
/* ------------------------------------------------------------------------ */

.tvz-call__rows { display: flex; flex-direction: column; gap: 6px; }

/* Раскрытая строка — обводка акцентом (референс владельца 06.08, раздел 3).
   Толщина набирается тенью, а не border-width: 1.5px вместо 1px сдвинули бы
   строку на полпикселя, и высота карточки менялась бы от раскрытия — ровно
   то, ради чего заведён слот (раздел 2). */
.tvz-call__row.is-open {
  border-color: var(--c-ac);
  box-shadow: 0 0 0 .5px var(--c-ac);
}
.tvz-call__row.is-open > .tvz-call__rh { background: var(--c-ac-tint); align-items: center; }
.tvz-call__row.is-open > .tvz-call__rh .tvz-call__fill {
  font-size: 12px;
  font-weight: 600;
  color: var(--c-ac-d);
}
/* Шапка раскрытой строки: название сделки и вопрос — две строки, не одна
   слепленная (владелец, 06.08 «прибери интерфейс»). */
.tvz-call__fill:has(.tvz-call__fname) { display: flex; flex-direction: column; gap: 1px; }
.tvz-call__fname { color: var(--c-tx); font-weight: 700; }
.tvz-call__fask { font-weight: 500; }
.tvz-call__row.is-open > .tvz-call__rh .tvz-call__edit { color: var(--c-ac); }

.tvz-call__att {
  padding: 10px 11px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  border-top: 1px solid var(--c-bd);
}
.tvz-call__attb { display: flex; flex-direction: column; gap: 7px; }

/* Сегментированный переключатель на всю ширину: два ответа строки. */
.tvz-call__seg {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--c-chip);
  border-radius: 8px;
}
.tvz-call__segb {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Высота НЕ фиксированная: при длинной подписи в узкой колонке текст
     переносился на две строки и вылезал за пределы кнопки — переключатель
     разъезжался. `min-height` держит прежний рост у коротких подписей, а
     длинной даёт вырасти, не ломая ряд; `nowrap` не ставим, чтобы подпись
     не обрезалась молча на узком экране. */
  min-height: 28px;
  padding: 4px 8px;
  line-height: 1.2;
  text-align: center;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--c-mut);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-call__segb.is-on {
  background: var(--c-surface);
  box-shadow: var(--e1);
  color: var(--c-tx);
  font-weight: 700;
}

/* Клиент, подставленный из строки выше: одно и то же не спрашивается дважды. */
.tvz-call__cli {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-bg);
}
.tvz-call__clic {
  flex: none;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--c-tx-4);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.tvz-call__clin {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-call__clif {
  flex: none;
  border: 0;
  background: none;
  padding: 0;
  color: var(--c-ac);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

/* Шаги 9c: клиент — шаг ВНУТРИ строки «Сделка». */
.tvz-call__step { display: flex; flex-direction: column; gap: 5px; }
.tvz-call__step.is-dim { opacity: .5; }
.tvz-call__stepc {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
}
.tvz-call__wait {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 0 12px;
  border: 1px dashed var(--c-line-strong);
  border-radius: 8px;
  font-size: 12px;
  color: var(--c-tx-4);
  text-align: center;
}
.tvz-call__hits {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  overflow: hidden;
}
.tvz-call__hit {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border: 0;
  border-bottom: 1px solid var(--c-bd2);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.tvz-call__hit:last-child { border-bottom: 0; }
.tvz-call__hit.is-on { background: var(--c-sel); }
.tvz-call__hit:hover { background: var(--c-hover); }
.tvz-call__hitn { font-size: 12.5px; font-weight: 600; color: var(--c-tx); }
.tvz-call__hitw { font-size: 11.5px; color: var(--c-tx-4); }
.tvz-call__hit.is-new { font-size: 12.5px; font-weight: 600; color: var(--c-ac); }

/* Список сделок: радио-строки той же геометрии, что кандидаты 7a. */
.tvz-call__deals { display: flex; flex-direction: column; gap: 7px; }
.tvz-call__dopt {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 8px 10px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  cursor: pointer;
}
.tvz-call__dopt.is-on { border: 1.5px solid var(--c-ac); background: var(--c-sel); }
.tvz-call__dopt.is-on .tvz-call__radio { border-color: var(--c-ac); }
.tvz-call__dopt.is-on .tvz-call__radio::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-ac);
}
.tvz-call__dopt .tvz-call__radio { margin-top: 2px; }
.tvz-call__dname { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.tvz-call__dtitle { font-size: 12.5px; font-weight: 600; line-height: 1.4; }
.tvz-call__dmeta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tvz-call__dtouch { font-size: 11.5px; color: var(--c-tx-4); }
.tvz-call__dwhy { font-size: 11.5px; color: var(--c-ac-d); }
.tvz-call__pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* Не выше содержимого и не шире колонки: «прикрепим к существующей» на
     узкой правой колонке распирало строку и выдавливало название. */
  min-height: 20px;
  max-width: 100%;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--c-chip);
  font-size: 11px;
  font-weight: 600;
  color: var(--c-tx-2);
}
.tvz-call__pill.is-ac {
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
  font-weight: 700;
}
/* Закрытая сделка находится только поиском и приходит С ЭТИМ СЛОВОМ:
   «прикрепим к закрытой» человек обязан решать, видя его (14c). */
.tvz-call__pill.is-done {
  background: var(--c-okbg);
  color: var(--c-ok-d);
  font-weight: 700;
}
/* Чужой клиент — предупреждение, а не пометка: выбор такой сделки заменит
   клиента карточки, и цвет обязан отличаться от «просто этапа». */
.tvz-call__pill.is-alien {
  background: var(--c-warnbg);
  color: var(--c-warn);
  font-weight: 700;
}

/* Вход в окно «Найти сделку» из слота: ссылка, а не вторая строка поиска —
   слот отвечает «к какой из его открытых», окно — «а если нужной тут нет». */
.tvz-call__other {
  align-self: flex-start;
  padding: 0;
  border: 0;
  background: none;
  color: var(--c-ac);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-call__other:hover { color: var(--c-ac-d); text-decoration: underline; }

/* --- окно «Найти сделку» (14c) ------------------------------------------- */
.tvz-find { display: flex; flex-direction: column; gap: 10px; }
.tvz-find__q {
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--rad);
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: var(--fz);
}
.tvz-find__q:focus {
  outline: none;
  border: 1.5px solid var(--c-ac);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}
/* Выдача СКРОЛЛИТСЯ внутри окна: тело форм-фактора держит 520 (П-74), а
   длина выдачи — вопрос запроса, а не окна. */
.tvz-find__list {
  display: flex;
  flex-direction: column;
  gap: 7px;
  max-height: 340px;
  overflow: auto;
}
.tvz-find__note { font-size: var(--fz-sm); color: var(--c-warn); }

/* Поиск клиента в слоте — ПОЛЕ, а не пунктирная строка (Р-4, владелец 07.08:
   «инпут сливается с фоном»). Пунктир на прозрачном читался приглашением, а
   не местом ввода: панель слота залита `--c-bg`, и поле на ней исчезало.
   Приём взят у полей продукта (`.tvz-find__q`, окно «Найти сделку», и поля
   `.tvz-modal--pack`): сплошная кромка `--c-line-strong`, поверхность
   `--c-surface`, фокус — 1.5px акцентом с тинтом. Своего вида у карточки
   касания здесь нет и быть не должно — поле везде выглядит полем. */
.tvz-call__find { position: relative; display: flex; align-items: center; }
.tvz-call__find svg { position: absolute; left: 10px; color: var(--c-tx-4); }
.tvz-call__find input {
  width: 100%;
  height: 32px;
  padding: 0 10px 0 31px;
  border: 1px solid var(--c-line-strong);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: 12px;
  outline: none;
}
.tvz-call__find.is-focus svg { color: var(--c-ac); }
.tvz-call__find.is-focus input {
  height: 34px;
  border: 1.5px solid var(--c-ac);
  background: var(--c-surface);
  font-size: 12.5px;
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}

/* ------------------------------------------------------------------------ */
/* Слот фиксированной высоты — правило неподвижности (референс владельца
   06.08, раздел 2). В списке строк «Контакт / Клиент / Сделка» всегда стоит
   одна область 292px: свободна — в ней плитка «Уедет в сделку» под всеми
   строками, открыта строка — её правка или выбор вплотную под ЭТОЙ строкой
   (Р-4). Прежде раскрытие росло внутрь строки, и карточка прыгала под
   курсором вместе с левой колонкой.                                         */
/* ------------------------------------------------------------------------ */
.tvz-call__slot { flex: none; height: 292px; display: flex; flex-direction: column; }
.tvz-call__panel {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-bg);
  overflow: hidden;
}
/* Панель строки ЛЕВОЙ колонки слота не знает: там расти можно, и обёртка
   растворяется — форма и кандидаты остаются прямыми детьми строки, со своими
   отбивками и разделителем. */
.tvz-call__row > .tvz-call__panel { display: contents; }
/* Внутри слота отбивки и разделители снимаются: рамку и фон держит сама
   панель, второй набор границ рисовал бы коробку в коробке. */
.tvz-call__panel > .tvz-call__att,
.tvz-call__panel > .tvz-call__form,
.tvz-call__panel > .tvz-call__pick { padding: 0; border-top: 0; }
/* Длинные списки (кандидаты, сделки клиента, коллеги) скроллятся ВНУТРИ
   слота и наружу не растут. Выбор прикрепления ужимается первым: его шапка —
   переключатель — обязана остаться на виду, прокручивается только список. */
.tvz-call__panel > .tvz-call__att { flex: 0 1 auto; min-height: 0; }
.tvz-call__panel .tvz-call__attb { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.tvz-call__panel > .tvz-call__form,
.tvz-call__panel > .tvz-call__pick { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* --- строка и слот — ОДИН блок (Р-4, владелец 07.08) ---------------------- */
/* «Смотри, я хочу найти или создать клиента — приходится перепрыгивать через
   сделку»: строка «Клиент» стояла второй, а её поле поиска — внизу, под
   строкой «Сделка». Слот переехал под свою строку (см. `editSlot`), и здесь
   закрывается стык: щель списка съедается отрицательным отступом и тут же
   возвращается снизу. Возврат несущий — без него занятый слот укорачивал бы
   колонку на 6px, а правило неподвижности запрещает ей меняться вовсе. */
.tvz-call__row.is-open + .tvz-call__slot { margin-top: -6px; margin-bottom: 6px; }
/* Строка — шапка блока, слот — его тело: одна обводка акцентом на двоих,
   скруглений на стыке нет, а разделяет их одна линия (нижняя граница
   строки), а не две сложенные. */
.tvz-call__row.is-open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.tvz-call__row.is-open + .tvz-call__slot > .tvz-call__panel {
  border-top: 0;
  padding-top: 10px; /* 9 + снятая граница: содержимое не съезжает вверх */
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-color: var(--c-ac);
  box-shadow: 0 0 0 .5px var(--c-ac); /* та же полуторапиксельная кромка, что у строки */
}
/* Слова гейта в слоте — СТРОКА ТЕКСТА, а не плашка: место действия уже
   обведено акцентом, и заливать его вторым цветом тревоги незачем. Плашка
   осталась там, где она одна и говорит, — у свёрнутой строки. */
.tvz-call__panel > .tvz-call__bad { padding: 0; }

/* Плитка «Уедет в сделку» — счёт отмеченного словами. */
.tvz-call__go {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 11px;
  border: 1px solid var(--c-bd);
  border-radius: 8px;
  background: var(--c-bg);
}
/* Не больше двух строк, дальше многоточие (референс, раздел 2): плитка
   отвечает на «что уедет», а не пересказывает карточку заново. */
.tvz-call__got {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-tx-2);
}

/* Найденное в базе — пилюля рядом со значением (референс, раздел 3): строка
   остаётся одной строкой, а «уже в базе» читается взглядом. */
.tvz-call__found {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: 19px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--c-okbg);
  color: var(--c-ok-d);
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
}
/* Значение и пилюля делят ОДНУ строку, а не две. Остальные строки (задачи с
   чипами, раскрытая «Сделка» с вопросом) остаются колонкой. */
.tvz-call__mid:has(.tvz-call__found) { flex-direction: row; align-items: center; gap: 7px; }

/* Строка с пилюлей отдаёт имени СВОЮ строку (Р-4 п.2, владелец 07.08).

   Пока клиента не выбрали, имени в строке 173px — оно переносится по словам
   и читается. Как только его выбрали поиском, рядом встают пилюля «уже в
   базе», «Поправить» и «Убрать»: от 400px правой колонки имени остаётся 44,
   и оно рвётся ПОСРЕДИ СЛОВ — «Двойн / ик4 / Полны / й». А это состояние,
   в котором менеджер живёт весь день.

   Многоточием не режем: «менеджер отвечает за то, что принимает, и прочитать
   это он должен целиком» (правило переноса выше по файлу). Значит имени нужна
   ширина — и берётся она тем же приёмом и теми же четырьмя правилами, какими
   её берёт телефон (медиазапрос 560px выше): метка с кнопками остаются
   первой строкой, значение с пилюлей встают второй, во всю ширину. Своей
   раскладки для этого случая продукт не заводит.

   Только правая колонка: пилюля бывает у «Контакта» и «Клиента», а в левой
   живут задачи, и там строка многоэтажная и без того. */
.tvz-call__rows .tvz-call__row.is-found > .tvz-call__rh { flex-wrap: wrap; }
.tvz-call__rows .tvz-call__row.is-found > .tvz-call__rh > .tvz-call__type { order: 1; }
.tvz-call__rows .tvz-call__row.is-found > .tvz-call__rh > .tvz-call__edit {
  order: 2;
  margin-left: auto;
}
.tvz-call__rows .tvz-call__row.is-found > .tvz-call__rh > .tvz-call__mid {
  order: 3;
  flex: 1 1 100%;
}

/* Пилюля не ломается посреди слова: узкая колонка переносит РЯД пилюль,
   а не текст внутри одной (правая колонка 400 против 456 в макете). */
.tvz-call__pill { white-space: nowrap; }

/* ===========================================================================
   Окно «Создать клиента» — визард на три шага (референс
   `_flow/refs/wizard/design_handoff_new_client/`, 07.08).

   Инлайновый стиль макета живёт ЗДЕСЬ классом, а не в разметке экрана:
   макет рисует одно окно, а продукт держит светлую и тёмную тему, узкое
   окно и правки владельца — восемь копий геометрии по строкам `style=`
   разъехались бы на первой же из них (тот же довод, что у `.tvz-modal--pack`).

   Несущее — ГЕОМЕТРИЯ: окно 1040, шапка 60, степпер 56, подвал 60, а левая
   колонка тела держит `min-height: 452px`. Ради последней строки всё и
   затевалось: без неё окно прыгает между шагами, и человек на каждом шаге
   заново ищет глазами кнопку «Далее» (референс, раздел 1).
   =========================================================================== */

.tvz-cw .tvz-modal__head { height: 60px; padding: 0 20px; }
/* Высота тела ЗАДАНА, а не выведена из содержимого, и это несущее. `min-height`
   референса держит окно ровно до тех пор, пока шаг влезает; шаг, которому мало
   (третий с полным словарём ролей, второй с четырьмя юрлицами), растил бы окно —
   и человек на каждом переходе заново искал бы глазами «Далее». Не влезло —
   прокручивается ЛЕВАЯ КОЛОНКА, окно стоит. */
.tvz-cw .tvz-modal__body { flex: none; height: 452px; padding: 0; overflow: hidden; }
.tvz-cw .tvz-modal__foot { height: 60px; padding: 0 20px; align-items: center; gap: 12px; }

/* Лента шагов — ТАБЫ продукта (`tabs()` из core/ui.js), тот же переключатель,
   каким живут админка и карточка клиента (слово владельца 07.08: «давай
   сделаем шаги-табами»). Здесь только ПОСАДКА ленты в окно: своя высота 56 из
   геометрии референса, отбивка по краю окна и общая нижняя линия. Вид самого
   таба — общий, из дизайн-системы, и переопределять его отсюда нельзя: тогда
   у продукта стало бы два разных таба.

   Правило доступности прежнее — вперёд по гейту, назад свободно: недоступный
   таб гаснет (`is-off`), а ПОЧЕМУ стоит словами в подвале, там же, где
   объясняется погашенная кнопка хода. */
.tvz-cw__steps {
  flex: none;
  display: flex;
  align-items: stretch;
  height: 56px;
  padding: 0 20px;
  border-bottom: 1px solid var(--c-bd);
  background: var(--c-head);
}
/* Своя линия ленте не нужна: её роль здесь играет нижняя граница полосы, и
   две линии в один пиксель дали бы двойную черту под шапкой. */
.tvz-cw__steps .tvz-tabs { flex: 1; min-width: 0; border-bottom: none; }
/* Погашенный таб не `disabled` нарочно: наведение обязано работать — на нём
   висит подсказка с причиной. Нажатие при этом ничего не меняет (обработчик
   возвращает ленту на место). */
.tvz-cw__steps .tvz-tab.is-off,
.tvz-cw__steps .tvz-tab.is-off:hover { opacity: .45; color: var(--c-mut); cursor: default; }

/* Тело: слева работа, справа зеркало. Правая колонка фиксирована 320 —
   ширина, при которой дерево «группа → юрлицо → площадка» не переносится. */
.tvz-cw__grid {
  height: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
}
.tvz-cw__main {
  min-width: 0;
  min-height: 452px;
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow: auto;
}
.tvz-cw__side {
  border-left: 1px solid var(--c-bd);
  background: var(--c-head);
  padding: 18px 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: auto;
}

/* Поля. Высота читает вложенность: 38 в основных блоках, 36 в карточке
   юрлица, 34 в строке площадки (референс, раздел 1) — отступами то же самое
   не сказать, ряды поехали бы вбок. */
.tvz-cw__f { display: flex; flex-direction: column; gap: 5px; }
.tvz-cw__f-lbl { display: flex; align-items: baseline; gap: 6px; }
.tvz-cw__f-name { font-size: 12px; font-weight: 600; color: var(--c-tx-2); }
.tvz-cw__f-note { font-size: 11px; color: var(--c-tx-4); }
.tvz-cw__in,
.tvz-cw__sel {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-line-strong);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: 13px;
  outline: none;
}
.tvz-cw__sel { padding: 0 10px; }
.tvz-cw__in:focus,
.tvz-cw__sel:focus,
.tvz-cw__ta:focus {
  border-color: var(--c-ac);
  box-shadow: 0 0 0 3px var(--c-ac-tint);
}
.tvz-cw__in--mono { font-family: var(--font-mono); }
.tvz-cw__in--strong { font-weight: 600; }
.tvz-cw__in--sm { height: 36px; padding: 0 11px; font-size: 12.5px; }
.tvz-cw__in--xs { height: 34px; padding: 0 10px; font-size: 12.5px; }
.tvz-cw__sel--xs { height: 34px; padding: 0 8px; font-size: 12px; }
.tvz-cw__ta {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--c-line-strong);
  border-radius: 8px;
  background: var(--c-surface);
  color: var(--c-tx);
  font: inherit;
  font-size: 13px;
  resize: none;
  outline: none;
}
.tvz-cw__row { display: grid; gap: 14px; align-items: start; }
.tvz-cw__row--inn { grid-template-columns: 220px minmax(0, 1fr); }
.tvz-cw__row--two { grid-template-columns: 1fr 1fr; }
.tvz-cw__row--end { align-items: end; }
.tvz-cw__row--pairs { grid-template-columns: 1fr 1fr; gap: 12px 14px; }
.tvz-cw__block { display: flex; flex-direction: column; gap: 16px; }
.tvz-cw__block--tight { gap: 12px; }
.tvz-cw__sec { display: flex; align-items: baseline; gap: 8px; }
.tvz-cw__sec-t { font-size: 13.5px; font-weight: 700; }
.tvz-cw__sec-hint { font-size: 12px; color: var(--c-tx-4); }

/* «Кто это нам» — сегменты внутри поля, а не два радио: вариантов два и
   оба видны сразу. */
.tvz-cw__seg {
  display: flex;
  padding: 3px;
  gap: 3px;
  border: 1px solid var(--c-line-strong);
  border-radius: 9px;
  background: var(--c-chip);
}
.tvz-cw__seg-b {
  flex: 1;
  height: 32px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--c-tx-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-cw__seg-b.is-on {
  background: var(--c-surface);
  box-shadow: var(--shadow-e1);
  color: var(--c-tx);
}
.tvz-cw__check {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-line-strong);
  border-radius: 8px;
  cursor: pointer;
}
.tvz-cw__check:hover { background: var(--c-hover); }
.tvz-cw__check input { width: 15px; height: 15px; accent-color: var(--c-ac); margin: 0; }
.tvz-cw__check span { font-size: 12.5px; font-weight: 600; color: var(--c-tx-2); }

/* Находка по ИНН — ПРЕДЛОЖЕНИЕ с кнопкой, а не молчаливая правка полей
   (референс, раздел 5; тот же довод, что у `askLegalRequisites`). */
.tvz-cw__found {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--c-ac-bd);
  border-radius: 10px;
  background: var(--c-ac-tint);
}
/* Место находки внутри карточки юрлица на втором шаге: пусто — не занимает
   ничего (`:empty`), иначе карточка держала бы под подсказку постоянный
   зазор и выглядела бы недорисованной. */
.tvz-cw__found-box { margin-top: 10px; }
.tvz-cw__found-box:empty { margin-top: 0; }
.tvz-cw__found .tvz-icon { flex: none; margin-top: 1px; color: var(--c-ac); }
.tvz-cw__found-b { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.tvz-cw__found-t { font-size: 13px; font-weight: 700; color: var(--c-ac-d); }
.tvz-cw__found-m { font-size: 12px; color: var(--c-tx-2); font-family: var(--font-mono); }
.tvz-cw__found-a { font-size: 12px; color: var(--c-tx-2); }
.tvz-cw__found-w { font-size: 12px; font-weight: 700; color: var(--c-warn); }

/* «Подставить» стоит НА тинтовой плашке находки, и `tvz-btn--soft` (тот же
   тинт фоном) на ней растворяется — кнопка перестаёт читаться кнопкой.
   Здесь она наоборот: поверхность внутри тинта, обведённая акцентом. */
.tvz-cw__take {
  background: var(--c-surface);
  border-color: var(--c-ac);
  color: var(--c-ac);
  font-weight: 600;
}
.tvz-cw__take:hover { border-color: var(--c-ac-d); color: var(--c-ac-d); }

/* Третий ход финала — самый тихий из трёх: он не уводит с экрана, а
   возвращает окно в начало. Рамки у него нет намеренно (референс, раздел 8):
   три одинаково обведённые кнопки не сказали бы, какая главная. */
.tvz-cw__more {
  background: transparent;
  border-color: transparent;
  color: var(--c-ac);
  font-weight: 600;
}
.tvz-cw__more:hover { background: var(--c-ac-tint); border-color: transparent; color: var(--c-ac-d); }

/* Карточка юрлица. Площадки лежат ВНУТРИ неё за вертикальной линией —
   принадлежность читается графически, без слов (референс, раздел 4). */
.tvz-cw__le { border: 1px solid var(--c-bd); border-radius: 10px; overflow: hidden; }
.tvz-cw__le-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  background: var(--c-head);
  border-bottom: 1px solid var(--c-bd);
}
.tvz-cw__le-badge {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  background: var(--c-chip);
  color: var(--c-tx-4);
}
.tvz-cw__le-badge.is-main { background: var(--c-ac); color: var(--c-surface); }
.tvz-cw__le-title {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-cw__le-main {
  flex: none;
  height: 26px;
  padding: 0 9px;
  border: 1px solid var(--c-line-strong);
  border-radius: 7px;
  background: transparent;
  color: var(--c-tx-4);
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-cw__le-main.is-main {
  border-color: transparent;
  background: var(--c-ac-tint);
  color: var(--c-ac-d);
  cursor: default;
}
.tvz-cw__x {
  flex: none;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--c-tx-4);
  cursor: pointer;
}
.tvz-cw__x:hover { background: var(--c-errbg); color: var(--c-err); }
.tvz-cw__x--sm { width: 30px; height: 30px; }
.tvz-cw__le-body { padding: 12px; display: flex; flex-direction: column; gap: 11px; }
.tvz-cw__le-req { display: grid; grid-template-columns: minmax(0, 1fr) 132px 132px; gap: 9px; }
.tvz-cw__le-req .tvz-cw__f { gap: 4px; }
.tvz-cw__le-req .tvz-cw__f-name { font-size: 11.5px; }
.tvz-cw__sites {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-left: 11px;
  border-left: 2px solid var(--c-ac-bd);
}
.tvz-cw__sites-t { font-size: 11.5px; font-weight: 600; color: var(--c-tx-2); }
.tvz-cw__sites-t span { font-weight: 500; color: var(--c-tx-4); }
.tvz-cw__site {
  display: grid;
  grid-template-columns: minmax(0, 170px) minmax(0, 1fr) 160px 30px;
  gap: 8px;
  align-items: center;
}
.tvz-cw__add {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 12px;
  border: 1px dashed var(--c-line-strong);
  border-radius: 8px;
  background: transparent;
  color: var(--c-ac);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.tvz-cw__add:hover { background: var(--c-ac-tint); border-color: var(--c-ac-bd); }
.tvz-cw__add--sm { height: 30px; padding: 0 10px; gap: 6px; font-size: 12px; }

/* Роли — ТА ЖЕ доска, что в окне ролей на карточке контакта (П-100), просто
   вставленная в шаг, а не в модалку: своя вёрстка того же вопроса — ровно то
   расхождение, ради которого доску и вынесли в общий сборщик (B-80).

   Здесь только ПОСАДКА доски в колонку шага. Окна вокруг неё нет, поэтому
   тень и предел ширины снимаются, а рамка встаёт та же, что у карточки
   юрлица на соседнем шаге: в одном окне не должно быть двух видов рамки.

   ОДНА ЛЕНТА, а не скролл в скролле (слово владельца 10.08, живьём на
   стенде). Доска приехала из модалки со своей прокруткой списка, и в шаге
   их оказалось две вложенных: колесо над списком крутило список, на пиксель
   в сторону — крутило колонку, а докуда доехал каждый, человек не видел.
   Собственной прокрутки у доски здесь нет: список растёт по содержимому,
   прокручивает его колонка шага (`.tvz-cw__main`, overflow: auto).

   Окно от этого не прыгает — высота тела ЗАДАНА (452px, `.tvz-cw
   .tvz-modal__body`), и растёт не окно, а лента внутри него. Прежний предел
   в 210px берёгся как раз от прыжка, но брал не ту причину: прыжок держит
   заданная высота, а предел только рождал вторую прокрутку. */
.tvz-cw__roles .tvz-rmodal {
  max-width: none;
  border: 1px solid var(--c-bd);
  border-radius: 10px;
  /* Низ доски скруглён под окно (14), а здесь рамка карточки шага (10):
     без подрезки заливка подвала выглядывала бы из-под угла рамки. */
  overflow: hidden;
  box-shadow: none;
  background: transparent;
}
.tvz-cw__roles .tvz-rmodal__list { max-height: none; overflow: visible; }
.tvz-cw__roles .tvz-rmodal__head { padding: 8px 10px; }
.tvz-cw__roles .tvz-rmodal__foot { padding: 8px 12px; }

/* Правая панель «Что создастся» — зеркало, а не второй ввод: ни одного поля,
   незаполненное серым и со словами, чего не хватает (референс, раздел 6). */
.tvz-cw__side-t {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--c-tx-4);
}
.tvz-cw__tree { display: flex; flex-direction: column; gap: 2px; }
.tvz-cw__tree-row { display: flex; align-items: flex-start; gap: 9px; padding: 6px 0; }
.tvz-cw__tree-row.is-in1 { padding-left: 15px; }
.tvz-cw__tree-row.is-in2 { padding-left: 30px; }
.tvz-cw__tree-dot {
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border-radius: 2px;
  background: var(--c-ac);
}
.tvz-cw__tree-row.is-off .tvz-cw__tree-dot { background: var(--c-line-strong); }
.tvz-cw__tree-row.is-site .tvz-cw__tree-dot { background: var(--c-ac-l); }
.tvz-cw__tree-row.is-role .tvz-cw__tree-dot { background: var(--c-ok); }
.tvz-cw__tree-b { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.tvz-cw__tree-lbl {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--c-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-cw__tree-row.is-off .tvz-cw__tree-lbl { font-weight: 500; color: var(--c-tx-4); }
.tvz-cw__tree-sub {
  font-size: 11px;
  color: var(--c-tx-4);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tvz-cw__side-foot {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--c-bd);
  font-size: 11.5px;
  color: var(--c-tx-4);
}

/* Подвал: причина СЛОВАМИ слева, кнопки справа. «Далее» при незакрытом гейте
   не исчезает и не ругается модалкой — гаснет (`.tvz-btn:disabled`), а
   почему — стоит рядом текстом (референс, раздел 2). */
/* Причина отказа — КНОПКА: она уводит к полю, которого не хватает, и это
   должно читаться до нажатия. Подчёркивание пунктиром, а не сплошное: перед
   нами не ссылка на другой экран, а ход внутри этого же окна. Когда отказа
   нет, в строке стоит честное «можно создать сейчас» — нажимать там нечего,
   и вид кнопки снимается (`:empty` не годится, текст есть всегда). */
.tvz-cw__gate {
  font-size: 12px;
  color: var(--c-tx-4);
  margin-right: auto;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  font: inherit;
  font-size: 12px;
  cursor: default;
}
.tvz-cw__gate.is-aiming {
  color: var(--c-tx-2);
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.tvz-cw__gate.is-aiming:hover { color: var(--c-accent); }

/* Обёртка погашенной кнопки: сама кнопка кликов не отдаёт (disabled), а
   спросить «почему нельзя» человек вправе — обёртка ловит нажатие и ведёт
   к полю. Курсор помощи, а не «запрещено»: ход здесь ЕСТЬ, просто не тот,
   которого ждали. */
.tvz-cw__holdbtn { display: inline-flex; cursor: help; }

/* «Смотри сюда» — на полторы секунды, а не пометка ошибки: человек ещё
   ничего не сделал неправильно, он просто не дошёл до этого поля. */
.tvz-cw__f.is-aimed,
.tvz-cw__le.is-aimed {
  border-radius: 10px;
  box-shadow: 0 0 0 2px var(--c-accent);
  transition: box-shadow 0.25s ease;
}

/* Финал: три хода, степпер и подвал уходят — шагов больше нет (раздел 8). */
.tvz-cw__done {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
  padding-top: 8px;
}
.tvz-cw__done-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--c-okbg);
  color: var(--c-ok-d);
  font-size: 12.5px;
  font-weight: 700;
}
.tvz-cw__done-name { font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.tvz-cw__done-sum { font-size: 13px; color: var(--c-tx-2); max-width: 440px; }
.tvz-cw__done-acts { display: flex; gap: 10px; padding-top: 4px; }

/* Узкое окно. Ширина 1040 — контракт (референс, раздел 9), но `.tvz-modal`
   ограничен 92vw, и на экране уже ~1130 колонка панели съела бы работу.
   Тогда зеркало уходит ПОД левую колонку, а не прячется: оно объясняет,
   чего не хватает, и на узком это нужно ровно так же. */
@media (max-width: 1130px) {
  .tvz-cw__grid { grid-template-columns: minmax(0, 1fr); height: auto; }
  /* Заданную высоту тела здесь СНИМАЕМ: в одну колонку шаг вдвое длиннее,
     и 452 обрезали бы его посреди поля. Прокручивается всё тело, а окно
     упирается в потолок `.tvz-modal` (88vh) — прыжок между шагами на узком
     мельче, чем обрезанная форма. */
  .tvz-cw .tvz-modal__body { flex: 1 1 auto; height: auto; overflow: auto; }
  .tvz-cw__main { min-height: 0; overflow: visible; }
  .tvz-cw__side { border-left: none; border-top: 1px solid var(--c-bd); }
  .tvz-cw__le-req { grid-template-columns: minmax(0, 1fr); }
  /* Строка площадки в одну колонку не «переносится» сама: четыре ячейки на
     две колонки уложили бы АДРЕС в клетку крестика шириной 30px. Название и
     адрес занимают строку целиком, регион делит последнюю с удалением. */
  .tvz-cw__site { grid-template-columns: minmax(0, 1fr) 30px; }
  .tvz-cw__site > :nth-child(1),
  .tvz-cw__site > :nth-child(2) { grid-column: 1 / -1; }
  .tvz-cw__row--inn,
  .tvz-cw__row--two,
  .tvz-cw__row--pairs { grid-template-columns: minmax(0, 1fr); }
}

/* ===========================================================================
   ТЕЛЕФОН: то же окно ЛИСТОМ снизу (П-55, B-150).

   Контейнер телефону уже достался правильный: `.tvz-modal` встаёт шторкой в
   общем медиазапросе ветки (docs/UI-MOBILE.md, правило 3 — «модалок по центру
   на телефоне нет»). Ломалась ГЕОМЕТРИЯ ОКНА, написанная выше под стол:
   шапка ростом ровно 60 съедала отступ под «ручку» листа, и полоска
   печаталась поверх слова «Новый клиент»; подвал ростом 60 держал в ОДИН ряд
   три кнопки и причину словами — на 390 точках причина уезжала под форму;
   ходы финала стояли рядом, и третий («Ещё клиента») висел за правым краем.

   Приём тот же, каким П-59 переписала окно ролей: второй формы «под телефон»
   не заводится, переписывается ТОЛЬКО то, как разложены уже собранные части.
   Развилки в JS здесь нет — у раскладок разный вид, а не разный состав.

   Блок стоит ЗДЕСЬ, после базовых правил окна и после узкой раскладки, а не
   в общем медиазапросе ветки — по доводу B-113: при равной специфичности
   побеждает написанное НИЖЕ по файлу, а общий запрос стоит выше `.tvz-cw`.
   Положенный туда, он повторил бы судьбу прежних 44px формы внесения —
   правило написано и не действует ни одного дня.

   Отбор — признак всей ветки (`isPhoneView`, people.js): узкое окно И грубый
   указатель. За столом, в том числе в окне 375 точек, окно остаётся окном.

   Меры — те же, что у формы внесения на телефоне (хендофф 5e): поля 46,
   касание не меньше 44, кнопки подвала 48. Своих чисел здесь не заводится.
   =========================================================================== */

@media (max-width: 900px) and (pointer: coarse) {
  /* Лист занимает экран, и рост ЗАДАН, а не выведен из шага. Это то же
     несущее, ради которого за столом задана высота тела (референс, раздел 1):
     лист, меняющий рост на каждом шаге, заставляет искать «Создать клиента»
     заново — а на телефоне кнопка при этом ещё и переезжает из-под большого
     пальца. Прокручивается тело, лист стоит.
     94% — потолок шторки дизайн-системы; полоска чужого экрана сверху
     говорит, что лист поднят НАД чем-то и закрывается вниз. */
  .tvz-cw {
    height: 94%;
  }

  /* Рост шапки — по содержимому: заданные 60 точек резали подзаголовок,
     который на 390 точках занимает две строки. Место под «ручку» шапка
     больше не выпрашивает — его держит сам лист (см. врезку выше). */
  .tvz-cw .tvz-modal__head {
    height: auto;
    padding: 12px 14px;
  }

  /* Лента шагов уезжает вбок САМА — прокруткой внутри своей полосы (`.tvz-tabs`
     ниже 900 точек уже так и живёт, D-89). Резать подписи до «1 · 2 · 3» или
     жать буквы здесь нельзя: подпись шага — единственное место, где сказано,
     О ЧЁМ этот шаг, а номер об этом молчит. Полосе остаётся только посадка:
     отбивка ужимается до 10, чтобы соседний шаг было ВИДНО краем — обрезанное
     слово и есть приглашение потянуть.
     Вид самого таба не трогаем (иначе у продукта стало бы два разных таба):
     активный шаг подводит к краю JS, а не CSS (`paintSteps`). */
  .tvz-cw__steps {
    padding: 0 10px;
  }

  /* Рамка тела — по мере телефона (12/14), а не 20/22 стола. */
  .tvz-cw__main {
    padding: 14px;
    gap: 14px;
  }

  /* Поля 46 и текст 14: в поле 38 палец «на ходу, в каске» не попадает
     (та же мера, что у формы внесения на телефоне). */
  .tvz-cw__in,
  .tvz-cw__sel,
  .tvz-cw__in--sm,
  .tvz-cw__in--xs,
  .tvz-cw__sel--xs {
    height: 46px;
    font-size: 14px;
  }

  .tvz-cw__ta {
    min-height: 46px;
    font-size: 14px;
  }

  /* Цели пальца — 44 (канон ветки, правило 5): сегменты «Клиент · Дилер»,
     «Ещё юрлицо» и «Площадка», «Сделать основным», «Подставить» из находки
     по ИНН. Ролей в этом списке больше нет: их строки — доска ролей (П-100),
     и палец им меряет та же ветка, что и шторке ролей на карточке. */
  .tvz-cw__seg-b,
  .tvz-cw__add,
  .tvz-cw__add--sm,
  .tvz-cw__le-main,
  .tvz-cw__take {
    height: 44px;
    font-size: 13.5px;
  }

  .tvz-cw__check {
    height: 46px;
  }

  /* Кнопки-иконки — 40×40 тем же правилом: у безымянного крестика цель
     меньше, чем у кнопки со словом, но всё ещё палец, а не курсор. */
  .tvz-cw__x,
  .tvz-cw__x--sm {
    width: 40px;
    height: 40px;
  }

  /* Строка площадки: колонка под крестик — те же 40. */
  .tvz-cw__site {
    grid-template-columns: minmax(0, 1fr) 40px;
  }

  /* Подвал — панель главного действия (канон ветки, правило 13): причина
     СЛОВАМИ занимает строку целиком, ходы стоят под ней. В одном ряду с
     кнопками причине оставалось три буквы ширины, и она печаталась столбиком
     поверх формы. Рост подвала теперь по содержимому, а не 60 стола. */
  .tvz-cw .tvz-modal__foot {
    height: auto;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  }

  .tvz-cw .tvz-modal__foot .tvz-cw__gate {
    flex: 1 0 100%;
    margin-right: 0;
  }

  .tvz-cw .tvz-modal__foot .tvz-btn {
    height: 48px;
    padding: 0 14px;
    border-radius: 13px;
    font-size: 14px;
  }

  /* «Создать клиента» забирает остаток строки: главное действие шире и
     правее, под большой палец (тот же приём, что у «Сохранить» в шторке
     ролей). Погашенной она остаётся на месте — исчезнувшая означала бы,
     что хода нет вовсе. */
  .tvz-cw .tvz-modal__foot .tvz-btn--primary {
    flex: 1;
  }

  /* Зеркало «Что создастся» на телефоне идёт ПОСЛЕ шагов и ширины не отнимает
     (колонку сняла узкая раскладка выше). Прятать его за раскрывашку было
     нечестно: панель говорит, чего у клиента нет («Юрлиц нет — договор потом
     не собрать»), и спрятанное предупреждение не предупреждает. Дойти до
     кнопки мимо него не надо — «Создать клиента» закреплена в подвале. */
  .tvz-cw__side {
    padding: 14px;
    gap: 10px;
  }

  /* Ходы финала — столбиком во всю ширину: в ряд третий («Ещё клиента») висел
     за правым краем экрана, то есть его на телефоне не было вовсе. */
  .tvz-cw__done-acts {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }

  .tvz-cw__done-acts .tvz-btn {
    height: 48px;
    border-radius: 13px;
    font-size: 14px;
  }
}
