/* crm.ihelp.az — рабочие места. Режим Operate: интерфейс обслуживает задачу.
   Структура «следующее действие»: экран показывает не данные, а то, что нужно сделать сейчас,
   и кнопка стоит в самой строке задачи. Искать по экрану нечего. */

:root {
  /* Хром — фирменные чернила сайта; полотно работы — светлое, под восемь часов смены. */
  --chrome: #0b241d;
  --chrome-2: #103029;
  --canvas: #f5f4ef;
  --surface: #ffffff;
  --surface-2: #faf9f5;

  --ink: #14181b;
  --ink-2: #4d5754;
  --ink-3: #6b7570;
  --line: #dfded6;
  --line-strong: #c7c6bc;

  /* ─────────── четыре цвета, и у каждого одно значение ───────────
     Смена длится восемь часов, людей за экраном учить некому, поэтому цвет
     обязан отвечать на один вопрос — «мне тут что-то делать?» — раньше, чем
     человек прочитает надпись. Значения не пересекаются и не меняются от экрана
     к экрану: увидел цвет один раз — знаешь его везде.

     ЗЕЛЁНЫЙ  — твой ход и сделанное. Главные кнопки, выбранное, закрытые работы.
     СИНИЙ    — система подсказывает или дело у кого-то другого. Рекомендации,
                пояснения, «у мастера», «у кассы».
     ЖЁЛТЫЙ   — ждём и не можем ускорить: деталь, ответ, срок на исходе.
     КРАСНЫЙ  — нельзя, необратимо или уже плохо: отмена, отказ, просрочка.

     Цвет никогда не единственный признак: рядом всегда слово. */
  --go: #186b46;              /* твой ход, подтверждение, готово */
  --go-ink: #ffffff;
  --go-bg: #e6f3ec;
  --go-line: #a9d4bd;
  --go-hover: #12583a;

  --info: #1d5fa4;            /* подсказка системы, ход не твой */
  --info-ink: #ffffff;
  --info-bg: #e7f0fa;
  --info-line: #b2d0ee;

  --wait: #8a5b06;            /* ждём внешнего: деталь, оплату, время */
  --wait-bg: #fbf2df;
  --wait-line: #e8d3a4;

  --stop: #b32d1d;            /* нельзя, необратимо, просрочено */
  --stop-bg: #fceae7;
  --stop-line: #f0bcb3;

  /* Старые имена остаются как псевдонимы: значение задаётся выше, в одном месте. */
  --accent: var(--go);
  --accent-ink: var(--go-ink);
  --ok: var(--go);
  --ok-bg: var(--go-bg);
  --warn: var(--wait);
  --warn-bg: var(--wait-bg);
  --danger: var(--stop);
  --danger-bg: var(--stop-bg);
  --brass: var(--wait);

  /* Скругления лесенкой: мелкие элементы мягче крупных, иначе карточка выглядит
     подушкой, а кнопка внутри неё — таблеткой. Одно значение на всё не работает. */
  --r: 13px;              /* карточки, плитки, поля */
  --r-sm: 9px;            /* кнопки и мелкие элементы */
  --r-lg: 20px;           /* крупные секции */
  --r-pill: 999px;        /* метки и счётчики */

  /* Тень со смещением и мягким размытием, а не цветной ореол вокруг элемента. */
  --shadow-1: 0 1px 2px rgba(20, 24, 27, .04), 0 6px 16px -10px rgba(20, 24, 27, .1);
  --shadow-2: 0 10px 28px -14px rgba(20, 24, 27, .3), 0 2px 6px -2px rgba(20, 24, 27, .08);
  --shadow-go: 0 2px 8px -2px rgba(24, 107, 70, .35);

  /* Шкала отступов под плотный рабочий экран: восемь часов и много строк. */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;

  --fast: 160ms cubic-bezier(.2, .6, .3, 1);
  --smooth: 220ms cubic-bezier(.2, .7, .3, 1);

  --sans: ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "Martian Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font: 400 15px/1.5 var(--sans);
  font-variant-numeric: tabular-nums;
}

/* Выделение, каретка и полоса прокрутки — тоже часть интерфейса: браузерные
   умолчания здесь единственное, что не принадлежит ни одной системе. */
::selection { background: #cfe6db; color: var(--ink); }
html { caret-color: var(--go); accent-color: var(--go); }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--canvas); }
::-webkit-scrollbar-thumb { background: var(--line-strong); border: 3px solid var(--canvas); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); }

:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; border-radius: 3px; }

h2 { font-size: 1.35rem; line-height: 1.25; margin: 0 0 .6rem; letter-spacing: -.01em; }
h3 { font-size: 1.05rem; line-height: 1.3; margin: 1.6rem 0 .6rem; letter-spacing: -.005em; }
h3:first-child { margin-top: 0; }
p { margin: 0 0 .7rem; }

/* ─────────── шапка ─────────── */
header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 10px 20px;
  background: var(--chrome);
  color: #eef1ee;
  box-shadow: var(--shadow-1);
}
header b { font-size: .95rem; font-weight: 600; letter-spacing: .01em; }
header .brand { height: 28px; width: auto; display: block; }
header span { margin-left: auto; font-size: .85rem; color: #b6c3bc; }
/* «Выйти» не главное действие ни на одном экране — на тёмной шапке оно живёт
   контуром, а не заливкой: зелёная кнопка здесь и читалась бы плохо, и звала бы зря. */
header button {
  flex: 0 0 auto;
  background: transparent;
  color: #cfdcd5;
  border-color: rgba(207, 220, 213, .35);
  min-height: 34px;
  padding: 6px 14px;
  font-size: .85rem;
}
header button:hover { background: rgba(255, 255, 255, .1); color: #fff; border-color: rgba(255, 255, 255, .5); }

/* ─────────── основа ─────────── */
main {
  max-width: 1180px;
  margin: 22px auto 80px;
  padding: 0 20px;
}
/* ─────────── дверь: единственный вход в систему ───────────
   Рабочие экраны светлые — на них смотрят восемь часов. Дверь тёмная:
   это единственный экран, где не работают, и граница «снаружи / внутри» должна читаться сразу.
   Тот же приём уже держит табло в зале, так что мир системы остаётся один. */
body.door {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--chrome);
  color: #eef1ee;
  overflow: hidden;
}

.door__mark {
  position: fixed;
  right: -6vw;
  bottom: -14vh;
  height: 128vh;
  width: auto;
  color: #eef1ee;
  opacity: .05;
  pointer-events: none;
}

.door__panel {
  position: relative;
  width: 100%;
  max-width: 380px;
  text-align: center;
  animation: door-in 620ms cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes door-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .door__panel { animation: none; }
}

.door__logo { display: block; margin: 0 auto 22px; height: 34px; width: auto; }

.door__card {
  background: var(--surface);
  color: var(--ink);
  border-radius: 10px;
  padding: 26px 24px 24px;
  text-align: left;
  box-shadow: 0 18px 44px -20px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .18);
}
.door__card h1 { font-size: 1.3rem; line-height: 1.25; margin: 0 0 6px; letter-spacing: -.015em; }
.door__lede { color: var(--ink-2); font-size: .88rem; margin: 0 0 20px; }
.door__card .field { margin-bottom: 14px; }
.door__card .field__label { font-size: .82rem; }
.door__card input { width: 100%; min-height: 46px; }
.door__card button { width: 100%; min-height: 48px; margin-top: 4px; font-size: .98rem; }

.door__err {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: var(--stop-bg);
  border: 1px solid var(--stop-line);
  border-radius: var(--r);
  color: #7f2415;
  font-size: .88rem;
}

.door__foot { margin: 18px 0 0; font-size: .82rem; color: #a9bdb0; }

/* Имя-ссылка: строка таблицы ведёт на свою страницу. Это кнопка, а не ссылка,
   потому что переход внутренний, но выглядеть должна как то, на что жмут. */
.linkish {
  background: none; border: 0; padding: 0; min-height: 0;
  font: inherit; font-weight: 500; color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--line-strong);
  text-underline-offset: 3px; cursor: pointer;
}
.linkish:hover { background: none; color: var(--info); text-decoration-color: currentColor; }

/* Остаток гарантии полосой: цифру читают, а полоса отвечает «много ещё или на исходе»
   без чтения. Используется и на клиентской странице, и за стойкой. */
.wbar { height: 4px; margin-top: 8px; max-width: 320px; border-radius: 2px;
  background: var(--line); overflow: hidden; }
.wbar i { display: block; height: 100%; background: var(--ok); border-radius: 2px; }

/* Клетка варианта в справочнике: цена и срок гарантии стоят рядом,
   потому что это одно решение — какую деталь ставим и что обещаем клиенту. */
.vcell { display: flex; gap: 4px; align-items: center; }
.vcell input { width: 74px; min-height: 34px; padding: 5px 7px; font-size: .86rem; }
.vcell input[data-wdays], .vcell input[data-nwdays] { width: 62px; color: var(--ink-2); }
.vcell--new { flex-wrap: wrap; width: 160px; }
.vcell--new .field__label { flex: 1 0 100%; }
th .hint { display: block; font-weight: 400; font-size: .72rem; }

/* ─────────── карта сотрудника ───────────
   Печатается на бумаге и носится в кармане, поэтому карточка белая и без лишнего:
   код, имя, роль. Всё остальное на бейдже только мешает сканеру. */
.qrwrap { max-width: 340px; margin: 0; }
.qrcard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 18px 18px 16px;
  text-align: center;
}
.qrcard__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.qrcard__logo { height: 20px; width: auto; }
.qrcard__role { font-size: .74rem; color: var(--ink-2); text-transform: lowercase; }
.qrcard__code svg { width: 200px; height: 200px; display: block; margin: 0 auto; }
.qrcard__name { font-size: 1.05rem; font-weight: 600; margin-top: 12px; letter-spacing: -.01em; }
.qrcard__note { font-size: .76rem; color: var(--ink-2); margin: 8px 0 0; }

/* Проверка гарантии: клиент читает ответ с телефона, поэтому строки крупнее рабочих экранов. */
.door__panel--wide { max-width: 460px; }
.door__result { margin-top: 14px; }
.door__result h2 { font-size: 1.15rem; margin: 0 0 2px; letter-spacing: -.01em; }
.door__result .hint { display: block; margin-bottom: 14px; }

.wrow { padding: 12px 0; border-top: 1px solid var(--line); }
.wrow:first-of-type { border-top: 0; padding-top: 4px; }
.wrow__what { font-weight: 500; margin-bottom: 3px; }
.wrow__state { font-size: .9rem; }
.wrow__state .hint { display: inline; margin: 0 0 0 6px; font-size: .84rem; }
.wrow__state--ok { color: var(--ok); }
.wrow__state--off { color: var(--danger); }
.wrow__state--none { color: var(--ink-2); }

@media (max-width: 420px) {
  .door__mark { display: none; }
  .door__card { padding: 22px 18px 20px; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px;
  margin-bottom: 14px;
  box-shadow: var(--shadow-1);
}
a.card { display: block; text-decoration: none; color: inherit;
  transition: border-color var(--smooth), transform var(--smooth), box-shadow var(--smooth); }
a.card:hover { border-color: var(--ink-3); transform: translateY(-1px); box-shadow: var(--shadow-2); }

.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.row:last-child { margin-bottom: 0; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }

.hint { color: var(--ink-2); font-size: .85rem; }
.err { color: var(--stop); font-size: .9rem; }

/* ─────────── три голоса системы ───────────
   Пояснение (синее) — система рассказывает, как это работает и что предлагает.
   Ожидание (жёлтое) — не от нас зависит, но знать надо.
   Запрет (красное) — так нельзя или уже случилось плохое.
   Все три — плашки одной формы: человек различает их цветом, а читает словами. */
.note {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 14px; margin: 0 0 12px;
  border: 1px solid var(--info-line);
  background: var(--info-bg);
  border-radius: var(--r);
  font-size: .86rem; line-height: 1.5; color: #17416f;
}
.note .ic { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px; color: var(--info); }
.note b { color: #12325a; }
.note--wait { border-color: var(--wait-line); background: var(--wait-bg); color: #6b4705; }
.note--wait .ic { color: var(--wait); }
.note--wait b { color: #57390a; }
.note--stop { border-color: var(--stop-line); background: var(--stop-bg); color: #8c2216; }
.note--stop .ic { color: var(--stop); }
.note--stop b { color: #6f1b12; }
.note button { margin-left: 2px; }
code { font-family: var(--mono); font-size: .78em; letter-spacing: -.03em; word-break: break-all; color: var(--ink-2); }

/* ─────────── элементы управления ─────────── */
input, select, textarea {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 9px 12px;
  min-height: 40px;
  transition: border-color var(--fast), box-shadow var(--fast);
}
input::placeholder { color: var(--ink-3); }
input:hover, select:hover, textarea:hover { border-color: var(--ink-3); }
/* Фокус — синий: это система показывает, где вы находитесь, а не действие. */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--info);
  box-shadow: 0 0 0 3px rgba(29, 95, 164, .16);
}
input:disabled, select:disabled, button:disabled { opacity: .5; cursor: not-allowed; }
input[type=file] { padding: 6px; border-style: dashed; }
select { appearance: none; padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: right 14px center, right 9px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* Кнопка отвечает цветом на вопрос «что будет, если нажать».
   Зелёная двигает дело вперёд, серая — сопутствующее, красная останавливает
   или уничтожает. Красной заливки нет ни одной: необратимое не должно быть
   самым ярким пятном на экране, иначе на него жмут не глядя. */
button {
  font: 500 inherit;
  font-size: .92rem;
  min-height: 40px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--go);
  color: var(--go-ink);
  cursor: pointer;
  box-shadow: var(--shadow-go);
  transition: background var(--smooth), border-color var(--smooth), color var(--smooth),
              transform var(--fast), box-shadow var(--smooth);
}
button.ghost, button.quiet, button.danger, button.info { box-shadow: none; }
button:hover { background: var(--go-hover); }
button:active { transform: translateY(1px); }
button.ghost { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
button.ghost:hover { background: var(--surface-2); border-color: var(--ink-3); }
button.ghost:disabled:hover { background: var(--surface); border-color: var(--line-strong); }
button.quiet { background: transparent; color: var(--ink-2); border-color: transparent; padding-inline: 8px; }
button.quiet:hover { background: var(--surface-2); color: var(--ink); }
/* Телефон клиента — ссылка «позвонить»: со стойки набирают прямо отсюда,
   поэтому она выглядит нажимаемой, но браузерным синим не светит. */
a.quiet {
  color: var(--info); text-decoration: underline; text-decoration-color: var(--info-line);
  text-underline-offset: 3px; font-weight: 500;
}
a.quiet:hover { text-decoration-color: currentColor; }
/* Останавливающее действие: видно, но не зовёт. Цвет проступает под курсором,
   когда человек уже целится, а не пока он просматривает экран. */
button.danger { background: var(--surface); color: var(--stop); border-color: var(--stop-line); }
button.danger:hover { background: var(--stop-bg); border-color: var(--stop); }
button.quiet.danger { background: transparent; border-color: transparent; }
button.quiet.danger:hover { background: var(--stop-bg); color: var(--stop); }
/* Действие-подсказка: система предлагает, решает человек. */
button.info { background: var(--surface); color: var(--info); border-color: var(--info-line); }
button.info:hover { background: var(--info-bg); border-color: var(--info); }

label.chk {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  padding: 8px 12px;
  min-height: 40px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  font-size: .9rem;
  transition: border-color var(--fast), background var(--fast);
}
label.chk:hover { border-color: var(--ink-3); }
label.chk:has(input:checked) { border-color: var(--accent); background: #fdf3f1; }
label.chk input { min-height: 0; accent-color: var(--accent); width: 17px; height: 17px; }

/* ─────────── строка задачи: сердце экрана ─────────── */
.tasks { display: grid; gap: 8px; }

.task {
  display: grid;
  grid-template-columns: 3.4rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  transition: border-color var(--fast), box-shadow var(--fast);
}
.task:hover { border-color: var(--line-strong); box-shadow: var(--shadow-2); }
.task.is-open { border-color: var(--ink-3); }

/* Состояние несёт блок с номером — он и так есть в строке.
   Декоративная полоса сбоку тут ничего не сообщает, только шумит. */
.task__no {
  align-self: stretch;
  display: grid;
  place-content: center;
  padding: 6px 4px;
  border-radius: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
}
.task__no small { display: block; font-size: .56rem; letter-spacing: .06em; color: var(--ink-3); font-weight: 400; }

.task--urgent .task__no { background: var(--stop-bg); border-color: var(--stop-line); color: var(--stop); }
.task--urgent .task__no small { color: var(--danger); opacity: .75; }
.task--wait .task__no { background: var(--wait-bg); border-color: var(--wait-line); color: var(--wait); }
.task--wait .task__no small { color: var(--warn); opacity: .75; }
.task--ready .task__no { background: var(--go-bg); border-color: var(--go-line); color: var(--go); }
.task--ready .task__no small { color: var(--ok); opacity: .75; }
/* Закрытая работа в очереди работ: видно с одного взгляда, докуда дошли. */
.task__no.done { background: var(--go-bg); border-color: var(--go-line); color: var(--go); }
.task__no.done small { color: var(--ok); opacity: .75; }

.task__main { min-width: 0; }
.task__title { font-weight: 600; font-size: .98rem; }
.task__title span { font-weight: 400; color: var(--ink-2); }
.task__meta { font-size: .82rem; color: var(--ink-2); display: flex; gap: 10px; flex-wrap: wrap; margin-top: 2px; }
.task__meta b { color: var(--ink); font-weight: 500; }

.task__act { display: flex; gap: 8px; align-items: center; }
.task__act .sum { font-family: var(--mono); font-size: 1rem; font-weight: 600; margin-right: 4px; }

/* Раскрытая карточка живёт в потоке — сотрудник не теряет очередь из виду. */
.task__panel {
  grid-column: 1 / -1;
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px dashed var(--line-strong);
}

/* ─────────── статусы ─────────── */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .01em;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: #eceae2;
  color: var(--ink-2);
  white-space: nowrap;
}
.tag::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Метка красится не по названию статуса, а по ответу на вопрос «чей сейчас ход».
   Сотрудник не обязан помнить, что «diagnosed» — это его дело, а «in_progress» —
   уже нет: он видит зелёное и знает, что это к нему. */
.tag.new,                                    /* ждёт разбора — ваш ход */
.tag.diagnosed,                              /* назначить мастера — ваш ход */
.tag.done,                                   /* передать кассиру — ваш ход */
.tag.open { background: var(--go-bg); color: var(--go); }

.tag.in_progress,                            /* у мастера */
.tag.awaiting_payment { background: var(--info-bg); color: var(--info); }   /* у кассы */

.tag.waiting_part,                           /* ждём деталь */
.tag.paused { background: var(--wait-bg); color: var(--wait); }

/* Ваш ход не по статусу заявки, а по событию: мастер поднял руку и ждёт ответа. */
.tag.mine { background: var(--go-bg); color: var(--go); }
/* Человек сидит в зале: не ждём мы, а ждут нас — поэтому жёлтый, а не синий. */
.tag.hot { background: var(--wait-bg); color: var(--wait); }
.tag.cancelled { background: var(--stop-bg); color: var(--stop); }
.tag.paid, .tag.closed { background: #eceae2; color: var(--ink-2); }        /* дело закрыто */

/* ─────────── таблицы ─────────── */
table { width: 100%; border-collapse: collapse; background: var(--surface); font-size: .9rem; }
th {
  text-align: left;
  font-weight: 500;
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 8px 10px;
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr:hover td, tr:hover td { background: var(--surface-2); }
table .row { margin: 0; gap: 6px; }
table button { min-height: 32px; padding: 5px 10px; font-size: .84rem; }

/* ─────────── экран хостес и крупные подтверждения ─────────── */
.big {
  font-size: clamp(1.6rem, 4vw, 2.4rem);
  font-weight: 600;
  line-height: 1.2;
  padding: 28px 24px;
  text-align: center;
  background: var(--ok-bg);
  color: #14432c;
  border: 1px solid #bfe0cd;
  border-radius: var(--r);
}
.big small { display: block; margin-top: 8px; font-size: 1rem; font-weight: 400; color: #2f6b4c; }

/* ─────────── пустые состояния и загрузка ─────────── */
.empty {
  padding: 32px 20px;
  text-align: center;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r);
}
.empty b { display: block; color: var(--ink); font-weight: 600; margin-bottom: 4px; }

.skeleton {
  height: 62px;
  border-radius: var(--r);
  background: linear-gradient(90deg, #eeece5 25%, #f6f5f0 37%, #eeece5 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* ─────────── подтверждение картой ─────────── */
.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(11, 36, 29, .55);
  backdrop-filter: blur(2px);
  display: grid;
  place-items: start center;
  padding: 12vh 16px;
  animation: fade 140ms ease-out;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal .card { max-width: 520px; width: 100%; margin: 0; box-shadow: var(--shadow-2); }
.modal input, .modal select, .modal textarea { width: 100%; }
/* Поле сканера — моноширинное: код карты читается посимвольно. */
.modal #qrInput { font-family: var(--mono); }

/* Форма в диалоге: все поля разом, а не вопрос за вопросом. */
.formgrid { display: grid; gap: 12px; }
.field { display: grid; gap: 5px; }
.field__label { font-size: .78rem; font-weight: 500; color: var(--ink-2); }
.field textarea { resize: vertical; font: inherit; }
@media (min-width: 560px) {
  .formgrid { grid-template-columns: 1fr 1fr; }
  .formgrid .field:only-child, .field--wide { grid-column: 1 / -1; }
}

/* ─────────── уведомление ─────────── */
#toast {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translate(-50%, 160%);
  z-index: 70;
  max-width: min(560px, calc(100vw - 32px));
  padding: 11px 16px;
  border-radius: var(--r);
  background: var(--chrome);
  color: #eef1ee;
  font-size: .9rem;
  box-shadow: var(--shadow-2);
  opacity: 0;
  visibility: hidden;
  transition: transform 260ms cubic-bezier(.2, .6, .3, 1), opacity 200ms, visibility 260ms;
}
#toast.is-on { transform: translate(-50%, 0); opacity: 1; visibility: visible; }
#toast.err { background: var(--danger); }

/* ─────────── вкладки ─────────── */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line-strong); margin-bottom: 18px; }
.tabs button {
  background: transparent;
  color: var(--ink-2);
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 10px 14px;
  min-height: 42px;
}
.tabs button:hover { color: var(--ink); background: transparent; }
.tabs button[aria-current="true"] { color: var(--ink); border-bottom-color: var(--go); font-weight: 600; }
.tabs .count {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 20px;
  background: var(--line);
  color: var(--ink-2);
  font-size: .74rem;
  font-weight: 500;
}
.tabs button[aria-current="true"] .count { background: var(--go); color: #fff; }

/* ─────────── полоса состояния смены ─────────── */
.shiftbar {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px 14px;
  margin-bottom: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.shiftbar .spacer { margin-left: auto; }

/* ─────────── показатели ─────────── */
.stats { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.stat {
  flex: 1 1 130px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.stat b { display: block; font-size: 1.5rem; line-height: 1.1; font-family: var(--mono); letter-spacing: -.04em; }
.stat span { font-size: .78rem; color: var(--ink-2); }
.stat.alert { border-color: var(--stop-line); background: var(--stop-bg); }
.stat.alert b { color: var(--stop); }
.stat.go { border-color: var(--go-line); background: var(--go-bg); }
.stat.go b { color: var(--go); }
.stat.wait { border-color: var(--wait-line); background: var(--wait-bg); }
.stat.wait b { color: var(--wait); }

/* ─────────── шаги приёма ─────────── */
.steps { counter-reset: s; display: grid; gap: 10px; }
.step { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 12px; align-items: start; }
.step::before {
  counter-increment: s;
  content: counter(s);
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--chrome);
  color: #fff;
  font-size: .78rem;
  font-weight: 600;
}
.step.is-done::before { background: var(--ok); }
.step.is-todo::before { background: var(--line-strong); color: var(--ink-2); }
.step__title { font-weight: 500; margin-bottom: 6px; }

/* ─────────── адаптация ─────────── */
@media (max-width: 760px) {
  main { padding: 0 12px; margin-top: 14px; }
  header { padding: 8px 12px; gap: 10px; }
  header span { width: 100%; order: 5; margin-left: 0; }
  .task { grid-template-columns: 2.6rem minmax(0, 1fr); row-gap: 10px; }
  .task__act { grid-column: 1 / -1; justify-content: flex-end; }
  .tabs { overflow-x: auto; }
  table { font-size: .84rem; }
  th, td { padding: 7px 8px; }
  /* Счётчики в две колонки: шесть штук в ряд на телефоне превращаются в ленту
     из обрезков, по которой ничего не прочитать. */
  .stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .stat { min-width: 0; }
  /* Путь заявки прокручивается, а не рвётся на строки: это одна дорога. */
  .flow { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
  .flow::-webkit-scrollbar { display: none; }
  .note { padding: 10px 12px; font-size: .84rem; }
  /* В зале жмут пальцем, а иногда в перчатке: цель не меньше сорока точек. */
  header button { min-height: 40px; padding: 8px 14px; }
  /* Кнопка стадии — главное действие экрана, на телефоне она во всю ширину. */
  .adm__sum button, #take { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ─────────── разбор заявки у администратора ───────────
   Работа слева, смета справа и всегда на виду: её администратор произносит клиенту вслух,
   поэтому она не должна уезжать при прокрутке. */
.adm { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 20px; align-items: start; }
/* Отступ от реальной высоты шапки, а не от числа: на узком экране шапка переносит
   строку и становится выше, и смета уезжала под неё. */
.adm__sum { position: sticky; top: calc(var(--head-h, 66px) + 10px); }
.adm__sum .card { margin: 0; }
@media (max-width: 900px) {
  .adm { grid-template-columns: 1fr; }
  .adm__sum { position: static; }
}

.admsay { margin: 10px 0 0; font-size: .92rem; }
.admsay .quiet { margin-left: 6px; }

/* Плитки поломок: администратор думает узлами аппарата, а не строками справочника. */
.tiles { display: grid; gap: 14px; }
.tiles__group { display: grid; gap: 6px; }
.tiles__head {
  font-size: .74rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3);
}
.tiles__group { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.tiles__head { grid-column: 1 / -1; }

.tile {
  display: grid; gap: 2px; justify-items: start; text-align: left;
  padding: 10px 12px; min-height: 56px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  font: inherit; cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
}
.tile:hover { background: var(--surface-2); border-color: var(--ink-3); }
.tile__name { font-weight: 500; font-size: .92rem; }
.tile__price { font-size: .8rem; color: var(--ink-2); }
.tile.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.tile.is-on:hover { background: #b03a22; }
.tile.is-on .tile__price { color: #fbded7; }
/* Названо клиентом, но ещё не подтверждено диагностом — версия, а не выбор. */
.tile--said { border-style: dashed; border-color: var(--info-line); background: var(--info-bg); }
.tile--said::after { content: 'со слов клиента'; font-size: .68rem; color: var(--info); }
.tile--said:hover { background: var(--info-bg); border-color: var(--info); }

/* Кандидаты в мастера: подсказка обязана объяснять себя, иначе её обходят. */
.cands { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cand {
  display: grid; gap: 1px; justify-items: start; text-align: left;
  padding: 8px 12px; min-width: 170px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  font: inherit; cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
}
.cand:hover { background: var(--surface-2); border-color: var(--ink-3); }
.cand__flag {
  font-size: .66rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--info);
}
.cand--best { border-color: var(--info-line); background: var(--info-bg); }
.cand--best:hover { border-color: var(--info); background: var(--info-bg); }
.cand__name { font-weight: 500; font-size: .92rem; }
.cand__why { font-size: .78rem; color: var(--ink-2); }
.cand.is-on { background: var(--chrome); border-color: var(--chrome); color: #eef1ee; }
.cand.is-on .cand__why { color: #a9bdb0; }
.cand.is-on .cand__flag { color: #8ec1f0; }
/* «Не берёт эту работу» и «предел загрузки» — предупреждение, а не запрет: красный
   пунктир, но кнопка живая. Спрятать нельзя — администратор будет искать человека
   и не поймёт, куда тот делся. */
.cand--off { border-style: dashed; border-color: var(--stop-line); background: var(--surface); }
.cand--off .cand__name { color: var(--ink-2); }
.cand--off .cand__why { color: var(--stop); }
.cand--off:hover { background: var(--stop-bg); border-color: var(--stop); }

/* ─────────── путь заявки ───────────
   Администратор должен видеть не статус в базе, а место заявки в дороге:
   где она сейчас и чей следующий ход. */
.flow { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0 0 8px; padding: 0; }
.flow__i {
  padding: 5px 12px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-3);
  border: 1px solid var(--line); font-size: .8rem; white-space: nowrap;
}
/* Пройденное — зелёное и приглушённое, текущее — зелёное и полное.
   Будущее остаётся серым: цветом отмечено только то, что уже случилось. */
.flow__i.is-past { background: var(--go-bg); border-color: var(--go-line); color: var(--go); }
.flow__i.is-now {
  background: var(--go); border-color: var(--go); color: var(--go-ink); font-weight: 600;
  box-shadow: 0 1px 2px rgba(24, 107, 70, .3);
}
.flow__next { margin: 0 0 14px; font-size: .92rem; color: var(--ink-2); }
.flow__next b { color: var(--ink); }

/* Предупреждение, которое администратор обязан увидеть до разговора о цене:
   гарантия ещё жива, у клиента здесь второй аппарат. */
/* Предупреждение над заявкой: жёлтое, потому что это не запрет, а «прочти,
   прежде чем говорить с клиентом о цене» — живая гарантия, второй аппарат. */
.card--warn { border-color: var(--wait-line); background: var(--wait-bg); }
.card--warn .estim li { border-bottom-color: var(--wait-line); }
.card--warn > b { color: #57390a; }

/* Снимки приёмки: доказательство, а не украшение — поэтому мелко и в ряд. */
.shots { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.shots img {
  width: 96px; height: 96px; object-fit: cover;
  border-radius: var(--r); border: 1px solid var(--line-strong);
}

/* От чего клиент отказался: остаётся видно, но в сумму не идёт. */
.task--off { opacity: .6; }
.estim li.is-off { opacity: .6; text-decoration: line-through; }
.estim li.is-off .hint { text-decoration: none; }

/* Смета */
.estim { list-style: none; margin: 0 0 10px; padding: 0; }
.estim li { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0;
  border-bottom: 1px solid var(--line); font-size: .9rem; }
.estim__total { display: flex; justify-content: space-between; align-items: baseline;
  margin: 0 0 12px; font-size: 1.05rem; }
.estim__total b { font-size: 1.3rem; letter-spacing: -.02em; }
.adm__sum button { width: 100%; margin-top: 6px; }

.quiet.is-on { background: var(--chrome); color: #eef1ee; }

/* ─────────── выбор устройства плитками ───────────
   За стойкой не читают выпадающий список из двухсот строк: узнают модель в лицо
   и попадают пальцем. Цель нажатия крупная — работают в перчатках и в спешке. */
.pickpath { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin-bottom: 8px; }
.pickpath__sep { color: var(--ink-3); font-size: .8rem; }
.pickpath .quiet { font-size: .84rem; padding: 4px 8px; min-height: 30px; }

.pickgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; }
.pick {
  min-height: 54px; padding: 10px 12px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  font: 500 .95rem/1.25 var(--sans); text-align: left; cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
}
.pick:hover { background: var(--surface-2); border-color: var(--ink-3); }
/* Конечная модель — на неё уже можно оформлять, поэтому она читается иначе, чем раздел. */
.pick--leaf { border-color: var(--ink-3); }
.pick--leaf::after { content: '→'; float: right; color: var(--ink-3); }

/* ─────────── силуэты ───────────
   Свои SVG в одном весе линии. Хостес тратит на приём десять секунд:
   за это время читается силуэт, а не подпись. Подпись — подтверждение, а не опознание. */
.ic { flex: 0 0 auto; display: block; }
.ic--brand { width: 30px; height: 30px; color: var(--ink-2); }

/* Плитка симптома: крупная цель, силуэт сверху, слово под ним. */
.symp {
  display: grid; justify-items: center; gap: 7px;
  min-height: 92px; padding: 14px 10px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r);
  font: 500 .9rem/1.2 var(--sans); text-align: center; cursor: pointer;
  transition: border-color var(--fast), background var(--fast), color var(--fast);
}
.symp .ic { width: 30px; height: 30px; color: var(--ink-2); }
.symp:hover { background: var(--surface-2); border-color: var(--ink-3); }
.symp:hover .ic { color: var(--ink); }
.symp.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.symp.is-on .ic { color: var(--accent-ink); }

/* Подтверждение приёма. Самое необратимое действие экрана: отдельная крупная кнопка,
   а не касание симптома — промах пальцем не должен стоить вызова владельца. */
#take { min-width: 260px; padding: 14px 22px; font-size: 1.05rem; }
#sumUp.ready, #willBe { font-size: 1rem; color: var(--ink); margin-bottom: .5rem; }

/* Плитка устройства: на первом уровне силуэт слева от имени бренда. */
.pick { display: flex; align-items: center; gap: 10px; }
.pick > span { min-width: 0; }
.pick:hover .ic--brand { color: var(--ink); }

/* ═══════════════════ деньги и себестоимость ═══════════════════ */

/* Первый экран владельца отвечает на первый вопрос владельца.
   Не таблица, не график — одна цифра, крупно, и под ней честная арифметика,
   из которой она получилась. Спорить с такой цифрой можно построчно. */
.daymoney {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--s5);
  align-items: center;
  padding: var(--s5);
  margin-bottom: var(--s4);
  border-radius: var(--r-lg);
  background: linear-gradient(158deg, var(--chrome) 0%, #0e2f26 62%, #123a2c 100%);
  color: #eef1ee;
  box-shadow: var(--shadow-2);
}
.daymoney__label {
  display: block; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: #8fae9d;
}
.daymoney__sum {
  display: block; margin: 2px 0 4px;
  font-family: var(--mono); font-size: clamp(2rem, 5vw, 2.9rem); font-weight: 600;
  letter-spacing: -.04em; line-height: 1;
}
.daymoney__sub { font-size: .85rem; color: #a9bdb0; }

/* Арифметика дня: принято → минус детали → минус траты → осталось.
   Каждая строка на своём месте, итог отделён линией, а не цветом. */
.daymoney__flow { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.daymoney__flow li {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3);
  padding: 7px 0; font-size: .88rem; color: #cfdcd5;
}
.daymoney__flow b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.daymoney__flow .is-minus { color: #a9bdb0; }
.daymoney__flow .is-sub {
  margin: var(--s1) 0; padding: 7px 0;
  border-top: 1px solid rgba(207, 220, 213, .14);
  border-bottom: 1px solid rgba(207, 220, 213, .14);
  color: #eef1ee; font-weight: 500;
}
.daymoney__flow .is-total {
  margin-top: var(--s1); padding-top: var(--s3);
  border-top: 1px solid rgba(207, 220, 213, .22);
  color: #fff; font-weight: 600; font-size: 1rem;
}
/* Минус виден цветом, но и знаком: на тёмном фоне один цвет читается хуже. */
.daymoney__sum.is-neg, .daymoney__flow .is-total.is-neg b { color: #f0a99e; }
@media (max-width: 760px) {
  .daymoney { grid-template-columns: 1fr; gap: var(--s4); padding: var(--s4); }
}

/* Себестоимость в смете администратора: цену он называет клиенту вслух, а прибыль
   читает глазами — поэтому мельче итога и приглушённее, но на том же месте. */
.estim__margin {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s2);
  margin: 0 0 2px; font-size: .84rem; color: var(--ink-2);
}
.estim__margin--net {
  margin-top: var(--s1); padding-top: var(--s2);
  border-top: 1px solid var(--line); color: var(--ink); font-size: .92rem;
}
.estim__margin--net b { font-family: var(--mono); color: var(--go); font-size: 1.05rem; }

/* Прибыль по заявке в отчёте: минус читается сразу, а не вычисляется взглядом. */
b.pos { color: var(--go); }
b.neg { color: var(--stop); }

/* Закупочная цена в справочнике отличается от цены клиенту: её видит только владелец. */
.vcell input.cost { background: var(--surface-2); color: var(--ink-2); }
.vcell input.cost:focus { background: var(--surface); color: var(--ink); }

/* Код разблокировки: его диктуют вслух и набирают на чужом аппарате,
   поэтому моноширинный и с разрядкой — «0» и «O» не должны спорить. */
.pass {
  font-family: var(--mono); font-size: .95em; letter-spacing: .06em;
  padding: 1px 6px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--line);
}
.miss { color: var(--stop); }

/* ═══════════════════ журнал действий ═══════════════════ */

/* Лента длинная, читают её по диагонали в поисках одного человека или одного дня.
   Поэтому действие подсвечено видом, а не строка целиком: цветные полосы во всю
   ширину превращают таблицу в ковёр, по которому взгляду не за что зацепиться. */
.jrn td { vertical-align: top; }
.jrn__act {
  display: inline-block; padding: 1px 8px; border-radius: var(--r-pill);
  font-size: .8rem; font-weight: 500; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-2);
}
.jrn__act--money { background: var(--go-bg); color: var(--go); }        /* деньги */
.jrn__act--order { background: var(--info-bg); color: var(--info); }    /* заявки */
.jrn__act--shift { background: var(--wait-bg); color: var(--wait); }    /* приход-уход */
.jrn__act--catalog, .jrn__act--staff { background: #eceae2; color: var(--ink-2); }

/* Плитка сотрудника в сводке кликается: это фильтр, а не украшение. */
.stat[data-jwho] { transition: border-color var(--fast), background var(--fast); }
.stat[data-jwho]:hover { border-color: var(--info); background: var(--info-bg); }

/* ═══════════════════ касса ═══════════════════

   У кассира одна работа и очередь живых людей перед ним. Всё, что он делает, — это
   назвать сумму, взять деньги и отдать аппарат, и на экране должно быть ровно это.
   Раньше здесь стояли два длинных списка подряд, способ оплаты выбирался мелким
   выпадающим списком внутри строки, а сумма была подписью — то есть экран администратора,
   которому просто не досталось своего.

   Правила: одна задача на экране, сумма крупнее всего остального, способ оплаты —
   кнопка под палец, сдача считается сама. */

.pos { display: grid; gap: var(--s4); }

/* Шапка: остаток наличных и поиск. Остаток виден весь день, а не в момент сдачи —
   расхождение ищут по свежим следам. */
.pos__bar {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4); border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-1);
}
.pos__cash { display: flex; align-items: baseline; gap: 8px; }
.pos__cash b { font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.15rem; letter-spacing: -.03em; }
.pos__cash span { font-size: .78rem; color: var(--ink-2); }
.pos__bar input { flex: 1; min-width: 180px; max-width: 320px; }

/* Строка очереди. Кликается целиком и крупно: кассир попадает в неё, не глядя. */
.pos__row {
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  width: 100%; min-height: 74px; padding: 14px var(--s4); text-align: left;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: none;
  font: 400 1rem/1.3 var(--sans);
  transition: border-color var(--fast), box-shadow var(--fast);
}
.pos__row:hover { background: var(--surface); border-color: var(--go); box-shadow: var(--shadow-1); }
.pos__no {
  flex: 0 0 auto; min-width: 52px; padding: 6px 10px; border-radius: var(--r-sm);
  background: var(--go-bg); border: 1px solid var(--go-line); color: var(--go);
  font: 600 1.25rem/1.1 var(--mono); text-align: center; letter-spacing: -.03em;
}
.pos__no small { display: block; font: 400 .56rem/1.4 var(--sans); letter-spacing: .06em;
  color: var(--ink-3); }
.pos__who { min-width: 0; flex: 1 1 200px; }
.pos__who b { display: block; font-weight: 600; }
.pos__who span { font-size: .85rem; color: var(--ink-2); }
.pos__due { margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.4rem; font-weight: 600; letter-spacing: -.03em; white-space: nowrap; }
.pos__row--issue .pos__no { background: var(--info-bg); border-color: var(--info-line); color: var(--info); }

/* Экран одной оплаты. Сумма — единственное крупное число, всё остальное её объясняет. */
.pay { max-width: 560px; margin: 0 auto; }
.pay__head { text-align: center; padding: var(--s5) var(--s4) var(--s4); }
.pay__who { font-size: 1.05rem; font-weight: 600; }
.pay__dev { font-size: .9rem; color: var(--ink-2); margin-top: 2px; }
.pay__sum {
  display: block; margin: var(--s4) 0 2px; font-family: var(--mono);
  font-size: clamp(2.6rem, 11vw, 3.6rem); font-weight: 600; letter-spacing: -.05em; line-height: 1;
}
.pay__sub { font-size: .85rem; color: var(--ink-2); }

.pay__lines { list-style: none; margin: 0; padding: 0; }
.pay__lines li {
  display: flex; justify-content: space-between; gap: var(--s3);
  padding: 10px var(--s4); border-bottom: 1px solid var(--line); font-size: .95rem;
}
.pay__lines li:last-child { border-bottom: 0; }
.pay__lines b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.pay__lines .is-off { color: var(--ink-2); }

/* Способ оплаты — кнопки под палец, а не выпадающий список в 24 пикселя.
   Кассир нажимает их сотню раз за смену, глядя на клиента, а не на экран. */
.pay__ways { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.pay__way {
  min-height: 62px; padding: 12px; border-radius: var(--r);
  background: var(--surface); color: var(--ink); border: 1px solid var(--line-strong);
  box-shadow: none; font: 500 .98rem/1.2 var(--sans);
  display: grid; gap: 3px; justify-items: center; align-content: center;
}
.pay__way small { font-size: .72rem; color: var(--ink-3); font-weight: 400; }
.pay__way:hover { background: var(--surface-2); border-color: var(--ink-3); }
.pay__way[aria-pressed="true"] {
  background: var(--go-bg); border-color: var(--go); color: var(--go); font-weight: 600;
}
.pay__way[aria-pressed="true"] small { color: var(--go); opacity: .8; }

/* Сдача. Единственная арифметика, которую кассир делает в уме сто раз за смену. */
.change {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: 14px var(--s4); border-radius: var(--r);
  background: var(--wait-bg); border: 1px solid var(--wait-line); color: #6b4705;
}
.change b { font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.8rem; font-weight: 600; letter-spacing: -.04em; color: #57390a; }
.change--short { background: var(--stop-bg); border-color: var(--stop-line); color: #8c2216; }
.change--short b { color: var(--stop); }
.change--exact { background: var(--go-bg); border-color: var(--go-line); color: #14503a; }
.change--exact b { color: var(--go); font-size: 1.15rem; }

/* Главное действие экрана: во всю ширину, с суммой прямо на кнопке. */
.pay__go { width: 100%; min-height: 60px; font-size: 1.1rem; font-weight: 600; }
.pay__go .num { font-size: 1.2rem; }

/* Возврат живёт внутри строки выдачи. Отдельная цель под палец, а не подпись:
   промахнуться отсюда в «отдал телефон» стоит дороже, чем лишние восемь пикселей. */
.pos__back {
  display: inline-flex; align-items: center; min-height: 44px; padding: 8px 14px;
  border-radius: var(--r-sm); border: 1px solid transparent;
  color: var(--stop); font-size: .88rem; cursor: pointer;
  transition: background var(--fast), border-color var(--fast);
}
.pos__back:hover { background: var(--stop-bg); border-color: var(--stop-line); }
.pos__back:focus-visible { outline: 2px solid var(--stop); outline-offset: 1px; }

/* Пальцем попадают хуже, чем курсором: сегменты подрастают до сорока четырёх точек
   там, где вероятен палец, — на узком экране и на грубом указателе. Это не про
   красоту, это про промахи в чужие деньги. Проверяем оба условия: кассовый терминал
   с тачскрином на широком мониторе прикидывается мышью, а телефон в альбомной
   ориентации — широким экраном. */
@media (pointer: coarse), (max-width: 900px) {
  .bseg button { min-height: 44px; padding-inline: 16px; }
}
/* Касса — рабочее место с очередью людей: здесь палец всегда, на любой ширине. */
.pos .bseg button { min-height: 44px; padding-inline: 16px; }

/* ═══════════════════ кабинет владельца ═══════════════════

   Владелец заходит на минуту и с вопросом, а не на смену и с задачей. Поэтому здесь
   другая плотность, чем у мастера: воздуха больше, крупных чисел ровно по одному на
   экран, а всё, что можно свернуть, свёрнуто до клика. Токены и четыре цвета — общие
   с остальными рабочими местами: цвет не должен менять значение при переходе между
   экранами одной системы. */

.bwrap { display: grid; grid-template-columns: 208px minmax(0, 1fr); gap: var(--s5); align-items: start; }

/* Разделов шесть, и они разной важности: «Сегодня» открывают каждый день, «Справочник» —
   раз в месяц. В ряд вкладок это не помещается: на 1366px подписи переносились на вторую
   строку и прыгали при переключении. Колонка держит порядок при любой ширине. */
.bnav {
  position: sticky; top: calc(var(--head-h, 66px) + var(--s3));
  display: grid; gap: 2px; align-content: start;
}
.bnav button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 9px 12px;
  background: transparent; color: var(--ink-2); border: 1px solid transparent;
  border-radius: var(--r); box-shadow: none;
  font: 500 .93rem/1.2 var(--sans); text-align: left;
  transition: background var(--fast), color var(--fast);
}
.bnav button .ic { width: 18px; height: 18px; color: var(--ink-3); }
.bnav button:hover { background: var(--surface); color: var(--ink); }
.bnav button:hover .ic { color: var(--ink-2); }
.bnav button[aria-current="true"] {
  background: var(--surface); color: var(--ink); font-weight: 600;
  border-color: var(--line); box-shadow: var(--shadow-1);
}
.bnav button[aria-current="true"] .ic { color: var(--go); }
/* Счётчик на пункте — только когда там ждут человека. Ноль не рисуем: «0 решений»
   занимает столько же места, сколько «3 решения», и читать его приходится каждый раз. */
.bnav .count {
  margin-left: auto; min-width: 20px; padding: 1px 6px; border-radius: var(--r-pill);
  background: var(--stop); color: #fff; font: 600 .72rem/1.5 var(--mono); text-align: center;
}

@media (max-width: 900px) {
  .bwrap { grid-template-columns: 1fr; gap: var(--s4); }
  /* На телефоне колонка становится лентой: шесть подписей в строку не влезут,
     а прятать половину под «Ещё» — прятать половину системы. */
  .bnav {
    position: sticky; top: var(--head-h, 66px); z-index: 5;
    grid-auto-flow: column; grid-auto-columns: max-content;
    gap: 4px; overflow-x: auto; scrollbar-width: none;
    margin: 0 calc(var(--s4) * -1); padding: var(--s2) var(--s4);
    background: var(--canvas); box-shadow: 0 1px 0 var(--line);
  }
  .bnav::-webkit-scrollbar { display: none; }
  /* Не ниже 44px: на телефоне в это попадают пальцем, а не курсором. */
  .bnav button { min-height: 44px; white-space: nowrap; }
}

/* Секция — карточка с заголовком. Раньше это был h3 и таблица встык под ним:
   на экране из семи таблиц подряд глазу не за что зацепиться, где кончается одно
   и начинается следующее. */
.bsec { margin-bottom: var(--s4); }
.bsec__head {
  display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  margin: 0 0 var(--s3);
}
.bsec__head h3 { margin: 0; font-size: 1rem; }
.bsec__head p { margin: 0; }
.bsec__head .spacer { margin-left: auto; }
.bsec__body {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); overflow: hidden;
}
.bsec__body > p, .bsec__body > .bpad { padding: var(--s4); margin: 0; }
.bsec__body > table th:first-child, .bsec__body > table td:first-child { padding-left: var(--s4); }
.bsec__body > table th:last-child, .bsec__body > table td:last-child { padding-right: var(--s4); }
.bsec__body > table tr:last-child td { border-bottom: 0; }
.bsec__body .empty { border: 0; margin: 0; background: transparent; }

/* Разворачивается по клику: подробности существуют, но не занимают экран, пока их
   не спросили. Владелец сначала смотрит итог и лезет внутрь, только если он странный. */
.bmore > summary {
  list-style: none; cursor: pointer; padding: var(--s3) var(--s4);
  font-size: .88rem; color: var(--ink-2); border-top: 1px solid var(--line);
  transition: background var(--fast), color var(--fast);
}
.bmore > summary::-webkit-details-marker { display: none; }
.bmore > summary::before { content: '\25B8  '; color: var(--ink-3); }
.bmore[open] > summary::before { content: '\25BE  '; }
.bmore > summary:hover { background: var(--surface-2); color: var(--ink); }
.bmore > summary:focus-visible { outline: 2px solid var(--go); outline-offset: -2px; }

/* Числа моноширинные и по правому краю. Иначе колонка сумм пляшет по ширине,
   и «1 200» с «980» нельзя сравнить взглядом — только вычитанием. */
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
td.num, th.num { text-align: right; white-space: nowrap; }
td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Полоса «требует вас». Пустого состояния у неё нет: вместо «0 решений»
   её просто нет на экране. */
.balert { display: grid; gap: 8px; margin-bottom: var(--s4); }
.balert__i {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: 12px var(--s4); border-radius: var(--r);
  border: 1px solid var(--wait-line); background: var(--wait-bg); color: #6b4705;
  font-size: .92rem;
}
.balert__i b { color: #57390a; }
.balert__i .spacer { margin-left: auto; }
.balert__i .ic { width: 18px; height: 18px; color: var(--wait); }
.balert__i--stop { border-color: var(--stop-line); background: var(--stop-bg); color: #8c2216; }
.balert__i--stop b { color: #6f1b12; }
.balert__i--stop .ic { color: var(--stop); }
.balert__i--go { border-color: var(--go-line); background: var(--go-bg); color: #14503a; }
.balert__i--go b { color: #0f3d2c; }
.balert__i--go .ic { color: var(--go); }

/* Воронка дня. Шесть одинаковых плиток со счётчиками не показывали главного —
   где встало. Здесь этапы стоят по порядку движения заявки, и затор виден местом. */
.bfunnel { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: var(--s4); }
.bfunnel__i {
  flex: 1 1 108px; padding: 12px 14px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
}
.bfunnel__i b { display: block; font: 600 1.5rem/1.1 var(--mono); letter-spacing: -.04em; }
.bfunnel__i span { font-size: .78rem; color: var(--ink-2); }
.bfunnel__i.is-hot { border-color: var(--wait-line); background: var(--wait-bg); }
.bfunnel__i.is-hot b { color: var(--wait); }

/* Отчёт о прибыли читается фразой сверху вниз, а не набором плиток.
   Строка расхода разворачивается в то, из чего сложилась. */
.bpl { list-style: none; margin: 0; padding: 0; }
.bpl li {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: 9px var(--s4); border-bottom: 1px solid var(--line);
}
.bpl li:last-child { border-bottom: 0; }
.bpl b { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.bpl .is-sub { padding-left: calc(var(--s4) + 18px); font-size: .88rem; color: var(--ink-2); }
.bpl .is-sub b { font-weight: 400; }
.bpl .is-head { font-weight: 600; }
.bpl .is-out b { color: var(--stop); }
.bpl .is-total {
  padding-top: var(--s3); padding-bottom: var(--s3);
  border-top: 2px solid var(--line-strong); font-weight: 600; font-size: 1.05rem;
}
.bpl .is-total b { font-size: 1.3rem; color: var(--go); }
.bpl .is-total.is-neg b { color: var(--stop); }

/* Переключатель периода: один на весь раздел «Деньги». Раньше период жил только
   в «Финансах» и сбрасывался при уходе на соседнюю вкладку. */
.bseg { display: flex; gap: 2px; padding: 3px; border-radius: var(--r-pill);
  background: var(--surface-2); border: 1px solid var(--line); }
.bseg button {
  background: transparent; color: var(--ink-2); border: 0; box-shadow: none;
  min-height: 34px; padding: 5px 13px; border-radius: var(--r-pill);
  font: 500 .85rem/1.2 var(--sans);
}
.bseg button:hover { background: var(--surface); color: var(--ink); }
.bseg button[aria-current="true"] {
  background: var(--surface); color: var(--ink); font-weight: 600; box-shadow: var(--shadow-1);
}

/* Строка человека кликается целиком: имя, деньги и состояние — один объект,
   и попадать надо в него, а не в шестипиксельную ссылку внутри. */
.bpeople { display: grid; gap: 6px; }
.bperson {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  width: 100%; min-height: 60px; padding: 11px var(--s4); text-align: left;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: none;
  font: 400 .95rem/1.3 var(--sans);
  transition: border-color var(--fast), box-shadow var(--fast);
}
.bperson:hover { background: var(--surface); border-color: var(--ink-3); box-shadow: var(--shadow-1); }
.bperson__name { font-weight: 600; }
.bperson__meta { font-size: .82rem; color: var(--ink-2); }
.bperson__sum { margin-left: auto; text-align: right; }
.bperson__sum b { display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.05rem; letter-spacing: -.02em; }
.bperson__sum span { font-size: .74rem; color: var(--ink-2); }
.bperson--off { opacity: .55; }
.bperson__sum.is-debt b { color: var(--stop); }
.bperson__sum.is-clear b { color: var(--ink-3); font-weight: 400; }

/* Карточка человека: деньги сверху и крупно — это первое, зачем сюда заходят. */
.bmoney {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s5);
  padding: var(--s5); margin-bottom: var(--s4);
  border-radius: var(--r-lg); background: var(--surface);
  border: 1px solid var(--line); box-shadow: var(--shadow-1);
}
.bmoney__main { min-width: 180px; }
.bmoney__label { display: block; font-size: .78rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3); }
.bmoney__sum { display: block; margin-top: 4px; font-family: var(--mono);
  font-size: clamp(1.8rem, 4vw, 2.4rem); font-weight: 600; letter-spacing: -.04em; line-height: 1; }
.bmoney__sum.is-debt { color: var(--stop); }
.bmoney__sum.is-clear { color: var(--ink-3); }
.bmoney__note { display: block; margin-top: 6px; font-size: .85rem; color: var(--ink-2); }
.bmoney__side { display: flex; gap: var(--s5); flex-wrap: wrap; }
.bmoney__side div { min-width: 90px; }
.bmoney__side b { display: block; font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.15rem; letter-spacing: -.03em; }
.bmoney__side span { font-size: .76rem; color: var(--ink-2); }
.bmoney__act { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; align-self: center; }

/* Появление раздела: движение объясняет смену содержимого, поэтому оно есть,
   и оно короткое, поэтому не мешает. */
.bfade { animation: bfade 200ms cubic-bezier(.2, .7, .3, 1) both; }
@keyframes bfade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .bfade { animation: none; } }

/* ═══════════════ рабочее место администратора: очередь и поиск ═══════════════

   Экран отвечает на два разных вопроса, и раньше они были свалены в одну строку.
   Первый — «что горит прямо сейчас»: на него отвечают счётчики и ленты. Второй —
   «что с телефоном вот этого человека»: на него отвечает поиск, и он не должен
   выглядеть как ещё одно поле в ряду кнопок, потому что за ним стоит живой клиент. */

.admbar {
  display: grid;
  grid-template-columns: auto minmax(260px, 420px) 1fr;
  gap: var(--s4) var(--s5);
  align-items: end;
  margin-bottom: var(--s5);
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--line);
}
.admbar h1 { font-size: 1.5rem; line-height: 1.15; margin: 0 0 2px; letter-spacing: -.02em; }
.admbar__find { min-width: 0; }
.admbar__find input { width: 100%; }
/* Подсказка под полем, а не плейсхолдером внутри: плейсхолдер исчезает ровно тогда,
   когда человек начал печатать, то есть когда подсказка и нужна. */
.admbar__find .hint { margin: 4px 0 0; font-size: .78rem; }
.admbar__act { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; align-self: end; }

/* Счётчик — кнопка к своей ленте, а не табло. Выглядит как раньше, но нажимается,
   и это видно до нажатия: курсор, подсветка и рамка выбранного. */
/* Только button.stat: те же счётчики стоят табло у кассира и у владельца, и курсор-палец
   над тем, что не нажимается, — обещание, которого экран не выполнит. */
button.stat {
  display: block;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  min-height: 0;
  box-shadow: none;
  transition: border-color var(--fast), box-shadow var(--fast), transform var(--fast);
}
button.stat:hover { background: var(--surface); border-color: var(--line-strong); box-shadow: var(--shadow-1); }
button.stat.alert:hover { background: var(--stop-bg); }
button.stat.go:hover { background: var(--go-bg); }
button.stat.wait:hover { background: var(--wait-bg); }
button.stat:active { transform: translateY(1px); }
button.stat.is-on { border-color: var(--ink-3); box-shadow: inset 0 -3px 0 var(--go); }

/* Полоса срочного: «мастер ждёт ответа» и «срок вышел» — не заголовок среди заголовков,
   а отдельный блок с краем. Иначе они тонут между вкладками и лентой. */
.band { margin: 0 0 var(--s5); padding-left: var(--s3); border-left: 3px solid var(--line-strong); }
.band--stop { border-left-color: var(--stop); }
.band h2 { display: flex; align-items: center; gap: 8px; font-size: 1.05rem; margin-bottom: var(--s3); }
.band__n {
  font-family: var(--mono); font-size: .78rem; font-weight: 600;
  padding: 1px 8px; border-radius: var(--r-pill);
  background: var(--stop-bg); color: var(--stop);
}

/* ─────────── результат поиска ───────────
   Не строка очереди, а ответ вслух: где аппарат, что сделано, когда будет.
   Порядок сверху вниз — порядок, в котором это произносят клиенту. */
.founds { display: grid; gap: var(--s4); margin-bottom: var(--s4); }
.found {
  padding: var(--s4) var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: border-color var(--fast), box-shadow var(--fast);
}
.found:hover { border-color: var(--line-strong); box-shadow: var(--shadow-2); }
.found__top { display: flex; gap: var(--s4); align-items: flex-start; flex-wrap: wrap; }
.found__code { flex: 0 0 auto; }
.found__code b {
  display: block; font-family: var(--mono); font-size: 1.35rem;
  letter-spacing: .06em; line-height: 1.1;
}
.found__code small { display: block; font-size: .72rem; color: var(--ink-3); margin-top: 2px; }
.found__who { min-width: 0; flex: 1 1 220px; }
.found__who h3 { margin: 0; font-size: 1.05rem; }
.found__who p { margin: 2px 0 0; font-size: .85rem; color: var(--ink-2); }
.found__who a { color: inherit; }
.found__flags { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.found .flow { margin: var(--s4) 0 var(--s3); }
.found__did { margin: 0 0 6px; font-size: .88rem; }
.found__act { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: var(--s3); }
.found__act .sum { font-family: var(--mono); font-size: 1.05rem; font-weight: 600; }

/* Факты парами «вопрос — ответ». Таблица здесь была бы честнее по разметке, но
   четыре строки по два слова читаются хуже, чем четыре колонки. */
.facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s3) var(--s4); margin: 0 0 var(--s3);
  padding: var(--s3) 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.facts div { min-width: 0; }
.facts dt { font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-3); }
.facts dd { margin: 2px 0 0; font-size: .92rem; font-weight: 500; }

@media (max-width: 900px) {
  .admbar { grid-template-columns: 1fr; align-items: stretch; }
  .admbar__act { justify-content: flex-start; }
  .found { padding: var(--s4); }
  .found__flags { margin-left: 0; }
}

/* Длинный чекбокс: право с объяснением, зачем оно и чем платится. Обычный .chk —
   строка в одну фразу, и переносить в нём абзац некуда. */
label.chk--long { display: flex; width: 100%; align-items: flex-start; margin-bottom: 8px; }
label.chk--long input { margin-top: 3px; flex: 0 0 auto; }
label.chk--long span { line-height: 1.45; color: var(--ink-2); }
label.chk--long span b { color: var(--ink); }

/* Выбор файла выглядит кнопкой: настоящий input[type=file] показывает «Файл не выбран»
   и подпись на языке системы, а не на языке экрана. */
.filebtn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 9px 16px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-size: .92rem; font-weight: 500; cursor: pointer;
  transition: background var(--fast), border-color var(--fast);
}
.filebtn:hover { background: var(--surface-2); border-color: var(--ink-3); }
.filebtn:focus-within { outline: 2px solid var(--info); outline-offset: 2px; }
