/* Палитра держится на одном синем. Нейтрали уведены в его сторону — серый
   без примеси выглядит не выбранным, а доставшимся по умолчанию. Приглушённый
   и бледный текст затемнены до контраста 4.5 и выше: диспетчер читает мелкие
   подписи весь день, а прежние оттенки на белом давали 3:1 и разбирались
   только на хорошем мониторе. */
:root {
  --bg: #f1f3f7;
  --surface: #ffffff;
  --surface-2: #f7f9fc;
  --border: #e3e7ee;
  --border-strong: #c8cfdb;
  --text: #141821;
  --text-dim: #525b6b;
  --text-faint: #6b7482;
  --accent: #1d4ed8;
  --accent-hover: #1a43b8;
  --accent-soft: #e7eefd;
  /* Что пишем поверх яркой заливки. В светлой теме сама заливка
     тёмная, и белый на ней читается; в тёмной всё наоборот. */
  --on-accent: #ffffff;
  --danger: #d92d20;
  --danger-soft: #fdecea;
  --warn: #b54708;
  --warn-soft: #fdf1e3;
  --warn-bd: rgba(181, 71, 8, .35);
  --ok: #0b7a4b;
  --ok-soft: #e6f4ed;
  --sidebar: #151922;
  --sidebar-text: #a8b0bd;
  --sidebar-dim: #7d8798;
  --sidebar-active: #ffffff;
  /* В светлой теме тёмное меню и так отделено от содержимого. */
  --sidebar-edge: transparent;

  /* Пять ступеней рейтинга: от «без единой претензии» до «спорят постоянно». */
  --rate-top: #06603a;   --rate-top-bg: #ddf3e8;  --rate-top-bd: rgba(6, 96, 58, .3);
  --rate-good: #3f7d1f;  --rate-good-bg: #eaf5df; --rate-good-bd: rgba(63, 125, 31, .3);
  --rate-mid: #8a6100;   --rate-mid-bg: #fbf1d8;  --rate-mid-bd: rgba(138, 97, 0, .3);
  --rate-low: #b54708;   --rate-low-bg: #fdeee0;  --rate-low-bd: rgba(181, 71, 8, .3);
  --rate-bad: #b42318;   --rate-bad-bg: #fdeae8;  --rate-bad-bd: rgba(180, 35, 24, .3);

  --radius: 8px;
  /* Тень со смещением и мягким размытием. Прежняя лежала ровно под краем и
     на светлом фоне не читалась вовсе — карточки висели без глубины. */
  --shadow: 0 1px 2px rgba(19, 26, 46, .05), 0 4px 12px -3px rgba(19, 26, 46, .07);

  /* Движение. Выход экспоненциальный: быстро стартует, мягко доезжает. */
  --ease: cubic-bezier(.22, .8, .26, 1);
  --t-fast: .09s;
  --t-screen: .18s;
}

/* Тёмная тема разведена по ступеням заново: фон, карточка и вложенная
   поверхность различались на полтона и сливались, а тень в темноте не
   работает совсем — глубину там держат граница и разница светлот. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0a0d12;
    --surface: #1a2029;
    --surface-2: #212936;
    --border: #2c3542;
    --border-strong: #414b5a;
    --text: #e6e9ef;
    --text-dim: #99a3b2;
    --text-faint: #828d9e;
    --accent: #5b92f7;
    --accent-hover: #74a4f9;
    --accent-soft: #1b2740;
    --on-accent: #0b1220;
    --danger: #f87066;
    --danger-soft: #3a1d1c;
    --warn: #f0a35e;
    --warn-soft: #392718;
    --warn-bd: rgba(240, 163, 94, .35);
    --ok: #4ec38a;
    --ok-soft: #14301f;
    --rate-top: #55d19a;   --rate-top-bg: #0e2f20;  --rate-top-bd: rgba(85, 209, 154, .3);
    --rate-good: #9ed36a;  --rate-good-bg: #1e2c16;  --rate-good-bd: rgba(158, 211, 106, .3);
    --rate-mid: #e8c455;   --rate-mid-bg: #2f2812;  --rate-mid-bd: rgba(232, 196, 85, .3);
    --rate-low: #f0a35e;   --rate-low-bg: #38240f;  --rate-low-bd: rgba(240, 163, 94, .3);
    --rate-bad: #f87066;   --rate-bad-bg: #3a1a18;  --rate-bad-bd: rgba(248, 112, 102, .3);

    --sidebar: #05070c;
    --sidebar-text: #98a2b1;
    --sidebar-dim: #7d8798;
    /* А в тёмной оно чуть темнее фона и без границы сливается с ним. */
    --sidebar-edge: #2c3542;
    --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 6px 16px -4px rgba(0, 0, 0, .5);
  }
}

* { box-sizing: border-box; }

/* Поверхности, которые рисует браузер, а не мы: выделение, каретка, полосы
   прокрутки, системные контролы. По умолчанию они не принадлежат никакой теме
   и выдают собранную страницу — поэтому задаём их из той же палитры. */
:root { color-scheme: light dark; }
::selection { background: var(--accent-soft); color: var(--text); }
input, textarea, select { caret-color: var(--accent); }

* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }

/* Одна рамка фокуса на всё приложение. Раньше её видели только поля ввода,
   а кнопки, ссылки и вкладки клавиатурой проходились вслепую. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.nav a:focus-visible { outline-color: #fff; outline-offset: -2px; }

/* Правила ниже задают display контейнерам, а это перебивает браузерное
   [hidden] { display: none }. Без этой строки скрытие атрибутом не работает. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { margin: 0; font-weight: 600; }

/* ---------- Каркас ---------- */

.layout { display: grid; grid-template-columns: 224px 1fr; min-height: 100vh; }

/* Панель одна на все экраны и обе темы. Раньше градиент жил только на
   главной администратора, и человек, уходя с неё, видел другую панель —
   будто сменил систему. Цвета здесь свои, не из токенов: панель тёмная
   всегда, и в светлой теме тоже. */
.sidebar {
  background: linear-gradient(165deg, #254563, #142c45 65%);
  color: var(--sidebar-text);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  border-right: 0;
}

/* Шапка панели одна на все роли: «Поток» со знаком, под ним — чьё это
   место и какая организация. Раньше крупное написание со знаком жило
   только на главной администратора, а у сторон стояло «Кабинет
   исполнителя» без логотипа вовсе. */
.brand {
  padding: 22px 20px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
/* По базовой линии, а не по центру: знак — это буква, и низ у него должен
   стоять на той же строке, что и у слова. По центру он съезжал вниз на
   несколько точек, и слово со знаком читались как две отдельные вещи. */
.brand-name { display: flex; align-items: baseline; gap: 7px; }
.brand b {
  color: #fff;
  font-size: 22px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  line-height: 1;
}
/* На тёмной панели правый штрих знака почти сливается с фоном: у него и
   у панели один тон синего. Высветляем сам знак, а не подкладываем под него
   плашку или ореол — так на панели остаётся тот же логотип, только читаемый.
   На светлых экранах (вход, шапка главной) знак берётся из файла как есть. */
.brand .potok-mark {
  display: block;
  flex: none;
  width: auto;
  filter: brightness(1.3) saturate(1.06);
}
.brand span {
  display: block;
  margin-top: 9px;
  font-size: 9px;
  color: var(--sidebar-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  line-height: 1.5;
}

.nav { padding: 18px 12px; flex: 1; overflow-y: auto; }
.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 9px;
  color: var(--sidebar-text);
  font-size: 13px;
  margin-bottom: 3px;
}
.nav a:hover { background: rgba(255, 255, 255, .05); color: #fff; text-decoration: none; }
/* Где человек сейчас — светло-голубая полоска слева. Одной заливки на
   тёмном фоне мало: в списке из десяти разделов её не видно с первого
   взгляда, и люди теряли, куда попали. */
.nav a.active {
  background: #ffffff18;
  box-shadow: inset 3px 0 #64aaff;
  color: #fff;
  font-weight: 500;
}
.ico {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav a .ico { opacity: .75; }
.nav a:hover .ico, .nav a.active .ico { opacity: 1; }
.nav a .badge {
  margin-left: auto;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 10px;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 600;
}

.proto-note {
  padding: 12px 16px;
  font-size: 11px;
  color: var(--sidebar-dim);
  border-top: 1px solid rgba(255, 255, 255, .07);
  line-height: 1.4;
}

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

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar h1 { font-size: 18px; letter-spacing: -.2px; }
.topbar .spacer { flex: 1; }

.role-picker { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-dim); }
.role-picker select {
  font: inherit;
  padding: 5px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.content { padding: 22px 24px 60px; max-width: 1440px; width: 100%; }

/* Кнопка меню нужна только там, где меню спрятано. Селектор с .topbar —
   чтобы правило было сильнее .btn, иначе кнопка вылезает на десктопе. */
/* Кнопка меню должна оставаться нажимаемой и при открытой шторке: самый
   привычный жест — тапнуть бургер второй раз. Шторка накрывала шапку
   целиком, и попадание уходило в её логотип; закрыть меню можно было только
   тапом по узкой полосе справа. */
.nav-open .topbar .nav-toggle { position: relative; z-index: 60; }
.topbar .nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  align-items: center;
  justify-content: center;
  flex: none;
}
.nav-scrim { display: none; }
/* Пока открыто меню, страница за ним стоит на месте. */
body.nav-locked { overflow: hidden; }

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

  .sidebar {
    position: fixed;
    z-index: 40;
    left: 0;
    top: 0;
    width: 268px;
    max-width: 84vw;
    height: 100dvh;
    transform: translateX(-100%);
    transition: transform .18s ease-out;
    box-shadow: 12px 0 40px rgba(0, 0, 0, .45);
  }
  .layout.nav-open .sidebar { transform: none; }

  .layout.nav-open .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 30;
    border: 0;
    padding: 0;
    background: rgba(6, 8, 12, .55);
  }
  .topbar .nav-toggle { display: inline-flex; }

  .topbar { padding: 10px 14px; gap: 10px; }
  .topbar h1 { font-size: 16px; }
  .content { padding: 14px 14px 48px; }
  .card-body { padding: 14px; }

  /* Кто вошёл — видно и на телефоне: на общем компьютере в диспетчерской
     это первое, что надо проверить. Раньше этот блок с двумя кнопками стоял
     в шапке и съедал больше половины ширины — от названия экрана
     оставалось «Сд…». Теперь он переезжает вниз меню (см. app.js), где
     рядом с именем есть место и для «Пароля», и для «Выйти». */
  .topbar h1 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .sidebar > .user-box {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid rgba(255, 255, 255, .07);
  }
  .sidebar > .user-box .user-info { text-align: left; color: var(--sidebar-text); }
  .sidebar > .user-box .user-info b { color: var(--sidebar-active); font-size: 14px; }
  .sidebar > .user-box .user-info span { color: var(--sidebar-dim); }
  /* Светлая кнопка на чёрном меню бьёт по глазам — берём её тон
     оттуда же, откуда берёт подсветку выбранный пункт меню. */
  .sidebar > .user-box .btn {
    background: rgba(255, 255, 255, .06);
    border-color: rgba(255, 255, 255, .14);
    color: var(--sidebar-active);
    justify-content: center;
  }
  .sidebar > .user-box .btn:hover { background: rgba(255, 255, 255, .12); }

  /* Пальцем в цель 24 px не попадают. Поднимаем всё нажимаемое до сорока,
     а размер шрифта в полях — до шестнадцати: меньше, и Safari при фокусе
     приближает страницу. */
  .btn { min-height: 40px; padding: 9px 14px; }
  .btn-sm { min-height: 36px; padding: 7px 12px; }
  .nav a { padding: 11px 12px; }
  input[type=text], input[type=date], input[type=time], input[type=number],
  input[type=password], input[type=email], input[type=tel], select, textarea { min-height: 40px; font-size: 16px; }
  input[type=checkbox], input[type=radio] { width: 18px; height: 18px; }
  .doc-row, .work-row, .file-row { padding-top: 10px; padding-bottom: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
}

/* ---------- Общие блоки ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 18px;
}

/* Карточка заявки собирается как лист: у каждого раздела свой ясный заголовок,
   а документы и вложения располагаются парой по сторонам сделки. */
.deal-showcase { display: flex; flex-direction: column; gap: 16px; }
.deal-showcase .card { margin-bottom: 0; }
.client-order-sections,
.contractor-order-sections {
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}
.client-order-sections > div,
.contractor-order-sections > div { display: contents; }
.client-order-sections .card,
.contractor-order-sections .card { margin-bottom: 0; }
.deal-items, .deal-item-stack { display: grid; gap: 16px; }
/* Ячейка сетки по умолчанию не уже своего содержимого (min-width: auto), и
   таблица подбора подрядчиков шириной 760 растягивала карточку позиции, а с
   ней и всю страницу: на телефоне экран подбора ездил вбок на 776 точек.
   С нулём таблица прокручивается внутри своей обёртки, как и задумано. */
.deal-items > *, .deal-item-stack > * { min-width: 0; }
.deal-party-grid { align-items: stretch; }
.deal-party-grid > div { min-width: 0; }
.deal-party-grid .card { height: 100%; }
.deal-section > h2 { min-height: 48px; display: flex; align-items: center; gap: 10px; }
.section-icon {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 7px;
}
.section-icon .ico { display: block; }
.deal-request .card-body { padding-top: 18px; padding-bottom: 18px; }
.deal-item > h2 { color: var(--accent); }
.deal-item > h2 .hint { color: var(--text-dim); font-weight: 400; }
.deal-pricing > h2 { color: var(--text); }
.deal-pricing .facts { border-bottom: 0; }
/* Часть карточки: позиция внутри заявки. Заголовок тот же, что у карточки,
   но сверху линия — по ней видно, где кончается одно и начинается другое. */
.deal-part { border-top: 1px solid var(--border); }

.card > h2,
.deal-part > h2 {
  font-size: 14px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
}
.card > h2 .hint,
.deal-part > h2 .hint { font-weight: 400; color: var(--text-faint); font-size: 12px; }

.card-body { padding: 16px; }

/* Каждый сотрудник — одна цель нажатия; имя и роль не смешиваются
   с соседями даже в узкой карточке. */
.visibility-description { margin: 0 0 16px; color: var(--text-dim); font-size: 14px; }
.visibility-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 8px;
}
.visibility-person {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  min-height: 68px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
}
.visibility-person:hover { background: var(--surface-2); border-color: var(--border-strong); }
.visibility-person:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); }
.visibility-person:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.visibility-person input[type=checkbox] {
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.visibility-person-info { display: grid; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.visibility-person-name { color: var(--text); font-size: 14px; font-weight: 600; line-height: 1.35; }
.visibility-person-role { color: var(--text-dim); font-size: 12px; line-height: 1.4; }
.visibility-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.visibility-footer p { margin: 0; color: var(--text-dim); font-size: 13px; }
.visibility-footer .btn { min-height: 40px; }
@media (max-width: 480px) {
  .visibility-footer .btn { width: 100%; justify-content: center; }
}

.grid { display: grid; gap: 14px; }
.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* Заказ подрядчика: на телефоне первым идёт «что надо сделать».
   Карточка живёт в левой колонке сетки, и на узком экране оказывалась пятой —
   после ленты, менеджера, реквизитов и файлов. Подрядчик открывает заказ ради
   неё: вид работы, объём, время и адрес. На широком экране всё это видно и
   так, поэтому там порядок прежний.

   Всё тело заказа лежит в одном потоке (.order-stack). На узком сетка и её
   колонки распускаются через display: contents — карточки становятся прямыми
   детьми потока, и order к ним начинает применяться. */
.order-stack { display: flex; flex-direction: column; }
@media (max-width: 560px) {
  .order-stack > .grid,
  .order-stack > .grid > div { display: contents; }
  .order-stack .task-card { order: -1; }
}

/* Колонки всегда через minmax(0, 1fr). Обычный 1fr — это minmax(auto, 1fr):
   такая колонка не умеет становиться уже своего содержимого, и один жёсткий
   блок внутри (например dl.kv) уводит всю страницу вбок. */
@media (max-width: 1100px) {
  .cols-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .cols-6, .cols-3, .cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Три плитки в две колонки дают ряд с пустой правой половиной — на
     «Финансах» и «Статистике» это две зияющие дырки подряд. Пусть третья
     занимает всю ширину: ряд выглядит законченным. */
  .cols-3 > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .cols-6, .cols-4, .cols-3, .cols-2 { grid-template-columns: minmax(0, 1fr); }

  /* Сводка — исключение. Плитка это подпись и одно число; в одну колонку
     дашборд растягивался на три экрана, хотя цифр там немного. Ставим их
     по две в ряд и ужимаем. Правило про поля форм не задевает: сетку
     выбираем по тому, что внутри неё лежит. */
  .grid:has(> .tile) { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .tile { padding: 10px 12px; }
  .tile .label { font-size: 11px; margin-bottom: 2px; }
  .tile .value { font-size: 18px; letter-spacing: -.3px; }
  .tile .sub { font-size: 11px; margin-top: 1px; }
}

.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow: var(--shadow);
  display: block;
  color: inherit;
}
a.tile:hover { border-color: var(--border-strong); text-decoration: none; }
.tile .label { font-size: 12px; color: var(--text-dim); margin-bottom: 6px; }
.tile .value { font-size: 24px; font-weight: 600; letter-spacing: -.5px; }
.tile .sub { font-size: 12px; color: var(--text-faint); margin-top: 3px; }
.tile.alert .value { color: var(--danger); }

/* ---------- Таблицы ---------- */

.table-wrap { overflow-x: auto; }

/* Длинный список прокручивается внутри карточки, а шапка таблицы остаётся
   на месте. Сорок три заявки на одиннадцать столбцов: докрутив до середины,
   человек уже не помнит, где «Оплата», а где «Прибыль», и едет наверх
   сверяться. Прилипание к странице здесь не работает вовсе — обёртка
   прокручивается вбок и тем самым становится собственной областью
   прокрутки, — поэтому предел высоты и прокрутка внутри неё. Коротким
   таблицам предел ничего не меняет: до него они не дорастают. */
.table-wrap.sheet { max-height: calc(100vh - 180px); overflow: auto; }
.table-wrap.sheet thead th { position: sticky; top: 0; z-index: 3; }
/* Тень у правого края, пока таблица не докручена до конца. На телефоне из
   девяти столбцов видно два, полосы прокрутки нет, слова обрываются посреди
   буквы — и человек не догадывается, что справа есть «Оборот», «Долг» и
   кнопка действия. Тень исчезает, когда крутить больше некуда.

   Раньше это работало только уже 900 px, а список сделок просит 1262 и не
   влезает в обычный ноутбук: столбец «Оплата» уходил за край молча.
   Цвет затухания — цвет карточки, на которой лежит таблица, а не фона
   страницы: раньше на белом рисовалась серая полоса. */
.table-wrap {
  background:
    linear-gradient(to left, var(--surface) 0, transparent 24px) right center / 40px 100% no-repeat,
    linear-gradient(to left, rgba(6, 8, 12, .14), transparent 12px) right center / 14px 100% no-repeat;
  background-attachment: local, scroll;
}

/* Широкие таблицы: первый столбец остаётся на месте, когда крутят вбок.
   Без этого, докрутив до «Прибыли», человек видит суммы без номеров
   заявок — в таблице с деньгами это прямой путь к ошибке. */
.stick-first thead th:first-child,
.stick-first tbody td:first-child {
  position: sticky;
  left: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
}
.stick-first tbody td:first-child { z-index: 1; }
.stick-first thead th:first-child { z-index: 4; background: var(--surface-2); }
.stick-first tbody tr:hover td:first-child { background: var(--surface-2); }
/* Одиннадцать столбцов — двенадцать пикселей по краям каждой ячейки стоят
   двадцати пяти процентов ширины. Широкая таблица живёт плотнее — так она
   целиком помещается в ноутбук, где раньше требовала прокрутки вбок. */
.stick-first thead th, .stick-first tbody td { padding-left: 10px; padding-right: 10px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  text-align: left;
  font-weight: 500;
  font-size: 12px;
  color: var(--text-dim);
  /* Одна высота строки на все таблицы: 8 пикселей сверху и снизу дают
     строку в 37 px. Было по-разному — 9 в шапке, 10 в теле, — и таблицы
     на соседних экранах жили в разном ритме. */
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  white-space: nowrap;
}
tbody td { padding: 8px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface-2); }
td.num, th.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Цифры табличные везде, где их читают как данные: разряды стоят друг под
   другом, и число не дёргается при обновлении. В колонке сумм это видно
   сразу, в плитках дашборда — при каждом опросе сервера. Прозе табличные
   цифры не мешают: они шире только в местах, где цифра и стоит. */
table,
.kv dd,
.peek-row dd,
.tile .value,
.tile .sub,
.mini-now,
.doc-row .pill {
  font-variant-numeric: tabular-nums;
}
.muted { color: var(--text-faint); }
.dim { color: var(--text-dim); }
.small { font-size: 12px; }
.text-ok { color: var(--ok); font-weight: 500; }

/* Длинные названия компаний рвали строки на две-три и делали список
   нечитаемым: обрезаем в одну, полное имя остаётся в подсказке. */
td.ell { max-width: 134px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Дата со временем — одной строкой. Разбитые на две, они растили строку
   списка вдвое, а колонка от этого только сужалась: ширину столбца таблица
   считает по содержимому, и чем короче написано, тем меньше ей достаётся. */
td.nowrap { white-space: nowrap; }

/* Списки заявок на телефоне. Одиннадцать колонок в 390 px не помещаются
   никак, и прокрутка вбок на главном экране — это не работа: строка
   разворачивается в карточку, а заголовки колонок переезжают к значениям. */
@media (max-width: 700px) {
  /* Строка разворачивается в карточку, и коробка с прокруткой внутри
     страницы только мешает: список крутится вместе с ней. */
  .table-wrap.sheet { max-height: none; overflow: visible; overflow-x: auto; }
  .as-cards { overflow-x: visible; }
  /* На телефоне строка разворачивается в карточку — липнуть там нечему. */
  .as-cards.stick-first thead th:first-child,
  .as-cards.stick-first tbody td:first-child {
    position: static; border-right: 0; background: transparent;
  }
  .as-cards table, .as-cards tbody, .as-cards tr, .as-cards td { display: block; }
  .as-cards thead { display: none; }

  .as-cards tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 8px;
    background: var(--surface);
  }
  .as-cards tr:hover { background: var(--surface); }

  .as-cards td, .as-cards td.num, .as-cards td.ell {
    display: flex;
    gap: 12px;
    align-items: baseline;
    padding: 5px 12px;
    border: 0;
    text-align: left;
    max-width: none;
    overflow: visible;
    white-space: normal;
  }
  .as-cards td::before {
    content: attr(data-label);
    flex: none;
    width: 104px;
    color: var(--text-dim);
    font-size: 12px;
  }
  /* Первая ячейка — шапка карточки: номер заявки без подписи. */
  .as-cards td:first-child {
    border-bottom: 1px solid var(--border);
    padding: 9px 12px;
    font-weight: 600;
  }
  /* Единственный вход в карточку — ссылка с номером, а это цель примерно
     42 на 19 точек: попасть пальцем в перчатке нельзя. Растягиваем ссылку
     на всю ячейку, чтобы нажималась вся верхняя полоса карточки. */
  .as-cards td:first-child a {
    display: block;
    margin: -9px -12px;
    padding: 12px;
    min-height: 44px;
    box-sizing: border-box;
  }
  .as-cards td:first-child::before { display: none; }
  .as-cards td:not([data-label])::before { display: none; }
}

/* ---------- Значки статусов ---------- */

.pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid transparent;
}
.pill-new      { background: var(--accent-soft); color: var(--accent); }
.pill-work     { background: var(--accent-soft); color: var(--accent); }
.pill-assigned { background: var(--ok-soft); color: var(--ok); }
.pill-doing    { background: var(--warn-soft); color: var(--warn); }
.pill-done     { background: var(--ok-soft); color: var(--ok); }
.pill-docs     { background: var(--warn-soft); color: var(--warn); }
.pill-pay      { background: var(--warn-soft); color: var(--warn); }
.pill-closed   { background: var(--surface-2); color: var(--text-dim); border-color: var(--border); }
.pill-problem  { background: var(--danger-soft); color: var(--danger); }
.pill-ok       { background: var(--ok-soft); color: var(--ok); }
.pill-wait     { background: var(--warn-soft); color: var(--warn); }
.pill-na       { background: var(--surface-2); color: var(--text-faint); border-color: var(--border); }

/* ---------- Кнопки и поля ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 7px 14px;
  border-radius: 6px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-accent); }
.btn-sm { padding: 4px 10px; font-size: 12px; }

.button-pending { position: relative; }
.button-pending-original { display: contents; visibility: hidden; }
.button-pending::after {
  content: attr(data-pending-label);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  white-space: nowrap;
  overflow: hidden;
  border-radius: inherit;
}
.button-label-stable { display: inline-grid; min-width: 0; }
.button-label-stable > span { grid-area: 1 / 1; }
.button-label-reserve { visibility: hidden; pointer-events: none; }
.layout-placeholder { visibility: hidden; pointer-events: none; }

.filters { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
/* Поле пароля в этот список не входило и рисовалось браузерной рамкой:
   чужой серый цвет, свой радиус. Заметнее всего на экране входа, где оно
   стоит рядом с полем логина. Адрес и телефон — такая же история. */
input[type=text], input[type=date], input[type=time], input[type=number],
input[type=password], input[type=email], input[type=tel], select, textarea {
  font: inherit;
  font-size: 13px;
  padding: 6px 9px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  min-width: 0;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }

/* Запертое поле. Сотруднику стороны, у которого нет права на этот раздел,
   кнопку убирают, а поле оставляют — читать можно всё своё. Но браузер
   помечает сам только select и только disabled: readonly-поле выглядит
   обычным, и человек печатает в него, не понимая, почему ничего не
   сохраняется. Показываем это до нажатия. */
input[readonly], textarea[readonly],
input:disabled, select:disabled, textarea:disabled {
  /* Фон страницы, а не карточки: в светлой теме это серее белого поля, в
     тёмной — темнее, и в обеих поле выглядит утопленным, а не поднятым. */
  background: var(--bg);
  color: var(--text-dim);
  border-color: var(--border);
  cursor: default;
}
input[readonly]:focus, textarea[readonly]:focus { outline-color: var(--border-strong); }

.filters input[type=text] { min-width: 220px; flex: 1; }

.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: 12px; color: var(--text-dim); }
.field input, .field select, .field textarea { width: 100%; }

/* Поле по справочнику (вид работы, техника): input+datalist вместо select —
   тот же список, но с поиском по подстроке. Кнопка «+» рядом появляется
   только у тех, кому можно пополнять справочник. */
/* stretch, а не center: .btn-sm ниже поля ввода, и «+» по центру выглядел
   приплюснутой кнопкой рядом с полноростым полем. */
.ref-field { display: flex; gap: 6px; align-items: stretch; width: 100%; }
.ref-field .ref-input { flex: 1; min-width: 0; }
.ref-field .ref-add {
  flex: none; width: 32px; padding: 0; justify-content: center;
  font-size: 16px; line-height: 1;
}

/* Ввод по ИНН — вход в форму: одно нажатие заполняет одиннадцать полей ниже.
   Раньше это была ячейка сетки наравне с «ОКПО» и «Формой», а кнопка стояла
   такая же серая, как «Отмена», — её замечали последней и забивали реквизиты
   руками. Полоса во всю ширину отделяет шаг от того, что он заполняет. */
.inn-lookup {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 18px;
  padding: 12px 14px;
  border: 1px solid rgba(37, 99, 235, .2);
  border-radius: var(--radius);
  background: var(--accent-soft);
}
.inn-lookup > label { font-size: 12px; color: var(--text-dim); }
.inn-lookup-row { display: flex; align-items: stretch; gap: 8px; }
/* ИНН — десять знаков у организации, двенадцать у предпринимателя. Поле во
   всю ширину обещало бы значение подлиннее и сбивало с толку. */
.inn-lookup-row input {
  flex: 0 0 auto;
  width: 17ch;
  font-variant-numeric: tabular-nums;
}
.inn-lookup-row .btn { flex: 0 0 auto; }
/* Обводка фокуса рисуется цветом --accent-soft, а здесь он же под полем:
   кольцо растворилось бы в заливке. Внутри полосы берём сам синий. */
.inn-lookup-row input:focus { outline-color: var(--accent); outline-offset: 1px; }

/* Строка под ИНН: сперва объясняет, что делает кнопка, после нажатия — что
   подтянулось из ЕГРЮЛ и что оставили как было. Тревожное — ликвидация,
   банкротство — цветом предупреждения: такое замечают уже после того, как
   договор подписан. */
#cf-pull-note { font-size: 12px; line-height: 1.4; color: var(--text-faint); }
#cf-pull-note:empty { display: none; }
#cf-pull-note.bad { color: var(--warn); }

/* Услуги в форме заявки. Их бывает несколько, и без разделителя поля идут
   сплошной простынёй: непонятно, где кончается вывоз мусора и начинается
   экскаватор. Заголовок с номером и черта сверху разделяют их явно. */
.item-row + .item-row {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-strong);
}
.item-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.item-head b {
  font-size: 12px; font-weight: 600;
  color: var(--text-dim); text-transform: uppercase; letter-spacing: .5px;
}
.item-head .btn { margin-left: auto; }

/* Кнопка добавления идёт следом за списком услуг и без отступа читается
   как часть последней из них. */
[data-item-add], [data-pb-add] { margin-top: 14px; }

.form-block { border-top: 1px solid var(--border); padding: 16px; }
.form-block:first-of-type { border-top: 0; }
.form-block > h3 { font-size: 13px; margin-bottom: 12px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .4px; }

/* ---------- Карточка заявки ---------- */

.req-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.req-head h2 { font-size: 20px; letter-spacing: -.3px; }

.kv { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 7px 14px; font-size: 13px; }
.kv dt { color: var(--text-dim); }
/* ---------- Шапка заявки ---------- */

/* Не список «подпись — значение», а короткая карточка: заказчик заголовком,
   условия оплаты плашкой рядом, адрес строкой под ним, работа с датой —
   парой. Семь серых подписей столбиком занимали весь экран телефона ради
   значений в одно слово. */
.req { display: grid; gap: 12px; }
.req-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.req-who { font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.req-who a { text-decoration: none; }
.req-terms {
  font-size: 12px;
  color: var(--text-dim);
  background: var(--surface-2);
  border-radius: 999px;
  padding: 4px 11px;
  white-space: nowrap;
}
.req-terms-empty { color: var(--text-faint); font-style: italic; }
.req-where { font-size: 14px; line-height: 1.45; }
/* Район — уточнение к адресу, поэтому он бледнее и отделён точкой: без неё
   «Дмитровское шоссе дом 110 САО» читается как один адрес. */
.req-dim { color: var(--text-faint); }
.req-dim::before { content: '·'; margin: 0 7px; color: var(--border-strong); }

.req-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px 20px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 15px;
}
.req-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--text-faint);
  margin-bottom: 2px;
}

.req-note { font-size: 13px; color: var(--text-dim); line-height: 1.5; }

/* Заметки ещё нет: вместо пустой строки — кнопка с плюсом, как «Добавить
   фото» рядом. Нажимается она целиком, а не только слово. */
.req-add .field-edit {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--text-faint);
  border: 1px dashed var(--border-strong);
  border-radius: 8px;
  padding: 6px 12px;
  cursor: pointer;
}
.req-add .field-edit:hover {
  color: var(--accent);
  border-color: var(--accent);
  border-style: dashed;
}
/* Карандаш здесь лишний: кнопка и так говорит, что делает. */
.req-add .field-edit i { display: none; }
.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

/* На телефоне подпись встаёт над значением: две колонки в 390 px не живут. */
@media (max-width: 560px) {
  .kv { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .kv dt { font-size: 12px; margin-top: 10px; }
  .kv dt:first-child { margin-top: 0; }

  /* Реквизиты организации — пятнадцать полей, и почти все короткие: форма,
     ИНН, КПП, ОГРН, прочерк, прочерк. Столбиком они занимали тысячу точек
     прокрутки ради двух заполненных строк. Здесь пары текут в две колонки;
     пара не разрывается между колонками, поэтому подпись и значение всегда
     остаются вместе. */
  .kv-2 .kv { display: block; column-count: 2; column-gap: 18px; }
  .kv-2 .kv dt { margin-top: 0; font-size: 11px; break-after: avoid; }
  .kv-2 .kv dd { margin: 0 0 9px; break-before: avoid; break-inside: avoid; }
  /* Длинные значения — адреса и почта — в узкой колонке рвутся по буквам,
     а не уезжают за край. */
  .kv-2 .kv dd, .kv-2 .kv dd code { overflow-wrap: anywhere; }
}

.doc-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.doc-row:last-child { border-bottom: 0; }
.doc-row .name { flex: 1; }

.deal-documents-actions {
  padding: 12px 18px;
  border-top: 1px solid var(--border);
}
.deal-documents-actions .btn {
  max-width: 100%;
  white-space: normal;
  text-align: left;
}

/* Развернуть остальное. Вместо кнопки с надписью — стрелка во всю ширину
   посередине: она не спорит с записями за внимание, а сколько именно скрыто,
   говорит подсказка при наведении. */
.more-arrow {
  display: block;
  width: 100%;
  height: 28px;
  margin-top: 6px;
  border: 0;
  background: none;
  cursor: pointer;
  position: relative;
  border-radius: 6px;
}
.more-arrow::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9px; height: 9px;
  border-right: 2px solid var(--text-faint);
  border-bottom: 2px solid var(--text-faint);
  transform: translate(-50%, -70%) rotate(45deg);
  transition: border-color var(--t-fast) var(--ease);
}
.more-arrow.up::after { transform: translate(-50%, -30%) rotate(-135deg); }
.more-arrow:hover { background: var(--surface-2); }
.more-arrow:hover::after { border-color: var(--accent); }
.more-arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Полоса фактов. Главные цифры позиции — объём, даты, деньги — стоят в
   строку во всю ширину: столбиком они занимали треть карточки, а остальное
   пустовало. Ячейки разделены линией в один пиксель — тем же приёмом, что
   таблицы, — и переносятся сами, когда ширины перестаёт хватать. */
/* Ровно три линии: над полосой, под ней и одна между значениями. Сетка
   раньше рисовалась фоном, и в неполном ряду фон оставался открытым — серой
   заплаткой; рамки вокруг каждой ячейки дыру убрали, но дали пять линий на
   два числа. Верхнюю границу держит сама полоса, поэтому у шапки над ней
   своей линии больше нет — иначе их было две подряд. */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.fact { padding: 14px 16px; }
/* Разделитель между соседями. Ячеек в полосе две или три, и в ряд они
   помещаются целиком, поэтому «не первая» и «не первая в ряду» здесь одно и
   то же; на узком экране колонок ровно две, и линию у начала второго ряда
   снимаем отдельно. */
.fact + .fact { border-left: 1px solid var(--border); }
@media (max-width: 700px) {
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fact:nth-child(odd) { border-left: 0; }
  .fact:nth-child(n + 3) { border-top: 1px solid var(--border); }
}
.fact-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.fact-value { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }
.fact-sub { font-size: 12px; color: var(--text-faint); margin-top: 2px; }

.timeline { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.timeline li { padding: 8px 0 8px 16px; border-left: 2px solid var(--border); position: relative; }
.timeline li::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 14px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border-strong);
}
.timeline .when { color: var(--text-faint); font-size: 12px; }
.timeline .who { font-weight: 500; }

/* Обычный блок, а не flex. При flex каждый кусок текста и каждое <b> или
   ссылка внутри становились отдельной колонкой: «К оплате…:» | «465 000 ₽» |
   «. Счета…» — три столбца и точка в начале строки. Значков в плашках нет,
   раскладка была ни к чему. */
.banner {
  display: block;
  padding: 11px 14px;
  border-radius: var(--radius);
  font-size: 13px;
  margin-bottom: 16px;
  border: 1px solid transparent;
}
.banner-danger { background: var(--danger-soft); color: var(--danger); border-color: rgba(217, 45, 32, .2); }
.banner-info { background: var(--accent-soft); color: var(--accent); border-color: rgba(37, 99, 235, .2); }

.attention-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
}
.attention-item:last-child { border-bottom: 0; }
.attention-item .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dot-danger { background: var(--danger); }
.dot-warn { background: var(--warn); }
.dot-info { background: var(--accent); }
.attention-item .txt { flex: 1; }
.attention-item .req-no { font-weight: 600; }

/* Список дел и предпросмотр заявки рядом. Предпросмотр — только там, где
   есть мышь и место: на телефоне он не нужен и не поместился бы. */
.attention-split { display: grid; grid-template-columns: minmax(0, 1fr); }
.attention-peek { display: none; }

@media (min-width: 1180px) {
  .attention-split { grid-template-columns: minmax(0, 1fr) 340px; }
  /* Колонка — подложка на всю высоту списка, сама карточка лежит на ней
     и прилипает при прокрутке: список длинный, а смотрят в оба. */
  .attention-peek {
    display: block;
    border-left: 1px solid var(--border);
    padding: 14px;
    background: var(--surface-2);
  }
  .peek {
    position: sticky;
    top: 64px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 14px;
  }
}

.attention-item { transition: background var(--t-fast) var(--ease); cursor: default; }
.attention-item[data-peek]:hover,
.attention-item.peeked { background: var(--surface-2); }
.attention-item .txt { transition: transform var(--t-fast) var(--ease); }
.attention-item[data-peek]:hover .txt,
.attention-item.peeked .txt { transform: translateX(4px); }
.attention-item[data-peek]:hover .req-no,
.attention-item.peeked .req-no { text-decoration: underline; }

/* Карточка в панели */
.peek { animation: peek-in .16s var(--ease); }
@keyframes peek-in { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }

.peek-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.peek-no { font-size: 15px; font-weight: 600; }
.peek-client { font-size: 13px; color: var(--text-dim); margin: 2px 0 12px; }

.peek-kv { margin: 12px 0 14px; display: flex; flex-direction: column; gap: 7px; }
.peek-row { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; font-size: 12px; }
.peek-row dt { color: var(--text-faint); }
.peek-row dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.peek-open { width: 100%; justify-content: center; display: inline-flex; }

/* Сжатая лента этапов: девять точек на одной линии. Подписан текущий
   этап — девять названий в триста пикселей превратились бы в кашу. */
.flow-mini { margin-top: 12px; }
.mini { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; }
.mini-step { flex: 1; display: flex; align-items: center; }
.mini-step::after {
  content: ''; flex: 1; height: 2px; background: var(--border); margin: 0 2px;
}
.mini-step:last-child { flex: none; }
.mini-step:last-child::after { display: none; }
.mini-step > i {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--border-strong);
}
.mini-step.done > i { background: var(--ok); }
.mini-step.done::after { background: var(--ok); }
.mini-step.now > i {
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.mini-step.complete > i {
  background: var(--ok);
  box-shadow: 0 0 0 3px var(--ok-soft);
}
.mini-now { font-size: 12px; margin-top: 10px; }

@media (prefers-reduced-motion: reduce) {
  .attention-item, .attention-item .txt { transition: none; }
  .peek { animation: none; }
}

.bar { height: 6px; border-radius: 4px; background: var(--border); overflow: hidden; margin-top: 6px; }
.bar > i { display: block; height: 100%; background: var(--accent); }

.chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 10px; border: 1px solid var(--border);
  border-radius: 6px; background: var(--surface-2); font-size: 13px;
}
.chip-x {
  border: 0; background: none; cursor: pointer; line-height: 1;
  font-size: 15px; color: var(--text-dim); padding: 0 2px;
}
.chip-x:hover { color: var(--danger); }

.empty { padding: 40px 16px; text-align: center; color: var(--text-faint); }

.tag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 12px;
  margin: 0 3px 3px 0;
  color: var(--text-dim);
}

.hidden-note {
  font-size: 12px;
  color: var(--text-faint);
  font-style: italic;
}

/* ---------- Дополнения ---------- */

.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* Порядок здесь важнее вида: эти правила стоят ниже общего мобильного блока,
   значит при равной силе побеждают они. Раньше тут обрывалось на двух
   колонках, и на телефоне «Добавить технику», «Новая учётная запись» и
   «Отметить занятость» набирались вслепую — поле шириной в половину слова.
   Поэтому узкий случай дописан здесь же. */
@media (max-width: 760px) { .cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .cols-4 { grid-template-columns: minmax(0, 1fr); } }

.stars { color: #e0a800; font-size: 12px; letter-spacing: 1px; }
.stars .dim { color: var(--border-strong); }

/* Выделяем карточку рамкой по кругу, а не толстой полосой слева: полоса
   заметнее, но она же — самый узнаваемый штамп сгенерированного интерфейса. */
.new-req { border-color: var(--accent); }

.attn-line {
  padding: 7px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.attn-line:last-child { border-bottom: 0; }
.attn-danger { color: var(--danger); font-weight: 500; }
.attn-warn { color: var(--warn); }
.attn-info { color: var(--text-dim); }

.suggest {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(16, 24, 40, .12);
  overflow: hidden;
  margin-top: 2px;
}
.suggest.open { display: block; }
.suggest-item { padding: 8px 10px; font-size: 13px; cursor: pointer; }
.suggest-item:hover { background: var(--accent-soft); }
.suggest-item.muted { cursor: default; color: var(--text-dim); border-top: 1px solid var(--border); }
.suggest-item.muted:hover { background: var(--surface-2); }

.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 20px);
  background: var(--sidebar);
  color: #fff;
  padding: 11px 18px;
  border-radius: 8px;
  font-size: 13px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s, transform .18s;
  z-index: 100;
  max-width: 90vw;
  text-align: center;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- Экран входа ---------- */

/* Главная администратора: фотография задаёт атмосферу, данные остаются HTML. */
/* Базовая светлая палитра. Тёмные поверхности и обе фотографии задаются
   отдельным блоком ниже, вместе со статусами и полями дашборда. */
.admin-home {
  background: #edf3f9;
  color: #14243b;
  --surface: #ffffff;
  --surface-2: #f5f8fc;
  --border: #e3e7ee;
  --border-strong: #c8cfdb;
  --text: #141821;
  --text-dim: #525b6b;
  --text-faint: #6b7482;
  --accent: #1d4ed8;
  --accent-soft: #e7eefd;
  --on-accent: #ffffff;
  --danger: #d92d20;
  --danger-soft: #fdecea;
  --warn: #b54708;
  --warn-soft: #fdf1e3;
  --ok: #0b7a4b;
  --ok-soft: #e6f4ed;
}
.admin-home .topbar { background: #f9fcffdf; backdrop-filter: blur(16px); border-color: #dae5f0; padding: 16px 32px; }
.admin-home .topbar h1 { font-size: 16px; font-weight: 600; }
.admin-home.nav-open .topbar { z-index: 50; }
.admin-home .content { max-width: none; padding: 0; }
.admin-dashboard { --text: #14243b; --text-dim: #596d83; --surface: #fff; --surface-2: #f3f7fb; --border: #dce6ef; --accent: #126ce5; }
.dash-hero { position: relative; isolation: isolate; display: grid; grid-template-columns: 1.05fr 1fr; align-items: center; gap: 38px; min-height: 510px; padding: 44px 38px 48px; background: linear-gradient(0deg, #edf3f9, #edf3f900 25%), linear-gradient(90deg, #f8fbfff5, #f8fbffb8 48%, #f8fbff0d), url('entry-construction.webp') center 53% / cover; }
.dash-hero::after { content: ''; position: absolute; z-index: -1; right: 5%; top: 26%; width: 38%; height: 45%; border: 1px solid #d8f3ffb3; border-radius: 50%; transform: rotate(-20deg); box-shadow: 0 0 20px #c3eaff, inset 0 0 18px #e0f4ff; pointer-events: none; }
.dash-hero { overflow: clip; }
.dash-eyebrow { display: flex; align-items: center; gap: 9px; color: #334b65; font-size: 10px; font-weight: 700; letter-spacing: 1.7px; margin-bottom: 34px; }
.dash-eyebrow .potok-mark { display: block; margin: 0 2px; width: auto; }
.dash-intro h2 { font-size: clamp(34px, 3.4vw, 57px); font-weight: 750; line-height: 1.08; letter-spacing: -2px; margin: 0; color: #101d30; }
.dash-intro h2 > span { color: #0965ed; }
.dash-intro > p { color: #596c82; font-size: 15px; line-height: 1.6; margin: 22px 0 25px; }
.dash-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.dash-actions .btn { min-height: 45px; padding: 10px 18px; gap: 10px; border-radius: 6px; background: #ffffffbd; border: 1px solid #2879d8; color: #165eb8; }
.dash-actions .btn-primary { background: #126ce5; color: #fff; border-color: #126ce5; box-shadow: 0 6px 20px #126ce51c; }
.dash-actions .btn:hover { box-shadow: 0 5px 18px #1252a02b; }
.dash-live { background: #f9fcfff0; backdrop-filter: blur(18px); border: 1px solid #ffffff; border-radius: 15px; box-shadow: 0 18px 60px #173f6526; overflow: hidden; min-width: 0; }
.dash-live-heading { display: flex; justify-content: space-between; align-items: center; padding: 22px 23px 0; }
.dash-kicker { font-size: 9px; letter-spacing: 1.6px; font-weight: 600; color: #647d96; }
.dash-live-heading h3 { font-size: 16px; margin-top: 5px; }
.dash-live-heading > a { display: grid; place-items: center; width: 36px; height: 36px; background: #eaf2fc; border-radius: 9px; font-size: 21px; }
.dash-live-count { display: flex; align-items: center; gap: 14px; padding: 17px 23px; }
.dash-live-count > strong { font-size: 38px; line-height: 1.1; font-weight: 650; letter-spacing: -1px; }
.dash-live-count > span { font-size: 11px; line-height: 1.5; color: #667c92; }
.dash-live-count .dash-live-icon { margin-left: auto; color: #428cea; }
.dash-live-icon .ico { width: 30px; height: 30px; }
.dash-recent { padding: 0 23px; }
.dash-request { display: flex; align-items: center; gap: 10px; min-height: 58px; border-top: 1px solid #dfe8f0; color: #223751; }
.dash-request:hover { text-decoration: none; background: #eaf3fc; }
.dash-request-icon { color: #267adf; display: grid; place-items: center; flex: none; }
.dash-request-copy { flex: 1; min-width: 0; }
.dash-request-copy b { display: block; font-size: 11px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-request-copy b > span { color: #62778d; font-weight: 400; }
.dash-request-copy small { display: block; font-size: 10px; margin-top: 3px; color: #6b7e92; }
.dash-request .pill { font-size: 9px; max-width: 43%; white-space: normal; text-align: center; padding: 3px 6px; }
.dash-live-footer { padding: 14px 23px; border-top: 1px solid #dfe8f0; display: flex; justify-content: space-between; font-size: 11px; font-weight: 500; }
.dash-empty { padding: 24px 0 30px; color: #344f69; font-size: 14px; line-height: 1.8; }
.dash-empty span { font-size: 12px; color: #637a91; }
.dash-overview, .dash-workspace { margin: 0 32px 25px; }
.dash-section-heading { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px; margin-bottom: 18px; }
.dash-section-heading h2 { font-size: 22px; letter-spacing: -.5px; margin-top: 3px; }
.dash-period { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-period select { min-height: 38px; border: 1px solid #d5e1ed; border-radius: 7px; padding: 6px 10px; font: inherit; font-size: 12px; color: #334e6b; background: #ffffffce; }
.dash-metrics { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; }
.dash-metric { position: relative; display: flex; flex-direction: column; align-items: flex-start; padding: 17px 15px; border: 1px solid #fff; border-radius: 12px; background: #ffffffd9; box-shadow: 0 5px 20px #274b6f06; color: #1c344e; transition: box-shadow .15s, border-color .15s; }
.dash-metric:hover { text-decoration: none; border-color: #a8cefa; box-shadow: 0 8px 24px #274b6f13; }
.dash-metric-icon { display: grid; place-items: center; width: 31px; height: 31px; background: #eaf3ff; color: #247de5; border-radius: 8px; margin-bottom: 14px; }
.dash-metric-label { font-size: 11px; color: #566d84; min-height: 32px; }
.dash-metric strong { font-size: 29px; font-weight: 650; line-height: 1.2; margin-top: 5px; }
.dash-metric-arrow { position: absolute; right: 15px; top: 19px; font-size: 17px; color: #809bb6; }
.dash-metric-new { background: #156ce6; border-color: #156ce6; color: #fff; }
.dash-metric-new .dash-metric-label, .dash-metric-new .dash-metric-arrow { color: #e5f0ff; }
.dash-metric-new .dash-metric-icon { background: #ffffff25; color: #fff; }
.dash-period-note { font-size: 11px; color: #62768b; margin: 12px 0 0; }
.dash-workspace .card { border-radius: 13px; border: 1px solid #e0e9f2; box-shadow: 0 5px 20px #274b6f06; background: #ffffffeb; }
.dash-workspace .card > h2 { padding: 20px 22px; font-size: 17px; color: #19324d; }
.dash-workspace .attention-item { padding: 15px 20px; }
.dash-bottom { display: flex; align-items: center; gap: 16px; margin: 30px 32px; color: #70869b; font-size: 10px; }
.dash-bottom > span { font-weight: 750; letter-spacing: 1px; color: #466481; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
@media (min-width: 1600px) { .admin-dashboard { max-width: 1600px; margin: auto; } .dash-hero { padding: 64px 60px; min-height: 570px; } }
@media (max-width: 1200px) { .dash-hero { gap: 24px; padding: 34px 26px 42px; } .dash-intro h2 { font-size: 38px; } .dash-intro > p { font-size: 13px; } .dash-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); } .dash-metric-label { min-height: 0; } }
@media (max-width: 900px) {
  .admin-home .topbar { padding: 10px 20px; }
  .admin-home .sidebar { box-shadow: none; }
  .admin-home.nav-open .sidebar { box-shadow: 12px 0 40px #112a4550; }
  .dash-hero { min-height: 470px; }
}
@media (max-width: 650px) {
  .admin-home .topbar { padding: 8px 16px; }
  .dash-hero { grid-template-columns: minmax(0, 1fr); gap: 28px; padding: 30px 20px 32px; background-position: 66% center; background-image: linear-gradient(0deg, #edf3f9, #edf3f900 40%), linear-gradient(90deg, #f8fbffed, #f8fbff99), url('entry-construction.webp'); }
  /* На телефоне оставляем только заголовок и кнопки. Строка «ПОТОК М» и
     подпись под заголовком — рассказ о себе: на большом экране он стоит
     рядом с делом, а на телефоне отодвигает само дело за нижний край. Тире
     в конце первой строки заголовка там тоже лишнее: перенос и так на месте.
     («Обзор работы» и «От первой заявки до закрытия сделки» убраны совсем
     19.09.2026 — просьба заказчика.) */
  .dash-eyebrow,
  .dash-intro > p,
  .dash-dash { display: none; }
  .dash-intro h2 { font-size: clamp(32px, 8.5vw, 47px); letter-spacing: -1.5px; }
  .dash-actions { margin-top: 22px; }
  .dash-actions { gap: 8px; }
  .dash-actions .btn { min-height: 46px; padding: 10px 12px; font-size: 12px; }
  .dash-live-heading { padding: 20px 18px 0; }
  .dash-live-count { padding: 16px 18px; }
  .dash-recent { padding: 0 18px; }
  .dash-live-footer { min-height: 44px; padding: 14px 18px; }
  .dash-hero::after { top: 37%; right: 3%; width: 88%; height: 28%; }
  .dash-overview, .dash-workspace { margin: 0 16px 22px; }
  .dash-section-heading { align-items: flex-start; }
  .dash-period { width: 100%; }
  .dash-period select { min-height: 44px; }
  .dash-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .dash-metric { padding: 16px; }
  .dash-metric-label { font-size: 12px; }
  .dash-workspace .attention-item { padding: 14px; }
  .dash-bottom { margin: 25px 20px; font-size: 9px; gap: 10px; flex-wrap: wrap; }
}

.login-screen {
  min-height: 100vh;
  background: #e9f0f6;
}
.entry-page {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: clamp(36px, 8.5vh, 86px) 6.6vw 7vh;
  color: #101b2b;
  background: linear-gradient(0deg, rgba(248,250,253,.96), transparent 19%), linear-gradient(90deg, rgba(248,250,253,.83), rgba(248,250,253,.35) 42%, transparent 70%), url('entry-construction.webp') center center / cover;
  font-family: Arial, Helvetica, sans-serif;
}
.entry-brand { display: flex; align-items: center; gap: 15px; width: fit-content; }
.entry-brand > span { font-size: 49px; font-weight: 800; line-height: 1; letter-spacing: -2px; transform: scaleX(1.18); transform-origin: left; margin-right: 26px; }
.entry-brand .potok-mark { width: auto; height: 48px; }
.entry-copy { margin-top: clamp(65px, 11vh, 115px); padding-bottom: 90px; }
.entry-copy h1 { margin: 0 0 18px; font-size: clamp(42px, 4.45vw, 72px); line-height: 1.04; font-weight: 750; letter-spacing: -2.2px; }
.entry-copy h1 span { color: #075ced; background: linear-gradient(100deg, #087bef, #123ae0); background-clip: text; -webkit-text-fill-color: transparent; }
.entry-copy > p { margin: 0; color: #55647a; font-size: clamp(15px, 1.2vw, 18px); line-height: 1.42; }
/* Кнопка на входе теперь одна («Создать аккаунт» снят) — её сделали
   длиннее и опустили от подписи, чтобы она не терялась короткой плашкой. */
/* Ширина кнопки — ровно ширина заголовка: блок текста сжат по самой
   широкой строке (fit-content), кнопка тянется на весь блок. Кнопка
   фиксированной ширины обрывалась посреди строки «в одном потоке.», и её
   правый край ни с чем не совпадал. На телефоне — во всю ширину экрана. */
.entry-copy { width: fit-content; max-width: 100%; }
.entry-actions { display: flex; gap: 16px; margin-top: 44px; }
/* Надпись жирная: у Arial нет промежуточной насыщенности, 500 рисовался
   обычным начертанием и на широкой кнопке терялся. */
.entry-actions .entry-primary { width: 100%; min-height: 56px; font-size: 17px; font-weight: 700; letter-spacing: .3px; }
.entry-button { min-height: 45px; display: inline-flex; justify-content: center; align-items: center; gap: 22px; padding: 0 32px; border: 1px solid #1770e5; border-radius: 5px; font: 500 14px Arial, sans-serif; cursor: pointer; transition: background .15s, box-shadow .15s; }
.entry-primary { background: #126ce5; color: #fff; }
.entry-primary:hover { background: #075bd0; box-shadow: 0 5px 18px #126ce52a; }
.entry-secondary { color: #1563c8; background: rgba(255,255,255,.62); }
.entry-secondary:hover { background: #fff; }
.entry-button:focus-visible, .entry-close:focus-visible { outline: 3px solid #438af5; outline-offset: 4px; }
.entry-button span { font-size: 20px; line-height: 1; }
.entry-footer { display: flex; gap: 12px; align-items: flex-start; margin-top: auto; color: #657487; }
.entry-footer > span { width: 20px; height: 1px; background: #6d9dd4; margin-top: 8px; flex-shrink: 0; }
.entry-footer p { font-size: 11px; line-height: 1.6; margin: 0; }
.entry-dialog { width: min(860px, calc(100% - 32px)); max-height: calc(100svh - 40px); margin: auto; padding: 38px 28px 28px; border: 1px solid var(--border); border-radius: 16px; background: var(--surface); color: var(--text); box-shadow: 0 24px 90px #071b3c40; }
.entry-dialog::backdrop { background: #13294366; backdrop-filter: blur(8px); }
.entry-dialog:not(:has(.acc-grid)) { max-width: 460px; }
.entry-close { position: absolute; top: 10px; right: 12px; width: 32px; height: 32px; border: 0; border-radius: 50%; font-size: 26px; line-height: 1; background: transparent; color: var(--text-dim); cursor: pointer; }
.entry-close:hover { background: var(--surface-2); }
.entry-dialog .login-head h2 { font-size: 26px; margin: 0 0 8px; }
.entry-dialog .login-form { border: 0; box-shadow: none; padding: 0; margin-bottom: 0; }
.entry-dialog .demo-title { margin-top: 26px; }
.entry-register h2 { font-size: 26px; margin: 0 0 16px; }
.entry-register p { color: var(--text-dim); line-height: 1.6; margin: 0 0 24px; }
@media (min-width: 1600px) { .entry-page { padding-left: max(6.6vw, calc((100vw - 1500px) / 2)); } }
@media (max-width: 700px) {
  .entry-page { min-height: 100svh; padding: 35px 26px 28px; background-position: 62% center; background-image: linear-gradient(90deg, rgba(248,250,253,.93), rgba(248,250,253,.64) 60%, rgba(248,250,253,.15)), url('entry-construction.webp'); }
  .entry-brand > span { font-size: 35px; margin-right: 18px; }
  .entry-brand .potok-mark { width: auto; height: 37px; }
  .entry-brand { gap: 10px; }
  .entry-copy { margin-top: 82px; padding-bottom: 100px; width: auto; }
  .entry-copy h1 { font-size: clamp(34px, 7.6vw, 52px); letter-spacing: -1.5px; line-height: 1.08; }
  .entry-copy > p { max-width: 380px; font-size: 15px; line-height: 1.5; }
  .entry-break { display: none; }
  .entry-actions { gap: 12px; flex-wrap: wrap; }
  .entry-button { padding: 0 22px; min-height: 48px; }
  .entry-footer p { max-width: 290px; }
  .entry-dialog { padding: 42px 20px 24px; }
}
.login-box { width: 100%; max-width: 860px; }

.login-head { text-align: center; margin-bottom: 26px; }
.login-head h1 { font-size: 26px; letter-spacing: -.5px; margin-bottom: 6px; }
.login-head p { margin: 0; color: var(--text-dim); font-size: 14px; }

.login-form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  max-width: 380px;
  margin: 0 auto 26px;
}
.login-form .field { margin-bottom: 12px; }
.login-form .btn { width: 100%; justify-content: center; padding: 9px; }
.login-error {
  color: var(--danger);
  font-size: 13px;
  margin: 0 0 12px;
  display: none;
}
.login-error.show { display: block; }
.login-privacy {
  margin: 14px 0 0;
  color: var(--text-faint);
  font-size: 12px;
  line-height: 1.5;
}
.login-privacy a { text-underline-offset: 2px; }

.demo-title {
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 12px;
}
.demo-title b { color: var(--text); }

.acc-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 780px) { .acc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .acc-grid { grid-template-columns: 1fr; } }

.acc {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  box-shadow: var(--shadow);
}
.acc:hover { border-color: var(--accent); background: var(--surface-2); }
.acc .acc-role { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.acc .acc-name { font-size: 12px; color: var(--text-dim); margin-bottom: 8px; }
.acc .acc-cred {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 12px;
  color: var(--text-faint);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 3px 6px;
  display: inline-block;
}
.acc.picked {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.acc.picked .acc-cred { border-color: var(--accent); color: var(--accent); }

.acc-group-label {
  grid-column: 1 / -1;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .6px;
  color: var(--text-faint);
  margin: 8px 0 0;
}

/* ---------- Пользователь в шапке ---------- */

/* ---------- Рейтинг: просто число, без классов ---------- */

/* Ширина у всех бейджей одна. В колонке списка рядом стоят «100 %», «96 %»
   и прочерк, и плашка под каждым была своей длины — колонка рябила, а
   глазу не за что зацепиться при сравнении. */
.rate {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 1px;
  min-width: 62px;
  box-sizing: border-box;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  border: 1px solid transparent;
  white-space: nowrap;
}
.rate i { font-style: normal; font-size: 11px; font-weight: 500; opacity: .8; }
.rate-sm { font-size: 13px; padding: 3px 7px; min-width: 54px; }

/* Пять ступеней вместо «зелёный или красный»: 96 % и 45 % — разные истории. */
.rate-top { background: var(--rate-top-bg); color: var(--rate-top); border-color: var(--rate-top-bd); }
.rate-good { background: var(--rate-good-bg); color: var(--rate-good); border-color: var(--rate-good-bd); }
.rate-mid { background: var(--rate-mid-bg); color: var(--rate-mid); border-color: var(--rate-mid-bd); }
.rate-low { background: var(--rate-low-bg); color: var(--rate-low); border-color: var(--rate-low-bd); }
.rate-bad { background: var(--rate-bad-bg); color: var(--rate-bad); border-color: var(--rate-bad-bd); }
.rate-na {
  background: var(--surface-2); color: var(--text-faint);
  border-color: var(--border); font-size: 12px; font-weight: 500;
}

/* ---------- Проекты и план работ ---------- */

.section-title {
  font-size: 13px; color: var(--text-dim); text-transform: uppercase;
  letter-spacing: .4px; margin: 24px 0 10px;
}

/* Полоска объектов в карточке проекта: обзор одним взглядом. */
.obj-strip { display: flex; gap: 10px; flex-wrap: wrap; }
.obj-chip {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); color: inherit; min-width: 180px;
}
.obj-chip:hover { border-color: var(--border-strong); text-decoration: none; }

/* План работ: дни сверху вниз, работы внутри дня. Заказчик мыслит днями
   выхода техники, а не строками таблицы. */
.timeline-plan { display: flex; flex-direction: column; gap: 18px; }
.tl-day { display: grid; grid-template-columns: 120px 1fr; gap: 16px; align-items: start; }
@media (max-width: 760px) { .tl-day { grid-template-columns: 1fr; gap: 6px; } }
.tl-date {
  font-weight: 600; font-size: 14px; padding-top: 10px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tl-works { display: flex; flex-direction: column; gap: 6px; }

.work-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface);
}
.work-row.work-sent { background: var(--surface-2); }
.work-main { flex: 1; min-width: 200px; font-size: 14px; }
.work-sum { font-variant-numeric: tabular-nums; white-space: nowrap; }
.work-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: none; margin: 0 4px;
}

/* ---------- Карта объектов ---------- */

/* Карта на OpenStreetMap: Leaflet рисует свои узлы, поэтому здесь только
   рамка, метка и подгонка чужих контролов под остальной интерфейс. */
.map-box {
  height: 380px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-2);
  z-index: 0;   /* иначе тайлы лезут поверх шапки при скролле */
}

.addr-row { display: flex; gap: 10px; align-items: end; margin-bottom: 14px; }
.addr-row .field { flex: 1; }

/* Метка — точка плюс подпись сбоку: подпись нужна, чтобы объект узнавали,
   не тыкая в каждую. Она выходит за габариты иконки, это нормально. */
.map-pin { overflow: visible; }
.map-pin i {
  display: block; width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent); border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(16, 24, 40, .4);
}
.map-pin b {
  position: absolute; left: 20px; top: -3px;
  padding: 1px 6px; white-space: nowrap;
  font-size: 12px; font-weight: 600; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
}

.leaflet-container { font: inherit; background: var(--surface-2); }
.leaflet-container a { color: var(--accent); }
.leaflet-bar a, .leaflet-bar a:hover {
  background: var(--surface); color: var(--text); border-bottom-color: var(--border);
}
.leaflet-control-attribution {
  background: var(--surface) !important;
  color: var(--text-faint); font-size: 10px; padding: 1px 5px;
}
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--surface); color: var(--text); box-shadow: var(--shadow);
}
.leaflet-popup-content { margin: 10px 12px; font-size: 13px; line-height: 1.5; }

/* Тёмная тема: тайлы приходят светлыми, инвертируем только их слой —
   метки и подписи живут в других слоях и остаются как есть. */
@media (prefers-color-scheme: dark) {
  .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(.9) contrast(.9) saturate(.8);
  }
  .map-pin i { border-color: var(--surface); }
}

/* ---------- Права сотрудника стороны ---------- */

/* Галочка и подпись — одна строка, галочка первой. Раньше здесь стоял класс
   от вложений, которого в стилях нет вовсе: подписи выстраивались слева,
   квадратики убегали к правому краю, и какой из них к какой подписи —
   приходилось угадывать. */
/* Список нарочно не внутри .field: там правило «.field input { width: 100% }»
   растягивает квадратик галочки на всю колонку, и подпись уезжает за край
   карточки. Сначала так и вышло. */
.perm-block { display: flex; flex-direction: column; gap: 7px; }
.perm-title { font-size: 12px; color: var(--text-dim); }
.perm-list { display: flex; flex-direction: column; gap: 7px; }
.perm-row {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 13px; line-height: 1.35; cursor: pointer;
}
.perm-row input { width: auto; margin: 1px 0 0; flex: none; }
.perm-row span { min-width: 0; }

/* ---------- Единица техники ---------- */

.unit-list { display: flex; flex-direction: column; gap: 6px; }
.unit { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.unit-plate {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .4px;
  padding: 2px 7px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--surface-2);
  white-space: nowrap;
}
.unit-kind { font-weight: 600; }
.unit-model { color: var(--text-dim); }
.unit-specs { color: var(--text-faint); font-size: 12px; }

/* Строка машины ведёт в её карточку. Синим её не красим: она стоит в ряду
   фактов о позиции, и цветная строка посреди них читалась бы как ошибка или
   как предупреждение. О том, что строка нажимается, говорит наведение. */
a.unit { color: inherit; text-decoration: none; }
a.unit:hover .unit-kind,
a.unit:focus-visible .unit-kind { color: var(--accent); }
a.unit:hover .unit-plate,
a.unit:focus-visible .unit-plate { border-color: var(--accent); color: var(--accent); }

/* ---------- Файлы заказа ---------- */

.file-list { display: flex; flex-direction: column; gap: 2px; }
.file-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 10px; border-radius: 6px;
}
.file-row:hover { background: var(--surface-2); }
.file-name { font-size: 14px; font-weight: 500; word-break: break-all; }
.file-meta { font-size: 12px; color: var(--text-faint); flex: 1; }

/* ---------- Лента процесса ---------- */

/* Путь заявки одной строкой. На узком экране колонка не ломается на два
   столбца, а честно становится вертикальной: этапов девять, и в 390 px
   горизонталь читалась бы хуже прокрутки. */
.flow {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 4px;
  overflow-x: auto;
}
.flow-step {
  flex: 1 1 0;
  min-width: 88px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  text-align: center;
  position: relative;
  padding-top: 4px;
}
/* Соединительная черта идёт от предыдущего шага, а не рисуется отдельным
   элементом: так она не появляется перед первым и после последнего. */
.flow-step + .flow-step::before {
  content: '';
  position: absolute;
  top: 21px;
  right: 50%;
  left: -50%;
  height: 1px;
  background: var(--border-strong);
  z-index: 0;
}
.flow-dot {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-faint);
}
.flow-step b { font-size: 12px; font-weight: 600; color: var(--text-dim); }
.flow-when {
  font-size: 11px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
}

.flow-step.done .flow-dot { border-color: var(--ok); color: var(--ok); background: var(--ok-soft); }
.flow-step.done b { color: var(--text); }
.flow-step.now .flow-dot {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.flow-step.now b { color: var(--accent); }
.flow-step.complete .flow-dot {
  border-color: var(--ok);
  color: var(--ok);
  background: var(--ok-soft);
  box-shadow: 0 0 0 3px var(--ok-soft);
}
.flow-step.complete b { color: var(--ok); }
.flow-step.wait .flow-dot { border-style: dashed; }

/* У админа кружки этапов завершённой заявки — кнопки возврата. Кнопка
   наследует вид кружка: лента не должна меняться от того, кто на неё
   смотрит, — меняется только то, что под пальцем она отзывается. */
button.flow-dot { padding: 0; font: inherit; cursor: pointer; }
button.flow-dot:hover,
button.flow-dot:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Строка списка открывает карточку целиком — значит, и курсор должен это
   обещать. Подсветка при наведении у таблиц уже есть (tbody tr:hover). */
tr[data-row-open] { cursor: pointer; }

/* ---------- Действия по позиции, в карточке подрядчика ---------- */

/* Подложка отделяет действия от сведений о подрядчике над ними: это не
   продолжение карточки, а то, что по позиции можно сделать. */
.item-actions {
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  display: grid;
  gap: 10px;
}
.act-line { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* Подписи строк в один столбик — по ним строки и читаются как список дел.
   Ширина общая, поэтому «Ответственный» и «Факт выполнения» стоят ровно
   друг под другом. */
.act-label {
  flex: none;
  width: 118px;
  font-size: 12px;
  color: var(--text-dim);
}

/* Поля не тянутся по ширине экрана. Раньше они делили всю строку, и на
   широком мониторе пояснение расползалось на пол-экрана, а кнопка улетала
   к правому краю — ряд выглядел случайным. Ширина у каждого своя и по
   делу: объём короткий, расходы — несколько цифр, пояснение длиннее всех. */
.act-who { width: 240px; }
.act-vol { width: 190px; }
.act-cost { width: 130px; }
.act-note { width: 260px; }

@media (max-width: 900px) {
  /* На телефоне подпись встаёт над строкой, поля — во всю ширину: пять
     ячеек в 360 точек дают пять нечитаемых огрызков. */
  .act-label { width: 100%; }
  .act-who, .act-vol, .act-cost, .act-note { width: 100%; }
  .act-line > .btn { width: 100%; }
}

/* ---------- Ценообразование позиции ---------- */

/* Сведения о работе — строкой, мелким: объём и дата нужны рядом с деньгами,
   но спорят с ними за внимание, если набраны тем же кеглем. */
.pricing { display: grid; gap: 14px; padding: 14px 16px 16px; }
.pricing-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
}
.pm { display: flex; align-items: baseline; gap: 8px; font-size: 13px; min-width: 0; }
.pm > span { color: var(--text-faint); }
.pm > b { font-weight: 600; }
.pm > i { font-style: normal; color: var(--text-faint); }

/* Деньги — плитками в ряд. auto-fit заполняет строку целиком, поэтому
   пустых клеток не остаётся ни при трёх плитках, ни при одной (продажнику
   цена подрядчика не видна вовсе). */
.pricing-money {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}
.mt {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  background: var(--surface);
  display: grid;
  gap: 3px;
  align-content: start;
}
.mt > span {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--text-dim);
}
.mt > b { font-size: 20px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.mt > b em { font-style: normal; font-size: 14px; font-weight: 500; color: var(--text-faint); }
.mt > i { font-style: normal; font-size: 12px; color: var(--text-faint); }

/* Прибыль — то, ради чего в карточку и заходят: у неё свой фон и цвет. */
.mt-profit { background: var(--accent-soft); border-color: transparent; }
.mt-profit > b { color: var(--accent); }

@media (max-width: 560px) {
  .pricing-money { grid-template-columns: 1fr; }
  .pricing-meta { gap: 6px 20px; }
}

/* ---------- Доп. расходы по позиции ---------- */

/* Строки расходов читаются списком: вид, сколько и почём, сумма.
   Сумма справа и моноширинными цифрами — их складывают глазами. */
.item-extras {
  border-top: 1px solid var(--border);
  display: grid;
  gap: 8px;
}
.extra-row {
  display: grid;
  grid-template-columns: 118px 150px 110px 1fr auto;
  gap: 8px;
  align-items: center;
  font-size: 13px;
}
.extra-kind { font-weight: 600; }
.extra-qty { color: var(--text-dim); }
.extra-sum { font-variant-numeric: tabular-nums; }
.extra-new { margin-top: 2px; }
.deal-editor { max-width: 1180px; margin: 0 auto; display: grid; gap: 20px; padding-bottom: 16px; }
.edit-panel { min-width: 0; padding: 24px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); box-shadow: var(--shadow); }
.edit-panel-heading, .edit-work-heading { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
.edit-panel-heading .section-icon { display: grid; place-items: center; width: 40px; height: 40px; flex-shrink: 0; border-radius: 12px; background: var(--accent-soft); color: var(--accent); }
.edit-panel h2, .edit-section-heading h2 { margin: 0; font-size: 17px; font-weight: 650; }
.edit-panel h3 { margin: 0; font-size: 16px; }
.edit-panel-heading p, .edit-section-heading p, .edit-work-heading p { margin: 5px 0 0; color: var(--text-dim); font-size: 13px; }
.edit-section-heading { padding: 8px 2px 0; }
.deal-editor .grid { gap: 18px 20px; }
.deal-editor .field { min-width: 0; gap: 7px; }
.deal-editor .field > label { font-size: 13px; }
.deal-editor .field input, .deal-editor .field select { min-height: 44px; border-radius: 8px; }
.deal-editor textarea { min-height: 80px; border-radius: 8px; resize: vertical; }
.edit-position-number { display: grid; place-items: center; width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px; font-weight: 650; background: var(--accent-soft); color: var(--accent); }
.edit-work-heading > div { flex: 1; min-width: 0; }
.edit-work-heading h3 { overflow-wrap: anywhere; }
.edit-work-heading > .btn { flex-shrink: 0; color: var(--text-dim); }
.edit-work-notice { margin: -6px 0 20px; padding: 10px 12px; border-radius: 8px; background: var(--warn-soft); color: var(--warn); font-size: 12px; line-height: 1.5; }
.edit-expenses { margin-top: 24px; border-top: 1px solid var(--border); padding-top: 16px; }
.edit-expenses summary { cursor: pointer; color: var(--text); font-size: 14px; font-weight: 600; padding: 8px 0; }
.edit-expenses summary::marker { color: var(--accent); }
.edit-expenses-hint { margin-left: 12px; color: var(--text-dim); font-size: 12px; font-weight: 400; }
.edit-expenses .expense-parties { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 12px; }
.edit-expenses .item-extras { min-width: 0; padding: 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); }
.edit-expenses .expense-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.edit-expenses .expense-fields > .field:first-child, .edit-expenses .expense-fields > .field:nth-child(4) { grid-column: 1 / -1; }
.edit-expenses .expense-fields > .btn { grid-column: 1 / -1; justify-self: start; min-height: 40px; }
.edit-expenses .extra-row { grid-template-columns: 1fr auto; gap: 6px 12px; }
.edit-expenses .extra-qty { grid-column: 1 / -1; }
.edit-add-work .btn { width: 100%; justify-content: center; min-height: 48px; border-style: dashed; background: transparent; color: var(--accent); }
#ed-new-items:empty, #ed-delete-items:empty { display: none; }
#ed-new-items { display: grid; gap: 20px; }
.deal-editor .item-row { margin: 0; }
.edit-savebar { position: sticky; bottom: 12px; z-index: 5; display: flex; align-items: center; gap: 10px; padding: 14px 18px; border: 1px solid var(--border-strong); border-radius: 12px; background: var(--surface); box-shadow: 0 4px 24px rgba(0, 0, 0, .12); }
.edit-savebar > span { flex: 1; color: var(--text-dim); font-size: 13px; }
.edit-savebar .btn { min-height: 44px; justify-content: center; }
.edit-fleet > h3 { margin-bottom: 12px; }
@media (max-width: 760px) {
  .edit-expenses .expense-parties { grid-template-columns: minmax(0, 1fr); }
  .edit-panel { padding: 18px; }
}
@media (max-width: 560px) {
  .deal-editor { gap: 16px; }
  .edit-panel { padding: 16px; border-radius: 12px; }
  .edit-panel-heading { align-items: flex-start; gap: 10px; }
  .edit-work-heading { flex-wrap: wrap; gap: 10px; }
  .edit-work-heading > .btn { padding: 6px 8px; }
  .edit-expenses-hint { display: block; margin: 6px 0 0 18px; }
  .edit-expenses .item-extras { padding: 12px; }
  .edit-expenses .expense-fields > .btn { justify-self: stretch; }
  .edit-savebar { bottom: 8px; padding: 10px; gap: 8px; }
  .edit-savebar > span { display: none; }
  .edit-savebar > .btn-primary { flex: 1; }
}
.expense-party-title { font-weight: 600; }
.expense-fields { display: grid; grid-template-columns: 2fr 1fr 1fr 2fr auto; gap: 10px; align-items: end; margin-top: 12px; }
.expense-fields > .field { min-width: 0; }
.expense-fields > .btn { min-height: 38px; }
@media (max-width: 900px) {
  .expense-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .expense-fields > .field:first-child, .expense-fields > .field:nth-child(4) { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .expense-fields > .btn { grid-column: 1 / -1; justify-content: center; }
}
/* Крестик — ровно по своему знаку: в общей сетке он иначе растягивается
   на всю свободную ширину и читается как поле ввода. */
.extra-x { justify-self: start; padding: 4px 10px; }

@media (max-width: 900px) {
  .extra-row { grid-template-columns: 1fr auto; }
  .extra-row .extra-qty { grid-column: 1 / -1; }
}

/* «Подобрать потом» под полем подрядчика в копии сделки: строка галочки
   прижата к полю, чтобы читалась как его продолжение, а не как отдельное
   поле формы. */
.copy-nocontr {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
}
.copy-nocontr input { width: 16px; height: 16px; flex: none; }

/* ---------- Правка поля нажатием по нему ---------- */

/* Значение остаётся значением: кнопка не выглядит кнопкой, пока на неё не
   навели. Иначе карточка заявки у человека с правом превращалась бы в
   россыпь рамок, хотя правят поле раз в месяц. */
.field-edit {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: text;
  border-bottom: 1px dashed transparent;
}
.field-edit:hover,
.field-edit:focus-visible { border-bottom-color: var(--accent); }
/* Пока карандаш не показан, он не занимает места. Раньше он держал ширину
   всегда, и после каждого правимого значения зияла пустая полоска в полтора
   знака: в столбик это не бросалось в глаза, а когда значения встали по два
   в строку, разделитель между ними повис далеко от первого. На телефоне
   наведения нет вовсе, и место там не тратится совсем. */
.field-edit i {
  font-style: normal;
  display: inline-block;
  width: 0;
  overflow: hidden;
  color: var(--text-faint);
  opacity: 0;
  transition: opacity .12s;
}
.field-edit:hover i,
.field-edit:focus-visible i { opacity: 1; width: auto; margin-left: 6px; }

/* Карандаш рядом со ссылкой (заказчик в шапке заявки): само название —
   ссылка в карточку организации, и оборачивать его в кнопку нельзя.
   Значок стоит рядом и проявляется, когда ведут по строке. */
/* Здесь значок — всё содержимое кнопки, а не довесок к значению, поэтому
   ширину он держит всегда: с нулевой кнопка схлопывается, и сменить
   заказчика становится нечем. */
.field-edit-near i { margin-left: 0; width: auto; }
dd:hover .field-edit-near i { opacity: 1; }

.field-editing {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  max-width: 100%;
}
.field-editing input,
.field-editing select,
.field-editing textarea { max-width: 260px; }
.field-editing textarea { min-width: 240px; }

.details-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

@media (max-width: 700px) {
  .flow { flex-direction: column; gap: 0; overflow: visible; }
  .flow-step {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    text-align: left;
    min-width: 0;
    padding: 5px 0;
  }
  .flow-step b { flex: 1; font-size: 13px; }
  .flow-step + .flow-step::before {
    top: -6px; bottom: auto; left: 17px; right: auto;
    width: 1px; height: 12px;
  }
}

/* ---------- Фотографии ---------- */

/* Компактная лента снимков в сводке: видно, что на объекте, без ухода
   в карточку файлов. */
/* Снимки объекта — одной полосой в карточке заявки и больше нигде: раньше
   те же фотографии стояли ещё и в карточке файлов, то есть человек видел
   одно и то же дважды на одном экране. Здесь же кнопка добавления. */
.photo-strip { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.photo-cell {
  width: 96px; height: 74px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  flex: none;
  cursor: zoom-in;
  background: var(--surface-2);
  transition: border-color var(--t-fast) var(--ease);
}
.photo-cell:hover { border-color: var(--border-strong); }
.photo-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Спрятанный от второй стороны снимок видно и в полосе: иначе о том, что
   его не покажут заказчику, узнают только открыв. */
.photo-cell.photo-hidden { border-color: var(--warn-bd); opacity: .75; }
.photo-cell.photo-hidden::after {
  content: '';
  position: absolute;
  inset: auto 4px 4px auto;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--warn);
}
.photo-cell { position: relative; }
.photo-strip img { width: 100%; height: 100%; object-fit: cover; display: block; }

.photo-add {
  width: 96px; height: 74px;
  flex: none;
  border: 1px dashed var(--border-strong);
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
  color: var(--text-dim);
  background: var(--surface-2);
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.photo-add:hover { border-color: var(--accent); color: var(--accent); }
.photo-add span:first-of-type { font-size: 20px; line-height: 1; }
.photo-add-txt { font-size: 11px; text-align: center; }

/* ---------- Снимок поверх страницы ---------- */

/* Открывается слоем, а не новой вкладкой: снимки смотрят подряд, и
   возвращаться назад после каждого — лишнее движение. Слой лежит в body,
   поэтому пересборка экрана по опросу сервера его не трогает. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(8, 11, 18, .92);
  display: grid;
  grid-template-columns: 56px 1fr 56px;
  grid-template-rows: auto 1fr auto;
  align-items: center;
}
.lightbox[hidden] { display: none; }
body.lb-open { overflow: hidden; }

.lb-top {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  color: #e6e9ef;
  font-size: 13px;
}
.lb-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-count { color: #99a3b2; font-variant-numeric: tabular-nums; margin-left: auto; }
.lb-btn {
  background: rgba(255, 255, 255, .12);
  color: #e6e9ef;
  border: 0;
  border-radius: 6px;
  padding: 6px 12px;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}
.lb-btn:hover { background: rgba(255, 255, 255, .2); }
.lb-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lb-close { font-size: 15px; line-height: 1; padding: 6px 10px; }

.lb-stage {
  grid-column: 2;
  grid-row: 2;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  touch-action: none;
}
.lb-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  user-select: none;
  transform-origin: center center;
  cursor: zoom-in;
}
.lightbox.lb-zoomed .lb-img { cursor: grab; }

.lb-arrow {
  grid-row: 2;
  background: none;
  border: 0;
  color: #e6e9ef;
  font-size: 40px;
  line-height: 1;
  cursor: pointer;
  padding: 8px;
  opacity: .7;
}
.lb-arrow:hover { opacity: 1; }
.lb-arrow:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lb-prev { grid-column: 1; }
.lb-next { grid-column: 3; }

.lb-meta {
  grid-column: 1 / -1;
  padding: 10px 16px 16px;
  color: #99a3b2;
  font-size: 12px;
  text-align: center;
}

@media (max-width: 560px) {
  .lightbox { grid-template-columns: 40px 1fr 40px; }
  .lb-arrow { font-size: 30px; }
  .photo-cell, .photo-add { width: 84px; height: 66px; }
}

/* Снимок с объекта должен быть виден снимком. Сетка тянется сама:
   auto-fill не даёт одинокой фотографии растянуться на всю ширину. */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 10px;
}
.photo {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-2);
}
.photo a { display: block; }
.photo img {
  display: block;
  width: 100%;
  height: 140px;
  object-fit: cover;
  background: var(--surface-2);
}
.photo figcaption {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  font-size: 11px;
  color: var(--text-faint);
  border-top: 1px solid var(--border);
}
.photo figcaption span {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Выбранные, но ещё не отправленные: заявки-то ещё нет */
.attach-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  margin-top: 12px;
}
.attach-grid:empty { margin-top: 0; }
.attach {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-2);
  padding-bottom: 6px;
}
.attach img {
  display: block; width: 100%; height: 100px; object-fit: cover;
}
.attach-doc {
  display: flex; align-items: center; justify-content: center;
  height: 100px;
  font-size: 13px; font-weight: 600; letter-spacing: .5px;
  color: var(--text-dim); text-transform: uppercase;
  background: var(--surface);
}
.attach-name {
  display: block; padding: 6px 8px 0;
  font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.attach-size { display: block; padding: 0 8px; font-size: 11px; color: var(--text-faint); }
/* Цель удаления снимка была 24 точки — попасть пальцем в перчатке нельзя, а
   промах удаляет соседний кадр без подтверждения. Снимок здесь — главное
   доказательство объёма в споре. */
@media (max-width: 760px) {
  .attach-del { width: 34px; height: 34px; font-size: 20px; }
}
.attach-del {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: 50%;
  background: rgba(6, 8, 12, .6); color: #fff;
  font-size: 16px; line-height: 1; cursor: pointer;
}
.attach-del:hover { background: var(--danger); }

/* Выбор файла — это <input type="file"> внутри <label>: свой вид кнопки
   браузеру не задать, поэтому сам input скрыт, а нажимают на label. */
.file-btn { display: inline-block; cursor: pointer; }

/* ---------- Претензии ---------- */

.claim {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 10px;
  background: var(--surface-2);
}
.claim:last-child { margin-bottom: 0; }
.claim-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.claim-sides { font-size: 13px; margin-bottom: 8px; }
.claim-sides .muted { margin: 0 2px; }
.claim-text { font-size: 14px; line-height: 1.5; white-space: pre-wrap; }
.claim-res {
  margin-top: 8px; padding-top: 8px; font-size: 13px;
  border-top: 1px dashed var(--border); color: var(--text-dim);
}
.claim-foot {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; margin-top: 10px;
}
textarea {
  width: 100%; font: inherit; font-size: 14px;
  padding: 9px 11px; border-radius: 6px; resize: vertical;
  background: var(--surface); color: var(--text); border: 1px solid var(--border-strong);
}
textarea:focus { outline: none; border-color: var(--accent); }

/* ---------- Подбор подрядчика ---------- */

tr.row-off { opacity: .55; }
tr.row-off:hover { background: transparent; }

.doc-check { display: flex; align-items: center; gap: 8px; flex: 1; cursor: pointer; }
.doc-check input { margin: 0; }

/* Выбор машин под заявку. Строки те же, что у документов, но в рамке:
   это часть решения «принимаю», а не отдельный список. На телефоне
   госномер и марка переносятся, а не режутся. */
.pick-units {
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
}
.pick-units .doc-check { padding: 6px 0; flex-wrap: wrap; }
.pick-title {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 4px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: baseline;
}

/* ---------- Старый рейтинг с классами (не используется) ---------- */

.rating {
  display: inline-flex;
  align-items: stretch;
  border-radius: 6px;
  overflow: hidden;
  font-size: 14px;
  line-height: 1;
  border: 1px solid var(--rc, var(--border-strong));
  white-space: nowrap;
}
.rating b { padding: 5px 8px; font-weight: 600; color: var(--rc); background: var(--rcs); }
.rating i {
  padding: 5px 8px;
  font-style: normal;
  font-weight: 700;
  background: var(--rc);
  /* Ступени рейтинга в тёмной теме светлые — белым по ним не напишешь. */
  color: var(--on-accent);
}
.rating-sm { font-size: 12px; }
.rating-sm b, .rating-sm i { padding: 3px 6px; }

.rating-S { --rc: #0b7a4b; --rcs: #e6f4ed; }
.rating-A { --rc: #2f8f4e; --rcs: #eaf5ec; }
.rating-B { --rc: #1d4ed8; --rcs: #e7eefd; }
.rating-C { --rc: #b54708; --rcs: #fdf1e3; }
.rating-D { --rc: #c2410c; --rcs: #fdeee6; }
.rating-E { --rc: #d92d20; --rcs: #fdecea; }

@media (prefers-color-scheme: dark) {
  .rating-S { --rcs: #14301f; }
  .rating-A { --rcs: #16301d; }
  .rating-B { --rcs: #17233c; }
  .rating-C { --rcs: #392718; }
  .rating-D { --rcs: #3a2318; }
  .rating-E { --rcs: #3a1d1c; }
}

.rating-head { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.rating-table { margin-top: 4px; }
.rating-table tfoot td { padding: 10px 12px; border-top: 1px solid var(--border-strong); }

.scale { display: flex; flex-wrap: wrap; gap: 14px; }
.scale-item { display: flex; align-items: center; gap: 7px; }

/* ---------- Биржа заказов ---------- */

.board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; }
@media (max-width: 1200px) { .board { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 760px) { .board { grid-template-columns: 1fr; } }

.board-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
  display: flex;
  flex-direction: column;
}
.board-card:hover { border-color: var(--border-strong); }
.board-top { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; margin-bottom: 12px; }
.board-work { font-size: 16px; font-weight: 600; letter-spacing: -.2px; }
.board-price { font-size: 24px; font-weight: 600; letter-spacing: -.5px; }
.board-price span { font-size: 13px; font-weight: 400; color: var(--text-dim); margin-left: 5px; }
.board-kv { grid-template-columns: 110px 1fr; font-size: 13px; margin-bottom: 10px; }
.board-note {
  font-size: 12.5px;
  color: var(--text-dim);
  background: var(--surface-2);
  border-radius: 6px;
  padding: 8px 10px;
  margin-bottom: 10px;
}
.board-fit { font-size: 12px; margin-bottom: 12px; }
.board-fit.ok { color: var(--ok); }
.board-fit.warn { color: var(--warn); }
.board-actions { margin-top: auto; display: flex; gap: 8px; }
.board-actions .btn { flex: 1; justify-content: center; }

/* ---------- Файлы документов ---------- */

.file-btn { cursor: pointer; }

.doc-files { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.doc-file {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 12px;
  color: inherit;
}
.doc-file:hover { border-color: var(--accent); text-decoration: none; }
.doc-file-name { color: var(--accent); word-break: break-all; }

/* ---------- Мониторинг диска ---------- */

.disk-bar {
  position: relative;
  height: 22px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  overflow: hidden;
}
/* Тянем масштабом, а не шириной: анимация ширины дёргает раскладку. */
.disk-bar > i {
  display: block; height: 100%; width: 100%;
  transform-origin: left; transition: transform .3s;
}
.disk-bar > i.lvl-ok { background: var(--ok); }
.disk-bar > i.lvl-warning { background: var(--warn); }
.disk-bar > i.lvl-critical { background: var(--danger); }
.disk-bar .mark {
  position: absolute;
  top: 0;
  width: 2px;
  height: 100%;
  background: var(--text-dim);
  opacity: .55;
}
.disk-bar .mark.crit { background: var(--danger); opacity: .8; }
.disk-legend {
  position: relative;
  height: 14px;
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 5px;
}
.disk-legend > span { position: absolute; top: 0; white-space: nowrap; }
.disk-legend .at-start { left: 0; }
.disk-legend .at-end { right: 0; }
/* Подпись порога — серединой под меткой; у правой к метке прижат правый
   край, чтобы она не вылезала за полосу. */
.disk-legend .at { transform: translateX(-50%); }
.disk-legend .at.to-left { transform: translateX(-100%); }
/* На телефоне пороги стоят в полусантиметре друг от друга, и подписи
   налезали одна на другую. Оставляем проценты; словами — в подсказке. */
@media (max-width: 700px) {
  .disk-legend .long { display: none; }
}

/* ---------- Партнёр в карточке ---------- */

/* Своей нижней границы нет: под шапкой сразу идёт полоса фактов со своей
   верхней линией, и вместе они давали две черты подряд. */
.partner-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding-bottom: 14px;
}

/* ---------- Выбор районов ---------- */

.tag-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.tag-opt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border: 1px solid var(--border-strong);
  border-radius: 20px;
  font-size: 12.5px;
  cursor: pointer;
  background: var(--surface);
}
.tag-opt.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.tag-opt input { margin: 0; }

/* Район, который этот сотрудник менять не вправе. Сама галочка серая, а
   кружок вокруг неё оставался синим и нажимался как живой — читалось как
   поломка, а не как «вам сюда нельзя». */
.tag-opt:has(input:disabled) {
  cursor: default;
  opacity: .72;
  border-color: var(--border);
  background: var(--bg);
}
.tag-opt.on:has(input:disabled) { border-color: var(--border-strong); color: var(--text-dim); }

/* ---------- Расписание техники ---------- */

.legend { display: flex; gap: 18px; flex-wrap: wrap; font-size: 12px; color: var(--text-dim); }
.legend .sw {
  display: inline-block;
  width: 12px; height: 12px;
  border-radius: 3px;
  vertical-align: -2px;
  margin-right: 5px;
  border: 1px solid var(--border-strong);
}
.sw-platform { background: var(--accent); border-color: var(--accent); }
.sw-manual { background: var(--border-strong); }
.sw-free { background: var(--surface); }

table.schedule { font-size: 12px; table-layout: fixed; }
table.schedule th:first-child, table.schedule td:first-child { width: 190px; }
table.schedule th { text-align: center; }
table.schedule th.weekend, table.schedule td.weekend { background: var(--surface-2); }
.sch-unit { text-align: left; }
.sch-cell { padding: 4px !important; vertical-align: top; text-align: center; }
.sch-busy {
  display: block;
  border-radius: 4px;
  padding: 3px 4px;
  margin-bottom: 3px;
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: default;
}
.sch-busy.is-platform { background: var(--accent); color: var(--on-accent); }
.sch-busy.is-manual { background: var(--border-strong); color: var(--text); }

.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn[disabled]:hover { background: var(--surface); }
/* У основной кнопки заливка своя, и правило выше делало её на наведении
   белой — вместе с белыми буквами. Видно это как раз на «Ищем…», пока
   ждём ответ реестра. */
.btn-primary[disabled]:hover { background: var(--accent); color: var(--on-accent); }

.btn-danger { border-color: var(--danger); color: var(--danger); }
.btn-danger:hover { background: var(--danger-soft); }

code {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 12.5px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
}

.kv dd select[multiple], .field select[multiple] { padding: 4px; }

.user-box { display: flex; align-items: center; gap: 12px; }
.user-info { text-align: right; line-height: 1.25; }
.user-info b { display: block; font-size: 13px; }
.user-info span { font-size: 12px; color: var(--text-dim); }

/* ---------- Роли и права ---------- */

/* Матрица «роль × право». Заголовки узкие и длинные, поэтому ставим их
   боком — иначе таблица уезжает вширь на семь колонок подряд. */
.roles-table th { font-size: 11px; line-height: 1.25; vertical-align: bottom; }
.roles-table th:not(:first-child) { max-width: 92px; white-space: normal; }
.roles-table td { vertical-align: middle; }
.perm-cell { text-align: center; }
.perm input { width: 18px; height: 18px; cursor: pointer; }
.roles-table input[type=text] { min-width: 150px; }
.roles-mobile { display:none; }
@media (max-width:760px) {
  .roles-desktop { display:none; }
  .roles-mobile { display:block; padding:0 12px 14px; }
  .roles-card > h2 { border-bottom:0; padding-bottom:4px; }
  .roles-intro { margin:0 4px 16px; color:var(--text-dim); font-size:13px; }
  .role-panel { border:1px solid var(--border); border-radius:12px; margin-top:8px; background:var(--surface); overflow:hidden; }
  .role-panel > summary { display:flex; align-items:center; gap:10px; padding:14px 12px; cursor:pointer; list-style:none; min-height:72px; }
  .role-panel > summary::-webkit-details-marker { display:none; }
  .role-panel > summary:focus-visible { outline:2px solid var(--accent); outline-offset:-3px; border-radius:12px; }
  .role-avatar { display:flex; align-items:center; justify-content:center; width:36px; height:36px; flex-shrink:0; border-radius:10px; color:var(--accent); background:var(--accent-soft); }
  .role-summary { flex:1; min-width:0; }
  .role-summary b { display:block; font-size:14px; line-height:1.4; overflow-wrap:anywhere; }
  .role-summary small { display:block; margin-top:4px; font-size:11px; color:var(--text-dim); line-height:1.4; }
  .role-chevron { flex-shrink:0; font-size:22px; color:var(--text-dim); line-height:1; transform:translateY(-3px); }
  .role-panel[open] { border-color:var(--border-strong); }
  .role-panel[open] > summary { background:var(--surface-2); border-bottom:1px solid var(--border); }
  .role-panel[open] .role-chevron { transform:rotate(180deg); }
  .role-panel-body { padding:14px 12px; }
  .role-name-field { display:block; font-size:12px; color:var(--text-dim); }
  .role-name-field input { display:block; width:100%; min-width:0; margin-top:6px; font-size:16px; }
  .role-permission-group { margin-top:18px; }
  .role-permission-group h3 { margin:0 0 4px; padding:0 0 8px; color:var(--accent); font-size:11px; letter-spacing:.05em; text-transform:uppercase; line-height:1.5; }
  .role-permission { position:relative; display:flex; align-items:center; gap:12px; min-height:56px; padding:12px 0; border-top:1px solid var(--border); cursor:pointer; }
  .role-permission-text { flex:1; min-width:0; font-size:13px; line-height:1.5; color:var(--text); }
  .role-permission-text small { display:block; margin-top:4px; color:var(--text-dim); font-size:11px; }
  .role-permission input { position:absolute; right:0; width:44px; height:26px; margin:0; opacity:0; cursor:pointer; }
  .role-switch { width:40px; height:24px; flex-shrink:0; border-radius:20px; background:var(--border-strong); pointer-events:none; transition:background .15s; }
  .role-switch::after { content:''; display:block; width:18px; height:18px; margin:3px; border-radius:50%; background:var(--surface); box-shadow:0 1px 3px #0003; transition:transform .15s; }
  .role-permission input:checked + .role-switch { background:var(--accent); }
  .role-permission input:checked + .role-switch::after { transform:translateX(16px); }
  .role-permission input:focus-visible + .role-switch { outline:2px solid var(--accent); outline-offset:3px; }
  .role-permission input:disabled + .role-switch { opacity:.45; }
  .role-permission:has(input:disabled) { cursor:default; }
  .role-permission input:disabled { cursor:default; }
  .role-delete { margin-top:18px; width:100%; justify-content:center; }
  .roles-card .role-create { display:grid !important; grid-template-columns:minmax(0,1fr) auto; align-items:end; padding:16px; background:var(--surface-2); border-radius:0 0 var(--radius) var(--radius); }
  .role-create .field { min-width:0; max-width:none !important; }
  .role-create input { min-width:0; width:100%; font-size:16px; }
  .role-create .btn { min-height:44px; }
}
@media (prefers-reduced-motion:reduce) {
  .role-switch, .role-switch::after { transition:none; }
}

/* Подсказка про Ctrl всплывает поверх карты и сама уходит: писать её
   постоянной строкой под картой — шум ради одного раза. */
.map-box { position: relative; }
.map-hint {
  position: absolute;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(6, 8, 12, .5);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s;
}
.map-hint.show { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .map-hint { transition: none; } }

/* ---------- Комментарии в карточке организации ---------- */

.notes { display: flex; flex-direction: column; gap: 12px; }
.note { font-size: 13px; }
.note-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
.note-head b { font-size: 13px; }

/* ---------- Графики ---------- */

/* Две величины на графике — две роли цвета. Пара проверена на разделимость
   при дальтонизме на обеих подложках сайта (#ffffff и #181c22), поэтому
   менять эти значения на глаз нельзя: только вместе с новой проверкой. */
.viz {
  --viz-s1: #1d4ed8;   /* наша прибыль — она и есть смысл графика */
  --viz-s2: #eb6834;   /* выплаты подрядчикам */
  --viz-grid: var(--border);
  --viz-axis: var(--border-strong);
}

@media (prefers-color-scheme: dark) {
  .viz { --viz-s1: #5b92f7; --viz-s2: #d95926; }
}

.viz-plot { overflow-x: auto; }
.viz-svg { display: block; width: 100%; min-width: 480px; height: auto; }

.viz-grid { stroke: var(--viz-grid); stroke-width: 1; }
.viz-axis { stroke: var(--viz-axis); stroke-width: 1; }

/* Подписи носят цвет текста, а не цвет ряда: цвет несёт метка рядом. */
.viz-tick { fill: var(--text-faint); font-size: 11px; font-variant-numeric: tabular-nums; }
.viz-value { fill: var(--text-dim); font-size: 12px; font-weight: 600; }
/* На телефоне полоса недели около сорока точек, и подпись в двенадцать
   пунктов в неё не влезает. Мельче — влезает; те, что всё равно не помещаются,
   график пропускает сам. */
@media (max-width: 700px) { .viz-value { font-size: 10px; } }

.viz-s1 { fill: var(--viz-s1); }
.viz-s2 { fill: var(--viz-s2); fill-opacity: .88; }

/* Прозрачная область наведения во всю ширину полосы: попадать в тонкий
   столбик мышью не нужно. */
.viz-hit { fill: transparent; }
.viz-bar { cursor: default; }
.viz-bar:hover .viz-s1, .viz-bar:focus .viz-s1,
.viz-bar:hover .viz-s2, .viz-bar:focus .viz-s2 { filter: brightness(1.12); }
.viz-bar:focus { outline: none; }
.viz-bar:focus .viz-hit { fill: var(--accent-soft); }

.viz-legend {
  display: flex; gap: 18px; flex-wrap: wrap;
  font-size: 13px; color: var(--text-dim); margin-bottom: 10px;
}
.viz-key {
  display: inline-block; width: 10px; height: 10px;
  border-radius: 2px; margin-right: 6px;
}

/* Точки заявок: сумма заказчика против нашей маржи. Слабые (ниже десятой
   доли) — другим цветом и это же сказано в легенде словами: цвет не должен
   быть единственным признаком. */
.viz-dot { fill: var(--viz-s1); opacity: .72; stroke: var(--surface); stroke-width: 2; }
.viz-dot-low { fill: var(--viz-s2); opacity: .85; }
.viz-bar:hover .viz-dot, .viz-bar:focus .viz-dot { opacity: 1; r: 7; }
.viz-share { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 5 4; opacity: .55; }
.viz-key-dot { border-radius: 50%; background: var(--viz-s1); }
.viz-key-dot.low { background: var(--viz-s2); }

/* Кнопки отбора над точками — ссылки: отбор живёт в адресе, и ссылкой на
   «только аренда техники» можно поделиться. */
.viz-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.viz-chip {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 12.5px;
  color: var(--text-dim);
  text-decoration: none;
  white-space: nowrap;
}
.viz-chip:hover { border-color: var(--border-strong); color: var(--text); }
.viz-chip.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.viz-table { margin-top: 12px; }
.viz-table summary {
  cursor: pointer; font-size: 13px; color: var(--text-dim);
  padding: 4px 0;
}
.viz-table summary:hover { color: var(--text); }

.viz-tip {
  position: absolute; z-index: 60; transform: translate(-50%, -100%);
  background: var(--text); color: var(--surface);
  padding: 7px 10px; border-radius: 6px; font-size: 12px;
  max-width: 320px; pointer-events: none; opacity: 0;
  transition: opacity .12s;
}
.viz-tip.on { opacity: 1; }

/* ---------- Колонки одинаковой высоты ---------- */

/* Соседние карточки заканчиваются на одном уровне, а не рваной лесенкой.
   Сетка растягивает колонку, карточка внутри занимает её целиком. */
.grid.stretch { align-items: stretch; }
.grid.stretch > div { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.grid.stretch > div > .card:last-child { flex: 1 1 auto; }

/* ---------- Пары полей: объём с единицей, время с и до ---------- */

.pair { display: flex; gap: 6px; }
.pair > * { min-width: 0; }
.pair > input { flex: 1 1 auto; }
.pair > select { flex: 0 0 auto; width: auto; }

/* ---------- Кто ведёт заявку и передача её в подбор ---------- */

/* Две половины работы: продажник на стороне заказчика, аккаунт-менеджер
   на стороне подрядчиков. В шапке они стоят рядом, чтобы было видно,
   к кому идти с вопросом. */
.owners { display: flex; gap: 16px; flex-wrap: wrap; margin-right: 12px; }
.owner { font-size: 13px; white-space: nowrap; }
.owner i {
  display: block;
  font-style: normal;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.handoff { display: inline-flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.handoff select { min-width: 210px; }

@media (max-width: 720px) {
  .owners { width: 100%; margin: 8px 0 0; }
  .handoff { width: 100%; }
  .handoff select, .handoff .btn { width: 100%; }
}

/* ---------- Окно с причиной отказа ---------- */

.ask {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  padding: 0;
  width: min(420px, calc(100vw - 32px));
  box-shadow: 0 12px 32px rgba(16, 24, 40, .18);
}
.ask::backdrop { background: rgba(16, 24, 40, .45); }
.ask form { display: flex; flex-direction: column; gap: 12px; padding: 18px; }
.ask h3 { margin: 0; font-size: 16px; }
.ask-hint { margin: 0; font-size: 13px; color: var(--text-dim); }
.ask-warn {
  margin: 0; font-size: 13px; color: var(--danger);
  background: var(--danger-soft); border-radius: 6px; padding: 8px 10px;
}
.ask-list { display: flex; flex-direction: column; gap: 2px; }
.ask-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 6px; cursor: pointer; font-size: 14px;
}
.ask-item:hover { background: var(--surface-2); }
.ask-item input { margin: 0; }
.ask-item:has(input:checked) { background: var(--accent-soft); }
/* Пояснение можно дописать к любой причине, но у «другой» оно и есть причина. */
.ask-note .ask-req { display: none; color: var(--danger); }
.ask-note.need .ask-req { display: inline; }
.ask-note textarea { resize: vertical; }
.ask-buttons { display: flex; justify-content: flex-end; gap: 8px; }

.tg-cell { display: flex; align-items: center; gap: 6px; }
.tg-input { width: 130px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* ---------- Заявки из телеграма ---------- */

.banner-warn { background: var(--warn-soft); color: var(--warn); border-color: var(--warn-bd); }

.lead-list { display: flex; flex-direction: column; gap: 10px; }
.lead {
  display: flex; flex-direction: column; gap: 6px;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px; background: var(--surface-2);
}
/* Непринятую видно сразу: это единственное, ради чего сюда заходят. Отличается
   вся карточка целиком — заливкой и границей, а не полоской у края. */
.lead-missed { border-color: var(--warn-bd); background: var(--warn-soft); }
.lead-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.lead-gaps { color: var(--warn); }
.lead-text summary { cursor: pointer; color: var(--text-dim); }
.lead-text pre {
  margin: 6px 0 0; padding: 10px; border-radius: 6px;
  background: var(--surface); border: 1px solid var(--border);
  white-space: pre-wrap; font-size: 12px; overflow-x: auto;
}
.lead-buttons { display: flex; gap: 8px; align-items: center; margin-top: 2px; }

/* ---------- Почему отказываются ---------- */

.why-block h3 { font-size: 13px; margin: 0 0 10px; font-weight: 600; }
.why { display: flex; flex-direction: column; gap: 6px; }
.why-row {
  display: grid; grid-template-columns: minmax(90px, 1.4fr) 2fr auto;
  gap: 10px; align-items: center; font-size: 12px;
}
.why-name { color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.why-track { background: var(--surface-2); border-radius: 3px; height: 10px; }
.why-fill { background: var(--viz-s1); border-radius: 3px; height: 100%; }
.why-n { font-variant-numeric: tabular-nums; color: var(--text); min-width: 54px; text-align: right; }

.mail-input { width: 170px; font-size: 12px; }

/* ---------- Движение ----------

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

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

   Класс на .content ставится заново при каждой отрисовке (см. render в
   app.js). Смещение живёт только пока идёт анимация, поэтому всплывающие
   подсказки внутри содержимого от него не съезжают. */

@keyframes screen-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.content.screen-in > * { animation: screen-in var(--t-screen) var(--ease) backwards; }
.content.screen-in > *:nth-child(2) { animation-delay: .02s; }
.content.screen-in > *:nth-child(3) { animation-delay: .04s; }
.content.screen-in > *:nth-child(4) { animation-delay: .06s; }
.content.screen-in > *:nth-child(5) { animation-delay: .08s; }
.content.screen-in > *:nth-child(n+6) { animation-delay: .1s; }

/* Отклик управления. Только цвет и граница: ничего не двигается и не
   меняет размер, чтобы соседние элементы стояли на месте. */
.btn, .nav a, .tile, .suggest-item, .role-picker select {
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.card { transition: border-color var(--t-fast) var(--ease); }
input[type=text], input[type=date], input[type=time], input[type=number],
input[type=password], input[type=email], input[type=tel], select, textarea {
  transition: border-color var(--t-fast) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .content.screen-in > * { animation: none; }
  .btn, .nav a, .tile, .card, .suggest-item, .role-picker select,
  input, select, textarea { transition: none; }
}

/* ---------- Список сделок: месяцы, дни, отметки ---------- */

/* Полоса месяцев вместо календарика с двумя датами. Диспетчер живёт
   месяцами — «что было в августе», «что едет в октябре», — и попадать в
   два поля ради этого не должен. Соседние месяцы видны рядом, потому что
   переход между ними — самое частое движение на экране. */
.month-strip {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.month-strip .month {
  padding: 7px 14px;
  border-radius: 8px;
  color: var(--text-dim);
  font-weight: 500;
  white-space: nowrap;
}
.month-strip a.month:hover { background: var(--surface-2); text-decoration: none; }
.month-strip .month.now {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}
/* Пустое место соседнего месяца не схлопываем: иначе выбранный месяц
   прыгает влево-вправо при переходе к краю списка. */
.month-strip .month.off { opacity: 0; pointer-events: none; min-width: 40px; }
.month-strip .month-arrow {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  color: var(--text-dim);
  font-size: 18px;
  line-height: 1;
}
.month-strip .month-arrow:hover { background: var(--surface-2); text-decoration: none; }
.month-strip .month-arrow.off { opacity: .4; pointer-events: none; }
.month-strip .today-box { display: flex; gap: 6px; align-items: baseline; margin-right: 8px; }
.month-day-range { display: flex; align-items: center; gap: 12px; margin-left: 8px; padding-left: 18px; border-left: 1px solid var(--border); }
.day-range-title { color: var(--text-dim); font-size: 12px; white-space: nowrap; }
.day-range-fields { display: flex; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); overflow: hidden; }
.day-range-field { display: flex; align-items: center; gap: 3px; padding: 0 10px; cursor: text; }
.day-range-field + .day-range-field { border-left: 1px solid var(--border); }
.day-range-field > span { color: var(--text-dim); font-size: 12px; }
.month-day-range input { appearance: textfield; -moz-appearance: textfield; width: 34px; min-width: 0; height: 40px; padding: 0; text-align: center; font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--accent); border: 0; border-radius: 0; background: transparent; box-shadow: none; }
.month-day-range input::-webkit-inner-spin-button, .month-day-range input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.month-day-range input.is-default { color: var(--text-faint); font-weight: 500; }
.day-range-field:hover { background: var(--surface); }
.day-range-field:focus-within { background: var(--accent-soft); box-shadow: inset 0 -2px var(--accent); }
.month-day-range input:focus { outline: none; box-shadow: none; }
@media (max-width: 700px) {
  .month-strip .month-day-range { order: 10; flex: 1 0 100%; justify-content: space-between; gap: 12px; margin: 6px 0 0; padding: 12px 0 0; border-left: 0; border-top: 1px solid var(--border); }
  .day-range-title { font-size: 13px; }
  .day-range-field { gap: 5px; padding: 0 12px; }
  .day-range-field > span { font-size: 13px; }
  .month-day-range input { width: 36px; height: 44px; font-size: 16px; }
}

/* ---------- Список сделок: карточки ----------

   Была таблица в десять колонок, и она читалась сплошной простынёй: у
   каждого дня своя шапка и свои ширины столбцов, так что «Заказчик» во
   втором дне стоял не там, где в первом; работа и адрес резались
   многоточием. Теперь каждая сделка — своя скруглённая карточка с зазором
   до соседней, дни — подписи между ними, деньги — отдельный блок справа. */
.deals-month { margin-bottom: 12px; }
.month-head {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  padding: 12px 12px 12px 20px;
  margin-bottom: 4px;
  font-size: 15px;
  border-radius: 14px;
}
.month-head > b:first-child { font-size: 18px; letter-spacing: -.2px; }
/* «Итого» и сумма — одним куском: на телефоне строка переносится, и слово
   оставалось справа, а число уезжало на следующую строку одно. */
.month-total { white-space: nowrap; }
.month-total b { font-size: 17px; font-variant-numeric: tabular-nums; }
.month-head .btn { border-radius: 10px; }
.day-head {
  display: flex;
  gap: 8px;
  align-items: baseline;
  flex-wrap: wrap;
  padding: 14px 20px 8px;
  font-size: 14px;
}
/* Дата дня — главный ориентир в списке: по ней ищут «что было 16-го».
   Была того же кегля, что и соседние подписи, и терялась между карточками.
   Теперь она крупнее и синяя — акцент списка на ней, а не на номерах
   сделок (их притушили в .deal-card-no). Синяя метка слева была, пока
   синим был номер; теперь синяя сама дата, и метка стала лишней. */
.day-head > b {
  font-size: 17px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -.2px;
}
.deals-month > .empty { border-radius: 14px; }

.deal-cards { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.deal-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 400px;
  gap: 20px;
  align-items: center;
  padding: 14px 14px 14px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(19, 26, 46, .04);
  /* Вся карточка ведёт в заявку, поэтому и выглядит нажимаемой. Ссылки
     внутри (заказчик, подрядчик) остаются собой и ведут в свои карточки. */
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease);
}
.deal-card:hover { border-color: var(--border-strong); }
.deal-card-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.deal-card-top { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; }
/* Номер — служебный: по нему сделку называют вслух, но ищут её по дате и
   работе. Синий и крупный, он перетягивал на себя весь акцент карточки;
   теперь тише — тёмно-серый и мельче. Ссылкой он остаётся: по наведению
   синеет, как и положено ссылке. */
.deal-card-no { font-size: 14px; font-weight: 600; color: var(--text-dim); }
.deal-card-no:hover { color: var(--accent); }
.deal-card-top .pill { padding: 3px 10px; font-weight: 600; }
.deal-card-when { color: var(--text-dim); font-size: 13px; font-variant-numeric: tabular-nums; }
.deal-card-when:empty { display: none; }
.deal-card-work { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 10px; }
.deal-card-work b { font-size: 15px; font-weight: 600; }
.deal-card-work .muted { font-size: 13px; }
.deal-card-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 20px;
  font-size: 13px;
  color: var(--text-dim);
}
.deal-card-sides { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; }
.deal-card-arrow { color: var(--text-faint); }

.deal-card-money {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--surface-2);
  font-variant-numeric: tabular-nums;
}
/* Без права видеть цену подрядчика остаётся одна сумма — блок не тянется
   на три пустых места. */
.deal-card-money.one { grid-template-columns: minmax(0, 1fr); justify-self: end; min-width: 140px; }
.deal-card-money dt { font-size: 12px; font-weight: 600; color: var(--text-faint); }
.deal-card-money dd { margin: 2px 0 0; font-size: 15px; white-space: nowrap; }
.deal-card-money .pay dd { color: var(--text-dim); }
.deal-card-money .profit b { color: var(--ok); }

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

/* Телефон: та же карточка в столбик. Деньги уходят под описание во всю
   ширину, три суммы остаются в ряд — их сравнивают друг с другом. */
@media (max-width: 700px) {
  .month-head { padding: 10px 12px; gap: 8px 10px; }
  .month-head .btn { flex: 1 1 100%; justify-content: center; }
  .day-head { padding: 10px 6px 6px; }
  .deal-card { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 14px; }
  .deal-card-meta { flex-direction: column; gap: 4px; }
  .deal-card-money { padding: 10px 12px; }
  .deal-card-money.one { justify-self: stretch; }
  .deal-card-money dd { font-size: 14px; }
}

@media (max-width: 700px) {
  /* Остальные телефонные правила этого экрана — в конце файла: они должны
     перебивать общий блок про отбор и кнопки, который стоит ниже. */
  .month-strip .month.off { display: none; }
}

/* Фильтры на телефоне встают сеткой по два в ряд. Свободным потоком
   каждый список занимал свою строку разной длины, и отбор съедал больше
   половины экрана — до самих заявок надо было ещё долистать. */
@media (max-width: 700px) {
  .filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .filters > input[type=text] { grid-column: 1 / -1; min-width: 0; }
  .filters > .pill { grid-column: 1 / -1; }
  /* В равных ячейках кнопка с текстом у левого края читается как поле ввода. */
  .filters > .btn { display: inline-flex; align-items: center; justify-content: center; }
  /* Распорка, которая в потоке отжимала кнопку вправо, в сетке стала бы
     пустой ячейкой. */
  .filters > span:empty { display: none; }

  /* Пояснение рядом с заголовком карточки рвало сам заголовок
     на две строки; пусть переезжает под него целиком. */
  /* Длинное пояснение переедет под заголовок само; короткий счётчик
     останется рядом — раньше «48» занимало целую строку. */
  .card > h2 { flex-wrap: wrap; }
}

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

   Только для настоящего курсора: на сенсорном экране hover залипает после
   касания, и строка осталась бы сдвинутой без причины. */
@media (hover: hover) {
  tbody td:first-child > a { display: inline-block; transition: transform var(--t-fast) var(--ease); }
  tbody tr:hover > td:first-child > a { transform: translateX(4px); }
}

@media (prefers-reduced-motion: reduce) {
  tbody td:first-child > a { transition: none; }
  tbody tr:hover > td:first-child > a { transform: none; }
}

/* Статистика: спокойная карточка с линией тренда вместо тяжёлой таблицы столбиков. */
.viz {
  overflow: hidden;
  background: linear-gradient(145deg, var(--surface), var(--surface-2));
}
.viz > h2,
.viz > .viz-title-row {
  min-height: 68px;
  margin: 0;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(120deg, var(--surface), var(--surface-2));
}
.viz-title-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.viz-title-row h2 { margin: 0; padding: 0; border: 0; min-width: 0; }
.viz-title-row .hint { display: block; margin-top: 5px; }
.viz-kpi { display: grid; gap: 2px; flex: none; text-align: right; }
.viz-kpi strong { color: var(--viz-s1); font-size: 19px; letter-spacing: -.02em; }
.viz-kpi span { color: var(--text-faint); font-size: 11px; }
.viz .card-body { padding: 18px 20px 16px; }
.viz-plot {
  overflow-x: auto;
  margin: 2px 0 0;
  padding: 10px 8px 4px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.55);
}
.viz-svg { min-width: 620px; }
.viz-svg-count { min-height: 190px; }
.viz-grid { stroke-dasharray: 2 6; opacity: .72; }
.viz-now { stroke: var(--accent); stroke-width: 1; stroke-dasharray: 3 5; opacity: .38; }
.viz-area { fill: url(#viz-client-area); opacity: .9; pointer-events: none; }
.viz-area-start { stop-color: var(--viz-s2); stop-opacity: .18; }
.viz-area-end { stop-color: var(--viz-s2); stop-opacity: 0; }
.viz-client-line { fill: none; stroke: var(--viz-s2); stroke-width: 2; stroke-dasharray: 5 5; opacity: .85; pointer-events: none; }
.viz-line { fill: none; stroke: var(--viz-s1); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; filter: drop-shadow(0 3px 4px rgba(29,78,216,.18)); }
.viz-point { fill: var(--surface); stroke: var(--viz-s1); stroke-width: 3; pointer-events: none; }
.viz-count-area { fill: url(#viz-count-area); opacity: .65; pointer-events: none; }
.viz-count-area-start { stop-color: var(--viz-s1); stop-opacity: .16; }
.viz-count-area-end { stop-color: var(--viz-s1); stop-opacity: 0; }
.viz-count-bar { fill: var(--viz-s1); opacity: .82; pointer-events: none; }
.viz-count-line { fill: none; stroke: var(--viz-s1); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; opacity: .88; }
.viz-count-point { fill: var(--surface); stroke: var(--viz-s1); stroke-width: 2.5; pointer-events: none; }
.viz-bar:hover .viz-count-bar, .viz-bar:focus .viz-count-bar { opacity: 1; }
.viz-legend { align-items: center; margin-bottom: 12px; }
.viz-legend span:last-child { color: var(--text-faint); }
.viz-key.viz-s2 { opacity: .72; }

@media (max-width: 700px) {
  .viz > h2, .viz > .viz-title-row { min-height: 0; padding: 14px; }
  .viz-title-row { align-items: flex-start; gap: 10px; }
  .viz-svg { min-width: 0; }
  .viz-kpi strong { font-size: 16px; }
  .viz-kpi span { max-width: 90px; line-height: 1.25; }
  .viz .card-body { padding: 14px; }
  .viz-plot { margin-inline: -2px; }
}

@media (prefers-color-scheme: dark) {
  .viz-plot { box-shadow: inset 0 1px 0 rgba(255,255,255,.03); }
  .viz-line { filter: drop-shadow(0 3px 4px rgba(91,146,247,.24)); }
}

/* Стрелки у числовых полей убраны. В диспетчерской в эти поля вбивают
   объёмы и цены — тысячи и десятки кубов, а не шагают по единичке. Зато
   колесо мыши над таким полем меняло цену незаметно для человека. */
input[type=number] { appearance: textfield; -moz-appearance: textfield; }
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Промежуток дат в полосе отбора: два поля читаются как одна фраза
   «работы с … по …», а не как два одиноких календарика среди списков. */
.filter-range { display: flex; align-items: center; gap: 6px; }
.filter-range label { font-size: 13px; color: var(--text-dim); white-space: nowrap; }

/* Календарик и часы — браузерные, но значок у них свой и в тёмной теме
   остаётся чёрным на чёрном. Подмешиваем его к цвету текста. */
input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .6;
}
input[type=date]:hover::-webkit-calendar-picker-indicator,
input[type=time]:hover::-webkit-calendar-picker-indicator { opacity: 1; }

@media (prefers-color-scheme: dark) {
  input[type=date]::-webkit-calendar-picker-indicator,
  input[type=time]::-webkit-calendar-picker-indicator { filter: invert(1) brightness(1.4); }
}

/* ---------- Список сделок на телефоне ---------- */

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

   Мерили: до первой заявки было 546 px при экране 844, то есть список
   начинался за краем экрана и человек видел один отбор. Отбор свёрнут в
   «Отбор» с числом поставленных условий, сегодняшняя дата убрана (она есть
   в заголовке дня), отступы шапок урезаны. */
.filters-box > summary { display: none; }

@media (max-width: 700px) {
  .filters-box > summary {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 11px 12px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    list-style: none;
  }
  .filters-box > summary::-webkit-details-marker { display: none; }
  /* Стрелка своя: у родной нет ни цвета, ни размера, которыми можно
     управлять, а свёрнутый отбор должен читаться как «тут что-то есть». */
  .filters-box > summary::after { content: '⌄'; margin-left: auto; color: var(--text-dim); }
  .filters-box[open] > summary::after { content: '⌃'; }
  .filters-box[open] > summary { border-bottom: 1px solid var(--border); }
  .month-strip { gap: 6px; padding: 10px 12px; }
  .month-strip .today-box { display: none; }
  /* «Сбросить» на телефоне прячем — то же делают сами списки отбора и
     крестики на пилюлях, а отдельная строка кнопки стоила целого ряда.
     Только на экране сделок и только эту кнопку: сначала правило было
     написано на все кнопки строки отбора, и с телефона пропали «+ Заказчик»,
     «+ Подрядчик» и «Загрузить документ» — экраны, куда другого входа нет. */
  .deals-head .filters > .btn { display: none; }
}


/* ---------- Телефон: пальцы и цифры ----------

   Только узкий экран; на ПК ничего не меняется. По мотивам разбора
   адаптива: забраны правила, которые не трогают поведение, и отброшены
   те, что его меняли (кнопки во всю ширину везде, прятанная прокрутка
   страницы, свой вид входного экрана). */
@media (max-width: 700px) {
  /* Мерили на 390 точках: у диспетчера на главной 14 кнопок и полей ниже
     40 точек, в «Моей технике» подрядчика — 18. Кнопка в 28 точек — это
     промах пальцем по соседней, а соседняя тут бывает «Убрать в корзину». */
  .btn,
  input[type=text], input[type=date], input[type=time], input[type=number],
  input[type=password], input[type=email], input[type=tel], input[type=search],
  select, textarea { min-height: 44px; }
  .btn { justify-content: center; }
  .btn-sm { min-height: 40px; }

  /* Карточка сделки в списке: номер и статус — в одной шапке. Статус
     стоял седьмой строкой, под заказчиком и объектом, и чтобы понять,
     что со сделкой, каждую карточку приходилось дочитывать до середины. */
  /* Суммы в карточках — к правому краю и цифра под цифрой: сравнивают их
     глазами сверху вниз, «От заказчика» против «Подрядчику», а слева
     разнобойные тысячи сливались в одну кашу. */
  .as-cards td.num { font-variant-numeric: tabular-nums; }
  .as-cards td.num::before { flex: 1 1 auto; }

  /* Полоса фактов позиции — ровно по две: при 168 точках на ячейку на
     экранах уже 380 она падала в один столбец, и цифры занимали полэкрана. */
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fact { padding: 10px 12px; }

  /* Строка документа: название в две строки не должно тащить кнопку
     вниз к середине — кнопка у первой строки названия. */
  .doc-row { align-items: flex-start; }
  .doc-row .btn { flex: none; }
}

/* Тёмный дашборд наследует свою палитру целиком: прежние светлые значения
   внутри .admin-home перекрывали системную тему даже у статусов и полей.
   Фотографии имеют разные композиции — узкий кадр не обрезает кран с ПК. */
@media (prefers-color-scheme: dark) {
  .admin-home {
    color-scheme: dark;
    --bg: #0b1421;
    --surface: #142235;
    --surface-2: #1a2c42;
    --border: #2b3e55;
    --border-strong: #48627f;
    --text: #eef4fc;
    --text-dim: #b7c7db;
    --text-faint: #9bafc8;
    --accent: #8bbcff;
    --accent-hover: #bad7ff;
    --accent-soft: #203a5b;
    --on-accent: #09182c;
    --danger: #ff948b;
    --danger-soft: #402527;
    --warn: #ffc184;
    --warn-soft: #3e3025;
    --warn-bd: #806043;
    --ok: #77deb0;
    --ok-soft: #173a32;
    background: var(--bg);
    color: var(--text);
  }
  .admin-home .topbar { background: #0c1828ed; border-color: var(--border); }
  .admin-home .admin-dashboard {
    --text: inherit;
    --text-dim: inherit;
    --surface: inherit;
    --surface-2: inherit;
    --border: inherit;
    --accent: inherit;
  }
  .admin-home .dash-hero {
    background-image: linear-gradient(0deg, #0b1421, #0b142100 35%),
      linear-gradient(90deg, #091321aa, #0913211a 70%), url('dashboard-night-desktop.webp');
    background-position: center, center, center 58%;
  }
  .admin-home .dash-hero::after { display: none; }
  .admin-home .dash-eyebrow { color: #b7cbe2; }
  .admin-home .dash-intro h2 { color: #f1f6ff; }
  .admin-home .dash-intro h2 > span { color: #87baff; }
  .admin-home .dash-intro > p { color: #becfe2; }
  .admin-home .dash-actions .btn { color: #d3e5ff; background: #142840db; border-color: #608cc0; }
  .admin-home .dash-actions .btn-primary { color: #fff; background: #2566d2; border-color: #4989eb; }
  .admin-home .dash-actions .btn:hover { background: #254261; }
  .admin-home .dash-actions .btn-primary:hover { background: #3075e3; }
  .admin-home .dash-live { background: #102035de; border-color: #49627d; box-shadow: 0 20px 60px #0005; }
  .admin-home .dash-kicker { color: #a1b8d2; }
  .admin-home .dash-live-heading > a { background: #223d5e; color: #b4d4ff; }
  .admin-home .dash-live-count > span { color: #b3c6dd; }
  .admin-home .dash-live-count .dash-live-icon,
  .admin-home .dash-request-icon { color: #8bbcff; }
  .admin-home .dash-request { color: #e6effc; border-color: #354c65; }
  .admin-home .dash-request:hover { background: #243d58; }
  .admin-home .dash-request-copy b > span,
  .admin-home .dash-request-copy small { color: #a8bed8; }
  .admin-home .dash-live-footer { color: #a9ceff; border-color: #354c65; }
  .admin-home .dash-empty, .admin-home .dash-empty span { color: #b3c6dd; }
  .admin-home .dash-period select { color: var(--text); background: var(--surface); border-color: var(--border-strong); }
  .admin-home .dash-metric { background: #142235; color: var(--text); border-color: #30455e; box-shadow: 0 5px 20px #0002; }
  .admin-home .dash-metric:hover { background: #1b2e46; border-color: #709dcc; }
  .admin-home .dash-metric-icon { color: #95c2ff; background: #233d5d; }
  .admin-home .dash-metric-label { color: #b7c9df; }
  .admin-home .dash-metric-arrow { color: #9ebcdd; }
  .admin-home .dash-metric-new { background: #245dc1; border-color: #4e83dc; }
  .admin-home .dash-metric-new:hover { background: #2b6bd7; }
  .admin-home .dash-metric-new .dash-metric-label,
  .admin-home .dash-metric-new .dash-metric-arrow { color: #f0f6ff; }
  .admin-home .dash-metric-new .dash-metric-icon { background: #ffffff20; color: #fff; }
  .admin-home .dash-period-note { color: #9eb3cc; }
  .admin-home .dash-workspace .card { background: var(--surface); border-color: var(--border); box-shadow: 0 5px 20px #0002; }
  .admin-home .dash-workspace .card > h2 { color: var(--text); }
  .admin-home .dash-bottom, .admin-home .dash-bottom > span { color: #9eb3cc; }
}
@media (prefers-color-scheme: dark) and (max-width: 650px) {
  .admin-home .dash-hero {
    background-image: linear-gradient(0deg, #0b1421, #0b142100 28%),
      linear-gradient(90deg, #09132155, #09132100), url('dashboard-night-mobile.webp');
    background-position: center, center, center;
  }
  .admin-home .dash-live { background: #102035df; }
}

/* ---------- Выпадающий список с поиском (combo.js) ----------

   Один на страницу, висит в body над всем: внутри карточки его обрезала бы
   рамка с overflow. */
#combo-list {
  position: absolute;
  z-index: 1000;
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 300px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  box-shadow: 0 12px 32px -8px rgba(19, 26, 46, .22);
  font-size: 14px;
}
#combo-list[hidden] { display: none; }
#combo-list li {
  padding: 8px 10px;
  border-radius: 7px;
  cursor: pointer;
}
#combo-list li[aria-selected="true"] { background: var(--accent-soft); }
#combo-list li:hover { background: var(--surface-2); }
#combo-list li[aria-selected="true"]:hover { background: var(--accent-soft); }
#combo-list li[aria-disabled] { color: var(--text-faint); cursor: default; }
#combo-list li[aria-disabled]:hover { background: none; }
#combo-list mark { background: none; color: var(--accent); font-weight: 700; }
.combo-input { width: 100%; }

/* На телефоне пункт — под палец. */
@media (max-width: 700px) {
  #combo-list { max-height: 45vh; font-size: 15px; }
  #combo-list li { padding: 12px; }
}

/* ---------- Комментарии по заявке ----------

   Общая лента трёх сторон. Своё выделено рамкой слева — в ленте, где пишут
   втроём, глазами ищут прежде всего свои слова. */
.comments { display: flex; flex-direction: column; gap: 10px; }
.comment {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
}
.comment.mine { background: var(--surface); border-color: var(--border-strong); }
.comment-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.comment-head b { font-size: 14px; }
.comment-head .pill { padding: 1px 8px; }
.comment-del { margin-left: auto; padding: 4px 8px; color: var(--text-dim); }
.comment-del:hover { color: var(--danger); border-color: var(--danger); }
/* Переносы строк человек ставит сам, и они должны остаться: «в 8 у ворот,
   в 10 на объекте» пишут столбиком. */
.comment-text { margin-top: 6px; white-space: pre-wrap; font-size: 14px; line-height: 1.45; }

.comment-new { margin-top: 14px; }
.comment-new textarea { width: 100%; resize: vertical; min-height: 64px; }
.comment-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
  margin-top: 8px;
}
.comment-foot .btn { margin-left: auto; }

@media (max-width: 700px) {
  .comment-foot .btn { margin-left: 0; width: 100%; }
}

/* Прибыль месяца рядом с «Итого» — тем же зелёным, что прибыль в карточках:
   глаз сразу связывает итог с колонкой, из которой он сложен. */
.month-profit b { color: var(--ok); }

/* Подрядчик в копии сделки — отдельной полосой под позицией: это сторона
   подрядчика, её цену заказчик никогда не видит, и глазу стоит отделить
   её от цены заказчика строкой выше. */
.copy-contractor {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
}

/* ---------- Поля на телефоне — не мельче 16 точек ----------

   Safari на iPhone увеличивает страницу, когда фокус попадает в поле со
   шрифтом мельче 16 точек, и сам обратно не уменьшает. Поля у нас 13 точек,
   и страница «рандомно зумилась»: стоило ткнуть в поиск или вернуться на
   вкладку, где фокус стоял в поле. 16 — порог, при котором Safari не
   трогает масштаб.

   !important здесь нарочно: мелкие поля заданы и классами (.tg-input,
   .mail-input, отбор дашборда), и правило обязано перебить их все — одно
   забытое поле возвращает зум. Условие — сенсорный экран или узкое окно:
   iPad тоже Safari, хоть и шире 700 точек. */
@media (max-width: 700px), (pointer: coarse) {
  input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]),
  select,
  textarea {
    font-size: 16px !important;
  }
}
/* Короткая строка Google-реестра: действия доступны и при закрытых настройках. */
.google-finance-header { display:flex; align-items:center; gap:12px; padding:14px 16px; }
.card .google-finance-header h2 { flex:1; min-width:0; margin:0; padding:0; border:0; font-size:16px; }
.google-finance-header h2 a { display:inline; color:var(--accent, #0664ee); text-decoration:none; }
.google-finance-header h2 a:hover { text-decoration:underline; }
.google-finance-header h2 a svg { width:15px; height:15px; vertical-align:-2px; margin-left:3px; }
.google-finance-tools { display:flex; align-items:center; flex-shrink:0; gap:4px; }
.google-icon-button { display:inline-flex; align-items:center; justify-content:center; width:40px; height:40px; padding:8px; border:1px solid var(--border); border-radius:9px; background:transparent; color:var(--text); cursor:pointer; }
.google-icon-button:hover:not(:disabled) { background:var(--bg); }
.google-icon-button:focus-visible { outline:2px solid var(--accent, #0664ee); outline-offset:2px; }
.google-icon-button:disabled { color:#939aa5; background:rgba(128,128,128,.08); opacity:.5; cursor:not-allowed; }
.google-auto.is-on { color:#159447; background:rgba(21,148,71,.09); }
.google-auto.is-off { color:#dc3545; background:rgba(220,53,69,.08); }
.google-auto.is-on svg { animation:google-auto-spin 2.4s linear infinite; }
.google-expand svg { transition:transform .18s ease; }
.google-expand[aria-expanded="true"] svg { transform:rotate(180deg); }
#google-finance-details { border-top:1px solid var(--border); }
#google-finance-details[hidden] { display:none; }
@keyframes google-auto-spin { to { transform:rotate(360deg); } }
@media (max-width:480px) {
  .google-finance-header { gap:6px; padding:10px 12px; }
  .card .google-finance-header h2 { font-size:14px; }
  .google-finance-tools { gap:3px; }
}
@media (prefers-reduced-motion:reduce) {
  .google-auto.is-on svg { animation:none; }
  .google-expand svg { transition:none; }
}
