/* Компоненты интерфейса Linetix. Собраны вручную на токенах из tokens.css.
   Сборщик стилей не подключается намеренно: набор компонентов небольшой и
   заранее известен, а лишний шаг сборки усложнил бы выкладку.

   Плотность и размеры взяты из docs/14-DESIGN-SYSTEM.md: строка таблицы 38px,
   сайдбар 200px, главная кнопка графитовая, а не цветная. */

/* ── Каркас страницы ─────────────────────────────────────────────── */

.layout { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sidebar__brand {
  padding: 4px 10px 16px;
  line-height: 0;
}

/* ── Логотип ─────────────────────────────────────────────────────────
   Логотип лежит парой файлов: у светлой и тёмной темы разные цвета знака
   и слова. Переключение делает CSS, чтобы не тащить ради этого скрипт. */

.logo { display: block; height: auto; }
.logo--dark { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo--light { display: none; }
  :root:not([data-theme="light"]) .logo--dark { display: block; }
}
:root[data-theme="dark"] .logo--light { display: none; }
:root[data-theme="dark"] .logo--dark { display: block; }

/* Знак в шапке телефона. На десктопе его место занимает сайдбар. */
.topbar__mark { display: none; line-height: 0; flex: none; }

.sidebar__link {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: var(--radius);
  color: var(--ink-2);
  text-decoration: none;
}
.sidebar__link:hover { background: var(--surface-2); color: var(--ink); }
.sidebar__link--active { background: var(--brand-soft); color: var(--brand); font-weight: 500; }
.sidebar__link--soon { color: var(--muted); cursor: default; }
.sidebar__link--soon:hover { background: transparent; color: var(--muted); }


.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: 52px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
  background: var(--ground);
}

.content { padding: 22px 20px 60px; max-width: 1180px; }

/* ── Переключатель локации ───────────────────────────────────────── */
/* На видном месте в шапке, не в подменю — критерий 6.
   Точка серая, а не цветная: локация опознаётся текстом. */

.location { display: flex; align-items: center; gap: 8px; }
.location__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted); flex: none;
}
.location__label { color: var(--muted); font-size: var(--text-small); }
.location__form { display: inline; }
.location__select {
  border: 1px solid var(--line-strong);
  background: var(--ground);
  color: var(--ink);
  border-radius: var(--radius);
  padding: 5px 8px;
  font: inherit;
  font-size: var(--text-body);
}

/* ── Заголовки ───────────────────────────────────────────────────── */

.page-title { font-size: var(--text-title); font-weight: 600; margin: 0 0 3px; }
.page-subtitle { font-size: var(--text-subtitle); color: var(--muted); margin: 0 0 22px; }
.page-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }

/* ── Кнопки ──────────────────────────────────────────────────────── */
/* Главная кнопка тёмно-графитовая. Синяя была бы лишним источником цвета
   там, где цвет уже занят пользовательскими статусами. */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 34px; padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--ground);
  color: var(--ink);
  font: inherit; font-size: var(--text-body);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover { background: var(--surface); }
.btn--primary { background: var(--ink); border-color: var(--ink); color: var(--ground); }
.btn--primary:hover { opacity: 0.9; background: var(--ink); }
.btn--danger { color: var(--status-red-fg); border-color: var(--line-strong); }
.btn--small { height: 28px; padding: 0 10px; font-size: var(--text-subtitle); }
.btn--link { border: 0; background: none; color: var(--brand); padding: 0; height: auto; }

/* Выход — обычный пункт меню, а не акцент. Акцент означает «здесь важное»,
   а выход из системы к важному не относится. */
.sidebar__link.btn--link { color: var(--ink-2); font: inherit; }
.sidebar__link.btn--link:hover { color: var(--ink); }

/* ── Карточки и панели ───────────────────────────────────────────── */

/* Островок: белый на сером фоне страницы, с едва заметной тенью. */
.card {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--ground);
  padding: 18px;
  box-shadow: var(--island-shadow);
}
.card + .card { margin-top: 14px; }
.card__title { font-weight: 600; margin: 0 0 2px; }
.card__hint { color: var(--muted); font-size: var(--text-subtitle); margin: 0 0 14px; }

/* ── Формы ───────────────────────────────────────────────────────── */

.field { margin-bottom: 14px; max-width: 460px; }
.field__label {
  display: block;
  font-size: var(--text-subtitle);
  color: var(--ink-2);
  margin-bottom: 4px;
}
.field__hint { font-size: var(--text-small); color: var(--muted); margin-top: 4px; }
.field__error { font-size: var(--text-small); color: var(--status-red-fg); margin-top: 4px; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="url"], input[type="tel"], input[type="search"], input[type="date"],
input[type="datetime-local"], input[type="time"], input[type="file"],
select, textarea {
  width: 100%;
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-body);
}
textarea { height: auto; padding: 8px 10px; }
input[type="checkbox"] { accent-color: var(--brand); width: 15px; height: 15px; }
/* Django помечает поле с ошибкой `aria-invalid="true"` — рамка тем же
   красным токеном, что и текст ошибки, и тёмная тема получается сама. Стоит
   после общего правила полей: та же сила селектора, побеждает порядок. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--status-red-fg);
}

.form-actions { display: flex; gap: 10px; align-items: center; margin-top: 18px; }
.checkbox-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.checkbox-row label { font-size: var(--text-body); }

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

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { width: 100%; border-collapse: collapse; }
/* Шапка таблиц — «М'ята» (выбор заказчика 05.10, вариант 2): мятная полоса,
   обычный регистр вместо капители, текст полужирный в цвет «Ремонтів».
   Правило одно на все списки — каждая таблица с классом .table получает её
   сама; цвета — токены --thead-* (tokens.css, три блока). */
.table th {
  text-align: left;
  font-size: 12.5px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--thead-fg);
  font-weight: 600;
  background: var(--thead-bg);
  padding: 8px var(--cell-pad-x);
  border-bottom: 1px solid var(--thead-line);
  white-space: nowrap;
}
.table td {
  padding: var(--cell-pad-y) var(--cell-pad-x);
  border-bottom: 1px solid var(--line);
  height: var(--row-h);
  vertical-align: middle;
}
.table tr:hover td { background: var(--surface); }
.table__actions { text-align: right; white-space: nowrap; }

/* Две величины в одной ячейке: данных вдвое больше, таблица не растёт вширь. */
.cell-main { display: block; }
.cell-sub { display: block; font-size: var(--text-small); color: var(--muted); }

/* ── Чипы и метки ────────────────────────────────────────────────── */

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 10px;
  border-radius: var(--radius-chip);
  font-size: var(--text-small);
  background: var(--status-gray-bg);
  color: var(--status-gray-fg);
  white-space: nowrap;
}
.chip--ok { background: var(--status-green-bg); color: var(--status-green-fg); }
.chip--warn { background: var(--status-amber-bg); color: var(--status-amber-fg); }
.chip--off { background: var(--status-red-bg); color: var(--status-red-fg); }
.chip--soon { background: var(--surface-2); color: var(--muted); }

/* ── Сообщения ───────────────────────────────────────────────────── */

.messages { margin-bottom: 16px; display: flex; flex-direction: column; gap: 8px; }
.messages:not(:has(.message)) { display: none; }
.message {
  padding: 9px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: var(--text-body);
}
.message--success { background: var(--status-green-bg); color: var(--status-green-fg); border-color: transparent; }
.message--error { background: var(--status-red-bg); color: var(--status-red-fg); border-color: transparent; }

/* ── Список настроек ─────────────────────────────────────────────── */
/* Каждый пункт с подписью, объясняющей, что он меняет — критерий 14. */

.settings-list { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.settings-item {
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  text-decoration: none;
  color: inherit;
  background: var(--ground);
}
.settings-item:hover { border-color: var(--line-strong); background: var(--surface); }
.settings-item--soon { background: var(--surface); cursor: default; }
.settings-item--soon:hover { border-color: var(--line); }
.settings-item__title { display: flex; justify-content: space-between; gap: 10px; align-items: center; font-weight: 500; }
.settings-item__hint { color: var(--muted); font-size: var(--text-subtitle); margin-top: 3px; }

/* ── Внутренние страницы настроек ────────────────────────────────── */
/* Слева список разделов, справа страница. Из филиалов в сотрудников —
   один щелчок, а не два через общий список. Ширина колонки из макета. */

.settings-layout { display: grid; grid-template-columns: 212px 1fr; gap: 22px; align-items: start; }
.settings-main { min-width: 0; }
.settings-nav { display: flex; flex-direction: column; gap: 1px; }
.settings-nav__link {
  display: block;
  padding: 8px 11px;
  border-radius: var(--radius);
  color: var(--ink-2);
  text-decoration: none;
}
.settings-nav__link:hover { background: var(--surface); color: var(--ink); }
.settings-nav__link--active { background: var(--surface); color: var(--ink); font-weight: 500; }
.settings-nav__link--soon { color: var(--muted); cursor: default; }
.settings-nav__link--soon:hover { background: transparent; color: var(--muted); }

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

.role-sum {
  display: flex; gap: 24px; align-items: center;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  margin-bottom: 14px;
}
.role-sum b { font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.role-sum span { font-size: var(--text-small); color: var(--muted); display: block; }

.perm-group {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  margin-bottom: 10px;
  overflow: hidden;
}
.perm-group__head {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.perm-group__title {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--muted); font-weight: 500;
}
.perm-group__count {
  margin-left: auto;
  font-size: var(--text-small);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.perm-grid { padding: 11px 14px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px 18px; }

/* Галочки выравниваются по верху: названия вроде «Керування співробітниками»
   в две строки неизбежны, и при выравнивании по центру квадратик уезжает
   в середину второй строки. */
.perm-item { display: flex; align-items: flex-start; gap: 8px; line-height: 1.3; }
.perm-item input[type="checkbox"] { margin: 1px 0 0; flex: none; }
.perm-item label { color: var(--ink-2); }

/* Переключатель всей группы. Три состояния обязаны различаться на глаз,
   а не по подписи: выключено — серая дорожка, включено всё — заливка
   акцентом, включено частично — акцентная точка на светлой дорожке.
   Под ним настоящий checkbox: щелчок мышью, пробел с клавиатуры и кольцо
   фокуса достаются бесплатно, а рисовать это на div пришлось бы руками. */
.sw-wrap { display: inline-flex; align-items: center; cursor: pointer; }
.sw-input { position: absolute; opacity: 0; width: 0; height: 0; }
.sw {
  width: 30px; height: 17px; border-radius: var(--radius-chip);
  background: var(--line-strong); flex: none;
  display: inline-flex; align-items: center; padding: 2px;
  transition: background 0.12s ease-out;
}
.sw i { width: 13px; height: 13px; border-radius: 50%; background: #fff; display: block; }
.sw-input:checked + .sw { background: var(--brand); justify-content: flex-end; }
.sw-input:indeterminate + .sw {
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px var(--brand);
  justify-content: center;
}
.sw-input:indeterminate + .sw i { width: 9px; height: 9px; background: var(--brand); }
.sw-input:focus-visible + .sw { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ── Экраны входа ────────────────────────────────────────────────── */
/* Карточка на подложке, а не форма на белом листе. Это единственный экран,
   который человек видит до того, как войдёт, и по нему он судит о продукте
   целиком. Размеры из макета: карточка 400 точек, скругление 14.
   Знак, заголовок и подпись по центру, поля и кнопка — слева: центрировать
   поля значит заставить глаз искать начало каждой строки заново. */

.auth {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 44px 20px;
  background: var(--surface);
}
.auth__card {
  width: 400px;
  max-width: 100%;
  background: var(--ground);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 28px 30px 26px;
}
.auth__card--wide { width: 560px; }

.auth__logo { margin: 0 0 20px; line-height: 0; display: flex; justify-content: center; }
.auth__title { font-size: var(--text-title); font-weight: 600; margin: 0 0 4px; text-align: center; }
.auth__hint {
  color: var(--muted);
  font-size: var(--text-subtitle);
  margin: 0 0 20px;
  line-height: 1.4;
  text-align: center;
}
/* Строка «запомнить меня» и «забыли пароль» — по краям одной строки:
   это два разных действия, и разводить их по вертикали незачем. */
.auth__row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; font-size: var(--text-subtitle); color: var(--muted);
  margin-bottom: 16px;
}
.auth__row .checkbox-row { margin: 0; }
.auth__foot {
  margin: 18px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: var(--text-subtitle);
  color: var(--muted);
  text-align: center;
}
/* В карточке поле занимает её целиком: ограничение в 460 точек придумано
   для широких страниц настроек и здесь только сузило бы форму. */
.auth .field { max-width: none; }
.auth .form-actions { margin-top: 0; }

/* Кружок с галочкой на страницах «проверьте почту» и «ссылка не действует».
   Заливка мягкая: это уведомление, а не тревога. */
.auth__mark {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand);
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; margin: 0 auto 16px;
}
.auth__mark--warn { background: var(--status-amber-bg); color: var(--status-amber-fg); }

.btn--wide { width: 100%; height: 38px; }

a { color: var(--brand); }

.empty { color: var(--muted); padding: 22px 0; }
.muted { color: var(--muted); }
.small { font-size: var(--text-subtitle); }

/* ── Выдвижное меню на телефоне ──────────────────────────────────── */

.burger {
  display: none;
  width: 34px; height: 34px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--ground);
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  flex: none;
}
.burger svg { display: block; }

.scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 40;
  border: 0;
  padding: 0;
}

/* ── Телефон ─────────────────────────────────────────────────────── */
/* Клиент просил больше информации на одном экране: воздух ужат,
   карточки ниже, отступы меньше. */

@media (max-width: 760px) {
  .burger { display: inline-flex; }
  .topbar__mark { display: block; }

  .sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    z-index: 50;
    width: 260px;
    flex-basis: 260px;
    transform: translateX(-100%);
    transition: transform 0.18s ease-out;
    overflow-y: auto;
  }
  .sidebar--open { transform: translateX(0); }
  .sidebar--open ~ .scrim,
  .scrim--visible { display: block; }

  .topbar { padding: 0 12px; gap: 10px; }
  .content { padding: 14px 12px 40px; }
  body { font-size: 15px; }

  .settings-list { grid-template-columns: 1fr; gap: 6px; }
  .settings-item { padding: 9px 12px; border-radius: var(--radius); }
  .settings-item__hint { font-size: 12px; margin-top: 1px; }

  .page-title { margin-bottom: 1px; }
  .page-subtitle { margin-bottom: 14px; }
  .card { padding: 14px; }
  .field { margin-bottom: 11px; }

  /* Название компании в шапке съедает место у переключателя локации */
  .topbar__company { display: none; }
  /* Выход остаётся иконкой: в шапке телефона слово не помещается. */
  .topbar__out-t { display: none; }
  .topbar__out-btn { padding: 0 9px; }
  .location__label { display: none; }

  /* Карточка входа на телефоне прижимается к верху: по центру она уезжает
     под клавиатуру, как только человек ставит курсор в поле. */
  .auth { padding: 20px 14px 40px; align-items: flex-start; }
  .auth__card { padding: 22px 20px; border-radius: 12px; }

  /* Права в три колонки на телефоне не помещаются — по одной в строку. */
  .perm-grid { grid-template-columns: 1fr; gap: 9px; }
}

/* Боковой список настроек встаёт полосой над страницей раньше, чем включается
   телефонная раскладка. Порог здесь не 760: на планшете колонка в 212 точек
   ещё помещается, но забирает их у таблиц, и те начинают ехать вбок. Список
   разделов ужать можно, таблицу — уже нет.
   Было 1000 — подбиралось под таблицу сотрудников. Таблица статусов ремонтов
   шире: семь колонок без переносов просят 700 точек, а на 1024 странице
   настроек остаётся 580, и она уезжала вбок внутри обёртки. Замерено 09.09
   тем же способом, каким нашёлся дефект списка заказов. */
@media (max-width: 1100px) {
  .settings-layout { grid-template-columns: 1fr; gap: 12px; }
  .settings-nav {
    flex-direction: row; flex-wrap: nowrap;
    overflow-x: auto; gap: 4px;
    padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
  }
  .settings-nav__link { white-space: nowrap; border: 1px solid var(--line); }
}

/* Промежуточная ширина: планшет и узкое окно на компьютере. Три колонки
   прав здесь уже режут подписи, две — ещё читаются. */
@media (min-width: 761px) and (max-width: 1100px) {
  .perm-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ─────────────────────────────────────────────────────────── этап 2: клиенты
   Счётчики, полоса фильтров, окно быстрой заявки и статусные метки. Классы
   продолжают словарь этапа 1 (.table, .chip, .card), а не заводят второй:
   макетные страницы в docs/brand живут со своим набором имён, но это
   презентация, а не продукт. */

.counters {
  display: grid; gap: 10px; margin: 0 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.cnt {
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--ground); padding: 11px 13px;
}
.cnt b {
  display: block; font-size: 21px; font-weight: 600; line-height: 1.15;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.cnt span { display: block; font-size: var(--text-small); color: var(--muted); margin-top: 2px; }
/* Просроченный звонок — единственный счётчик, который имеет право кричать. */
.cnt b.cnt--warn { color: var(--status-red-fg); }

.filters {
  display: flex; align-items: flex-end; gap: 10px;
  margin: 0 0 14px; flex-wrap: wrap;
}
.filters__group {
  display: flex; align-items: flex-end; gap: 10px;
  margin-left: auto; flex-wrap: wrap;
}
.filters .field { margin: 0; max-width: none; }
.filters select, .filters input { height: 32px; }
.filters .field__label { font-size: var(--text-small); margin-bottom: 3px; }

/* ─────────────────────────────────────────────────────── статусная метка
   Цвет статуса задаёт директор, поэтому набор классов соответствует набору
   значений в справочнике, а не придуман здесь. */
.pill {
  display: inline-block; padding: 2px 9px; border-radius: var(--radius-chip);
  font-size: var(--text-small); white-space: nowrap;
  background: var(--status-gray-bg); color: var(--status-gray-fg);
}
.pill--green  { background: var(--status-green-bg);  color: var(--status-green-fg); }
.pill--amber  { background: var(--status-amber-bg);  color: var(--status-amber-fg); }
.pill--blue   { background: var(--status-blue-bg);   color: var(--status-blue-fg); }
.pill--violet { background: var(--status-violet-bg); color: var(--status-violet-fg); }
.pill--red    { background: var(--status-red-bg);    color: var(--status-red-fg); }
/* Операция продажи в журнале кассы (этап 8) — цветом раздела «Продажі». */
.pill--sale   { background: var(--sec-sales-bg);    color: var(--sec-sales-fg); }
.pill--teal   { background: var(--brand-soft);       color: var(--brand); }
.pill--slate  { background: var(--status-gray-bg);   color: var(--status-gray-fg); }
.pill--wine   { background: var(--status-wine-bg);   color: var(--status-wine-fg); }
.pill--rose   { background: var(--status-rose-bg);   color: var(--status-rose-fg); }
/* «Готово» в заказах и «Здав у ремонт» в заявках. Заливка с 07.09 нежная,
   по просьбе заказчика; выделяется жирностью, а не громкостью цвета. */
.pill--green-strong {
  background: var(--status-green-strong-bg); color: var(--status-green-strong-fg);
  font-weight: 600;
}

.overdue { color: var(--status-red-fg); }

/* ───────────────────────────────────────────────────────────── окно поверх
   Быстрая заявка открывается над списком: оператор не уходит с экрана, с
   которого работает. Это диалог браузера, а не свой div с обработчиками —
   Escape, фокус и подложка достаются даром. */
.modal {
  border: 0; padding: 0; background: transparent;
  width: min(560px, calc(100vw - 24px));
}
.modal::backdrop { background: rgba(10, 20, 20, 0.42); }
.modal__card {
  background: var(--ground); border-radius: var(--radius-card);
  border: 1px solid var(--line); padding: 18px 20px 20px;
  max-height: calc(100vh - 48px); overflow-y: auto;
}
.modal__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; margin-bottom: 14px;
}
.modal__title { font-size: 16px; font-weight: 600; margin: 0; }
.modal__close {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 20px; line-height: 1; padding: 0 2px;
}
.modal__close:hover { color: var(--ink); }
.modal .field { max-width: none; margin-bottom: 11px; }

/* Две колонки в форме заявки: она должна закрываться за один экран. */
.form-row { display: grid; gap: 0 12px; grid-template-columns: 1fr 1fr; }
@media (max-width: 560px) { .form-row { grid-template-columns: 1fr; } }

/* ──────────────────────────────────────────── подсказка под полем телефона
   Живёт под полем и меняется во время набора. Три состояния, потому что
   «ничего не нашли» и «ещё не искали» — разные вещи. */
.lookup { font-size: var(--text-small); margin-top: 4px; min-height: 16px; }
.lookup--found { color: var(--brand); }
.lookup--new { color: var(--muted); }
.lookup a { color: inherit; }

/* ───────────────────────────────────────────────────── карточка клиента
   Вся история человека на одном экране: ремонты, заявки, устройства, деньги. */
.head-card {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.head-card__sub { color: var(--muted); font-size: var(--text-subtitle); margin: 3px 0 0; }
.head-card__actions { display: flex; gap: 8px; flex-wrap: wrap; }

.cols { display: grid; grid-template-columns: 1fr 320px; gap: 14px; align-items: start; }
@media (max-width: 899px) { .cols { grid-template-columns: 1fr; } }

.phone-line {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line);
}
.phone-line:last-child { border-bottom: 0; }
.phone-line__num { font-variant-numeric: tabular-nums; }

/* ═════════════════════════════════════════════════════════ этап 3: ремонты
   Имена компонентов продуктовые. Макеты в docs/brand живут со своим набором
   имён, но это презентация, а не продукт: оттуда берутся раскладка, порядок
   блоков и метрики, а классы остаются здешними. */

.ta-r { text-align: right; }

/* ───────────────────────────────────────────────────────── список заказов */

/* Колонки фиксированной ширины и обрезка многоточием. Без этого длинная
   модель или длинная фамилия переносятся на вторую строку, ячейка вырастает,
   и строки списка получаются разной высоты. Список разной высоты перестаёт
   читаться пачкой: глаз теряет вертикаль и начинает читать каждую строку
   отдельно. Правило дизайн-системы — обрезать, а не переносить. */
.orders-table table { table-layout: fixed; }
.orders-table td { max-width: 0; }
.orders-table .cell-main,
.orders-table .cell-sub {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Вторая строка ячейки фиксирована по высоте, а чип срочности вписан в неё.
   Без этого строка со срочным заказом на одну точку выше остальных: мелочь,
   но именно из таких мелочей список и получается неровным. */
.orders-table .cell-sub { height: 16px; line-height: 16px; }
.orders-table .cell-sub .chip--urgent { height: 16px; line-height: 14px; padding: 0 8px; font-size: 10px; }

/* Срочный заказ подсвечен в общем списке. Подсветка тонкая: заливать строку
   целиком значит спорить со статусом, а статус здесь главный. */
.orders-table tr.row--urgent td:first-child { box-shadow: inset 3px 0 0 var(--urgent-stripe); }

/* Единственное место, где красный в таблице что-то значит: сорванный срок. */
.v1--late { color: var(--status-red-fg); }

/* «Взяти замовлення» прямо в строке: менеджер становится назначенным, не
   открывая заказ. Кнопка во всю ширину ячейки, чтобы попасть по ней мышью
   с первого раза. */
/* Ровно та же высота, что у выпадающего списка статуса в соседней ячейке:
   иначе строка со взятым заказом и строка с невзятым разной высоты. */
.take-row {
  display: block; width: 100%; height: 34px; padding: 0 8px;
  background: var(--ink); color: var(--ground); border: 0;
  border-radius: var(--radius); font: inherit; font-size: 12px; cursor: pointer;
}
.take-row:hover { opacity: .9; }

/* На телефоне счётчики поджимаются в одну строку. Четыре карточки в две
   полосы занимали 250 точек, и список начинался за первым экраном — а в
   принятом макете плитки видны сразу под шапкой. Класс свой, чтобы не
   трогать счётчики на уже принятых экранах заявок и клиентов. */
@media (max-width: 760px) {
  /* Одной строкой на всех списках — видео 10 выровняло заявки и клиентов
     по заказам. */
  .counters {
    display: flex; gap: 8px; overflow-x: auto; padding-bottom: 2px;
  }
  .counters .cnt {
    flex: 0 0 auto; padding: 7px 11px; border-radius: var(--radius);
    display: flex; align-items: baseline; gap: 6px;
  }
  .counters .cnt b { font-size: 15px; }
  .counters .cnt span { font-size: 11.5px; }
  /* Колонок на телефоне нет — там плитки, и настраивать нечего. */
  .cols-setup { display: none; }
}

/* Панель настройки колонок раскрывается под фильтрами и не толкает список
   вниз, пока закрыта. */
.cols-setup { margin-bottom: 12px; }
.cols-setup summary { display: inline-flex; cursor: pointer; list-style: none; }
.cols-setup summary::-webkit-details-marker { display: none; }
.cols-setup .card { margin-top: 8px; }

/* Перелистыватель: слева «Назад», номера страниц и «Далі», справа «Показувати
   по» (видео заказчика 21.09, 5:46 — «первая страница, 2, 3, 4… от 30 с
   возможностью выбирать»). На телефоне строка переносится, номера остаются
   пальцевыми: 30 точек в высоту. */
.pager {
  display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap;
  justify-content: space-between;
}
.pager__pages { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pager__n {
  min-width: 30px; height: 30px; padding: 0 7px; border-radius: var(--radius);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-variant-numeric: tabular-nums; color: var(--ink-2);
  text-decoration: none; border: 1px solid transparent;
}
a.pager__n:hover { background: var(--surface); border-color: var(--line); color: var(--ink); }
.pager__n--on { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.pager__gap { color: var(--muted); padding: 0 2px; }
.pager__per { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.pager__per select { height: 30px; min-height: 0; padding: 0 8px; width: auto; background: var(--ground); }
@media (max-width: 760px) {
  .pager { gap: 8px; }
  .pager__per { margin-left: 0; width: 100%; justify-content: flex-end; }
}

/* Фильтров в заказах шесть плюс поиск — вдвое больше, чем в макете, потому
   что столько их в оплаченном составе. Группа занимает остаток строки и
   переносится внутри себя: иначе кнопка «Створити замовлення» оставалась бы
   одна на своей строке, и это читалось бы как незавершённая вёрстка. */
.filters--orders .filters__group { flex: 1 1 auto; min-width: 0; }

/* Переключатель фильтров: с 07.09 и на столе — шесть списков спрятаны под
   кнопку «Фільтри» справа от поиска (правка заказчика по ПК-версии). */
/* Счётчик уведомлений в шапке. Единственное место в системе, где число
   залито цветом: это не украшение, а «тебя позвали». */
.bell {
  display: inline-flex; align-items: center; gap: 6px; margin-left: 14px;
  color: var(--ink-2); text-decoration: none; font-size: 12.5px; white-space: nowrap;
}
.bell:hover { color: var(--ink); }
.bell__n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 19px; height: 19px; padding: 0 5px; border-radius: 100px;
  background: var(--status-red-bg); color: var(--status-red-fg);
  font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
@media (max-width: 760px) { .bell span:not(.bell__n) { display: none; } }

.filters__toggle { position: absolute; opacity: 0; pointer-events: none; }
.filters__label { display: none; }

/* ─────────────────────────────────────────────────── плитка на телефоне
   Строка таблицы на телефоне превращается в карточку. Состав продиктован
   заказчиком: три пары — номер и срочность, модель и статус, ФИО с телефоном
   и стоимость. Правый край выровнен в одну вертикаль, чтобы глаз находил цену. */
.tiles { display: none; flex-direction: column; gap: 7px; }
.tile {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 10px;
  align-items: center; padding: 9px 11px; border: 1px solid var(--line);
  border-radius: var(--radius-card); color: inherit; text-decoration: none;
}
/* Длинное имя обрезается, а не переносится: один перенос ломает ритм всего
   списка, и плитки перестают читаться пачкой. */
.t-l { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-r { justify-self: end; white-space: nowrap; }
.t-dev { font-size: 15px; font-weight: 550; line-height: 1.25; }
.t-cl { font-size: 12px; color: var(--muted); }
.t-sum { font-size: 14px; font-weight: 600; }
.t-wide { grid-column: 1 / -1; }
.t-due { display: inline-flex; align-items: center; gap: 4px;
         font-size: 11.5px; color: var(--muted); }

/* ───────────────────────────────────────────────────────── карточка заказа */

.kv { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
.kv--wide {
  grid-template-columns: 1fr; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line);
}
@media (max-width: 640px) { .kv { grid-template-columns: 1fr; } }

.chips { display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; }
.tag {
  display: inline-flex; align-items: center; height: 21px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-chip);
  font-size: 11.5px; color: var(--ink-2);
}

/* Участники и готовность одной полосой: заказчик просил видеть их вместе. */
.crew { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 18px; }
.crew__r { padding-left: 18px; border-left: 1px solid var(--line); }
@media (max-width: 760px) {
  .crew { grid-template-columns: 1fr; }
  .crew__r {
    padding-left: 0; border-left: 0;
    border-top: 1px solid var(--line); padding-top: 12px;
  }
}
.who-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--line);
}
.who-row:last-child { border-bottom: 0; }
.who-row form { margin: 0; }
.who-row select { max-width: 220px; }
.who { display: inline-flex; align-items: center; gap: 7px; }
/* Инициалы вместо аватарки: рисованных человечков в этой системе нет.
   Кружок, а не квадрат — «если легко, делаем» из видео 10. */
.ini {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  background: var(--surface-2); color: var(--ink-2);
  font-size: 10.5px; font-weight: 600; letter-spacing: .02em;
}
.ini--lg { width: 40px; height: 40px; font-size: 14px; background: var(--sec-bg); color: var(--sec-fg); }
.ini--sys { background: var(--brand-soft); color: var(--brand); font-size: 8.5px; }

.date-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
.date-row input { max-width: 190px; }
.warr-note { margin: 6px 0 0; }
.transfer, .notify { margin-top: 10px; }
.transfer summary, .notify summary { display: inline-flex; cursor: pointer; list-style: none; }
.transfer summary::-webkit-details-marker,
.notify summary::-webkit-details-marker { display: none; }

/* Гарантийная плашка. Появляется только после выдачи — до неё гарантии нет. */
.warranty-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 14px;
  background: var(--brand-soft); border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
.warranty-bar__t {
  font-size: var(--text-small); text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
}
.warranty-bar__v { font-weight: 600; }

/* ───────────────────────────────────────────────────────────── живая лента
   Лента ограничена по высоте и прокручивается внутри себя. Без этого блок
   суммы уезжает за первый экран, а именно на сумму смотрит приёмщик,
   принимая оплату. */
.feed { list-style: none; margin: 0 0 12px; padding: 0; max-height: 300px; overflow-y: auto; }
/* Развёрнутая история читается целиком, а не в окошке на 300 точек. */
.feed--all { max-height: none; }
.ev { display: flex; gap: 8px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.ev:last-child { border-bottom: 0; }
.ev__b { min-width: 0; }
.ev__h { margin: 0; font-size: 12.5px; line-height: 1.4; }
.ev__x { color: var(--ink-2); }
.ev__t { color: var(--muted); font-size: 11.5px; margin-left: 4px; }

.cl__n { margin: 0 0 2px; font-weight: 600; }
.cl__p { margin: 0; color: var(--ink-2); }

/* Предварительная стоимость отдельной плашкой: «должна больше бросаться в
   глаза». Это первое, что называют клиенту, и первое, о чём он спрашивает. */
.est {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 9px 12px; margin-bottom: 10px;
  background: var(--surface); border-radius: var(--radius);
}
.est__t { color: var(--ink-2); font-size: var(--text-subtitle); }
.est__v { font-size: 17px; font-weight: 600; }

.totals__sum { font-weight: 600; border-top: 1px solid var(--line-strong); }
/* «До сплати» — та цифра, на которую смотрит приёмщик, принимая деньги.
   Она обязана быть крупнее остальных, иначе он примет не ту сумму. */
.totals__due { font-weight: 600; font-size: 15px; }

/* Привязанная заявка: без собственной рамки и внизу колонки — параметр
   важный и нужный, но на видном месте быть не должен. */
.lead-note {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; margin: 14px 0; background: var(--brand-soft);
  border-radius: var(--radius); font-size: 12.5px;
}
.lead-note__x {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--brand); cursor: pointer;
}

.photos { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.photo { margin: 0; display: flex; flex-direction: column; gap: 5px; }
.photo img {
  display: block; width: 120px; height: 120px; object-fit: cover;
  border: 1px solid var(--line); border-radius: var(--radius);
}

/* ───────────────────────────────────────────────────────── форма приёма */

.cols--form { grid-template-columns: 1fr 400px; }
@media (max-width: 999px) { .cols--form { grid-template-columns: 1fr; } }

.form-row--3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 760px) { .form-row--3 { grid-template-columns: 1fr; } }

/* «Прийнято через» стоит вверху формы: это первый известный факт о заказе. */
.seg-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.seg {
  display: inline-flex; flex-wrap: wrap; border: 1px solid var(--line-strong);
  border-radius: var(--radius); overflow: hidden;
}
.seg__i { display: inline-flex; position: relative; }
.seg__i input { position: absolute; opacity: 0; pointer-events: none; }
.seg__i span {
  display: inline-flex; align-items: center; height: 32px; padding: 0 12px;
  border-right: 1px solid var(--line); font-size: 13px; cursor: pointer;
}
.seg__i:last-child span { border-right: 0; }
.seg__i input:checked + span { background: var(--ink); color: var(--ground); }
.seg__i input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: -2px; }

/* На широком экране список виден весь, кнопка не нужна. На телефоне шесть
   кнопок занимали целый экран, а самый частый ответ один и тот же. */
.seg-pick { display: none; }

.lead-found {
  padding: 12px 14px; margin-bottom: 14px;
  background: var(--brand-soft); border: 1px solid var(--line-strong);
  border-radius: var(--radius-card);
}
.lead-found__h { font-size: 13px; }
.lead-found__x { margin: 4px 0 10px; font-size: 12.5px; color: var(--ink-2); }
.lead-found__b { display: flex; gap: 8px; flex-wrap: wrap; }

/* Комплектация и внешний вид галочками. Именно они сжали форму до одного
   экрана: списком с прокруткой это не помещалось. */
.ck-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 12px; }
.ck-grid--wide { grid-template-columns: repeat(4, 1fr); }
.ck-grid ul { list-style: none; margin: 0; padding: 0; display: contents; }
.ck-grid li { display: flex; }
.ck-grid label {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; padding: 3px 0; cursor: pointer;
}
.ck-grid input[type="checkbox"] { flex: none; }
@media (max-width: 760px) { .ck-grid, .ck-grid--wide { grid-template-columns: 1fr 1fr; } }

.ck { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.ck--urgent { margin-top: 6px; }

/* Подсказка неисправности перекрывает форму, а не раздвигает её: иначе поля
   ниже прыгают под курсором ровно в момент выбора. */
.drop-wrap { position: relative; }
.drop {
  position: absolute; z-index: 20; left: 0; right: 0; top: 100%;
  max-width: 460px; max-height: 240px; overflow-y: auto;
  background: var(--ground); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: 0 8px 24px rgba(20, 29, 31, .12);
}
.drop__i, .drop__new {
  display: block; width: 100%; text-align: left; padding: 8px 12px;
  background: none; border: 0; border-bottom: 1px solid var(--line);
  font: inherit; font-size: 13px; cursor: pointer;
}
.drop__i:hover, .drop__new:hover { background: var(--surface); }
.drop__new { color: var(--brand); border-bottom: 0; }

.device-card { position: relative; }

/* Действие блока стоит в шапке блока, а не поверх него. Галочка «Прибрати
   пристрій», висевшая в углу карточки, читалась как «принять без
   устройства» — заказчик сказал об этом прямо. */
.device-card__h { align-items: center; margin-bottom: 10px; }
.device-card__n { margin: 0; }

/* ─────────────────────────────────────────────── поле с поиском по вводу
   Модель устройства, мастер и менеджер. Значение уезжает скрытым полем,
   человек видит обычный ввод: список моделей на десятки тысяч строк в
   <select> не кладут, а листать сотрудников глазами долго. */

.combo { position: relative; display: flex; gap: 6px; align-items: center; }
.combo__input { flex: 1 1 auto; min-width: 0; }
.combo__add {
  flex: none; width: 34px; height: 34px; padding: 0;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--ground); color: var(--ink);
  font: inherit; font-size: 17px; line-height: 1; cursor: pointer;
}
.combo__add:hover { background: var(--surface); }
.combo__drop {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 3px);
  max-height: 260px; overflow-y: auto;
  background: var(--ground); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: 0 8px 24px rgba(20, 29, 31, .12);
}
/* Подсказка справа отвечает на вопрос «который из двух»: одинаковые названия
   у разных категорий встречаются постоянно. */
.combo__drop .drop__i { display: flex; justify-content: space-between; gap: 12px; }
.drop__h { color: var(--muted); font-size: var(--text-small); white-space: nowrap; }
.drop__e { padding: 8px 12px; color: var(--muted); font-size: 13px; }
/* «Не призначено» — действие, а не найденная строка, и читается тише. */
.drop__c { color: var(--muted); }

/* Поле во всю ширину карточки: модель и «Додаткова інформація» в 460 точек
   не помещаются, а обрезать их нечем. */
.field--wide { max-width: none; }

/* ═════════════════════════════════════════════════════════ этап 4: печать
   Меню «Друк» в карточке и редактор шаблонов в настройках. Сами документы
   верстаются отдельным листом print.css: у бумаги нет тем и хрома. */

/* Кнопка-меню: пять печатных форм под одной кнопкой с принтером. */
.print-menu { position: relative; }
.print-menu summary { list-style: none; cursor: pointer; }
.print-menu summary::-webkit-details-marker { display: none; }
.print-menu__list {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; min-width: 220px;
  background: var(--ground); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: 0 8px 24px rgba(20, 29, 31, .12);
  display: flex; flex-direction: column; padding: 4px;
}
.print-menu__list a {
  display: block; padding: 8px 12px; border-radius: var(--radius);
  color: var(--ink); text-decoration: none; font-size: var(--text-body);
}
.print-menu__list a:hover { background: var(--surface); }
/* На телефоне список считается от РЯДА ДЕЙСТВИЙ, а не от кнопки. Кнопка
   «Друк» стоит в ряду последней, и её место плавает: когда ряд помещается в
   строку, она справа, когда переносится — оказывается слева на своей строке.
   Поэтому любая фиксированная сторона рано или поздно уезжает за экран.
   Замерено 10.09 на стенде: при left:0 список вылезал ВПРАВО на 135 точек
   (360-760px), при right:0 — ВЛЕВО на 135 точек на 320. Привязка к ряду даёт
   ноль вылетов на всех ширинах в обоих режимах карточки, а кнопка стоит на
   последней строке ряда, так что список по-прежнему падает прямо под неё —
   отрыв 4 точки. Заказчик просил «поставить влево, чтобы видно было». */
@media (max-width: 760px) {
  .head-card__actions { position: relative; }
  .print-menu { position: static; }
  .print-menu__list { left: 0; right: auto; min-width: 0; width: min(240px, 100%); }
}

/* Полупрозрачная кнопка: второе действие рядом с главным. «Прийняти і друк»
   на приёме — заливку поменяли местами по видео 10. */
.btn--ghost { background: var(--surface); border-color: var(--line-strong); color: var(--ink); }
.btn--ghost:hover { background: var(--surface-2); }
.form-actions--intake { margin-top: 18px; }
.form-cancel { margin: 10px 0 0; }

/* Редактор шаблонов: список документов слева, редактор, справка справа. */
.doc-layout { display: grid; grid-template-columns: 196px minmax(0, 1fr) 260px; gap: 16px; align-items: start; }
.doc-main { min-width: 0; }
.doc-side { min-width: 0; }
.doc-nav { display: flex; flex-direction: column; gap: 1px; }
.doc-nav__h {
  font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
  margin: 14px 0 6px; padding: 0 11px;
}
.doc-nav__h:first-child { margin-top: 0; }
.doc-nav__i { display: block; padding: 8px 11px; border-radius: var(--radius); color: var(--ink-2); text-decoration: none; }
.doc-nav__i:hover { background: var(--surface); color: var(--ink); }
.doc-nav__i--on { background: var(--surface); color: var(--ink); font-weight: 500; }
.doc-head { align-items: center; margin-bottom: 10px; }
.doc-head .card__title { margin: 0; }
.doc-reset { font-size: var(--text-small); }
.doc-reset:disabled { color: var(--muted); cursor: default; }
.card--soft { background: var(--surface); }
.doc-text { width: 100%; max-width: none; line-height: 1.55; }
.var-list { display: flex; flex-wrap: wrap; gap: 6px; }
.var-btn { cursor: pointer; background: var(--ground); font: inherit; font-size: 12.5px; }
.var-btn:hover { background: var(--surface); border-color: var(--ink-2); }
@media (max-width: 1100px) {
  .doc-layout { grid-template-columns: 1fr; gap: 12px; }
  .doc-nav { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; gap: 4px; padding-bottom: 4px; }
  .doc-nav__h { display: none; }
  .doc-nav__i { white-space: nowrap; border: 1px solid var(--line); }
}

/* ─────────────────────────────────────────────────────────────── телефон
   На телефоне таблица уступает место плиткам. Не оба сразу: две разные
   раскладки одних и тех же данных на одном экране читаются как ошибка. */
@media (max-width: 760px) {
  .orders-table { display: none; }
  .tiles { display: flex; }
  .filters__group { width: 100%; }
  .who-row { flex-wrap: wrap; }
  .who-row select { max-width: 100%; }
  .photo img { width: 96px; height: 96px; }

  /* «Прийнято через» складывается под кнопку с текущим выбором. */
  .seg-pick { display: inline-flex; }
  .seg-row .seg { display: none; }
  .seg-row--open .seg {
    display: flex; flex-direction: column; width: 100%;
    border-radius: var(--radius); overflow: hidden;
  }
  .seg-row--open .seg__i { width: 100%; }
  .seg-row--open .seg__i span {
    width: 100%; border-right: 0; border-bottom: 1px solid var(--line);
  }
  .seg-row--open .seg__i:last-child span { border-bottom: 0; }

  /* Кнопка «+» рядом с моделью на телефоне остаётся квадратной: сжимать её
     некуда, а промахнуться по ней пальцем нельзя. */
  .combo__add { width: 38px; height: 38px; }
}

/* ═══════════════════════════════════════════ финальный дизайн: видео 10
   Перетягивание согласованного дизайна: серый фон и белые островки,
   разделы своим цветом, круги-инициалы, подсветка строк, лента с
   различением системы и людей, плашки-галочки, плашка сохранения и
   карточка поверх списка. Десктоп не пересобирается: правится то, что
   есть, классы этапов 1–3 остаются на своих местах. */

/* ── Цвет раздела ──────────────────────────────────────────────────── */
body[data-section="orders"]  { --sec-bg: var(--sec-orders-bg);  --sec-fg: var(--sec-orders-fg);  --sec-line: var(--sec-orders-line); }
body[data-section="leads"]   { --sec-bg: var(--sec-leads-bg);   --sec-fg: var(--sec-leads-fg);   --sec-line: var(--sec-leads-line); }
body[data-section="clients"] { --sec-bg: var(--sec-clients-bg); --sec-fg: var(--sec-clients-fg); --sec-line: var(--sec-clients-line); }
body[data-section="cash"]    { --sec-bg: var(--sec-cash-bg);    --sec-fg: var(--sec-cash-fg);    --sec-line: var(--sec-cash-line); }
body[data-section="sales"]   { --sec-bg: var(--sec-sales-bg);   --sec-fg: var(--sec-sales-fg);   --sec-line: var(--sec-sales-line); }
/* Своего цвета у «Повідомлень» больше нет: с 02.10 журнал — подпункт
   «Клієнти» и красится их цветом (видео 02.10, п. 8). Токены --ev-sms-*
   остались — ими красится запись SMS в ленте заказа. */

/* Кнопка создания раздела залита цветом раздела: заказы зелёные, заявки
   фиолетовые, клиенты тёмные. Остальные главные кнопки остаются графитом. */
.btn--section { background: var(--sec-fg); border-color: var(--sec-fg); color: #fff; }
.btn--section:hover { opacity: .92; background: var(--sec-fg); }
.sidebar__link--active { background: var(--sec-bg); color: var(--sec-fg); }

/* Счётчики — островки; первый подсвечен цветом раздела, как у заказчика. */
.cnt { box-shadow: var(--island-shadow); }
.counters .cnt:first-child { background: var(--sec-bg); border-color: var(--sec-line); }
.counters .cnt:first-child b { color: var(--sec-fg); }

/* Островки-таблицы: список лежит на белом внутри серой страницы. */
.table-wrap { background: var(--ground); border: 1px solid var(--line);
  border-radius: var(--radius-card); box-shadow: var(--island-shadow); }
.table-wrap .table tbody tr:last-child td { border-bottom: 0; }
.card .table-wrap { border: 0; box-shadow: none; border-radius: 0; }
.settings-item { box-shadow: var(--island-shadow); }
.topbar { background: var(--ground); }

/* Плашка места в шапке: филия приёма иконкой и названием, без слова
   «філія». Читается как место, а не как поле. */
.place-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px;
  border-radius: var(--radius-chip); background: var(--sec-bg); color: var(--sec-fg);
  font-size: 12px; font-weight: 500; white-space: nowrap; vertical-align: middle;
}
.place-chip svg { flex: none; }
.page-title .place-chip { margin-left: 8px; }

/* ── Подсветка строк и плиток ─────────────────────────────────────── */
.table tr.row--issued td { background: var(--row-issued-bg); }
.table tr.row--overdue td { background: var(--row-overdue-bg); }
.table tr.row--issued:hover td { background: var(--row-issued-bg); }
.table tr.row--overdue:hover td { background: var(--row-overdue-bg); }
.tile { background: var(--ground); box-shadow: var(--island-shadow); }
.tile.row--issued { background: var(--row-issued-bg); border-color: var(--row-issued-line); }
.tile.row--overdue { background: var(--row-overdue-bg); border-color: var(--row-overdue-line); }
.t-ok { color: var(--status-green-fg); }
/* Плитки заявок: тот же ритм, что у заказов, третья строка — суть звернення. */
.tile--lead .t-note { grid-column: 1 / -1; font-size: 12px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile--lead .t-note--late { color: var(--status-red-fg); }
.tile--lead .t-note--ok { color: var(--status-green-fg); }

/* ── Клиент в карточке заказа и карточке клиента ───────────────────── */
.client-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.client-head__b { min-width: 0; flex: 1; }
.client-head__n { margin: 0; font-weight: 600; font-size: 15px; }
.client-head__n a { color: var(--ink); text-decoration: none; }
.client-head__n a:hover { color: var(--brand); }
.client-head__m { margin: 2px 0 0; font-size: var(--text-small); color: var(--muted); }
.phone-row { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.phone-row .num { color: var(--ink-2); }
.copy-btn {
  width: 26px; height: 26px; border: 1px solid transparent; border-radius: var(--radius);
  background: none; color: var(--muted); cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color .15s, background .15s, transform .15s;
}
.copy-btn:hover { background: var(--surface); color: var(--ink); }
.copy-btn.copied { color: var(--status-green-fg); background: var(--status-green-bg); transform: scale(1.12); }
.copy-btn svg { display: block; }
.contact-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.contact-btns .btn { width: 100%; min-width: 0; }
/* На самом узком экране две кнопки связи не помещаются в ряд — одна под другой. */
@media (max-width: 360px) { .contact-btns { grid-template-columns: 1fr; } }
.btn--tel { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); }
.btn--tel:hover { background: var(--sec-bg); opacity: .9; }
/* Метки клиента: постоянный, проблемный, скидка. Информативные, без логики. */
.tag--regular { background: var(--status-green-bg); color: var(--status-green-fg); border-color: transparent; }
.tag--problem { background: var(--status-red-bg); color: var(--status-red-fg); border-color: transparent; }
.tag--discount { background: var(--status-amber-bg); color: var(--status-amber-fg); border-color: transparent; font-weight: 600; }
.client-tags { display: inline-flex; gap: 5px; flex-wrap: wrap; vertical-align: middle; margin-left: 6px; }
.client-tags .tag { height: 19px; padding: 0 7px; font-size: 11px; }
.client-meta { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 14px 0; }

/* ── Карточка заказа ──────────────────────────────────────────────── */
.card__head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; }
.card__head .card__title { margin: 0; }
/* Плашка модели приглушена: значение читается, а не редактируется на глаз. */
.model-plate, .combo__input.model-plate { background: var(--surface); }
.model-plate:focus { background: var(--ground); }
.btn--dashed { border-style: dashed; background: transparent; color: var(--sec-fg); font-weight: 500; }
.btn--dashed:hover { background: var(--sec-bg); }
.btn--center { display: flex; margin: 0 auto; min-width: 240px; }
.btn--ghost { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); }
.btn--ghost:hover { background: var(--sec-bg); opacity: .9; }

/* Лента: системные записи и комментарии сотрудников различаются цветом и
   рамкой; вкладки фильтруют, не перезагружая страницу. */
.feed-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 8px; }
.feed-tab {
  padding: 6px 10px; font-size: 12.5px; color: var(--muted); background: none; border: 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; font-family: inherit;
}
.feed-tab--on { color: var(--ink); border-bottom-color: var(--sec-fg); font-weight: 500; }
.ev--staff { background: var(--surface); border-left: 3px solid var(--sec-fg);
  border-radius: 0 var(--radius) var(--radius) 0; padding: 8px 10px; margin: 4px 0; border-bottom: 0; }
.ev--staff .ev__h b { color: var(--sec-fg); }
.ev--system .ev__h { color: var(--ink-2); }
.ev--system .ini { background: var(--brand-soft); color: var(--brand); font-size: 9px; }
/* Вкладки ленты фильтруют по трём классам записей: системная, сотрудника и
   сообщение клиенту. Четвёртая вкладка «Повідомлення» — просьба заказчика
   22.09. Записи сообщений не системные и не «сотрудников», поэтому в обеих
   прежних вкладках их тоже не видно. */
.feed[data-show="system"] .ev--staff,
.feed[data-show="system"] .ev--sms,
.feed[data-show="staff"] .ev--system,
.feed[data-show="staff"] .ev--sms,
.feed[data-show="sms"] .ev--system,
.feed[data-show="sms"] .ev--staff { display: none; }
.ev__file { display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 12px; }
.ev__file img { width: 44px; height: 44px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--line); }
.comment-row { display: flex; gap: 8px; align-items: flex-start; }
.comment-row .field { flex: 1; margin: 0; max-width: none; }
.pin-btn {
  width: 34px; height: 34px; border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--ground); color: var(--ink-2); cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; flex: none; padding: 0; position: relative;
}
.pin-btn:hover { background: var(--surface); }
.pin-btn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; }
.pin-btn.has-file { color: var(--brand); border-color: var(--brand); }
.comment-actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.pin-name { font-size: var(--text-small); color: var(--muted); }
.remind-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
@media (max-width: 560px) { .remind-row { grid-template-columns: 1fr; } }

/* ── Приём ────────────────────────────────────────────────────────── */
.via-card { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.via-card .field { margin: 0; max-width: none; min-width: 220px; }
/* «Прийнято через» остаётся одной строкой и на телефоне: подпись слева,
   список справа, как в файлах заказчика. В столбик его уводил
   flex-direction: column отсюда — заказчик поймал это на приёме 08.09.
   Стоявший тут же align-items: stretch всё равно был мёртв: его перебивает
   поздняя приписка .via-card ниже по файлу. */
@media (max-width: 560px) {
  .via-card .field { min-width: 0; flex: 1 1 auto; }
}
/* Поджатие островка «Прийнято через» на телефоне стоит НИЖЕ поздней приписки
   .via-card: у них одинаковый вес, и в медиазапросе выше по файлу оно было
   мертво — gap и padding приходили из приписки. Найдено перепроверкой 09.09. */
@media (max-width: 560px) {
  .via-card { gap: 10px; padding: 9px 11px; }
}
/* Комплектация и внешний вид — плашки-галочки. Галочка остаётся настоящим
   checkbox внутри плашки: так она отправляется формой и читается прогоном. */
.ck-grid { gap: 6px 8px; }
.ck-grid label {
  border: 1px solid var(--line); border-radius: 8px; padding: 6px 10px;
  background: var(--ground); font-size: 12.5px; color: var(--ink-2); width: 100%;
  transition: background .12s, border-color .12s;
}
.ck-grid label:hover { border-color: var(--line-strong); }
.ck-grid label:has(input:checked) { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); font-weight: 500; }
.ck-grid input[type="checkbox"] { accent-color: var(--sec-fg); }
/* «Свій варіант» — пунктирная строка под плашками. */
.ck-note input { border-style: dashed; background: transparent; }
.ck-note input:focus { border-style: solid; background: var(--ground); }
.ck-note .field__label { display: none; }
.ck-note.field { margin-top: 6px; margin-bottom: 0; }
/* Срочный ремонт — красная плашка, когда отмечен. */
.ck--urgent { border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; width: 100%; }
.ck--urgent:has(input:checked) { background: var(--status-red-bg); border-color: var(--status-red-fg); color: var(--status-red-fg); font-weight: 500; }
.ck--urgent input[type="checkbox"] { accent-color: var(--status-red-fg); }
.form-row--stack { grid-template-columns: 1fr; }
.form-row--stack .field { max-width: none; }
.form-actions--intake { flex-wrap: wrap; }
.form-actions--intake .btn { min-width: 160px; }
/* На узком телефоне две кнопки делят строку поровну, а не выталкивают экран вбок. */
@media (max-width: 420px) {
  .form-actions--intake .btn { min-width: 0; flex: 1 1 calc(50% - 4px); }
}

/* ── Плашка сохранения ────────────────────────────────────────────── */
/* Всплывает снизу, когда в форме есть несохранённое: «видно, что нужно
   сохранить» — так заказчик и просил, тихого автосейва нет. */
.save-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%) translateY(20px);
  z-index: 60; display: flex; align-items: center; gap: 10px;
  padding: 10px 12px 10px 16px; background: var(--ink); color: var(--ground);
  border-radius: 12px; box-shadow: 0 12px 32px rgba(20, 29, 31, .28);
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
  max-width: calc(100vw - 24px); font-size: 13.5px;
}
.save-bar--on { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.save-bar__t { white-space: nowrap; }
.save-bar .btn { height: 32px; border-color: transparent; }
.save-bar .btn--primary { background: var(--sec-fg); color: #fff; }
.save-bar .btn--link { color: var(--ground); opacity: .8; }
.save-bar--busy { opacity: .7; }
html.js .js-hide { display: none; }

/* ── Чат поддержки: запас под кружок (этап 9) ──────────────────────── */
/* Кружок Tawk (billing/_support_chat.html) висит в правом нижнем углу
   поверх страницы, и страница, прокрученная до конца, оставляла под ним
   последние кнопки: «Прийняти і друк» на приёме, «Додати» в карточке,
   выбор в профиле компании, а на короткой странице надходжень — плитку,
   которую и прокрутить было некуда (снимки с заглушкой, 12.10).
   Запас снизу посчитан от положения кружка в Tawk_API.customStyle того же
   шаблона: на столе 20 px от низа + 60 кружок + 12 = 92, на телефоне кружок
   поднят над плашкой сохранения до 84 px — 84 + 60 + 12 = 156. Меняется
   положение там — меняется и запас здесь. Касание без мыши тоже считаем
   телефоном: по какому признаку Tawk узнаёт телефон — по ширине или по
   устройству, — в его документации не сказано, а телефон боком шире 760
   точек. Только на экране: на бумаге кружка нет (перед печатью его прячет
   тот же шаблон), а лишние 32–116 px внизу могли бы вытолкнуть хвост
   журнала кассы на пустой лист. Класс ставит base_app.html, только когда
   чат есть на этой странице. Селектор из двух классов — чтобы правило
   держалось, где бы в файле ни стояло: поля .content задаёт и раздел
   телефона, и более поздний .content перебил бы одиночный класс. */
@media screen {
  .content.content--chat { padding-bottom: 92px; }
}
@media screen and (max-width: 760px), screen and (pointer: coarse) {
  .content.content--chat { padding-bottom: 156px; }
}

/* ── Карточка поверх списка ───────────────────────────────────────── */
/* Заказ и заявка открываются нахлёстом, как в Gincore; клик по пустому месту
   возвращает к списку. Это <dialog>: подложка, Escape и фокус даром. */
.overlay {
  border: 0; padding: 0; background: transparent; width: min(1060px, calc(100vw - 24px));
  max-height: calc(100vh - 32px); margin: 16px auto; overflow: visible;
}
.overlay::backdrop { background: rgba(10, 20, 20, 0.38); }
.overlay__panel {
  background: var(--page-bg); border-radius: 14px; border: 1px solid var(--line);
  max-height: calc(100vh - 32px); overflow-y: auto; padding: 20px 22px 28px; position: relative;
  box-shadow: 0 24px 60px rgba(20, 29, 31, .28);
}
.overlay__close {
  position: sticky; top: 0; float: right; z-index: 2; width: 32px; height: 32px;
  border: 1px solid var(--line-strong); border-radius: 50%; background: var(--ground);
  color: var(--ink-2); cursor: pointer; font-size: 18px; line-height: 1; margin: -6px -8px 0 0;
}
.overlay__close:hover { color: var(--ink); background: var(--surface); }
.overlay__panel .content { padding: 0; max-width: none; }
.overlay__panel .head-card { padding-right: 36px; }
.overlay--busy .overlay__panel { opacity: .6; }
@media (max-width: 760px) {
  /* max-width: у <dialog> в стилях браузера стоит calc(100% - 6px - 2em), и без
     сброса карточка на телефоне не занимала весь экран. */
  .overlay { width: 100vw; max-width: 100vw; max-height: 100vh; margin: 0; }
  .overlay__panel { border-radius: 0; max-height: 100vh; padding: 14px 12px 40px; }
}

/* ── Карточка клиента ─────────────────────────────────────────────── */
/* Кружок с инициалами в шапке, метки у имени, кнопки связи рядом, три
   счётчика — по файлу заказчика. Устройства свёрнуты до четырёх. */
.devices-more summary { list-style: none; cursor: pointer; display: inline-flex; }
.devices-more summary::-webkit-details-marker { display: none; }
.devices-more { margin-top: 8px; }
.devices-more[open] > summary { display: none; }
.comm-head { display: flex; align-items: center; gap: 10px; margin-bottom: 2px; }
.comm-head .card__title { margin: 0; }
/* Каркас-заглушка «Історія зв'язку» (.stub, .comm-tabs) снят 02.10: в блоке
   настоящие SMS и рабочие вкладки ленты, правила — в секции видео 02.10. */
.comm-empty { padding: 18px 0 6px; font-size: 13px; color: var(--muted); text-align: center; }
.head-avatar { display: flex; align-items: center; gap: 14px; min-width: 0; }
.head-avatar .page-title { margin: 0; }
.head-avatar .client-tags { margin-left: 8px; }
.ini--xl { width: 48px; height: 48px; font-size: 17px; background: var(--sec-bg); color: var(--sec-fg); }
.contact-btns--head { margin: 0 0 14px; max-width: 460px; }
.counters--client { margin-bottom: 14px; }
.phone-line__act { display: inline-flex; align-items: center; gap: 6px; }
/* «Додати телефон» — пунктирная кнопка по центру; форма раскрывается по ней. */
.add-phone { margin-top: 10px; }
.add-phone summary { list-style: none; cursor: pointer; }
.add-phone summary::-webkit-details-marker { display: none; }
.add-phone[open] > summary { display: none; }
.add-phone form { margin-top: 8px; }
.dev-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.dev-row:last-child { border-bottom: 0; }
.dev-row__n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-row__s { color: var(--muted); font-size: var(--text-small); margin-left: 6px; }
.dev-row__c { color: var(--muted); font-size: var(--text-small); white-space: nowrap; }
.about-row { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.about-row:last-child { border-bottom: 0; }
.about-row > span:first-child { color: var(--muted); flex: none; }
.about-row > span:last-child { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.note-box { margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: var(--status-amber-bg); color: var(--status-amber-fg); font-size: 13px; }
.ck--problem { margin: 6px 0 0; }
/* Плитки списка клиентов на телефоне: имя с метками, номер, справа ремонты. */
.tile--client .t-dev { font-size: 14.5px; }
.tile--client .client-tags { margin-left: 4px; }
.tile--client .t-r .tag { height: 22px; }

/* ── Карточка заказа компактно: чипы комплектации и вида ──────────────── */
.dev-chips { margin-top: 10px; display: grid; gap: 8px; }
.dev-chips__g { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.dev-chips__l { font-size: var(--text-small); color: var(--muted); width: 100%; }
.dev-chips .tag--look { background: var(--status-amber-bg); color: var(--status-amber-fg); border-color: transparent; }
.dev-src-toggle { margin: 2px 0 8px; }
.dev-src-toggle .btn--link { font-size: 12.5px; }

/* ── Телефон: карточка заказа в порядке макета заказчика ─────────────────
   Шапка → клиент → устройство → условия → участники → запчасти → работы →
   висновок → сума → фото → лента → заявка. Колонки раскрываются
   (display: contents), и карточки становятся элементами одной сетки. */
@media (max-width: 899px) {
  .cols--card > div { display: contents; }
  .cols--card > div > * { min-width: 0; }
  .cols--card .card + .card { margin-top: 0; }
  .cols--card .blk-client { order: 1; }
  .cols--card .blk-device { order: 2; }
  .cols--card .blk-terms { order: 3; }
  .cols--card .blk-crew { order: 4; }
  .cols--card .blk-parts { order: 5; }
  .cols--card .blk-works { order: 6; }
  .cols--card .blk-report { order: 7; }
  .cols--card .blk-sum { order: 8; }
  .cols--card .blk-photos { order: 9; }
  .cols--card .blk-feed { order: 10; }
  .cols--card .lead-note { order: 11; }
  /* Ряд действий: статус во всю оставшуюся ширину, дзвіночок иконкой, друк. */
  .head-card__actions .act-status { order: 1; flex: 1 1 auto; min-width: 0; }
  .head-card__actions .act-status select { width: 100%; }
  .head-card__actions .act-bell { order: 2; }
  .head-card__actions .act-bell__t { display: none; }
  .head-card__actions .act-print { order: 3; }
  /* «Видалити» на телефоне — тихая ссылка в конце ряда, не красная кнопка. */
  .head-card__actions .act-delete {
    order: 4; flex: 1 1 100%; justify-content: flex-end; border: 0; background: none;
    height: auto; padding: 2px 0 0; font-size: 12.5px; color: var(--status-red-fg);
  }
}

/* Таблица заявок на телефоне уступает место плиткам, как и заказы. */
@media (max-width: 760px) { .hide-phone { display: none; } }

/* Колонки карточки не растут под min-content содержимого: таблица работ на
   телефоне прокручивается внутри своей обёртки, а не выталкивает экран вбок.
   Длинное слово без пробелов в ленте переносится, а не растягивает карточку —
   такое пришло из обхода форм мусором. */
.cols > * { min-width: 0; }
.feed .ev__b, .feed .ev__h, .feed .ev__x, .feed .ev__t { min-width: 0; overflow-wrap: anywhere; }
.feed .ev { min-width: 0; }
/* Текст только для читалок: филия в шапке карточки читается и прогонами. */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ═══════════════════════════════ финальный дизайн, версия 2 (видео 11, 06.09)
   Один в один по файлам заказчика от 03.09 и согласованному дизайн-проекту:
   подписи полей заглавными 11px, поля 35px с радиусом 10, острова с радиусом
   14 и тенью, теги прямоугольные с рамкой, статус в шапке — цветная плашка
   во всю ширину, участники строками, работы строками, лента — таймлайн.
   Ниже только переопределения: классы этапов 1–3 остаются на местах. */

:root {
  --r-field: 10px;
  --r-island: 14px;
  --shadow-card: 0 1px 3px rgba(15, 23, 42, .04), 0 4px 12px -2px rgba(15, 23, 42, .03);
  --label: 11px;
}

/* ── Острова, подписи, поля ─────────────────────────────────────────── */
.card { border-radius: var(--r-island); box-shadow: var(--shadow-card); padding: 14px 16px; }
.card + .card { margin-top: 12px; }
.card__head { padding-bottom: 9px; margin-bottom: 12px; border-bottom: 1px solid var(--line); }
.card__head .card__title { margin: 0; }
.card__title { font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-2); display: flex; align-items: center; gap: 7px; }
.card__title svg { color: var(--muted); flex: none; }
.card__hint { margin: -6px 0 10px; }
.field__label {
  font-size: var(--label); font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 4px; display: flex; justify-content: space-between; align-items: center; gap: 8px;
}
.field { margin-bottom: 10px; }
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), select, textarea {
  border-radius: var(--r-field); min-height: 35px; font-size: 13px;
}
select { height: 35px; }
.field textarea { min-height: 54px; }
.form-row { gap: 10px; }
.btn { border-radius: var(--r-field); font-weight: 600; font-size: 12.5px; }
.btn--small { height: 30px; border-radius: 8px; }
.btn--wide { height: 36px; }
.btn--wide-sm { width: 100%; height: 35px; justify-content: center; }
.input-plate {
  display: flex; align-items: center; min-height: 35px; padding: 6px 11px; border: 1px solid var(--line);
  border-radius: var(--r-field); background: var(--surface); font-size: 13px; color: var(--ink);
}
.model-plate, .combo__input.model-plate { background: var(--surface); font-weight: 600; border-color: var(--line-strong); }

/* ── Теги: прямоугольные с рамкой — как в согласованном проекте ─────────── */
.tag {
  border-radius: 6px; height: auto; padding: 2px 9px; font-size: 12px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2);
}
.tag--look { background: var(--status-amber-bg); color: var(--status-amber-fg); border-color: transparent; }
.tag--meta { font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 4px; }
/* Плашка «Терміново» — по его файлу карточки (.urgent-badge) и скрину от
   07.09: пилюля, светлый фон, яркий текст, розовая рамка, лёгкая тень. */
.chip--urgent {
  border-radius: 999px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: 0 9px; height: 20px; line-height: 18px; display: inline-flex; align-items: center; gap: 5px;
  background: var(--urgent-bg); color: var(--urgent-fg); border: 1px solid var(--urgent-line);
  box-shadow: 0 1px 2px rgba(185, 28, 28, .08);
}
.chip__dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; display: inline-block; }
.place-chip { border-radius: 6px; border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font-weight: 600; font-size: 11px; height: 22px; padding: 0 7px; }

/* ── Шапка карточки и приёма ────────────────────────────────────────── */
.head-card--order .page-title { font-size: 19px; font-weight: 700; letter-spacing: -.02em; }
.head-card--order .head-card__sub { font-size: 12px; }
.head-card__actions { align-items: center; }
.status-pill {
  display: flex; align-items: center; gap: 7px; height: 36px; padding: 0 6px 0 12px; border-radius: var(--r-field);
  border: 1px solid rgba(0, 0, 0, .06); font-weight: 600; font-size: 12.5px; min-width: 180px;
}
.status-pill select {
  background: transparent; border: 0; color: inherit; font: inherit; font-weight: 600; height: 34px; min-height: 0;
  padding: 0 4px; flex: 1 1 auto; min-width: 0; cursor: pointer;
}
.status-pill select:focus { outline: none; }
.status-pill__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none;
  box-shadow: 0 0 0 3px rgba(0, 0, 0, .06); }
.act-bell { width: 36px; height: 36px; padding: 0; justify-content: center; border-radius: var(--r-field); }
.act-bell__t { display: none; }
.print-menu summary.btn { height: 36px; border-radius: var(--r-field); }
.act-delete { border: 0; background: none; color: var(--status-red-fg); height: auto; padding: 0 4px; font-size: 12px; }

/* ── Устройство в карточке ──────────────────────────────────────────── */
.dev-src-toggle { margin: 2px 0 8px; }
.dev-src-toggle .btn--link { font-size: 12px; font-weight: 500; }
.dev-chips { margin-top: 8px; display: grid; gap: 8px; }
.dev-chips__g { display: grid; gap: 4px; }
.dev-chips__g .chips { gap: 5px; }
.dev-check { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 640px) { .dev-check { grid-template-columns: 1fr; } }
.btn-relocate {
  display: inline-flex; align-items: center; gap: 4px; border: 1px solid #D1FAE5; background: #F0FDF4; color: #047857;
  border-radius: 6px; padding: 1px 7px; font-size: 10px; font-weight: 600; text-transform: none; letter-spacing: 0;
  cursor: pointer; font-family: inherit;
}
.btn-relocate:hover { background: #047857; color: #fff; border-color: #047857; }
.transfer { margin-top: 8px; }
.transfer form { margin-top: 8px; padding: 10px 12px; border: 1px dashed var(--line-strong); border-radius: var(--r-field); }
.params { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.params__s { cursor: pointer; list-style: none; font-size: 12px; font-weight: 600; color: var(--ink-2);
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.params__s::-webkit-details-marker { display: none; }
.params__s::before { content: ""; width: 6px; height: 6px; border-right: 1.5px solid var(--muted);
  border-bottom: 1.5px solid var(--muted); transform: rotate(-45deg); margin-right: 2px; transition: transform .15s; }
.params[open] .params__s::before { transform: rotate(45deg); }
.params[open] .params__s { margin-bottom: 10px; }
.params--read { display: grid; gap: 6px; }
.params--money { margin-top: 10px; }
.ck--plate { border: 1px solid var(--line); border-radius: var(--r-field); padding: 8px 12px; width: 100%; min-height: 35px;
  font-size: 12.5px; font-weight: 500; color: var(--ink-2); background: var(--surface); }
.ck--plate:has(input:checked) { background: var(--status-red-bg); border-color: #F3D3D3; color: var(--status-red-fg); font-weight: 700; }

/* ── Участники и готовность ─────────────────────────────────────────── */
.who-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 6px 0;
  border-bottom: 1px solid var(--line); min-height: 44px; }
.who-row:last-of-type { border-bottom: 0; }
.who-row__l { font-size: 12px; color: var(--muted); font-weight: 500; flex: none; }
.who-form { margin: 0; flex: 0 1 65%; max-width: 240px; }
.who-row > .combo--who { flex: 0 1 65%; max-width: 240px; }
.combo--who { border: 1px solid var(--line); border-radius: var(--r-field); padding: 2px 6px; background: var(--ground);
  gap: 4px; }
.combo--who:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.combo--who .combo__input { border: 0; min-height: 28px; height: 28px; padding: 0 4px; font-weight: 600; font-size: 12.5px;
  background: transparent; }
.combo--who .combo__input:focus { outline: none; box-shadow: none; }
.combo__ini { flex: none; }
.ini--master { background: #EBF3F2; color: #115E59; }
.who .ini { margin-right: 2px; }
.ready-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; margin-top: 12px; }
.ready-row .field { margin: 0; max-width: none; }
.ready-row input { width: 100%; font-weight: 600; font-size: 12px; }
.notice-caption { font-size: 11.5px; color: var(--muted); margin: 10px 0 0; line-height: 1.4; }

/* ── Работы строками ────────────────────────────────────────────────── */
.items { display: flex; flex-direction: column; }
.item-row { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.item-row:last-of-type { border-bottom: 0; }
.item-row__t { font-size: 13px; font-weight: 600; color: var(--ink); min-width: 0; }
.item-row__p { font-size: 13.5px; font-weight: 700; text-align: right; }
.item-row__s { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted); flex-wrap: wrap; }
.warranty-chip { background: var(--brand-soft); color: var(--brand); border: 1px solid #CCF0E8; border-radius: 100px;
  padding: 1px 8px; font-size: 10.5px; font-weight: 600; }
.inline-form { display: inline; margin: 0; }
.link-remove { border: 0; background: none; padding: 0; color: #DC2626; font-size: 11px; font-weight: 500; cursor: pointer; font-family: inherit; }
.link-remove:hover { text-decoration: underline; }
.add-work { margin-top: 10px; }
.add-work__row { display: grid; grid-template-columns: 1fr 96px; gap: 8px; }
.add-work__row .field { margin: 0; max-width: none; }
.add-work .btn--wide { margin-top: 8px; }
.empty--tight { padding: 8px 0; }

/* ── Клиент ─────────────────────────────────────────────────────────── */
.client-head { align-items: flex-start; }
.client-head__n { font-size: 13.5px; }
.client-head__n a { color: var(--ink); }
.cl-meta { margin-left: auto; text-align: right; display: grid; gap: 3px; justify-items: end; font-size: 11px; flex: none; }
.contact-btns { margin: 0; }
.contact-btns .btn { height: 35px; }
.blk-contact { margin-top: 8px; }
.cols > div > .contact-btns + .card { margin-top: 12px; }

/* ── Лента — таймлайн ───────────────────────────────────────────────── */
/* Четыре вкладки ленты («Усі / Система / Співробітники / Повідомлення»,
   этап 7) в шапку островка на телефоне не влезают: с третьей их было три, и
   строка была ровно по ширине. Поэтому шапка и сам ряд вкладок переносятся —
   прятать вкладку или резать подпись нельзя, её просил заказчик. */
.card__head .feed-tabs { border: 0; margin: 0; flex-wrap: wrap; row-gap: 4px; }
.blk-feed .card__head { flex-wrap: wrap; }
.card__head .feed-tab { padding: 2px 8px; border: 1px solid var(--line); border-radius: 100px; font-size: 11px; margin: 0; }
.card__head .feed-tab--on { background: var(--sec-bg); color: var(--sec-fg); border-color: var(--sec-line); }
.timeline { position: relative; padding-left: 14px; margin: 4px 0 12px; display: grid; gap: 10px; }
.timeline::before { content: ""; position: absolute; left: 3px; top: 6px; bottom: 6px; width: 2px; background: var(--line); border-radius: 2px; }
.timeline .ev { display: block; position: relative; padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--r-field);
  background: var(--surface); margin: 0; }
.timeline .ev--staff { background: #F8FAF9; border-color: #D1E5E2; border-left: 3px solid var(--brand); }
.timeline .ev--system { border-left: 1px solid var(--line); }
/* Сообщение клиенту — своя ветка со своим цветом и конвертиком (просьба
   заказчика 22.09). Правило стоит здесь, после общего «.timeline .ev», иначе
   фон и рамку перебивало бы оно. */
.timeline .ev--sms { background: var(--ev-sms-bg); border-color: var(--ev-sms-line);
  border-left: 3px solid var(--ev-sms-fg); }
.timeline .ev--sms .ev__h b { color: var(--ev-sms-fg); }
.ev--sms .timeline__dot { background: var(--ev-sms-fg); }
.ev__ico { color: var(--ev-sms-fg); flex: none; margin-right: -2px; }
.timeline .ev--sms .ev__h { gap: 5px; justify-content: flex-start; }
.timeline .ev--sms .ev__t { margin-left: auto; }
.timeline__dot { position: absolute; left: -15px; top: 10px; width: 8px; height: 8px; border-radius: 50%;
  background: #94A3B8; border: 2px solid var(--ground); }
.ev--staff .timeline__dot { background: var(--brand); }
.timeline .ev__h { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 0 0 3px; font-size: 11.5px; }
.timeline .ev__h b { color: var(--ink); font-weight: 700; }
.timeline .ev--staff .ev__h b { color: var(--brand); }
.timeline .ev__t { color: var(--muted); font-size: 10.5px; margin: 0; }
.timeline .ev__x { margin: 0; font-size: 12px; color: var(--ink-2); line-height: 1.4; }
.feed-input { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-field); padding: 8px 10px;
  display: grid; gap: 8px; margin-top: 4px; }
.feed-input:focus-within { background: var(--ground); border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.feed-input__ta { border: 0; background: transparent; min-height: 44px; padding: 0; font-size: 12.5px; resize: none; }
.feed-input__ta:focus { outline: none; box-shadow: none; }
.feed-input__bar { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding-top: 6px; border-top: 1px solid var(--line); }
.pin-btn--flat { width: auto; height: 28px; border: 0; background: none; gap: 6px; padding: 0 4px; color: var(--muted); font-size: 11px; }
.pin-btn--flat.has-file { color: var(--brand); }
.notify { margin-top: 12px; }
.lead-note { border-radius: var(--r-island); background: var(--ground); border: 1px solid var(--line); color: var(--ink-2);
  font-weight: 500; box-shadow: 0 1px 2px rgba(0, 0, 0, .04); }
.lead-note b { color: var(--brand); }
.lead-note > span { display: inline-flex; align-items: center; gap: 8px; }
.lead-note__x { color: var(--brand); font-weight: 600; text-decoration: none; opacity: 1; }

/* ── Сумма и оплата ─────────────────────────────────────────────────── */
.finance-row { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; font-size: 13px; color: var(--ink-2); }
.finance-total { border-top: 1px solid var(--line); margin-top: 6px; padding-top: 9px; font-weight: 700; font-size: 14px; color: var(--ink); }
.finance-paid { color: var(--brand); font-weight: 600; }
/* Переплата: своя строка под плашкой «До сплати», не минус в ней. */
.finance-refund { margin: -6px 0 10px; }
.finance-refund .num { color: var(--brand); font-weight: 700; }
.due-banner { display: flex; justify-content: space-between; align-items: center; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-field); padding: 10px 14px; margin: 10px 0 12px; }
.due-banner__l { font-weight: 600; font-size: 13px; color: var(--ink-2); }
.due-banner__v { font-size: 18px; font-weight: 800; color: var(--brand); letter-spacing: -.02em; }
.btn--pay { width: 100%; height: 40px; justify-content: center; gap: 8px; background: var(--sec-fg); color: #fff; border-color: var(--sec-fg);
  font-size: 13.5px; font-weight: 700; }
/* Наведение задаётся здесь нарочно: у «.btn:hover» вес 0,2,0, а у
   «.btn--pay» — 0,1,0, поэтому общее правило перекрашивало залитую кнопку в
   --surface, а текст у неё белый — под курсором кнопка пропадала. Заказчик
   21.09: «кнопочка принять оплату слишком-слишком белая, теряется… и так
   понятно, что цвет меняется, но он слишком белый». У всех остальных
   залитых кнопок (--primary, --section, --tel, --quick) своё :hover есть,
   не было только у этой. */
.btn--pay:hover { background: var(--sec-fg); border-color: var(--sec-fg); opacity: .92; }
.btn--pay[disabled] { opacity: .55; cursor: not-allowed; }
.pay-history { font-size: 11px; color: var(--muted); margin: 10px 0 0; display: flex; align-items: center; gap: 6px; }
.pay-history::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--brand); flex: none; }

/* ── Приём ──────────────────────────────────────────────────────────── */
.via-card { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 9px 13px; margin-bottom: 12px; }
.via-card__l { margin: 0; }
.via-card__f { margin: 0; max-width: none; }
.via-select { height: 31px; min-height: 31px; background: var(--brand-soft); border-color: #CCF0E8; color: var(--brand);
  font-weight: 600; font-size: 12.5px; padding: 0 28px 0 10px; }
.lead-found--line { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 13px;
  border-radius: var(--r-island); margin-bottom: 12px; }
.lead-found--line .lead-found__h { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--ink); line-height: 1.35; min-width: 0; }
.lead-found--line .lead-found__h b { color: var(--brand); }
.lead-found__b { display: flex; gap: 6px; flex: none; }
.lead-found__link { border: 1px solid #CCF0E8; background: var(--ground); color: var(--brand); border-radius: 6px; padding: 3px 8px;
  font-size: 11.5px; font-weight: 700; cursor: pointer; font-family: inherit; text-decoration: none; white-space: nowrap; }
.lead-found__link:hover { background: var(--brand); color: #fff; }
.lead-found__link--no { border-color: var(--line); color: var(--muted); font-weight: 500; }
.phone-wrap { position: relative; }
.phone-wrap input { padding-right: 34px; width: 100%; font-weight: 600; background: var(--surface); }
.copy-btn--in { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); }
.copy-btn--in.copied { transform: translateY(-50%) scale(1.1); }
.lookup { margin: -4px 0 8px; }
.ck-grid { gap: 6px; }
.ck-grid label { border-radius: var(--r-field); padding: 6px 9px; font-size: 12px; background: var(--surface); }
.ck-grid label:has(input:checked) { background: #F0FDF9; border-color: #CCF0E8; color: #094F49; font-weight: 600; }
.ck-grid input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--brand); }
.ck-grid--extra { grid-template-columns: 1fr 1fr; }
@media (max-width: 640px) { .ck-grid--extra { grid-template-columns: 1fr; } }
.ck-note input { border-style: dashed; background: #FAFCFC; font-size: 12px; min-height: 31px; }
.cols--intake { grid-template-columns: 1fr 380px; }
@media (max-width: 899px) { .cols--intake { grid-template-columns: 1fr; } }
.cols--intake > div > .btn--dashed { margin: 0 0 12px; height: 36px; color: var(--brand); border-color: var(--line-strong); background: var(--ground); }
.form-actions--intake { display: grid; grid-template-columns: 1fr 1.3fr; gap: 8px; margin-top: 4px; }
.form-actions--intake .btn { min-width: 0; height: 42px; font-size: 13px; font-weight: 700; justify-content: center; }
.btn--accept { background: #F0FDF9; border-color: #CCF0E8; color: var(--brand); }
.btn--accept:hover { background: var(--brand-soft); border-color: var(--brand); }
.form-cancel { margin: 8px 0 0; }
.btn--cancel { height: 35px; justify-content: center; color: var(--ink-2); }
@media (max-width: 420px) { .form-actions--intake .btn { flex: none; } }

/* ── Списки: статус меняется в строке, но остаётся цветной плашкой ─────── */
.status-inline { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 4px 0 10px; border-radius: 100px;
  font-size: 12px; font-weight: 600; max-width: 100%; }
.status-inline select { background: transparent; border: 0; color: inherit; font: inherit; font-weight: 600; height: 24px; min-height: 0;
  padding: 0 2px; cursor: pointer; max-width: 100%; }
.status-inline select:focus { outline: none; }
.status-inline__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

/* ── Телефон ─────────────────────────────────────────────────────────── */
@media (max-width: 899px) {
  .cols--card .blk-contact { order: 2; }
  .cols--card .blk-device { order: 3; }
  .cols--card .blk-crew { order: 4; }
  .cols--card .blk-works { order: 5; }
  .cols--card .blk-parts { order: 6; }
  .cols--card .blk-report { order: 7; }
  .cols--card .blk-sum { order: 8; }
  .cols--card .blk-photos { order: 9; }
  .cols--card .blk-feed { order: 10; }
  .cols--card .blk-lead { order: 11; }
  .head-card__actions .act-status { order: 1; flex: 1 1 auto; min-width: 0; }
  .head-card__actions .act-bell { order: 2; }
  .head-card__actions .act-print { order: 3; }
  .head-card__actions .act-delete { order: 4; flex: 1 1 100%; justify-content: flex-end; }
  .terms-form { display: contents; }
}

/* Клиент в карточке: мета-колонка не сжимается, иначе теги наезжают на имя. */
.client-head__n a { overflow-wrap: anywhere; }
.dev-chips__g .chips { justify-content: flex-start; }
/* На телефоне поля устройства и приёма идут по два в ряд — как в файлах заказчика. */
@media (max-width: 560px) {
  .device-card .form-row, .cols--intake .form-row, .cols--card .form-row { grid-template-columns: 1fr 1fr; }
}

/* Загрузка карточки в оверлее: подпись и кольцо, пока идёт запрос. */
.overlay__loading { display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 40vh;
  color: var(--muted); font-size: 13px; }
.overlay__spin { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--line-strong);
  border-top-color: var(--brand); animation: overlay-spin .8s linear infinite; }
@keyframes overlay-spin { to { transform: rotate(360deg); } }
.overlay--busy .overlay__panel { opacity: 1; }
.overlay--busy .overlay__body > :not(.overlay__loading) { opacity: .6; }
/* Пока ответ в пути, карточка не принимает нажатий: на медленной сети
   второй щелчок по другой форме уходил вторым запросом, и побеждал тот
   ответ, что пришёл позже. Для денег это чужая карточка поверх своей. */
.overlay--busy .overlay__body { pointer-events: none; }

/* Готовность: поле даты имеет собственную минимальную ширину, на узком экране
   она распирала сетку и карточка ехала вбок. Колонки сжимаются, на 320 — в столбик. */
.ready-row > * { min-width: 0; }
.ready-row input { min-width: 0; }
.form-row > .field, .add-work__row > .field { min-width: 0; }
/* Порог был 359 и не срабатывал никогда: у телефона заказчика 390 точек.
   В две колонки поле даты и кнопка «Змінити термін» вставали впритык и
   выглядели налезающими друг на друга, а с полем в 16 точек (иначе Safari
   зумит страницу) полная дата со временем в половину экрана уже не влезает.
   На телефоне они идут друг под другом; пустая подпись-распорка над кнопкой
   нужна была, только пока кнопка стояла рядом с полем. */
@media (max-width: 560px) {
  .ready-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .ready-row > .field:last-child .field__label { display: none; }
}
/* Телефон клиента в карточке не переносится на две строки: мета-колонка справа
   ограничена, имя переносится по словам. */
.client-head .phone-row { white-space: nowrap; }
.cl-meta { max-width: 42%; }
.cl-meta .tag--meta { white-space: normal; text-align: center; line-height: 1.2; }

/* ═══════════════════════════════ правки заказчика по ПК-версии, 07.09
   Разбор ПК-версии после принятого телефона: фон страницы на столе белый
   (tokens.css), номер и клиент в списках без подчёркивания и жирнее, модель
   и сумма жирнее, счётчики своим островом, фильтры под кнопкой, строки
   через одну затемнены, «Приймальник» отдельной колонкой, правая колонка
   карточки шире, на приёме «Умови» → «Зовнішній вигляд» → «Комплектація»
   справа, «Додаткова інформація» внизу одной строкой, «Попередня вартість»
   выделена, календарь и выпадающие списки свои, колокольчик — окно поверх. */

/* ── Ширина страницы: списки шире, карточка и приём чуть шире ──────────── */
/* «Остаётся огромное количество пустого места правее» — списки растут до
   1480, карточка и приём до 1340; остальные страницы как были. */
.content--wide { max-width: 1480px; }
.content--card { max-width: 1340px; }

/* ── Счётчики: свой чуть затемнённый остров, цифры жирнее ─────────────── */
@media (min-width: 761px) {
  .counters--box {
    background: var(--island-bg); border: 1px solid var(--island-line); border-radius: var(--r-island);
    padding: 12px; gap: 12px; margin-bottom: 16px;
  }
  .counters--box .cnt { border-radius: 12px; padding: 12px 15px; }
  .counters--box .cnt b { font-weight: 700; font-size: 24px; letter-spacing: -.02em; }
  .counters--box .cnt span { font-size: 12px; margin-top: 3px; }
  /* Оттенок общего количества чуть светлее плашки раздела — как на его скрине. */
  body[data-section="orders"] .counters--box .cnt:first-child {
    background: var(--cnt-first-bg); border-color: var(--cnt-first-line);
  }
}

/* ── Списки: номер и клиент без подчёркивания и жирнее, модель и сумма жирнее,
      строки через одну слегка затемнены ────────────────────────────────── */
.table a.cell-main { color: var(--brand); text-decoration: none; font-weight: 700; }
.table a.cell-main:hover { text-decoration: underline; }
.orders-table .cell-main { font-weight: 500; }
.orders-table .cell-dev, .orders-table .cell-sum { font-weight: 700; color: var(--ink); }
/* Приглушённая «попер.» убрана 22.09 по видео заказчика 21.09: сумма в
   списке теперь всегда обычная чёрная, независимо от того, откуда она
   взялась. Правила .orders-table .cell-sum--est и .cell-est удалены вместе
   с разметкой — мёртвый CSS живёт годами и путает следующего. */
/* :where обнуляет специфичность условий: подсветка выданных и просроченных
   строк объявлена выше и обязана остаться главнее зебры. */
.table-wrap > .table tbody :where(tr:nth-child(even):not(.row--issued):not(.row--overdue)) td { background: var(--row-zebra); }
/* Наведение темнее зебры (17.09 она стала темнее --surface): иначе чётная
   строка под курсором светлела бы, а нечётная — темнела. */
.table-wrap > .table tbody tr:hover td { background: var(--surface-2); }
.table-wrap > .table tbody tr.row--issued:hover td { background: var(--row-issued-bg); }
.table-wrap > .table tbody tr.row--overdue:hover td { background: var(--row-overdue-bg); }

/* ── Поиск и фильтры: поиск шире, остальное под кнопкой «Фільтри» справа от
      него, «Налаштувати колонки» правее ─────────────────────────────────── */
.list-create { margin: 0 0 14px; }
.list-tools { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.list-tools .filters { flex: 1 1 auto; margin: 0; gap: 8px; }
.search-bar { display: flex; align-items: flex-end; gap: 8px; flex: 1 1 auto; }
.search-bar .field { flex: 0 1 380px; min-width: 200px; }
.search-bar input[type="search"] { height: 35px; }
.search-bar .btn { height: 35px; }
.filters__label { display: inline-flex; gap: 6px; }
.filters__label svg { flex: none; }
.filters__n {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 100px; background: var(--sec-fg); color: #fff; font-size: 11px; font-weight: 700;
}
.filters__toggle:checked ~ .list-tools .filters__label { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); }
.filters__toggle:focus-visible ~ .list-tools .filters__label { outline: 2px solid var(--brand); outline-offset: 2px; }
.list-tools .cols-setup { margin: 0; position: relative; }
.list-tools .cols-setup summary { height: 35px; }
.list-tools .cols-setup .card {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; margin: 0;
  width: min(760px, calc(100vw - 40px)); box-shadow: 0 12px 32px rgba(20, 29, 31, .14);
}
.filters__panel {
  display: none; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; padding: 12px; margin: 0 0 12px;
  border: 1px solid var(--island-line); border-radius: 12px; background: var(--island-bg);
}
.filters__toggle:checked ~ .filters__panel { display: grid; }
.filters__panel .field { margin: 0; max-width: none; min-width: 0; }
.filters__panel .field__label { font-size: var(--text-small); margin-bottom: 3px; }
.filters__panel select { height: 35px; background: var(--ground); }
.filters__reset { grid-column: 1 / -1; font-size: 12px; margin: 0; }
@media (max-width: 1100px) { .filters__panel { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) {
  .filters__panel { grid-template-columns: 1fr 1fr; padding: 10px; }
  .list-tools { flex-direction: column; align-items: stretch; }
  .search-bar { flex-wrap: wrap; }
  .search-bar .field { flex: 1 1 100%; }
}

/* ── Карточка заказа: правая колонка (клиент, лента, оплата) шире ──────── */
.cols--card { grid-template-columns: minmax(0, 1fr) 380px; }
@media (max-width: 899px) { .cols--card { grid-template-columns: 1fr; } }
/* Диалог карточки на столе шире прочих. Медиазапрос обязателен: без него это
   правило стоит ниже телефонного блока с width: 100vw и молча его перебивает —
   на телефоне карточка открывалась ровно на 24 точки уже экрана, и справа
   оставалась полоса списка. Заказчик поймал это 08.09. */
@media (min-width: 761px) {
  /* Ширина считается от экрана, а не «сколько влезет». На его ноутбуке
     2736×1824 при масштабе Windows 200% сайту достаётся ≈1368 точек, и
     прежнее min(1200px, 100vw − 24px) занимало 98% ширины: «заказ тянется
     на всю страничку, всё слишком объёмное» (видео 21.09, 15:20). Теперь по
     бокам остаётся видна полоса списка — 76% экрана, но не уже 900 точек
     (иначе на маленьком столе правая колонка карточки в 380 точек съела бы
     всё) и не шире прежних 1200. На 1918 точках стенда ничего не меняется. */
  .overlay { width: min(1200px, max(76vw, 900px), calc(100vw - 24px)); }
}

/* ── Приём ─────────────────────────────────────────────────────────────── */
/* «Попередня вартість» — важный пункт: подпись и поле выделены. */
.field--strong .field__label { color: var(--ink); font-weight: 700; font-size: 11.5px; }
.field--strong input { font-weight: 700; font-size: 14px; border-color: var(--line-strong); background: var(--surface); }
.field--strong input:focus { background: var(--ground); }
.cols__full { grid-column: 1 / -1; min-width: 0; }
/* Комплектация и внешний вид на столе стоят справа под «Умовами»: сначала
   вигляд, потом комплектація, оба в два столбца. Поля остаются полями
   устройства — их переносит intake-скрипт, разметка одна. На телефоне они
   остаются внутри «Пристрою», как в принятом файле заказчика. */
@media (min-width: 900px) { .cols--intake .device-card .dev-check { display: none; } }
.checks-aside { display: grid; gap: 12px; margin-top: 12px; }
.checks-aside__h { margin: 0 0 -4px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 600; }
.checks-aside .dev-check { display: contents; }
.checks-aside .dev-check > .field--wide {
  margin: 0; border: 1px solid var(--line); border-radius: var(--r-island); background: var(--ground);
  padding: 14px 16px; box-shadow: var(--shadow-card);
}
.checks-aside .dev-check > .field--wide:first-child { order: 2; }
.checks-aside .dev-check > .field--wide > .field__label {
  font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2);
  padding-bottom: 9px; margin-bottom: 12px; border-bottom: 1px solid var(--line);
}
.card--extra { margin-top: 0; }
@media (min-width: 900px) {
  .cols--intake .card--extra { margin-top: 0; }
  .ck-grid--extra { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .intake-actions { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
  .intake-actions .form-actions--intake { display: flex; margin: 0; gap: 10px; }
  .intake-actions .form-actions--intake .btn { min-width: 200px; }
  .intake-actions .form-cancel { margin: 0; }
  .intake-actions .btn--cancel { width: auto; border: 0; background: none; color: var(--muted); padding: 0 8px; }
  .intake-actions .btn--cancel:hover { color: var(--ink); }
}

/* ── Свой выпадающий список (select[data-nice]) ────────────────────────── */
/* Родной <select> остаётся в разметке невидимым и несёт значение формы;
   человек видит кнопку и список под ней. Только на столе: на телефоне
   родной список выезжает снизу и удобнее любого своего. */
.nice-host { position: relative; }
.nice-host > select[data-nice] { position: absolute; inset: 0; width: 100%; height: 100%; min-height: 0; opacity: 0; pointer-events: none; margin: 0; z-index: -1; }
.nice__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; min-height: 35px;
  padding: 0 30px 0 11px; border: 1px solid var(--line-strong); border-radius: var(--r-field); background: var(--ground);
  color: var(--ink); font: inherit; font-size: 13px; text-align: left; cursor: pointer; position: relative;
}
.nice__btn::after {
  content: ""; position: absolute; right: 12px; top: 50%; width: 7px; height: 7px;
  border-right: 1.6px solid var(--muted); border-bottom: 1.6px solid var(--muted); transform: translateY(-70%) rotate(45deg);
}
.nice__btn:hover { border-color: var(--ink-2); }
.nice__btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.nice__btn[disabled] { color: var(--muted); background: var(--surface); cursor: default; }
.nice--open .nice__btn { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.nice__v { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nice__drop {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px); max-height: 280px; overflow-y: auto;
  background: var(--ground); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 32px rgba(20, 29, 31, .14); padding: 5px;
}
.nice__i {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; padding: 8px 10px;
  border: 0; border-radius: 8px; background: none; font: inherit; font-size: 13px; color: var(--ink); text-align: left; cursor: pointer;
}
.nice__i:hover, .nice__i--hi { background: var(--surface); }
/* Поиск внутри списка (видео 21.09, 14:38). Появляется сам, когда строк
   больше десяти: «если у кого-то будет 20–30 сотрудников… нажал первые
   буквы имени, фамилии — всё подтянула». Поле липнет к верху, пока список
   прокручивается. */
.nice__find { position: sticky; top: 0; background: var(--ground); padding: 6px; border-bottom: 1px solid var(--line); }
/* Селектор длинный не для красоты, а по весу: общее
   «input:not([type="checkbox"]):not([type="radio"]):not([type="file"])»
   (app.css:1461) весит 0,3,1 и ставит полю min-height: 35px. Один класс
   (0,1,0) и даже два ему проигрывают — поле поиска молча получало размеры
   обычного поля формы. Здесь ровно тот же вес 0,3,1, но ниже по файлу. */
.nice__drop .nice__find input.nice__q {
  width: 100%; height: 30px; min-height: 0; padding: 0 8px; font-size: 13px;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
}
.nice__drop .nice__find input.nice__q:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
.nice__e { padding: 8px 10px; font-size: 13px; color: var(--muted); }
.nice__i--on { color: var(--brand); font-weight: 600; }
.nice__i--on::after { content: "✓"; font-size: 12px; }
/* «Прийнято через» на приёме остаётся плашкой фирменного цвета. */
.via-card__f .nice__btn { min-height: 31px; background: var(--brand-soft); border-color: #CCF0E8; color: var(--brand); font-weight: 600; font-size: 12.5px; }
.via-card__f .nice__btn::after { border-color: var(--brand); }

/* Пункт списка: точка цвета статуса (option[data-dot]) → название → галочка. */
.nice__t { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nice__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.nice__drop .nice__dot[class] { background: currentColor; }
/* Список, вынесенный в верхний слой (select[data-nice="float"]): внутри
   таблицы с прокруткой абсолютный блок резался бы по нижнему краю. */
.nice__drop--float { position: fixed; left: auto; right: auto; top: auto; min-width: 200px; }

/* Статус в строке списка и в шапке карточки (07.09, видео заказчика): после
   «Готово» пункты родного списка наследовали белый цвет плашки и пропадали.
   Родной select теперь невидим, а список — свой; пункты родного на всякий
   случай красятся явно (телефон, клавиатура). */
.status-inline select option, .status-pill select option { color: var(--ink); background: var(--ground); }
.status-inline .nice__btn, .status-pill .nice__btn {
  min-height: 0; height: 24px; width: auto; border: 0; border-radius: 0; background: transparent;
  color: inherit; font-weight: 600; font-size: inherit; padding: 0 18px 0 2px;
}
.status-pill .nice__btn { height: 34px; flex: 1 1 auto; padding-right: 22px; }
.status-inline .nice__btn::after, .status-pill .nice__btn::after { border-color: currentColor; opacity: .75; right: 6px; width: 6px; height: 6px; }
.status-pill .nice__btn::after { right: 8px; }
.status-inline .nice__btn:hover, .status-pill .nice__btn:hover { border-color: transparent; }
.status-inline.nice--open .nice__btn, .status-pill.nice--open .nice__btn { border-color: transparent; box-shadow: none; }
.status-inline.nice--open, .status-pill.nice--open { box-shadow: 0 0 0 3px rgba(0, 0, 0, .07); }
.status-inline:has(.nice__btn) { cursor: pointer; }

/* ── Свой календарь для полей даты и времени ───────────────────────────── */
/* Поле остаётся родным datetime-local: ввод с клавиатуры и прогоны работают
   как прежде, календарь лишь пишет в него значение. Только на столе. */
@media (min-width: 761px) {
  input.dp-input::-webkit-calendar-picker-indicator { display: none; }
  input.dp-input {
    padding-right: 34px; cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'><rect x='2' y='3' width='12' height='11' rx='2' stroke='%236A7A7C' stroke-width='1.3'/><path d='M2 6.5h12M5.5 1.5v3M10.5 1.5v3' stroke='%236A7A7C' stroke-width='1.3' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat; background-position: right 10px center; background-size: 15px 15px;
  }
}
.dp {
  position: fixed; z-index: 90; width: 296px; background: var(--ground); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 16px 40px rgba(20, 29, 31, .18); padding: 12px; font-size: 13px; color: var(--ink);
}
.dp__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.dp__title { font-weight: 700; font-size: 13.5px; }
.dp__nav {
  width: 28px; height: 28px; border: 1px solid var(--line); border-radius: 8px; background: var(--ground); cursor: pointer;
  font: inherit; color: var(--ink-2); display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.dp__nav:hover { background: var(--surface); }
.dp__wd { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.dp__wd span { text-align: center; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 600; padding: 4px 0; }
.dp__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp__d {
  height: 32px; border: 0; border-radius: 8px; background: none; font: inherit; font-size: 13px; color: var(--ink);
  cursor: pointer; font-variant-numeric: tabular-nums; padding: 0;
}
.dp__d:hover { background: var(--surface); }
.dp__d--out { color: var(--muted); opacity: .55; }
.dp__d--today { box-shadow: inset 0 0 0 1px var(--brand); color: var(--brand); font-weight: 700; }
.dp__d--on, .dp__d--on:hover { background: var(--brand); color: #fff; font-weight: 700; }
.dp__time { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.dp__time label { font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); font-weight: 600; }
.dp__time input[type="time"] { width: 96px; min-height: 32px; height: 32px; font-weight: 600; padding: 0 8px; }
.dp__quick { display: flex; gap: 4px; margin-left: auto; }
.dp__q { border: 1px solid var(--line); background: var(--surface); border-radius: 6px; padding: 3px 7px; font: inherit; font-size: 11px; cursor: pointer; color: var(--ink-2); }
.dp__q:hover { border-color: var(--brand); color: var(--brand); }
.dp__foot { display: flex; gap: 8px; margin-top: 10px; }
.dp__foot .btn { height: 30px; font-size: 12px; padding: 0 10px; }
.dp__foot .btn--primary { background: var(--brand); border-color: var(--brand); color: #fff; margin-left: auto; }

/* ── Колокольчик — окно поверх экрана, как в Gincore (скрин 3) ─────────── */
.modal--notify { width: min(540px, calc(100vw - 24px)); }
.modal--notify .modal__card { padding: 18px 20px 18px; }
.modal--notify .notify__row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.modal--notify .ck { margin: 2px 0 12px; font-size: 12.5px; color: var(--ink-2); }
.modal--notify .modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.modal--notify .btn--section { min-width: 120px; }
.notify__hist { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.notify__hist summary {
  cursor: pointer; list-style: none; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  display: flex; align-items: center; gap: 6px;
}
.notify__hist summary::-webkit-details-marker { display: none; }
.notify__hist summary::before {
  content: ""; width: 6px; height: 6px; border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted);
  transform: rotate(-45deg); margin-right: 2px; transition: transform .15s;
}
.notify__hist[open] summary::before { transform: rotate(45deg); }
.nh { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; max-height: 240px; overflow-y: auto; }
.nh__i { padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); font-size: 12.5px; }
.nh__i--new { border-color: #CCF0E8; background: #F0FDF9; }
.nh__h { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; color: var(--muted); margin-bottom: 2px; }
.nh__h b { color: var(--ink); font-weight: 600; }
.nh__t { color: var(--ink-2); overflow-wrap: anywhere; }
.nh__when { font-size: 11px; color: var(--brand); font-weight: 600; margin-top: 2px; }
@media (max-width: 560px) { .modal--notify .notify__row { grid-template-columns: minmax(0, 1fr); } }
/* На столе «Прийняти і друк» первой, как на дизайне; на телефоне порядок
   принятого файла (разметка не меняется). */
@media (min-width: 900px) { .intake-actions .btn--print { order: -1; } }

/* Плашки-галочки в два (и четыре) столбца. Django 5 рендерит список
   галочек вложенными div, а не ul/li, и обёртка занимала одну колонку сетки:
   все плашки стояли в столбик вполовину ширины. Обёртка раскрывается в
   сетку, каждая плашка — её ячейка. */
.ck-grid > div { display: contents; }
.ck-grid > div > div { display: flex; min-width: 0; }
.dp__time input[type="time"]::-webkit-calendar-picker-indicator { display: none; }

/* ═══════════════════════════════ правки заказчика по 08.09
   «С моего ноута всё отлично, но зашёл с другого — слишком большое всё, не
   помещается на экран». Экран у него уже не 1900 точек, а около 1300: то ли
   ноутбук поменьше, то ли масштаб Windows. Всё, что ниже, чинит эту полосу
   от 1000 до 1400 точек и не трогает широкий экран, который он принял. */

/* ── Список заказов: колонки долями, а не точками ──────────────────────── */
/* Восемь колонок дают в сумме 1140 точек. Содержимое страницы на 1363 —
   1121 точка, на 1280 — 1038: таблица не помещалась и уезжала вбок внутри
   .table-wrap, обрезая «Готовність». Документ при этом не ехал, поэтому
   проверка ширин, которая смотрит на scrollWidth документа, молчала.
   Ниже 1400 те же пропорции берутся долями из --col, и таблица всегда ровно
   по месту. !important обязателен: ширина в точках стоит атрибутом style. */
/* Доля приходит атрибутом style на каждом th. Объявление здесь — и запасное
   значение, если атрибута не оказалось, и адрес, по которому проверка стилей
   находит переменную: она сверяет var(--имя) с объявлениями только в
   css-файлах и на переменной из разметки упала бы. */
.orders-table th { --col: auto; }

/* Три колонки с ОГРАНИЧЕННЫМ содержимым держат ширину в точках, остальные
   тянутся долями. Числа замерены, а не прикинуты: «08.09 видано» и чип
   «Терміново» просят 118 точек, «завдаток 500» — 93, подпись «№ / ДАТА» — 104.
   Содержимое этих трёх не бывает длиннее, поэтому им и не нужна доля: пусть
   растягиваются те, где живут длинные названия и имена, они и обрезаются
   многоточием по правилу дизайн-системы.

   Так эта колонка обрезалась: доля макета (8,95%) на узком столе давала ей
   меньше нужного, и печаталось «08.09 вида…», «Терміно…». Прежняя заплатка —
   жёсткие проценты ниже 1250 — чинила лишь часть полосы и вдобавок не
   пересчитывалась под выключенные колонки. Полоса 1401–1509 ломалась и до
   долей, на пиксельных ширинах макета: «Готовність» выходила 104–117 точек
   при нужных 118. Поэтому режим теперь ОДИН на все ширины: два разных режима
   с границей посередине — ровно то место, где дефект и прятался.

   Пол нельзя задать ни через min-width, ни через max(): при
   table-layout: fixed браузер min-width на колонке игнорирует, а max() с
   процентом внутри разрешает по проценту. Проверено прямым замером:
   width: 120px даёт 120, width: max(8.9474%, 120px) даёт 73. */
.orders-table th { width: var(--col) !important; }
.orders-table .col-number { width: 106px !important; }
.orders-table .col-total { width: 124px !important; }
.orders-table .col-ready { width: 120px !important; }

/* Подписи шапки обрезаются так же, как значения. Без этого они вылезали за
   свою ячейку: у .table th стоит white-space: nowrap и не стоит overflow, и
   на планшете «ПРИЙМАЛЬНИК» выносил таблицу вбок на 14 точек внутри обёртки.
   Было с этапа 3, нашлось сплошной перепроверкой 09.09. */
.orders-table th { overflow: hidden; text-overflow: ellipsis; }

/* Правые колонки: подпись над числами тоже справа. Класс ta-r на шапке стоял
   с этапа 3, но был мёртв — .table th { text-align: left } весит больше
   (0,1,1 против 0,1,0), и «СУМА» с «ГОТОВНІСТЮ» стояли слева над правыми
   числами. Здесь вес (0,2,1), правило наконец действует. */
.orders-table th.ta-r { text-align: right; }

/* ── Плотность на узком столе ──────────────────────────────────────────── */
/* Место отыгрывается у хрома, а не у данных: колонка меню уже, поля ячеек
   поджаты. Токенами, а не переписыванием правил, — цифры лежат в tokens.css. */
@media (min-width: 761px) and (max-width: 1400px) {
  :root { --sidebar-w: 160px; --cell-pad-x: 9px; }
  .content { padding-left: 16px; padding-right: 16px; }
  .counters--box { padding: 10px; gap: 10px; }
  .counters--box .cnt { padding: 10px 12px; }
  .counters--box .cnt b { font-size: 21px; }
}

/* Карточка заказа: правая колонка в 380 точек забирает у левой слишком много,
   когда всей ширины 1100. Ужимается она, порядок блоков не меняется. */
@media (min-width: 900px) and (max-width: 1400px) {
  .cols--card { grid-template-columns: minmax(0, 1fr) 320px; }
}

/* Приём на планшете. Схлопывание .cols--form на 999 стоит выше по файлу, а
   безусловное .cols--intake { 1fr 380px } — ниже, и молча его перебивало:
   на 900–999 приём оставался в две колонки вопреки замыслу. Найдено при
   разборе адаптива 08.09, заказчик про это не писал. */
@media (max-width: 999px) {
  .cols--intake { grid-template-columns: 1fr; }
}

/* ── Правый верхний угол карточки ──────────────────────────────────────── */
/* Крестик возврата к списку для полной страницы. В диалоге поверх списка его
   рисует overlay.js, здесь он не выводится — иначе крестика было бы два. */
.head-card__back {
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); border-radius: 50%;
  background: var(--ground); color: var(--ink-2); text-decoration: none;
  font-size: 18px; line-height: 1;
}
.head-card__back:hover { color: var(--ink); background: var(--surface); }

/* Удаление в самом низу карточки. Тихая ссылка на отдельной строке, с
   отбивкой сверху, чтобы не липла к последнему блоку: рядом с ней не должно
   оказаться ничего, что нажимают часто. */
.order-danger { margin: 22px 0 4px; padding-top: 14px; border-top: 1px solid var(--line); text-align: center; }
.order-danger .act-delete { font-size: 12.5px; color: var(--status-red-fg); text-decoration: none; }
.order-danger .act-delete:hover { text-decoration: underline; }

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

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

   Своим блоком проще и надёжнее: на телефоне он встаёт в строку заголовка
   порядком в сетке, ряд действий занимает свою строку целиком, и перекрыть
   ничего нельзя в принципе. */
.head-card__corner { display: flex; align-items: center; gap: 10px; flex: none; }
/* На столе угол уходит вправо, а ряд действий прижимается к нему: у шапки
   стоит space-between, и без этого действия оказались бы посередине. */
.head-card__actions { margin-left: auto; }

/* Перестройка касается ТОЛЬКО шапок с углом — карточки заказа и заявки.
   Сначала правило стояло на всех .head-card подряд, и на приёме кнопка
   «Назад» уехала на свою строку: у неё нет угла, а ряд действий получил
   flex: 1 1 100%. Заказчик прислал скрин через полчаса. */
@media (max-width: 899px) {
  /* Блок заголовка раскрывается, и его заголовок с подписью становятся
     элементами той же сетки. Без этого угол не помещался в первую строку:
     подпись «Прийнято … · Прийнято в СЦ · платний» длинная, она задавала
     блоку минимальную ширину во весь экран и выталкивала угол вниз.
     Теперь строка первая — номер и угол, вторая — подпись во всю ширину,
     третья — ряд действий. */
  .head-card:has(.head-card__corner) { align-items: flex-start; }
  .head-card:has(.head-card__corner) > .head-card__ttl,
  .head-card:has(.head-card__corner) > div:first-child { display: contents; }
  /* Базис 0, а не auto. При flex-wrap: wrap браузер сперва ПЕРЕНОСИТ, и лишь
     потом сжимает то, что осталось на строке: с базисом auto заголовок
     требовал места по своему содержимому, угол не влезал и уезжал вниз, а
     заголовок после переноса растягивался на всю ширину. С нулевым базисом
     оба помещаются в строку, а заголовок занимает остаток. */
  .head-card:has(.head-card__corner) .page-title {
    flex: 1 1 0; min-width: 0; order: 1; margin-bottom: 0;
  }
  .head-card:has(.head-card__corner) .head-card__corner { order: 2; flex: none; }
  .head-card:has(.head-card__corner) .head-card__sub { flex: 1 1 100%; order: 3; }
  .head-card:has(.head-card__corner) .head-card__actions {
    order: 4; flex: 1 1 100%; margin-left: 0;
  }
  /* Строки шапки разъезжались на общий gap: 16px — заказчик заметил, что при
     растянутой шапке «увеличивается интервал между номером заказа и строкой
     принято» (10.09). Между строками хватает шести точек, а воздух перед
     рядом действий возвращается его собственным отступом. Замер: 19..23 -> 9..13. */
  .head-card:has(.head-card__corner) { row-gap: 6px; }
  .head-card:has(.head-card__corner) .head-card__actions { margin-top: 8px; }
}

/* ── Приём: поле готовности в свою строку ──────────────────────────────── */
/* На телефоне поля приёма идут по два в ряд — так в файлах заказчика. Но
   родной datetime-local в Safari до половины экрана не сжимается и не режет
   содержимое: дата с временем вылезала за правый край карточки. В свою
   строку уходит только пара с датой, остальные остаются по две. */
@media (max-width: 560px) {
  .cols--intake .form-row:has(input[type="datetime-local"]),
  .cols--card .form-row:has(input[type="datetime-local"]),
  .device-card .form-row:has(input[type="datetime-local"]) {
    grid-template-columns: 1fr;
  }
}

/* ── Страницы ошибок ───────────────────────────────────────────────────── */
/* Внутри кабинета: не пустой лист с кодом, а тупик, из которого видно выход.
   Снаружи страница ошибки берёт карточку экранов входа и своего CSS не
   требует вовсе. */
.err { max-width: 460px; margin: 6vh auto 0; text-align: center; }
.err__mark {
  width: 44px; height: 44px; margin: 0 auto 14px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--status-amber-bg); color: var(--status-amber-fg);
  font-size: 23px; font-weight: 700;
}
.err__acts { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 18px; }
.err-code { margin-top: 16px; }

/* ── Зум при постановке курсора в поле (iPhone) ────────────────────────── */
/* Раньше здесь поля поднимались до 16 точек: Safari на iPhone увеличивает
   страницу на поле мельче 16 и обратно её не отматывает. Заказчик сразу
   сказал, что стало крупнее, и спросил, как обходится у Gincore. Оказалось —
   мета-вьюпортом: браузеру просто запрещают масштабировать страницу самому,
   и порог перестаёт работать. Правило переехало в base.html и включается
   только на iPhone; размеры полей вернулись к принятым. */

/* ── Родное поле даты на телефоне ──────────────────────────────────────── */
/* iOS рисует input[type="datetime-local"] своим контролом и берёт его ширину
   по содержимому, игнорируя width и min-width. В сетке одна колонка — это
   1fr, то есть minmax(auto, 1fr): колонка не имеет права стать уже своего
   содержимого. Поэтому наружу вылезает не только само поле, а всё, что стоит
   в этой колонке: у заказчика 10.09 за правый край карточки ушли и
   «Готовність», и кнопка «Змінити термін» под ней — ровно на одну величину,
   что и выдаёт распёртую колонку, а не широкое поле.

   Та же беда уже чинилась для формы приёма (секция «Приём: поле готовности в
   свою строку»), но то правило написано для .form-row, а .ready-row и
   .notify__row — другие сетки, и под него не попали. Колонки переведены на
   minmax(0, 1fr) там же, где объявлены.

   Снятие родного вида возвращает полю обычное блочное поведение. Ни настольный
   WebKit, ни Chromium этого дефекта не показывают — он живёт только в Safari на
   самом телефоне, проверить его здесь нечем. Что от снятия вида поле не
   схлопывается, проверено в обоих движках: высота 35 точек до и после. */
@media (max-width: 760px) {
  input[type="date"], input[type="datetime-local"], input[type="time"] {
    -webkit-appearance: none; appearance: none;
    min-width: 0; max-width: 100%;
  }
}
/* Отдельным правилом, а не в общем списке: неизвестный псевдоэлемент
   обнуляет ВЕСЬ список селекторов, а этот знает только WebKit. */
input[type="datetime-local"]::-webkit-date-and-time-value { min-width: 0; }

/* ── Окно «Нова модель» из поля модели, 12.09 ─────────────────────────────
   «+» у модели раньше создавал модель вслепую, а ошибку клал в выпадающий
   список, который закрывался по уходу фокуса на ту же кнопку (заказчик 11.09:
   «нажимаю + — ничего не происходит»). Теперь окно с тремя полями; собирается
   скриптом combo.js, одно на страницу. Уже прочих окон: три поля и две кнопки.
   Медиазапросов ниже нет — ширина уже считается от вьюпорта. */
.modal--new-model { width: min(440px, calc(100vw - 24px)); }
/* У <dialog> браузер ставит color: CanvasText, а color-scheme в проекте не
   задан — в тёмной теме заголовок окна был чёрным на тёмном (контраст 1,1).
   Касается всех окон, включая «Швидку заявку». */
.modal { color: var(--ink); }
.modal--new-model .modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.modal--new-model .field__error { margin: -4px 0 10px; }
.modal--new-model .field[hidden] { display: none; }

/* ═══════════════════════════════════════════ этап 5: склад, 13.09
   Структура и подписи — из макета «Склад і закупівлі» (docs/brand/
   client-stock-page.html), оболочка — нынешняя: островки, цвет раздела,
   плитки на телефоне. Компонентов два новых — вкладки склада и строки
   прихода; остальное продолжает словарь кабинета (.table, .pill, .card).
   Мобильные переопределения — ниже, в конце этой же секции: поздняя
   секция перебивает ранние медиазапросы (ловушка каскада). */

body[data-section="warehouse"] { --sec-bg: var(--sec-warehouse-bg); --sec-fg: var(--sec-warehouse-fg); --sec-line: var(--sec-warehouse-line); }

/* Название позиции без пробелов («ДисплейiPhone17ProMaxOriginal…», артикул
   вместо имени) не переносилось и распирало заголовок карточки и строку
   запчасти в заказе на телефоне вбок. Переносится где угодно. */
body[data-section="warehouse"] .page-title, body[data-section="warehouse"] .head-card__sub,
.item-row__t, .bind-row, .part-need, .parts-msg, .receipt-note { overflow-wrap: anywhere; }
.receipt-doc .finance-row { gap: 12px; }
.receipt-doc .finance-row > span:last-child { min-width: 0; text-align: right; overflow-wrap: anywhere; }

/* ── Вкладки склада ───────────────────────────────────────────────────── */
/* Полоса вкладок листается только вбок (видео 14, 11:38): серая линия — тенью
   внутри полосы, а не границей, и у вкладок нет отступа −1px — иначе у полосы
   был запас в точку по высоте, и iPhone на косом свайпе тянул её вниз. */
.wh-tabs { display: flex; gap: 4px; margin: 0 0 14px; box-shadow: inset 0 -1px 0 var(--line); overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.wh-tabs::-webkit-scrollbar { display: none; }
.wh-tab { display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; margin-bottom: 0; white-space: nowrap;
  color: var(--ink-2); text-decoration: none; font-weight: 500; font-size: 13px; border-bottom: 2px solid transparent; }
.wh-tab:hover { color: var(--ink); }
.wh-tab--on { color: var(--sec-fg); border-bottom-color: var(--sec-fg); font-weight: 600; }
.wh-tab__n { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 100px; background: var(--status-blue-bg); color: var(--status-blue-fg); font-size: 11px; font-weight: 700; }
/* Ноль тоже виден (пункт 1 приёмки: «на последней — число новых запросов»), но тихо. */
.wh-tab__n--zero { background: var(--surface-2); color: var(--muted); font-weight: 600; }

/* ── Остатки ──────────────────────────────────────────────────────────── */
.filters__panel--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Остатки и закупки — колонки фиксированной ширины и обрезка многоточием, как
   в списке заказов: длинное название позиции или поставщика иначе распирало
   таблицу, и на 1024–1440 она уезжала вбок внутри своей обёртки (замер
   check_widths 13.09 на названиях прогона приёмки). */
.stock-table .table, .requests-table .table { table-layout: fixed; }
.stock-table td, .requests-table td { max-width: 0; }
.stock-table th, .requests-table th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stock-table .cell-main, .stock-table .cell-sub,
.requests-table .cell-main, .requests-table .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stock-table .col-name { width: 30%; }
.stock-table .col-sku { width: 13%; }
.stock-table .col-cat { width: 16%; }
.stock-table .col-total { width: 8%; }
.stock-table .col-free { width: 11%; }
.stock-table .col-cost { width: 10%; }
.stock-table .col-supplier { width: 14%; }
.requests-table .col-what { width: 24%; }
.requests-table .col-order { width: 13%; }
.requests-table .col-who { width: 12%; }
.requests-table .col-status { width: 15%; }
.requests-table .col-supplier { width: 12%; }
.requests-table .col-price { width: 8%; }
.requests-table .col-wait { width: 8%; }
.requests-table .col-act { width: 96px; }
.moves-table .table { table-layout: fixed; }
.moves-table td { max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.moves-table th { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.moves-table .cell-main, .moves-table .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.moves-table .mv { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.moves-table .col-date { width: 10%; }
.moves-table .col-kind { width: 15%; }
.moves-table .col-product { width: 23%; }
.moves-table .col-basis { width: 20%; }
.moves-table .col-qty { width: 7%; }
.moves-table .col-price { width: 9%; }
/* «Хто» — имя с фамилией: на 11% «Олександр Ковальчу…» обрезалось. */
.moves-table .col-who { width: 16%; }
.requests-table .status-inline { max-width: 100%; }
.requests-table .status-inline select { min-width: 0; text-overflow: ellipsis; }
.stock-free { font-weight: 700; }
.list-found { margin: 0 0 8px; }
/* Красное в остатках значит одно: свободных нет («Червоний означає рівно
   одне — нема чим працювати», макет). Других красных строк на складе нет. */
.table tr.row--nofree td, .table-wrap > .table tbody tr.row--nofree td { background: var(--row-overdue-bg); }
.table tr.row--nofree .stock-free { color: var(--status-red-fg); }
.tile.row--nofree { background: var(--row-overdue-bg); border-color: var(--row-overdue-line); }
.tile.row--nofree .stock-free b { color: var(--status-red-fg); }

/* Разбивка по филиалам — нажатием на «Усього», а не наведением: на
   телефоне наведения нет (решение И документа приёмки). */
.split { position: relative; display: inline-block; }
.split > summary { list-style: none; cursor: pointer; color: var(--brand); text-decoration: underline dotted; text-underline-offset: 3px; }
.split > summary::-webkit-details-marker { display: none; }
.split__list { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; display: flex; flex-direction: column; gap: 4px;
  min-width: 220px; padding: 9px 11px; background: var(--ground); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(20, 29, 31, .14); text-align: left; white-space: nowrap; font-size: 12px; color: var(--ink-2); }
.split__i b { color: var(--ink); font-weight: 600; }

/* ── Журнал движения ─────────────────────────────────────────────────── */
.filters--moves .field { flex: 0 1 220px; min-width: 150px; }
.filters--moves .field:first-child { flex-basis: 320px; }
.mv { display: inline-block; padding: 1px 8px; border-radius: 100px; font-size: 11.5px; font-weight: 500;
  background: var(--status-gray-bg); color: var(--status-gray-fg); white-space: nowrap; }
.mv--receipt, .mv--return { background: var(--status-green-bg); color: var(--status-green-fg); }
.mv--write_off { background: var(--status-amber-bg); color: var(--status-amber-fg); }
.mv--storno { background: var(--status-red-bg); color: var(--status-red-fg); }
.mv-qty { font-weight: 700; }
.mv-qty--in { color: var(--status-green-fg); }
.mv-qty--out { color: var(--ink); }
.table tr.row--reversed td { color: var(--muted); }
.table tr.row--reversed a.cell-main { text-decoration: line-through; }

/* ── Приход ──────────────────────────────────────────────────────────── */
.rlines-head, .rline, .rlines-total {
  display: grid; grid-template-columns: minmax(0, 1fr) 78px 96px 96px 28px; gap: 8px; align-items: start;
}
.rlines-head { font-size: 11px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  padding: 0 0 6px; border-bottom: 1px solid var(--line); }
.rlines-head span:nth-child(n+2), .rlines-total span:nth-child(n+2) { text-align: right; }
.rline { padding: 9px 0; border-bottom: 1px solid var(--line); }
.rline input { width: 100%; min-width: 0; }
.rline input[name="line_qty"], .rline input[name="line_price"] { text-align: right; }
.rline__pos { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.rline__was { min-height: 15px; }
.rline__unit { width: 100%; }
.rline__was--new { color: var(--sec-fg); }
.rline__sum { text-align: right; font-weight: 600; padding-top: 8px; }
.rline__x { border: 0; background: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; padding: 7px 4px; }
.rline__x:hover { color: var(--status-red-fg); }
.rlines-total { padding: 10px 0 4px; font-weight: 700; }
.rlines-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.notice-caption--top { margin: 0 0 10px; }
.bind-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.bind-list li { padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); font-size: 12.5px; }
.bind-list li b { color: var(--ink); }
.bind-list .small { display: block; margin-top: 2px; }
.bind-row { margin: 0 0 6px; font-size: 13px; }
.receipt-form .card { margin-bottom: 14px; }

/* ── Карточка позиции ────────────────────────────────────────────────── */
/* Свои две колонки, а не .cols--card: у той на телефоне поля идут по два в
   ряд (правило карточки заказа), а формы склада на телефоне — в одну. */
.cols--wh { grid-template-columns: minmax(0, 1fr) 340px; }
.cols--wh > div { min-width: 0; }
.cols--wh .card { margin-bottom: 14px; }
/* В одну колонку раньше, чем карточка заказа: таблицы остатков и движений в
   узкой левой колонке на 900 точках прокручивались внутри себя. */
@media (max-width: 1100px) { .cols--wh { grid-template-columns: minmax(0, 1fr); } }
.who-sees { list-style: none; margin: 0; padding: 0; }
.who-sees li { padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13px; color: var(--ink-2);
  overflow-wrap: anywhere; }
.who-sees li:last-child { border-bottom: 0; }
.table--compact th, .table--compact td { padding-top: 7px; padding-bottom: 7px; }

/* ── Замовлення постачальникам ───────────────────────────────────────── */
.table tr.row--late td:nth-last-child(2) { font-weight: 700; }
.tile--req { grid-template-columns: minmax(0, 1fr) auto; }
.tile--req.row--late { border-color: var(--row-overdue-line); }
.t-act { grid-column: 1 / -1; display: flex; justify-content: flex-end; margin-top: 4px; }
.modal--process { width: min(600px, calc(100vw - 24px)); }
.modal__sub { margin: 2px 0 0; }
.p-msg { margin: 0 0 10px; }
.modal__foot--process { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 6px; }
.modal__foot--process .btn--danger-link { margin-left: auto; }
.btn--danger-link { color: var(--status-red-fg); }
.modal .field__hint { margin-top: 4px; }
.p-new { font-size: inherit; font-weight: 600; cursor: pointer; }
.p-new-note { display: block; margin-top: 3px; color: var(--sec-fg); }
.rline--new .combo__input { border-style: dashed; }

/* ── Запчастини в карточке заказа ────────────────────────────────────── */
.part-row--wait .item-row__t { color: var(--ink-2); }
.part-qty { font-weight: 500; color: var(--muted); }
.part-src { color: var(--ink-2); }
.part-cost { color: var(--muted); }
.part-link { color: var(--brand); font-size: 11px; font-weight: 500; text-decoration: none; cursor: pointer; }
.part-link:hover { text-decoration: underline; }
.part-act { display: inline-block; }
.part-act > summary { list-style: none; display: inline; }
.part-act > summary::-webkit-details-marker { display: none; }
.part-act[open] { display: block; flex: 1 1 100%; }
.part-act__form { display: grid; gap: 6px; margin: 8px 0 4px; padding: 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface); max-width: 360px; }
.part-act__form .field__label { margin: 0; }
.part-act__form select, .part-act__form input { width: 100%; }
.part-act__form .btn { justify-self: start; }
.add-part { padding-top: 10px; border-top: 1px dashed var(--line-strong); }
.add-part .field { margin-bottom: 8px; max-width: none; }
.add-part__row { display: grid; grid-template-columns: 70px minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.add-part__row .field { margin: 0; min-width: 0; }
.add-part__row input, .add-part__row select { width: 100%; min-width: 0; }
.add-part__row:has(> .field:nth-child(2):last-child) { grid-template-columns: 70px minmax(0, 1fr); }
.part-request { margin-top: 10px; }
.part-request > summary { list-style: none; cursor: pointer; justify-content: center; }
.part-request > summary::-webkit-details-marker { display: none; }
.part-request[open] > summary { margin-bottom: 10px; }
.part-request__form .field { max-width: none; margin-bottom: 8px; }
.part-request__form .ck { margin: 8px 0 6px; font-size: 12.5px; }
.part-request__form .btn--section { width: 100%; justify-content: center; height: 36px; }
.status-plate { margin: 0 0 10px; padding: 8px 10px; border-radius: 8px; background: var(--status-amber-bg); color: var(--status-amber-fg);
  font-size: 11.5px; line-height: 1.4; }
.part-request:has(input[name="keep_status"]:checked) .status-plate { display: none; }
/* Одно поле запчасти (13.09, как в Gincore заказчика): поиск и «+» в ряд,
   выбор «зі складу / запит» — в окне после «Додати запчастину». */
.part-pick { display: flex; gap: 6px; align-items: stretch; }
.part-pick .combo { flex: 1 1 auto; min-width: 0; }
.part-pick__new { flex: 0 0 38px; justify-content: center; padding: 0; font-size: 18px; font-weight: 500; }
.part-error { margin: -2px 0 8px; }
.part-choice { width: min(460px, calc(100vw - 24px)); }
.part-choice .modal__title { overflow-wrap: anywhere; }
.part-choice__msg { margin: 4px 0 14px; padding: 9px 11px; border-radius: 8px; background: var(--surface); font-size: 13px; line-height: 1.45; }
.part-choice__else { margin: -8px 0 14px; padding: 7px 11px; border-radius: 8px; background: var(--status-blue-bg); color: var(--status-blue-fg); }
.part-choice__acts { display: grid; gap: 8px; }
.part-choice__acts > .btn, .part-choice__req > .btn { width: 100%; justify-content: center; height: 38px; }
.part-choice__req { display: grid; gap: 6px; padding-top: 4px; }
.part-choice__req .ck { font-size: 12.5px; }
.part-choice__or { margin: 6px 0 0; padding-top: 10px; border-top: 1px dashed var(--line-strong); font-size: 12px; color: var(--muted); }
.part-choice__req .status-plate { margin: 0; }
.part-choice__req:has(input[name="keep_status"]:checked) .status-plate { display: none; }
.part-choice__note { margin: 10px 0 0; }
.part-new .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.part-new .modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.part-new .notice-caption { margin: 0 0 10px; }
/* Нехватка детали — не ошибка, а подсказка над готовым запросом (п.13). */
.part-need { margin: 0 0 10px; padding: 8px 10px; border-radius: 8px; background: var(--status-blue-bg); color: var(--status-blue-fg);
  font-size: 12.5px; line-height: 1.4; }
.parts-msg { margin: 0 0 10px; }
.add-work__warranty { margin: 8px 0 0; max-width: none; }
.add-work__warranty select { width: 100%; }

/* ── Телефон: склад ──────────────────────────────────────────────────── */
@media (max-width: 760px) {
  .filters__panel--3 { grid-template-columns: 1fr 1fr; }
  .filters--moves .field, .filters--moves .field:first-child { flex: 1 1 100%; }
  .rlines-head { display: none; }
  .rline { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 28px; grid-template-areas: "pos pos x" "qty price x" "sum sum sum"; }
  .rline__pos { grid-area: pos; }
  .rline input[name="line_qty"] { grid-area: qty; }
  .rline input[name="line_price"] { grid-area: price; }
  .rline__sum { grid-area: sum; padding-top: 0; }
  .rline__x { grid-area: x; }
  .rlines-total { grid-template-columns: 1fr auto; }
  .rlines-total span:empty { display: none; }
  .rlines-total span[data-total-qty] { display: none; }
  .split__list { right: auto; left: 0; }
  .add-part__row { grid-template-columns: 64px minmax(0, 1fr); }
  .add-part__row > .field:nth-child(3) { grid-column: 1 / -1; }
  .modal__foot--process .btn { flex: 1 1 auto; justify-content: center; }
  .modal__foot--process .btn--danger-link { margin-left: 0; flex-basis: 100%; }
}
/* «Останні рухи» карточки позиции: шесть колонок в 360 точек не лезут и
   уезжали вбок внутри обёртки — строка становится карточкой в три ряда. Порог
   выше телефонного: на планшете 768 колонка «Хто» выносила таблицу на 6 точек. */
@media (max-width: 860px) {
  .moves-mini thead { display: none; }
  .moves-mini tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; padding: 8px 12px;
    grid-template-areas: "kind qty" "basis price" "date who"; border-bottom: 1px solid var(--line); }
  .moves-mini tbody tr:last-child { border-bottom: 0; }
  /* height: auto — у ячейки таблицы высота строки (38px), и в блоке длинное
     «надходження №4 · накладна …» наезжало на дату ниже. */
  .table-wrap > .table.moves-mini tbody td { display: block; height: auto; padding: 0; border: 0; min-width: 0; background: transparent; }
  .moves-mini .mv-c-kind { grid-area: kind; }
  .moves-mini .mv-c-qty { grid-area: qty; }
  .moves-mini .mv-c-basis { grid-area: basis; }
  .moves-mini .mv-c-price { grid-area: price; color: var(--muted); }
  .moves-mini .mv-c-date { grid-area: date; color: var(--muted); font-size: 12px; }
  .moves-mini .mv-c-date .cell-sub { display: inline; margin-left: 4px; }
  .moves-mini .mv-c-who { grid-area: who; text-align: right; color: var(--muted); font-size: 12px; }
  .moves-mini td.empty { grid-column: 1 / -1; }
}

/* ═══════════════════════════════════════════ модуль 13.09: штуки, места
   Учёт по штукам, ячейки, места устройств, перемещения, брак и возврат
   поставщику. Словарь прежний — .card, .table, .pill, .modal; новое — только
   то, чего не было: список штук в окне выбора, строка «Куди», кнопка
   перемещения в шапке. Мобильные правила — в конце этой же секции. */

/* Перемещение — под рукой на любой странице (видео 13). */
.topbar__move { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px; border-radius: 100px;
  border: 1px solid var(--line); color: var(--ink-2); text-decoration: none; font-size: 12.5px; font-weight: 500; white-space: nowrap; }
.topbar__move:hover { border-color: var(--line-strong); color: var(--ink); }
.topbar__move--on { background: var(--sec-bg, var(--brand-soft)); border-color: var(--sec-line, var(--line)); color: var(--sec-fg, var(--brand)); }

.wh-tab__n--warn { background: var(--status-amber-bg); color: var(--status-amber-fg); }
.sub-tabs { display: flex; gap: 6px; margin: 0 0 14px; }
.sub-tab { padding: 6px 12px; border: 1px solid var(--line); border-radius: 100px; color: var(--ink-2); text-decoration: none; font-size: 12.5px; font-weight: 500; }
.sub-tab--on { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); font-weight: 600; }

/* Строка «Куди»: список мест и поле для наклейки места рядом. */
.dest-row { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 10px; }
.dest-row .field { max-width: none; min-width: 0; }
.dest-row select, .dest-row input { width: 100%; min-width: 0; }
.transfer-form textarea { width: 100%; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-size: 13px; }
.transfer-form .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.transfer-form .field { max-width: none; }
.transfer-form .btn--section { min-width: 160px; justify-content: center; }

/* Коды штук в строке запчасти заказа и в таблицах. */
.part-codes { font-size: 11px; color: var(--muted); overflow-wrap: anywhere; }
.part-codes .code, .pieces-table .code, a.code { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-size: 12px; color: var(--brand); text-decoration: none; }
.part-codes .code:hover, a.code:hover { text-decoration: underline; }
.part-link--btn { border: 0; background: none; padding: 0; font: inherit; font-size: 11px; font-weight: 500; }

/* Какие штуки взять — в окне «Відвантажити» (самые старые отмечены). */
.part-choice__items { margin: -4px 0 14px; }
.part-choice__items > p { margin: 0 0 6px; }
.piece-list { display: grid; gap: 4px; max-height: 190px; overflow-y: auto; padding: 2px; }
.piece-ck { display: flex; gap: 8px; align-items: center; padding: 6px 9px; border: 1px solid var(--line); border-radius: 8px;
  font-size: 12px; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; cursor: pointer; min-width: 0; }
.piece-ck span { overflow-wrap: anywhere; }
.piece-ck:has(input:checked) { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); }
.piece-ck input { flex: none; accent-color: var(--sec-fg); }

/* «Знаходиться зараз» и окно перемещения устройства. */
.here-plate { overflow-wrap: anywhere; }
.modal--transfer { width: min(520px, calc(100vw - 24px)); }
.modal--transfer .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.modal--transfer select, .modal--transfer textarea { width: 100%; }
.modal--transfer .modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }

/* «Експрес-оприбуткування» — янтарная, как у Gincore заказчика: не основной путь. */
.btn--quick { background: var(--status-amber-bg); border-color: var(--status-amber-fg); color: var(--status-amber-fg); font-weight: 600; }
.btn--quick:hover { background: var(--status-amber-bg); opacity: .9; }
.p-quick-note { margin: 0 0 8px; }

/* Брак и возврат: отметки в строках и кнопки под таблицей. */
.filters--inline { display: flex; gap: 10px; margin: 0 0 12px; }
.filters--inline .field { min-width: 200px; max-width: 280px; }
.col-ck { width: 34px; }
.special-acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 12px 0 6px; }
.special-acts input[type="text"] { flex: 1 1 220px; min-width: 0; }
.special-acts select { flex: 0 1 240px; min-width: 0; }
.special-hist { margin-top: 18px; }
.table tr.row--muted td { color: var(--muted); }

/* Места филиала в настройках: строка — сразу форма правки. */
.places-card { margin-bottom: 14px; }
.place-edit, .place-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.place-edit input[name="name"], .place-add input[name="name"] { flex: 1 1 200px; min-width: 0; }
.place-edit__n { width: 70px; flex: none; }
.place-add { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--line-strong); }

/* Штуки в карточке позиции и прихода. */
.cells-split { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.pieces-table .pill { font-size: 11px; }
.serial-in { width: 100%; min-width: 0; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; }
.serial-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: end; margin-top: 10px; }
.serial-form .field { margin: 0; max-width: none; }
.bulk-move { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--line-strong); }
.bulk-move .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.bulk-move .field { max-width: none; }
.rline__cell { width: 100%; font-size: 12px; }
.plabel-count--total { color: var(--muted); }

.mv--transfer_out, .mv--transfer_in { background: var(--status-blue-bg); color: var(--status-blue-fg); }
.mv--return_to_supplier { background: var(--status-violet-bg, var(--status-blue-bg)); color: var(--status-violet-fg, var(--status-blue-fg)); }
.mv--defect_write_off { background: var(--status-red-bg); color: var(--status-red-fg); }
/* Этап 8: продажа — цветом раздела «Продажі», возврат покупателя — зелёным, как приход. */
.mv--sale { background: var(--sec-sales-bg); color: var(--sec-sales-fg); }
.mv--sale_return { background: var(--status-green-bg); color: var(--status-green-fg); }

/* «Знаходиться зараз» на телефоне — в пол-экрана: «Філія на Подолі / Сейф»
   переносится, а не режется краем поля. */
.here-plate { white-space: normal; line-height: 1.3; min-width: 0; }

@media (max-width: 760px) {
  /* Брак и возврат на телефоне — карточками, как «Останні рухи»: семь колонок
     в 390 точек не лезут. Отметка слева, деталь и код — первой строкой. */
  .special-table thead { display: none; }
  .table-wrap.special-table > .table tbody tr { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 2px 10px;
    padding: 10px 12px; border-bottom: 1px solid var(--line); }
  .table-wrap.special-table > .table tbody td { display: block; height: auto; padding: 0; border: 0; min-width: 0; background: transparent; }
  .special-table td.col-ck { grid-row: 1 / span 4; }
  .special-table td:not(.col-ck) { grid-column: 2 / 4; font-size: 12.5px; }
  .special-table td.ta-r { grid-column: 3; grid-row: 1; }
  .special-table td.empty { grid-column: 1 / -1; }
  .special-table tfoot td:empty { display: none; }
  .topbar__move { padding: 0 9px; }
  .topbar__move-t { display: none; }
  .dest-row, .transfer-form .form-row, .modal--transfer .form-row, .bulk-move .form-row { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .filters--inline .field { min-width: 0; max-width: none; flex: 1 1 100%; }
  .special-acts .btn { flex: 1 1 auto; justify-content: center; }
  .serial-form { grid-template-columns: minmax(0, 1fr); }
}

/* ═══════════════════════════════════════════ мелочи по виду, видео 13.09
   Пятнадцать пунктов заказчика (docs/raw/video13-summary.md). Секция —
   последняя в файле: перебивает ранние правила тех же классов намеренно, а
   мобильные переопределения — в её же конце (ловушка каскада). */

/* 1–3. Карточка заказа: работа и запчасть — в две строки. Цена шире и с
   серой заливкой («меньше белого»), «Додати» — заливкой раздела. */
.add-work__row { grid-template-columns: minmax(0, 1fr) 132px; }
.add-work input[name="price"], .add-part input[name="client_price"] {
  background: var(--surface); border-color: var(--line-strong); font-weight: 600; }
.add-go { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: end; margin-top: 8px; }
.add-go .add-work__warranty { margin: 0; }
.btn--add { height: 35px; padding: 0 16px; justify-content: center; white-space: nowrap;
  background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); font-weight: 600; }
.btn--add:hover { background: var(--sec-fg); border-color: var(--sec-fg); color: #fff; }
.add-part__top { display: grid; grid-template-columns: minmax(0, 1fr) 132px; gap: 8px; align-items: end; margin-bottom: 8px; }
.add-part__top > .field { margin: 0; min-width: 0; }
.add-part__top:not(:has(.add-part__price)) { grid-template-columns: minmax(0, 1fr); }
.add-part__price input { width: 100%; }
.add-part__row--go, .add-part__row.add-part__row--go { grid-template-columns: 70px minmax(0, 1fr) auto; align-items: end; }

/* 4. «Опис виконаних робіт» — свёрнутым, внизу. */
.report-box > summary { list-style: none; cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.report-box > summary::-webkit-details-marker { display: none; }
.report-box > summary .card__title::after { content: " ▾"; color: var(--muted); font-size: 11px; }
.report-box[open] > summary .card__title::after { content: " ▴"; }
.report-box:not([open]) > summary { margin-bottom: 0; border-bottom: 0; padding-bottom: 0; }
.report-box__peek { flex: 1 1 200px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 5–6. «Готовність» и «Додаткова інформація» — с 17.09 в секции «правки по видео 14–15». */
.tag--extra { background: var(--status-amber-bg); color: var(--status-amber-fg); border-color: transparent; font-weight: 600; }

/* 7. «+ Швидка заявка» — нежнее: см. секцию «проверка вида, 14.09». */

/* 8, 11, 12. Плитки над списками — ниже, цифра и подпись в строку, кликаются.
   Выбранная с 14.09 была светло-серой: заказчик просил убрать с неё зелёный,
   пока зелёной была плитка, а не строки. 19.09 он попросил обратное —
   «эту плашечку вернуть цветом, которым она была, ярко-зелёным», а серым
   сделать зебру строк (--row-zebra в tokens.css). Поэтому выбранная плитка
   снова красится цветом раздела: на заказах мятная, в других разделах —
   их цветом. Правило объявлено ДВАЖДЫ (здесь и в конце файла, где оно
   побеждает по каскаду) — править обе копии, иначе фон не изменится. */
@media (min-width: 761px) {
  .counters--box .cnt { display: flex; align-items: baseline; gap: 8px; padding: 9px 14px; }
  .counters--box .cnt b { font-size: 21px; }
  .counters--box .cnt span { margin-top: 0; }
  body[data-section="orders"] .counters--box .cnt:first-child { background: var(--ground); border-color: var(--line); }
  body[data-section="orders"] .counters--box .cnt:first-child b { color: var(--ink); }
}
a.cnt { color: inherit; text-decoration: none; cursor: pointer; }
a.cnt:hover { border-color: var(--line-strong); }
.counters .cnt.cnt--on, body[data-section="orders"] .counters--box .cnt.cnt--on { background: var(--sec-bg); border-color: var(--sec-line); }
.counters .cnt.cnt--on b, body[data-section="orders"] .counters--box .cnt.cnt--on b { color: var(--sec-fg); }

/* 9. Закрыт без заработка — без зелёной подсветки. */
.t-closed { color: var(--muted); }
.table tr.row--closed td { color: var(--ink-2); }

/* 10. Жирный в списке тоньше; приёмщик — обычным. */
.orders-table .cell-dev, .orders-table .cell-sum { font-weight: 600; }
.orders-table .cell-acceptor { font-weight: 400; }
.table a.cell-main { font-weight: 600; }

/* 13. Карточка клиента: основной телефон под именем, плашки не наезжают. */
.head-phone { display: flex; align-items: center; gap: 6px; margin: 4px 0 0; font-size: 14px; font-weight: 600; color: var(--ink); }
.contact-btns--head { margin-bottom: 12px; }
.counters--client { gap: 10px; }

/* 14. «Взяти замовлення» и «Взяти в ремонт» — не чёрные: заливка раздела. */
.take-row { background: var(--sec-bg); color: var(--sec-fg); border: 1px solid var(--sec-line); font-weight: 600; }
.take-row:hover { background: var(--sec-fg); color: #fff; opacity: 1; }
.blk-crew form[action$="/take"] .btn--primary { background: var(--sec-bg); color: var(--sec-fg); border: 1px solid var(--sec-line); }
.blk-crew form[action$="/take"] .btn--primary:hover { background: var(--sec-fg); color: #fff; }

/* 15. Боковое меню: текущий раздел подсвечен, у склада подменю. */
.sidebar__group { display: flex; flex-direction: column; }
.sidebar__sub { display: none; flex-direction: column; gap: 1px; margin: 2px 0 6px 12px; padding-left: 8px; border-left: 1px solid var(--line); }
.sidebar__group:hover .sidebar__sub, .sidebar__group--on .sidebar__sub, .sidebar__group:focus-within .sidebar__sub { display: flex; }
.sidebar__sub a { padding: 5px 10px; border-radius: 8px; color: var(--ink-2); text-decoration: none; font-size: 12.5px; }
.sidebar__sub a:hover { background: var(--surface-2); color: var(--ink); }
.sidebar__sub a.on { color: var(--sec-fg); font-weight: 600; }

/* Телефон: тот же порядок, что на столе — запчасти выше работ, «Опис
   виконаних робіт» после фотографий, в самом конце левой колонки. */
@media (max-width: 899px) {
  .cols--card .blk-parts { order: 5; }
  .cols--card .blk-works { order: 6; }
  .cols--card .blk-sum { order: 7; }
  .cols--card .blk-photos { order: 8; }
  .cols--card .blk-report { order: 9; }
}

@media (max-width: 760px) {
  .add-work__row, .add-part__top { grid-template-columns: minmax(0, 1fr) 110px; }
  .add-part__row--go, .add-part__row.add-part__row--go { grid-template-columns: 58px minmax(0, 1fr) auto; }
  .add-part__row--go > .field:nth-child(3) { grid-column: auto; }
  .btn--add { padding: 0 12px; }
}

/* ═══════════════════════════════════════════ проверка вида, 14.09
   Второй круг перед сдачей склада: замеры на 1440 / 1280 / 1024 / 390 /
   360 / 320 в Chromium и WebKit. Секция последняя перед печатью — перебивает
   ранние правила намеренно (ловушка каскада), мобильное — в её же конце. */

/* Подсказки поиска запчасти — на ширину всей формы, а не узкого поля: на
   телефоне список был 100–170 точек, названия ломались по слову в строку, а
   «вільно N» обрезалось. */
.add-part__top { position: relative; }
.add-part__top .part-pick .combo { position: static; }

/* Моноширинный шрифт убран 16.08 (перечёркнутый ноль Consolas режет глаз
   заказчику) и вернулся с кодами штук. Ровные цифры дают табличные. */
.transfer-form textarea, .part-codes .code, .pieces-table .code, a.code, .piece-ck, .serial-in {
  font-family: inherit; font-variant-numeric: tabular-nums; }

/* «перемістити» не лезет на соседний «Колір»: подпись переносится, кнопка
   встаёт под неё, поля ряда выравниваются по низу. Цвет — из токенов, чтобы
   в тёмной теме это не была ярко-мятная плашка. */
.field__label:has(> .btn-relocate) { flex-wrap: wrap; justify-content: flex-start; row-gap: 3px; }
.form-row:has(.btn-relocate) { align-items: end; }
.btn-relocate { background: var(--status-green-bg); border-color: transparent; color: var(--status-green-fg);
  font-size: 11px; padding: 2px 8px; }
.btn-relocate:hover { background: var(--status-green-fg); border-color: var(--status-green-fg); color: var(--ground); }

/* Список заказов на 1024–1280: «Взяти замовлення» в две строки в той же
   высоте, статус не шире своей ячейки — длинное название обрезается. */
.take-row { height: auto; min-height: 34px; padding: 2px 6px; line-height: 1.15; white-space: normal; font-size: 11.5px; }
.take-row__short { display: none; }
@media (max-width: 1100px) {
  /* На 1024 колонка менеджера — 65 точек: «замовлення» не влезает даже в две
     строки. Короткое «Взяти» — в колонке «Менеджер» и так понятно, что. */
  .take-row__full { display: none; }
  .take-row__short { display: inline; }
  /* Статус в узкой колонке: без точки и с меньшими полями — «В ремонті»
     помещается целиком, длинное обрезается многоточием, а не лезет в соседа. */
  .orders-table .status-inline { padding-left: 8px; gap: 0; }
  .orders-table .status-inline__dot { display: none; }
  .orders-table .status-inline .nice__btn { padding-right: 13px; }
  .orders-table .status-inline .nice__btn::after { right: 3px; }
}
.orders-table .status-inline { max-width: 100%; }
.orders-table .status-inline .nice__btn { min-width: 0; flex: 0 1 auto; overflow: hidden; }
.orders-table .status-inline .nice__v { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Места филиала: поле «Порядок» — 70 точек (общее правило полей растягивало
   его на всю строку, и форма ломалась в три этажа). */
.place-edit input.place-edit__n, .place-add input.place-edit__n { width: 70px; flex: none; }

/* Списки поиска в окнах — в потоке окна, а не поверх: иначе их обрезал край
   окна («Нова позиція», «+ Замовлення постачальнику»). */
.modal .combo { flex-wrap: wrap; }
.modal .combo__drop { position: static; flex: 1 1 100%; order: 10; margin-top: 3px; max-height: 210px; box-shadow: none; }

/* Плитки над заказами: «усього» не зелёная и на телефоне — иначе при
   выбранной другой плитке выбранной казалась она. */
body[data-section="orders"] .counters--box .cnt:first-child { background: var(--ground); border-color: var(--line); }
body[data-section="orders"] .counters--box .cnt:first-child b { color: var(--ink); }
/* Вторая копия правила выбранной плитки — она и побеждает по каскаду.
   Значения обязаны совпадать с копией в секции «8, 11, 12» выше. Цвет цифры
   повторён здесь же: у правила строкой выше вес тот же (0,4,2), и без этой
   копии цифра выбранной «усього» оставалась бы чёрной. */
.counters .cnt.cnt--on, body[data-section="orders"] .counters--box .cnt.cnt--on { background: var(--sec-bg); border-color: var(--sec-line); }
.counters .cnt.cnt--on b, body[data-section="orders"] .counters--box .cnt.cnt--on b { color: var(--sec-fg); }
/* Кроме «прострочено»: выбранная плитка не отменяет красную цифру (раньше
   она у выбранной становилась чёрной, а с цветом раздела стала бы зелёной). */
.counters .cnt.cnt--on b.cnt--warn,
body[data-section="orders"] .counters--box .cnt.cnt--on b.cnt--warn { color: var(--status-red-fg); }

/* Числа справа — и подписи над ними справа. */
.table th.ta-r { text-align: right; }

/* «+ Швидка заявка» — «чуть-чуточку светлее, нежнее» (видео 13, п. 7):
   заливка раздела остаётся, но светлее и спокойнее, из токена. */
body[data-section="leads"] #open-quick { background: var(--sec-leads-quick); border-color: var(--sec-leads-quick); color: #fff; }
body[data-section="leads"] #open-quick:hover { background: var(--sec-fg); border-color: var(--sec-fg); opacity: 1; }

/* Текущий раздел в меню — светло-зелёной плашкой, как в дизайне (видео 13,
   п. 15), в любом разделе. */
.sidebar__link--active { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.sidebar__sub a.on { color: var(--brand); }
/* «Вийти» — кнопка в роли пункта меню: отступ как у пунктов. */
.sidebar__link.btn--link { padding: 7px 10px; height: auto; color: var(--ink-2); }

/* Плитка «Руху товару»: куда ушла деталь, видно целиком. */
.tile .t-wrap { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }

@media (max-width: 899px) {
  /* Карточка поверх списка — та же шапка, что полной страницей: крестик
     окна не отнимает ширину у ряда действий, а встаёт над пустым углом. */
  .overlay__panel .head-card { padding-right: 0; }
  .overlay__panel .head-card:has(.head-card__corner) .head-card__corner { min-width: 34px; min-height: 30px; }
  .overlay__close { margin-bottom: -32px; }
}

@media (max-width: 760px) {
  /* Подсказка запчасти — под названием, а не обрезанной справа. */
  .part-pick .combo__drop .drop__i { flex-direction: column; align-items: flex-start; gap: 1px; }
  .part-pick .drop__h { white-space: normal; }

  /* Брак и возврат: строка-карточка во всю ширину таблицы, сумма — у края. */
  .table-wrap.special-table > .table, .table-wrap.special-table > .table > tbody,
  .table-wrap.special-table > .table > tfoot { display: block; width: 100%; }
  .table-wrap.special-table > .table > tfoot > tr { display: flex; justify-content: space-between; gap: 10px; padding: 10px 12px; }
  .table-wrap.special-table > .table > tfoot td { display: block; height: auto; padding: 0; border: 0; }

  /* Значения в карточках брака и возврата — с подписью: без шапки таблицы
     «Філія на Подолі» и дата стояли без объяснения; пустые «—» не нужны. */
  .special-table td[data-l]::before { content: attr(data-l) ": "; color: var(--muted); }
  .special-table td.td-dash { display: none; }

  /* Штуки прихода и позиции — карточками: код и деталь, серийник во всю
     ширину, где лежит — ниже. Без бокового свайпа. Не сеткой: колонка «auto»
     с длинным названием сжимала колонку кода до нуля, и код налезал на
     название (видео 14, 08:16). Флексом код занимает свою ширину, а что не
     влезло — переносится строкой ниже. */
  .pieces-table thead { display: none; }
  .table-wrap > .pieces-table, .pieces-table > tbody { display: block; width: 100%; }
  .pieces-table > tbody > tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 10px;
    padding: 9px 12px; border-bottom: 1px solid var(--line); }
  .pieces-table > tbody > tr > td { display: block; flex: 0 1 auto; height: auto; padding: 0; border: 0; min-width: 0; white-space: normal; overflow-wrap: anywhere; background: transparent; }
  .pieces-table > tbody > tr > td:nth-child(2) { flex: 1 1 9em; }
  .pieces-table > tbody > tr > td:has(.serial-in), .pieces-table > tbody > tr > td.empty { flex-basis: 100%; }
  .pieces-table > tbody > tr > td.ta-r { margin-left: auto; }

  /* Ссылки в строке запчасти — не мельче 13 точек и с полем для пальца. */
  .part-link, .part-link--btn, .link-remove { font-size: 13px; padding: 4px 2px; }
  .part-codes, .part-codes .code { font-size: 12.5px; }
  .btn-relocate { font-size: 12px; padding: 4px 10px; }
}

/* ─────────────────────────────────────────── печать списков по Ctrl+P
   Лист A4 с полями Chrome — около 760 точек, и телефонные правила выше
   (max-width: 760px, без screen) срабатывали и в печати: списки заказов,
   клиентов и заявок печатались плитками, вместе с меню. В печати — всегда
   таблица, без меню и шапки кабинета. */
/* ═══════════════════════════════════════════ правки по видео 14–15, 17.09
   Карточка заказа по макету заказчика «Без имени.jpg»: «Заміна» уже,
   «Якість» и «Готовність» — одним рядом под моделью; «Додаткова інформація»
   чипами справа от комплектации и вида, галочки — в «Параметри замовлення»
   мелкими плашками в строку. */
.device-card .form-row--repl { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr) minmax(0, 1fr); }
.dev-ready input[type="datetime-local"] { width: 100%; }
.dev-chips--extra { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 12px; align-items: start; }
.dev-chips__col { display: grid; gap: 8px; min-width: 0; }
.dev-chips--extra > .dev-src-toggle { grid-column: 1 / -1; }
.params .ck-grid--line { display: flex; flex-wrap: wrap; gap: 6px; }
.params .ck-grid--line > div, .params .ck-grid--line ul, .params .ck-grid--line li { display: contents; }
.params .ck-grid--line label { font-size: 12px; white-space: nowrap; padding: 4px 9px; }
@media (max-width: 560px) {
  /* На телефоне «Заміна» и «Якість» — по две в ряд, «Готовність» — своей
     строкой: родной datetime-local в Safari не сжимается до полэкрана
     (правило «Приём: поле готовности в свою строку» выше). */
  .device-card .form-row.form-row--repl:has(input[type="datetime-local"]) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .device-card .form-row--repl > .dev-ready { grid-column: 1 / -1; }
  .params .ck-grid--line label { white-space: normal; }
}

/* Фильтры «Надходження» и «Замовлення постачальникам» с периодом (видео 14,
   3:45–4:42): шесть полей в ряд на ПК, по три до 1100, по два на телефоне;
   поле даты — той же высоты, что выбор. «+N» в строке прихода раскрывается
   влево — колонка узкая. */
.filters__panel--dates { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.filters__panel input[type="date"] { height: 35px; width: 100%; background: var(--ground); }
.split--left .split__list { right: auto; left: 0; }
.split--left > summary { display: inline; }
.found-line { margin: -4px 0 10px; }
@media (max-width: 1100px) { .filters__panel--dates { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) { .filters__panel--dates { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* «Замовлення постачальникам» (видео 14, 1:02–1:50): название позиции —
   ссылка, но не жирным цветом бренда рядом с номером ремонта; код штуки в
   подписи; рядом с «Змінити» — значок печати наклейки. */
.requests-table a.cell-main { font-weight: 500; color: inherit; }
.requests-table a.cell-main:hover { color: var(--brand); text-decoration: underline; }
.requests-table .col-what { width: 23%; }
.requests-table .col-wait { width: 7%; }
.requests-table .col-act { width: 136px; }
.requests-table .table__actions { white-space: nowrap; }
.btn--icon { display: inline-flex; align-items: center; justify-content: center; padding-inline: 8px; }
.tile--req .t-act { display: flex; gap: 6px; }

/* «+ Замовлення постачальнику» — строки позиций (видео 14, 5:10–5:48). */
.restock-line { display: grid; grid-template-columns: minmax(0, 1fr) 96px; gap: 0 10px; align-items: start; }
.restock-line + .restock-line { padding-top: 8px; border-top: 1px dashed var(--line); }
.restock-line__pick { display: flex; gap: 6px; align-items: stretch; }
.restock-line__pick .combo { flex: 1 1 auto; min-width: 0; }
.part-pick__new.is-on { background: var(--sec-bg); border-color: var(--sec-line); color: var(--sec-fg); }

/* Карточка штуки окном поверх заказа (видео 15, 0:03). */
.modal--piece { width: min(760px, calc(100vw - 24px)); }
.modal--piece .modal__card { position: relative; max-height: calc(100vh - 48px); overflow: auto; }
.modal--piece .modal__close { position: absolute; top: 12px; right: 12px; z-index: 2; }
.modal--piece .head-card { padding-right: 36px; }
.modal--piece .cols--wh, .modal--piece .cols { grid-template-columns: minmax(0, 1fr); }

/* «Прийняти і друк» — ссылка на документ, если вкладку не открыли (видео 14, 10:09). */
.print-now { margin: 0 0 10px; }
/* Девятая вкладка склада «Налаштування» (видео 14, 6:10): ряд на 1440 уже не
   вмещался на 3 точки — поля вкладок чуть уже. */
.wh-tab { padding-inline: 11px; }

/* Категорія і модель нової позиції у вікнах складу (просьба заказчика 17.09). */
.new-fields { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 8px; margin-top: 6px; }
.rline__cat, .rline__model { margin-top: 6px; }
.rline__model .combo__input { width: 100%; }

/* Период одним полем и панель на два месяца (видео заказчика 21.09, 13:00:
   «нужны календарики везде именно в таком виде, чтобы он не разделялся на
   два»). Поле занимает две клетки панели фильтров: «03.09.2026 – 10.09.2026»
   в одну не помещается. */
.dates-range { grid-column: span 2; }
.dates-range .range__f { width: 100%; font-variant-numeric: tabular-nums; }
.dp__hint { margin: 0 10px 8px; font-size: 11.5px; color: var(--muted); }
.dp__d--in { background: var(--sec-bg); color: var(--sec-fg); border-radius: 0; }
.dp2 { width: auto; }
.dp2__b { display: flex; gap: 14px; }
.dp2__m { width: 272px; }
.dp2__h { text-align: center; font-weight: 700; font-size: 13.5px; margin-bottom: 8px; }
.dp2__nav { display: flex; justify-content: space-between; margin-bottom: 4px; }
/* Один месяц там, где два не влезают: на 390 точках панель иначе уезжает
   за край экрана. Граница та же, что в daterange.js. */
@media (max-width: 619px) {
  .dp2 { width: calc(100vw - 16px); max-width: 320px; }
  .dp2__m { width: 100%; }
  .dates-range { grid-column: 1 / -1; }
}

@media print {
  .sidebar, .topbar, .scrim, .tiles { display: none !important; }
  .orders-table, .table-wrap.hide-phone { display: block !important; }
  th.hide-phone, td.hide-phone { display: table-cell !important; }
  .table-wrap { overflow: visible !important; }
}

/* ═══════════════════════════════════════════ этап 6: касса, оплаты и отчёты, 18.09
   Структура и подписи — из макета «Гроші» (docs/brand/client-money-page.html),
   оболочка — нынешняя: островки, цвет раздела, плитки на телефоне. Цвет
   раздела — body[data-section="cash"] выше, рядом с остальными разделами;
   токены — в tokens.css. Каждая ветка этапа пишет только внутрь своей
   подсекции ниже; мобильные переопределения — в конце своей подсекции,
   медиазапросы с screen, иначе они срабатывают в печати (ловушка каскада:
   поздняя секция перебивает ранние медиазапросы той же специфичности). */

/* ── этап 6: каса — картка замовлення ─────────────────────────────────── */
/* Блок «Сума та оплата» в обоих режимах карточки, окна «Прийняти оплату»,
   «Повернути клієнту», выбор при закрытии, история оплат; колонка «Сума»
   списка и плитка на телефоне. .finance-row не переименовывать — его
   переиспользуют warehouse/product.html и warehouse/receipt.html. */

/* Суммы — всегда одной шириной цифры: столбик «Роботи / Запчастини / Разом»
   и история оплат читаются вертикально, а не пересчитываются глазом. */
.blk-sum, .pay-list, .pay-totals, .modal--pay, .modal--refund, .modal--status { font-variant-numeric: tabular-nums; }

/* Строка «Знижка», когда она не действует (сумма вписана вручную или взята
   из предварительной): цифра приглушена, под строкой — почему. */
.finance-row--off .num { color: var(--muted); }
.finance-hint { margin: -2px 0 4px; font-size: 11px; color: var(--muted); line-height: 1.35; }

/* «Разом 1 500,00 · вручну» и под ним мелко «за розрахунком 1 400,00 ·
   повернути»: калькулятор остаётся подсказкой, а не спорит с суммой. */
.sum-manual { font-weight: 500; font-size: 11.5px; color: var(--muted); }
.finance-calc { display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap;
  margin: -3px 0 4px; font-size: 11px; color: var(--muted); }
.finance-calc__f { display: inline; margin: 0; }
.btn-text { border: 0; background: none; padding: 0; font: inherit; color: var(--brand);
  cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.btn-text:hover { color: var(--ink); }

/* Плашка «До сплати» с карандашом. Правка открывается прямо в ней: заказчик
   31.08 — «поле до сплаты можно легко менять», без «Змінити вартість». */
.due-banner__r { display: inline-flex; align-items: center; gap: 8px; }
.due-banner__note { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.due-banner--state { justify-content: center; }
.due-banner--state .due-banner__v { font-size: 15px; }
.due-pencil { border: 0; background: none; padding: 2px; line-height: 0; color: var(--muted); cursor: pointer; }
.due-pencil:hover { color: var(--brand); }
.due-state { margin: -6px 0 10px; font-size: 12px; color: var(--muted); }

.due-edit { margin: 10px 0 12px; padding: 10px 12px; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-field); }
.due-edit__row { display: flex; gap: 6px; align-items: center; }
.due-edit__row input { flex: 1 1 0; min-width: 0; font-weight: 700; }
.due-edit .field__error { margin-top: 6px; }
.due-edit__whole { margin-top: 8px; font-size: 11.5px; }

/* «борг N» — янтарным, рядом с заголовком блока, а не в шапке карточки: у
   меню «Друк» на 761–899 нулевой запас (§14). */
.money-debt { font-weight: 600; }
.money-warning { margin: 8px 0 0; padding: 8px 10px; border-radius: var(--r-field);
  background: var(--status-amber-bg); color: var(--status-amber-fg); font-size: 12px; }
.money-actions { display: grid; gap: 8px; margin-top: 12px; }
.btn--refund { width: 100%; justify-content: center; }

/* История оплат: дата·тип·спосіб / сума / хто·коментар. Отменённая строка
   перечёркнута и остаётся — «Скасування» стоит рядом своей строкой. */
.pay-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.pay-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1px 10px;
  padding-bottom: 7px; border-bottom: 1px solid var(--line); font-size: 11.5px; }
.pay-row:last-child { border-bottom: 0; padding-bottom: 0; }
.pay-row__what { color: var(--ink-2); font-weight: 500; }
.pay-row__sum { justify-self: end; font-weight: 700; }
.pay-row__sum--in { color: var(--status-green-fg); }
.pay-row__sum--out { color: var(--status-red-fg); }
.pay-row__who { grid-column: 1 / 2; color: var(--muted); overflow-wrap: anywhere; }
.pay-row__old { font-style: italic; }
.pay-row__x { justify-self: end; font-size: 11px; }
.pay-row--void { opacity: .6; }
.pay-row--void .pay-row__what, .pay-row--void .pay-row__sum { text-decoration: line-through; }

/* Три цифры над полем суммы в окне оплаты: «приймальник має дивитися на цю
   цифру, щоб не натворити дурниць» (видео 1). */
.pay-totals { display: grid; gap: 4px; margin-bottom: 14px; }
.pay-totals > div { display: flex; justify-content: space-between; gap: 20px; }
.pay-totals span { color: var(--muted); font-size: 12.5px; }
.pay-totals b { font-weight: 500; }
.pay-totals__due { padding-top: 6px; border-top: 1px solid var(--line); }
.pay-totals__due span { color: var(--ink-2); font-weight: 600; }
.pay-totals__due b { font-size: 16px; font-weight: 700; }

/* Ошибка — внутри окна, там, куда смотрит человек (урок 14.09). */
.modal__error { margin: 0 0 12px; padding: 8px 10px; border-radius: var(--r-field);
  background: var(--status-red-bg); color: var(--status-red-fg); font-size: 12.5px; }
.modal--pay, .modal--refund, .modal--status { width: min(520px, calc(100vw - 24px)); }
.modal--pay .form-row, .modal--refund .form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.modal--pay input[type="text"], .modal--pay select,
.modal--refund input[type="text"], .modal--status input[type="text"] { width: 100%; }
.modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.modal__foot--pay, .modal__foot--status { justify-content: flex-start; }
.modal__foot--pay .btn--link, .modal__foot--status .btn--link { margin-left: auto; }
.pay-debt { margin: 8px 0 0; font-size: 12.5px; font-weight: 600; color: var(--status-amber-fg); }
.status-ask { margin: 0 0 12px; font-size: 13.5px; font-weight: 600; color: var(--ink); }
/* Галка в окнах денег — не про срочность: красный тут ничего не значит. */
.ck--pay:has(input:checked) { background: var(--brand-soft); border-color: var(--brand);
  color: var(--brand); font-weight: 600; }

/* Отказ удаления — у самой кнопки, крупнее обычной ошибки поля. */
.delete-error { margin: 0 0 10px; font-size: 13px; font-weight: 600; }

/* Подпись слева от сегментов («Спосіб»): в app.css был .seg-row без неё. */
.seg-lbl { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
/* Способ оплаты — три значения, и все три видны сразу, в том числе на
   телефоне: список стоил бы лишний клик в самой частой операции дня (§7).
   Общее правило .seg-row .seg на 760 прячет сегменты под кнопку «seg-pick» —
   там их шесть, здесь три, поэтому свой класс и своя ширина. */
.seg-row--pay .seg { display: inline-flex; }

/* Завдаток на приёме: сумма, спосіб сегментами, коментар одним блоком. */
.advance { margin-bottom: 4px; }
.advance .seg-row { margin-bottom: 10px; }

/* Лента: оплата, возврат и отмена видны среди прочих событий. */
.ev--money .ev__x { font-weight: 500; }

/* Колонка «Сума» списка и плитка: «борг N» янтарным, «повернути N» и
   «сплачено N» под главной цифрой. На телефоне «сплачено» не показывается —
   лишний ряд, плитка перестаёт быть ровной (видео 21.09). */
.orders-table .cell-sum, .tiles .t-sum { font-variant-numeric: tabular-nums; }
.cell-debt { color: var(--status-amber-fg); font-weight: 600; }
.cell-refund { color: var(--brand); font-weight: 600; }
.tiles .t-sum { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.t-money { font-size: 11px; font-weight: 500; color: var(--muted); }

/* Телефон: окна на всю ширину, кнопки внизу и во всю ширину — палец попадает
   в кнопку, а не мимо. Медиазапрос со screen: без него он срабатывает в
   печати (Ctrl+P печатал плитки). */
@media screen and (max-width: 560px) {
  /* Окно на всю ширину и на весь экран: у диалога свои поля от браузера, и
     без обнуления карточка вылезала за его край — кнопки уходили под обрез. */
  .modal--pay, .modal--refund, .modal--status {
    width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh;
    margin: 0; inset: 0;
  }
  .modal--pay .modal__card, .modal--refund .modal__card, .modal--status .modal__card {
    border-radius: 0; border-left: 0; border-right: 0; min-height: 100%; max-height: 100%;
    display: flex; flex-direction: column;
  }
  .modal--pay .form-row, .modal--refund .form-row { grid-template-columns: minmax(0, 1fr); }
  .modal--pay .modal__foot, .modal--refund .modal__foot, .modal--status .modal__foot {
    margin-top: auto; padding-top: 12px; flex-direction: column-reverse; align-items: stretch;
  }
  .modal--pay .modal__foot .btn, .modal--refund .modal__foot .btn, .modal--status .modal__foot .btn {
    width: 100%; justify-content: center;
  }
  .modal__foot--pay .btn--link, .modal__foot--status .btn--link { margin-left: 0; }
  .seg { width: 100%; }
  .seg__i { flex: 1 1 0; }
  .seg__i span { width: 100%; justify-content: center; padding: 0 6px; }
  .due-edit__row { flex-wrap: wrap; }
  .due-edit__row input { flex: 1 1 100%; }
  .pay-row { grid-template-columns: minmax(0, 1fr) auto; }
}


/* ─────────────────────────────────────────────────────────────────────── */
/*                                                                         */
/* ─────────────────────────────────────────────────────────────────────── */

/* ── этап 6: каса — журнал каси ───────────────────────────────────────── */
/* Счётчики, фильтры, таблица журнала, подвал по способам и кассам филиалов,
   окна «Внести до каси» / «Видати з каси», плитки на телефоне. */

/* Кнопки шапки: «Внести до каси», «Видати з каси», «Вивантажити». «Прийняти
   оплату» здесь нет намеренно — решение Щ документа приёмки. */
.cash-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
/* Кнопки кассы для телефона: на столе их не видно, там тот же набор стоит в
   шапке страницы (видео 21.09, 4:35). Блок объявлен здесь, рядом с .cash-actions,
   а показывается в телефонном разделе ниже — иначе поздний @media перебил бы
   это правило по порядку. */
.cash-actions--phone { display: none; }

/* Деньги: пришло зелёным с плюсом, ушло красным с настоящим минусом. Красный
   в кассе — сознательное исключение из правила «красный = сорванный срок»
   (§7 промта): он стоит только здесь и в истории оплат карточки. */
.cash-in { color: var(--status-green-fg); }
.cash-out { color: var(--status-red-fg); }
.cash-sum { white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 600; }

/* Подсказка под «Готівка в касі», когда остаток ушёл ниже нуля: работу это не
   блокирует — данные могли не внести (решение М). */
.cnt__hint { display: block; font-size: 11.5px; color: var(--status-red-fg); margin-top: 2px; }

/* Журнал: суммы одной вертикалью, колонки — по смыслу, а не поровну.
   table-layout остаётся авто: с fixed min-width колонок игнорируется. */
.cash-table .table { font-variant-numeric: tabular-nums; }
.cash-table .col-when { width: 84px; }
.cash-table .col-kind { width: 136px; }
.cash-table .col-method { width: 98px; }
.cash-table .col-order { width: 96px; }
.cash-table .col-article { width: 158px; }
.cash-table .col-who { width: 132px; }
.cash-table .col-sum { width: 116px; }
.cash-table .col-act { width: 104px; }
.cash-comment { display: block; overflow-wrap: anywhere; }
/* «Пристрій» своей колонкой — видео 02.10, 08:55: «у нас устройство длинное,
   много символов, она пишет его в два ряда… можем добавить ещё один столбик —
   замовлення, номер замовлення, пристрій». Название в одну строку с
   многоточием, полное — в подсказке (title в разметке).
   Ширина — долей, поровну с «Коментарем», а не точками. Замерено 03.10 на
   его 1368 точках: при 220px всё свободное место уходило устройству, а
   «Коментар» сжимался до 80 точек и рвал «Початковий залишок» посреди слова;
   строка с длинным комментарием вырастала до 240 точек. По 14% у обоих —
   164 и 164 на 1368, 201 и 201 на 1920; на 1024 таблица по-прежнему по месту.
   max-width: 0 у ячейки — то, что даёт многоточию сработать в авто-раскладке:
   без него ячейка растягивается под всю строку. «Замовлення» уже: в ней
   остался один номер (было 124), ширину держит подпись шапки. */
.cash-table .col-device { width: 14%; }
.cash-table .col-comment { width: 14%; }
.cash-table td.col-device { max-width: 0; }
.cash-table .col-device .cell-main { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Узкий стол, 761–1180. Десять колонок даже по минимуму содержимого просят
   938 точек, а на 1024 у таблицы их 830: она прокручивалась внутри обёртки
   (замер 03.10; без «Пристрою» было 862 — тоже не помещалось, пилюля «Оплата
   постачальнику» этапа 7 одна держит 155). Здесь поля ячеек уже, подписи
   шапки без разрядки, а длинный тип операции и устройство переносятся: в
   колонке в 70 точек «Apple i…» ничего не говорит, две строки — говорят.
   Граница 1180, а не 1100: на 1101–1150 таблица тоже не помещалась.
   Со screen — иначе правило подхватит печать. */
@media screen and (min-width: 761px) and (max-width: 1180px) {
  .cash-table .table th, .cash-table .table td { padding-left: 6px; padding-right: 6px; }
  .cash-table .table th { letter-spacing: 0; }
  .cash-table .col-kind .pill { white-space: normal; }
  .cash-table .col-device .cell-main { white-space: normal; overflow: visible; }
  /* «Каси філій» в подвале на 1024 выезжала из своей обёртки на 1 точку
     («Філія на Хрещатику» и четыре суммы в половине ширины) — нашла
     tools/check_widths.py 03.10, так было и до правок этого дня. */
  .cash-foot .table th, .cash-foot .table td { padding-left: 8px; padding-right: 8px; }
}
/* Отменённая операция перечёркнута — обе строки остаются (решение К). */
.cash-table tr.row--reversed .cash-sum, .tile--cash.row--reversed .cash-sum { text-decoration: line-through; }

/* Подвал: «Підсумок за способом оплати» и «Каси філій» рядом, как в макете. */
.cash-foot { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 14px; margin-top: 14px; }
.cash-foot .card { margin: 0; }
.cash-foot .table-wrap { margin-top: 8px; }
.cash-total-table { font-variant-numeric: tabular-nums; }
.cash-total-table tfoot td {
  border-top: 1px solid var(--line-strong); border-bottom: 0;
  font-weight: 700; padding: var(--cell-pad-y) var(--cell-pad-x);
}
.cash-total-table tbody tr.cash-row--on td { background: var(--sec-bg); }

/* Окна «Внести до каси» / «Видати з каси» / «Скасувати операцію». */
.modal--cash-move { width: min(520px, calc(100vw - 24px)); }
.modal--cash-move .modal__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.modal--cash-move select, .modal--cash-move input[type="text"] { width: 100%; }
.modal--cash-move .seg { width: 100%; }
.modal--cash-move .seg__i { flex: 1 1 0; }
.modal--cash-move .seg__i span { width: 100%; justify-content: center; }
.modal--cash-move .field[hidden] { display: none; }
.modal--cash-move .message { margin-bottom: 12px; }

/* «Налаштування → Статті»: заголовок вида и «Додати статтю» одной строкой над
   своей таблицей, между видами — воздух. */
.articles-group { align-items: center; margin: 0 0 8px; }
/* Воздух нужен только там, где заголовок вида идёт следом за таблицей
   предыдущего: у первого над ним и так подзаголовок страницы. */
.table-wrap + .articles-group { margin-top: 22px; }

/* Телефон: журнал плитками, счётчики в две колонки, окна на всю ширину с
   кнопками внизу. Медиазапросы с screen — иначе они срабатывают в печати. */
@media screen and (max-width: 760px) {
  .cash-actions { width: 100%; justify-content: stretch; }
  /* Двумя классами, а не одним: общее «.hide-phone { display: none }» стоит
     выше по файлу, чем «.cash-actions { display: flex }», и по весу
     проигрывало ему — кнопки оставались и в шапке, и под плитками. Та же
     ловушка каскада, что с кнопкой оплаты (§14). */
  .cash-actions.hide-phone { display: none; }
  .cash-actions--phone { display: flex; margin: 10px 0 12px; }
  /* «Вивантажити» под списком операций — одной кнопкой во всю ширину. */
  .cash-actions--after { margin: 12px 0 0; }
  .cash-actions .btn { flex: 1 1 auto; justify-content: center; }
  .counters--cash { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; overflow: visible; }
  .counters--cash .cnt { display: block; flex: none; padding: 9px 11px; }
  .counters--cash .cnt b { font-size: 17px; }
  .tile--cash { grid-template-columns: minmax(0, 1fr) auto; }
  .tile--cash .pill { margin-left: 6px; }
  .tile--cash .t-wide { grid-column: 1 / -1; }
  .cash-foot { grid-template-columns: minmax(0, 1fr); }
  /* Четыре колонки подвала на 390 не влезают: ячейки уже, а если и так мало —
     таблица прокручивается внутри своей обёртки, страница остаётся на месте. */
  .cash-foot .table th, .cash-foot .table td { padding-inline: 8px; }
  .modal--cash-move { width: calc(100vw - 16px); }
  .modal--cash-move .modal__card { max-height: calc(100vh - 24px); }
  .modal--cash-move .form-row { grid-template-columns: 1fr; }
  .modal--cash-move .modal__foot { flex-direction: column-reverse; }
  .modal--cash-move .modal__foot .btn { width: 100%; justify-content: center; height: 40px; }
}

/* Печать журнала: таблица таблицей, без кнопок, фильтров и страниц. */
@media print {
  .cash-actions, .cash-table .col-act, .list-tools, .filters__panel, .pager { display: none !important; }
  .cash-table.table-wrap { overflow: visible !important; box-shadow: none; }
  .cash-foot { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* Ряд разделов кассы (видео 02.10, п. 19) на бумаге не нужен: по нему не
     щёлкнуть, а высоту листа он съедает. Внутренний ряд настроек — тоже, и
     ряд склада, который печатался с этапа 5. */
  .wh-tabs, .sub-tabs { display: none !important; }
  /* На бумаге наведения нет — название устройства печатается целиком, в
     несколько строк, а не обрезанным. */
  .cash-table td.col-device { max-width: none; }
  .cash-table .col-device .cell-main { white-space: normal; overflow: visible; }
  /* Журнал печатается альбомным листом. Посчитано 03.10, Chromium, A4 с
     полями по умолчанию: книжный лист даёт 718 точек, а девять печатных
     колонок журнала даже по минимуму содержимого просят 906 (без «Пристрою»
     было 824 — книжный не помещал журнал и до 02.10). Браузер в таком случае
     ужимает весь лист примерно до 79%: шрифт мельче, «Коментар» рвётся по
     слову в строку, строка с длинным комментарием — до 300 точек. Альбомный
     даёт 1047 точек — журнал помещается в натуральную величину. Именованная
     страница, а не общее @page: остальные печатные формы кабинета остаются
     книжными. */
  body:has(.cash-table) { page: cash-journal; }
}
@page cash-journal { size: A4 landscape; }


/* ─────────────────────────────────────────────────────────────────────── */
/*                                                                         */
/* ─────────────────────────────────────────────────────────────────────── */

/* ── этап 6: каса — звіти ─────────────────────────────────────────────── */
/* Четыре цифры, график SVG с сервера, таблицы мастеров, способов, филиалов,
   блок «Закриті замовлення». */

/* Шапка: заголовок слева, «Вивантажити в Excel» справа, как в макете. */
.rep-head { align-items: center; margin-bottom: 4px; }
.rep-head .page-subtitle { margin-bottom: 18px; }
.rep-export { white-space: nowrap; }

/* Фильтры отчёта всегда раскрыты: их четыре, прятать под кнопку нечего. */
.rep-filters {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px;
  padding: 12px; margin: 0 0 14px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--ground); box-shadow: var(--island-shadow);
}
.rep-filters .field { margin: 0; max-width: none; min-width: 0; }
.rep-filters .field__label { font-size: var(--text-small); margin-bottom: 3px; }
.rep-filters select,
.rep-filters input[type="date"] { height: 35px; width: 100%; background: var(--ground); }
/* Пара дат занимает две колонки сетки — иначе поля вдвое уже остальных. */
.rep-filters .dates-range { grid-column: span 2; }
.rep-filters__reset { grid-column: 1 / -1; font-size: 12px; margin: 0; }

/* Четыре цифры одной полосой без заливок: «шесть плиток, залитых цветом» —
   это то, что раздражало заказчика в RemOnline (заметки макета). Первый
   островок в цвете раздела, как на остальных экранах продукта. */
.rep-kpis {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px;
  margin: 0 0 10px;
}
.rep-kpis--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rep-kpi {
  padding: 12px 14px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--ground); box-shadow: var(--island-shadow);
}
.rep-kpi--lead { background: var(--sec-bg); border-color: var(--sec-line); }
.rep-kpi__v {
  display: block; font-size: 23px; font-weight: 600; line-height: 1.25;
  font-variant-numeric: tabular-nums; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Копейки мельче: цифра читается целым числом, но остаётся точной. */
.rep-kpi__v small { font-size: 14px; font-weight: 500; color: var(--ink-2); }
.rep-kpi--lead .rep-kpi__v { color: var(--sec-fg); }
.rep-kpi--lead .rep-kpi__v small { color: var(--sec-fg); opacity: .8; }
.rep-kpi__t { display: block; font-size: var(--text-small); color: var(--muted); margin-top: 2px; }
.rep-kpi__cmp {
  display: block; font-style: normal; font-size: var(--text-small);
  color: var(--muted); margin-top: 6px;
}
.rep-delta { font-weight: 600; }
.rep-delta--up { color: var(--status-green-fg); }
.rep-delta--down { color: var(--status-red-fg); }

.rep-lines { margin: 0 0 14px; }
.rep-line { margin: 0 0 3px; font-size: var(--text-subtitle); color: var(--ink-2); }
.rep-line .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.rep-line--muted { color: var(--muted); }

/* График: одноцветные столбцы, сетка волосяная, подпись только у пика. */
.rep-chart { margin-bottom: 14px; }
.rep-chart__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rep-chart__svg { display: block; width: 100%; height: auto; max-width: 100%; }
/* Много столбцов — график не сжимается, а прокручивается своей полосой. */
.rep-chart__svg--wide { width: auto; max-width: none; }
.rep-chart__bar { fill: var(--sec-fg); }
.rep-chart__grid { stroke: var(--line); stroke-width: 1; }
.rep-chart__tick, .rep-chart__day { font-size: 10.5px; fill: var(--muted); }
.rep-chart__peak { font-size: 11px; font-weight: 600; fill: var(--ink); }
/* Прозрачная мишень во всю высоту столбца: в низкий иначе не попасть. */
.rep-chart__hit { fill: transparent; }
.rep-chart__col:hover .rep-chart__hit { fill: var(--surface); }
.rep-chart__col:hover .rep-chart__bar { opacity: .85; }

/* Переключатель «за днями / за тижнями» — ссылками: состояние в адресе,
   значит F5 и «назад» его не теряют. */
.rep-seg {
  display: inline-flex; border: 1px solid var(--line-strong);
  border-radius: var(--radius); overflow: hidden;
}
.rep-seg__i {
  display: inline-flex; align-items: center; height: 26px; padding: 0 10px;
  font-size: 12px; color: var(--ink-2); text-decoration: none;
  border-right: 1px solid var(--line);
}
.rep-seg__i:last-child { border-right: 0; }
.rep-seg__i--on { background: var(--ink); color: var(--ground); }

/* Две пары половинок под графиком (видео 21.09, 9:59: «каждый на половину
   ширины»). Раньше здесь стояла общая сетка .cols — широкая таблица слева и
   узкая колонка 320 точек справа. */
.rep-cols { align-items: start; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
/* Обязательно своим медиазапросом: общее «@media (max-width: 899px) { .cols }»
   стоит выше по файлу и при равном весе проигрывает этой строке — без него
   пара блоков осталась бы на телефоне двумя колонками по 176 точек. Та же
   ловушка каскада, что с кнопкой оплаты и кнопками кассы (§14). */
@media (max-width: 899px) { .rep-cols { grid-template-columns: minmax(0, 1fr); } }
/* Нижняя пара: слева «Закриті замовлення» — четыре короткие строки, справа
   таблица мастеров на семь колонок. Ровно пополам она на узком столе (1368
   точек) не помещается, и колонка «Разом» уезжала за край — делим 0,72 к
   1,28. Верхняя пара остаётся половинками, как он и просил. */
.rep-cols--masters { grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr); }
/* На ноутбуке уже 1280 даже с узкими полями таблица мастеров в половину не
   входит — тогда оба блока идут друг под другом во всю ширину, а не с
   прокруткой вбок внутри карточки. */
@media (max-width: 1279px) { .rep-cols--masters { grid-template-columns: minmax(0, 1fr); } }
.rep-cols + .rep-cols { margin-top: 12px; }
.rep-cols + .rep-cols + .rep-side { margin-top: 12px; }
.rep-table { font-variant-numeric: tabular-nums; }
.rep-table .num { white-space: nowrap; }
.rep-col-n { width: 76px; }
.rep-col-m { width: 96px; }
/* На узком столе (его 1368 точек) семь колонок мастеров в правой половине
   не помещаются, и «Разом» уезжал за край карточки. Поля ячеек здесь уже —
   цифры остаются целиком, таблица не прокручивается вбок. */
@media (max-width: 1520px) {
  .rep-masters .rep-table th, .rep-masters .rep-table td { padding-inline: 6px; }
  .rep-masters .rep-table { font-size: 12.5px; }
}
.rep-table tfoot td {
  font-weight: 600; border-top: 1px solid var(--line-strong); padding: 9px 10px;
}
.rep-table tbody tr.rep-row--on td { background: var(--sec-bg); }
.rep-cell--sum { font-weight: 600; }
.rep-note { margin: 10px 0 0; font-size: var(--text-small); color: var(--muted); line-height: 1.5; }

/* Островки правой колонки: строка «подпись — сумма», итог отчёркнут. */
.rep-side + .rep-side { margin-top: 12px; }
.rep-rows { font-variant-numeric: tabular-nums; }
.rep-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 6px 0; font-size: var(--text-subtitle);
}
.rep-row + .rep-row { border-top: 1px solid var(--line); }
.rep-row span { color: var(--ink-2); min-width: 0; }
.rep-row b { white-space: nowrap; }
.rep-row--sum { font-weight: 600; border-top: 1px solid var(--line-strong); }
.rep-share { color: var(--muted); font-weight: 400; font-size: var(--text-small); }
.rep-rule p { margin: 0 0 8px; font-size: var(--text-subtitle); line-height: 1.5; color: var(--ink-2); }
.rep-rule p:last-child { margin-bottom: 0; }

.rep-tiles { display: none; flex-direction: column; gap: 7px; }
.rep-tile {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-card);
}
.rep-tile--on { background: var(--sec-bg); border-color: var(--sec-line); }
.rep-tile--sum { font-weight: 600; background: var(--surface); }
.rep-tile__n {
  font-size: 14.5px; font-weight: 550; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rep-tile__s {
  justify-self: end; font-size: 14px; font-weight: 600;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.rep-tile__c {
  grid-column: 1 / -1; font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Телефон (медиазапрос с screen: без него он сработал бы и в печати —
   ловушка §14). Цифры в две колонки, мастера плитками, график со своей
   горизонтальной прокруткой. */
@media screen and (max-width: 760px) {
  .rep-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .rep-head .page-subtitle { margin-bottom: 10px; }
  .rep-export { align-self: flex-start; }
  .rep-filters { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: 10px; }
  .rep-filters .dates-range { grid-column: 1 / -1; }
  .rep-kpis, .rep-kpis--two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .rep-kpi { padding: 10px 12px; }
  .rep-kpi__v { font-size: 19px; }
  .rep-kpi__v small { font-size: 12px; }
  .rep-chart__svg { width: auto; max-width: none; min-width: 560px; }
  .rep-masters .table-wrap { display: none; }
  .rep-tiles { display: flex; }
}

/* Печать отчёта: без фильтров и кнопок, график и таблицы целиком. */
@media print {
  .rep-filters, .rep-export, .rep-seg { display: none !important; }
  .rep-chart__scroll { overflow: visible !important; }
  .rep-chart__svg { width: 100% !important; max-width: 100% !important; min-width: 0 !important; }
  .rep-cols { display: block; }
  .rep-side, .rep-masters, .rep-chart { break-inside: avoid; }
  .rep-side + .rep-side, .rep-cols > aside { margin-top: 12px; }
  .rep-tiles { display: none !important; }
  .rep-masters .table-wrap { display: block !important; }
}

/* ─────────────────────────────────────────────────────────────────────── */
/*                                                                         */
/* ─────────────────────────────────────────────────────────────────────── */

/* ── этап 6: каса — постачальники ─────────────────────────────────────── */
/* Сводка поставщика «закуплено − повернено − сплачено = борг», окно
   «Оплата постачальнику». */

/* Колонка «Борг» в списке. Переплата — синим: зелёный и красный в кассе
   заняты смыслом «пришло / ушло». */
.sup-debt { font-weight: 700; color: var(--ink); white-space: nowrap; }
.sup-debt__over { font-weight: 600; color: var(--status-blue-fg); }

/* Сводка карточки: цветом раздела выделен итог — борг, а не первая цифра,
   как на остальных экранах. Специфичность выше общего правила
   .counters .cnt:first-child, стоящего раньше. */
.counters.sup-counters .cnt:first-child { background: var(--ground); border-color: var(--line); }
.counters.sup-counters .cnt:first-child b { color: var(--ink); }
.counters.sup-counters .sup-cnt { background: var(--sec-bg); border-color: var(--sec-line); }
.counters.sup-counters .sup-cnt b { color: var(--sec-fg); }
.counters.sup-counters .sup-cnt--over b { color: var(--status-blue-fg); }

/* Одна история: приходы, возвраты, оплаты. То, что в долг не идёт (сторно,
   отменённая оплата), — приглушено, сумма перечёркнута. */
.sup-hist { margin-top: 16px; }
.sup-hist__what { white-space: nowrap; }
.sup-hist__what .pill { margin-left: 4px; }
.sup-hist__sum { font-weight: 700; white-space: nowrap; }
.sup-hist__row--void td { color: var(--muted); }
.sup-hist__row--void .sup-hist__sum,
.sup-tile--void .sup-hist__sum { font-weight: 500; color: var(--muted); text-decoration: line-through; }
.sup-tile { cursor: default; }
.sup-tile .t-dev { font-size: 14px; }
.sup-tile__note:empty { display: none; }
.sup-tile__note { white-space: normal; overflow-wrap: anywhere; }

/* Окно «Оплата постачальнику». */
.modal--supplier-pay { width: min(520px, calc(100vw - 24px)); }
.modal--supplier-pay select, .modal--supplier-pay input[type="text"] { width: 100%; }
.modal--supplier-pay .messages { margin: 0 0 12px; }
.sup-pay__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 14px; align-items: start; }
.sup-pay__seg { display: flex; flex-wrap: nowrap; }
.sup-pay__seg .seg__i { flex: 1 1 0; }
.sup-pay__seg .seg__i span { width: 100%; justify-content: center; height: 35px; }
.sup-pay__foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.modal--supplier-pay [aria-invalid="true"] { border-color: var(--status-red-fg); }

/* Телефон: четыре цифры сводки — сеткой 2×2 (в общей ленте борг уезжал бы за
   край), история — плитками, окно — на всю ширину, способ — под суммой. */
@media screen and (max-width: 760px) {
  .counters.sup-counters {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); overflow: visible;
  }
  .counters.sup-counters .cnt { display: block; min-width: 0; }
  .counters.sup-counters .cnt span { margin-top: 1px; }
  .sup-hist { padding-left: 10px; padding-right: 10px; }
  .modal--supplier-pay { width: calc(100vw - 16px); max-width: none; }
  .modal--supplier-pay .modal__card { padding: 16px 14px 16px; }
  .sup-pay__row { grid-template-columns: minmax(0, 1fr); }
  .sup-pay__foot .btn { flex: 1 1 0; justify-content: center; }
}


/* ─────────────────────────────────────────────────────────────────────── */
/*                                                                         */
/* ─────────────────────────────────────────────────────────────────────── */

/* ── этап 6: каса — друк ──────────────────────────────────────────────── */
/* Акт работ с «Оплата» и «Коригування суми», печать журнала и отчёта:
   @media print проверять — журнал и отчёт будут печатать. */



/* ── Боковое меню: подменю чужого раздела выезжает вправо ───── */
/* Видео заказчика 19.09: «прошёл по складу, решил зайти в кассы — и
   вот, наводя на кассы, они у нас, хоп, и пропали», «в Gincore она
   развёртывается вправо, ничего никуда не уплывает». Подменю лежало в
   потоке, и раскрытие по наведению (его же просьба из видео 13) уводило
   «Касу» вниз на высоту девяти подпунктов склада, а уход курсора возвращал
   её обратно — целиться было некуда. Теперь в потоке остаётся только
   подменю ТЕКУЩЕГО раздела (иначе в кассе пропадут «Звіти»: своего
   ряда вкладок у неё, в отличие от склада, нет), а чужие разделы показывают
   подменю отдельной панелью справа, ничего не двигая.
   Только на столе: на телефоне сайдбар — выездная панель (с 03.10 — 232
   точки) с прокруткой, вправо выезжать некуда — там остаётся прежняя
   гармошка. */
@media (min-width: 761px) {
  .sidebar__group { position: relative; }
  .sidebar__group:not(.sidebar__group--on):hover > .sidebar__sub,
  .sidebar__group:not(.sidebar__group--on):focus-within > .sidebar__sub {
    display: flex;
    position: absolute;
    left: 100%; top: -6px;
    z-index: 45;              /* выше выпадашек контента (20–40), ниже плашки сохранения (60) и окон (90) */
    min-width: 208px;
    margin: 0;
    padding: 6px;
    /* Зазора между пунктом и панелью быть не должно, иначе наведение
       рвётся и панель мигает: отступ даёт прозрачная левая рамка,
       она же мост под курсором. */
    border: 1px solid var(--line-strong);
    border-left: 11px solid transparent;
    background: var(--ground);
    background-clip: padding-box;
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(20, 29, 31, 0.12);
  }
}

/* ── Боковое меню: иконки и свёрнутый вид (видео 25.09) ─────────────── */
/* Заказчик на Surface (1368 точек): открытое меню «берёт на себя очень
   много внимания и места» — колонка уже на 16 точек (≈3 мм у него на
   экране: 200 → 184, на узком столе 176 → 160, цифры в tokens.css и в
   блоке плотности выше), слово Linetix на пару точек ниже (22 → 20).
   У пунктов появились иконки: «не сухой текст, а с картинками», свои, не
   взятые у Gincore и RemOnline. Иконка раздела — цветом раздела, тем же,
   что кнопка создания и счётчики: меню и страница говорят одним цветом.
   Кнопка в шапке сворачивает меню в колонку иконок, «когда закрываем
   шторку, остаются только картинки»; подпись всплывает при наведении,
   у склада и кассы — вместе с подменю. */
.nav-icons { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Слово и знак — каждый в своей обёртке: прячется обёртка, а пара
   светлая/тёмная внутри по-прежнему переключается общими правилами логотипа. */
.sidebar__brand { display: flex; align-items: center; height: 24px; padding: 0 10px; margin: 0 0 18px; }
.sidebar__word .logo { width: 132px; height: 20px; }
.sidebar__mark { display: none; }

/* Правое поле 6 вместо 10: на 160 точках «Налаштування» при десятке
   вылезало из своей строки на 2 точки (замер scrollWidth). Кнопка «Вийти»
   названа отдельно — её поля весят больше (.sidebar__link.btn--link).
   min-height держит высоту пункта одинаковой в обоих видах: в свёрнутом
   подпись уходит в absolute и без него строка проседала на 2 точки, а
   нижние иконки при сворачивании прыгали вверх на все десять. */
.sidebar__link { justify-content: flex-start; padding-right: 6px; min-height: 34px; }
.sidebar__link.btn--link { padding-right: 6px; }
.sidebar__link .ico {
  flex: none; width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  color: var(--muted);
}
.sidebar__t { flex: 1; min-width: 0; }
/* Имя человека — одной строкой с многоточием: «Олена Приймальник» и любое
   обычное имя с фамилией в 97 точек уже не влезает, а перенос ломал ровный
   ряд пунктов и вешал иконку между строк. Полное имя — в подсказке. */
.sidebar__t--name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Подменю: поля пунктов 6 вместо 10. Колонка стала уже на 16 точек, и в
   русском «Движение товара» начало переноситься; здесь оно снова в строку,
   а место под текст даже больше прежнего. */
.sidebar__sub a { padding-left: 6px; padding-right: 6px; }
.sidebar__link .chip--soon { flex: none; }
.sidebar__link .ico--clients { color: var(--sec-clients-fg); }
.sidebar__link .ico--leads { color: var(--sec-leads-fg); }
.sidebar__link .ico--orders { color: var(--sec-orders-fg); }
.sidebar__link .ico--warehouse { color: var(--sec-warehouse-fg); }
.sidebar__link .ico--cash { color: var(--sec-cash-fg); }
.sidebar__link .ico--sales { color: var(--sec-sales-fg); }
.sidebar__link--soon .ico { opacity: .6; }

/* ── Профиль сотрудника наверху меню (скрин заказчика 26.09) ────────── */
/* «Забыл на видео показать, как профиль сотрудника сверху в Gincore». У него
   там кружок, имя и роль над пунктами — так и делаем, только кружок с
   инициалами: фотографий сотрудников в системе нет.

   Блок занимает ту же ширину, что и пункты, и держит ту же высоту строки,
   иначе при сворачивании иконки под ним поехали бы. */
.sidebar__me {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 10px; padding: 7px 6px 7px 10px;
  border-radius: var(--radius);
  text-decoration: none; color: var(--ink);
  min-height: 44px;
}
.sidebar__me:hover { background: var(--surface-2); }
.sidebar__me--on { background: var(--sec-bg); }
/* Кружок не цветом раздела: аватарка человека не должна перекрашиваться,
   пока он ходит по разделам. Серым он был до 02.10 — заказчик: «слишком
   сливается… более зелёным, более красивым»; цвет и размер теперь задаёт
   секция «меню и настройки» в конце файла, постоянство цвета осталось. */
.ini--me { width: 30px; height: 30px; font-size: 12px; background: var(--surface-2); color: var(--ink-2); }
.sidebar__me .sidebar__t { display: flex; flex-direction: column; gap: 1px; line-height: 1.15; }
.sidebar__me-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.sidebar__me-role { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }

/* Выход в правом верхнем углу — просьба 27.09, как в его Gincore. Кнопка
   формы, а не ссылка: выход меняет состояние, по GET его делать нельзя. */
.topbar__out { display: flex; margin-left: 4px; }
.topbar__out-btn {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 11px;
  border: 1px solid var(--line-strong); border-radius: 100px;
  background: var(--ground); color: var(--ink-2);
  font: inherit; font-size: var(--text-small); cursor: pointer;
}
.topbar__out-btn:hover { border-color: var(--line-strong); color: var(--ink); background: var(--surface); }
.topbar__out-btn .ico {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* Кнопка меню видна и на столе: там она сворачивает колонку. */
.burger { display: inline-flex; }

/* «Не телефон», а не min-width: 761px — так же считает скрипт кнопки:
   при дробной ширине (масштаб браузера) между 760 и 761 точками не
   действовало бы ни одно из двух правил. */
@media not all and (max-width: 760px) {
  /* 26.09 плавного сужения здесь нарочно не было: класс снимается сразу, и
     пока колонка ехала бы с 60 до 160, слово Linetix и подписи уже стояли в
     потоке — первые сто миллисекунд логотип был срезан шапкой, а подписи
     подменю вылезали на страницу. 02.10 заказчик попросил именно переход
     («чтобы он именно заезжал»): он сделан в секции «меню и настройки» в
     конце файла — только на время layout--moving и с обрезкой краем
     колонки, поэтому тот дефект не возвращается. */
  .layout--mini { --sidebar-w: 60px; }
  .layout--mini .sidebar__group { position: relative; }
  .layout--mini .sidebar__brand { justify-content: center; padding: 0; }
  .layout--mini .sidebar__word { display: none; }
  .layout--mini .sidebar__mark { display: block; }
  .layout--mini .sidebar__link { justify-content: center; padding-left: 0; padding-right: 0; position: relative; }
  .layout--mini .sidebar__me { justify-content: center; padding-left: 0; padding-right: 0; position: relative; }
  .layout--mini .sidebar__me .sidebar__t { display: block; }
  .layout--mini .sidebar__me-name, .layout--mini .sidebar__me-role { display: block; font-size: 13px; }
  .layout--mini .sidebar__me-role { color: var(--muted); font-size: 11.5px; font-weight: 400; }
  .layout--mini .sidebar__link .chip--soon { display: none; }

  /* Подпись остаётся в разметке (её читает экранный диктор и по ней
     кликают прогоны), но на экране появляется только при наведении —
     плашкой справа от иконки. Прозрачная левая рамка — мост под курсором,
     как у подменю: без зазора, иначе плашка мигает. */
  .layout--mini .sidebar__t {
    position: absolute; left: 100%; top: 50%; transform: translateY(-50%);
    z-index: 45;
    white-space: nowrap;
    padding: 6px 12px;
    border: 1px solid var(--line-strong);
    border-left: 11px solid transparent;
    background: var(--ground);
    background-clip: padding-box;
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(20, 29, 31, 0.12);
    color: var(--ink);
    font-weight: 500;
    opacity: 0;
    pointer-events: none;
  }
  .layout--mini .sidebar__me > .sidebar__t { position: absolute; left: 100%; top: 50%;
    transform: translateY(-50%); z-index: 45; white-space: nowrap; padding: 6px 12px;
    border: 1px solid var(--line-strong); border-left: 11px solid transparent;
    background: var(--ground); background-clip: padding-box; border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(20, 29, 31, 0.12); color: var(--ink);
    opacity: 0; pointer-events: none; }
  .layout--mini .sidebar__link:hover > .sidebar__t,
  .layout--mini .sidebar__link:focus-visible > .sidebar__t,
  .layout--mini .sidebar__me:hover > .sidebar__t,
  .layout--mini .sidebar__me:focus-visible > .sidebar__t { opacity: 1; pointer-events: auto; }
  /* У склада и кассы плашки нет: там по наведению выезжает всё подменю, и
     плашка встала бы поверх него. */
  .layout--mini .sidebar__group > .sidebar__link > .sidebar__t { opacity: 0 !important; pointer-events: none !important; }

  /* Подменю открытого раздела в потоке не помещается в 60 точек: в
     свёрнутом меню оно, как у остальных, выезжает панелью по наведению.
     Панель всегда в разметке и прячется видимостью, а не display: это
     даёт задержку закрытия. Без неё курсор, идущий по диагонали от иконки
     к нижнему пункту, выходит из колонки в пустое место под иконкой,
     наведение рвётся и панель захлопывается — ровно та жалоба 19.09
     («наводя на кассы, они у нас, хоп, и пропали»). Теперь панель держится
     ещё 0,3 с и курсор успевает вернуться. */
  .layout--mini .sidebar__group > .sidebar__sub {
    display: flex;
    visibility: hidden;
    opacity: 0;
    transition: opacity .12s ease .18s, visibility 0s linear .3s;
    position: absolute;
    left: 100%; top: -6px;
    z-index: 45;
    min-width: 208px;
    margin: 0;
    padding: 6px;
    border: 1px solid var(--line-strong);
    border-left: 11px solid transparent;
    background: var(--ground);
    background-clip: padding-box;
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(20, 29, 31, 0.12);
  }
  .layout--mini .sidebar__group:hover > .sidebar__sub,
  .layout--mini .sidebar__group:focus-within > .sidebar__sub,
  .layout--mini .sidebar__group--tap > .sidebar__sub {
    visibility: visible;
    opacity: 1;
    transition-delay: 0s;
  }
}

/* Сенсорный экран без мыши: наведение там «залипает» на последнем, чего
   коснулись, и плашка с названием оставалась висеть поверх страницы, ловя
   касания. Касание по иконке и так сразу ведёт в раздел, поэтому плашки
   на таких экранах нет вовсе; название остаётся в разметке для диктора. */
@media not all and (max-width: 760px) {
  @media (hover: none) {
    .layout--mini .sidebar__link > .sidebar__t { opacity: 0 !important; pointer-events: none !important; }
  }
}

/* ═══════════════════════════════════════════ видео заказчика 02.10: SMS, клиент, заявки
   Разбор — docs/165-VIDEO-02-10-BREAKDOWN.md. Разметку окна отправки, журнала
   /sms, «Історії зв'язку» и кнопки SMS в заявках переписали раньше, а стилей
   у полутора десятков новых классов не было вовсе: окно рисовалось голыми
   рамками и маркерами браузера — ровно то, что заказчик снял на видео.
   Секции стоят ПОСЛЕДНИМИ в файле намеренно: половина их правил весит
   ровно столько же, сколько общие правила выше, и побеждает только порядком
   (ловушка каскада) — .tile--sms и .tile--lead против сетки .tile,
   .sms-table td против высоты .table td, .modal--sms против ширины .modal,
   .seg--sms против «.seg { width: 100% }» из телефонного блока кассы.
   Цвета — только токенами. */

/* ── Окно «Надіслати повідомлення» (пункты 1–2) ─────────────────────── */
/* Плашка канала. «Очень странно у нас потянули SMS в кружочке, возможно, его
   сделать каким-то затемнённым, возможно красивым… чуть-чуть несуразно
   смотрится» (00:05). Причина: у .seg--sms и .seg__i--on не было ни одного
   правила, а «включённый» сегмент в app.css рисуется через input:checked +
   span — радиокнопки в этом окне нет, и вкладка выходила голым словом в
   рамке группы. Теперь — мягкая фирменная плашка со знаком SMS, как
   «Прийнято через» на приёме. Не графитовая нарочно: графит — это кнопка
   «Надіслати» в этом же окне, и в полутораста точках друг от друга стояли бы
   два одинаковых тёмных прямоугольника (в тёмной теме — два светлых).
   Ширина окна — 520, как у остальных окон с формой (оплата, повернення,
   статус, каса): было 560 общего .modal от «Швидкої заявки». */
.modal--sms { width: min(520px, calc(100vw - 24px)); }
.seg--sms { display: flex; width: auto; margin: 0 0 12px; border: 0; border-radius: 0; overflow: visible; }
.seg--sms .seg__i { flex: none; }
.seg--sms .seg__i--on {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 12px 0 10px;
  border-radius: var(--radius-chip);
  background: var(--brand-soft); color: var(--brand);
  font-size: 12px; font-weight: 700; letter-spacing: .04em;
  cursor: default;
}
/* Знак — то же скруглённое облачко, что у записи SMS в ленте и на кнопке
   «Надіслати SMS» (п. 4), маской: цвет берётся от текста плашки и в тёмной
   теме меняется сам. */
.seg--sms .seg__i--on::before {
  content: ""; flex: none; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'><path d='M4 2.75h8a2.25 2.25 0 0 1 2.25 2.25v4a2.25 2.25 0 0 1-2.25 2.25H8.2l-3.1 2.4v-2.4H4A2.25 2.25 0 0 1 1.75 9V5A2.25 2.25 0 0 1 4 2.75ZM5.25 7h.01M8 7h.01M10.75 7h.01' stroke='black' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'><path d='M4 2.75h8a2.25 2.25 0 0 1 2.25 2.25v4a2.25 2.25 0 0 1-2.25 2.25H8.2l-3.1 2.4v-2.4H4A2.25 2.25 0 0 1 1.75 9V5A2.25 2.25 0 0 1 4 2.75ZM5.25 7h.01M8 7h.01M10.75 7h.01' stroke='black' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round'/></svg>") center / contain no-repeat;
}

/* «Вже надсилали». «Эта надпись почти налазит у нас на две кнопки… немножко
   больше интервал, и эту надпись возможно немножко меньше, и вот здесь
   интервал также уменьшить» (00:21). У блока не было ни отступа, ни правил:
   заголовок стоял к кнопкам вплотную, список рисовался маркерами браузера с
   полем в 40 точек, а время, номер, статус и текст шли сплошным абзацем.
   Теперь история — своя секция под линией, заголовок — мелкой подписью, как
   «Номер» и «Шаблон» в этом же окне, сообщение — карточкой в две строки, как
   история напоминаний в окне колокольчика (.nh__i). Десять сообщений (столько
   отдаёт сервер) выталкивали окно за экран, и кнопки уезжали вверх, —
   поэтому после четырёх список прокручивается сам. */
.sms-history { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.sms-history__h {
  margin: 0 0 8px; font-size: var(--label); font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted);
}
.sms-history__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 6px; max-height: 236px; overflow-y: auto;
}
.sms-history__list > li {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 3px 8px;
  padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-field);
  background: var(--surface); font-size: 12px; line-height: 1.35;
}
.sms-history__when { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sms-history__to {
  min-width: 0; color: var(--ink-2); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sms-history__list .pill { justify-self: end; font-size: 11px; padding: 1px 8px; }
.sms-history__text { grid-column: 1 / -1; color: var(--ink-2); overflow-wrap: anywhere; }

/* ── Журнал /sms (пункт 9) ─────────────────────────────────────────────── */
/* «Страничка слишком-слишком массивная… текст самого сообщения — меньше
   шрифт… сейчас весь перечень абсолютно разный по размерам» (03:43). Шире
   страница уже быть не может (content--wide стоит с первого дня), массу
   давали ячейки без ширин и без обрезки: строки выходили от 38 до 150 точек.
   Рецепт списка заказов: table-layout: fixed, max-width: 0 у ячеек, в каждой
   ячейке ровно две строки (cell-main / cell-sub) с многоточием. Колонки с
   коротким содержимым — в точках, имена и названия — долями, текст сообщения
   забирает остаток. Полные значения остаются в title. */
.sms-table .table { table-layout: fixed; font-size: var(--text-subtitle); }
.sms-table td { max-width: 0; height: var(--row-h-double); }
.sms-table th { overflow: hidden; text-overflow: ellipsis; }
.sms-table .cell-main, .sms-table .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Высота строки задана, а не «как выйдет»: 18 + 16 точек на две строки
   ячейки и пилюля статуса высотой в первую строку — все строки ровно по 52
   точки (--row-h-double, высота строки утверждённого макета), с ошибкой
   оператора и без, с кнопкой и без, с длинным текстом и коротким. */
.sms-table .cell-main { height: 18px; line-height: 18px; }
.sms-table .cell-sub { height: 16px; line-height: 16px; }
.sms-table .col-status .pill {
  display: block; width: fit-content; max-width: 100%; height: 18px; line-height: 14px;
  overflow: hidden; text-overflow: ellipsis;
}
/* Ширины замерены на настоящих значениях, а не прикинуты: «02.10.2026» —
   55 точек, «+380985673211» — 93, «Власник Компанії» — 104, «Повідомлення
   про готовність» — 177, плюс поля ячейки. Доли подобраны так, чтобы на его
   1368 и на 1280 номер, отправитель и самый частый шаблон стояли целиком, а
   текст сообщения получал остальное: 328 точек на 1368, 489 на 1920. */
.sms-table .col-when { width: 88px; }
.sms-table .col-to { width: 10.5%; }
.sms-table .col-event { width: 18%; }
/* Текст сообщения — без ширины нарочно: он забирает всё, что осталось. */
.sms-table .col-text { width: auto; }
.sms-table .col-parts { width: 72px; }
.sms-table .col-status { width: 124px; }
.sms-table .col-who { width: 10.5%; }
.sms-table .col-act { width: 104px; }
/* На 1024 текст иначе получал 120 точек: статус и кнопка ужимаются ближе к
   своему содержимому (пилюля «Не доставлено» — 96 точек, кнопка и так в две
   строки). Номер и шаблон здесь уже с многоточием: места больше нет. */
@media (max-width: 1100px) {
  .sms-table .col-status { width: 116px; }
  .sms-table .col-act { width: 88px; }
}
/* Сам текст — мельче и не длиннее двух строк: семьдесят знаков его шаблонов
   видны целиком, длинное обрезается многоточием. max-height — запас для
   браузера без line-clamp: там текст просто срежется по второй строке. */
.sms-text {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; max-height: 2.6em; font-size: 12.5px; line-height: 1.3;
  color: var(--ink-2); white-space: normal; overflow-wrap: anywhere;
}
/* «Оновити статус» в узкой колонке — в две строки, как «Взяти замовлення» в
   списке заказов: подпись дословно из документа приёмки, менять её нельзя, а
   одной строкой она не помещалась в колонку на 1024–1280. */
.sms-table .col-act .btn {
  height: auto; min-height: 28px; max-width: 100%; padding: 2px 8px;
  line-height: 1.15; white-space: normal; font-size: 11.5px;
}
/* Телефон: плитки вместо таблицы (сами .tiles включает общее правило на
   760). Справа — пилюля статуса и отправитель: не шире половины плитки и с
   многоточием, иначе длинное имя сжимало левую колонку в ноль — та же беда,
   что у плитки заявок ниже. */
.tile--sms { grid-template-columns: minmax(0, 1fr) fit-content(48%); }
.tile--sms .t-r { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.tile--sms .sms-text { font-size: 12px; margin-top: 1px; }

/* ── Карточка клиента: «Історія зв'язку» (пункт 11) ──────────────────── */
/* «Історія зв'язку — смс пока туда не тянет» (сообщение 02.10 с фото). Блок
   стал лентой: те же .feed, .timeline и .ev--sms, что лента заказа, и те же
   вкладки .feed-tab — их переключает общий ui.js, ставя ленте data-show.
   Прятать по вкладке — дело этих правил. Без них «Усі» показывали фразу про
   звонки под сообщениями, а «Дзвінки» — сами сообщения. */
.comm-head { flex-wrap: wrap; row-gap: 6px; }
.feed[data-show="call"] .comm-sms,
.feed[data-show="all"] .comm-call,
.feed[data-show="sms"] .comm-call { display: none; }
/* Время записи — одной строкой: у ленты стоит overflow-wrap: anywhere, и на
   360 точках рядом с длинным названием своего шаблона «03.10.2026 00:46»
   рвалось посреди года. */
.comm-sms .ev__t { white-space: nowrap; flex: none; }
/* Линия ленты не тянется вдоль одной фразы без единой записи — на вкладке
   «Дзвінки» и в пустом блоке. Пустой ленте заказа это тоже на пользу. */
.timeline[data-show="call"]::before,
.timeline:not(:has(.ev))::before { display: none; }

/* ── Список заявок: кнопка SMS (пункт 10) ────────────────────────────── */
/* «Желательно сделать вот здесь кнопочку „Отправить SMS“, не заходя в саму
   заявку» (03:20). На столе кнопка стоит своей колонкой справа и правил не
   просит. На телефоне плитка стала <div> — кнопку внутрь ссылки класть
   нельзя, — и «тап по плитке открывает заявку» держит ссылка номера,
   растянутая на всю плитку; кнопка лежит над ней. */
.tile--lead { position: relative; grid-template-columns: minmax(0, 1fr) fit-content(50%); }
/* Имя клиента справа — не шире половины и с многоточием. Замерено 03.10 на
   390 точках: «Олександра-Вікторія Скоропадська-Вишневецька» сжимало номер и
   модель в ноль и выносило страницу вбок до 421 точки. Так было и у
   плитки-ссылки до кнопки. */
.tile--lead .t-r { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.tile--lead .t-open { color: inherit; text-decoration: none; }
.tile--lead .t-open::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-card); }
.tile--lead .t-open:focus-visible { outline: none; }
.tile--lead .t-open:focus-visible::after { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Кнопка — своим рядом справа, над растянутой ссылкой. Пробовал ставить её
   в строку «суті звернення», чтобы плитка была ниже: суть тогда обрезалась
   на половине (правая колонка занята именем клиента) и из 70 знаков было
   видно около 28 — а это то, ради чего плитку и открывают. */
.tile--lead .t-act { position: relative; z-index: 1; }

/* Выключенная кнопка выглядит выключенной. «SMS» в заявках и «Надіслати SMS»
   в карточках стоят выключенными, пока шлюз не подключён (причина — в
   подсказке), но у .btn не было ни одного правила для disabled: кнопка
   выглядела рабочей, нажал — ничего. Так уже сделано у «Прийняти оплату»
   (.btn--pay[disabled]). Вес 0,3,0 — выше :hover залитых кнопок, иначе под
   курсором они «оживали» снова. Кнопки-ссылки не трогаем: у «Скинути» в
   редакторе документов своё приглушение. */
.btn:not(.btn--link):disabled { opacity: .55; cursor: not-allowed; }

/* ═══════════════════════════════════════════ видео заказчика 02.10: меню и настройки
   Пункты 12–18 разбора docs/165-VIDEO-02-10-BREAKDOWN.md. Разметку меню
   (профиль столбиком, «Налаштування» под разделами) переставили раньше и
   оставили стилям две зацепки: sidebar__me--stack и sidebar__link--foot.
   Секция стоит ПОСЛЕДНЕЙ нарочно: правила свёрнутого меню выше живут внутри
   «@media not all and (max-width: 760px)» и весят столько же, сколько эти, а
   телефонная панель — в самом первом @media файла. Поставь секцию выше — и её
   молча перебьют порядком (ловушка каскада). Цвета — только токенами. */

/* ── Профиль столбиком (п. 15) ─────────────────────────────────────────── */
/* «Сверху сделать вот такой кружок с инициалами, снизу имя фамилия и ещё ниже
   непосредственно сама должность. Она займёт определённое место, чуть-чуть
   сдвинет вниз все колонки, и будет массивно-красиво смотреться выдвижная
   панель» (06:16). Порядок частей задаёт разметка, здесь — только столбик.
   Высота блока задана, а не «как выйдет»: в свёрнутом меню имя и должность
   уходят во всплывающую плашку, и блок, сжавшись до кружка, дёргал бы вверх
   все иконки под ним — ровно тот «тупнячок», от которого уходит п. 17.
   Строки имени и должности поэтому тоже в точках: 10 + 38 + 6 + 16 + 1 + 14 +
   8 = 93, держим 94. Поля слева и справа равные — иначе кружок при
   сворачивании сдвигался бы на их разницу.
   flex: none — не сжиматься: выездная панель телефона — колонка высотой в
   экран, и на коротком экране (375 × 667, открыт склад) сжимаемый блок
   профиля сплющивало, а имя и должность ложились поверх «Клієнти»
   (поймано замером 03.10). Пусть лучше панель прокручивается. */
.sidebar__me--stack {
  flex: none; flex-direction: column; justify-content: flex-start; gap: 6px;
  height: 94px; padding: 10px 6px 8px; margin-bottom: 8px;
}
/* Растягивается текст, а не задаётся ширина: ширина 100% сжала бы в свёрнутом
   меню плашку с именем до колонки в 60 точек и обрезала имя в ней. */
.sidebar__me--stack > .sidebar__t--name { flex: none; align-self: stretch; text-align: center; }
.sidebar__me--stack .sidebar__me-name { font-size: 13px; line-height: 16px; }
.sidebar__me--stack .sidebar__me-role { font-size: 11.5px; line-height: 14px; }

/* ── Кружок инициалов (п. 16) ──────────────────────────────────────────── */
/* «Сам кружочек на данный момент слишком сливается по цвету с вот этим
   подменю, возможно каким-то более зелёным, более красивым сделать» (06:46).
   Был --surface-2 на --surface колонки: 1,07 : 1, то есть никак. Теперь
   фирменный зелёный — цвет знака Linetix над ним — с инициалами цветом листа
   и мягким кольцом. Цвет постоянный, а не цветом раздела: аватарка человека
   не перекрашивается, пока он ходит по разделам. Инициалы к заливке 6,45 : 1
   в светлой теме и 8,48 : 1 в тёмной, кружок к колонке 6,02 : 1 и 7,86 : 1
   (считает tests/test_nav.py, все три ветки токенов). Новых токенов нет:
   --brand, --ground и --brand-soft уже определены во всех трёх ветках. */
.ini--me {
  background: var(--brand); color: var(--ground);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.sidebar__me--stack .ini--me { width: 38px; height: 38px; font-size: 14px; letter-spacing: .03em; }

/* ── Сворачивание меню — анимацией (п. 17) ─────────────────────────────── */
/* «Можешь ли сделать, чтобы он именно заезжал… и вот эти у нас все заказы
   немножечко расширялись: то есть всё статически остаётся на месте, и при
   закрытии она просто расширяется. А так получается небольшой тупнячок»
   (07:47). 26.09 плавное сужение убирали нарочно: класс снимался сразу, и
   пока колонка ехала с 60 до 160, подписи и слово Linetix уже стояли в потоке
   и вылезали на страницу. Теперь переход делается иначе.
   1. Ехать разрешено только на время самого перехода: класс layout--moving
      ставит кнопка меню (скрипт в base_app.html) и снимает, когда колонка
      доехала (transitionend, на крайний случай — таймер 1,5 с). Без
      него ширина меняется мгновенно — поэтому страница, открытая уже
      свёрнутой (кука lx_nav, сервер отдаёт layout--mini), на загрузке не
      анимируется, и «Назад» из кэша браузера тоже.
   2. Пока колонка едет, она обрезает всё, что в неё не влезает (overflow:
      hidden): подписи, слово Linetix, имя в профиле открываются краем
      колонки, как шторкой, и не выходят на страницу ни в одном кадре.
      Подписи вдобавок проявляются чуть позже, когда места уже почти хватает.
   3. Иконки, знак и кружок не прыгают: в свёрнутом виде иконки и знак стоят
      там же, где в раскрытом (поле 10 слева, без центрирования), кружок
      держит центр колонки и едет вместе с её краем.
   4. Колонка контента — flex: 1 и едет вместе с меню, это и есть «заказы
      расширялись».
   Тише, если человек попросил систему меньше двигаться
   (prefers-reduced-motion): тогда всё переключается сразу, как раньше. */
@media not all and (max-width: 760px) {
  /* interpolate-size — только колонке меню: высота подменю едет от auto к
     нулю, а контенту страницы переход по ключевым словам ни к чему. */
  .layout--moving .sidebar {
    overflow: hidden; interpolate-size: allow-keywords;
    transition: width .22s ease, flex-basis .22s ease;
  }
  .layout--moving:not(.layout--mini) .sidebar__t,
  .layout--moving:not(.layout--mini) .sidebar__sub a { transition: opacity .12s ease .1s; }
  /* Подпункты раскрываемого подменю тоже проявляются, а не стоят с первого
     кадра: в узкой ещё колонке «Рух товару» и «Замовлення постачальникам»
     переносились по слову и мельтешили, пока колонка не доехала. */
  .layout--opening .sidebar__sub a { opacity: 0; }
  /* Строка подписи — ровно 20 точек: 14 × 1,45 давали 20,3, пункт с подписью
     выходил 34,3 при 34 у свёрнутого, и иконки за шесть пунктов уезжали при
     сворачивании на полторы точки. */
  .sidebar__link { line-height: 20px; }
  .layout--mini .sidebar__brand { justify-content: flex-start; padding: 0 10px; }
  .layout--mini .sidebar__link { justify-content: flex-start; padding-left: 10px; }
  /* Кружок наверху блока той же высоты, что в раскрытом виде: правило
     свёрнутого меню выше центрирует по главной оси, а она здесь вертикальная. */
  .layout--mini .sidebar__me--stack { justify-content: flex-start; padding-left: 0; padding-right: 0; }
  /* Плашка с именем — на уровне кружка, а не середины высокого блока. */
  .layout--mini .sidebar__me--stack > .sidebar__t { top: 29px; }

  /* Подменю открытого раздела (склад, каса, клієнти) в раскрытом меню лежит в
     потоке, в свёрнутом — панелью сбоку. Без перехода пункты под ним
     прыгали на его высоту (на складе — 275 точек) одним кадром, а сама
     панель ещё 0,3 с висела справа от колонки: её задержка закрытия (см.
     выше, жалоба 19.09) срабатывала и на сворачивании. На время перехода
     подменю остаётся в потоке и плавно складывается или раскрывается по
     высоте; панелью оно становится, когда колонка уже доехала.
     Раскрытию нужна точка отсчёта «высота 0 в потоке» — до него подменю было
     панелью сбоку со своей высотой, и без этой точки «Каса» под ним прыгала
     вниз одним кадром (так и было в первой пробе). Её даёт layout--opening:
     скрипт ставит его на один пересчёт стилей перед раскрытием. Перехода в
     нём нет: interpolate-size включён только на время layout--moving, и высота
     встаёт в ноль сразу; transition: none — для верности, если его включат
     шире. */
  .layout--moving .sidebar__group--on > .sidebar__sub {
    position: static; overflow: hidden;
    transition: height .22s ease, margin .22s ease;
  }
  .layout--moving.layout--mini .sidebar__group--on > .sidebar__sub,
  .layout--opening.layout--mini .sidebar__group--on > .sidebar__sub {
    position: static; overflow: hidden;
    height: 0; min-width: 0; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;
    border-top-width: 0; border-bottom-width: 0; box-shadow: none;
    visibility: hidden;
    transition: height .22s ease, margin .22s ease;
  }
  .layout--opening.layout--mini .sidebar__group--on > .sidebar__sub { transition: none; }
}
/* Не none, а тысячная секунды: переход формально есть, его transitionend
   приходит сразу и снимает layout--moving, а не ждёт запасного таймера,
   пока колонка обрезает всплывающие панели. */
@media (prefers-reduced-motion: reduce) {
  .layout--moving .sidebar,
  .layout--moving .sidebar__t,
  .layout--moving .sidebar__sub,
  .layout--moving .sidebar__sub a { transition-duration: .001s !important; transition-delay: 0s !important; }
}

/* ── Выездная панель на телефоне (п. 12, 13, 14, 15) ──────────────────── */
/* «Я просил тебя сделать больше текст… нам нужно ещё немножко больше… сам
   текст» (04:56), «ширину просил чуть-чуть уменьшить в мобильной версии…
   слишком много пустого пространства… сейчас он съедает пол странички. И само
   подменю, когда выпадает, слишком крупное» (05:07). Под «подменю» на телефоне
   он показывает саму выездную панель. Цифр в панели нет — «маленькие цифры»
   в расшифровке, судя по кадрам, это сами подписи.
   Ширина 232 вместо 260 (на его экране в 400 точек — 58 % вместо 65 %).
   Меньше не берём: самая длинная подпись панели — украинское «Замовлення
   постачальникам» в подменю склада (русское «Заказы поставщикам» короче), и в
   232 она при выбранном пункте влезает в строку с запасом в 5 точек.
   Подписи разделов 16 вместо 15, иконки 20, профиль крупнее; подпункты —
   13, их текст начинается в 31 точке от края панели вместо 37: подменю
   легче, чем было. */
@media (max-width: 760px) {
  /* 03.10 ещё уже — 212 (53 % его экрана): «вот эту сноску у нас, левое
     меню, надо чуть-чуточку ещё короче сделать». Чтобы «Замовлення
     постачальникам» осталось в одну строку, подпункты 12,5 и начинаются
     ближе к краю. */
  .sidebar { width: 212px; flex-basis: 212px; }
  .sidebar__link { font-size: 16px; min-height: 42px; gap: 10px; }
  .sidebar__link .ico { width: 20px; height: 20px; }
  .sidebar__sub { margin: 1px 0 6px 6px; padding-left: 2px; gap: 1px; }
  .sidebar__sub a { font-size: 12.5px; padding: 7px 5px; }
  .sidebar__me--stack { height: auto; padding: 12px 6px 10px; margin-bottom: 10px; }
  .sidebar__me--stack .ini--me { width: 44px; height: 44px; font-size: 15px; }
  .sidebar__me--stack .sidebar__me-name { font-size: 15px; line-height: 19px; }
  .sidebar__me--stack .sidebar__me-role { font-size: 13px; line-height: 17px; }
  /* «Налаштування» — к низу панели, только здесь (п. 14): «в мобильной
     версии вот как было, настройки там снизу… таким образом не будет вот
     здесь пусто» (05:51). На столе пункт просто идёт за разделами: сам он
     попросил «снизу настройки» под разделами, а не у края экрана. */
  .sidebar__link--foot { margin-top: auto; }
}

/* ── Разделы настроек (п. 18) ──────────────────────────────────────────── */
/* «Вот эти плашечки были белые, в данный момент они стали серые, сливаются со
   всем, что есть на фоне. Сделай просто их белыми… и возможно, чтобы
   подсвечивалась сама плашечка категории, в которой мы сейчас находимся,
   каким-то другим цветом» (07:10). Серыми они не «стали»: у плашки не было
   своего фона, сквозь неё шёл серый фон страницы телефона, а выбранная
   красилась --surface — почти тем же серым (#F4F8F7 на #F3F6F7). Теперь
   плашка белая, как островки, а выбранная — цветом раздела, как выбранная
   плитка счётчиков: мятная заливка и зелёный текст. На столе слева тот же
   принцип: страница там белая, и выбранный пункт виден заливкой. Ниже
   правила полосы 1100 по файлу нарочно — иначе её рамка перебила бы цвет. */
.settings-nav__link { background: var(--ground); }
.settings-nav__link:hover { background: var(--surface); color: var(--ink); }
.settings-nav__link--active,
.settings-nav__link--active:hover {
  background: var(--sec-bg); color: var(--sec-fg); border-color: var(--sec-line); font-weight: 600;
}
.settings-nav__link--soon,
.settings-nav__link--soon:hover { background: var(--ground); color: var(--muted); }
@media (max-width: 1100px) {
  .settings-nav__link { box-shadow: var(--island-shadow); }
  /* На полосе под пальцем серый :hover залипает после касания: остаётся
     белой, темнеет только рамка. */
  .settings-nav__link:hover { background: var(--ground); border-color: var(--line-strong); }
  .settings-nav__link--active, .settings-nav__link--active:hover {
    background: var(--sec-bg); border-color: var(--sec-line);
  }
}

/* «Де взяти ключ» в «Налаштування → SMS» — шаги оператора нумерованным
   списком. Поле браузера (40 точек) уводило номера вглубь от подписей
   формы; отступ по ширине цифры. */
.sms-steps { margin: 0 0 16px; padding-left: 20px; color: var(--ink-2); line-height: 1.55; }

/* ═══════════════════════════════════════════════════════════════════════ */
/* Дизайн-проход 03.10 — варианты, которые заказчик выбрал сам              */
/* ═══════════════════════════════════════════════════════════════════════ */
/* Видео 02.10, пункты 21–23 и 4 разбора docs/165: «админка слишком светлая —
   прогони два-три варианта». Показаны картинками docs/shots/design-02-10,
   03.10 он ответил цифрами: меню — «Графіт», счётчики — «давай попробуем как
   ты предложил», SMS — «синий, но чуть светлее» (это токены --ev-sms-* в
   tokens.css), настройки — карточку «залить таким же светло-серым, как у нас
   плитка заказов». И сверх картинок: «много серого в мобильной версии, где
   вверху сноска категорий, может её белой сделать».
   Секция последняя в файле нарочно: она меняет цвета, заданные выше, и
   побеждать должна порядком, а не !important. */

/* ── Левое меню «Графіт» ────────────────────────────────────────────────
   Те же селекторы, что выше по файлу, — меняются только цвета, раскладка и
   сворачивание не трогаются. Цвет в меню один: подсвеченный раздел. Значки
   разделов здесь гаснут до цвета подписи — шесть разных цветов на тёмном
   перетягивали бы на себя весь экран (так было на варианте с цветными). */
.sidebar { background: var(--nav-bg); border-right-color: var(--nav-line); }
/* На тёмном нужен светлый знак — тот же файл, что в тёмной теме. */
.sidebar .logo--light { display: none; }
.sidebar .logo--dark { display: block; }

.sidebar__link,
.sidebar__me,
.sidebar__link.btn--link { color: var(--nav-fg); }
.sidebar__link:hover,
.sidebar__me:hover,
.sidebar__link.btn--link:hover { background: var(--nav-hover-bg); color: var(--nav-fg); }
.sidebar__link--soon,
.sidebar__link--soon:hover,
.sidebar__me-role { color: var(--nav-muted); background: transparent; }
.sidebar__link--active,
.sidebar__link--active:hover,
.sidebar__me--on,
.sidebar__me--on:hover { background: var(--nav-active-bg); color: var(--nav-active-fg); }
.sidebar__link .ico,
.sidebar__link .ico--clients,
.sidebar__link .ico--leads,
.sidebar__link .ico--orders,
.sidebar__link .ico--warehouse,
.sidebar__link .ico--cash,
.sidebar__link .ico--sales { color: currentColor; }

/* Кружок инициалов: тот же зелёный тон, но на тёмной колонке — 3,3 : 1 к
   колонке и 5,2 : 1 инициалам (tests/test_nav.py меряет обе цифры). Кольцо —
   цвет колонки, а не светлая мята: светлое кольцо на тёмном читалось
   ободком-ошибкой. */
.ini--me { background: var(--nav-ini-bg); color: var(--nav-ini-fg); box-shadow: 0 0 0 3px var(--nav-line); }

/* Подменю: в потоке и всплывающей панелью — на том же тёмном. Белая панель
   вылетала бы из тёмной колонки заплаткой. */
.sidebar__sub { border-left-color: var(--nav-line); }
.sidebar__sub a { color: var(--nav-muted); }
.sidebar__sub a:hover { background: var(--nav-hover-bg); color: var(--nav-fg); }
.sidebar__sub a.on { color: var(--nav-active-fg); }
@media (min-width: 761px) {
  .sidebar__group:not(.sidebar__group--on):hover > .sidebar__sub,
  .sidebar__group:not(.sidebar__group--on):focus-within > .sidebar__sub {
    background: var(--nav-bg);
    border-color: var(--nav-line);
    border-left-color: transparent;
  }
  /* Подпись у свёрнутого меню всплывает рядом с колонкой — тоже тёмной. */
  .layout--mini .sidebar__t,
  .layout--mini .sidebar__me > .sidebar__t {
    background: var(--nav-bg);
    border-color: var(--nav-line);
    border-left-color: transparent;
    color: var(--nav-fg);
  }
  .layout--mini .sidebar__me-role { color: var(--nav-muted); }
  /* Всплывающая панель подменю — тем же кеглем, что пункты меню (14), а не
     12,5: «вот здесь чуть-чуточку ещё больше текста надо будет сделать для
     гармоничности» (видео 03.10 13:40, кадр с панелью склада). Подменю
     открытого раздела в самой колонке не трогаем: в 160 точках длинные
     подпункты склада и так встают в две строки. */
  .sidebar__group:not(.sidebar__group--on) > .sidebar__sub a { font-size: 14px; padding: 6px 12px; }
}

/* ── Счётчики над списками: без острова, у плиток лёгкая тень ──────────
   Его слова 02.10: «я просил сделать плашку вокруг плашек статистики; если её
   убрать и сделать небольшую тень этим плашкам — будет красивее». Остров
   (--island-bg с рамкой) снят, плитки отделены тенью, а не рамкой. Только на
   столе: на телефоне плитки и так лежат островками на сером. */
@media (min-width: 761px) {
  .counters--box { background: transparent; border: 0; padding: 0; }
  .counters--box .cnt {
    border-color: transparent;
    box-shadow: 0 1px 2px rgba(20, 29, 31, 0.05), 0 6px 16px rgba(20, 29, 31, 0.07);
  }
  body[data-section] .counters--box .cnt:first-child { border-color: transparent; }
}

/* ── Настройки: карточка формы светло-серая, как плитки заказов ─────────
   «Настройки — карточку… можем залить таким же светло-серым, как у нас
   плитка заказов» (03.10). Это --row-zebra, его «98 белым» (#FAFAFA): поля
   формы остаются белыми и проступают на сером — меньше сплошного белого. */
.settings-main .card { background: var(--row-zebra); }

/* ── Телефон: полоса вкладок раздела — белой, во всю ширину экрана ──────
   «Много серого в мобильной версии, где вверху сноска категорий, может её
   белой сделать» (03.10, его фото кассы и склада). Сначала стала белым
   островком со скруглёнными углами; на видео 03.10 13:40 он попросил её «по
   всей ширине экрана: если она будет залетать и сюда, и сюда, тогда… не будет
   выглядеть так, вроде она не полная». Вкладки листаются вбок и последняя
   обрезана краем — у островка это читалось как недорисованная рамка, у
   полосы от края до края — как продолжение. Отступ страницы на телефоне 12
   точек, на столько полоса и выходит в обе стороны. */
@media (max-width: 760px) {
  .wh-tabs {
    background: var(--ground);
    margin-left: -12px;
    margin-right: -12px;
    padding: 0 12px;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    box-shadow: none;
  }
}

/* ── Надходження на телефоне: видео 03.10 18:45 (IMG_4041, IMG_4042) ───── */
/* «+» у поля позиции — тот же combo__add, что у модели в карточке заказа.
   Новая строка уже стала новой номенклатурой — плюс ей не нужен. */
.rline--new .rline__new { display: none; }
/* Кнопки в конце формы видны всегда; на телефоне верхние прячутся: форма
   длинная, и «вернуться в самый верх, чтобы оприходовать» — ровно то, на что
   он жаловался. */
.receipt-form__foot { justify-content: flex-end; }
@media (max-width: 760px) {
  .receipt-form .head-card__actions { display: none; }
  .receipt-form__foot { justify-content: stretch; }
  .receipt-form__foot .btn { flex: 1 1 0; justify-content: center; }
}

/* ── Колір: свой список вместо <datalist> (04.10, фото с айфона) ───────── */
/* Строки списков — кнопки; без своего цвета кнопка берёт цвет браузера
   (чёрный), и в тёмной теме список выглядел пустым: чёрное на почти чёрном. */
.drop__i { color: var(--ink); }
.drop__c { color: var(--muted); }
/* Строка, подсвеченная стрелками, и цвет, который стоит сейчас. */
.drop__i--active { background: var(--surface); }
.drop__i--on { font-weight: 600; }
/* Семь с половиной строк: видно, что список листается дальше. */
.combo--color .combo__drop { max-height: 272px; }
/* Поле, поднятое к верху экрана над клавиатурой, — с подписью и зазором. */
.field--color { scroll-margin-top: 10px; }
/* Карточка поверх списка — <dialog>, у него цвет текста браузерный
   (CanvasText); как у .modal — свой. */
.overlay { color: var(--ink); }
/* «Своє, через кому» в тёмной теме было белым со светлым текстом. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ck-note input { background: var(--surface); }
}
:root[data-theme="dark"] .ck-note input { background: var(--surface); }

/* ── Продажі — этап 8 (06.10) ─────────────────────────────────────────── */
/* Список по макету client-billing-page.html :634-713, форма — :715-797.
   Красная сумма возврата и минус прибыли — токеном, не литералом: в тёмной
   теме красный свой. */
.sale-minus { color: var(--status-red-fg); }
.counters--sales { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

.sale-filters {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px;
  margin: 0 0 14px;
}
.sale-filters .field { margin: 0; min-width: 150px; }
.sale-filters__q { flex: 1 1 220px; }
.sale-filters__q input { width: 100%; }
.sale-filters__reset { align-self: center; font-size: 12.5px; white-space: nowrap; }
/* Ширины — фиксированной раскладкой, как у остатков склада: на 1024 с
   открытым меню таблица с ширинами в точках (сумма 756 + товары) вылезала
   из обёртки на 132 точки (check_widths 06.10). Длинное обрезается
   многоточием, полное — в title и в карточке. */
.sale-table .table { table-layout: fixed; }
.sale-table td { max-width: 0; }
.sale-table .col-num { width: 92px; }
.sale-table .col-goods { width: auto; }
.sale-table .col-client { width: 19%; }
.sale-table .col-pay { width: 15%; }
.sale-table .col-seller { width: 15%; }
.sale-table .col-sum { width: 140px; }
.sale-table .cell-main, .sale-table .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sale-table .col-pay .pill { margin: 0 4px 2px 0; }
.sale-table .who { max-width: 100%; }
.sale-table .who__n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sale-goods { display: block; }
.sale-hint { margin-top: 14px; }
.tile--sale .pill { margin-left: 4px; }

/* Форма: строки чека сеткой — название, количество, цена, гарантия, сумма, ×. */
.sale-combo .combo__drop { max-height: 320px; }
.sale-scan { font-size: 12.5px; }
.sale-flash { margin: 6px 0 0; }
.slines-head, .sline, .slines-total {
  display: grid; grid-template-columns: minmax(0, 1fr) 74px 104px 132px 96px 28px;
  gap: 8px; align-items: start;
}
.slines-head {
  margin-top: 14px; padding: 0 0 6px; border-bottom: 1px solid var(--line);
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.slines-head span:nth-child(2), .slines-head span:nth-child(3), .slines-head span:nth-child(5) { text-align: right; }
.slines-head span:nth-child(4) { padding-left: 10px; }
.sline { padding: 10px 0; border-bottom: 1px solid var(--line); }
.sline__name { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sline__title { font-weight: 550; overflow-wrap: anywhere; }
.sline__sub { font-size: 12px; color: var(--muted); }
.sline--short .sline__sub { color: var(--status-red-fg); }
.sline--short { background: var(--status-red-bg); }
.sline--error .sline__price, .sline--error .sline__qty { border-color: var(--status-red-fg); }
.sline__err { font-size: 12px; color: var(--status-red-fg); }
.sline__short { font-size: 12px; color: var(--status-red-fg); font-weight: 550; }
.sline__act { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.sline__act:empty { display: none; }
.sline__pieces { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.sline__pieces:empty { display: none; }
.sline__piece { font-size: 11.5px; }
.sline__qty, .sline__price { width: 100%; text-align: right; }
.sline__warranty { width: 100%; }
.sline__sum { text-align: right; padding-top: 8px; font-weight: 550; }
.sline__x { align-self: center; }
.slines { display: flex; flex-direction: column; }
.sale-form { max-width: 1280px; }
.slines-empty { margin: 12px 0 4px; }
.slines-total { padding-top: 10px; font-weight: 600; }
.slines-total span:nth-child(2), .slines-total span:nth-child(5) { text-align: right; }

.sale-client { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.sale-client__name { font-weight: 600; }
.sale-newclient { margin-bottom: 6px; }
.sale-seg { display: flex; width: 100%; }
.sale-seg .seg__i { flex: 1 1 0; }
.sale-seg .seg__i span { width: 100%; justify-content: center; }
.sale-split { display: flex; flex-direction: column; gap: 6px; }
.sale-split__row { display: grid; grid-template-columns: minmax(0, 1fr) 120px 28px; gap: 6px; align-items: center; }
.sale-split__row input { text-align: right; }
.sale-split__add { margin: 6px 0 10px; font-size: 12.5px; }
.sale-discount { margin: 4px 0 12px; }
.sale-discount__row { display: flex; gap: 8px; align-items: center; }
.sale-discount__row input { width: 110px; text-align: right; }
.seg--small .seg__i span { height: 30px; padding: 0 10px; }
.sale-totals { margin: 8px 0 12px; display: flex; flex-direction: column; gap: 4px; }
.sale-totals > div { display: flex; justify-content: space-between; gap: 12px; }
.sale-rest { color: var(--status-amber-fg); font-weight: 550; margin: 0 0 8px; }
.sale-rest--ok { color: var(--status-green-fg); }
.sale-pay-card .btn--wide { width: 100%; justify-content: center; }
.sale-submit2 { margin-top: 8px; }
.sale-profit .kv { grid-template-columns: 1fr; }
.kv--nar { grid-template-columns: 1fr; }
.kv--nar > div { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; }
.hint { font-size: 12.5px; color: var(--ink-2); margin: 8px 0 0; }
.hint--muted { color: var(--muted); }
.sale-error { margin-bottom: 12px; }
.sale-pieces { display: flex; flex-direction: column; gap: 6px; max-height: 50vh; overflow: auto; margin: 8px 0; }
.sale-piece { display: flex; gap: 8px; align-items: center; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer; }
.sale-piece input { flex: none; }
.sale-waiting { color: var(--status-amber-fg); }

/* Карточка и окно возврата. */
.sale-items td .cell-sub { display: block; }
.sale-items td .sale-qp { display: none; }
.sale-items .col-sum { white-space: nowrap; }
.plain-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.modal--wide { width: min(640px, calc(100vw - 24px)); max-width: none; overflow-x: hidden; }
.ret-lines { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.ret-line {
  display: grid; grid-template-columns: minmax(0, 1fr) 96px 96px; gap: 8px; align-items: center;
  padding: 8px 0; border-bottom: 1px solid var(--line);
}
.ret-line__name { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ret-line__pieces { display: flex; flex-direction: column; gap: 4px; }
.ret-line__qty { text-align: right; }
.ret-line__money { text-align: right; font-weight: 550; }
tr.row--return .cell-main { color: var(--ink-2); }
/* «Продажі» в «Звітах» — отдельный островок под блоками ремонтов. */
.rep-sales { margin-top: 14px; }
.rep-sales .field__label { margin: 4px 0 2px; }
.rep-sales .rep-cols { column-gap: 32px; }
.sale-filters__reset { align-self: flex-end; line-height: 36px; }
/* Строки чека — по ширине своей карточки, а не окна: на 768–900 и на
   1100–1300 с открытым меню колонка формы узкая, и названию оставались
   68–126 точек — слова рвались посреди (круг 3, 06.10). Раскладка «телефона»
   включается, когда карточке строк меньше 660 точек. */
.sale-lines-card { container-type: inline-size; }
@container (max-width: 660px) {
  .slines-head { display: none; }
  .sline {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 28px;
    grid-template-areas: "name name x" "qty price price" "warranty sum sum";
  }
  .sline__name { grid-area: name; }
  .sline__qty { grid-area: qty; }
  .sline__price { grid-area: price; }
  .sline__warranty { grid-area: warranty; }
  .sline__sum { grid-area: sum; padding-top: 6px; }
  .sline__x { grid-area: x; align-self: start; }
  /* «Разом 13 143 260,00» читалось одним числом: количество — с единицей
     подписью, сумма — справа. */
  .slines-total { grid-template-columns: minmax(0, 1fr) auto; }
  .slines-total span:empty { display: none; }
  .slines-total [data-total-qty] { display: none; }
}

@media screen and (max-width: 760px) {
  .sale-filters .field { min-width: 0; flex: 1 1 140px; }
  .sale-filters__q { flex-basis: 100%; }
  /* Счётчики — сеткой 2×2, как у кассы: лентой «середній чек» резался
     посреди слова, а четвёртого не было видно. */
  .counters--sales { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; overflow: visible; }
  .counters--sales .cnt { display: block; flex: none; padding: 9px 11px; }
  .counters--sales .cnt b { font-size: 17px; }
  /* Карточка продажи: «К-ть» и «Ціна» — строкой под названием, колонка
     «Сума» целиком (пятизначные суммы не помещались). */
  .sale-items .col-qty, .sale-items .col-price { display: none; }
  .sale-items td .sale-qp { display: block; }
  .sale-split__row { grid-template-columns: minmax(0, 1fr) 110px 28px; }
  .modal--wide { width: 100vw; max-width: 100vw; margin: auto 0; }
  .modal--wide .modal__card { border-radius: 12px; }
  .ret-line { grid-template-columns: minmax(0, 1fr) 80px; }
  .ret-line__pieces { grid-column: 1 / -1; }
  .ret-line__money { grid-column: 2; }
}

/* ── «Моя компанія» (этап 10) ──────────────────────────────────────────────
   Секция стоит в конце файла намеренно: позднее правило без медиазапроса
   перебивает ранний @media, поэтому мобильные правила страницы лежат внутри
   этой же секции, ниже настольных (память linetix-css-cascade-trap).

   Вид — вариант B, который заказчик выбрал 4 октября:
   docs/shots/my-company-04-10/2-B-komputer.png и B-phone.png. Цвета полос и
   значков — токены --mc-1…--mc-5 из tokens.css (во всех трёх темах), а не
   hex в разметке. */

.mc-icons { position: absolute; width: 0; height: 0; overflow: hidden; }
.mc-i {
  width: 18px; height: 18px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Значки вне меню остались бы залитыми чёрным: обводка висит только на
   .sidebar__link .ico. Поэтому у страницы свой класс со штрихом. */
.mc-head { align-items: flex-start; }
.mc-detail { white-space: nowrap; }
.mc-filters { margin-bottom: 14px; }

.mc-tiles {
  display: grid; gap: 10px; margin: 0 0 12px;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
/* Без права на закупочные цены плиток две, а не пять: растягивать их на всю
   ширину нечестно — тот же приём, что у счётчиков «Звітів» (.rep-kpis--two). */
.mc-tiles--two { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 640px; }
.mc-tile {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 2px;
  padding: 13px 14px 12px; border-radius: var(--r-island, 14px);
  background: var(--ground); border: 1px solid var(--mc-tile-line);
  box-shadow: var(--mc-tile-shadow);
}
/* Цветная полоса 3 px сверху — как на картинке B. */
.mc-tile::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--mc-c, var(--brand));
}
.mc-tile--revenue   { --mc-c: var(--mc-1); --mc-s: var(--mc-1-soft); }
.mc-tile--profit    { --mc-c: var(--mc-2); --mc-s: var(--mc-2-soft); }
.mc-tile--average   { --mc-c: var(--mc-3); --mc-s: var(--mc-3-soft); }
.mc-tile--per_order { --mc-c: var(--mc-4); --mc-s: var(--mc-4-soft); }
.mc-tile--share     { --mc-c: var(--mc-5); --mc-s: var(--mc-5-soft); }
.mc-tile__ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 8px; margin-bottom: 4px;
  background: var(--mc-s, var(--brand-soft)); color: var(--mc-c, var(--brand));
}
/* Сумму не обрезать многоточием: обрезанное число — враньё. Поэтому у плиток
   нет text-overflow, а на узких окнах они переносятся (см. медиазапросы). */
.mc-tile__v {
  font-family: var(--font-num); font-size: 22px; line-height: 1.15;
  font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.mc-tile__t { font-size: 13px; color: var(--ink-2); font-weight: 600; }
.mc-tile__h { font-size: var(--text-small); color: var(--muted); line-height: 1.4; }
.mc-tile__cmp {
  display: block; margin-top: 6px; font-style: normal;
  font-size: var(--text-small); color: var(--muted);
}

/* Сравнение «вровень»: у «Звітів» такого класса не было — там стрелка
   всегда вверх или вниз. На странице у доли бывает «0,0 п.п.». */
.rep-delta--flat { color: var(--muted); }

.mc-sales {
  margin: 0 0 14px; padding: 9px 12px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); font-size: 13px; color: var(--ink-2);
}

.mc-chart { margin-bottom: 14px; }
.mc-chart .card__title { display: flex; align-items: center; gap: 7px; }
.mc-side .card__title { display: flex; align-items: center; gap: 7px; }
.mc-chart__scroll { overflow-x: auto; }
/* Ряд 3 картинки B: «Замовлення» / «Робота майстрів» / «Час ремонту»,
   пропорции макета (mc_shots.py: 1.25fr 1.1fr .8fr). */
.mc-cols { display: grid; grid-template-columns: 1.25fr 1.1fr .8fr; gap: 14px; align-items: start; }

.mc-line { margin: 0 0 8px; font-size: 13px; color: var(--ink-2); }
.mc-line--hint { color: var(--muted); font-size: var(--text-small); }
.mc-line--total { margin-top: 10px; font-weight: 600; color: var(--ink); }

.mc-bars { display: flex; flex-direction: column; gap: 9px; }
.mc-bar__l { font-size: 13px; color: var(--ink-2); }
/* display: block обязателен: это <span>, а строчному элементу высота не
   действует — полоса просто не рисуется (поймано на снимке экрана). */
.mc-bar__track {
  display: block; height: 7px; border-radius: 100px;
  background: var(--surface-2); overflow: hidden;
}
.mc-bar__track > i { display: block; height: 100%; background: var(--mc-b, var(--brand)); }
.mc-bar--issued           { --mc-b: var(--mc-1); }
.mc-bar--issued_no_repair { --mc-b: var(--mc-5); }
.mc-bar--refused          { --mc-b: var(--status-red-fg); }
.mc-bar--donors           { --mc-b: var(--mc-3); }
.mc-bar--master           { --mc-b: var(--mc-2); }
.mc-bar .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.mc-bar__s { display: block; margin-top: 3px; font-size: var(--text-small); color: var(--muted); }
.mc-bar--master { padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.mc-bar--master:last-child { border-bottom: 0; }

/* Ноутбук с открытым меню: пять колонок дают около 118 px, и суммы
   обрезались бы. Переносим плитки, а не режем числа. */
@media (min-width: 761px) and (max-width: 1300px) {
  .mc-tiles:not(.mc-tiles--two) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media screen and (max-width: 760px) {
  /* Телефон: плитки 2×2, пятая во всю ширину — как на B-phone.png. */
  .mc-tiles { grid-template-columns: 1fr 1fr; }
  .mc-tiles .mc-tile:nth-child(5) { grid-column: 1 / -1; }
  .mc-tile__v { font-size: 20px; }
  .mc-cols { grid-template-columns: 1fr; }
  /* Кнопка «Детально у „Звітах“» — под подзаголовком, слева. */
  .mc-head { flex-direction: column; gap: 8px; }
}

/* «Моя компанія»: ряд графика и «Очікується», плашки «на зараз» (этап 10,
   ряд 2 и блок «Замовлення» картинки B). */
.mc-cols--chart { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; align-items: start; margin-bottom: 14px; }
.mc-cols--chart.mc-cols--alone { grid-template-columns: 1fr; }
.mc-cols--chart .mc-chart { margin-bottom: 0; }
.mc-big {
  display: block; font-family: var(--font-num); font-size: 24px; font-weight: 650;
  color: var(--ink); font-variant-numeric: tabular-nums; margin-bottom: 2px;
}
.mc-bar__track--wide { display: block; height: 9px; margin: 10px 0 8px; }
.mc-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.mc-legend__i { display: inline-flex; align-items: center; gap: 5px; font-size: var(--text-small); color: var(--muted); }
.mc-legend__i::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--mc-b, var(--brand)); }
.mc-legend__i--paid { --mc-b: var(--mc-1); }
.mc-legend__i--rest { --mc-b: var(--mc-5); }
.mc-legend__i .num { color: var(--ink-2); }
.mc-expected .mc-bar__track > i { background: var(--mc-1); }
.mc-expected .mc-bar__track { background: var(--mc-5-soft); }

.mc-now { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.mc-now__i {
  display: flex; flex-direction: column; gap: 1px; flex: 1 1 86px;
  padding: 8px 10px; border-radius: var(--radius); text-decoration: none;
  background: var(--mc-n-bg, var(--surface)); color: var(--mc-n-fg, var(--ink-2));
}
.mc-now__i b { font-family: var(--font-num); font-size: 19px; font-variant-numeric: tabular-nums; }
.mc-now__i span { font-size: var(--text-small); }
.mc-now__i--open { --mc-n-bg: var(--status-blue-bg); --mc-n-fg: var(--status-blue-fg); }
.mc-now__i--ready { --mc-n-bg: var(--status-green-bg); --mc-n-fg: var(--status-green-fg); }
.mc-now__i--overdue { --mc-n-bg: var(--status-red-bg); --mc-n-fg: var(--status-red-fg); }
a.mc-now__i:hover { filter: brightness(.97); }

@media screen and (max-width: 760px) {
  .mc-cols--chart { grid-template-columns: 1fr; }
}

.mc-time__second {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line);
}
.mc-big--second { font-size: 20px; }
@media (min-width: 761px) and (max-width: 1100px) {
  /* На ноутбуке три колонки дают узкие блоки: «Час ремонту» уходит под них. */
  .mc-cols { grid-template-columns: 1fr 1fr; }
  .mc-cols .mc-time { grid-column: 1 / -1; }
}

/* Строки блоков по картинке B: подпись и число одной строкой, полоса под
   ними во всю ширину; у «Замовлень» сверху ещё сводная полоса из долей. */
.mc-bar { display: block; }
.mc-bar__top {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-bottom: 4px;
}
.mc-bar__track--sum { display: flex; height: 8px; margin: 10px 0 12px; }
.mc-seg { display: block; height: 100%; background: var(--mc-b, var(--brand)); }
.mc-seg--issued { --mc-b: var(--mc-1); }
.mc-seg--issued_no_repair { --mc-b: var(--mc-5); }
.mc-seg--refused { --mc-b: var(--status-red-fg); }
.mc-seg--donors { --mc-b: var(--mc-3); }
.mc-rows { margin-top: 8px; }

/* Пиковый столбец графика — оранжевый, как на картинке B. Класс приходит
   только со страницы «Моя компанія» (mark_peak=True), в «Звітах» его нет. */
.rep-chart__bar--peak { fill: var(--mc-5); }

/* График страницы: широкая картинка на столе, узкая — на телефоне. Узкая
   рисуется отдельно (своя система координат), потому что растянутая широкая
   даёт подписи осей около четырёх точек — их не прочесть. */
.mc-chart__wide { overflow-x: auto; }
.mc-chart__narrow { display: none; }
.mc-chart__tip {
  margin: 8px 0 0; padding: 8px 10px; border-radius: var(--radius);
  background: var(--surface-2); color: var(--ink-2); font-size: 13px;
}
@media screen and (max-width: 760px) {
  .mc-chart__wide { display: none; }
  .mc-chart__narrow { display: block; }
  /* У «Звітів» график на телефоне прокручивается вбок (min-width: 560px).
     Здесь обещано «целиком по ширине экрана» — переопределяем только своим
     классом, чужой график не трогаем. */
  .mc-chart__narrow .rep-chart__svg { min-width: 0; width: 100%; }
}

/* ── Период одной кнопкой «как в Gincore» (этап 10, решение Д) ──────────── */
.period { position: relative; }
.period__native--off { display: none !important; }
.period__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; min-height: 36px; padding: 7px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--ground); color: var(--ink); font: inherit; text-align: left;
  font-variant-numeric: tabular-nums; cursor: pointer;
}
.period__btn::after {
  content: ""; width: 8px; height: 8px; flex: none;
  border-right: 1.6px solid var(--muted); border-bottom: 1.6px solid var(--muted);
  transform: rotate(45deg) translate(-2px, -2px);
}
.period__btn:hover { border-color: var(--brand); }
.period__btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.period__pop {
  position: absolute; z-index: 90; top: calc(100% + 4px); left: 0; min-width: 240px;
  padding: 6px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--ground); box-shadow: 0 10px 30px rgba(20, 29, 31, .14);
  display: flex; flex-direction: column; gap: 1px; max-height: min(70vh, 560px);
  overflow-y: auto;
}
.period__i {
  display: block; width: 100%; padding: 8px 10px; border: 0; border-radius: 6px;
  background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.period__i:hover { background: var(--surface); }
.period__i:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.period__i--on { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.period__i--custom { border-top: 1px solid var(--line); border-radius: 0 0 6px 6px; margin-top: 4px; }
/* Поле дат показывается, только когда выбран «Вибрати період». */
.period__dates--off { display: none; }
.period__dates { padding: 6px 4px 2px; }
/* Встроенный календарь: в потоке списка, без своей тени и рамки. */
.dp--inline {
  position: static; box-shadow: none; border: 0; padding: 0; margin-top: 4px;
}
@media screen and (max-width: 760px) {
  /* На телефоне список во всю ширину экрана, календарь — одним месяцем
     (этим занимается сам daterange.js по ширине окна).

     max-height здесь — только запас на случай, если скрипт не успел:
     настоящую высоту ставит period.js от нижней кромки кнопки до низа
     экрана. Было `calc(100dvh - 16px)` — список начинается на 260 px ниже
     верха, и разрешённые 828 px уводили календарь под край: с 390×844
     числа после 20-го выбрать было нельзя вовсе, и внутренняя прокрутка не
     включалась, потому что по мнению браузера список помещался. */
  .period__pop {
    position: fixed; left: 8px; right: 8px; top: auto; min-width: 0;
    max-height: calc(100dvh - 16px);
  }
  /* Кнопка с датами — во всю ширину острова, как поле дат рядом: на 390 ей
     достаётся 167 px, и подпись «01.09.2026 – 30.09.2026» переносилась в
     две строки, а соседнее поле «Філія» оставалось в одну. */
  .rep-filters .period { grid-column: 1 / -1; }
  /* С чатом поддержки (этап 9) в правом нижнем углу висит его кружок:
     84–144 px от низа экрана (customStyle в billing/_support_chat.html), а
     список кончается в 16 px от низа. Прокрученный до конца, он оставлял
     под кружком правый столбец последних недель календаря — «29» и «5» в
     березні 2026 на 390×844, — а дальше не крутится. Запас снизу даёт
     докрутить хвост выше кружка: 144 − 16 + 8 = 136 px. */
  .content--chat .period__pop { padding-bottom: 136px; }
}
.period__btn { white-space: nowrap; }

/* ── Картинка B построчно: то, чего не хватало после первого круга ──────── */

/* Стрелка у сравнения с прошлым периодом. На картинке B она есть у каждой
   плитки: «▲ +12 %», «▼ −1,8 п.п.». Только у плиток — в «Звітах»
   написание принято и менять его нельзя. */
.mc-tile__cmp .rep-delta--up::before { content: "▲"; }
.mc-tile__cmp .rep-delta--down::before { content: "▼"; }
.mc-tile__cmp .rep-delta--up::before,
.mc-tile__cmp .rep-delta--down::before {
  margin-right: 3px; font-size: 8px; line-height: 1; vertical-align: 1px;
}

/* Значок в шапке блока — в тонированном квадрате своего цвета, как у
   плиток (на картинке B чертёж синий, песочные часы янтарные, заказы
   синие, мастера фиолетовые, часы бирюзовые). */
.mc-badge {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 26px; height: 26px; border-radius: 8px;
  background: var(--mc-s, var(--brand-soft)); color: var(--mc-c, var(--brand));
}
.mc-badge--1 { --mc-c: var(--mc-1); --mc-s: var(--mc-1-soft); }
.mc-badge--2 { --mc-c: var(--mc-2); --mc-s: var(--mc-2-soft); }
.mc-badge--3 { --mc-c: var(--mc-3); --mc-s: var(--mc-3-soft); }
.mc-badge--4 { --mc-c: var(--mc-4); --mc-s: var(--mc-4-soft); }
.mc-badge--5 { --mc-c: var(--mc-5); --mc-s: var(--mc-5-soft); }

/* Столбцы с переливом сверху вниз — как на картинке B. Цвета берутся из
   токенов, поэтому тёмная тема получает свою пару сама. Пик остаётся
   оранжевым: правило ниже и той же силы. */
.mc-chart .rep-chart__g0 { stop-color: var(--mc-1); }
.mc-chart .rep-chart__g1 { stop-color: var(--brand); }
.mc-chart__wide .rep-chart__bar { fill: url(#mcg-wide); }
.mc-chart__narrow .rep-chart__bar { fill: url(#mcg-narrow); }
.mc-chart__wide .rep-chart__bar--peak,
.mc-chart__narrow .rep-chart__bar--peak { fill: var(--mc-5); }

/* Карточки ряда начинаются вровень и заканчиваются вровень. `.card + .card`
   задуман для карточек стопкой, а в сетках ряда они прямые соседи — и
   второй доставался отступ сверху: ступенька в 12 px на всех широких
   окнах. Высоту выравниваем stretch вместо start: на картинке B низы
   карточек ряда лежат на одной линии. На телефоне колонка одна, и там
   отступ как раз нужен — поэтому только от 761 px. */
@media (min-width: 761px) {
  /* Сила правила — не меньше, чем у `.card + .card` (два класса),
     иначе отступ остаётся на месте: ступенька была видна и после
     первой попытки, замер показал верх 746 и 758. */
  .mc-cols > .card + .card, .mc-cols--chart > .card + .card { margin-top: 0; }
  .mc-cols > * + *, .mc-cols--chart > * + * { margin-top: 0; }
  .mc-cols, .mc-cols--chart { align-items: stretch; }
}


/* ======================================================================
   Этап 9: подписки — публичные страницы, карточки тарифов, полоса срока.
   11.10.2026

   Классы макета (.pub, .plans, .plan*) в продукте не существовали: это
   первые страницы без сайдбара. Геометрия взята из исходника макета
   (kit.py: радиус 14px, padding 22px, цена 32px/600, список через
   border-top), но на токенах продукта, а не на «своих» цветах — иначе
   тёмная тема получилась бы светлой.

   Мобильные переопределения лежат ЗДЕСЬ ЖЕ, ниже своих правил: файл растёт
   приписками в конец, и обычное правило в конце молча перебивает
   медиазапрос из ранней секции. На этом уже ломалась карточка на телефоне.
   ====================================================================== */

.pub {
  max-width: 1040px;
  margin: 0 auto;
  padding: 24px 16px 40px;
}
.pub__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 36px;
}
.pub__logo { display: inline-flex; text-decoration: none; }
.pub__nav { display: flex; gap: 8px; flex-wrap: wrap; }

.pub__h { text-align: center; margin: 0 auto 32px; max-width: 720px; }
.pub__h h1 { font-size: 30px; line-height: 1.2; margin: 0 0 12px; color: var(--ink); }
.pub__h p { margin: 0; color: var(--ink-2); font-size: var(--text-subtitle); }

/* Три карточки в ряд на столе. На телефоне жёсткий repeat(3,1fr) выносил
   бы страницу вбок, и check_widths это ловит на тринадцати ширинах. */
.plans {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 16px; align-items: start;
}
.plan {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 22px 22px 24px;
}
/* Выделен СРЕДНИЙ тариф, а не старший: приём макета, который заказчик
   хвалил. Обводка токеном --ink, поэтому в тёмной теме она не кричит. */
.plan--on { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }
.plan__n { font-size: 17px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 8px; }
.plan__badge {
  font-size: var(--text-small); font-weight: 500;
  background: var(--brand-soft); color: var(--brand);
  border-radius: var(--radius-chip); padding: 2px 10px;
}
.plan__x { color: var(--muted); font-size: var(--text-subtitle); margin: 6px 0 16px; }
.plan__p { display: flex; align-items: baseline; gap: 8px; margin-bottom: 16px; }
.plan__p b { font-size: 32px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.plan__p span { color: var(--muted); font-size: var(--text-subtitle); }
.plan__l { list-style: none; margin: 16px 0 0; padding: 16px 0 0; border-top: 1px solid var(--line); }
.plan__l li { display: flex; gap: 8px; padding: 5px 0; font-size: var(--text-subtitle); color: var(--ink-2); }
.plan__l i { font-style: normal; color: var(--brand); }
.plan__warn {
  margin: 12px 0 0; padding: 8px 10px;
  background: var(--status-amber-bg); color: var(--status-amber-fg);
  border-radius: var(--radius); font-size: var(--text-small);
}
.plan select.input { margin-bottom: 8px; }

.pub__foot { text-align: center; color: var(--muted); font-size: var(--text-subtitle); margin-top: 28px; }

.pub__text { max-width: 760px; margin: 0 auto; }
.pub__text h1 { font-size: 24px; margin: 0 0 18px; color: var(--ink); }
.pub__text p { color: var(--ink-2); line-height: 1.6; }

.pub__f { margin-top: 44px; padding-top: 20px; border-top: 1px solid var(--line); }
.pub__links { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 12px; }
.pub__links a { color: var(--ink-2); font-size: var(--text-subtitle); }
.pub__req { margin: 2px 0; color: var(--muted); font-size: var(--text-small); }

/* Полоса «підписку не оплачено». Берём готовый блок найденной заявки и
   перекрашиваем его токенами статуса — в макете тут стоял инлайновый
   #EBD5AE, и в тёмной теме это была бы светлая рамка на тёмном. */
.lead-found--billing {
  background: var(--status-amber-bg);
  border-color: var(--status-amber-fg);
}
.lead-found--billing .lead-found__h { color: var(--status-amber-fg); font-weight: 600; }
.lead-found--billing .lead-found__b form { display: inline-flex; }

@media (max-width: 760px) {
  .plans { grid-template-columns: 1fr; }
  .pub__h h1 { font-size: 23px; }
  .pub__top { margin-bottom: 24px; }
  .pub { padding: 16px 16px 32px; }
}


/* ======================================================================
   Правки «Моєї компанії» по его сообщению 11.10. Четыре из пяти: пятая
   (размер выпадающего списка периода) ждёт его снимок.
   ====================================================================== */

/* 1. «Само наименование фильтра — „ПЕРІОД“ „ФІЛІЯ“ — лучше убрать капс».
   Капс приходит из общего .field__label; здесь он снимается на обеих
   страницах с этим блоком фильтров — «Моя компанія» и «Звіти», — иначе
   одинаковые подписи на соседних экранах выглядели бы по-разному. */
.rep-filters .field__label {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
}

/* 2. «Период лучше расположить в одном ряду с фильтром по филии, две
   плашки одинакового размера (можно меньше шрифт)». На «Моїй компанії»
   полей всего два, а сетка была на четыре колонки: поля получались разной
   ширины и занимали половину ряда. */
.mc-filters { grid-template-columns: 1fr 1fr; }
.mc-filters .dates-range { grid-column: auto; }
.mc-filters .field__label,
.mc-filters select,
.mc-filters .period__btn { font-size: var(--text-small); }

/* 3. «Плашка „продажи за период“ сильно сливается с задним фоном — можно
   сделать таким же, как шапка в таблицах». Берём те же токены, что у
   thead, поэтому тёмная тема получается сама. */
.mc-sales {
  background: var(--thead-bg);
  border-color: var(--thead-line);
  color: var(--thead-fg);
}

@media (max-width: 760px) {
  /* 4. «Кнопка „подробно в отчетах“ с моб версии занимает много места».
     Была кнопкой во всю ширину под подзаголовком; стала короткой ссылкой
     в строке, без рамки и без лишней высоты. */
  .mc-detail {
    align-self: flex-start;
    padding: 0; height: auto; min-height: 0;
    border: 0; background: none;
    color: var(--brand); font-size: var(--text-small);
  }
  .mc-detail:hover { background: none; text-decoration: underline; }
}

/* Второй круг по снимкам 11.10 — то, что увидели глаза, а не тест. */

/* Подпись и подвал страницы тарифов — двумя строками, как в макете. */
.pub__h p { margin: 0 0 2px; }
.pub__foot p { margin: 0 0 2px; }

@media (max-width: 480px) {
  /* На 390 логотип и две кнопки в одной строке налезали друг на друга:
     логотип широкий, кнопки переносились и слипались. */
  .pub__top { flex-direction: column; align-items: stretch; gap: 10px; }
  .pub__nav { width: 100%; }
  .pub__nav .btn { flex: 1 1 0; justify-content: center; }
}

@media (max-width: 760px) {
  /* «Период лучше расположить в одном ряду с фильтром по филии, две плашки
     одинакового размера (можно меньше шрифт)». Смотрел он с телефона —
     значит и в один ряд надо именно здесь, а не только на столе. */
  .mc-filters { grid-template-columns: 1fr 1fr; gap: 8px; padding: 10px; }
  .mc-filters .dates-range { grid-column: auto; }
  /* Выше по файлу кнопка периода на телефоне нарочно занимает весь ряд: на
     390 ей доставалось 167 px и подпись с датами переносилась в две строки.
     Здесь заказчик попросил обратное — «две плашки одинакового размера,
     можно меньше шрифт». Поэтому возвращаем её в свою колонку и уменьшаем
     шрифт ровно настолько, чтобы «01.10.2026 – 11.10.2026» встало в строку.
     Только на «Моїй компанії»: на «Звітах» полей четыре, там это сломало бы
     ряд. */
  .mc-filters .period { grid-column: auto; }
  .mc-filters .period__btn { font-size: 11px; padding-left: 6px; padding-right: 6px; }
  .mc-filters .field__label { font-size: 11px; }
  .mc-filters select,
  .mc-filters .period__btn { font-size: 12px; padding-left: 8px; padding-right: 8px; }
}

/* Строка-сводка подписки: пять пар «значение/подпись» в ряд. На 320–414
   точках они выносили страницу вбок до 432 — нашла проверка ширин, не
   глаза. Перенос именно здесь, а не у всех .role-sum: на странице ролей
   пар две, и там ряд в одну строку стоит сознательно. */
.sub-sum { flex-wrap: wrap; gap: 14px 22px; }
.sub-sum > div { min-width: 0; }
@media (max-width: 480px) {
  .sub-sum { gap: 10px 16px; padding: 10px 12px; }
}

/* ── Поддомены и «Зручний вхід» (этап 9) ─────────────────────────── */

/* Адрес сервиса в регистрации: поле и хвост домена одной плашкой —
   человек видит адрес целиком, как его откроет браузер. Хвост не
   выбирается мышью и не уезжает на новую строку. */
.addr { display: flex; align-items: stretch; min-width: 0; }
.addr input { flex: 1 1 auto; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.addr__suffix {
  display: flex; align-items: center; flex: none;
  padding: 0 10px; border: 1px solid var(--line-strong); border-left: 0;
  border-radius: 0 var(--r-field) var(--r-field) 0;
  background: var(--surface); color: var(--muted);
  font-size: 13px; white-space: nowrap; user-select: none;
}
@media (max-width: 420px) {
  .addr__suffix { padding: 0 7px; font-size: 12px; }
}

/* Поле-ловушка регистрации: за краем экрана, а не display:none — часть
   ботов поля с display:none пропускает и ловушку бы обошла. */
.hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* Выбор сервиса, когда почта и пароль совпали в нескольких. Строка —
   целиком кнопка: попасть пальцем по маленькой ссылке на телефоне трудно. */
.choose { display: flex; flex-direction: column; gap: 8px; }
.choose form { margin: 0; }
.choose__item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; padding: 11px 14px; text-align: left; cursor: pointer;
  border: 1px solid var(--line-strong); border-radius: var(--r-field);
  background: var(--ground); color: var(--ink); font: inherit;
}
.choose__item:hover, .choose__item:focus-visible { border-color: var(--brand); }
.choose__name { font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }
.choose__host { color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }

/* Оплата на странице «Підписка» (этап 9): галочка согласия с офертой и
   автосписанием стоит прямо над кнопкой — её нельзя не увидеть, и текст
   переносится, а не выносит страницу вбок на телефоне. */
.pay-form { margin-top: 14px; max-width: 560px; }
.pay-consent { align-items: flex-start; gap: 9px; margin-bottom: 12px; }
.pay-consent input { flex: none; margin-top: 2px; }
.pay-consent span { font-size: var(--text-subtitle); line-height: 1.4; overflow-wrap: anywhere; }
.plan__q { margin: -4px 0 10px; color: var(--muted); font-size: 12px; }


/* ======================================================================
   Этап 9, круг «Экраны: телефон и тёмная тема», 12.10.2026.
   Всё ниже найдено глазами на снимках (docs/shots/stage9-12-10-screens),
   ни один тест этого не ловил. Блок последний в файле нарочно: телефонные
   правила здесь перебивают общие поздних секций, а не наоборот.
   ====================================================================== */

/* Полоса срока и плашка тестовой страницы банка. Заголовок там — <p>, и
   браузерный отступ в 13 px делал поле над заголовком вдвое больше поля
   под кнопками и отрывал заголовок от текста. В макете они вплотную. */
.lead-found--billing .lead-found__h { margin: 0; }
.lead-found--billing .lead-found__x:last-child { margin-bottom: 0; }

/* Карточки тарифов. На телефоне фон страницы (#F3F6F7) и --surface
   карточки (#F4F8F7) совпадали — карточки держались одной рамкой, а в
   макете они светлее страницы. Заливка — как у карточек настроек
   (--row-zebra, его «98 белым»): отделяется и на сером, и в тёмной теме. */
.plan { background: var(--row-zebra); }

/* Выбор тарифа на планшете и узком ноутбуке. «Поточний тариф — змінити
   строк» не переносилась, и средняя карточка брала ширину по этой кнопке:
   на 768 крайние сжимались до 145 px, текст согласия рвался по буквам, а
   страница уезжала вбок на 2 px (check_widths, плательщик). Колонки
   равные, длинная подпись кнопки переносится. Телефонная одна колонка —
   заново в медиазапросе ниже: это правило иначе перебило бы её. */
.plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.plan .btn--wide {
  white-space: normal; height: auto; min-height: 36px;
  padding-top: 7px; padding-bottom: 7px; line-height: 1.25; text-align: center;
}

/* Публичные страницы — как на утверждённой картинке тарифов
   (docs/shots/billing-mockup-07-10/4-…png): страница серая, карточки
   тарифов белые. Было наоборот: правило «на столе фон белый» (07.09)
   сделано для кабинета и делало белой и эту страницу, а карточки были
   серыми. Схема та же, что у экранов входа (.auth: --surface и --ground),
   поэтому все страницы до входа выглядят одинаково и в тёмной теме. */
.pub-body { background: var(--surface); }
.pub-body .plan { background: var(--ground); }

/* Плашка-предупреждение вне карточки тарифа (службова, заблокована) липла
   к карточкам снизу, в карточке «Підписки» — к строке-сводке. */
.settings-main > .plan__warn { margin-bottom: 14px; }
.card > .plan__warn { margin-bottom: 12px; }

/* «Оплачений строк почнеться …» стояла вплотную над кнопкой оплаты. */
.pay-form .hint { margin: 0 0 10px; }

/* Адрес сервиса в регистрации «одной плашкой» не складывался: общее
   правило полей (три :not() — специфичность 0,3,1) возвращало полю правые
   скругления, и между полем и хвостом домена торчали уголки. */
.addr input:not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

/* Сумма на тестовой странице банка: подпись мельче суммы и стояла выше
   её строки. */
.auth .pay-totals > div { align-items: baseline; }

/* Кабинет платформы, «Керування сервісом»: строки «подпись — поле —
   кнопка». Подписи разной длины сдвигали поля («Тариф» начинался левее
   «Адреси сервісу»). */
.pl-row .field__label { flex: 0 0 110px; margin: 0; }
.pl-row .input { flex: 1 1 auto; min-width: 0; }
/* «минуло днів:» и число — одной строкой, число не остаётся сиротой. */
.pl-overdue { white-space: nowrap; }

/* Галочки в тёмной теме были браузерными белыми квадратами: color-scheme в
   проекте не задан (о том же — у .modal выше). Тёмная схема — только
   галочкам и переключателям: поля и списки покрашены токенами сами. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) input[type="checkbox"],
  :root:not([data-theme="light"]) input[type="radio"] { color-scheme: dark; }
}
:root[data-theme="dark"] input[type="checkbox"],
:root[data-theme="dark"] input[type="radio"] { color-scheme: dark; }

@media (max-width: 760px) {
  /* Карточки тарифов на телефоне — одной колонкой (см. .plans выше). */
  .plans { grid-template-columns: 1fr; }
  /* Пальцем мимо: кнопки полосы срока и «Вимкнути автосписання» — 30 px,
     «Скасувати підписку» и «Заблокувати» — 18 px. */
  .lead-found--billing .btn--small,
  .sub-actions .btn--small { height: 36px; }
  .sub-actions .btn--link,
  .pl-row .btn--link { min-height: 36px; }
  /* Счётчики кабинета платформы — 2×2, как у кассы и продаж: в строку
     четвёртый уходил за край экрана. */
  .counters--platform { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; overflow: visible; }
  .counters--platform .cnt { display: block; flex: none; padding: 9px 11px; }
  .counters--platform .cnt b { font-size: 17px; }
  /* «Забули адресу сервісу?» и «Забули пароль?» — 19 px высотой. */
  .auth__row { margin-bottom: 8px; }
  .auth__row a { display: inline-block; padding: 9px 0; }
}

@media (max-width: 480px) {
  /* Публичные страницы: «Увійти» и «Спробувати безкоштовно» — 30 px, ссылки
     подвала (оферта, политика, повернення) — 19 px. */
  .pub__nav .btn { height: 40px; }
  .pub__links { gap: 0 16px; margin-bottom: 6px; }
  .pub__links a { display: inline-block; padding: 9px 0; }
  /* Кабинет платформы: подпись над полем, поле во всю ширину — на 320
     поле адреса сжималось до 70 точек. */
  .pl-row { flex-wrap: wrap; gap: 8px; }
  .pl-row .field__label { flex-basis: 100%; }
  .pl-row .input { flex-basis: 100%; }
  /* История платежей «Підписки»: «Сума» на 390 уходила за край обёртки.
     «Спосіб» на телефоне спрятан — почти всегда это «Картка». */
  .sub-payments th:nth-child(3), .sub-payments td:nth-child(3) { display: none; }
  .sub-payments th, .sub-payments td { padding-left: 8px; padding-right: 8px; }
}
