/* ============================================================================
   MOBILAND ERP — оформление «Точный».

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

   Правила, которых держимся:
     * строка таблицы 34 px — тридцать строк на экран всё ещё влезают;
     * цвет несёт смысл (минус — красный, проведено — зелёный), а не настроение;
     * цифры моноширинные по разрядам, иначе колонки «пляшут»;
     * статус — точка и слово, а не цветной прямоугольник;
     * движение показывает СОСТОЯНИЕ, а не себя;
     * обязательные поля помечены звёздочкой, как в МС.

   ШРИФТЫ НЕ ТЯНУТСЯ ИЗ СЕТИ. Golos Text и JetBrains Mono названы первыми,
   но касса обязана работать без интернета, поэтому ни одной внешней
   ссылки в разметке нет: не нашлись — вступает системный набор, и вёрстка
   от этого не едет (моноширинность и разрядность держатся всё равно).
   Файл писан целиком, а не дописывался кусками — иначе он превращается
   в лоскутное одеяло, что уже однажды и произошло.
   ============================================================================ */

:root {
  /* Цвет. Имена оставлены прежними: их знают шаблоны и вторая пара глаз. */
  --bg:        #e8edf5;
  --panel:     #ffffff;
  --sub:       #f7f9fc;   /* подложка: наведение, шапки таблиц, заголовки дней */
  --ink:       #151b27;
  --ink-soft:  #525d73;
  --ink-dim:   #8791a5;
  --line:      #dae1ed;
  --line-soft: #eff3f9;
  --accent:    #24528f;
  --accent-dk: #1c4276;
  --accent-bg: #e5edfa;
  --neg:       #b23b32;
  --pos:       #1c7a56;
  --warn-bg:   #fbf0d9;
  --warn-ink:  #8a6412;
  --dark:      #1a2330;   /* тёмные плитки: выручка, шапка кассы, итог чека */

  /* Форма и движение. */
  --r:      12px;         /* лист */
  --r-sm:    9px;         /* кнопка, поле */
  --r-xs:    6px;         /* мелочь внутри строки */
  --shadow:    0 1px 2px rgba(21,27,39,.05), 0 10px 28px -14px rgba(21,27,39,.22);
  --shadow-hi: 0 2px 4px rgba(21,27,39,.06), 0 18px 40px -16px rgba(21,27,39,.28);
  --move:   150ms cubic-bezier(.2,.7,.3,1);

  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --side: 186px;
  --row:   34px;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 13.5px/1.45 "Golos Text", -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; transition: color var(--move); }
a:hover { color: var(--accent-dk); text-decoration: underline; }

/* ЛЮБОЕ ПОЛЕ ВВОДА ВЫГЛЯДИТ КАК ПОЛЕ ВВОДА. Правило нарочно слабое —
   по имени тега, — чтобы всякое правило с классом его перебивало. Без
   него голый <input> в шаблоне доставался браузеру: своя рамка, свой
   шрифт, свои отступы, и рядом с нашими полями он смотрелся чужим.
   Ровно так выглядели сроки гарантии, на которые владелец и показал. */
input, textarea, select {
  font-family: inherit; font-size: 13.5px; color: var(--ink);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 6px 10px;
  transition: border-color var(--move), box-shadow var(--move);
}
input:hover, textarea:hover, select:hover { border-color: #c2d4ee; }
input:focus, textarea:focus, select:focus {
  outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(36,82,143,.15);
}
input:disabled, textarea:disabled, select:disabled {
  background: var(--line-soft); color: var(--ink-dim); cursor: default;
}
/* Галки и точки — не поля: рамка и отступы им только мешают. */
input[type=checkbox], input[type=radio] {
  padding: 0; border: 0; background: none; box-shadow: none;
  width: 15px; height: 15px; cursor: pointer; accent-color: var(--accent);
}
input[type=checkbox]:hover, input[type=radio]:hover { border: 0; }
input[type=checkbox]:focus, input[type=radio]:focus { box-shadow: none; }

.dim { color: var(--ink-dim); }
.ok-text { color: var(--pos); }
.neg, td.neg { color: var(--neg); }

/* ЧИСЛА — МОНОШИРИННЫЕ, НО НЕ ВЕСЬ ТЕКСТ. Колонка сумм должна вставать
   разряд под разряд, а название товара моноширинным читается хуже.
   Поэтому шрифт висит на том, что заведомо число: правые колонки, итоги,
   показатели, поля ввода сумм. Разрядность — на всём. */
td, th, input, .val, b { font-variant-numeric: tabular-nums; }
.grid td.r, .grid th.r, .grid tfoot td.r, .totals b, .sums b, .val,
.proof-grid b, td.qty, td.sum, .cell, .цена-строки, .pos-итог b,
.зачёт .крупно, .остаток, .сдача, .отчёт td:last-child, .link-box {
  font-family: var(--mono); letter-spacing: -.01em;
}

/* ------------------------------------------------------------ боковое меню */
/* Меню стало светлым листом, как и всё остальное. Тёмная плита во всю
   высоту тянула на себя половину внимания, а нужна она ровно на переход
   между разделами — раз в несколько минут. */
.side {
  position: fixed; inset: 12px auto 12px 12px; width: var(--side);
  background: var(--panel); color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow); padding: 15px 0; overflow-y: auto;
}
.brand {
  font-size: 15.5px; font-weight: 700; letter-spacing: .01em;
  padding: 0 15px 15px; color: var(--ink);
}
.brand span { display: block; font-size: 10.5px; font-weight: 600; margin-top: 3px;
              color: var(--ink-dim); letter-spacing: .15em; text-transform: uppercase; }
.side nav a, .side nav .soon {
  display: block; padding: 7px 13px; margin: 0 7px; border-radius: 8px;
  color: var(--ink-soft); font-size: 13px;
  transition: background var(--move), color var(--move);
}
.side nav a:hover { background: #eef3fa; color: var(--ink); text-decoration: none; }
.side nav a.on {
  background: var(--accent); color: #fff; font-weight: 600;
  box-shadow: 0 1px 2px rgba(36,82,143,.25), 0 6px 14px -8px rgba(36,82,143,.5);
}
.side nav .soon { color: var(--ink-dim); cursor: default; }

main { margin-left: calc(var(--side) + 24px); padding: 14px 18px 40px; }

h1 { font-size: 22px; font-weight: 600; margin: 0 0 10px; letter-spacing: -.022em; }
h2 { font-size: 10.5px; font-weight: 600; margin: 0 0 9px;
     text-transform: uppercase; letter-spacing: .09em; color: var(--ink-dim); }
.doc-h1 { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.doc-h1 b { font-weight: 600; }

.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow);
  padding: 14px 16px; margin-bottom: 11px;
}
.card.flush { padding: 0; }
.hint { color: var(--ink-soft); margin: -2px 0 10px; }

/* ЧЕТВЁРТЫЙ РАЗ ОДНА И ТА ЖЕ ЗАСАДА, ПОЭТОМУ ПРАВИЛО ОБЩЕЕ.
   Атрибут `hidden` прячет элемент только правилом `display: none` из
   браузерной таблицы стилей — и ЛЮБОЕ наше правило с `display` его
   перебивает: спрятанный узел остаётся на экране. Так уже горели блоки
   режимов (`display: grid`), окно закрытия смены, поле «получено
   наличными» (`display: block` у label) и кнопка «Показать ещё»
   (`display: inline-block` у `.btn`) — последняя выглядела как «касса
   показывает пустую историю с кнопкой».
   Одно правило вместо пяти заплаток. `!important` здесь уместен: он
   защищает не оформление, а смысл атрибута. */
[hidden] { display: none !important; }

/* ------------------------------------------------------------------ кнопки */
/* Кнопка отзывается на касание: приподнимается на пиксель и получает
   тень. Это не украшение — за день по ней бьют сотни раз, и «нажалось
   или нет» должно читаться до того, как придёт ответ сервера. */
.btn {
  display: inline-block; border: 1px solid transparent; border-radius: var(--r-sm);
  padding: 6px 13px; font-size: 13px; cursor: pointer; line-height: 18px;
  background: var(--accent); color: #fff; white-space: nowrap;
  font-family: inherit;
  box-shadow: 0 1px 2px rgba(36,82,143,.28), 0 8px 18px -10px rgba(36,82,143,.55);
  transition: transform var(--move), box-shadow var(--move),
              background var(--move), border-color var(--move), color var(--move);
}
.btn:hover { background: var(--accent-dk); text-decoration: none;
             transform: translateY(-1px); box-shadow: var(--shadow-hi); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow); }
.btn:disabled { opacity: .45; cursor: default; transform: none;
                box-shadow: none; background: var(--accent); }
.btn.green { background: #2f8a54; box-shadow: 0 1px 2px rgba(47,138,84,.28),
             0 8px 18px -10px rgba(47,138,84,.55); }
.btn.green:hover { background: #276f45; }
.btn.plain { background: var(--panel); color: var(--ink); border-color: var(--line);
             box-shadow: 0 1px 2px rgba(21,27,39,.04); }
.btn.plain:hover { background: var(--panel); border-color: #c2d4ee; }
.btn.ghost { background: transparent; color: var(--accent); border-color: var(--line);
             box-shadow: none; }
.btn.ghost:hover { background: var(--accent-bg); }
.btn.sm { padding: 4px 10px; font-size: 12px; }

/* -------------------------------------------------- панель действий документа */
/* Прилипает, как и шапка списка: в документе на тридцать строк «Сохранить»
   и «Отложить товар» уезжали наверх ровно тогда, когда до них доходит дело.
   Обёртка нужна, чтобы под панелью не было прозрачной щели: сама панель
   белая с рамкой, а фон полосы — серый, и стыковать их margin'ом нельзя. */
.tbar-hold {
  position: sticky; top: var(--lbar-h-top, 0px); z-index: 20;
  background: var(--bg); margin: 0 -18px 10px; padding: 6px 18px 0;
}
.tbar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--shadow);
  padding: 8px 11px; flex-wrap: wrap;
}
.tbar-left, .tbar-right { display: flex; align-items: center; gap: 7px; }
.tbar form { margin: 0; }
.nav-of { color: var(--ink-soft); margin-left: 6px; white-space: nowrap; }
.nav-arr {
  display: inline-block; width: 26px; height: 26px; line-height: 24px;
  text-align: center; border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ink-soft); font-size: 15px; background: var(--panel);
  transition: border-color var(--move), color var(--move);
}
.nav-arr:hover { border-color: #c2d4ee; color: var(--ink); text-decoration: none; }
.nav-arr.off { opacity: .35; pointer-events: none; }

/* СТАТУС — ТОЧКА И СЛОВО, а не цветной прямоугольник. Владелец выбрал
   именно так: чип кричит громче содержимого строки, а точка ставит
   состояние ровно в тот вес, который у него есть на самом деле. */
.posted { padding: 0; background: none; color: var(--ink-soft); font-size: 12.5px;
          display: inline-flex; align-items: center; gap: 7px; }
.posted::before { content: ""; width: 6px; height: 6px; border-radius: 50%;
                  background: currentColor; flex: 0 0 6px; }
.posted.on { background: none; color: var(--pos); }

/* Выпадающее меню кнопки — как «Изменить ▾» и «Печать ▾» в МС */
.menu { position: relative; }
.menu .drop::after { content: " ▾"; opacity: .6; }
.menu-list {
  display: none; position: absolute; z-index: 40; top: 100%; left: 0;
  min-width: 190px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-sm); margin-top: 4px; padding: 5px;
  box-shadow: 0 4px 10px rgba(21,27,39,.1), 0 24px 50px -18px rgba(21,27,39,.35);
}
.menu:hover .menu-list, .menu:focus-within .menu-list { display: block; }
.menu-list a, .menu-list button {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 6px 11px; font-size: 13px; color: var(--ink); cursor: pointer;
  font-family: inherit; border-radius: var(--r-xs);
  transition: background var(--move);
}
.menu-list a:hover, .menu-list button:hover { background: var(--accent-bg);
                                              text-decoration: none; }
.menu-list button.danger { color: var(--neg); }
.menu-list button:disabled { color: var(--ink-dim); cursor: default; background: none; }
.menu-list form { margin: 0; }
.menu-none { display: block; padding: 6px 12px; color: var(--ink-dim); }

/* ------------------------------------------------------------ шапка документа */
.dhead { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 36px; }
/* Есть снимок — он становится первой колонкой шапки, как в карточке МС */
.dhead.has-pic { grid-template-columns: 64px 1fr 1fr; align-items: start; }
.dhead dl { display: grid; grid-template-columns: 138px 1fr;
            gap: 5px 10px; margin: 0; align-items: center; }
.dhead dt { color: var(--ink-soft); }
.dhead dd { margin: 0; min-height: 24px; display: flex; align-items: center; gap: 6px; }
/* Ячейка, где под числом идёт пояснение. Без неё flex ставит пояснение
   СБОКУ, и «880 ₽» вытягивается в столбик по одной цифре. */
.dhead dd.stack { flex-direction: column; align-items: flex-start; gap: 1px; }
.dhead dd.stack .sm { line-height: 1.3; }
.req-mark::before { content: "* "; color: var(--neg); }
.dhead .total { font-size: 15px; font-weight: 600; }

/* ----------------------------------------------------------------- вкладки */
/* Тоже прилипают — под панелью документа. Уехавшие вкладки означают, что
   для перехода на «Связанные документы» надо сперва листать наверх. */
.tabs { display: flex; gap: 2px; padding-left: 2px;
        position: sticky; top: var(--filters-h-top, 0px); z-index: 19;
        background: var(--bg); margin: 0 -18px -1px; padding: 0 18px 0 20px; }
.tabs a {
  padding: 7px 14px; color: var(--ink-soft); border: 1px solid transparent;
  border-bottom: 0; border-radius: var(--r) var(--r) 0 0; background: transparent;
  transition: color var(--move), background var(--move);
}
.tabs a:hover { color: var(--ink); text-decoration: none; background: #eef3fa; }
.tabs a.on { background: var(--panel); border-color: var(--line);
             color: var(--ink); font-weight: 600; }
.tabs .cnt { display: inline-block; background: var(--line-soft); color: var(--ink-soft);
             border-radius: 999px; padding: 0 7px; font-size: 11px; margin-left: 4px; }

/* ------------------------------------------------------------------ таблицы */
.grid { width: 100%; border-collapse: collapse; }
.grid th {
  font-size: 10.5px; font-weight: 600; text-align: left; white-space: nowrap;
  color: var(--ink-dim); text-transform: uppercase; letter-spacing: .09em;
  padding: 9px 10px; border-bottom: 1px solid var(--line); background: #fbfcfe;
  /* Шапка не уезжает при прокрутке. В списке на сотню строк без этого
     к середине уже не помнишь, где какая колонка. */
  position: sticky; top: 0; z-index: 5;
  /* Тень появляется, только когда под шапкой что-то проехало. */
  box-shadow: 0 1px 0 var(--line);
}
.grid td { padding: 5px 10px; border-bottom: 1px solid var(--line-soft);
           height: var(--row); }
.grid th.r, .grid td.r { text-align: right; }
/* СУММА НЕ ПЕРЕНОСИТСЯ. В узкой колонке «36 100 ₽» разрывалось на две
   строки, и одна сумма читалась как две. */
.grid td.r, .grid th.r { white-space: nowrap; }
/* Строки-суммы весомее остального текста: в списке ищут глазами именно
   их, а не название колонки. */
.grid td.sum, .grid tfoot td.r { font-weight: 600; }
.grid tbody tr { transition: background var(--move); }
.grid tbody tr:hover { background: var(--sub); }
.grid tfoot td { border-bottom: 0; border-top: 1px solid var(--line);
                 font-weight: 600; }
.grid .pad { padding: 22px 8px; text-align: center; }
.grid td.code { font-size: 12px; color: var(--ink-dim); }

/* Строка-документ открывается по клику целиком */
.grid.rows tbody tr { cursor: pointer; }
.grid.rows tbody tr:hover { background: var(--accent-bg); }
/* Полоска слева у строки под курсором: в списке на сотню строк подсветки
   фоном мало — глаз теряет, на какой именно строке он стоит. */
.grid.rows tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 var(--accent); }

.w-no { width: 34px; } .w-code { width: 64px; } .w-num { width: 92px; }
.w-date { width: 86px; } .w-qty { width: 78px; } .w-price { width: 104px; }
.w-sum { width: 118px; } .w-ser { width: 116px; } .w-state { width: 120px; }
.w-disc { width: 74px; } .w-img { width: 34px; } .w-reason { width: 210px; }

/* Причина списания — текст, а не число: выравнивание по левому краю. */
.cell.left { text-align: left; }

/* Правка прямо в ячейке */
.cell {
  width: 100%; padding: 4px 7px; border: 1px solid transparent;
  border-radius: var(--r-xs); text-align: right; font-size: 13px;
  background: transparent; color: inherit;
  transition: border-color var(--move), box-shadow var(--move);
}
.cell:hover { border-color: var(--line); background: #fff; }
.cell:focus { outline: 0; border-color: var(--accent); background: #fff;
              box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

/* --------------------------------------------------------------------- итоги */
.totals { display: flex; justify-content: flex-end; gap: 30px;
          padding: 10px 8px 2px; }
.totals div { display: flex; gap: 12px; align-items: baseline; }
.totals span { color: var(--ink-soft); }
.totals b { font-weight: 600; min-width: 90px; text-align: right; }
.totals .grand b { font-size: 19px; }

/* ----------------------------------------------------------------- пометки */
.chip { display: inline-block; padding: 2px 8px; border-radius: var(--r-xs);
        font-size: 11px; background: var(--line-soft); color: var(--ink-soft); }
.chip.ok    { background: #e2f1e9; color: var(--pos); }
.chip.draft { background: var(--warn-bg); color: var(--warn-ink); }
.warn-chip  { background: var(--warn-bg); color: var(--warn-ink);
              padding: 2px 7px; border-radius: var(--r-xs); font-size: 11px; }

.alert { background: var(--warn-bg); border: 1px solid #eddcb2;
         border-radius: var(--r); padding: 10px 13px; margin-bottom: 11px; }
.alert ul { margin: 5px 0 0; padding-left: 18px; }
.deviation { color: var(--warn-ink); font-size: 12px; margin-top: 2px; }

/* Полоска выполнения под числом — как «Принято» в списке заказов МС */
.bar { display: inline-block; min-width: 62px; }
.bar i { display: block; height: 2px; margin-top: 2px; background: var(--line); }
.bar.full i { background: var(--pos); }
.bar.part i { background: #e0a63a; }

/* ------------------------------------------------------------- серийники */
.serial-list { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.serial { background: var(--accent-bg); color: var(--accent-dk); border-radius: var(--r-xs);
          padding: 2px 8px; font-size: 12px; font-family: var(--mono); }
.serial.internal { background: var(--warn-bg); color: var(--warn-ink); }
.serial .x, .sum .x { margin-left: 5px; opacity: .5; cursor: pointer; }
.serial .x:hover, .sum .x:hover { opacity: 1; color: var(--neg); }

.ser-toggle { background: var(--accent-bg); color: var(--accent-dk); border: 0;
              border-radius: var(--r-xs); padding: 3px 9px; cursor: pointer;
              font-size: 12px; font-family: inherit; }
.ser-toggle.full  { background: #e2f1e9; color: var(--pos); }
.ser-toggle.empty { background: var(--warn-bg); color: var(--warn-ink); }
.ser-toggle.open  { box-shadow: inset 0 0 0 1px currentColor; }
.ser-row > td { background: var(--sub); padding: 9px; }

.scan { display: flex; gap: 6px; margin-top: 7px; max-width: 620px; }
.scan-in { flex: 1; padding: 7px 11px; border: 1px solid var(--line);
           border-radius: var(--r-sm); font-size: 14px; font-family: var(--mono);
           transition: border-color var(--move), box-shadow var(--move); }
.scan-in:focus { outline: 0; border-color: var(--accent);
                 box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.scan-msg .msg { margin-top: 7px; padding: 7px 11px; border-radius: var(--r-sm);
                 font-size: 12px; max-width: 620px; }
.scan-msg .error   { background: #fbeeec; color: var(--neg); }
.scan-msg .warning { background: var(--warn-bg); color: var(--warn-ink); }

/* --------------------------------------------------- поле с подстановкой */
.pick { position: relative; max-width: 250px; width: 100%; }
.pick.wide { max-width: 100%; }
.pick-in { width: 100%; padding: 5px 9px; border: 1px solid var(--line);
           border-radius: var(--r-sm); font-size: 13px; background: #fff;
           font-family: inherit; color: inherit;
           transition: border-color var(--move), box-shadow var(--move); }
.pick-in:focus { outline: 0; border-color: var(--accent);
                 box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.pick-in::placeholder { color: var(--ink-dim); }
.pick-list { position: absolute; z-index: 30; left: 0; top: 100%;
             min-width: 340px; max-width: 560px; background: #fff;
             border: 1px solid var(--line); border-radius: var(--r-sm); margin-top: 4px;
             max-height: 320px; overflow-y: auto; padding: 5px;
             box-shadow: 0 4px 10px rgba(21,27,39,.1), 0 24px 50px -18px rgba(21,27,39,.35); }
.pick-row { padding: 6px 10px; cursor: pointer; display: flex; border-radius: var(--r-xs);
            justify-content: space-between; gap: 12px; align-items: baseline; }
.pick-row.on, .pick-row:hover { background: var(--accent-bg); }
.pick-name { flex: 1; }
.pick-hint { color: var(--ink-dim); font-size: 11px; white-space: nowrap; }
.pick-empty { padding: 8px 10px; color: var(--ink-dim); }
/* Строки-действия обхода: «наверх» и «выбрать эту группу». Отделены
   от вариантов выбора, потому что делают не то же самое. */
.pick-serv { color: var(--ink-soft); font-size: 12px; }
.pick-up { border-bottom: 1px solid var(--line-soft); }
.pick-take { color: var(--accent); border-bottom: 1px solid var(--line);
             font-weight: 500; }
/* Крестик очистки: у выпадашки была строка «— без группы —», и без неё
   товар нельзя вынуть из группы вовсе. Внутри поля, а не рядом, — чтобы
   не разъезжалась строка формы. */
.pick-clear { position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
              color: var(--ink-dim); cursor: pointer; font-size: 15px;
              line-height: 1; padding: 0 2px; }
.pick-clear:hover { color: var(--neg); }
/* Место под крестик, иначе он ложится поверх хвоста длинного пути. */
.pick[data-clear] .pick-in { padding-right: 22px; }
.add-row > td { background: var(--sub); }

/* ------------------------------------------------------- список документов */
/* Шапка списка НЕ УЕЗЖАЕТ при прокрутке: поиск, фильтры, счётчик и стрелки
   нужны как раз тогда, когда пролистал вниз и понял, что искал не то.
   Отступы `top` считает JS (sticky.js) по реальной высоте — она разная,
   потому что у одних разделов есть строка фильтров, у других нет. */
.lbar, .filters {
  position: sticky; z-index: 20; background: var(--bg);
  padding-top: 6px; margin-left: -18px; margin-right: -18px;
  padding-left: 18px; padding-right: 18px;
}
.lbar { top: var(--lbar-h-top, 0px); }
.filters { top: var(--filters-h-top, 0px); }
/* Шапка таблицы встаёт ПОД ними, а не под самый верх окна. */
.grid th { top: var(--head-h, 0px); }

.lbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lbar h1 { margin: 0; }
.lbar .spacer { flex: 1; }
.lbar form { margin: 0; display: flex; gap: 6px; }
.search-in { padding: 7px 12px; border: 1px solid var(--line); border-radius: var(--r-sm);
             font-size: 13px; min-width: 260px; font-family: inherit; background: var(--panel);
             transition: border-color var(--move), box-shadow var(--move); }
.search-in:focus { outline: 0; border-color: var(--accent);
                   box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

/* ------------------------------------------------------------------ главная */
.two-up { display: grid; grid-template-columns: 2fr 1fr; gap: 10px;
          align-items: start; }
/* Топ товаров и точки продаж — рядом, а не друг под другом. Класса .two
   в файле не было вовсе, и обе панели растягивались во всю ширину. */
.two { display: grid; grid-template-columns: 3fr 2fr; gap: 10px;
       align-items: start; }
@media (max-width: 1100px) { .two { grid-template-columns: 1fr; } }

/* Длинный список причин не должен занимать пол-экрана */
.alert-head { display: flex; align-items: center; gap: 12px;
              justify-content: space-between; flex-wrap: wrap; }
.alert-head form { margin: 0; }
.alert ul.fold { max-height: 108px; overflow: hidden; }
.alert .more { display: inline-block; margin-top: 4px; cursor: pointer;
               color: var(--accent); }

/* Дата документа правится прямо в заголовке — 46 % приёмок задним числом */
.date-in { font: inherit; color: var(--ink); padding: 4px 8px;
           border: 1px solid var(--line); border-radius: var(--r-xs); background: #fff; }
.date-in:focus { outline: 0; border-color: var(--accent);
                 box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.comment-box label { display: block; color: var(--ink-soft); margin-bottom: 4px; }
.comment-box textarea { width: 100%; padding: 8px 11px; border: 1px solid var(--line);
                        border-radius: var(--r-sm); font: inherit; resize: vertical; }
.comment-box textarea:focus { outline: 0; border-color: var(--accent); }
.comment-ro { color: var(--ink); white-space: pre-wrap; }
.ellip { max-width: 240px; overflow: hidden; text-overflow: ellipsis;
         white-space: nowrap; }

/* Файлы к документу */
.drop-zone { margin-top: 10px; padding: 20px; border: 1px dashed var(--line);
             border-radius: var(--r); text-align: center; color: var(--ink-soft);
             transition: border-color var(--move), background var(--move); }
.drop-zone.over { border-color: var(--accent); background: var(--accent-bg); }
.drop-zone a { cursor: pointer; }
#file-msg .msg { margin-top: 8px; padding: 6px 10px; border-radius: 3px; font-size: 12px; }
#file-msg .error { background: #fbe9e7; color: var(--neg); }

/* ============================================================================
   ГЛАВНАЯ.

   Стили восстановлены после того, как я переписал файл целиком и снёс их
   заодно с лоскутами — владелец справедливо заметил, что главная была лучше.
   Уплотнены под новый масштаб (13 px, строка 30), но раскладка та же:
   плитки показателей, тёмная плитка выручки, график по дням, топ товаров,
   точки продаж и блок сверки с МС.
   ============================================================================ */

.head { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.sub { color: var(--ink-dim); margin: 4px 0 14px; }

.periods { display: flex; gap: 2px; margin-left: auto; flex-wrap: wrap; }
.periods a { padding: 5px 12px; border-radius: 999px; color: var(--ink-soft);
             background: #e1e7f2; font-size: 12px; border: 1px solid transparent;
             transition: background var(--move), color var(--move), border-color var(--move); }
.periods a:hover { background: #d8e0ee; color: var(--ink); text-decoration: none; }
.periods a.on { background: var(--accent-bg); color: var(--accent-dk);
                border-color: #c2d4ee; font-weight: 600; }

/* Плитки показателей */
.kpi { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
       margin-bottom: 10px; }
.kpi .card { margin: 0; padding: 10px 12px; }
.card.big { grid-column: span 2; background: var(--dark); border-color: var(--dark);
            box-shadow: 0 2px 6px rgba(21,27,39,.14), 0 20px 40px -18px rgba(21,27,39,.5); }
.card.big .lbl { color: #8996ac; }
.card.big .val { color: #fff; font-size: 28px; }
.card.big .note { color: #79809a; }

.lbl { font-size: 10.5px; text-transform: uppercase; letter-spacing: .09em;
       color: var(--ink-dim); font-weight: 600; }
/* Крупное число ПРОЯВЛЯЕТСЯ, а не возникает: глаз успевает за ним, и
   при перезагрузке страницы видно, что оно посчиталось заново. */
.val { display: block; font-size: 21px; font-weight: 600; margin: 4px 0 1px;
       animation: проступает 480ms cubic-bezier(.2,.7,.3,1) both; }
@keyframes проступает { from { opacity: 0; transform: translateY(5px); } }
.note { font-size: 11px; color: var(--ink-dim); }

.panel { background: var(--panel); border: 1px solid var(--line);
         border-radius: var(--r); box-shadow: var(--shadow);
         padding: 14px 16px; margin-bottom: 11px; }
.panel h2 { margin-bottom: 10px; }

@media (max-width: 1100px) {
  .kpi { grid-template-columns: repeat(2, 1fr); }
  .card.big { grid-column: span 2; }
  .two-up { grid-template-columns: 1fr; }
}

/* График выручки.
   Столбик — отдельный класс, а не общий .bar: тем же именем названа полоска
   выполнения в списке заказов, и её min-width ломала раскладку графика. */
/* Шкала слева + поле со столбиками справа. Без шкалы высота столбика
   ни о чём не говорит: непонятно, много это или мало. */
.chart-wrap { display: flex; gap: 8px; align-items: stretch; }
.chart-y { display: flex; flex-direction: column; justify-content: space-between;
           width: 76px; flex: none; font-size: 10px; color: var(--ink-dim);
           text-align: right; height: 140px; }
.chart-y span { line-height: 1; transform: translateY(-4px); }
.chart-y span:last-child { transform: none; }

.chart {
  position: relative; flex: 1; display: flex; align-items: flex-end; gap: 2px;
  height: 140px; border-bottom: 1px solid var(--line);
}
/* Семь дней не должны превращаться в семь плит на пол-экрана —
   это уже не график, а заливка. */
.chart.few { gap: 10px; }
.chart.few .col-wrap { max-width: 96px; }

.chart .gridline { position: absolute; left: 0; right: 0; height: 0;
                   border-top: 1px dashed var(--line); pointer-events: none; }
.chart .col-wrap { position: relative; flex: 1 1 0; min-width: 2px; height: 100%;
                   display: flex; align-items: flex-end; cursor: default; }
.chart .col { width: 100%; background: #b6cbe8; border-radius: 3px 3px 0 0;
              min-height: 1px; transition: background var(--move); }
.chart .col-wrap:hover { background: rgba(26,110,192,.06); }
.chart .col-wrap:hover .col { background: var(--accent); }

/* Подписи оси идут ровно теми же долями, что и столбики, — иначе они
   разъезжаются с ними на пиксель-другой и перестают попадать в колонку. */
.chart-x { display: flex; gap: 2px; margin: 4px 0 0 84px; font-size: 10px;
           color: var(--ink-dim); }
.chart.few ~ .chart-x { gap: 10px; }
.chart-x span { flex: 1 1 0; min-width: 2px; text-align: center;
                white-space: nowrap; overflow: visible; }

.chart-tip {
  position: absolute; z-index: 20; pointer-events: none;
  background: var(--dark); color: #fff; border-radius: var(--r-sm); padding: 6px 10px;
  font-size: 12px; line-height: 1.35; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(20,24,35,.25);
}
.chart-tip .dim { color: #9aa3b8; }
/* Панель графика — точка отсчёта для подсказки, чтобы та не уезжала
   за край окна: у браузерной подсказки этим управлять нельзя, и на первом
   столбике её обрезало. */
.panel { position: relative; }

/* Таблицы главной: топ товаров, точки продаж, разбивка по типам.
   Без ширины таблица жалась к левому краю, а половина панели пустовала. */
.panel table { width: 100%; border-collapse: collapse; }
.panel table td { padding: 4px 0; border-bottom: 1px solid var(--line-soft);
                  vertical-align: baseline; }
.panel table tr:last-child td { border-bottom: 0; }
.panel .types th { font-size: 11px; text-transform: uppercase; text-align: left;
                   color: var(--ink-dim); padding: 4px 0;
                   border-bottom: 1px solid var(--line); }
.panel .types th:not(:first-child) { text-align: right; }
td.name { padding-right: 12px; }
td.name .dim { display: block; font-size: 11px; }
td.qty { text-align: right; color: var(--ink-soft); white-space: nowrap;
         width: 92px; }
td.sum { text-align: right; font-weight: 600; white-space: nowrap; width: 130px; }
.empty { color: var(--ink-dim); margin: 4px 0; }

/* Блок сверки с МойСкладом */
.proof { border-color: #cfdcf7; background: #fbfcff; }
.proof-grid { display: grid; grid-template-columns: repeat(4, 1fr);
              gap: 10px; margin-top: 8px; }
.proof-grid div { padding: 6px 0; }
.proof-grid b { display: block; font-size: 16px; font-weight: 600; }
.proof-grid span { font-size: 11px; color: var(--ink-dim); }

.types { margin-top: 8px; }
.types summary { cursor: pointer; color: var(--accent); }
.item-name { cursor: pointer; border-bottom: 1px dashed transparent; }
.item-name:hover { border-bottom-color: var(--ink-dim); }

/* ------------------------------------------------------------------ товары */
.cat-split { display: grid; grid-template-columns: 230px 1fr; gap: 10px;
             align-items: start; }
/* Дерево групп остаётся на месте, пока листаешь товары: раньше оно уезжало
   вверх, и чтобы перейти в соседнюю группу приходилось скроллить назад. */
.folders { position: sticky; top: 10px; max-height: calc(100vh - 24px);
           overflow-y: auto; padding: 10px; }
.folders h2 { margin-bottom: 6px; }
.fold { display: flex; justify-content: space-between; gap: 8px;
        padding: 4px 8px; border-radius: 3px; color: var(--ink); }
.fold:hover { background: #eef3fa; text-decoration: none; }
.fold.on { background: var(--accent-bg); color: var(--accent-dk); font-weight: 600; }
.price-chip { display: inline-block; background: var(--line-soft);
              border-radius: var(--r-xs); padding: 4px 10px; margin: 0 5px 5px 0; }
@media (max-width: 1000px) { .cat-split { grid-template-columns: 1fr; } }

/* Дерево групп */
.fold-row { display: block; }
.fold { display: flex; align-items: center; gap: 5px; padding: 4px 9px;
        border-radius: var(--r-xs); color: var(--ink);
        transition: background var(--move); }
.fold-name { flex: 1; }
.tw { display: inline-block; width: 10px; color: var(--ink-dim);
      transition: transform .1s; }
.tw.open { transform: rotate(90deg); }
.tw-none { display: inline-block; width: 10px; }

/* Правка полей прямо в карточке — отдельной админки нет */
.edit { width: 100%; max-width: 300px; padding: 4px 8px;
        border: 1px solid transparent; border-radius: var(--r-xs); background: transparent;
        font: inherit; color: inherit;
        transition: border-color var(--move), box-shadow var(--move); }
.edit:hover { border-color: var(--line); background: #fff; }
.edit:focus { outline: 0; border-color: var(--accent); background: #fff;
              box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
td .edit { max-width: none; text-align: inherit; }
textarea.edit { max-width: none; resize: vertical; line-height: 1.45; }

/* ------------------------------------------------- сортировка по колонкам */
.grid th.sortable { padding: 0; }
.grid th.sortable a {
  display: block; padding: 6px 8px; color: inherit; white-space: nowrap;
}
.grid th.sortable a:hover { color: var(--ink); text-decoration: none;
                            background: #eef3fa; }
.grid th.sorted a { color: var(--accent); }
.grid th .arw { margin-left: 3px; font-size: 9px; }
/* Место под стрелку держим всегда — иначе при сортировке колонка дёргается
   на пару пикселей, и таблица «прыгает» под курсором. */
.grid th.sortable .arw::after { content: "\00a0"; }

/* -------------------------------------------------------------- галки */
.pickcell { width: 28px; text-align: center; padding: 0 4px !important; }
.pickcell input { cursor: pointer; margin: 0; vertical-align: middle; }

/* Панель массовых действий. Показывается, только когда что-то отмечено. */
/* Панель массовых действий тёмная и приезжает: она появляется поверх
   привычного экрана, и «что-то отмечено» должно быть видно, не читая. */
.bulkbar {
  display: flex; align-items: center; gap: 8px; margin-bottom: 9px;
  padding: 9px 12px; border-radius: var(--r);
  background: var(--dark); border: 1px solid var(--dark); color: #e3e9f2;
  box-shadow: 0 4px 10px rgba(21,27,39,.2), 0 24px 50px -18px rgba(21,27,39,.5);
  animation: приехала 300ms cubic-bezier(.2,.7,.3,1) both;
}
@keyframes приехала { from { opacity: 0; transform: translateY(10px); } }
.bulkbar .btn.plain { background: rgba(255,255,255,.07); color: #dbe3ef;
                      border-color: rgba(255,255,255,.16); box-shadow: none; }
.bulkbar .btn.plain:hover { background: rgba(255,255,255,.15);
                            border-color: rgba(255,255,255,.3); }
.bulkbar .spacer { flex: 1; }
.bulkbar #bulk-clear { cursor: pointer; }
.btn.danger-text { color: var(--neg); }
/* Кнопка необратимого действия. Красная не «для красоты»: рядом с ней
   всегда стоит обычная «Отмена», и разница должна читаться до нажатия. */
.btn.danger { background: var(--neg); border-color: var(--neg); color: #fff; }
.btn.danger:hover { filter: brightness(.93); }

.alert.good { background: #eef7f1; border-color: #cbe4d5; }
.alert ul { margin: 4px 0 0; padding-left: 18px; }

/* Отступ между прилипающими полосами — ПАДДИНГОМ, а не margin. Margin
   прозрачен и не закрашивается: строки списка пролезали в эту щель между
   шапкой и фильтрами, и это было первое, что бросалось в глаза при
   прокрутке. Паддинг входит в box, красится фоном, и полосы стыкуются
   вплотную — заодно JS меряет их высоту вместе с ним. */
.lbar, .filters { padding-bottom: 10px; margin-bottom: 0; }

/* ----------------------------------------------------------- фильтры */
/* Видны всегда. Пока прятались под ссылку «Отбор», про них забывали —
   а список без фильтра это не рабочее состояние, а первая страница
   из тысяч документов. */
.filter-form {
  display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow); padding: 11px 13px;
}
.filter-label { font-size: 11px; color: var(--ink-soft); text-transform: uppercase;
                letter-spacing: .03em; align-self: center; padding-right: 2px; }
.filter-form label { display: flex; flex-direction: column; gap: 3px;
                     font-size: 11px; color: var(--ink-soft);
                     text-transform: uppercase; letter-spacing: .03em; }
.filter-form select, .filter-form input {
  padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
  font: 13px/1.4 inherit; background: #fff; color: var(--ink);
  text-transform: none; letter-spacing: normal;
  transition: border-color var(--move), box-shadow var(--move);
}
.filter-form select { max-width: 280px; }
.filter-form select:focus, .filter-form input:focus {
  outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

/* ------------------------------------------------------------- перелистывание */
.pager { display: inline-flex; align-items: center; gap: 4px; margin-left: 10px; }
.pages { display: flex; align-items: center; justify-content: center; gap: 14px;
         margin-top: 10px; }
.pages .off { opacity: .4; pointer-events: none; }

/* --------------------------------------------------------------- картинки */
/* Миниатюра в списке. Ряд остаётся 30 px — картинка не должна раздувать
   таблицу, иначе теряется вся плотность, ради которой она делалась. */
.w-img { width: 34px; }
td.pic { padding: 2px 4px 2px 8px; }
td.pic img { display: block; width: 26px; height: 26px; object-fit: contain;
             border-radius: 3px; background: #fff; }

.gal { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; }
.gal-i { margin: 0; width: 132px; border: 1px solid var(--line);
         border-radius: var(--r); padding: 7px; background: #fff; }
.gal-i.main { border-color: var(--accent); }
.gal-i img { display: block; width: 118px; height: 118px; object-fit: contain; }
.gal-i figcaption { display: flex; align-items: center; justify-content: space-between;
                    gap: 6px; margin-top: 5px; font-size: 11px; }
.gal-i .mk-main { color: var(--accent); cursor: pointer; }
.gal-i .rm-img { color: var(--ink-dim); cursor: pointer; font-size: 14px; }
.gal-i .rm-img:hover { color: var(--neg); }

.gal-add { display: flex; flex-direction: column; align-items: center;
           justify-content: center; gap: 3px; width: 132px; height: 145px;
           border: 1px dashed var(--line); border-radius: var(--r); cursor: pointer;
           color: var(--accent); font-size: 12px; text-align: center; }
.gal-add:hover, .gal-add.over { border-color: var(--accent); background: var(--accent-bg); }
.gal-add .dim { font-size: 11px; }
.img-msg .msg { margin-top: 8px; padding: 6px 10px; border-radius: 3px; font-size: 12px; }
.img-msg .error { background: #fbe9e7; color: var(--neg); }

/* Шапка выбранной группы: картинка + название + описание */
.grp { display: flex; gap: 12px; align-items: flex-start; }
.grp-img { flex: 0 0 74px; width: 74px; height: 74px; border-radius: 4px;
           border: 1px solid var(--line); display: flex; align-items: center;
           justify-content: center; cursor: pointer; overflow: hidden;
           background: #fff; }
.grp-img.empty { border-style: dashed; color: var(--accent); font-size: 11px;
                 text-align: center; }
.grp-img:hover { border-color: var(--accent); }
.grp-img img { width: 100%; height: 100%; object-fit: contain; }
.grp-text { flex: 1; min-width: 0; }
.grp-head { display: flex; align-items: center; gap: 8px; }
.grp-name { max-width: 340px; font-size: 15px; font-weight: 600; }
.grp-head .dim { cursor: pointer; font-size: 11px; }
.grp-descr { width: 100%; margin-top: 4px; }

/* Картинка в шапке карточки товара */
.card-pic { flex: 0 0 64px; width: 64px; height: 64px; object-fit: contain;
            border: 1px solid var(--line); border-radius: 4px; background: #fff; }

/* ------------------------------------------------- статусы заказов и отборы */
/* Цвет берём из МС — там он у каждого статуса свой, и люди узнают заказ
   по цвету раньше, чем прочтут название. */
.chip.status { background: var(--c); color: #fff; font-weight: 600; }
.menu-list .dot { display: inline-block; width: 8px; height: 8px;
                  border-radius: 2px; margin-right: 6px; }

.saved-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px;
             align-items: center; }
.chip-link { display: inline-flex; align-items: center; gap: 7px;
             padding: 6px 13px; border-radius: 8px; font-size: 12.5px;
             background: var(--panel); border: 1px solid var(--line); color: var(--ink-soft);
             transition: border-color var(--move), color var(--move), box-shadow var(--move); }
.chip-link:hover { border-color: #c2d4ee; color: var(--ink); text-decoration: none;
                   box-shadow: 0 1px 2px rgba(21,27,39,.06); }
.chip-link.on { background: var(--accent-bg); border-color: var(--accent);
                color: var(--accent-dk); font-weight: 500; }
.chip-link.add { border: 1px dashed var(--line); background: none;
                 color: var(--accent); cursor: pointer; }
.chip-link .x { opacity: .45; cursor: pointer; }
.chip-link .x:hover { opacity: 1; color: var(--neg); }

/* Полоска оплаты под суммой — доля закрытых денег по заказу */
.bar i { width: 100%; }

/* ------------------------------------------------------ правка заказа */
/* Кнопка «Сохранить» гаснет, пока сохранять нечего, и загорается, как
   только человек тронул хоть одно поле. Активная кнопка, которая ничего
   не делает, — то же самое, что её отсутствие. */
#save-doc:disabled { opacity: .45; cursor: default; }
#save-doc.dirty { box-shadow: 0 0 0 3px rgba(107, 165, 58, .25); }

/* Почему заказ не правится — текстом рядом с кнопками, а не догадками. */
.locked-why { font-size: 12px; padding: 4px 0; }

/* Резерв в строке — галка с числом рядом. Именно галка, а не поле:
   откладывать товар решает человек, когда заказ подтверждён, а не
   документ сам по факту проведения. */
.res-box { display: inline-flex; align-items: center; gap: 5px;
           cursor: pointer; justify-content: flex-end; }
.res-box input { cursor: pointer; }
.res-n { min-width: 12px; font-weight: 600; color: var(--pos); }

/* Галка «отложено» на заказе. Именно галка, а не кнопка: по кнопке не
   видно состояния, а тут с одного взгляда ясно, отложен заказ или нет. */
.res-toggle { display: inline-flex; align-items: center; gap: 7px;
              padding: 6px 12px; border: 1px solid var(--line);
              border-radius: var(--r-sm); font-size: 13px; cursor: pointer;
              background: #fff; white-space: nowrap;
              transition: background var(--move), border-color var(--move); }
.res-toggle.on { background: #f1f7f3; border-color: #c6e0d1; font-weight: 600; }
.res-toggle:has(input:disabled) { opacity: .5; cursor: default; }

/* Контрагент в списке заказов: длинные ФИО не должны съедать таблицу. */
.w-partner { width: 22%; max-width: 260px; }
td.w-partner, .grid td.w-partner { overflow: hidden; text-overflow: ellipsis;
                                   white-space: nowrap; }

/* ------------------------------------------------- строка разделов группы */
/* Вкладки группы: «Продажи» → заказы, продажи, возвраты, предоплаты.
   Как в МС второй строкой, только видны сразу, а не по наведению мыши. */
.sections {
  display: flex; flex-wrap: wrap; gap: 2px; align-items: center;
  position: sticky; top: 0; z-index: 21; background: var(--bg);
  margin: -14px -18px 10px; padding: 8px 18px 8px;
  border-bottom: 1px solid var(--line);
}
/* РАЗДЕЛЫ — ПОДЧЁРКИВАНИЕМ, а не заливкой. Синий прямоугольник в шапке
   спорил по весу с самим содержимым раздела; черта под словом говорит
   ровно то же самое и молчит, пока на неё не смотрят. */
.sections a, .sections .soon {
  padding: 9px 2px; margin-right: 18px; font-size: 13px; white-space: nowrap;
  transition: color var(--move), box-shadow var(--move);
}
.sections a { color: var(--ink-soft); }
.sections a:hover { color: var(--ink); text-decoration: none;
                    box-shadow: inset 0 -2px 0 var(--line); }
.sections a.on { color: var(--ink); font-weight: 600;
                 box-shadow: inset 0 -2px 0 var(--accent); }
.sections a.on:hover { box-shadow: inset 0 -2px 0 var(--accent); }
.sections .soon { color: var(--ink-dim); cursor: default; }

/* --------------------------------------------------- история изменений */
/* «Цена: 62 500 ₽ → 61 000 ₽» — читается взглядом, без разбора колонок. */
.chg { padding: 1px 0; }
.chg .arr { color: var(--ink-dim); margin: 0 3px; }

/* ------------------------------------------- итоги отбора над списком */
/* Считаются по ВСЕМУ отбору, а не по видимой странице: в списке на 33 966
   чеков сумма сотни строк не значит ничего, спрашивают «сколько за период». */
.sums { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
        margin-bottom: 10px; }
.sums > div { background: var(--panel); border: 1px solid var(--line);
              border-radius: var(--r); box-shadow: var(--shadow); padding: 10px 13px; }
.sums span { display: block; font-size: 10.5px; text-transform: uppercase;
             letter-spacing: .09em; color: var(--ink-dim); font-weight: 600; }
.sums b { display: block; font-size: 19px; font-weight: 600; margin-top: 3px;
          animation: проступает 480ms cubic-bezier(.2,.7,.3,1) both; }
.sums i { display: block; font-style: normal; font-size: 11px;
          color: var(--ink-dim); }
@media (max-width: 1100px) { .sums { grid-template-columns: repeat(2, 1fr); } }

/* ------------------------------------------- быстрый выбор периода */
/* «вч · сег · нед · мес» — как в МС. Две даты руками по двадцать раз
   на дню никто набирать не станет, а спрашивают именно эти четыре. */
.period { min-width: 250px; }
.period .quick { display: inline-flex; align-items: center; gap: 4px;
                 margin-left: 6px; text-transform: none; letter-spacing: normal; }
.period .quick a { color: var(--accent); cursor: pointer; font-size: 11px; }
.period .quick i { color: var(--ink-dim); font-style: normal; font-size: 10px; }
.period-in { display: inline-flex; align-items: center; gap: 5px; }
.period-in i { color: var(--ink-dim); font-style: normal; }
.period-in input { width: 128px; }

/* Подтверждение автосохранения — там, где кнопки «Сохранить» нет. */
.saved-mark { color: var(--pos); font-size: 11px; margin-left: 6px;
              text-transform: none; letter-spacing: normal; }

/* Серийник — ссылка на судьбу аппарата: откуда пришёл, кому продан. */
a.serial:hover { text-decoration: underline; }
.serial.big { font-size: 17px; }


/* ------------------------------------------------------- инвентаризация */
/* Пропавший аппарат зачёркнут: его не «нет в списке», его НЕ НАШЛИ. */
.serial.gone { text-decoration: line-through; color: var(--neg);
               border-color: var(--neg); opacity: .8; }
.grid tr.diff td { background: var(--accent-bg); }
.scan-bar { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.scan-bar form { display: flex; gap: 6px; }
.bad { color: var(--neg); } .ok { color: var(--pos); }

/* Заголовок внутри карточки без полей: сама карточка flush, отступ нужен
   только заголовку — иначе он лип бы к краю таблицы. */
.card.flush > h2.sec { padding: 10px 8px 0; }
.card.flush > .hint { padding: 0 8px; }

/* Пересчёт: строка, до которой ещё не дошли. Не ошибка и не расхождение —
   просто неизвестность, поэтому приглушена, а не покрашена в красное. */
.grid tr.todo td { color: #8a9099; }
.grid tr.todo td.code, .grid tr.todo td:nth-child(3) { color: #6b7280; }
a.mark-empty { color: #2563eb; cursor: pointer; font-size: 12px;
               border-bottom: 1px dashed currentColor; }
.tabs .cnt.neg { background: #fde2e1; color: #a11; }

/* ── Экраны до входа ────────────────────────────────────────────────────
   Отдельная раскладка: ни меню, ни вкладок, только карточка по центру.
   Человеку, который ещё не вошёл, нечего показывать, кроме одной формы. */
body.auth {
    display: flex; align-items: center; justify-content: center;
    min-height: 100vh; margin: 0; background: var(--bg);
}
.auth-box {
    width: 100%; max-width: 380px; padding: 32px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 16px;
    box-shadow: 0 2px 6px rgba(21,27,39,.06), 0 30px 60px -24px rgba(21,27,39,.35);
    animation: всплыть 420ms cubic-bezier(.2,.7,.3,1) both;
}
@keyframes всплыть { from { opacity: 0; transform: translateY(8px); } }
.auth-brand {
    font-weight: 700; font-size: 20px; letter-spacing: .01em;
    margin-bottom: 24px; color: var(--ink);
}
.auth-brand span {
    font-weight: 400; color: var(--ink-dim); margin-left: 6px; font-size: 15px;
}
.auth-form label {
    display: block; margin-bottom: 14px;
    font-size: 13px; color: var(--ink-soft);
}
.auth-form input, .auth-form select {
    display: block; width: 100%; box-sizing: border-box;
    margin-top: 5px; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: var(--r-sm);
    font-size: 15px; background: #fff; font-family: inherit; color: var(--ink);
    transition: border-color var(--move), box-shadow var(--move);
}
.auth-form input:focus, .auth-form select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(36,82,143,.15);
}
.auth-form button {
    width: 100%; margin-top: 6px; padding: 11px;
    border: 0; border-radius: var(--r-sm); cursor: pointer; font-family: inherit;
    background: var(--accent); color: #fff; font-size: 15px; font-weight: 500;
    box-shadow: 0 1px 2px rgba(36,82,143,.28), 0 8px 18px -10px rgba(36,82,143,.55);
    transition: background var(--move), transform var(--move), box-shadow var(--move);
}
.auth-form button:hover { background: var(--accent-dk);
                          transform: translateY(-1px); box-shadow: var(--shadow-hi); }
.auth-form button:active { transform: translateY(0); }
/* Ошибку показываем над формой, а не рядом с полем: причина у неудачного
   входа всегда одна на всю форму — мы намеренно не говорим, логин неверен
   или пароль. Иначе форма превращается в список сотрудников. */
.auth-err {
    margin-bottom: 16px; padding: 10px 12px;
    background: #fbeeec; border: 1px solid #edc7c3; border-radius: var(--r-sm);
    color: var(--neg); font-size: 13px;
}
.auth-note {
    margin: 16px 0 0; font-size: 12px; color: var(--ink-dim); line-height: 1.5;
}

/* Кто вошёл — внизу бокового меню. */
/* Меню стало светлым — и подпись «кто вошёл» вместе с ним: белый текст
   на белом листе был бы невидим. */
.whoami {
    margin-top: auto; margin-left: 15px; margin-right: 15px;
    padding: 12px 0 0; border-top: 1px solid var(--line-soft);
    font-size: 12px; line-height: 1.5;
}
.whoami-name { color: var(--ink); font-weight: 500; }
.whoami-role { color: var(--ink-dim); }
.whoami a { display: inline-block; margin-top: 6px; margin-right: 10px;
            color: var(--ink-soft); }
.whoami a:hover { color: var(--accent); }
/* Меню — колонкой, чтобы «кто вошёл» прижалось к низу. */
.side { display: flex; flex-direction: column; }
.side nav { flex: 1 1 auto; }

.no-access { max-width: 480px; margin: 60px auto; text-align: center; }
.no-access h1 { font-size: 20px; margin-bottom: 10px; }
.no-access .hint { color: var(--ink-dim); font-size: 13px; line-height: 1.6; margin-top: 18px; }


/* ── Настройки: роли, права, сотрудники ─────────────────────────────────
   Своих классов здесь минимум: всё, что можно, взято из общей раскладки
   (.card, .grid, .btn, .tbar, .chip). Первая версия этих экранов была
   написана на выдуманных классах, которых в проекте нет, — оттого и
   выглядела как чужой сайт внутри своего. */

/* Раскрывающаяся форма «+ Сотрудник» рядом с заголовком. Класс уже
   использовался в списке контрагентов, но описан не был. */
.newbox { position: relative; }
.newbox > summary { list-style: none; cursor: pointer; }
.newbox > summary::-webkit-details-marker { display: none; }
.newbox[open] > summary { background: #e9edf3; color: var(--ink);
    border-color: var(--line); }
.newbox .filter-form {
    position: absolute; z-index: 20; top: calc(100% + 6px); left: 0;
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
    min-width: 560px; padding: 15px;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: 0 4px 10px rgba(21,27,39,.1), 0 24px 50px -18px rgba(21,27,39,.35);
}

/* Полоса-предупреждение и полоса-подтверждение над списком. */
.warn-card, .ok-card {
    margin-bottom: 12px; padding: 10px 14px; border-left: 3px solid;
}
.warn-card { border-left-color: var(--neg); background: #fdf4f3; }
.ok-card   { border-left-color: var(--pos); background: #f1f7f3; }

.chip.neg-chip { background: #fbeeec; color: var(--neg); }

/* Одноразовая ссылка-приглашение: показывается один раз, поэтому её надо
   удобно выделить и скопировать, а не переписывать глазами. */
.link-card { border-left: 3px solid var(--accent); }
.link-box {
    width: 100%; box-sizing: border-box; padding: 9px 11px;
    font-size: 12px; background: var(--sub);
    border: 1px solid var(--line); border-radius: var(--r-sm);
}

/* Поля внутри карточки реквизитов тянутся на всю ячейку. Без этого
   выпадающий список схлопывается в чёрточку: ячейка — flex-контейнер,
   и элемент с width:100% без основы сжимается до нуля. */
.dhead dd > .edit { flex: 1 1 auto; min-width: 0; }
/* Раскладка на ОДИН столбец. Обычный .dhead всегда делает два — он писан
   под широкую карточку документа с реквизитами слева и справа. В узкой
   карточке с одним столбцом вторая половина всё равно резервируется, и
   полю остаётся тридцать пикселей: выпадающий список превращается в
   чёрточку. Ошибка не в поле, а в сетке вокруг него. */
.dhead.one { grid-template-columns: 1fr; }
.dhead dd > select.edit { max-width: none; }

/* Галки в карточке реквизитов. Колонка узкая — подпись не переносим,
   иначе текст разваливается в столбик по одному слову. */
.dhead dd input[type=checkbox] { width: 16px; height: 16px; margin: 0; }
label.flag { display: flex; align-items: center; gap: 7px;
    white-space: nowrap; color: var(--ink-soft); cursor: pointer; }
label.flag input { width: 15px; height: 15px; }

/* Поля названия и заметки прямо в панели действий. */
.in-tbar { width: 150px; padding: 5px 9px; font-size: 13px; font-family: inherit;
    border: 1px solid var(--line); border-radius: var(--r-sm); }
.in-tbar.wide { width: 240px; }

/* ── Таблица прав ─────────────────────────────────────────────────────
   Строка на раздел, колонка на операцию. Колонки узкие и одинаковые,
   чтобы галки стояли ровным столбиком: взгляд ищет пропуски по столбцу,
   а не читает каждую строку. */
.grid.perms td:first-child, .grid.perms th:first-child { width: 40%; }
.grid.perms th.c, .grid.perms td.c { width: 10%; text-align: center; }
.grid.perms input[type=checkbox] { width: 16px; height: 16px; cursor: pointer; }
.grid.perms tbody tr:hover { background: var(--sub); }
.perm-group td {
    padding-top: 12px; background: var(--sub);
    font-size: 11px; font-weight: 600; letter-spacing: .5px;
    text-transform: uppercase; color: var(--ink-soft);
}
.perm-na { color: #ccd0d6; }

/* Отдельные разрешения — списком с пояснением под каждым. */
.flags { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 10px 24px; }
.flag-row { display: flex; align-items: flex-start; gap: 9px; cursor: pointer; }
.flag-row input { margin-top: 2px; width: 16px; height: 16px; }
.flag-row span { display: block; line-height: 1.35; }
.flag-row i { display: block; font-style: normal; font-size: 12px;
    color: var(--ink-soft); }

.w-role { width: 220px; }
.w-act  { width: 90px; text-align: right; }
.w-act form { margin: 0; }

/* Полоса выбора периода — одна на все отчёты. */
.periods { display: flex; gap: 4px; margin-bottom: 12px; flex-wrap: wrap; }
.periods a {
    padding: 6px 13px; border-radius: 999px; font-size: 12.5px;
    color: var(--ink-soft); background: #e1e7f2;
}
.periods a:hover { background: #d8e0ee; color: var(--ink); text-decoration: none; }
.periods a.on { background: var(--accent-bg); color: var(--accent-dk);
                border-color: #c2d4ee; }

/* Раскрывашка «а это точно смотрели?»: объяснения того, почему беды нет.
   Свёрнута по умолчанию намеренно — развёрнутый список безобидных фактов
   читается как список бед. */
details.card > summary { cursor: pointer; color: var(--ink-soft); font-size: 13px; }
details.card > summary:hover { color: var(--ink); }
details.card[open] > summary { margin-bottom: 10px; }
details.card > section.card,
details.card > div.card { box-shadow: none; border: 0; padding-left: 0;
                          padding-right: 0; margin-bottom: 0; }

/* ── Касса ───────────────────────────────────────────────────────────────
   Две колонки: слева корзина, справа покупатель и оплата. Порядок не
   декоративный — за прилавком сначала кладут товар, а разговаривают
   потом. На узком экране колонки складываются в одну, корзина сверху.

   Крупные поля и кнопки здесь намеренно: в кассу тычут пальцем и смотрят
   на неё в полглаза, держа в руках коробку. */
.pos { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 11px;
       align-items: start; }
/* `display: grid` сильнее атрибута hidden, и скрытый режим оставался на
   экране: под чеком висел второй блок с полем «номер чека». Правило
   нужно ИМЕННО ЗДЕСЬ, рядом с display, — иначе следующая правка сетки
   снова его перебьёт, и никто не поймёт почему. */
@media (max-width: 900px) { .pos { grid-template-columns: 1fr; } }

.pos-режимы { display: flex; gap: 8px; margin: 0 0 12px; }

/* Поле сканера — самый крупный элемент экрана. Это единственное место,
   куда кассир смотрит весь день. */
#поле-скана { width: 100%; font-size: 20px; padding: 12px 15px;
    font-family: var(--mono); }

/* ИТОГ — ТЁМНАЯ ПЛИТКА С ОДНИМ КРУПНЫМ ЧИСЛОМ. Это то, что кассир
   называет вслух, и то, на что смотрит покупатель через плечо: числу
   нужен свой вес, а не строчка под таблицей. */
.pos-итог { display: flex; align-items: baseline; justify-content: space-between;
            gap: 12px; margin-top: 12px; padding: 13px 17px;
            background: var(--dark); color: #a0aec2; border-radius: var(--r);
            font-size: 14px;
            box-shadow: 0 2px 6px rgba(21,27,39,.14), 0 20px 40px -18px rgba(21,27,39,.5); }
.pos-итог b { font-size: 30px; font-weight: 600; color: #fff;
              animation: проступает 480ms cubic-bezier(.2,.7,.3,1) both; }

.pos-справа h3 { margin: 16px 0 8px; font-size: 10.5px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .09em; color: var(--ink-dim); }
.pos-справа h3:first-child { margin-top: 0; }

.pos-клиент { display: flex; align-items: center; justify-content: space-between;
              gap: 8px; }
.pos-баллы { display: grid; grid-template-columns: auto auto; gap: 2px 10px;
             margin: 8px 0; font-size: 13px; }
.pos-баллы dt { color: var(--ink-soft); }
.pos-баллы dd { margin: 0; text-align: right; }

.pos-списание { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.pos-списание label { flex: 1 1 120px; }
.pos-списание > div { flex-basis: 100%; font-size: 13px; }

.pos-начисление { margin-top: 10px; font-size: 13px; }
.pos-начисление ul { margin: 6px 0 0; padding-left: 18px; }

.pos-подсказки { display: flex; flex-direction: column; gap: 2px; margin: 6px 0; }
.pos-подсказки .btn { text-align: left; }

.pos-оплата label { display: block; margin-bottom: 8px; }
.pos-оплата input, .pos-поиск-клиента input, #искать-чек input {
    width: 100%; font-size: 17px; padding: 10px 12px; color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
    font-family: var(--mono); text-align: right;
    transition: border-color var(--move), box-shadow var(--move); }
/* Поиск — текст, а не сумма: моноширинный и по правому краю он читается
   как число, которым не является. */
.pos-поиск-клиента input, #искать-чек input, .pos-оплата input[type=text],
.pos-оплата #банк-кредита, .pos-оплата #сбп-кому, .pos-оплата #сбп-банк {
    font-family: inherit; text-align: left; }
.pos-оплата input:focus, .pos-поиск-клиента input:focus,
#искать-чек input:focus, #поле-скана:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
#поле-скана { border: 1px solid var(--line); border-radius: var(--r-sm); }
#поле-скана:focus { box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.pos-кнопки { display: flex; gap: 8px; margin-top: 13px; }
.pos-кнопки .btn { flex: 1; padding: 13px; font-size: 15px; text-align: center; }
/* «Пробить чек» — единственное действие, ради которого экран существует.
   Класс `primary` в разметке был, а в стилях его не было вовсе: главная
   кнопка кассы выглядела ровно как соседняя «Разнести». */
.btn.primary { background: #3468b8; font-size: 16px; font-weight: 600;
    box-shadow: 0 2px 6px rgba(52,104,184,.42), 0 12px 24px -12px rgba(52,104,184,.7); }
.btn.primary:hover { background: #2c5aa0; }

/* Числа в чеке НЕ ПЕРЕНОСЯТСЯ. Колонка узкая, и «133 700» разрывалось
   на две строки: сумма при этом читается как две разные суммы. */
#строки td.r, #строки th.r { white-space: nowrap; }

/* Строка возврата: галочка на каждом аппарате отдельно. «Вернуть одну
   штуку» из двух одинаковых телефонов — не ответ, надо знать какой. */
.pos-строка { padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.pos-аппарат { display: block; margin: 4px 0 0 20px; font-family: var(--mono);
               font-size: 13px; }
.pos-строка .сколько { width: 60px; margin-left: 24px; }

/* Отказ кассы виден и называет причину: молчаливое «не получилось»
   обходится продажей мимо системы. */
.беда { margin: 8px 0; padding: 9px 12px; border-radius: var(--r-sm);
        background: #fbeeec; color: var(--neg); font-size: 13px; }
.ok-строка { font-size: 13px; color: var(--ink-soft); }

.pos-узкая { max-width: 560px; }
.pos-форма { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.pos-форма label { display: flex; flex-direction: column; gap: 4px;
                   color: var(--ink-soft); font-size: 13px; width: 100%; }
.pos-форма input, .pos-форма select { font-size: 16px; padding: 10px 12px;
    color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-sm);
    font-family: inherit; background: #fff; }
.pos-форма input:focus, .pos-форма select:focus { outline: 0;
    border-color: var(--accent); box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.pos-точки { display: flex; flex-wrap: wrap; gap: 8px; }

/* Логотип организации в настройках: видно, что именно уйдёт на бумагу. */
.org-logo { display: flex; align-items: center; gap: 12px; margin: 12px 0 4px;
            flex-wrap: wrap; }
.org-logo .lbl { color: var(--ink-soft); font-size: 13px; }
.org-logo .logo-preview { max-height: 42px; max-width: 190px;
                          border: 1px solid var(--line-soft); border-radius: 4px;
                          padding: 4px 8px; background: #fff; }

/* ── Каталог на кассе ────────────────────────────────────────────────────
   Три колонки: каталог, корзина, оплата. Каталог слева, потому что с него
   начинается чек — товар кладут, а разговаривают потом. */
.пос-с-каталогом { grid-template-columns: 300px minmax(0, 1fr) 344px; }
@media (max-width: 1200px) {
    .пос-с-каталогом { grid-template-columns: minmax(0, 1fr) 320px; }
    .pos-каталог { grid-column: 1 / -1; }
}
@media (max-width: 900px) { .пос-с-каталогом { grid-template-columns: 1fr; } }

#искать-товар input { width: 100%; font-size: 16px; padding: 10px 13px;
    border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
    font-family: inherit; color: var(--ink);
    transition: border-color var(--move), box-shadow var(--move); }
#искать-товар input:focus { outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

.pos-крошки { display: flex; flex-wrap: wrap; gap: 4px; font-size: 12px;
    color: var(--ink-soft); margin: 8px 0 4px; min-height: 16px; }
.pos-крошки a { cursor: pointer; }

.pos-плитки { display: flex; flex-direction: column; gap: 1px;
    max-height: 52vh; overflow-y: auto; }

/* Строка каталога: звезда, картинка, название, остаток, цена. Пальцем
   попадают в строку целиком, а не в мелкую кнопку. */
/* Строка каталога без разделителя: подсветка под курсором говорит, где
   палец, лучше сетки линий, а линии на семи строках превращают каталог
   в бланк. */
.поз { display: flex; align-items: center; gap: 10px; padding: 8px;
    border-radius: var(--r-sm); cursor: pointer;
    transition: background var(--move); }
.поз:hover { background: var(--sub); }
.поз .звезда { font-size: 15px; color: #d6d9e0; cursor: pointer;
    line-height: 1; padding: 2px; }
.поз .звезда.на { color: #f0a500; }
.поз .фото { width: 30px; height: 30px; object-fit: contain; flex: none; }
.поз .имя { flex: 1; min-width: 0; line-height: 1.25; }
.поз .имя i { display: block; font-style: normal; font-size: 11px;
    color: var(--ink-soft); }
.поз .цена { font-weight: 600; white-space: nowrap; font-family: var(--mono);
    font-size: 14px; }
.поз.нет .цена, .поз.нет .имя { color: var(--ink-soft); }

/* Группа каталога — та же строка, но ведёт вглубь. */
.группа { display: flex; align-items: center; justify-content: space-between;
    padding: 10px 8px; border-radius: var(--r-sm); cursor: pointer;
    transition: background var(--move); }
.группа:hover { background: var(--sub); }
.группа .стрелка { color: var(--ink-soft); }

.pos-листалка { display: flex; gap: 6px; justify-content: center;
    margin-top: 8px; }

/* Касса ждёт серийник выбранного товара — и говорит об этом. */
.ждём { margin: 8px 0; padding: 9px 12px; border-radius: var(--r-sm);
        background: var(--warn-bg); color: var(--warn-ink); font-size: 13px; }

/* Окно поверх кассы: закрытие смены, где три вечерних вопроса решаются
   разом, а не тремя `prompt` подряд. */
.pos-окно { position: fixed; inset: 0; background: rgba(21, 27, 39, .45);
    display: flex; align-items: flex-start; justify-content: center;
    padding: 6vh 16px; z-index: 50; overflow-y: auto;
    animation: проступает 160ms ease-out both; }
.pos-окно .card { width: 100%; margin: 0; border-radius: 16px; border: 0;
    box-shadow: 0 8px 20px rgba(21,27,39,.18), 0 40px 80px -28px rgba(21,27,39,.6);
    animation: всплыть 260ms cubic-bezier(.2,.7,.3,1) both; }
.pos-окно-нутро { max-width: 620px; }
/* Покупатель — окно шире: пять колонок (имя, карта, телефон, почта,
   баллы) в 620 пикселей не помещаются и переносятся в кашу. */
#окно-покупателя .pos-окно-нутро,
#окно-нового-клиента .pos-окно-нутро { max-width: 900px; }
.pos-окно-шапка { display: flex; align-items: flex-start; gap: 10px;
    justify-content: space-between; }
.pos-окно-шапка h2 { margin: 0 0 10px; }
.pos-окно-шапка .btn { font-size: 20px; line-height: 1; padding: 2px 10px; }

/* Карточка операции: состав, оплата, кто пробил — читается сверху вниз. */
.карточка-строки td { padding: 6px 8px; border: 0;
    border-bottom: 1px solid var(--line-soft); }
.карточка-строки .номера { font-size: 12px; color: var(--ink-soft); }
.карточка-оплаты td { padding: 3px 8px; border: 0; }
.карточка-оплаты tr.итожная td { font-size: 16px; font-weight: 700;
    padding-top: 8px; }
.grid.лента tbody tr:not(.лента-смена) { cursor: pointer; }

/* Список покупателей в окне: строка целиком кликабельна — за прилавком
   целятся в строку, а не в ссылку внутри неё. */
.grid.клиенты tbody tr { cursor: pointer; }
.grid.клиенты tbody tr:hover { background: var(--accent-bg); }
.grid.клиенты tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 var(--accent); }

/* Поиск и переключатель вида — одной строкой над каталогом. */
.pos-строка-поиска { display: flex; gap: 8px; align-items: center; }
.pos-строка-поиска #искать-товар { flex: 1; }
.pos-вид { display: flex; gap: 2px; }
.pos-вид .btn { font-size: 15px; line-height: 1; padding: 6px 9px; }
.pos-вид .btn.на { background: var(--accent-bg); color: var(--accent-dk);
    border-color: #c2d4ee; font-weight: 700; }

/* ТРИ ВИДА КАТАЛОГА. Разметка позиции одна на все три — меняется только
   раскладка контейнера, иначе правка делается трижды и в третьем месте
   забывается. */
.pos-плитки.вид-tiles { display: grid; gap: 8px;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.pos-плитки.вид-tiles .группа,
.pos-плитки.вид-tiles .поз { flex-direction: column; align-items: flex-start;
    min-height: 96px; justify-content: space-between; border-radius: var(--r);
    border: 1px solid var(--line); padding: 11px; background: var(--panel);
    box-shadow: 0 1px 2px rgba(21,27,39,.04);
    transition: border-color var(--move), transform var(--move), box-shadow var(--move); }
.pos-плитки.вид-tiles .группа:hover,
.pos-плитки.вид-tiles .поз:hover { background: var(--panel); border-color: #c2d4ee;
    transform: translateY(-1px); box-shadow: var(--shadow-hi); }
.pos-плитки.вид-tiles .группа .стрелка { display: none; }
.pos-плитки.вид-tiles .поз .фото { display: none; }
.pos-плитки.вид-tiles .поз .цена { font-size: 15px; }
/* В дереве папка — крупная строка: в неё целятся пальцем. */
.pos-плитки.вид-tree .группа { padding: 12px 10px; font-size: 15px; }

/* Конструктор печатной формы: список блоков, который таскают мышью. */
.редактор-форм { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
    gap: 14px; align-items: start; }
@media (max-width: 1200px) { .редактор-форм { grid-template-columns: 1fr; } }
.редактор-форм .предпросмотр iframe { width: 100%; height: 70vh; border: 0;
    background: #fff; }

ul.блоки { list-style: none; margin: 8px 0; padding: 0; }
ul.блоки .блок { display: flex; align-items: flex-start; gap: 8px;
    padding: 9px 11px; margin-bottom: 5px; border-radius: var(--r-sm);
    border: 1px solid var(--line); background: #fff;
    box-shadow: 0 1px 2px rgba(21,27,39,.04); }
ul.блоки .блок.тянется { opacity: .45; }
ul.блоки .ручка { cursor: grab; color: var(--ink-soft); user-select: none;
    font-size: 15px; line-height: 1.4; }
ul.блоки .имя { flex: 1; min-width: 0; }
ul.блоки .кнопки { display: flex; gap: 2px; flex: none; }
ul.блоки .свой-текст { flex: 2 1 260px; display: flex; flex-direction: column;
    gap: 4px; }
ul.блоки .свой-текст input, ul.блоки .свой-текст textarea { width: 100%;
    font-size: 13px; padding: 5px 7px; }
ul.блоки.узкие .блок { padding: 5px 10px; }

/* Свой блок на самой бумаге. */
.own-block { margin: 8px 0; }
.own-title { font-weight: 700; margin-bottom: 2px; }
.own-text { white-space: pre-wrap; }

/* Сертификат и промокод: две строки ввода над блоком оплаты. */
.pos-допы { margin: 10px 0; display: flex; flex-direction: column; gap: 6px; }
.pos-строка-ввода { display: flex; gap: 6px; }
.pos-строка-ввода input { flex: 1; min-width: 0; padding: 7px 9px; }
.pos-допы .принято { display: flex; align-items: center; gap: 8px;
    padding: 7px 11px; border-radius: var(--r-sm); background: #eaf5ef;
    color: var(--pos); font-size: 13px; font-weight: 600; }

/* Окно ввода вместо `prompt`: одно поле и кнопки-ответы. */
.pos-окно-нутро.узкое-окно { max-width: 460px; }
#окно-ввода #ввод-значение { width: 100%; font-size: 24px; padding: 11px 14px;
    text-align: right; font-family: var(--mono); border: 1px solid var(--line);
    border-radius: var(--r-sm); color: var(--ink); }
#окно-ввода #ввод-значение:focus { outline: 0; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
#окно-ввода .pos-кнопки { margin-top: 12px; flex-wrap: wrap; }
#окно-ввода .pos-кнопки .btn { flex: 1 1 auto; justify-content: center; }

/* Список доступных аппаратов в окне номера: строку жмут пальцем. */
#номер-список { margin-top: 10px; max-height: 320px; overflow-y: auto; }
#номер-список .номер { display: flex; justify-content: space-between;
    gap: 10px; padding: 10px 12px; border-radius: var(--r-sm);
    cursor: pointer; font-family: var(--mono); font-size: 13px;
    transition: background var(--move); }
#номер-список .номер:hover { background: var(--sub); }
#номер-список .номер .бу { font-family: inherit; color: var(--ink-soft); }
#окно-номера #номер-поле { width: 100%; font-size: 17px; padding: 11px 13px;
    font-family: var(--mono); border: 1px solid var(--line);
    border-radius: var(--r-sm); }

/* Карточка нового покупателя: подпись слева, поле справа — как в кассе
   МС. Сетка, а не две колонки флексом: подписи разной длины иначе
   разъезжаются, и глазу не за что зацепиться. */
.клиент-поля { display: grid; grid-template-columns: 150px 1fr;
    gap: 10px 14px; align-items: start; margin: 6px 0 14px; }
.клиент-поля .подпись { padding-top: 7px; font-weight: 600; }
.клиент-поля input, .клиент-поля textarea { width: 100%; font-size: 15px;
    padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-sm);
    font-family: inherit; color: var(--ink); }
.клиент-поля input:focus, .клиент-поля textarea:focus { outline: 0;
    border-color: var(--accent); box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.клиент-поля .узкое { max-width: 260px; }
.клиент-поля .dim { margin: 4px 0 0; font-size: 12px; }
/* ФИО тремя полями — фамилию у прилавка называют отдельно от имени. */
.клиент-поля .фио { display: grid; grid-template-columns: 1fr 1fr 1fr;
    gap: 8px; }
.клиент-поля .пол { display: flex; gap: 16px; padding-top: 6px; }
.клиент-поля .пол label { display: flex; align-items: center; gap: 6px;
    font-weight: 400; }
.btn.широкая { width: 100%; text-align: center; font-size: 16px;
    padding: 13px; font-weight: 600; }

.сдача { margin: 7px 0 2px; padding: 9px 12px; border-radius: var(--r-sm);
    background: #eaf5ef; color: var(--pos); font-size: 15px; font-weight: 600; }
.сдача.мало { background: #fbeeec; color: var(--neg); }

/* КАК ПЛАТЯТ — ЧЕТЫРЕ КНОПКИ, А НЕ ЧЕТЫРЕ ПОЛЯ. Кассир жмёт способ и
   вводит одну сумму; разбивка разворачивается только под «смешанную».
   Кружок радиокнопки прячем: за прилавком целятся в плашку целиком,
   а не в шестипиксельную точку. */
.pos-вид { display: flex; gap: 6px; margin-bottom: 10px; }
.pos-вид label { flex: 1; margin: 0; }
.pos-вид input { position: absolute; opacity: 0; width: 0; height: 0; }
.pos-вид span { display: block; text-align: center; padding: 10px 5px;
    border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
    font-size: 13px; cursor: pointer; user-select: none;
    transition: border-color var(--move), background var(--move),
                transform var(--move); }
.pos-вид span:hover { border-color: #c2d4ee; transform: translateY(-1px); }
.pos-вид input:checked + span { border-color: var(--accent);
    background: var(--accent-bg); color: var(--accent-dk); font-weight: 600;
    transform: none; }
.pos-вид input:focus-visible + span { outline: 2px solid var(--accent);
    outline-offset: 1px; }

.pos-оплата .pos-вид { display: grid; gap: 6px;
    grid-template-columns: repeat(3, minmax(0, 1fr)); }
#строка-банк .pos-вид { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Остаток к разнесению — единственное число, которое кассир иначе
   считал бы в уме при очереди. */
.остаток { margin: 8px 0 2px; padding: 9px 12px; border-radius: var(--r-sm);
    background: var(--accent-bg); color: var(--accent-dk);
    font-size: 14px; font-weight: 600; }
.остаток.мало { background: #fbeeec; color: var(--neg); }

/* Свёрнутая сборка чека в истории: внутренняя таблица без рамок, чтобы
   раскрытая лента читалась как продолжение строки, а не как второй
   документ. */
tr.свёрнутая details { margin: 4px 0 2px; }
tr.свёрнутая table.подробно { width: 100%; margin-top: 6px; }
tr.свёрнутая table.подробно td { border: 0; padding: 2px 8px 2px 0;
    font-size: 12px; }

/* Цена в строке чека: поле, но не кричащее — обычно её не трогают.
   Рамка появляется по наведению и в фокусе. */
.цена-строки { width: 100%; max-width: 110px; text-align: right;
    border: 1px solid transparent; border-radius: var(--r-xs); padding: 4px 7px;
    background: transparent; font-size: inherit; color: var(--ink);
    transition: border-color var(--move), box-shadow var(--move); }
.цена-строки:hover { border-color: var(--line); background: #fff; }
.цена-строки:focus { outline: none; border-color: var(--accent);
    background: #fff; box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

/* ── Меню разделов кассы ──────────────────────────────────────────────
   Разделов девять, в строку они не помещаются. Гамбургер и панель
   поверх экрана — как в кассе МойСклада, к которой кассиры привыкли. */
.касса-бургер { display: inline-flex; align-items: center; gap: 9px;
    height: 32px; padding: 0 13px 0 10px; margin-right: 6px;
    border: 1px solid rgba(255,255,255,.18); border-radius: var(--r-sm);
    background: rgba(255,255,255,.06); color: #dbe3ef; cursor: pointer;
    font-family: inherit; font-size: 13px;
    transition: border-color var(--move), background var(--move); }
.касса-бургер .полоски { display: flex; flex-direction: column; gap: 4px;
    width: 16px; }
.касса-бургер .полоски span { display: block; height: 2px; background: #c9d4e3;
    border-radius: 2px; }
.касса-бургер b { font-weight: 500; }
.касса-бургер:hover { border-color: rgba(255,255,255,.4);
    background: rgba(255,255,255,.14); }

.касса-меню { position: fixed; inset: 0; z-index: 40;
    background: rgba(15, 23, 32, .35); }
.касса-меню-панель { display: flex; flex-direction: column;
    width: 280px; height: 100%; background: var(--dark);
    box-shadow: 6px 0 30px rgba(21, 27, 39, .35); overflow-y: auto;
    animation: выехало 220ms cubic-bezier(.2,.7,.3,1) both; }
@keyframes выехало { from { transform: translateX(-16px); opacity: 0; } }
.касса-меню .пункт { display: block; width: 100%; text-align: left;
    padding: 15px 22px; border: 0; background: transparent; color: #fff;
    font-size: 17px; cursor: pointer; text-decoration: none; }
.касса-меню .пункт:hover { background: rgba(255, 255, 255, .14); }
.касса-меню .пункт b { margin-left: 6px; opacity: .85; }
.касса-меню .пункт.снизу { margin-top: auto;
    border-top: 1px solid rgba(255, 255, 255, .2); font-size: 15px; }
.касса-меню-кто { padding: 16px 22px 10px; color: #fff;
    border-top: 1px solid rgba(255, 255, 255, .2); }
.касса-меню-кто b { display: block; }
.касса-меню-кто .dim { color: rgba(255, 255, 255, .75); font-size: 13px; }

/* Название текущего раздела: кассир должен видеть, где он. */
.pos-заголовок { display: flex; align-items: center; gap: 12px;
    margin: 2px 0 11px; font-size: 22px; font-weight: 600; letter-spacing: -.022em; }

/* Отчёт по смене — читается сверху вниз, как чековая лента. */
.отчёт-смены { max-width: 520px; }
.отчёт td { padding: 4px 8px; border: 0; }
.отчёт tr.итожная td { padding-top: 10px; font-size: 15px; }
.отчёт tr.крупная td { font-size: 18px; border-top: 1px solid var(--line-soft);
    padding-top: 12px; }

/* Помощь: вопрос — ответ, без картинок и без ссылок наружу. */
.помощь dt { margin-top: 14px; font-weight: 600; }
.помощь dd { margin: 4px 0 0; color: var(--ink-soft); }

/* Заголовок смены в ленте истории: лента режется по сменам, иначе
   вчерашний вечер и сегодняшнее утро сливаются в одно. */
/* Заголовок смены в ленте — на подложке, как заголовок дня в списках
   учёта: одна и та же мысль «дальше другой отрезок времени». */
.grid.лента tr.лента-смена td { padding: 10px 10px 8px;
    border-bottom: 1px solid var(--line-soft); background: var(--sub); }
.grid.лента tr.лента-смена b { font-size: 15px; }

/* Поиск по истории чеков: строка и галка «все точки» в одну линию. */
.pos-поиск-чеков { display: flex; gap: 10px; align-items: center;
    margin-bottom: 12px; }
.pos-поиск-чеков input[name="q"] { flex: 1; font-size: 16px; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
    font-family: inherit; color: var(--ink);
    transition: border-color var(--move), box-shadow var(--move); }
.pos-поиск-чеков input[name="q"]:focus { outline: none;
    border-color: var(--accent); box-shadow: 0 0 0 3px rgba(36,82,143,.15); }
.pos-поиск-чеков .галка { display: flex; align-items: center; gap: 6px;
    white-space: nowrap; font-size: 14px; color: var(--ink-soft); }
.pos-ещё { padding: 10px 0 2px; text-align: center; }

/* Выбор печатной формы прямо в строке истории чеков. */
.печать-чека { font-size: 12px; padding: 4px 7px; border-radius: var(--r-xs);
    border: 1px solid var(--line); background: #fff; margin-right: 6px;
    font-family: inherit; }

/* Замечание кассиру: продано, но карточку пора поправить. Не красное —
   ошибки тут нет, есть повод сказать старшему. */
.замечание { margin: 8px 0 0; padding: 9px 12px; border-radius: var(--r-sm);
    background: var(--warn-bg); color: var(--warn-ink); font-size: 13px; }

.pos-действия-чека { display: flex; align-items: flex-end; gap: 8px;
    flex-wrap: wrap; margin-top: 10px; }
.скидка-поле { display: flex; flex-direction: column; gap: 3px;
    font-size: 12px; color: var(--ink-soft); }
.скидка-поле input { border: 1px solid var(--line); border-radius: var(--r-sm);
    padding: 6px 9px; font-family: var(--mono); text-align: right; width: 76px; }
.цена-возврата { margin-left: 24px; font-size: 12px; color: var(--ink-soft); }
.цена-возврата input { border: 1px solid var(--line); border-radius: var(--r-xs);
    padding: 4px 8px; font-family: var(--mono); text-align: right; }
.без-чека { margin-top: 14px; }
.без-чека summary { cursor: pointer; }
.дим { color: var(--ink-soft); }

/* Зачёт предоплаты при выдаче заказа: число, ради которого кассир сюда
   и смотрит. */
.зачёт { margin-bottom: 10px; padding: 10px 13px; border-radius: var(--r-sm);
    background: var(--accent-bg); color: var(--accent-dk); font-size: 13px; }
.зачёт .крупно { font-size: 19px; font-weight: 700; margin-top: 4px; }

/* Выбор печатной формы: плитками, чтобы видеть все шестнадцать разом. */
.формы { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.форма-плитка { display: flex; flex-direction: column; gap: 2px;
    padding: 11px 14px; border: 1px solid var(--line); border-radius: var(--r);
    background: #fff; min-width: 200px; color: var(--ink);
    box-shadow: 0 1px 2px rgba(21,27,39,.04);
    transition: border-color var(--move), transform var(--move), box-shadow var(--move); }
.форма-плитка:hover { transform: translateY(-1px); box-shadow: var(--shadow-hi); }
.форма-плитка:hover { border-color: var(--accent); text-decoration: none; }
.форма-плитка.на { border-color: var(--accent); background: var(--accent-bg); }
.форма-плитка .dim { font-size: 12px; }

/* ── Каркас кассы ────────────────────────────────────────────────────────
   Касса живёт без бокового меню: за прилавком в закупки и отчёты не
   ходят, а промах мимо кнопки уводил кассира в чужую работу с очередью
   за спиной. Остаётся шапка «где мы и что в ящике» и рабочее поле. */
/* КАССА ЗАНИМАЕТ ЭКРАН ЦЕЛИКОМ, а не жмётся к левому верхнему углу.
   Пока карточки были высотой по своему содержимому, нижняя половина
   экрана пустовала, а каталог с чеком заканчивались там, где кончились
   строки, — владелец так и сказал: «блоки влево уехали». За прилавком
   монитор один и он весь наш: каталог, чек и оплата тянутся во всю
   высоту, а прокрутка живёт ВНУТРИ колонок. Тогда «Пробить чек» и итог
   всегда на одном и том же месте, и глаз их не ищет. */
body.касса-целиком { margin: 0; background: var(--bg);
    display: flex; flex-direction: column; min-height: 100vh; }
/* ОТСТУП ПОД БОКОВОЕ МЕНЮ КАССЕ НЕ НУЖЕН — меню у неё нет вовсе.
   Рабочее поле кассы это тоже <main>, и общий отступ под меню учёта
   доставался ему молча: слева пустовала полоса в двести с лишним
   пикселей, из-за которой весь экран выглядел сдвинутым. Тянулось это
   с тех пор, как касса переехала в свой каркас. */
.касса-поле { flex: 1 1 auto; min-height: 0; display: flex;
    flex-direction: column; margin-left: 0; }
/* Растягивается ТОЛЬКО рабочий экран (он прямой ребёнок поля), а не
   первый попавшийся блок: окна и полосы над ним должны остаться
   высотой по содержимому. */
.касса-поле > .pos { flex: 1 1 auto; min-height: 0; align-items: stretch; }
.pos > .card { display: flex; flex-direction: column; min-height: 0; }
/* Каталог листается сам по себе: его список длиннее любого чека. */
.pos-каталог .pos-плитки { flex: 1 1 auto; min-height: 0; max-height: none; }
/* Итог и кнопки чека прижаты к низу колонки — там их и ищут. */
.pos-корзина { overflow-y: auto; }
.pos-корзина .pos-итог { margin-top: auto; }
.pos-справа { overflow-y: auto; }
/* «ПРОБИТЬ ЧЕК» НЕ УЕЗЖАЕТ. Правая колонка длинная — покупатель, баллы,
   сертификат, промокод, способ, сдача, — и главная кнопка экрана
   оказывалась за краем: чтобы пробить чек, надо было сперва прокрутить
   до неё. Прилипает ко дну колонки, а не страницы. */
.pos-справа .pos-кнопки { position: sticky; bottom: 0; z-index: 2;
    margin-top: 13px; padding: 10px 0 2px; background: var(--panel);
    box-shadow: 0 -8px 12px -8px rgba(21,27,39,.18); }

/* ВЕРХНЯЯ ПАНЕЛЬ КАССЫ ТЁМНАЯ — это то немногое, что владелец принял
   сразу («верхняя панель кассы хорошо»). Смысл не в красоте: за
   прилавком экран видят боковым зрением, и тёмная полоса отделяет
   «где я и что в ящике» от рабочего поля быстрее любой рамки. */
.касса-шапка { display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; padding: 11px 16px; background: var(--dark);
    color: #e3e9f2; border: 0; border-radius: var(--r);
    margin: 12px 12px 0; position: sticky; top: 12px; z-index: 20;
    box-shadow: 0 2px 6px rgba(21,27,39,.12), 0 16px 34px -20px rgba(21,27,39,.45); }
.касса-где { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.касса-где b { font-size: 17px; font-weight: 600; }
.касса-кто { display: flex; align-items: center; gap: 12px; }
.касса-кто .учёт { text-decoration: underline dotted; }
/* Всё, что лежит НА тёмной полосе, перекрашивается здесь, а не в своих
   местах: иначе правка общего чипа однажды сделает его невидимым. */
.касса-шапка .dim { color: #8996ac; }
.касса-шапка a.dim:hover { color: #fff; }
.касса-шапка .chip.ok { background: rgba(79,175,133,.16); color: #7fc79b; }
.касса-шапка .btn.plain { background: rgba(255,255,255,.06); color: #dbe3ef;
    border-color: rgba(255,255,255,.22); box-shadow: none; }
.касса-шапка .btn.plain:hover { background: rgba(255,255,255,.14);
    border-color: rgba(255,255,255,.34); }

.касса-поле { padding: 10px 12px 24px; }

/* Полоса состояния связи. Видна, только когда есть что сказать: «всё
   хорошо и очередь пуста» — это не новость. */
.связь { padding: 9px 14px; font-size: 13px; font-weight: 600;
    margin: 10px 12px 0; border-radius: var(--r-sm); }
.связь.нет { background: #fbeeec; color: var(--neg); }
.связь.ждёт { background: var(--warn-bg); color: var(--warn-ink); }

/* ВТОРАЯ ЦЕНА НАД БЛОКОМ ОПЛАТЫ. На витрине стоит цена за наличные;
   карта, рассрочка и кредит стоят магазину комиссии, и по ним цена
   обычная. Вопрос «а если картой?» задают ДО оплаты — и ответ на него
   кассир обязан видеть, не переключая режим туда-сюда ради справки. */
.вторая-цена { margin: 4px 0 9px; padding: 9px 12px; border-radius: var(--r-sm);
    background: var(--accent-bg); color: var(--accent-dk); font-size: 12.5px;
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.вторая-цена.безнал { background: var(--warn-bg); color: var(--warn-ink); }
/* Смешанная оплата: в чеке появилась карта, а цена ещё наличная. Касса
   не решает за продавца — скидку за наличные иногда дают и по карте, —
   но и не молчит: решение принимается глазами, а не задним числом. */
.вторая-цена.просит { background: #fbeeec; color: var(--neg); font-weight: 600; }
.вторая-цена.просит .btn { border-color: var(--neg); color: var(--neg);
    background: #fff; box-shadow: none; }
.вторая-цена b { white-space: nowrap; }
.вторая-цена .btn { margin-left: auto; }

/* Кому и в какой банк ушёл перевод по СБП. Поля появляются только там,
   где СБП вообще есть, — как и банк по рассрочке. */
#строка-сбп { display: grid; gap: 6px; margin: 6px 0; }

/* ============================================================================
   ВЫПАДАЮЩИЕ СПИСКИ.

   Открытый <select> рисует операционная система, и стилями до него не
   дотянуться ничем: на маке он выезжает серо-красной плашкой чужого вида
   поверх нашего экрана. Поэтому список мы рисуем свой (`select.js`), а
   настоящий <select> остаётся на месте и продолжает быть полем формы.

   Здесь описаны обе половины: закрытое поле и наша панель. Раздел стоит
   последним НАМЕРЕННО — правила должны лечь поверх отступов, заданных
   отбором, карточкой и кассой, иначе стрелка налезает на текст.
   ============================================================================ */

select {
  appearance: none; -webkit-appearance: none;
  cursor: pointer; padding-right: 30px;
}
/* СТРЕЛКА РИСУЕТСЯ КАРТИНКОЙ ФОНА, и оттого её приходится повторять для
   каждого поля, чьё правило задаёт `background` сокращённо: сокращённое
   свойство сбрасывает картинку в «нет», и стрелка молча пропадает. Так
   она и пропала в отборе с первого захода. Отступ справа — там же и по
   той же причине. */
select, .filter-form select, .pos-форма select, .auth-form select,
select.edit, .печать-чека, .pos-оплата select {
  padding-right: 30px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%238791a5' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 10px center;
}
/* Поле правки в карточке прозрачно до наведения — но стрелка нужна и там:
   иначе не отличить его от обычного текста. */
select.edit, .печать-чека { background-position: right 8px center; }
/* Пока список раскрыт, поле подсвечено — иначе непонятно, чей это список. */
select.sel-открыт { border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(36,82,143,.15); }

.sel-pop {
  position: fixed; z-index: 60; display: flex; flex-direction: column;
  max-width: 460px; padding: 5px; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-sm);
  box-shadow: 0 4px 10px rgba(21,27,39,.1), 0 24px 50px -18px rgba(21,27,39,.35);
  animation: список-вышел 140ms cubic-bezier(.2,.7,.3,1) both;
}
@keyframes список-вышел { from { opacity: 0; transform: translateY(-4px); } }
.sel-find { margin: 1px 1px 5px; flex: none; }
.sel-rows { overflow-y: auto; min-height: 0; }
.sel-row {
  padding: 7px 11px; border-radius: var(--r-xs); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ПОДСВЕЧЕНА ВСЕГДА РОВНО ОДНА СТРОКА — та, на которую приедет Enter.
   Мышь и стрелки ведут одну и ту же подсветку, иначе их получается две
   и непонятно, что выберется. */
.sel-row:hover, .sel-row.на { background: var(--accent-bg); color: var(--accent-dk); }
.sel-row.выбран { font-weight: 600; }
.sel-row.выбран::after { content: "✓"; float: right; margin-left: 12px;
                         color: var(--accent); font-weight: 400; }
.sel-row.off { color: var(--ink-dim); cursor: default; }
.sel-row.off:hover { background: none; color: var(--ink-dim); }
.sel-grp { padding: 9px 11px 4px; font-size: 10.5px; font-weight: 600;
           text-transform: uppercase; letter-spacing: .09em; color: var(--ink-dim); }
.sel-пусто { padding: 10px 11px; color: var(--ink-dim); }

/* ── Срок гарантии строкой ───────────────────────────────────────────────
   Класс в разметке был, а правил для него не было вовсе: поле и кнопка
   вставали друг под другом, и каждая строка таблицы занимала три. */
.строка-срока { display: flex; align-items: center; gap: 6px; margin: 0; }
.строка-срока input { width: 92px; text-align: right; font-family: var(--mono);
                      padding: 5px 9px; }
.строка-срока .btn { flex: none; }

/* Ветка дерева в настройках — гарантия и ставки бонусов. Знак «▸» это
   кнопка, и вести себя должен как кнопка: курсор, отклик, неслучайный
   размер (иначе в него не попасть). */
.г-ветка, .б-ветка {
  display: inline-block; width: 14px; cursor: pointer; user-select: none;
  color: var(--ink-dim); transition: color var(--move);
}
.г-ветка:hover, .б-ветка:hover { color: var(--accent); }

/* ── Шапка карточки, приглушённая строка, след ошибки ───────────────────
   ПЕРВЫЕ ДВА КЛАССА БЫЛИ В ШАБЛОНАХ, НО НЕ БЫЛИ В СТИЛЯХ. `.card-head`
   стоит на четырёх экранах, `.muted` — на шести, и всё это время они не
   делали ничего: заголовок карточки выглядел как обычный текст, а
   «приглушённая» строка — как обычная. Поймано при сборке экрана ошибок;
   ровно та порода мелочей, ради которой затевается обход разделов. */
.card-head {
  padding: 11px 16px; border-bottom: 1px solid var(--line);
  font-weight: 600; display: flex; align-items: baseline; gap: 10px;
}
.card-head .hint { margin: 0; font-weight: 400; }
.card:not(.flush) > .card-head { padding: 0 0 9px; margin-bottom: 10px; }
.grid tr.muted td { color: var(--ink-dim); }

/* След питона. Ширины экрана ему не хватает никогда, поэтому прокрутка
   своя: страница целиком уезжать вбок не должна. */
pre.trace {
  margin: 0; padding: 12px 16px; overflow-x: auto;
  font-family: var(--mono); font-size: 12px; line-height: 1.5;
  color: var(--ink); white-space: pre;
}

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

   Ставим по центру ВМЕСТЕ С ЗАГОЛОВКОМ — иначе «Касса» осталась бы у
   левого края, а карточка уехала в середину, и это хуже исходного.

   Только прямые дети поля: `.pos-узкая` есть и внутри окна закрытия
   смены, а окно центрируется само и в этой правке не нуждается. */
.касса-поле > .doc-h1,
.касса-поле > .pos-узкая {
  width: 100%; max-width: 620px;
  margin-left: auto; margin-right: auto;
}
.касса-поле > .doc-h1 { margin-top: 20px; }

/* ── Трейд-ин: форма приёма устройства ──────────────────────────────────
   Полей полтора десятка, и в столбик они превращаются в анкету на два
   экрана. Сетка в три колонки: модель, дефекты и кнопки занимают строку
   целиком, остальное встаёт по три в ряд.

   Человек стоит у прилавка и ждёт, пока мы перепишем его телефон, —
   форма должна помещаться на экран без прокрутки. */
.трейд-форма {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px 14px; align-items: start;
}
.трейд-форма > label { display: flex; flex-direction: column; gap: 4px;
                       font-size: 13px; color: var(--ink-soft); }
.трейд-форма > label > input,
.трейд-форма > label > select { font-size: 15px; }
.трейд-форма .широкое { grid-column: 1 / -1; }
.трейд-форма .ставка { flex-direction: row; align-items: baseline; gap: 8px;
                       font-size: 14px; color: var(--ink); }
.трейд-форма .ставка .hint { margin: 0; }
.трейд-форма > div.широкое { display: flex; align-items: center; gap: 12px; }
.трейд-форма > div.широкое .hint { margin: 0; }
@media (max-width: 820px) {
  .трейд-форма { grid-template-columns: 1fr 1fr; }
}

/* Подсказка-плашка: не тревога и не удача, просто «как это устроено».
   Тон нейтральный — жёлтым в системе помечено то, что требует действия. */
.hint-card { background: var(--panel); border: 1px solid var(--line);
             color: var(--ink-soft); }
