/* ============================================================
   СМ · Производство — оформление
   Подключается ПОСЛЕ styles.css и задаёт единый визуальный слой.

   Почему отдельным файлом: styles.css рос слоями (базовые правила,
   поверх — второй :root с зелёной темой, потом дописанные блоки).
   Разбирать его целиком рискованно — там правила для страниц, которые
   легко не заметить. Поэтому здесь только то, что задаёт вид:
   шрифт, токены, типографика, таблицы, элементы управления.
   Разметка и классы не менялись.

   27.08.2026 — СВЕТЛАЯ ТЕМА по его просьбе («больно темно, мрачно;
   светлый фон, тёмный шрифт, минимализм, пусть дорого выглядит»).
   Тёмным остаётся ТОЛЬКО сайдбар — фирменный тёмно-зелёный якорь,
   на нём живёт логотип; весь контент — белые панели на светлом фоне,
   мягкие многослойные тени, тот же зелёный акцент, но глубже —
   на белом ему нужен контраст. Прежняя тёмная тема жила тут же и
   при желании восстанавливается из бэкапов до 27.08.
   ============================================================ */

/* ---------- Шрифт ----------
   Inter лежит рядом (public/fonts), а не тянется с CDN: приложение
   локальное и должно работать без интернета. Раньше Inter был объявлен
   в CSS, но в системе его нет — всё рисовалось системным шрифтом,
   хотя плотный трекинг заголовков рассчитан именно на Inter. */
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('/fonts/inter-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('/fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- Токены ----------
   Единственный источник правды по цвету. В styles.css два блока :root
   идут подряд и второй перекрывает первый — здесь третий, финальный.
   Зелёный на белом взят ГЛУБЖЕ прежнего акцента: светлый #4cc9a0 на
   белом фоне не читается (контраст ~2:1), у #157055 — 5,6:1. */
:root {
  --bg:        #f5f7f6;
  --panel:     #ffffff;
  --ink:       #17211c;
  --ink-2:     #3e4b45;
  --muted:     #71807a;
  --line:      #e3e9e6;
  --line-soft: #eef2f0;

  --accent:    #157055;
  --accent-lo: #e9f4ef;
  --accent-2:  #1e8a68;
  --warn:      #a9691b;
  --warn-lo:   #f8efdf;
  --danger:    #c0392f;
  --danger-lo: #faeceb;

  --radius:    10px;
  --radius-lg: 14px;
  /* Тени мягкие и многослойные — «дорогая» глубина без черноты. */
  --shadow:    0 1px 2px rgba(23,40,33,.05), 0 2px 10px rgba(23,40,33,.05);
  --shadow-md: 0 6px 20px rgba(23,40,33,.09);
  --shadow-lg: 0 24px 60px rgba(23,40,33,.18);

  /* Плотный инструмент: шаг 4px, без воздуха ради воздуха */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
}

/* ---------- Основа ---------- */
body {
  font-family: 'Inter', ui-sans-serif, system-ui, 'Segoe UI', Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  background: radial-gradient(1100px 480px at 85% -10%, #e6efe9 0%, transparent 60%), var(--bg);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'cv05' 1;   /* строчная l с хвостиком — меньше путаницы с I/1 */
}
/* На широком мониторе контент стоит ПО ЦЕНТРУ оставшегося места, а не
   прижат к сайдбару («всё съезжает налево» — его слова 27.08). */
main { padding: 30px 34px 56px; margin: 0 auto; }

h1 { font-size: 26px; font-weight: 700; letter-spacing: -.025em; color: var(--ink); margin: 0 0 3px; }
h2 { font-size: 16px; font-weight: 650; letter-spacing: -.012em; color: var(--ink); margin: 28px 0 10px; }
.sub { color: var(--muted); font-size: 13.5px; max-width: 78ch; margin: 0 0 20px; }

/* ---------- Боковое меню ----------
   Единственное тёмное место темы — фирменный тёмно-зелёный якорь,
   на нём логотип из гайдлайна (dark-версия). */
.sidebar {
  width: 246px;
  background: linear-gradient(168deg, #0f2b26 0%, #16403a 58%, #0d2621 100%);
  border-right: 0;
  box-shadow: 10px 0 30px rgba(12,40,34,.12);
}
.brand { padding: 24px 20px 18px; font-size: 17px; font-weight: 700; letter-spacing: -.01em; color: #fff; }
.brand::after { color: #8fb5a8; font-size: 10px; letter-spacing: .16em; margin-top: 6px; }
#nav { padding: 8px 10px; gap: 2px; }
#nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: 9px; border: 0;
  font-size: 13.5px; font-weight: 500; color: #b4ccc3;
  transition: background .16s ease, color .16s ease;
}
#nav a svg { width: 17px; height: 17px; flex: 0 0 auto; opacity: .75; transition: opacity .16s ease; }
#nav a:hover { background: rgba(255,255,255,.07); color: #fff; transform: none; }
#nav a:hover svg { opacity: 1; }
#nav a.active {
  background: rgba(255,255,255,.12); color: #fff; font-weight: 600;
  border: 0; box-shadow: none;
}
#nav a.active svg { opacity: 1; color: #6ee0b4; }
.sidebar-foot { color: #6f948a; font-size: 11px; padding: 16px 20px; }
.sidebar-foot .link { color: #9fc3b7; }

/* ---------- Панели и карточки ---------- */
.panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); padding: 20px; margin-bottom: 16px;
  backdrop-filter: none;
}
.cards { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 12px; }
.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px; box-shadow: var(--shadow);
  transition: border-color .16s ease, box-shadow .16s ease;
  backdrop-filter: none;
}
/* Карточка-показатель — не кнопка: не подпрыгивает, только мягко подсвечивается */
.cards .card:hover { transform: none; border-color: #c9d6d0; box-shadow: var(--shadow-md); }
.card .k {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
.card .v {
  font-size: 27px; font-weight: 700; letter-spacing: -.035em; color: var(--accent);
  margin-top: 3px; font-variant-numeric: tabular-nums;
}

/* ---------- Таблицы ----------
   Главная рабочая поверхность. Цифры — табличными, чтобы разряды
   стояли столбиком и колонку можно было читать по вертикали. */
table { font-size: 13px; }
/* Прилипающую шапку тут не сделать: .table-wrap из-за overflow-x:auto
   становится контейнером прокрутки и по вертикали, но по высоте не ограничен —
   sticky внутри него никогда не сработает. Нужна будет — задавать max-height. */
th {
  background: #f0f4f2; color: #66756e;
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: 9px 12px; border-bottom: 1px solid var(--line);
}
th:first-child { border-radius: 8px 0 0 8px; }
th:last-child  { border-radius: 0 8px 8px 0; }
td { padding: 9px 12px; border-bottom: 1px solid var(--line-soft); color: var(--ink-2); }
td:first-child { color: var(--ink); }
tbody tr { transition: background .12s ease; }
tbody tr:hover { background: var(--accent-lo); }
tbody tr:last-child td { border-bottom: 0; }
td.num, th.num { font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; border-radius: var(--radius); }

/* ---------- Кнопки ---------- */
button, .btn {
  border-radius: 8px; border: 1px solid #d8e1dc;
  padding: 7px 13px; font-size: 13px; font-weight: 550; color: var(--ink-2);
  transition: background .14s ease, border-color .14s ease, color .14s ease, box-shadow .14s ease;
}
/* Кнопка не должна ездить: в плотных таблицах это дёргает глаз */
button:hover { transform: none; box-shadow: none; background: var(--accent-lo); border-color: #aecbbe; color: var(--accent); }
button:active { transform: translateY(.5px); }
.btn-primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
  box-shadow: 0 1px 2px rgba(16,70,58,.25), 0 4px 12px rgba(21,112,85,.18);
}
.btn-primary:hover { background: #115e47; border-color: #115e47; color: #fff; }
.btn-danger { color: var(--danger); border-color: #ecc8c4; }
.btn-danger:hover { background: var(--danger-lo); border-color: #dfa8a2; color: var(--danger); }
.btn-sm { padding: 4px 9px; font-size: 12px; }

/* ---------- Поля ---------- */
input, select {
  border: 1px solid var(--line); border-radius: 8px; padding: 7px 10px;
  font-size: 13px; background: #fff; color: var(--ink);
  transition: border-color .14s ease, box-shadow .14s ease;
}
input::placeholder { color: #9aa8a1; }
input:focus, select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(21,112,85,.12); }
label.field { font-size: 11.5px; font-weight: 600; letter-spacing: .02em; color: var(--muted); gap: 5px; }

/* Видимая обводка при ходьбе по Tab — иначе с клавиатуры не понять, где ты */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* ---------- Мелочи ---------- */
.badge { padding: 2px 8px; font-size: 11px; font-weight: 650; background: var(--line-soft); color: var(--ink-2); }
.badge.ok    { background: var(--accent-lo); color: var(--accent); }
.badge.no    { background: var(--danger-lo); color: var(--danger); }
.badge.warn  { background: var(--warn-lo);   color: var(--warn); }
.badge.muted { background: var(--line-soft); color: var(--muted); }
.tag { background: var(--line-soft); color: var(--ink-2); font-size: 11.5px; border: 1px solid #dde5e1; }
.link { color: var(--accent); font-weight: 550; }
.link:hover { color: #115e47; text-decoration: underline; text-underline-offset: 2px; }
.muted { color: var(--muted); }
.empty { color: var(--muted); font-size: 13px; padding: 28px; }
.bar { background: #e8eeeb; height: 8px; }
.bar > span { background: linear-gradient(90deg, var(--accent-2), var(--accent)); }
.bar.over > span { background: linear-gradient(90deg, #e0705f, var(--danger)); }
.pill {
  border-color: #bfdbd0; background: var(--accent-lo); color: var(--accent);
  font-size: 11.5px; font-weight: 650;
}
.eyebrow { color: var(--accent); font-size: 10px; letter-spacing: .14em; }

/* ---------- Модалка ---------- */
#modal-backdrop { background: rgba(15,35,28,.32); backdrop-filter: blur(4px); }
#modal {
  position: relative;
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: 22px 24px;
  border: 1px solid var(--line);
}
#modal h2 { font-size: 18px; letter-spacing: -.02em; margin: 0 0 14px; padding-right: 30px; }
/* Единственный «неявный» способ закрыть окно — вот этот крестик (ну и Esc).
   Клик мимо окна ничего не закрывает: промах не должен стирать набранное. */
.modal-x {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 30px; height: 30px; padding: 0; line-height: 1;
  border: 0; background: transparent; color: var(--muted);
  font-size: 14px; border-radius: 8px; cursor: pointer;
}
.modal-x:hover { background: var(--danger-lo); color: var(--danger); }
.modal-foot { gap: 8px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
/* Накладная — это таблица на семь колонок, в 760 px она не живёт. */
#modal.wide { max-width: 1080px; }
.modal-foot #f_total { align-self: center; }

/* ---------- Выпуск по накладной ---------- */
/* Список позиций прокручивается ВНУТРИ модалки: иначе на накладной в 150 строк
   кнопка «Записать» уезжает вниз и не видно, сколько ты собрался записать. */
.pb-scroll { max-height: 46vh; overflow: auto; }
/* Заливка у липкой шапки обязательна: без неё строки видно НАСКВОЗЬ. */
.pb-table th { position: sticky; top: 0; z-index: 2; background: var(--panel); box-shadow: 0 1px 0 var(--line); }
.pb-table td, .pb-table th { padding: 5px 8px; font-size: 13px; }
.pb-table .pb-qty { width: 92px; text-align: right; padding: 4px 6px; }
/* Вариант исполнения (старый образец) — под названием позиции, неброско:
   у большинства строк выбора нет вовсе. */
.pb-table .pb-var { margin-top: 3px; max-width: 260px; padding: 2px 6px; font-size: 12px; }
.pb-table tr.pb-no { opacity: .55; }
.prod-flash {
  border-color: #bfdbd0; background: var(--accent-lo); color: var(--accent);
  padding: 10px 14px; font-size: 13.5px; font-weight: 600;
}

/* ---------- Время изделия и раскладка по станкам ---------- */
/* Панель стоит над схемой: сначала «сколько идёт изделие», потом «как это
   время делится по станкам» — в таком порядке о нём и думают. */
.rt-time-panel { margin-bottom: 12px; }
.rt-time-panel .rt-pt { gap: 8px; align-items: flex-end; }
.rt-time-panel .rt-pt input { width: 100%; }
.rt-fit {
  margin-top: 8px; padding: 8px 11px; border-radius: 8px;
  background: var(--accent-lo); color: var(--accent); font-size: 13px;
}
.rt-fit b { font-variant-numeric: tabular-nums; }

/* Перемещение — часть того же разговора о времени, но не про изготовление,
   поэтому отделено чертой, а не вынесено в отдельную панель. */
.rt-move { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.rt-move input, .rt-move select { width: 100%; }
/* Возка крупных — тот же разговор, но про другой станок: отбита, а не оторвана. */
.rt-move-hi { margin-top: 12px; padding: 10px 12px; border-radius: 8px; background: var(--line-soft); }

/* Проба по диаметру: «ввёл Ø — показало время» с разбивкой по шагам. */
.rt-probe { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.rt-probe input { width: 100%; }
.rt-probe-t { width: 100%; margin-top: 6px; }
.rt-probe-t td { padding: 3px 0; border: none; font-size: 13px; }
.rt-probe-t td:last-child { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- Машинное время: участок → станок → операции ---------- */
/* Плоский список на полсотни операций не читается: не видно, чем занят
   конкретный станок. Раскладка повторяет цех, чипы переключают участок. */
.mg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.mg-ws { margin-bottom: 12px; }
.mg-eq { margin-top: 10px; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.mg-eq-head {
  display: flex; align-items: baseline; gap: 8px;
  padding: 7px 11px; background: var(--line-soft); border-bottom: 1px solid var(--line);
}
.mg-t { width: 100%; }
.mg-t td { padding: 7px 11px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.mg-t tr:last-child td { border-bottom: none; }
.mg-name { width: 34%; min-width: 170px; }
.mg-mode { width: 1%; white-space: nowrap; }   /* иначе «кол-во × время» рвётся на две строки */
.mg-f { color: var(--ink-2); font-size: 13px; }

/* На узком экране формула — самое длинное в строке, и в своей колонке она
   рассыпается по слову на строку. Ниже 1000px кладём её отдельной строкой
   под названием: читается как подпись, а не как колонка в четыре символа. */
@media (max-width: 1000px) {
  .mg-t, .mg-t tbody, .mg-t tr, .mg-t td { display: block; width: auto; }
  .mg-t tr { padding: 7px 11px; border-bottom: 1px solid var(--line-soft); position: relative; }
  .mg-t tr:last-child { border-bottom: none; }
  .mg-t td { padding: 0; border: none; }
  .mg-name { min-width: 0; padding-right: 76px !important; }
  .mg-mode, .mg-f { margin-top: 3px; }
  .mg-t td.right { position: absolute; top: 6px; right: 8px; }
}

/* Операции станка прямо на карточке цеха: нажатие открывает тот же редактор,
   что и «Машинное время» — ходить в другой раздел незачем. */
.weq-ops { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px;
           padding-top: 8px; border-top: 1px dashed var(--line); }
.wchip-op { cursor: pointer; border: 1px solid var(--line); background: var(--panel); }
.wchip-op:hover { border-color: var(--accent); color: var(--accent); }

/* Готовый элемент — не операция, а целое изделие со своим маршрутом.
   Отличается заливкой, иначе в схеме его не отличить от обычного шага. */
.rt-card.is-part { background: var(--accent-lo); border-color: var(--accent); }

/* Вкладки толщин: у 1,5 мм свой маршрут и своё время. Точка = маршрут заведён,
   бледная вкладка = такой толщины в каталоге нет. */
.rt-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.rt-tab {
  display: flex; align-items: baseline; gap: 6px;
  padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--panel); color: var(--ink-2); font-size: 13px; cursor: pointer;
}
.rt-tab:hover { border-color: var(--accent); }
.rt-tab.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.rt-tab.is-none { opacity: .5; }
.rt-tab-n { font-size: 11px; opacity: .75; font-variant-numeric: tabular-nums; }
.rt-tab-dot { font-size: 9px; color: var(--ok, #2e9e6b); }
.rt-tab.is-on .rt-tab-dot { color: #fff; }

/* ---------- Загрузка заказа из файла ---------- */
/* Лучший кандидат — не строчка в выпадашке, а карточка с разницей словами:
   человек за секунду видит, что позиция та же, только в накладной лишнее «К». */
.oi-cand { margin-top: 6px; padding: 7px 9px; border-radius: 8px; background: var(--accent-lo); }
.oi-chk { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; }
.oi-chk input { width: auto; margin: 0; }
.oi-table td { vertical-align: top; }
.oi-table .oi-qty { width: 84px; text-align: right; }
.oi-table tr.oi-bad { background: var(--warn-lo); }

/* ---------- Тепловые карты ---------- */
.heat-cell { border-radius: var(--radius); box-shadow: var(--shadow); }
.heat-cell::after { display: none; }   /* декоративный кружок ни на что не указывал */
.heat-value { font-variant-numeric: tabular-nums; letter-spacing: -.035em; }
.heat-low      { background: #e8f5ee; border-color: #cfe8da; color: #176047; }
.heat-medium   { background: #fbf2d8; border-color: #eeda9e; color: #8a5d07; }
.heat-high     { background: #fdead4; border-color: #f2c493; color: #9a4e09; }
.heat-critical { background: #fbe4e2; border-color: #f0b8b8; color: #a12b2b; }

/* ---------- Кадры ----------
   ФИО ломалось на три строки. Задаём минимум только первой колонке:
   общий min-width таблице уводил кнопки действий за горизонтальную
   прокрутку — остальные колонки пусть переносятся сами. */
.staff-table td:nth-child(1), .staff-table th:nth-child(1) { min-width: 168px; }
.staff-table td:last-child { white-space: nowrap; }

/* Строка сотрудника, которого нет в базе — приглушаем, но не прячем */
tr.unmatched-row td { background: #f7f4e9; color: var(--muted); }

/* Остатки: позиция (SKU) с рулонами */
.stock-sku { padding: 12px 0; border-top: 1px solid var(--line-soft); }
.stock-sku:first-of-type { border-top: 0; }
.ss-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ss-w { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.roll-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-lo); color: var(--accent);
  border: 1px solid #cfe6db; border-radius: 20px; padding: 3px 6px 3px 11px;
  font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.roll-chip button {
  border: 0; background: transparent; color: var(--accent); cursor: pointer;
  padding: 0 3px; font-size: 12px; line-height: 1; border-radius: 50%;
}
.roll-chip button:hover { background: #cfe6db; color: var(--danger); transform: none; }

/* Цех: станок с прицепленными людьми */
.weq { padding: 14px 16px; margin-bottom: 10px; }
.wchips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.wchip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-lo); color: var(--accent);
  border: 1px solid #cfe6db; border-radius: 20px; padding: 3px 6px 3px 11px;
  font-size: 12.5px; font-weight: 550;
}
.wchip-x {
  border: 0; background: transparent; color: var(--accent); cursor: pointer;
  padding: 0 3px; font-size: 12px; line-height: 1; border-radius: 50%;
}
.wchip-x:hover { background: #cfe6db; color: var(--danger); transform: none; }

/* ---------- Дашборд: загрузка ---------- */
/* Шапка липнет к верху: при листании длинных списков должно оставаться видно,
   какой это период и где узкое место. */
.dash-head {
  position: sticky; top: 0; z-index: 5;
  background: var(--bg); padding: 4px 0 12px; margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.dash-date { flex: 0 0 auto; }
.dash-date input { padding: 6px 8px; }

/* Кнопки периода — одним переключателем, а не три отдельных: они выбор
   одного и того же, и глаз должен видеть их как одну ручку. */
.seg {
  display: inline-flex; border: 1px solid var(--line); border-radius: 9px;
  overflow: hidden; background: var(--panel); box-shadow: var(--shadow);
}
.seg button {
  border: 0; border-radius: 0; background: transparent;
  padding: 5px 12px; font-size: 12.5px; box-shadow: none;
}
.seg button + button { border-left: 1px solid var(--line); }
.seg button:hover { background: var(--accent-lo); color: var(--accent); }

/* Показатели периода — одна планка с перегородками, как ряд приборов,
   а не россыпь коробочек: коробочки повторяли карточки и дробили экран. */
.dash-facts {
  display: flex; flex-wrap: wrap; margin-top: 10px;
  background: linear-gradient(180deg, rgba(21,112,85,.025), transparent 42%), var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
}
.fact {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 18px; min-width: 118px;
  border-left: 1px solid var(--line-soft);
}
.fact:first-child { border-left: 0; }
.fact span { color: var(--muted); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.fact b { font-size: 20px; letter-spacing: -.025em; font-variant-numeric: tabular-nums; }
.fact-wide { flex: 1 1 260px; flex-direction: row; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.fact-wide span { align-self: center; }
.fact-wide b { font-size: 15px; letter-spacing: -.01em; }
.fact-wide i {
  font-style: normal; font-weight: 700; font-size: 12.5px;
  padding: 2px 8px; border-radius: 20px; background: var(--accent-lo); color: var(--accent);
}
.fact-wide i.lvl-high { background: var(--warn-lo); color: var(--warn); }
.fact-wide i.lvl-critical { background: var(--danger-lo); color: var(--danger); }
/* Перевод «кучи часов» на человеческий: сколько это суток всего завода
   (его просьба 27.08). Мелкой строкой под цифрой — это пояснение, не факт. */
.fact-days { color: var(--muted); font-size: 10.5px; font-weight: 500; text-transform: none; letter-spacing: 0; }

.dash-warn { border-color: #ecd9ae; background: var(--warn-lo); font-size: 13.5px; }
.dash-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1080px) { .dash-cols { grid-template-columns: minmax(0, 1fr); } }

.load-panel {
  background: linear-gradient(180deg, rgba(21,112,85,.02), transparent 42%), var(--panel);
}
.lp-head {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line);
}
.lp-head h2 {
  margin: 0; font-size: 11px; font-weight: 750; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
}
.lp-count {
  margin-left: auto; font-size: 15px; font-weight: 700; letter-spacing: -.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.lp-count i { font-style: normal; font-size: 11.5px; font-weight: 500; color: var(--muted); }

/* Загрузка цехов/станков/людей — ПЛИТКАМИ, а не строками с полосками
   (его слова 27.08: «не нравятся вот эти линии загрузки… пульс бодро
   сделан, нравится»). Плитка отвечает как пульс: крупная цифра сразу,
   цвет по уровню, тонкая полоса внизу — деталь, а не главный герой. */
.load-list {
  margin-top: 12px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 10px;
}
.load-list.hidden { display: none; }
.load-tile {
  position: relative;
  display: flex; flex-direction: column; gap: 1px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--panel);
  padding: 10px 12px 12px;
  box-shadow: 0 1px 2px rgba(23,40,33,.04);
  transition: border-color .16s ease, box-shadow .16s ease;
  min-width: 0;
}
.load-tile:hover { border-color: #c9d6d0; box-shadow: var(--shadow-md); }
.load-tile.is-link { cursor: pointer; }
.load-tile.is-link:hover { border-color: var(--accent); }
.lt-name {
  font-size: 12.5px; font-weight: 600; line-height: 1.25; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lt-sub {
  display: block; color: var(--muted); font-size: 10.5px; font-weight: 400;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lt-pct {
  margin-top: 5px; font-size: 22px; font-weight: 750; line-height: 1;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--accent);
}
.load-tile.lvl-medium   .lt-pct { color: var(--accent-2); }
.load-tile.lvl-high     .lt-pct { color: var(--warn); }
.load-tile.lvl-critical .lt-pct { color: var(--danger); }
.lt-hours { color: var(--muted); font-size: 10.5px; font-variant-numeric: tabular-nums; margin-top: 2px; }
.lt-bar {
  display: block; height: 5px; margin-top: 8px;
  border-radius: 20px; background: var(--line-soft); overflow: hidden;
}
.lt-bar i {
  display: block; height: 100%; width: 0; border-radius: 20px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
}
.load-tile.lvl-high     .lt-bar i { background: linear-gradient(90deg, #e5b063, var(--warn)); }
.load-tile.lvl-critical .lt-bar i { background: linear-gradient(90deg, #e88a80, var(--danger)); }

/* «Показать ещё» — во всю ширину и пунктиром: это дверь в продолжение
   списка, а не действие наравне с «Пересчитать». */
.dash-more {
  display: block; width: 100%; margin-top: 12px;
  border-style: dashed; background: transparent; color: var(--muted);
}
.dash-more:hover { color: var(--accent); border-color: var(--accent); border-style: solid; background: transparent; }

/* Легенда — подпись под экраном, а не ещё одна панель. */
.dash-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  padding: 2px 6px 0; margin-bottom: 16px;
}
.dash-legend .lg { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.dash-legend .lg i { width: 14px; height: 8px; border-radius: 20px; background: var(--accent); }
.dash-legend .lg i.lvl-medium   { background: var(--accent-2); }
.dash-legend .lg i.lvl-high     { background: #d69138; }
.dash-legend .lg i.lvl-critical { background: var(--danger); }
.small { font-size: 12px; }

/* ---------- Норма расхода: материал и его правила ---------- */
.bom-group { border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; margin-top: 10px; }
.bom-head { gap: 10px; align-items: baseline; }
.bom-rules { margin-top: 6px; }
.bom-rule {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 8px; border-radius: 8px; background: var(--accent-lo);
}
.bom-rule + .bom-rule { margin-top: 4px; }
.bom-when { min-width: 108px; font-size: 12.5px; font-weight: 650; color: var(--accent); }
.bom-qty { font-size: 13px; }
.bom-warn {
  margin-top: 8px; padding: 7px 10px; border-radius: 8px;
  background: var(--warn-lo); color: var(--warn); font-size: 12.5px;
}

/* ---------- Склад ---------- */
/* Ширина висит на САМОЙ колонке названия, а не на «первой по счёту».
   Было `th:first-child { width: 40% }` — и когда слева добавилась колонка
   флажков, эти 40% достались ей: галочки уехали на середину страницы.
   Номер колонки — не её признак. */
.wh-table th.wh-name, .wh-table td.wh-name { width: 40%; }
.wh-table th.num, .wh-table td.num { white-space: nowrap; }
.wh-in  { color: var(--accent); }
.wh-out { color: var(--warn); }
/* Значок у пункта меню: сколько позиций просит пополнения. */
.nav-badge {
  margin-left: auto; min-width: 18px; padding: 1px 6px; border-radius: 20px;
  background: rgba(240,192,120,.25); color: #f0c078;
  font-size: 11px; font-weight: 700; text-align: center;
}
.nav-badge.is-critical { background: rgba(239,128,128,.25); color: #f19a9a; }
#nav a { display: flex; align-items: center; gap: 10px; }

/* ---------- Комплектующие ---------- */
/* Наименования тут длинные («Гофрокороб 4-х клап. 203х203х1000, Т-23 "С"…»),
   а цена и единица короткие — отдаём место названию, цифры не переносим. */
/* Ширины — по классам колонок, а не по их номерам. На складе такое же
   правило через :first-child отдало 40% колонке флажков, когда она
   появилась слева, и галочки уехали на середину страницы. Номер колонки
   не признак колонки. */
.cons-table th.cons-name, .cons-table td.cons-name { width: 46%; }
.cons-table th.cons-price, .cons-table td.cons-price,
.cons-table th.cons-unit, .cons-table td.cons-unit { width: 1%; white-space: nowrap; }
.cons-table td.cons-comment { font-size: 12px; }

/* ---------- Маршрут как схема ---------- */
/* Этапы идут слева направо и переносятся на следующую строку, как текст:
   горизонтальная прокрутка на маршруте из 13 операций (сэндвич) означала бы,
   что «целую схему» целиком не видно никогда. */
/* Схема длинная — название и «Сохранить» не должны уезжать при листании. */
.rt-head {
  position: sticky; top: 0; z-index: 5;
  background: var(--bg); padding: 4px 0 10px; margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.rt-totals { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.rt-canvas { padding: 18px; }
.rt-flow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 2px; }
.rt-stage {
  display: flex; flex-direction: column; gap: 6px;
  min-width: 208px; max-width: 240px;
  background: var(--accent-lo); border: 1px solid #d7e9e1;
  border-radius: var(--radius-lg); padding: 8px;
}
.rt-stage-head { display: flex; align-items: center; gap: 6px; padding: 0 2px; }
.rt-stage-n { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.rt-stage-head .badge { font-size: 10.5px; }
.rt-mini {
  border: 1px solid #cfe6db; background: var(--panel); color: var(--accent);
  border-radius: 6px; padding: 0 6px; font-size: 13px; line-height: 18px; cursor: pointer;
}
.rt-mini:disabled { opacity: .35; cursor: default; }

.rt-card {
  display: flex; flex-direction: column; gap: 3px; position: relative;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 26px 10px 11px; cursor: pointer; box-shadow: var(--shadow);
}
.rt-card:hover { border-color: var(--accent); }
.rt-card b { font-size: 13px; line-height: 1.25; }
.rt-card.is-empty { border-style: dashed; background: transparent; box-shadow: none; color: var(--muted); }
.rt-card .rt-sub { color: var(--muted); font-size: 11px; }
/* Часть изделия на карточке: внутряк / наружка / вместе. Селектор без рамки —
   он подпись, а не поле ввода: смотрят на него чаще, чем меняют. */
.rt-part {
  appearance: none; background: transparent; border: 0; padding: 0;
  font: 700 10.5px/1.2 inherit; letter-spacing: .02em; text-transform: uppercase;
  cursor: pointer; max-width: 100%;
}
.rt-part:hover { text-decoration: underline dotted; }

/* Карта по частям — тот же вид, что у печатной карты маршрутов. */
.rt-map { display: flex; flex-direction: column; gap: 8px; }
.rt-lane { display: flex; align-items: stretch; gap: 8px; }
.rt-lane-name {
  flex: 0 0 24px; color: #fff; font-weight: 700; font-size: 11px; border-radius: var(--radius);
  writing-mode: vertical-rl; transform: rotate(180deg); text-align: center; padding: 6px 2px;
}
.rt-lane-flow { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; align-items: stretch; }
.rt-map-card {
  position: relative; min-width: 150px; max-width: 210px; padding: 16px 8px 7px;
  border: 2px solid var(--line); border-radius: var(--radius); background: var(--panel); cursor: pointer;
}
.rt-map-card:hover { box-shadow: var(--shadow); }
.rt-map-card b { display: block; font-size: 12.5px; line-height: 1.25; }
.rt-map-n {
  position: absolute; top: -1px; left: -1px; color: #fff; font-weight: 700; font-size: 11px;
  padding: 0 6px; border-radius: var(--radius) 0 var(--radius) 0;
}
.rt-move {
  align-self: center; text-align: center; font-size: 10.5px; color: var(--warn);
  border: 1px dashed var(--warn); border-radius: var(--radius); padding: 4px 6px; min-width: 86px;
}
.rt-move span { color: var(--muted); }
.rt-time { font-size: 12.5px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.rt-time.is-auto { color: var(--warn); }
.rt-time.is-off { color: var(--muted); }
/* Откуда взялось число: «развёртка 364 мм». Мелко — это подпись к времени,
   а не второе время: читают её, только когда цифра выше вызвала вопрос. */
.rt-card .rt-why { line-height: 1.25; }
.rt-card .rt-why.is-warn { color: var(--warn); }
.rt-note-warn { color: var(--warn); }
/* Крупный размер в карточке шага: отдельная рамка, потому что это разговор
   про другое изделие — то же место в маршруте, но другой станок и время. */
.rt-alt-box { margin-top: 10px; padding: 10px 12px; border-radius: 8px; background: var(--line-soft); }
.rt-alt-box select { width: 100%; }
/* Размер, на котором считаем, стоит в ряду итогов: соседние цифры меняются
   вместе с ним, и связь видна без объяснений. */
.fact-input { justify-content: center; }
.fact-input input { width: 96px; padding: 1px 6px; font-size: 17px; font-weight: 700; }
.rt-x {
  position: absolute; top: 6px; right: 6px;
  border: 0; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 12px; line-height: 1; padding: 2px 4px; border-radius: 4px;
}
.rt-x:hover { background: var(--danger-lo); color: var(--danger); }

/* Параллельная ветка: подпись со стрелкой вниз между карточками одного этапа. */
.rt-par {
  position: relative; text-align: center;
  color: var(--muted); font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase;
}
.rt-par::before { content: '↓'; display: block; color: var(--accent); font-size: 14px; line-height: 1; }
.rt-par-add {
  border: 1px dashed #cfe6db; background: transparent; color: var(--accent);
  border-radius: 8px; padding: 5px; font-size: 11.5px; cursor: pointer; width: 100%;
}
.rt-par-add:hover { background: var(--panel); border-style: solid; }

.rt-link { display: flex; flex-direction: column; align-items: center; gap: 2px; padding-top: 26px; width: 34px; }
.rt-arrow { color: var(--accent); font-size: 17px; line-height: 1; }
.rt-ins {
  border: 1px solid #cfe6db; background: var(--panel); color: var(--accent);
  border-radius: 50%; width: 20px; height: 20px; font-size: 12px; line-height: 1; cursor: pointer; padding: 0;
}
.rt-ins:hover { background: var(--accent); color: #fff; }
.rt-add-stage {
  align-self: stretch; min-height: 92px; margin-top: 22px;
  border: 1px dashed #cfe6db; background: transparent; color: var(--accent);
  border-radius: var(--radius-lg); padding: 10px 14px; font-size: 12.5px; cursor: pointer;
}
.rt-add-stage:hover { background: var(--accent-lo); border-style: solid; }

@media (max-width: 700px) {
  .rt-stage { min-width: 0; max-width: none; flex: 1 1 100%; }
  .rt-link { flex-direction: row; width: 100%; padding: 4px 0; }
  .rt-arrow { transform: rotate(90deg); }
}

/* ---------- Анкета в карточке сотрудника ---------- */
/* textarea в базовых стилях не описан (форм с длинным текстом раньше не было),
   поэтому выравниваем его по input вручную. */
textarea {
  width: 100%; font: inherit; color: var(--ink);
  background: #fff; border: 1px solid #d4e0da; border-radius: 9px;
  padding: 8px 10px; resize: vertical;
  transition: border .16s ease, box-shadow .16s ease;
}
textarea:focus { outline: none; border-color: #258069; box-shadow: 0 0 0 3px rgba(37,128,105,.14); }
label.field textarea { color: var(--ink); }

/* ---------- Карточки людей ---------- */
.person-avatar { background: linear-gradient(140deg, var(--accent-2), var(--accent)); border-radius: 10px; }
.people-card { border-radius: var(--radius); box-shadow: var(--shadow); }
.people-card:hover { transform: none; box-shadow: var(--shadow-md); }
.people-panel, .people-load { background: var(--panel); }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ============================================================
   СВЕТЛАЯ ДОБИВКА (27.08.2026)
   Перекрываем цветные хардкоды styles.css нашими токенами —
   theme.css грузится после и побеждает. Раньше здесь была
   «тёмная добивка» — теперь та же прослойка, но светлая.
   ============================================================ */
tbody tr:hover { background: var(--accent-lo); }
button, .btn { background: #fff; color: var(--ink-2); }
input, select, textarea { background: #fff; color: var(--ink); }
input::placeholder, textarea::placeholder { color: #9aa8a1; }
.badge.ok { background: var(--accent-lo); }
.badge.no { background: var(--danger-lo); }
.badge.warn { background: var(--warn-lo); }
.badge.muted { background: var(--line-soft); }
.bar { background: #e8eeeb; }
#modal { background: var(--panel); border: 1px solid var(--line); }
.tool-frame { background: var(--panel); }
.order-date { background: var(--accent-lo); }

.people-panel, .people-load {
  background: linear-gradient(135deg, rgba(255,255,255,.99), rgba(240,248,244,.92));
  border-color: rgba(21,112,85,.14);
}
.people-card { background: var(--panel); border-color: var(--line); box-shadow: var(--shadow); }
.people-card:hover { box-shadow: var(--shadow-md); }
.person-bar { background: #e8eeeb; }

/* Логотип в шапке сайдбара: сайдбар остался тёмным — dark-версия
   логотипа из гайдлайна живёт как жила. На светлой странице входа
   тоже она: у неё подложка-плашка своя, фон не важен. */
.brand-logo { display: block; width: 168px; max-width: 100%; height: auto; margin: 2px 0 4px; }
.login-logo { display: block; width: 220px; max-width: 80%; height: auto; margin: 0 auto 18px; }

/* ============================================================
   ДАШБОРД: ГЕРОЙ «СМЕНА» И ПУЛЬС ОТГРУЗОК

   Замечание пользователя 20.08: «как-то простенько смотрится».
   Разбирались не с украшением, а с порядком: первым на экране была форма
   выбора периода, а ответ на единственный вопрос экрана — успеваем или
   нет — лежал значком в углу.

   Шрифт остаётся Inter: он один лежит в public/fonts, а система работает
   без интернета и на чужих компьютерах в сети. Поэтому характер задаётся
   не второй гарнитурой, а масштабом и режимом цифр: крупные табличные
   цифры с плотным трекингом против мелких прописных подписей с широким.
   ============================================================ */

/* Сталь — единственный новый цвет, и только для штриховки и черты смены:
   зелёный, янтарный и красный уже заняты смыслами (норма / впритык / беда). */
:root { --steel: #7b8d99; }

.hero {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, rgba(21,112,85,.03), transparent 42%),
    var(--panel);
  padding: 20px 22px 18px;
  margin: 4px 0 16px;
  overflow: hidden;
  box-shadow: var(--shadow);
}
/* Тонкая полоса состояния по левому краю — цвет виден боковым зрением,
   когда экран висит на стене и никто в него не всматривается. */
.hero::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--accent);
}
.hero-tight::before { background: var(--warn); }
.hero-over::before  { background: var(--danger); }

.hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.hero-eyebrow {
  font-size: 10px; font-weight: 700; letter-spacing: .17em; text-transform: uppercase;
  color: var(--muted);
}
.hero-name { font-size: 21px; font-weight: 700; letter-spacing: -.02em; margin-top: 3px; }
.hero-verdict {
  font-size: 11.5px; font-weight: 750; letter-spacing: .04em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px;
  background: var(--accent-lo); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.hero-tight .hero-verdict { background: var(--warn-lo); color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 30%, transparent); }
.hero-over .hero-verdict { background: var(--danger-lo); color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 36%, transparent); }

/* ---------- Прибор ---------- */
.hero-gauge { margin: 18px 0 14px; }
.gauge-track {
  position: relative; height: 34px; border-radius: 8px;
  background: var(--line-soft);
  border: 1px solid var(--line);
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(23,40,33,.06);
}
.gauge-fit, .gauge-over { position: absolute; top: 0; bottom: 0; width: 0; }
.gauge-fit {
  left: 0; border-radius: 7px 0 0 7px;
  background: linear-gradient(180deg, var(--accent-2), var(--accent));
}
.hero-tight .gauge-fit { background: linear-gradient(180deg, #e5b063, #c07a20); }
.hero-over  .gauge-fit { background: linear-gradient(180deg, #35a381, #157055); }

/* То, что за чертой смены. Косая штриховка — как перечёркивают лишнее на
   чертеже: это не «больше красного», а другое по смыслу — не помещается. */
.gauge-over {
  left: var(--x);
  background:
    repeating-linear-gradient(135deg,
      var(--danger) 0 7px,
      color-mix(in srgb, var(--danger) 42%, transparent) 7px 14px);
  border-radius: 0 7px 7px 0;
}
.gauge-line {
  position: absolute; top: -1px; bottom: -1px; width: 2px;
  background: var(--steel);
  box-shadow: 0 0 0 1px rgba(255,255,255,.7);
}
.gauge-line i {
  position: absolute; left: 6px; top: 50%; transform: translateY(-50%);
  font-style: normal; font-size: 9.5px; font-weight: 750; letter-spacing: .14em;
  text-transform: uppercase; color: var(--steel); white-space: nowrap;
}

/* ---------- Числа ---------- */
.hero-nums { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.hero-big { display: flex; align-items: baseline; gap: 4px; }
.hero-big b {
  font-size: 58px; font-weight: 800; line-height: .92;
  letter-spacing: -.045em; font-variant-numeric: tabular-nums;
}
.hero-big span { font-size: 22px; font-weight: 700; color: var(--muted); }
.hero-over .hero-big b { color: var(--danger); }
.hero-tight .hero-big b { color: var(--warn); }

.hero-side { display: flex; gap: 22px; flex-wrap: wrap; padding-bottom: 4px; }
.hero-side > div { display: grid; gap: 2px; }
.hero-side span {
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.hero-side b { font-size: 17px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.hero-side .hero-over b { color: var(--danger); }

/* ---------- Пульс ---------- */
.pulse { padding-bottom: 14px; }
.pulse-bars {
  display: flex; align-items: flex-end; gap: 6px;
  height: 120px; margin: 16px 0 0;
}
.pulse-col {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  height: 100%; cursor: pointer; min-width: 0;
}
.pulse-bar {
  display: block; width: 100%; max-width: 34px; height: 0;
  border-radius: 5px 5px 2px 2px;
  background: var(--accent);
}
.pulse-col.lvl-medium   .pulse-bar { background: var(--accent-2); }
.pulse-col.lvl-high     .pulse-bar { background: #d69138; }
.pulse-col.lvl-critical .pulse-bar { background: var(--danger); }
.pulse-col:hover .pulse-bar { filter: brightness(1.12); }
.pulse-col em {
  font-style: normal; font-size: 10.5px; font-weight: 650; color: var(--muted);
  margin-top: 6px; font-variant-numeric: tabular-nums;
}
.pulse-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.pulse-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-size: 12px; font-weight: 650;
  border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
}
.pulse-chip i { font-style: normal; font-size: 11px; color: var(--muted); }
.pulse-worst { font-size: 12px; font-weight: 650; color: var(--danger); margin-left: auto; }

/* ---------- Появление ----------
   Класс is-live ставится ПОСЛЕ отрисовки: до него всё лежит в исходном
   состоянии, и переход происходит один раз, а не при каждой перерисовке
   таблиц. Длительности разные, чтобы получилась последовательность:
   сначала прибор, следом столбики, потом плитки. */
#dashBody .gauge-fit, #dashBody .gauge-over { transition: width .78s cubic-bezier(.22,.85,.28,1); }
#dashBody.is-live .gauge-fit,
#dashBody.is-live .gauge-over { width: var(--w); }

#dashBody .pulse-bar { transition: height .5s cubic-bezier(.22,.85,.28,1); }
#dashBody.is-live .pulse-bar { height: var(--h); }
#dashBody.is-live .pulse-col { transition-delay: calc(var(--i) * 26ms); }
#dashBody.is-live .pulse-col .pulse-bar { transition-delay: calc(var(--i) * 26ms); }

#dashBody .lt-bar i { transition: width .6s cubic-bezier(.22,.85,.28,1) .12s; }
#dashBody.is-live .lt-bar i { width: var(--w, 0); }

/* «Уменьшить движение» — показываем сразу и без переходов. */
#dashBody.no-motion .gauge-fit, #dashBody.no-motion .gauge-over { width: var(--w); transition: none; }
#dashBody.no-motion .pulse-bar { height: var(--h); transition: none; }
#dashBody.no-motion .lt-bar i { width: var(--w, 0); transition: none; }
@media (prefers-reduced-motion: reduce) {
  #dashBody .gauge-fit, #dashBody .gauge-over,
  #dashBody .pulse-bar, #dashBody .lt-bar i { transition: none !important; }
}

/* 820, а не 760: медиазапрос меряет вьюпорт ВМЕСТЕ с полосой прокрутки,
   и на планшете 768 он не срабатывал — цифра оставалась во весь экран. */
@media (max-width: 820px) {
  .hero-big b { font-size: 44px; }
  .pulse-bars { height: 92px; gap: 4px; }
}
.hero-note { margin: 14px 0 0; font-size: 12px; color: var(--muted); }

/* ---------- Карта завода (граф в «Справочниках») ---------- */
#fmapCanvas {
  display: block; margin-top: 12px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background:
    radial-gradient(600px 300px at 30% 20%, rgba(21,112,85,.04), transparent 70%),
    #fbfcfb;
}
.fmap-lg { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); }
.fmap-lg i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }

/* ============================================================
   КУЗНИЦА — индикатор загрузки (просьба пользователя 20.08:
   «робот молотом по наковальне колотит»). SVG рисуется в app.js
   (loaderHtml), здесь — цвета и вся анимация. Один цикл 1,05 с:
   замах → удар (62%) → искры → возврат. Всё на CSS-трансформациях,
   без JS: если данные пришли раньше, робота просто сносит разметкой.
   ============================================================ */
.loading { padding: 40px 20px 34px; opacity: 0; animation: loadingIn .35s ease .12s forwards; }
@keyframes loadingIn { to { opacity: 1; } }
.loading-label {
  margin-top: 8px; color: var(--muted);
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}

.forge { width: 200px; max-width: 60vw; height: auto; display: block; margin: 0 auto; }

/* Металл: наковальня темнее, робот светлее — сталь двух прокатов. */
.forge-anvil path, .forge-anvil rect, .forge-anvil polygon { fill: #4b574f; }
.forge-anvil { animation: forgeJolt 1.05s infinite; }
.forge-hot { fill: #d98e2b; animation: forgeHot 1.05s infinite; }
.forge-bot > rect { fill: #5d6c64; }
.forge-body  { fill: #71827a; }
.forge-chest { fill: #4c5a53; }
.forge-lamp  { fill: var(--accent-2); }
.forge-head  { fill: #7d8f86; }
.forge-eye   { fill: #f6c964; }
.forge-ant { stroke: #7d8f86; stroke-width: 2.5; }
.forge-ant-tip { fill: var(--danger); animation: forgeBeacon 1.4s ease-in-out infinite; }
.forge-arm-up { stroke: #71827a; stroke-width: 8; stroke-linecap: round; }
.forge-hand   { fill: #4c5a53; }
.forge-handle { stroke: #a5734a; stroke-width: 4; stroke-linecap: round; }
.forge-hammer { fill: #4c5a53; stroke: #38423c; stroke-width: 1; }
.forge-sparks line { stroke: #e8a51f; stroke-width: 2.5; stroke-linecap: round; }
.forge-ground { stroke: #d5ddd8; stroke-width: 2; stroke-linecap: round; }

/* Рука с молотом: нарисована в замахе, удар — поворот вокруг плеча. */
.forge-arm {
  transform-origin: 133px 72px;
  animation: forgeSwing 1.05s cubic-bezier(.55,.06,.68,.19) infinite;
}
@keyframes forgeSwing {
  0%   { transform: rotate(0deg); }
  36%  { transform: rotate(7deg); }    /* замах чуть выше */
  50%  { transform: rotate(7deg); }    /* пауза — прицелился */
  62%  { transform: rotate(-28deg); }  /* удар — молот точно по заготовке */
  70%  { transform: rotate(-22deg); }  /* отскок молота */
  100% { transform: rotate(0deg); }
}
/* Корпус чуть приседает в удар — иначе робот как приклеенный. */
.forge-bot { animation: forgeBob 1.05s infinite; }
@keyframes forgeBob {
  0%, 50%, 100% { transform: translateY(0); }
  63%           { transform: translateY(1.4px); }
}
@keyframes forgeJolt {
  0%, 58%, 100% { transform: translateY(0); }
  64%           { transform: translateY(1.2px); }
}
/* Искры живут только в момент удара. */
.forge-sparks {
  transform-origin: 74px 54px; opacity: 0;
  animation: forgeSparks 1.05s ease-out infinite;
}
@keyframes forgeSparks {
  0%, 58% { opacity: 0; transform: scale(.25); }
  64%     { opacity: 1; transform: scale(1); }
  82%     { opacity: 0; transform: scale(1.55); }
  100%    { opacity: 0; transform: scale(.25); }
}
@keyframes forgeHot {
  0%, 55%, 100% { opacity: .7; }
  64%           { opacity: 1; }
}
@keyframes forgeBeacon { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

/* «Уменьшить движение»: робот стоит с поднятым молотом, ничего не мигает. */
@media (prefers-reduced-motion: reduce) {
  .loading, .loading * { animation: none !important; }
  .loading { opacity: 1; }
  .forge-sparks { opacity: 0; }
}

/* ============================================================
   ТЕЛЕФОН (его просьба 27.08: «мобильная версия так себе»).
   Планшет 768+ живёт по общим правилам, здесь — узкие экраны.
   Меряно на 375 px: главные грехи были — календарь логистики
   лез 4 колонками за экран (+225 px вбок), неразрывный <code>
   распирал панели, липкие шапки съедали пол-экрана, меню
   уезжало из виду при листании.
   ============================================================ */

/* Меню на узком экране липнет к верху: разделы переключают часто,
   а мотать наверх за этим — главное раздражение телефона.
   Логотип прячем — место дороже подписи, что это «Производство». */
@media (max-width: 780px) {
  /* width:100% обязателен: базовый .sidebar{width:246px} из theme.css
     иначе перебивает мобильное правило styles.css — полоса меню была бы
     обрубком на четверть экрана. */
  .sidebar { position: sticky; top: 0; z-index: 40; height: auto; width: 100%; }
  .brand { display: none; }
  #nav { padding: 6px 8px; scrollbar-width: none; }
  #nav::-webkit-scrollbar { display: none; }
  #nav a { padding: 8px 10px; font-size: 13px; }
}

@media (max-width: 600px) {
  main { padding: 14px 12px 40px; }
  h1 { font-size: 21px; }
  h2 { font-size: 15px; }
  .sub { font-size: 12.5px; margin-bottom: 14px; }
  .panel { padding: 14px; margin-bottom: 12px; }
  /* Длинное неразрывное (пути, команды, артикулы) переносим посимвольно,
     а не распираем панель. */
  #main code, #main .muted { overflow-wrap: anywhere; }
  .row > * { min-width: 0; max-width: 100%; }

  /* Карточки-счётчики: две в ряд, компактнее. */
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .card { padding: 10px 12px; }
  .card .v { font-size: 22px; }

  /* Таблицы: чуть мельче и плотнее — сами они скроллятся в .table-wrap. */
  table { font-size: 12.5px; }
  th, td { padding: 7px 8px; }

  /* Календарь логистики: 2 колонки вместо 4, клетки умеют сжиматься
     (min-width:0 — без него грид растягивается по содержимому). */
  .cal { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
  .cal-cell { min-width: 0; min-height: 92px; padding: 7px 8px; }

  /* Дашборд: липкая шапка на телефоне съедала пол-экрана — отлипает. */
  .dash-head { position: static; padding-top: 0; }
  .hero { padding: 14px 14px 12px; }
  .hero-name { font-size: 17px; }
  .hero-big b { font-size: 36px; }
  .hero-big span { font-size: 16px; }
  .hero-side { gap: 12px; }
  .fact { padding: 8px 12px; min-width: 92px; }
  .fact b { font-size: 17px; }
  .pulse-bars { height: 72px; gap: 3px; }
  .load-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .lt-pct { font-size: 19px; }

  /* Модалка — почти во весь экран, поля не жмутся. */
  #modal-backdrop { padding: 10px 8px; }
  #modal { padding: 16px 14px; max-height: 94vh; }
  .modal-foot { flex-wrap: wrap; }

  /* Схема маршрута: липкая шапка редактора тоже отлипает. */
  .rt-head { position: static; }
}
