/* ЧЕРНОВИК основы (подпроект 0), итерация 2. Имена классов прежние; меняются
 * токены, общие правила и каркас. Принципы:
 *   1. Одна рамка на экран — боковое меню. Внутри — белый лист: карточка с
 *      рамкой только там, где она группирует таблицу или форму с заголовком;
 *      панели фильтров и ряды кнопок — без коробки.
 *   2. Все контролы ровно 32 px и стоят на одной линии; на сенсорном
 *      устройстве — 40 px (правило про палец на планшете сохранено там, где
 *      есть палец).
 *   3. Цифры — главный текст: табличные, справа, полужирные.
 *   4. Красный — только действие и тревога. Ссылки графитовые.
 *   5. Заголовки — текст с линейкой, не заливка; подписи — строчные, не капс.
 * Страничные блоки — из прежнего файла; их размеры, отступы и кегли приведены
 * к шкале после визуального прохода (см. разделитель ниже). */

:root {
  color-scheme: light;

  --primary: #e30613;
  --primary-dark: #b3050f;
  --primary-soft: #fdecec;
  --on-primary: #ffffff;
  --danger: #b3050f;
  --danger-soft: #fdecec;
  --green: #177a33;
  --green-soft: #eef8f1;
  --warn: #b45309;
  --warn-soft: #fdf6ec;

  --bg: #ffffff;
  --side: #faf9f7;
  --card: #ffffff;
  --text: #2b2a29;
  --muted: #6f6963;
  --border: #e7e2dd;
  --border-strong: #cdc6bf;

  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;

  --r1: 4px;
  --r2: 6px;
  --shadow: none;
  --fast: 120ms ease;

  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs: 13px;
  --fs-h2: 15px;
  --fs-h1: 17px;
  --fs-kpi: 22px;

  --ctl: 32px;      /* высота любого контрола */
  --side-w: 220px;
  --bar-h: 48px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  font-size: var(--fs);
  line-height: 1.45;
  background: var(--bg);
  color: var(--text);
  -webkit-text-size-adjust: 100%;
}

a { color: var(--text); text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
a:hover { color: var(--primary-dark); text-decoration-color: currentColor; }

:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r1); }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

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

.shell { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); min-height: 100vh; }

.side {
  background: var(--side);
  border-right: 1px solid var(--border);
  position: sticky; top: 0; height: 100vh; overflow: auto;
  padding: 0 0 var(--s4);
}
.side .brand { display: flex; align-items: center; height: var(--bar-h); padding: 0 var(--s4); border-bottom: 1px solid var(--border); margin-bottom: var(--s2); }
.side .brand .mark { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 10px; }
.side .brand .mark::before { content: ""; width: 12px; height: 12px; background: var(--primary); border-radius: 2px; flex: none; }
.side .brand .unit { display: none; }

.side nav { display: block; }
.side nav .g { font-size: var(--fs-sm); color: var(--muted); padding: var(--s4) var(--s4) var(--s1); }
.side nav a {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s2);
  padding: 7px var(--s4) 7px 13px;
  border-left: 3px solid transparent;
  color: var(--text); text-decoration: none; line-height: 1.3;
  transition: background var(--fast);
}
.side nav a:hover { background: var(--card); color: var(--text); }
.side nav a.on { border-left-color: var(--primary); background: var(--card); font-weight: 600; }
.side nav .count { font-size: var(--fs-xs); font-weight: 700; color: var(--primary); font-variant-numeric: tabular-nums; }

.main { min-width: 0; }
.bar {
  display: flex; align-items: center; gap: var(--s4);
  height: var(--bar-h); padding: 0 28px;
  border-bottom: 1px solid var(--border);
}
.bar h1 { font-size: var(--fs-h1); font-weight: 600; margin: 0; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar .who { margin-left: auto; font-size: var(--fs-sm); color: var(--muted); white-space: nowrap; }
.bar .who a { color: inherit; text-decoration: none; }
.bar .who a:hover { text-decoration: underline; }
.bar form { margin: 0; }
.bar button.link { font-size: var(--fs-sm); }
.wrap { padding: 20px 28px 40px; max-width: 1180px; }

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

h1 { font-size: var(--fs-h1); margin: 0 0 var(--s3); }
h2 { font-size: var(--fs-h2); font-weight: 600; margin: 0 0 var(--s3); letter-spacing: -.005em; }

/* --- Карточки и ряды --- */

.card { margin: 0 0 var(--s5); }
/* Рамку получает только карточка с заголовком: она группирует таблицу или
   форму. Ряд фильтров, ряд кнопок, справка — просто содержимое на листе. */
.card:has(> h2:first-child) {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--s3) var(--s4) var(--s4);
}
.card > h2:first-child { padding-bottom: var(--s2); border-bottom: 1px solid var(--border); margin-bottom: var(--s3); }
.card > :last-child { margin-bottom: 0; }

.row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3) var(--s4); }
/* Всё, что в ряду не поле и не кнопка (бейдж, счётчик, текст), центрируем на
   высоте контрола — иначе оно липнет к подписи над полем. Строка-форма внутри
   ячейки (.row.inline) из правила исключена: там высота контрола своя, ячейкина. */
.row:not(.inline) > :not(label):not(button):not(a.button):not(form):not(.badge) { align-self: flex-end; min-height: var(--ctl); display: inline-flex; align-items: center; }
/* Бейдж в ряду остаётся 22 px и стоит по центру зоны контрола, а не
   растягивается до её высоты правилом выше. Отступ считается от --ctl: на
   сенсорном экране контрол 40 px, и число 5 разъехалось бы с ним. */
.row > .badge { align-self: flex-end; margin-bottom: calc((var(--ctl) - 22px) / 2); }
.row > form.inline, .row > form.row { display: contents; }
form.card.row { padding-bottom: var(--s3); border-bottom: 1px solid var(--border); margin-bottom: var(--s5); }

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

label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--muted); }
input, select, textarea {
  font: inherit; font-size: var(--fs); color: var(--text); background: var(--card);
  height: var(--ctl); padding: 0 8px;
  border: 1px solid var(--border-strong); border-radius: var(--r1);
  transition: border-color var(--fast), box-shadow var(--fast);
}
/* Чекбокс и радиокнопка — не текстовое поле: без высоты контрола, рамки и
   отступов, иначе рисуются пустым квадратом 32 px. Акцент графитовый: красный —
   действие и тревога, а не «включено». */
input[type="checkbox"], input[type="radio"] { height: auto; width: auto; padding: 0; border: 0; accent-color: var(--text); vertical-align: middle; }
/* Подпись — колонка ради текстовых полей; чекбокс стоит рядом со своим текстом, а не над ним. */
label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) { flex-direction: row; align-items: center; gap: var(--s2); min-height: var(--ctl); }
input[type="date"] { min-width: 150px; }
input[type="number"] { max-width: 120px; }
input:hover, select:hover, textarea:hover { border-color: var(--muted); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
input:disabled, select:disabled { background: var(--side); color: var(--muted); }
textarea { height: auto; min-height: 100px; padding: 6px 8px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--fs-sm); }

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

button, a.button {
  font: inherit; font-size: var(--fs); font-weight: 500;
  height: var(--ctl); padding: 0 12px;
  border: 1px solid var(--border-strong); border-radius: var(--r1);
  background: var(--card); color: var(--text);
  cursor: pointer; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap;
  transition: background var(--fast), border-color var(--fast), color var(--fast);
}
button:hover, a.button:hover { border-color: var(--muted); background: var(--side); color: var(--text); }
button.primary, a.button.primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); font-weight: 600; }
button.primary:hover, a.button.primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: var(--on-primary); }
button.link { height: auto; background: none; border: 0; padding: 0; color: var(--text); font-weight: 400; text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
button.link:hover { background: none; color: var(--primary-dark); text-decoration-color: currentColor; }

/* Второстепенное действие рядом с главным: обычный вес, остальное как у кнопки. */
button.secondary, a.button.secondary { font-weight: 400; }

/* Мелкая кнопка — в строках таблиц и рядом с полями: высота как у полей в таблице. */
button.tiny { height: 28px; padding: 0 8px; font-size: var(--fs-sm); }

/* Узкое числовое поле: длительность фазы и норма на голову. Класс .tiny до этого
   действовал только на кнопки (button.tiny), и поле с ним оставалось широким. */
input.tiny { width: 88px; height: 28px; padding: 0 6px; font-size: var(--fs-sm); }

/* Крупная кнопка — единственное действие экрана (например, старт сверки). */
button.big, a.button.big { height: 44px; padding: 0 var(--s5); font-size: var(--fs-h2); }

button:disabled { opacity: .5; cursor: default; }
form.inline { display: inline; }
/* Форма-строка внутри ячейки таблицы или карточки: form.inline перебивает .row
   по специфичности, и без этого правила раскладка сваливается в inline, а
   td input { width: 100% } ставит контролы этажами. */
.row.inline { display: inline-flex; flex-wrap: nowrap; align-items: center; gap: var(--s2); vertical-align: middle; margin: 0; }
.row.inline > label { flex-direction: row; align-items: center; gap: var(--s1); white-space: nowrap; }
.row.inline > input, .row.inline > select { width: auto; }
/* Единственное поле в такой форме этажей не делает: пусть занимает ячейку
   целиком, иначе название завода на /mills обрезается на полуслове. Форме при
   этом нужен блочный flex — inline-flex сжимается по содержимому, и процент
   внутри него считать не от чего. */
.row.inline:has(> input:only-child), .row.inline:has(> select:only-child) { display: flex; }
.row.inline > input:only-child, .row.inline > select:only-child { width: 100%; }
/* На сенсорном экране контролы выше: по кнопке попадают пальцем. */
@media (pointer: coarse) { :root { --ctl: 40px; } }

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

.table-scroll { overflow-x: auto; margin: 0 0 var(--s3); }
table { width: 100%; border-collapse: collapse; font-size: var(--fs); }
th { padding: 0 10px 7px; text-align: left; font-size: var(--fs-sm); font-weight: 500; color: var(--muted); white-space: nowrap; border-bottom: 1px solid var(--border-strong); }
td { padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--side); }
th:first-child, td:first-child { padding-left: 0; }
th:last-child, td:last-child { padding-right: 0; }
td select, td input { height: 28px; padding: 0 6px; font-size: var(--fs-sm); width: 100%; }
/* Числовое поле в таблице стоит под правым заголовком «Кг» — и само по правому краю. */
td:has(> input[type="number"]) { text-align: right; }
td > input[type="number"] { width: 120px; text-align: right; font-variant-numeric: tabular-nums; }
td form { margin: 0; }
/* nowrap: kgRu() ставит неразрывный пробел между разрядами, а « кг» после числа —
   обычный, и в тесной таблице число переносится «8 000 / кг». */
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.num { font-weight: 600; }
th:empty { width: 1%; }
tr.off td { color: var(--muted); }
tr.done td { color: var(--green); }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--fs-sm); background: var(--side); padding: 1px 6px; border-radius: 3px; }

.facts { width: 100%; max-width: 560px; }
.facts td { padding: 7px 0; }
.facts tr:hover td { background: none; }
.facts td:first-child { color: var(--muted); }
.facts td:last-child { font-weight: 600; text-align: right; }

/* --- Состояния --- */

.badge { display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 11px; font-size: var(--fs-xs); font-weight: 600; border: 1px solid var(--border-strong); background: var(--card); color: var(--text); white-space: nowrap; }
.badge.match { border-color: transparent; color: var(--green); background: var(--green-soft); }
.badge.wait { color: var(--muted); }
.badge.warn-badge { border-color: transparent; color: var(--warn); background: var(--warn-soft); }
.badge.bad, .badge.mismatch { border-color: transparent; color: var(--danger); background: var(--danger-soft); }
.ok { color: var(--green); }
.warn { color: var(--warn); }
.error { color: var(--danger); background: var(--danger-soft); border-left: 3px solid var(--danger); padding: var(--s2) var(--s3); margin: 0 0 var(--s4); }
.muted { color: var(--muted); }
.hint { color: var(--muted); font-size: var(--fs-sm); margin: var(--s2) 0; }
.hint.ok { color: var(--green); }
.hint.error { color: var(--danger); }

/* Пять шагов: ровные ячейки одной высоты, шаг «ваш» — красная отметка сверху. */
.chain-five { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--s3); }
.chain-step { padding: var(--s3) 0 0; border-top: 2px solid var(--border); font-size: var(--fs-sm); min-height: 84px; }
.chain-step b { display: block; font-weight: 600; font-size: var(--fs); margin: 2px 0; }
.chain-step .muted { display: block; }
.chain-step.mine { border-top-color: var(--primary); }
.chain-n { font-size: var(--fs-sm); color: var(--muted); }
.chain-step.mine .chain-n { color: var(--primary-dark); font-weight: 700; }

/* Плитки сводки — одна полоса цифр, единственный крупный элемент страницы. */
.report-grid, .report-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s4); margin: 0 0 var(--s5); }
.report-tile { padding: 0 0 0 var(--s3); border-left: 2px solid var(--border); }
.report-tile .value { font-size: var(--fs-kpi); font-weight: 600; line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.report-tile .value.bad { color: var(--danger); }
.report-tile .label { font-size: var(--fs-sm); color: var(--muted); margin-top: 3px; }

/* --- Узкий экран --- */

@media (max-width: 900px) {
  .shell { display: block; }
  .side { position: static; height: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: 0; }
  .side .brand { height: 44px; padding: 0 var(--s3); margin: 0; border-bottom: 1px solid var(--border); }
  .side nav { display: flex; overflow-x: auto; padding: 0 var(--s1); scrollbar-width: none; }
  .side nav::-webkit-scrollbar { display: none; }
  .side nav .g { display: none; }
  .side nav a { border-left: 0; border-bottom: 2px solid transparent; padding: 10px 10px; white-space: nowrap; }
  .side nav a.on { border-bottom-color: var(--primary); background: none; }
  .bar { height: auto; padding: var(--s3); flex-wrap: wrap; row-gap: var(--s1); }
  .bar h1 { width: 100%; white-space: normal; }
  .bar .who { margin-left: 0; }
  .bar form { margin-left: auto; }
  .wrap { padding: var(--s4) var(--s3) var(--s6); }
  .row > label, .row > button, .row > a.button { flex: 1 1 100%; }
  input[type="number"] { max-width: none; }
  .table-scroll td, .table-scroll th { white-space: nowrap; }
  .chain-five { grid-template-columns: 1fr; gap: 0; }
  .chain-step { min-height: 0; padding: var(--s2) 0; border-top: 1px solid var(--border); }
  .chain-step.mine { border-top: 2px solid var(--primary); }
  .editor-side { flex: 1 1 100%; }
  .demo-bar { padding: var(--s2) var(--s3); }
}

/* --- Печать --- */

@media print {
  .side, .bar .who, .bar form, .demo-bar, .no-print { display: none !important; }
  .shell { display: block; }
  body { background: #fff; color: #000; }
  .card:has(> h2:first-child) { border-color: #999; break-inside: avoid; }
}

/* =====================================================================
   Ниже — страничные блоки прежнего admin.css. Структура прежняя; размеры,
   отступы и кегли приведены к шкале токенов после визуального прохода
   (см. .superpowers/sdd/…/task-4-report.md).
   ===================================================================== */

/* Служебный класс: им редактор плана прячет панель свойств, поле бункеров и
   инструменты в режиме просмотра. Правила у него не было вовсе — карточка
   «Точка» висела всегда, поле бункеров не убиралось из тулбара, а зритель
   видел полный набор инструментов. Тест этого не ловил: он проверяет класс в
   classList, а стили jsdom не считает.

   !important здесь осознанно. Спрятано — это состояние, которое обязано
   побеждать любой display компонента (.default-bins ставит flex, .card —
   block), и полагаться на порядок правил при равной специфичности здесь
   опаснее: та же ловушка уже описана про порядок состояний в схеме проезда. */
.hidden {
  display: none !important;
}

/* Строка реквизитов «свойство: значение» над формой. Правило жило только в
   templates/trip.css — а это стили офлайн-файла сверки, на страницы админки они
   не подключаются. Здесь класс использовался пятью местами вообще без
   оформления, и подписи слипались в одну строку. */
.trip-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s4);
  color: var(--muted);
  font-size: var(--fs);
  margin-bottom: var(--s3);
}

.trip-meta b {
  color: var(--text);
  font-weight: 600;
}

/* День в форме потребности: семь свёрнутых блоков подряд без разделителей
   читаются как сплошная лента. */
.day-block {
  border: 1px solid var(--border);
  border-radius: var(--r2);
  margin-bottom: var(--s4);
  background: var(--card);
}

.day-block > summary {
  padding: var(--s2) var(--s4);
  cursor: pointer;
  font-size: var(--fs);
}

.day-block[open] > summary {
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--s2);
}

.day-block .table-scroll {
  padding: 0 var(--s4) var(--s1);
}

.nowrap {
  white-space: nowrap;
}

/* Полоса показа. Липнет к верху и красная не случайно: человек, вошедший в
   чужую роль, должен видеть это всё время, а не вспоминать. На админских
   страницах красный — фирменный акцент, и здесь он работает как «внимание»,
   а не как отказ: сирены на этих экранах нет, путать не с чем. */
.demo-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  background: var(--primary);
  color: var(--on-primary);
  /* Полоса стоит над верхней полосой во всю ширину колонки: скругление и
     отступ снизу остались от прежнего места внутри страницы. Боковой отступ —
     как у .bar и .wrap (28 px, поле каркаса, не шаг шкалы). */
  padding: var(--s2) 28px;
  border-radius: 0;
  margin-bottom: 0;
  font-size: var(--fs);
}

/* Кнопки полосы держим вместе справа: «Дальше» — основное действие показа,
   и искать её глазами по всей ширине не должно приходиться. */
.demo-acts {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-left: auto;
}

.demo-bar button.link {
  color: var(--on-primary);
  text-decoration: underline;
  font-weight: 600;
}

.demo-step { margin-bottom: var(--s4); }

.demo-head {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  flex-wrap: wrap;
  margin-bottom: var(--s1);
}

.demo-n {
  font-size: var(--fs-sm);
  color: var(--muted);
  min-width: 1.2em;
}

.ok-mark {
  color: var(--green);
  font-weight: 600;
  white-space: nowrap;
}

.warn-mark {
  color: var(--danger);
  font-weight: 600;
  white-space: nowrap;
}

/* Карточка появляется, когда рейс погружен целиком, и несёт отмену погрузки.
   Тот же вид, что у .now-load.done выше на этой же странице: зелёная полоса слева и
   светло-зелёная заливка — исход, а не фирменный акцент, с красным «отказа» не
   путается. Отступ внутри — свой, как у .error; карточка без h2 отступов не имеет,
   и без него полоса ложилась вплотную к кнопке. */
.loaded-mark {
  border-left: 3px solid var(--green);
  background: var(--green-soft);
  padding: var(--s2) var(--s3);
}

/* Марка корма в таблицах графика, балансировки и дашборда изготовления. Правило
   тоже жило только в templates/trip.css: марка, которую в этих таблицах ищут
   глазами в первую очередь, ничем не выделялась. */
.sheet-recipe {
  font-weight: 600;
  color: var(--text);
}

/* --- Задание на погрузку --- */
/* Одно дело на экране: какую секцию из какого силоса грузить сейчас. У
   грузчика заняты руки, разбирать таблицу ему негде. */

.load-head {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin-bottom: var(--s3);
}

.load-head .bar-progress {
  margin-left: auto;
  color: var(--muted);
  font-size: var(--fs);
}

.now-load {
  display: flex;
  align-items: center;
  gap: var(--s4);
  flex-wrap: wrap;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--s4);
}

.now-load.done {
  border-color: var(--green);
  background: var(--green-soft);
}

/* Номер секции кричит — но графитом. Красный здесь означает тревогу, и красить
   им обычное состояние значит обесценить сигнал. */
.cur-num {
  flex: none;
  width: 76px;
  text-align: center;
  background: var(--text);
  color: var(--card);
  border-radius: var(--r2);
  padding: var(--s2) var(--s1);
}

.cur-num b {
  display: block;
  font-size: 34px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.cur-num span {
  font-size: var(--fs-xs);
  opacity: 0.75;
}

.cur-body {
  flex: 1;
  min-width: 200px;
}

.cur-from {
  font-size: var(--fs-h1);
  font-weight: 700;
  line-height: 1.25;
}

.cur-what {
  font-size: var(--fs);
  color: var(--muted);
  margin-top: 2px;
}

.now-load form {
  flex: none;
}

/* --- Свёртки --- */

.fold {
  border: 1px solid var(--border);
  border-radius: var(--r2);
  margin-top: var(--s3);
  background: var(--card);
}

.fold > summary {
  padding: var(--s2) var(--s4);
  font-size: var(--fs);
  font-weight: 600;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  gap: var(--s2);
}

.fold[open] > summary {
  border-bottom: 1px solid var(--border);
}

/* Отступы на теле свёртки, а не на детях: правило с id перебило бы их. */
.fold-body {
  padding: var(--s3) var(--s4);
}

ul.steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

ul.steps li {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-top: 1px solid var(--border);
  font-size: var(--fs);
}

ul.steps li:first-child {
  border-top: none;
}

ul.steps li.done {
  color: var(--muted);
}

.step-num {
  flex: none;
  width: 22px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  border-radius: var(--r1);
  background: var(--bg);
  border: 1px solid var(--border);
  font-weight: 700;
  font-size: var(--fs-sm);
}

.step-what {
  flex: 1;
  min-width: 0;
}

.step-state {
  flex: none;
  white-space: nowrap;
}

/* --- Строки размещения партии --- */

.place {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}

.place-row {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
}

/* Строка стоит в ячейке таблицы, где поля и списки 28 px (td select, td input);
   кнопка того же ряда — той же высоты, иначе торчит на 2 px сверху и снизу. */
.place button {
  height: 28px;
  font-size: var(--fs-sm);
}

/* --- Остаток корма на заводах, одной строкой --- */
/* Над графиком это справка, а не таблица: колонок нет, сравнивать нечего, а
   место она занимать не должна — логист смотрит сюда мельком, собирая день. */

.stock-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stock-strip li {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  font-size: var(--fs);
}

/* --- Вместимости бункеров --- */

.cap-list {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.cap-list > label {
  flex-direction: row;
  align-items: center;
  gap: var(--s2);
}

.cap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--s2);
}

.cap-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.cap-row span {
  color: var(--muted);
  font-size: var(--fs);
}

.cap-row input {
  width: 100%;
}

/* --- Редактор плана площадки --- */

.editor {
  display: flex;
  gap: var(--s4);
  align-items: flex-start;
  flex-wrap: wrap;
}

.editor-main {
  /* Без этого правила колонка получает flex: 0 1 auto и не растягивается:
     холст схлопывается до своей min-width, а справа остаётся пустое место во всю
     ширину. min-width: 0 обязателен — флекс-элемент по умолчанию не сжимается
     уже своего содержимого, и широкая схема выдавливала бы страницу вбок. */
  flex: 1 1 520px;
  min-width: 0;
}

.editor-side {
  flex: 0 0 280px;
  min-width: 240px;
}

.readonly #order-text {
  background: var(--bg);
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
  margin-bottom: var(--s3);
}

.toolbar-gap {
  flex: 1;
}

.tools {
  display: flex;
  gap: var(--s1);
  flex-wrap: wrap;
}

/* В тулбаре все контролы высоты --ctl: мелкие кнопки (.tiny, 28 px) стояли рядом
   с полями 32 px, и стрелка «↶ отменить» упиралась в верх кнопки. Кнопки
   инструментов — обычные кнопки, своего размера у них нет. */
.toolbar button,
.toolbar input,
.toolbar select {
  height: var(--ctl);
}

button.tool.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--on-primary);
}

.route-row {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: 6px 0;
  border-top: 1px solid var(--border);
}

.route-row.active {
  font-weight: 600;
}

.route-row .link {
  margin-left: auto;
}

.route-name-input {
  flex: 1;
  min-width: 0;
}

.route-name-input:focus {
  border-color: var(--primary);
}

.swatch {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex: none;
}

.canvas {
  min-width: 0;
  aspect-ratio: 16 / 9;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  overflow: hidden;
}

.canvas svg {
  display: block;
  width: 100%;
  /* Высота холста задана пропорцией, а не содержимым: раньше высота бралась из
     viewBox, а viewBox считался из высоты — круг, из-за которого первый расчёт
     вида шёл по запасному значению. */
  height: 100%;
  touch-action: none;
}

.canvas svg text {
  user-select: none;
}

.canvas svg.editing [data-id],
.canvas svg.tool-select [data-id] {
  cursor: pointer;
}

.canvas svg.tool-turn,
.canvas svg.tool-route [data-id] {
  cursor: crosshair;
}

.canvas svg.tool-select {
  cursor: default;
}

.canvas svg .in-route {
  opacity: 0.9;
}

.canvas svg .seq {
  font-weight: 700;
}

.canvas svg .selected {
  filter: drop-shadow(0 0 0 2px var(--primary));
}

.default-bins {
  display: flex;
  /* Это <label>, а глобальное правило для label раскладывает содержимое
     колонкой. Не сбросив направление, получаем «бункеров», поле, «по», поле и
     «кг» пятью этажами и тулбар в треть экрана. */
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}

.default-bins input {
  width: 70px;
}

#inspector label {
  margin-bottom: var(--s2);
}

#inspector input {
  width: 100%;
}

#inspector button {
  width: 100%;
  margin-top: var(--s2);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1);
  margin: var(--s2) 0;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  padding: 3px var(--s2);
  border-radius: 20px;
  background: var(--bg);
  border: 1px solid var(--border);
  font-size: var(--fs);
  white-space: nowrap;
}

.chip-x {
  /* Крестик рисуется кнопкой, поэтому с него надо снять всё кнопочное:
     иначе рамка и минимальная высота 34px раздувают каждую фишку, и девять
     точек маршрута занимают четыре ряда. */
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  min-height: 0;
  line-height: 1;
  font-size: var(--fs-h2);
  cursor: pointer;
  color: var(--muted);
}

.chip-x:hover {
  color: var(--danger);
}

.editor-actions {
  display: flex;
  gap: var(--s2);
  margin-top: var(--s3);
}

.editor-actions button {
  /* Кнопка в блоке одна, и flex: 1 растягивал её во всю ширину карточки:
     обычное действие кричало громче самой схемы. */
  flex: 0 0 auto;
}

/* Страница без пользователя — вход: меню нет, лист во всю ширину, форма по центру. */
.shell.solo { grid-template-columns: minmax(0, 1fr); }
.shell.solo .wrap { max-width: 480px; margin: 40px auto 0; }

/* Имя сервиса в меню — ссылка на главную, но без подчёркивания ссылок. */
.side .brand .mark { text-decoration: none; color: inherit; }

/* --- Сверка на телефоне: QR в карточке заявки --- */
.scan-qr { margin: var(--s4) 0; max-width: 420px; }
.scan-qr svg { display: block; width: 280px; height: 280px; margin: var(--s3) 0; }
