/* Шкала: отступы кратно 4, два радиуса и «пилюля», кегли без дробных значений.
   Рамку носят те блоки, где важна граница самих данных: карточка и строка-карточка (.card,
   .rcard), поля ввода и блок сканирования как оболочка поля, а также изображения бумаги и
   кадра (.sticker, .photo) — у них рамка и есть край предмета. Всё остальное — плитки, панели,
   сегменты, теги, плашки — ведётся фоном --row и его оттенками, без рамок. Тень значит «слой
   над страницей»: окно приложения, модалка и её липкий подвал.
   Цвета берём только из :root — литеральных hex в правилах ниже быть не должно.
   Две линии разного назначения: --line разделяет данные (строки таблицы, край карточки), --edge
   обводит то, во что тыкают, — поле ввода, серую кнопку, трек полосы. Порог у них тоже разный:
   разделителю хватает быть заметным, край управляющего элемента обязан держать 3:1 к фону
   (WCAG 1.4.11). --line на белом даёт 1,29:1, --edge — 3,10:1, поэтому граница поля берёт второй. */
:root{--bg:#eef1f6;--card:#fff;--line:#dde3ec;--line2:#c3cbd8;--edge:#8a93a3;--txt:#161b26;--dim:#5c6875;--acc:#285bdc;
--ok:#0f783f;--okbg:#e8f7ee;--ok-ink:#0e6b3c;--bad:#c62828;--badbg:#fdecec;--warn:#a35c00;--warnbg:#fff6e5;--warn-ink:#7a4a00;--warn-line:#eedcae;
--amber:#b45f06;--dark:#151a24;--live:#3fd07a;
--row:#f2f5fa;--sel:#e7efff;--mine:#eef8f1;--mono:ui-monospace,Consolas,monospace;--ui:system-ui,Segoe UI,Roboto,sans-serif;
/* Подсветка строк — отдельная шкала от сигнальной: --badbg/--warnbg кричат («просрочено»,
   «отклонено»), а --row-* только помечает строку, не перебивая текст и теги внутри: на помеченной
   строке рядом стоят красный и жёлтый теги, и они обязаны остаться читаемыми. */
--row-hi:#f6f9ff;--row-hurt:#fdf5f5;--row-warm:#fdf8ef;--placeholder:#6b7684;
--s1:4px;--s2:8px;--s3:12px;--s4:16px;--s5:24px;--s6:32px;--s7:48px;--s8:64px;--r1:8px;--r2:12px;--r3:999px;
/* Шкалы ниже держат весь размерный ряд приложения. Пока их не было, кегль, вес, высота элемента,
   ширина поля, слой и тень задавались числом прямо в правиле — и любое новое место приносило своё
   значение: 15 кеглей, 6 весов, 10 теней. Литералов этих свойств в файле больше быть не должно. */
--f1:13px;--f2:14px;--f3:16px;--f4:20px;--f5:22px;--f6:26px;--f7:34px;
--w-txt:400;--w-med:500;--w-ctl:600;--w-b:700;
/* --h — тач-цель и высота всего, во что тыкают. --h-chip — ВИДИМАЯ высота пилюли (чип, тег):
   до 44 такая пилюля добирается прозрачным полем, а не ростом плашки, иначе чип-подпись и
   чип-кнопка в одном ряду шапки расходятся на 14px. */
--h:44px;--h-lg:56px;--h-chip:32px;--h-tile:64px;--r0:6px;
--lh:1.55;--lh-tight:1.2;--mera:65ch;--w-s:120px;--w-m:200px;--w-l:320px;
--z-th:2;--z-sticky:5;--z-foot:6;--z-modal:50;--z-skip:80;
/* Тень значит «слой над страницей» и бывает у трёх сущностей: окно приложения, модалка, липкая
   полоса действий. Кольца — состояние фокуса поля. Обводка края (ring-edge/ring-acc) тенью не
   является: она рисует границу управляющего элемента, не двигая раскладку. */
--sh-win:0 0 0 1px rgba(16,24,40,.05),0 2px 28px rgba(16,24,40,.07);
--sh-modal:0 24px 64px rgba(16,24,40,.28);
--sh-foot:0 -1px 0 var(--line),0 -12px 16px -12px rgba(16,24,40,.22);
--ring:0 0 0 3px rgba(47,107,255,.15);--ring-bad:0 0 0 3px rgba(198,40,40,.14);
--ring-edge:inset 0 0 0 1px var(--edge);--ring-acc:inset 0 0 0 2px var(--acc);--ring-line:inset 0 0 0 1px var(--line2);
/* Тёмной темы у приложения нет: only light запрещает Chrome на Android подменять цвета своей
   автоматической тёмной — иначе сигнальные красный и жёлтый перекрашиваются на глазах у смены. */
color-scheme:only light}
*{box-sizing:border-box}
/* Любой класс с собственным display перебивает браузерное [hidden]{display:none}: чип сухого
   прогона и часы скрываются именно атрибутом, и пустая серая плашка 24×32 висела бы в шапке. */
[hidden]{display:none!important}
.skip-link{position:fixed;z-index:var(--z-skip);inset-block-start:var(--s2);inset-inline-start:var(--s2);transform:translateY(-160%);background:var(--dark);color:var(--card);
 display:inline-flex;align-items:center;min-height:var(--h);padding:var(--s2) var(--s4);line-height:var(--lh-tight);border-radius:var(--r1);font-weight:var(--w-b)}
.skip-link:focus{transform:translateY(0)}
/* tabular-nums держит разряды в колонке: без него на системном San Francisco числа разъезжаются. */
body{margin:0;font:var(--f3)/var(--lh) var(--ui);background:var(--bg);color:var(--txt);font-variant-numeric:tabular-nums;-webkit-text-size-adjust:100%;touch-action:manipulation;-webkit-tap-highlight-color:transparent}
/* Высота окна задана, а не минимальна: меню и страница получают каждое свою прокрутку, шапка со
   связью и очередью остаётся на месте. На телефоне высота снимается — там экран мал, и выгоднее
   прокручивать страницу целиком вместе с шапкой. */
.win{max-width:1560px;margin:0 auto;background:var(--card);height:100vh;height:100dvh;display:flex;flex-direction:column;
 box-shadow:var(--sh-win)}
/* Шапка отодвинута от выреза: приложение ставится на телефон как PWA (manifest fullscreen,
   viewport-fit=cover), и без этого логотип с чипом связи уезжают под статус-бар. */
.top{background:var(--dark);color:var(--card);padding-top:calc(var(--s2) + env(safe-area-inset-top,0px));padding-right:max(var(--s4),env(safe-area-inset-right,0px));padding-bottom:var(--s2);padding-left:max(var(--s4),env(safe-area-inset-left,0px));display:flex;align-items:center;gap:var(--s2);font-size:var(--f2);flex-wrap:wrap}
.top.off{background:var(--bad)}
/* Логотип держит высоту чипа: пока он был обычной строкой, в ряду шапки стояли три разные верхние
   границы — логотип, чип-подпись и чип-кнопка начинались на разной высоте. */
.top .logo{display:inline-flex;align-items:center;min-height:var(--h-chip);font-weight:var(--w-b);letter-spacing:.5px}
/* Чипы уходят из шапки по мере сужения экрана, начиная с самых бесполезных в работе: имя
   приложения и часы (время видно в строке заказа и в журнале), затем роль — её человек знает,
   и она же написана в меню. Остаются те, ради которых на шапку смотрят: связь, режим, место
   и «Завершить смену». Каждый снятый чип — это ряд высотой 44px, отданный работе. */
@media(max-width:1199px){.top{flex-wrap:nowrap}.top .logo,#clock{display:none}.top .chip{min-width:0;overflow:hidden;text-overflow:ellipsis}}
.top .sp{flex:1}
/* Видимая высота пилюли одна для всех — 32px, независимо от того, подпись это или кнопка. */
.chip{background:rgba(255,255,255,.13);padding:var(--s1) var(--s3);border-radius:var(--r3);white-space:nowrap;
 display:inline-flex;align-items:center;min-height:var(--h-chip);line-height:var(--lh-tight)}
/* Палец получает 44px, а плашка остаётся 32px: недостающие 12 добраны прозрачной рамкой сверху и
   снизу, фон обрезан по её внутреннему краю, отрицательное поле возвращает ряду прежнюю высоту.
   Тот же приём уже держит крестик модалки и .fold. Фон в состояниях задаём background-color:
   сокращённое background сбросило бы background-clip и растянуло заливку на все 44.
   !important здесь не про силу правила, а про инлайн: кнопку «Завершить смену» собирает
   session.mjs со строкой style="border:0", и без него добор тач-цели у неё пропадал — именно эта
   кнопка и стояла на снимке владельца вдвое выше соседнего чипа роли. */
.top button.chip{border:0;border-block:6px solid transparent!important;background-clip:padding-box;margin-block:-6px;min-height:var(--h);color:inherit;font:inherit;cursor:pointer}
.chip .dot{width:8px;height:8px;border-radius:50%;background:var(--live);display:inline-block;margin-right:var(--s2)}
/* Полоса адресована старшему смене, а высоту отнимает у сборщика на каждом экране. Кегль базовый
   (13px читались хуже соседнего текста), высоту держит плотное поле. Междустрочие тут общее,
   текстовое: своё значение 1.35 расходилось с полосой очереди, где кнопка наследовала 1.55. */
/* Правое поле держит и меру чтения: на мониторе строка тревоги растягивалась на 148 знаков при
   норме 65. Своего контейнера внутри полосы нет, поэтому ширину текста ограничивает поле. */
.alert{background:var(--bad);color:var(--card);padding-top:var(--s2);padding-right:max(var(--s4),env(safe-area-inset-right,0px),calc(100% - var(--mera) - var(--s4)));padding-bottom:var(--s2);padding-left:max(var(--s4),env(safe-area-inset-left,0px));font-size:var(--f3);display:none}
/* Янтарная полоса — состояние, которое надо закрыть до конца смены (забытые короба, сухой
   прогон). Красная остаётся аварии: обмен с WB остановлен, сервер отклонил операции, нет связи. */
.alert.amber{background:var(--warnbg);color:var(--warn-ink);box-shadow:inset 0 -1px 0 var(--warn-line)}
.alert.on{display:block}
/* Полосы тревоги рождаются в разное время (одни по ответу /counters, полоса очереди — по своему
   таймеру) и вставляются в конец уже вставленных, поэтому их порядок был случайным. Здесь он
   задан раз и навсегда, сверху вниз по цене простоя: остановленный обмен с WB, закрытые коробы,
   незаконченные операции планшета. Сухого прогона в этом ряду нет: он состояние, а не событие,
   и живёт чипом в шапке (app.mjs, dryChip). */
#wbBar{order:1}#alertBar{order:2}#queueBar{order:3}
.main{flex:1;display:flex;min-height:0;order:5}
/* Ширину держит обёртка, а не .nav: плашка «Идёт упаковка» иначе распирает колонку в момент
   сверки этикетки. Прокрутка у меню своя — 18 пунктов не помещаются в экран планшета. */
.side{--nav-bg:var(--row);--nav-surface:var(--card);--nav-text:var(--txt);--nav-muted:var(--dim);--nav-accent:var(--acc);
 --nav-border:var(--line);--nav-hover:var(--card);--nav-active:var(--sel);--nav-focus:var(--acc);
 --nav-h:44px;--nav-sub-h:40px;
 /* 288, а не 252: самая длинная подпись со счётчиком — «Приёмка возвратов» — просила 144
    точки при 143 доступных и резалась многоточием ровно на один пиксель. Ширины впритык мало:
    следующий раздел с длинным именем повторил бы историю, поэтому берём с запасом. */
 width:288px;flex-shrink:0;display:flex;flex-direction:column;min-height:0}
/* Строка раскрытия меню живёт только на узком экране; на рабочем столе список виден всегда. */
.navsum{display:none}
.nav{width:100%;flex:1;min-height:0;padding:var(--s3) var(--s2) var(--s4);overflow:auto;background:var(--nav-bg);
 border-right:1px solid var(--nav-border);scrollbar-width:thin;scrollbar-color:var(--line2) transparent}
.nav button{position:relative;display:flex;align-items:center;width:100%;height:var(--nav-h);min-height:var(--nav-h);
 gap:var(--s2);padding:0 var(--s3);overflow:hidden;border:0;border-radius:var(--r0);background:transparent;color:var(--nav-text);
 font:var(--w-med) var(--f2)/20px var(--ui);text-align:left;cursor:pointer;transition:background-color .15s ease,color .15s ease,box-shadow .15s ease}
.nav button.has-badge{padding-right:52px}
.nav button.has-icon{padding-left:calc(var(--s3) + 28px)}
.nav .navlabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav .navicon{position:absolute;left:var(--s3);width:16px;height:16px;display:flex;align-items:center;justify-content:center;color:var(--nav-muted);pointer-events:none}
.nav .navicon svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.nav button.on .navicon{color:var(--nav-accent)}
.nav button.on{background:var(--nav-active);color:var(--nav-accent);font-weight:var(--w-b)}
.nav .grp{padding:var(--s3) var(--s3) var(--s1);color:var(--nav-muted);font-size:11px;line-height:16px;
 font-weight:var(--w-b);text-transform:uppercase;letter-spacing:.65px}
.nav .badge{position:absolute;right:var(--s3);top:50%;transform:translateY(-50%);
 display:inline-flex;align-items:center;justify-content:center;
 width:46px;height:20px;padding:0;border-radius:var(--r3);background:var(--acc);color:var(--card);
 font:var(--w-b) 12px/16px var(--mono);font-variant-numeric:tabular-nums;letter-spacing:.2px;
 text-align:center}
.nav .badge.r{background:var(--bad)}.nav .badge.y{background:var(--warn)}
.nav.frozen{opacity:.42;pointer-events:none}
.nav button.soon,.nav button.soon.on{color:var(--nav-muted);font-weight:var(--w-txt)}
.nav button.soon.on{background:var(--nav-surface)}
.nav button.soon i{flex:none;margin-left:auto;padding:2px var(--s2);border-radius:var(--r3);background:var(--nav-surface);
 font-size:11px;line-height:16px;font-style:normal}
.nav button:focus-visible,.navsum:focus-visible{z-index:2;outline:2px solid var(--nav-focus);outline-offset:2px}
.navlock{display:none;padding:var(--s3) var(--s4);font-size:16px;color:var(--bad);background:var(--badbg)}
.navlock.on{display:block}
/* min-width:0 обязателен: иначе широкая таблица распирает flex-элемент и уезжает за край экрана.
   position:relative держит внутри себя подписи для диктора: они набраны position:absolute, и без
   позиционированного предка их считает документ, а не прокручиваемая страница. На упаковке это
   растило документ до 5927px при окне 768 — планшет уводил вверх всё разом: шапку со связью,
   меню и панель со сканом, а под окном оставалось пустое поле. */
.page{position:relative;flex:1;min-width:0;padding:var(--s5);overflow:auto}
h1{font-size:var(--f5);line-height:var(--lh-tight);font-weight:var(--w-b);letter-spacing:-.01em;margin:0 0 var(--s1)}
/* Пояснение читают глазами, а не «просматривают»: кегль базовый, мера строки в норме чтения
   (45–75 знаков). Прежние 78ch при 13px давали 78 знаков в строке на планшете и мониторе. */
/* Вес задан явно: внутри label пояснение наследовало 500 и на экране настроек стояло полужирнее,
   чем такое же пояснение рядом. */
.sub{color:var(--dim);font:var(--w-txt) var(--f3)/var(--lh) var(--ui);max-width:var(--mera);margin-bottom:var(--s3)}
.screen{display:none}.screen.on{display:block}
.btn{background:var(--acc);color:var(--card);border:0;border-radius:var(--r1);padding:var(--s3) var(--s5);min-height:var(--h);font:var(--w-ctl) var(--f3)/var(--lh-tight) var(--ui);cursor:pointer}
/* Серая кнопка стоит на белой карточке и отличается от неё на 1,09:1 — то есть ничем. Край даёт
   внутренняя тень: она не двигает раскладку, в отличие от рамки. */
.btn.gray{background:var(--row);color:var(--txt);box-shadow:var(--ring-edge)}
.btn.dark{background:var(--dark)}
.btn.green{background:var(--ok)}.btn.red{background:var(--bad)}.btn.orange{background:var(--amber)}
.btn.sm{padding:var(--s2) var(--s3);min-width:var(--h);min-height:var(--h);font-size:var(--f3)}
.btn.wide{width:100%}
/* Крупная кнопка отличается от обычной высотой и полем, но не кеглем: на 18px надпись главного
   действия разворачивалась в две строки и min-height:56 переставал что-либо держать. */
.btn.big{padding:var(--s4) var(--s5);min-height:var(--h-lg);font-size:var(--f3)}
/* Выключенная кнопка гасится цветом, а не прозрачностью: под opacity .38 надпись «Это вы» давала
   2,36:1 и не читалась вовсе. Серая заливка с приглушённым текстом — 5,2:1 и та же ясность,
   что кнопка не нажимается. */
.btn:disabled{background:var(--row);color:var(--dim);box-shadow:var(--ring-edge);cursor:not-allowed}
.btn:active{transform:translateY(1px)}
/* Ховер пункта меню белым: лента меню теперь на общей серой подложке, и любой светло-синий
   оттенок здесь путался бы с активным пунктом. */
@media(hover:hover){.btn:hover:enabled{filter:brightness(1.06)}.btn.orange:hover:enabled{filter:brightness(.92)}
 .nav button:hover,.navsum:hover{background:var(--nav-hover)}
 .nav button:hover .navicon{color:var(--nav-text)}.top button.chip:hover{background-color:rgba(255,255,255,.22)}
 input:hover,select:hover{border-color:var(--acc)}
 .x:hover{background:var(--row)}.photo:not(.big):hover,.grid button.pick:hover{box-shadow:var(--ring-acc)}
 .seg button:hover,.fold:hover,.link-btn:hover{background:var(--sel);color:var(--acc)}
 /* background-color, а не сокращённое background: оно сбросило бы background-clip тег-кнопки,
    и подсветка при наведении растянулась бы на всю тач-цель вместо самой пилюли. */
 .tag-button:hover{background-color:var(--sel);color:var(--acc)}}
:is(.btn,.nav button,.navsum,.top button.chip,.seg button,.tag-button,.fold,.link-btn,.photo:not(.big),.grid button,.kpi>button):active{transform:translateY(1px);filter:brightness(.94)}
:is(input,select):active{border-color:var(--acc)}
:focus-visible{outline:3px solid var(--acc);outline-offset:2px}
@media(forced-colors:active){:focus-visible{outline-color:Highlight}}
.row{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center}
.card{border:1px solid var(--line);border-radius:var(--r2);padding:var(--s4);margin-bottom:var(--s3);background:var(--card)}
/* Обёртка таблицы бывает в двух состояниях, и разница принципиальная. Любой overflow делает её
   скроллпортом, и шапка липнет к НЕЙ; по вертикали такая обёртка не прокручивается никогда, поэтому
   шапка просто уезжала вместе со строками — в журнале это «кто» против «что», в очереди печати
   «попыток» против «заданий». Правильных состояний два:
   — таблица умещается по ширине (класс fits, его ставит ui.mjs) — обёртка перестаёт быть
     скроллпортом, прокрутка одна на всю страницу, шапка липнет к ней;
   — не умещается — обёртка получает обе прокрутки разом (канонический приём для таблиц данных),
     и шапка липнет к её верху.
   Порядок правил важен: fits идёт последним и снимает и max-height, и overflow. */
.tw{overflow:auto;max-height:70dvh}
.tw.fits{overflow:visible;max-height:none}
table{width:100%;border-collapse:collapse;font-size:var(--f3)}
/* Поле ячейки уплотнено по вертикали: кегль таблиц поднят до базового (14px были ниже порога
   чтения), и без этого строка выросла бы на высоту лишней строки текста. */
th,td{padding:var(--s2) var(--s3);border-bottom:1px solid var(--line);text-align:left;vertical-align:middle}
/* --stick — высота липкой панели открытого экрана (её меряет ui.mjs): под панелью упаковки шапка
   иначе прилипает ровно за ней и не видна. В модалке панели нет, там смещение снимается.
   Перенос заголовку разрешён намеренно: запрет делал минимальной шириной колонки всю фразу, а она
   набрана прописными с трекингом и кеглем строки — «ЧТО ПЕЧАТАЕТСЯ» и «СПОСОБ ПЕЧАТИ» держали
   колонку шире её данных и уводили таблицы за край на планшете 1024. Тем же запретом растягивало
   заголовки строк: «расхождения остатков при последнем пересчёте» в «Базовой линии» — один th. */
th{position:sticky;top:var(--stick,0px);z-index:var(--z-th);background:var(--card);color:var(--dim);font-size:var(--f3);font-weight:var(--w-ctl);text-transform:uppercase;letter-spacing:.4px}
.modal th{top:0}
/* Смещение под панель верно, только пока прокрутка страничная. Когда обёртка не уместила таблицу,
   прокручивается она сама, и шапка обязана липнуть к её верху: на упаковке при 360px --stick=314px
   роняло шапку на 314px внутрь окна высотой 532px — над ней оставались строки без заголовков. */
.tw:not(.fits) th{top:0}
td.n,th.n{text-align:right}
td.n{font-family:var(--mono)}
/* Строка непрозрачна: под ней проезжает липкая шапка, и на просвет читались бы обе разом.
   Колонка действий больше не липнет: пока таблица шире экрана, прилипший столбец ложился поверх
   соседних данных — на «Не найдено» он закрывал 93 px из 112 у колонки «Решить до», а тег
   «после печати» обрезал до «посл». Кнопка теперь доезжает той же прокруткой, что и данные. */
table tr{background:var(--card)}
td .btn{white-space:nowrap}
/* Пара кнопок в ячейке разделена в разметке одним пробелом. При переносе в столбик margin-left
   не работает вовсе, и «Взял» с «Товара нет» стояли впритык — поле задано с обеих сторон. */
td .btn+.btn{margin-left:var(--s4)}
td .btn{margin-block:var(--s1)}
/* Подсветку строки держит один класс, поэтому белый фон выше набран слабым селектором:
   усилите его до .tw table tr — и выделенная строка снова станет белой. */
tr.sel{background:var(--sel)}
/* Своя позиция отличалась от чужой только заливкой 1,09:1 — под потолочным светом склада это
   не признак. Метка на краю строки держит 5,1:1 к её фону, то есть видна и без разбора оттенков. */
tr.mine{background:var(--mine)}
tr.mine>:first-child{box-shadow:inset 4px 0 0 var(--ok)}
.rcard.mine{border-left:4px solid var(--ok)}
/* Пометка строки состоянием: .hurt — срок вышел, .warm — состояние к закрытию (закрытый короб,
   непустой карантин). Класс не привязан к tr: карточку карантина на отгрузке метят им же. */
.hurt{background:var(--row-hurt)}
.warm{background:var(--row-warm)}
/* Подсветка строки под курсором — глаз не срывается на соседнюю в широких таблицах. Выделенные
   и помеченные строки исключены: их цвет важнее ховера — просроченная не должна белеть ровно
   в тот миг, когда на неё навели мышь, чтобы разобрать. */
@media(hover:hover){table tr:not(.sel):not(.mine):not(.gone):not(.hurt):not(.warm):hover{background:var(--row-hi)}}
tr.gone{opacity:.5}
.kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s3);margin-bottom:var(--s4)}
/* Только прямой потомок: селектор потомка красил и число, и подпись — серые прямоугольники
   ложились поверх заливки тревожной плитки, а двойной отступ выдавливал слово за её край. */
/* Минимальная высота одна у всех плиток ряда, а не только у кликабельных: раньше высоту задавало
   число строк подписи, и на одном экране рядом стояли плитки 78,7 и 103,5. */
.kpi>div,.kpi>button{background:var(--row);border:0;border-radius:var(--r2);padding:var(--s3) var(--s4);min-height:var(--h-tile);text-align:left;color:inherit;font:inherit}
.kpi>button{cursor:pointer}
.kpi .v{display:block;font:var(--w-b) var(--f6)/var(--lh-tight) var(--mono)}.kpi .l{display:block;color:var(--dim);font-size:var(--f3)}
.kpi .v.word{font:var(--w-b) var(--f4)/var(--lh-tight) var(--ui)}
/* Заливкой выделяется одна плитка — старшая тревога; остальные разведены цветом числа,
   иначе рядом стоят три цветных пятна и глазу не за что зацепиться. */
.kpi .hot{background:var(--badbg)}
.kpi .hot .v{color:var(--bad);font-size:var(--f7)}
.kpi .soft .v{color:var(--warn)}
.kpi .zero .v{color:var(--dim)}
/* Кликабельные плитки (журнал фильтруется по ним) отвечают на наведение — иначе о роли плитки
   узнают только методом тыка. */
@media(hover:hover){.kpi>[data-act]:hover{box-shadow:var(--ring-line)}}
.ok,.bad,.warn,.note{border-radius:var(--r2);padding:var(--s3) var(--s4);margin:var(--s3) 0;font-size:var(--f3)}
.ok{background:var(--okbg);color:var(--ok-ink)}
.bad{background:var(--badbg);color:var(--bad)}
.warn{background:var(--warnbg);color:var(--warn-ink)}
/* Причина отказа внутри плашки набрана .sub — серым по цветному фону она почти пропадает. */
.ok .sub,.bad .sub,.warn .sub{color:inherit;opacity:.85;margin-bottom:0}
/* Спокойное пояснение: постоянная инструкция не должна носить цвет тревоги. Ширина ограничена
   мерой чтения — на мониторе строка растягивалась на 169 знаков, и глаз терял начало следующей. */
.note{background:var(--row);border-left:3px solid var(--line2);max-width:var(--mera)}
/* Блок сканирования — главный элемент смены: единственная на экране крупная строка действия.
   Красный оставлен отказу, состояние lock штатно наступает на каждом заказе. */
.scan{border:1px solid var(--edge);border-radius:var(--r2);padding:var(--s4);background:var(--row-hi);margin-bottom:var(--s3)}
.scan .act{font-size:var(--f4);font-weight:var(--w-b);line-height:var(--lh-tight);text-align:center;margin-bottom:var(--s3);color:var(--acc)}
/* Поле скана — единственное крупное поле смены, и «крупный» размер у него тот же, что у крупной
   кнопки: 56 по высоте, кегль 20. Прежние 18px/56,6 не совпадали ни с одной ступенью. */
.scan input{width:100%;padding:var(--s3);min-height:var(--h-lg);font:var(--w-ctl) var(--f4)/var(--lh-tight) var(--mono);border:1px solid var(--edge);border-radius:var(--r1);text-align:center}
.scan .hint{text-align:center;color:var(--dim);font-size:var(--f3);margin-top:var(--s2)}
.scan.lock{border-color:var(--line2);background:var(--row)}
.scan.lock .act{color:var(--txt)}
.scan.err{border-color:var(--bad);background:var(--bad)}
.scan.err .act,.scan.err .hint{color:var(--card)}
.scan .cmp{display:flex;gap:var(--s4);justify-content:center;color:var(--card);font-size:var(--f3);margin-top:var(--s2);flex-wrap:wrap}
.scan .cmp b{display:block;font:var(--w-b) var(--f4)/var(--lh-tight) var(--mono)}
/* Поля панели белые с обеих сторон: без нижнего под ней остаётся незакрашенная щель, в которой
   при прокрутке мелькает текст. Отрицательного верхнего поля тут быть не должно — оно затягивало
   панель на 8px под заголовок и срезало нижние выносные букв. */
.sticky{position:sticky;top:0;background:var(--card);padding:var(--s3) 0;z-index:var(--z-sticky)}
.steps{display:flex;gap:var(--s2);margin-bottom:var(--s3)}
/* Шаг отвечает на вопрос «что сейчас сканировать», а был набран самым мелким кеглем приложения.
   Кегль базовый, поле тоньше — строка шагов от этого стала ниже, а не выше. */
/* Шаг не кликается, поэтому и весом отличается от кнопки: 500 у пройденного и предстоящего,
   600 — у текущего. С общим 600 строка шагов читалась как ряд кнопок, по которым не нажимается. */
.steps div{flex:1;padding:var(--s2) var(--s3);border-radius:var(--r1);background:var(--row);color:var(--dim);font:var(--w-med) var(--f3)/var(--lh-tight) var(--ui);text-align:center}
.steps div.on{background:var(--sel);color:var(--acc);font-weight:var(--w-ctl)}
.steps div.done{background:var(--okbg);color:var(--ok)}
.sticker{border:1px solid var(--txt);border-radius:var(--r1);padding:var(--s3);width:200px;text-align:center;background:var(--card)}
.sticker .code{font:var(--w-b) var(--f7)/var(--lh-tight) var(--mono);overflow-wrap:anywhere}
.photo{width:100px;height:100px;border-radius:var(--r2);border:1px solid var(--edge);background:linear-gradient(135deg,var(--sel),var(--row));
 padding:0;display:flex;align-items:center;justify-content:center;font:var(--f7)/var(--lh-tight) var(--ui);color:inherit;flex-shrink:0;cursor:pointer}
.photo.sm{width:var(--h);height:var(--h);font-size:var(--f4);border-radius:var(--r1)}
/* Крупная карточка фото — вдвое больше обычной, и глиф-заглушка в ней тоже удвоенная ступень:
   собственного значения 74px в шкале нет и быть не должно. */
.photo.big{width:200px;height:200px;font-size:calc(var(--f7) * 2);cursor:default}
.photo img{width:100%;height:100%;object-fit:cover;border-radius:inherit}
.prog{height:8px;background:var(--edge);border-radius:var(--r3);overflow:hidden;margin:var(--s2) 0}
.prog i{display:block;height:100%;background:var(--ok);width:0;transition:width .3s}
/* Окно живёт в ВИДИМОЙ части экрана, а не во всём вьюпорте: на телефоне клавиатура закрывает
   низ, и кнопка подтверждения оказывалась под ней — операцию нечем было закрыть. Высоту и
   смещение видимой области считает ui.mjs по visualViewport (--vvh/--vvt); запасные значения
   на случай, если его нет, — обычные dvh. */
.modal{position:fixed;left:0;right:0;top:var(--vvt,0px);height:var(--vvh,100dvh);background:rgba(15,20,30,.55);display:none;align-items:center;justify-content:center;padding:var(--s5);z-index:var(--z-modal)}
.modal.on{display:flex}
/* anywhere, а не break-word: в окне сплошь и рядом строки без пробелов — артикул WB заголовком,
   штрихкод, код короба, путь операции в очереди. break-word оставляет им ширину целого слова, и
   тег со штрихкодом или заголовок с артикулом вылезал за белый прямоугольник и обрезался краем
   окна (окно шириной 374 против заголовка в 921 — то самое «Печатать некуда» со снимка). */
/* Три полосы окна: шапка (заголовок и крестик), тело с прокруткой, подвал с кнопками. Поля
   держат полосы, а не коробка: прокручиваться должно только тело, иначе закреплённый крестик
   едет поверх текста и закрывает буквы своей плашкой. */
.modal .box{--pad:var(--s5);background:var(--card);border-radius:var(--r2);max-width:720px;width:100%;max-height:100%;display:flex;flex-direction:column;overflow:hidden;position:relative;
 overflow-wrap:anywhere;box-shadow:var(--sh-modal)}
/* Высота шапки не ниже крестика с его полем: иначе кнопка свисает в тело и закрывает первую
   строку текста — ровно то, от чего окно и лечили. Поле считается вместе с прозрачной тач-целью:
   видимый квадрат 32, а занимает кнопка 44 и стоит на 6 выше поля бокса, поэтому к --h-chip идёт
   ещё шаг шкалы. Без него нижние 6px кнопки свисали в тело, и касание по первой строке текста
   закрывало окно — на «Не хватило товара» это стирало уже набранное количество. */
.modal .mhead{flex:none;position:relative;min-height:calc(var(--pad) + var(--h-chip) + var(--s2));padding:var(--pad) var(--pad) 0}
.modal .mbody{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 var(--pad) var(--pad)}
/* Таблица внутри окна живёт по своим правилам: у неё есть прокрутка вбок, и рвать код по буквам
   там незачем — сверять его глазами после разрыва невозможно. */
.modal .tw{overflow-wrap:normal}
/* Заголовку нужно поле под крестик: без него длинная строка («Закрыть короба и передать
   в доставку») подлезает под кнопку закрытия. */
.modal h2{margin:0 0 var(--s2);font-size:var(--f4);font-weight:var(--w-b);line-height:var(--lh-tight);padding-right:calc(var(--pad) + var(--h-chip))}
/* Сообщение без своего заголовка целиком попадает в h2 (ui.mjs, say). Длинному тексту заголовочный
   кегль не идёт: восемь строк полужирного 20px занимали весь экран телефона при пустом теле окна.
   Поле под крестик остаётся, а вес и междустрочие — как у обычного текста. */
.modal h2.msg{font-size:var(--f3);font-weight:var(--w-txt);line-height:var(--lh);margin-bottom:var(--s3)}
.modal .mbody>.btn,.modal .mbody>.row{margin-top:var(--s4)}
/* Подвал окна собирает ui.mjs: замыкающие кнопки прилипают к низу и остаются на виду, сколько
   бы ни было текста выше и как бы ни выросла клавиатура. */
/* Подвал отбрасывает тень вверх на 16px. Тело обязано оставить под ней свободное место: без него
   последнее поле кончалось ровно на границе подвала, и тень закрывала низ поля и его кольцо
   фокуса. В «Входе» это выглядело так, будто пин обрезан кнопкой «Войти». Отступ входит в
   прокручиваемое тело: подвал остаётся на виду, а длинное окно по-прежнему прокручивает только
   содержимое. */
.modal .box.hasfoot .mbody{padding-bottom:var(--s4)}
/* Поле подвала одинаково сверху и снизу, поэтому подвал с одной кнопкой везде одной высоты:
   раньше нижнее поле тянулось за полем окна и давало 72 на телефоне против 80 на мониторе,
   а отбивка от текста складывалась из 16 отступа и 12 поля — 28, значения вне шкалы. */
.mfoot{flex:none;display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;background:var(--card);
 padding:var(--s3) var(--pad) calc(var(--s3) + env(safe-area-inset-bottom,0px));box-shadow:var(--sh-foot)}
/* !important гасит инлайновые margin-top у кнопок: они проставлены в двух десятках окон, и
   в подвале дали бы каждому окну свой случайный отступ. */
.mfoot>*{margin:0!important}
.mfoot>.row{flex:1 1 auto}
/* Тач-цель крестика 44px растим полем, а не размером: видимый квадрат 32px (та же видимая высота,
   что у чипа и тега) стоит ровно на поле бокса, а палец попадает по области вокруг. Раньше кнопка
   44px была вдавлена внутрь окна и выбивалась из сетки полей. */
/* Крестик стоит в шапке окна: она не прокручивается, поэтому кнопка видна и в длинном окне,
   а текст под неё не заезжает — прокручивается тело ниже. */
.x{position:absolute;right:var(--pad);top:var(--pad);width:var(--h-chip);height:var(--h-chip);padding:6px;margin:-6px;box-sizing:content-box;
 display:flex;align-items:center;justify-content:center;border:0;background:none;border-radius:var(--r1);font-size:var(--f4);cursor:pointer;color:var(--dim)}
/* Тег переносится по словам: перечень коробов одним nowrap-элементом шире экрана телефона.
   Видимая высота одна с чипом шапки: пилюля есть пилюля, где бы она ни стояла. */
.tag{display:inline-flex;align-items:center;min-height:var(--h-chip);background:var(--row);border-radius:var(--r3);padding:var(--s1) var(--s3);color:var(--dim);font:var(--w-med) var(--f3)/var(--lh-tight) var(--ui)}
.tag.g{background:var(--okbg);color:var(--ok)}.tag.r{background:var(--badbg);color:var(--bad)}
.tag.y{background:var(--warnbg);color:var(--warn)}
.tag.b{background:var(--sel);color:var(--acc)}
/* Тег-кнопка внешне не отличается от тега: те же 32 видимой высоты, а 44 тач-цели добраны
   прозрачной рамкой, как у чипа-кнопки. Раньше она росла до 44 плашкой и в строке тегов стояла
   на 13,6px выше соседей. */
.tag-button{border:0;border-block:6px solid transparent;background-clip:padding-box;margin-block:-6px;min-height:var(--h);cursor:pointer;font:var(--w-med) var(--f3)/var(--lh-tight) var(--ui)}
.fold{display:inline-grid;place-items:center;width:var(--h);height:var(--h);margin:-10px 0 -10px -10px;border:0;background:transparent;color:inherit;font:var(--f3)/var(--lh-tight) var(--ui);cursor:pointer}
.link-btn{display:inline-flex;align-items:center;min-height:var(--h);padding:0 var(--s2);border:0;background:transparent;color:var(--acc);font:inherit;text-decoration:underline;cursor:pointer}
/* Шрифт задан явно: подпись живёт внутри td.n, а та переведена на моноширинный ради разрядов. */
.dim{color:var(--dim);font:var(--w-txt) var(--f3)/var(--lh) var(--ui)}
label{display:block;font-size:var(--f1);font-weight:var(--w-med);color:var(--dim);margin-bottom:var(--s1)}
/* 16px — порог, ниже которого Safari масштабирует страницу при фокусе и обратно не откатывает. */
/* max-width держит поля внутри карточки: ширины 170–280px проставлены в разметке инлайном,
   и на экране 320px поиск по стикеру вылезал за правый край. */
/* Высота задана, а не выведена из содержимого: у select своя высота строки, и в одном ряду
   с полем ввода он стоял на 45 против 44 — разницу видно на стыке фильтров журнала. */
input.txt,select.txt{width:100%;max-width:100%;padding:var(--s3);height:var(--h);min-height:var(--h);font-size:var(--f3);line-height:var(--lh-tight);border:1px solid var(--edge);border-radius:var(--r1);background:var(--card);color:var(--txt)}
/* Плейсхолдер набирается тем же шрифтом, что и ввод, но приглушён: серый текст того же кегля
   читается как «это поле пустое», а не как чужой ввод. */
::placeholder{color:var(--placeholder);opacity:1}
.scan input::placeholder{font-weight:var(--w-ctl)}
input.qty{width:var(--w-s);padding:var(--s3);height:var(--h);min-height:var(--h);font:var(--w-b) var(--f3)/var(--lh-tight) var(--mono);text-align:center;border:1px solid var(--edge);border-radius:var(--r1)}
input.err,select.err{border-color:var(--bad);background:var(--badbg)}
/* Ореол вместо голой рамки: на тач-экране :focus-visible молчит, и без него не видно, куда
   прилетит следующий скан или символ. Общее кольцо 3px при этом остаётся: outline:none здесь
   отбирал его у полей, и с клавиатуры фокус на поле был втрое тоньше, чем на кнопке. */
input.txt:focus,select.txt:focus,input.qty:focus,.scan input:focus{border-color:var(--acc);box-shadow:var(--ring)}
input.err:focus,select.err:focus{border-color:var(--bad);box-shadow:var(--ring-bad)}
/* Флажок отмечает заказ к отправке — главное действие экрана, и жмут по нему стоя, в перчатке.
   Системный квадрат не умеет расти полем: 24×24 оставались тач-целью при норме 44×44. Рисуем сам
   флажок (appearance:none), тогда 44 — это размер цели, а 24 — размер видимого квадрата. */
input[type=checkbox]{appearance:none;-webkit-appearance:none;width:var(--h);height:var(--h);flex:0 0 var(--h);margin:0;padding:0;border:0;background:none;display:inline-grid;place-content:center;cursor:pointer;color:var(--txt)}
input[type=checkbox]::before{content:"";grid-area:1/1;width:24px;height:24px;border:2px solid var(--edge);border-radius:var(--r0);background:var(--card)}
input[type=checkbox]:checked::before{background:var(--acc);border-color:var(--acc)}
/* Галочка — две стороны рамки, повёрнутые на 45°: рисунок в data-URI пришлось бы держать
   литеральным цветом, а палитра живёт только в :root. */
input[type=checkbox]:checked::after{content:"";grid-area:1/1;place-self:center;width:12px;height:6px;border:solid var(--card);border-width:0 0 3px 3px;transform:translateY(-2px) rotate(-45deg)}
input[type=checkbox]:disabled{cursor:not-allowed}
input[type=checkbox]:disabled::before{background:var(--row);border-color:var(--line2)}
/* Строка с флажком держит тач-цель флексом. Label со своей раскладкой исключены: правило с :has
   перебивает класс по специфичности и отбирает у них display. У .setting-toggle это ломало сетку
   «флажок слева, заголовок и пояснение под ним», у .row — блочную строку списка наклеенных
   этикеток: inline-flex ужимал её по содержимому и ставил по две в ряд. */
label:has(input[type=checkbox]):not(.row,.setting-toggle){min-height:var(--h);display:inline-flex;align-items:center;gap:0}
/* Тач-цель теперь держит сам флажок (44×44), а ячейке остаётся дать ему место: колонка выбора
   размечена в экранах шириной 44px, и с обычным полем ячейки квадрат ужимался до 32px. */
td:has(>input[type=checkbox]){padding:0;min-width:var(--h);text-align:center}
.mono{font-family:var(--mono);font-size:var(--f3)}
.big-n{font:var(--w-b) var(--f6)/var(--lh-tight) var(--mono)}
.grid{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s2) 0}
/* В плитке пачки остался один хвост номера (pack.mjs, grid): подпись и угловой индекс убраны,
   поэтому здесь нет ни правил для них, ни position:relative под угловой индекс. */
/* margin:0 обязателен: подтверждённая плитка получает класс ok, а он идёт от плашек с отбивкой
   сверху и снизу — ряды сетки разъезжались по мере подтверждения стикеров в пачке. */
/* Плитка сетки — тач-цель: без своей высоты и кегля кнопка получала браузерный дефолт 13,33px
   и вставала на 37px против 44 у соседних управляющих элементов. */
.grid b,.grid button{display:flex;align-items:center;justify-content:center;min-width:96px;min-height:var(--h);margin:0;padding:var(--s2) var(--s3);border:0;border-radius:var(--r1);background:var(--row);color:inherit;font:var(--w-txt) var(--f3)/var(--lh-tight) var(--ui)}
.grid :is(b,button) u{display:block;font:var(--w-b) var(--f3)/var(--lh-tight) var(--mono);text-decoration:none}
.grid button.pick{cursor:pointer}
.grid b.ok{background:var(--okbg);color:var(--ok)}
.grid button.rp{background:var(--warnbg);color:var(--warn)}
.alert-action{width:100%;border:0;text-align:left;font:inherit;cursor:pointer}
/* Переключатель встаёт вровень с полем и кнопкой в той же строке: своего поля у контейнера нет,
   высоту задаёт кнопка внутри, радиус тот же, что у кнопки. Прежние 4px поля делали контейнер 52
   против 44 у поля рядом. Подпись не переносится — иначе на телефоне сегмент раздувался до 70. */
.seg{display:inline-flex;max-width:100%;overflow:auto;background:var(--row);border-radius:var(--r1);gap:var(--s1)}
.seg button{border:0;background:none;padding:var(--s2) var(--s3);min-height:var(--h);border-radius:var(--r1);color:var(--dim);font:var(--w-med) var(--f3)/var(--lh-tight) var(--ui);white-space:nowrap;cursor:pointer}
.seg button.on{background:var(--card);color:var(--acc);font-weight:var(--w-ctl)}
.bar{background:var(--row);border-radius:var(--r2);padding:var(--s3) var(--s4);margin-bottom:var(--s3);display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
.bar b{font-size:var(--f3);font-weight:var(--w-b)}
/* Указание маршрута важнее отчёта о пройденном. Вес адресу даёт .bar b, а подсветка отделяет
   его от счётчика «пройдено N из M», который стоит рядом тегом. */
#pickNext{background:var(--sel);color:var(--acc);border-radius:var(--r1);padding:var(--s2) var(--s3)}
/* Нижняя липкая полоса поднята над вырезом телефона: под ней живая кнопка отправки. Пустую полосу
   убираем совсем: на узком экране она закреплена у низа окна и пустой отнимала бы у работы полосу
   в четверть сантиметра. */
.foot:empty{display:none}
/* Полоса действий — один компонент на всех размерах: тот же слой и та же тень, что у подвала
   окна. Раньше на мониторе она была без слоя и без тени, а на телефоне со слоем и тенью — два
   разных вида одного и того же места. */
.foot{position:sticky;bottom:0;z-index:var(--z-foot);background:var(--card);box-shadow:var(--sh-foot);padding:var(--s3) 0;
 padding-bottom:calc(var(--s3) + env(safe-area-inset-bottom,0px));display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
.card.cards{display:none}
.admin-mobile{display:none}
.setting-toggle{display:grid;grid-template-columns:var(--h) minmax(0,1fr);align-items:start;gap:var(--s1) 0}
.setting-toggle>input{grid-row:1/span 2;margin:0}.setting-toggle>b,.setting-toggle>.sub{grid-column:2}
.admin-record{border-top:1px solid var(--line);padding:var(--s3) 0}
.admin-record:first-child{border-top:0}
.admin-record__head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3)}
.admin-record__head>div{min-width:0}
.admin-product{display:grid;grid-template-columns:var(--h) minmax(0,1fr);gap:var(--s3);align-items:center;margin-top:var(--s3)}
.admin-label,.admin-facts dt{display:block;color:var(--dim);font-size:var(--f1);font-weight:var(--w-ctl);text-transform:uppercase;letter-spacing:.4px}
.admin-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2) var(--s3);margin:var(--s3) 0 0}
.admin-facts div{min-width:0}.admin-facts dt,.admin-facts dd{margin:0}.admin-facts dd{overflow-wrap:anywhere}
.admin-total{display:flex;align-items:center;justify-content:space-between;margin-top:var(--s3);padding-top:var(--s2);border-top:1px solid var(--line)}
/* Итог списка — то же число, что в плитке показателей, значит и кегль тот же. */
.admin-total b,.admin-delta{font:var(--w-b) var(--f6)/var(--lh-tight) var(--mono)}
.admin-delta.plus{color:var(--ok)}.admin-delta.minus{color:var(--bad)}
.rcard{border:1px solid var(--line);border-radius:var(--r2);padding:var(--s3);margin-bottom:var(--s2)}
/* Перенос обязателен: номер ячейки набран 26px моно, и на телефоне «№СТ-12-345» вместе
   с количеством и сроком не помещается в строку — карточка распирала бы страницу вбок. */
.rcard .hd{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
.rcard .cell{font:var(--w-b) var(--f6)/var(--lh-tight) var(--mono)}
.rcard .qty{font:var(--w-b) var(--f6)/var(--lh-tight) var(--mono);color:var(--acc)}
/* На тач-экране мелкая кнопка в строке таблицы обязана держать палец; на мыши она остаётся плотной.
   Блок стоит ниже .btn.sm и .seg button: медиазапрос специфичности не добавляет, и выше по файлу
   его перебивало бы обычное правило сегмента. */
@media(pointer:coarse){.btn.sm{min-height:44px;padding:var(--s3) var(--s4)}.seg button{min-height:44px;padding:var(--s3) var(--s4)}
 /* Пункт меню уже держит 48 px независимо от типа указателя: устройство может не сообщить
    coarse до первого касания. Чипы шапки увеличиваем только на настоящем тач-экране. */
 .chip{padding-top:var(--s2);padding-bottom:var(--s2)}}
/* Три режима вместо одного рубежа. До 640 — телефон. 641–1199 — планшет и ноутбук с узким
   окном: меню раскрывается сверху, карточки заменяют широкие таблицы, кнопки идут в столбик.
   От 1200 — рабочий стол, от 1440 — большой монитор: окно расширяется, чтобы таблицы занимали
   ширину, а не жались в колонку между пустыми полями. */
@media(max-width:1199px){
 .main{flex-direction:column}
 /* Лента шириной 2500–3250 px показывала один-три пункта из полутора десятков, а названия групп
    в ней прятались вовсе: до «Показателей» доходили листанием вслепую. Меню сложено в строку
    с текущим разделом и раскрывается списком — те же пункты, но с группами и без ленты.
    Список отдаёт себе 60 % высоты и прокручивается сам, чтобы не выдавливать работу за экран. */
 .side{width:100%;background:var(--nav-bg);border-bottom:1px solid var(--nav-border)}
 .navsum{display:flex;align-items:center;gap:var(--s3);width:100%;min-height:56px;padding-top:var(--s2);padding-right:max(var(--s4),env(safe-area-inset-right,0px));padding-bottom:var(--s2);padding-left:max(var(--s4),env(safe-area-inset-left,0px));border:0;
  background:none;color:var(--nav-text);font:var(--w-ctl) var(--f3)/var(--lh-tight) var(--ui);text-align:left;cursor:pointer}
 .navsum-label{display:flex;min-width:0;flex-direction:column;gap:2px}
 .navsum-kicker{color:var(--nav-muted);font-size:11px;line-height:1;text-transform:uppercase;letter-spacing:.65px}
 #navSumTxt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
 .navsum-arrow{width:10px;height:10px;flex:none;margin:-5px 2px 0 auto;border-right:2px solid var(--nav-muted);border-bottom:2px solid var(--nav-muted);transform:rotate(45deg);transition:transform .15s ease}
 .side.open .navsum-arrow{margin-top:5px;transform:rotate(225deg)}
 .nav{display:none;flex:none;max-height:60dvh;border-right:0;border-top:1px solid var(--nav-border);padding:var(--s2)}
 .side.open .nav{display:block}
 .page{padding:var(--s4) max(var(--s4),env(safe-area-inset-right,0px)) var(--s4) max(var(--s4),env(safe-area-inset-left,0px))}
 .hide-sm{display:none}
 #roleChip{display:none}
 /* Длинное имя ужимается многоточием, а не переносит шапку на лишний ряд. Вместе с ним уступает
    чип связи: в обрыве он вырастает до «СВЯЗИ НЕТ · в очереди 12», и пока уступить было некому,
    вбок уезжала вся страница — 65px на телефоне 390. «Выйти» и «БЕЗ WB» при этом целы. */
 .top .chip{flex:0 0 auto}
 .top .chip:has(#who),#netChip{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
 .card.rows{display:none}
 /* Карточки маршрута сами себе рамка — контейнеру она не нужна, иначе рамка в рамке. */
 .card.cards{display:block;padding:0;border:0;background:none}
 /* В разметке пара кнопок разделена одним пробелом: в столбик по ним не промахиваются.
    Поле снизу, а не с обеих сторон: у соседних блоков поля схлопываются, и зазор выходил вдвое
    меньше заданного — 4 px между «Взял» и «Товара нет». */
 td .btn{display:block;width:100%;margin:0 0 var(--s2)}
 td .btn+.btn{margin-left:0}
 /* Полоса действий держится над клавиатурой: липкой ей не к чему прилипать (она последняя в
    экране, и запаса хода у неё нет), поэтому на узком экране она закреплена у низа окна, а экран
    получает поле под её высоту. Высоту меряет ui.mjs — кнопка бывает в одну и в две строки. */
 .foot{position:fixed;left:0;right:0;bottom:0;
  padding-left:max(var(--s4),env(safe-area-inset-left,0px));padding-right:max(var(--s4),env(safe-area-inset-right,0px))}
 .screen.on:has(.foot){padding-bottom:calc(var(--foot,0px) + var(--s3))}
 .grid b,.grid button{min-width:calc(33.333% - var(--s2) * 2 / 3)}
}
/* На планшете раскрытый список использует свободную ширину: группы стоят колонками, поэтому
   администратор видит все 20 пунктов без метров пустого места справа и длинной прокрутки. */
@media(min-width:641px) and (max-width:1199px){
 /* grid-auto-rows обязателен: у карточки цикла стоит overflow:hidden, из-за него её наименьшая
    высота для грида равна нулю, и строка сжималась до 356 px при содержимом 534. Группа вылезала
    на 178 px поверх следующей строки, и палец, метивший в «5 · Забрать из ПВЗ», открывал «Журнал».
    max-content запрещает строке быть ниже своего содержимого — список просто прокручивается. */
 /* Колонка 300, а не 240: на планшете подпись набрана 17 пунктами, а счётчик вырастает до 56 —
    «Приёмка возвратов» с числом 338 требовала 175 точек при 148 доступных и резалась многоточием.
    Три колонки вместо четырёх — меню всё равно раскрывается на весь экран. */
 .side.open .nav{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));grid-auto-rows:max-content;align-items:start}
 .nav button{height:52px;min-height:52px;font-size:17px}
 /* Отступ справа держит крупный счётчик: 52 точки под него же на 56 — это наезд числа на текст. */
 .nav button.has-badge{padding-right:68px}
 .nav .nav-deti button{height:48px;min-height:48px;font-size:16px}
 .nav .grp{font-size:13px}
 .nav .badge{width:56px;height:26px;font-size:15px}
 .navgroup+.navgroup{border-left:1px solid var(--nav-border)}
}
@media(max-width:900px){
 /* Две осмысленные строки вместо подрезанных чипов: человек и выход сверху, связь, место и
    адрес телефона снизу. Перенос держит пустой flex-элемент, уже стоящий между этими группами. */
 .top{flex-wrap:wrap}
 .top .sp{display:block;flex:0 0 100%;height:0}
 .top .chip:has(#who),#netChip{flex:none;overflow:visible;text-overflow:clip}
}
@media(max-width:640px){
 /* Прокрутка возвращается всей странице: у .page с overflow:auto липкой панели упаковки не к чему
    прилипать, а шапка на телефоне полезнее уезжающей, чем занимающей высоту постоянно. */
 .win{height:auto;min-height:100dvh}
 .page{overflow:visible;padding:var(--s3) max(var(--s3),env(safe-area-inset-right,0px)) calc(var(--s7) + var(--s3) + env(safe-area-inset-bottom,0px)) max(var(--s3),env(safe-area-inset-left,0px));scroll-padding-bottom:calc(var(--s7) + env(safe-area-inset-bottom,0px))}
 /* Телефон держат дальше от глаз, чем планшет у стола, поэтому кегль здесь не уменьшаем: плотность
    даёт поле ячейки, а не размер цифр — номер задания и штрихкод сверяют глазами. */
 th,td{padding:var(--s2)}
 /* Вертикальное поле шапки общее для всех размеров: при чипе 32 шапка везде 48, а не 52 против 60. */
 .top{padding-right:max(var(--s3),env(safe-area-inset-right,0px));padding-left:max(var(--s3),env(safe-area-inset-left,0px));gap:var(--s2)}
 /* Последним из шапки уходит место: на планшете оно нужно (от него зависит принтер), но на 390
    в ряду остаётся четыре чипа, и место сжимало имя и связь до одной буквы. */
 #placeChip{display:none}
 h1{font-size:var(--f4)}
 .card{padding:var(--s3)}
 .admin-table{display:none}
 .admin-mobile{display:block;max-height:70dvh;margin-top:var(--s2);overflow:auto;overscroll-behavior:contain}
 .steps{gap:var(--s1)}.steps div{padding:var(--s2) var(--s1)}
 /* Две плитки в ряд, не три: подпись плитки набрана 16px, а третья колонка оставляет тексту около
    84px (390 экрана минус поля страницы и плитки), и самая длинная подпись «требуют повторной
    отгрузки» встаёт по слову в строку — так же рвётся значение «нет связи 64 мин». Минимум 150px
    задан базовым правилом выше, здесь ужат только зазор. */
 .kpi{gap:var(--s2)}
 .scan{padding:var(--s3)}
 /* Окно отбито от края экрана так же, как содержимое страницы: 8 против 12 читалось как сбой. */
 .modal{padding:var(--s3)}.modal .box{--pad:var(--s4)}
 /* Порядок в панели: сначала то, чем работают (поле скана), потом где ты в маршруте (шаги).
    На телефоне до правки поле скана лежало последним — до него добирались прокруткой, держа
    сканер в руке. Сводку в панели не ищем: она стоит отдельной строкой над ней, а полосу
    прогресса на узком экране прячет hide-sm в самой разметке. */
 .sticky{display:flex;flex-direction:column}
 .sticky .scan{order:1}.sticky .steps{order:2;margin-bottom:0}
 .grid b,.grid button{min-width:calc(50% - var(--s2) / 2)}
 /* Короткая таблица остаётся естественной высоты, длинная получает собственный скроллпорт —
    журнал и очередь печати больше не растягивают страницу на несколько экранов. */
 .tw.fits{max-height:70dvh;overflow:auto}
 #s-ret .inp{width:100%;max-width:100%;height:var(--h);min-height:var(--h);padding:var(--s3);border:1px solid var(--edge);border-radius:var(--r1);background:var(--card);color:var(--txt);font-size:var(--f3);line-height:var(--lh-tight)}
 /* На телефоне название переносится целиком — колонка узкая, и в одну строку оно не влезает.
    Перенос по словам (break-word), а не по любому месту: anywhere рвал «православная» на
    «правосл / авная», хотя слово помещалось в следующую строку целиком. */
 #s-new.on .nz-product-copy span{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3;white-space:normal;overflow:hidden;text-overflow:clip;overflow-wrap:break-word}
 /* Колонка срока берёт ширину по самой длинной приписке («более 12 ч: 2 из 2»), и названию на
    390 px оставалось 74 px — там рвётся любое слово. Приписке разрешаем две строки, а колонку
    выбора ужимаем до её же чекбокса: название получает 116 px, на которых «православная»
    помещается целиком. */
 #s-new.on .nz-card-head{grid-template-columns:56px minmax(0,1fr) minmax(0,76px)}
 #s-new.on .nz-card-check{min-width:0}
}
/* Короткий экран — телефон в ландшафте: при фиксированной высоте странице осталось бы 250 px
   между шапкой и лентой меню, поэтому прокручивается всё окно целиком. Ширину проверяем тоже:
   у ноутбука при масштабе 125% высота вьюпорта уходит под 600 px, а там фиксированная шапка
   и своя прокрутка страницы полезнее. */
@media(max-width:1023px) and (max-height:600px){
 .win{height:auto;min-height:100dvh}
 .page{overflow:visible;padding-bottom:calc(var(--s7) + var(--s4) + env(safe-area-inset-bottom,0px));scroll-padding-bottom:calc(var(--s7) + env(safe-area-inset-bottom,0px))}
 .tw.fits{max-height:70dvh;overflow:auto}
 #s-ret .inp{width:100%;max-width:100%;height:var(--h);min-height:var(--h);padding:var(--s3);border:1px solid var(--edge);border-radius:var(--r1);background:var(--card);color:var(--txt);font-size:var(--f3);line-height:var(--lh-tight)}
 #s-pick.on .pick-queue-good span{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}
}
@media(min-width:1440px){.win{max-width:1800px}.page{padding:var(--s6)}.kpi{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}}
@media(min-width:2000px){.win{max-width:2160px}}
@media(prefers-reduced-motion:reduce){.nav{scroll-behavior:auto}.prog i{transition:none}}

/* Экран «Сборка из ячеек». Рабочая область намеренно не зависит от общих table/cards:
   ровно на 1024 px прежний JS строил таблицу, а CSS показывал пустые карточки. */
#s-pick.on{display:flex;flex-direction:column;min-height:100%}
#s-pick [hidden]{display:none!important}
#s-pick .pick-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
#s-pick .pick-title{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s3);margin-bottom:var(--s3)}
#s-pick .pick-title h1{margin:0;font-size:24px;font-weight:750}
/* min-width:0 обязателен: переключатель порядка шире узкой шапки, и без него он распирал бы
   страницу вбок вместо того, чтобы прокручиваться внутри себя. */
#s-pick .pick-title-side{display:flex;min-width:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--s3)}
#s-pick .pick-purpose{margin-top:var(--s1);color:var(--dim);font-size:15px;line-height:1.35}
#s-pick .pick-progress{flex:none;color:var(--dim);font-size:15px;white-space:nowrap}
#s-pick .pick-progress b{color:var(--txt);font:750 18px/1 var(--mono)}
#s-pick .pick-progress span{margin-inline:var(--s1)}
#s-pick #pickNet>.note,#s-pick #pickFreshness>:first-child{max-width:none;margin:0 0 var(--s3)}
#s-pick .pick-flash:empty{display:none}
#s-pick .pick-flash{position:sticky;top:0;z-index:8}
#s-pick .pick-flash>div{display:flex;align-items:center;min-height:56px;max-width:none;margin:0 0 var(--s3);font-size:18px;box-shadow:0 8px 18px -16px rgba(16,24,40,.7)}
#s-pick .pick-empty{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--s3);min-height:160px;padding:var(--s5);border-radius:var(--r2);background:var(--row);font-size:18px}
#s-pick .pick-empty-bad{background:var(--badbg);color:var(--bad)}
#s-pick .pick-work{display:grid;grid-template-columns:minmax(300px,390px) minmax(0,1fr);gap:var(--s4);align-items:start;min-height:0}
/* Узкий экран: карточка одна, и обёртка ряда только мешала бы — она отдаёт своё место сетке. */
#s-pick .pick-head{display:contents}
#s-pick .pick-focus,#s-pick .pick-queue{min-width:0;border:1px solid var(--line2);border-radius:var(--r2);background:var(--card)}
#s-pick .pick-focus{position:sticky;top:0;overflow:hidden;box-shadow:0 8px 24px rgba(16,24,40,.08)}
#s-pick .pick-section-title{padding:var(--s2) var(--s4);background:var(--dark);color:var(--card);font-size:13px;font-weight:750;letter-spacing:.08em;text-transform:uppercase}
/* Шапки предпросмотра спокойнее рабочей: порядок карточек читается с одного взгляда, но глаз
   держит тёмную «Сейчас», а не спорит с тремя одинаково громкими заголовками. */
#s-pick .pick-section-title.pick-next{background:var(--row);color:var(--dim)}
#s-pick .pick-card{padding:var(--s4)}
#s-pick .pick-target{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s4);padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
#s-pick .pick-cell,#s-pick .pick-take{display:flex;align-items:baseline;gap:var(--s2);min-width:0}
#s-pick .pick-cell{flex-direction:column;gap:0}
#s-pick .pick-cell>span,#s-pick .pick-take>span:first-child{color:var(--dim);font-size:13px;font-weight:650;text-transform:uppercase;letter-spacing:.04em}
#s-pick .pick-cell strong{font:800 52px/.95 var(--mono);letter-spacing:-.06em;overflow-wrap:anywhere}
#s-pick .pick-cell-missing strong{font:750 24px/1.1 var(--ui);color:var(--bad);letter-spacing:0}
#s-pick .pick-take{flex-wrap:wrap;justify-content:flex-end;color:var(--acc)}
#s-pick .pick-take>span:first-child{width:100%;text-align:right}
#s-pick .pick-take strong{font:800 38px/.9 var(--mono)}
#s-pick .pick-take>span:last-child{font-weight:700}
#s-pick .pick-good{display:grid;grid-template-columns:76px minmax(0,1fr);align-items:center;gap:var(--s3);margin:var(--s4) 0}
#s-pick .pick-good .photo{width:76px;height:76px}
#s-pick .pick-good-copy{min-width:0}
#s-pick .pick-good-copy>b{font:750 20px/1.25 var(--mono)}
#s-pick .pick-art{margin-top:2px;color:var(--dim);font:600 15px/1.3 var(--mono)}
#s-pick .pick-name{display:-webkit-box;margin-top:2px;overflow:hidden;color:var(--dim);font-size:16px;line-height:1.35;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}
#s-pick .pick-due{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s2)}
#s-pick .pick-good-copy .tag-button{margin-top:var(--s2)}
#s-pick .pick-plan{padding:var(--s3);margin-bottom:var(--s3);border-radius:var(--r1);background:var(--row);font-size:16px}
#s-pick .pick-plan>span{display:block;color:var(--dim);font-size:13px;font-weight:650;text-transform:uppercase}
#s-pick .pick-scan-cue{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:82px;padding:var(--s3);border:2px solid var(--acc);border-radius:var(--r2);background:var(--sel);color:var(--acc);text-align:center}
#s-pick .pick-scan-cue b{font-size:18px;line-height:1.25}
#s-pick .pick-scan-cue span{color:var(--txt);font-size:14px}
#s-pick .pick-actions{display:flex;gap:var(--s2);margin-top:var(--s3)}
#s-pick .pick-actions .btn{flex:1;padding-inline:var(--s3);font-size:15px}
#s-pick .pick-queue{overflow:hidden}
#s-pick .pick-queue-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);min-height:44px;padding:var(--s2) var(--s3);background:var(--row)}
#s-pick .pick-queue-head h2{margin:0;font-size:16px}
#s-pick .pick-queue-head span{color:var(--dim);font:650 14px/1 var(--mono)}
#s-pick .pick-list{max-height:calc(100dvh - 310px);overflow:auto;overscroll-behavior:contain}
#s-pick .pick-queue-row{position:relative;display:grid;grid-template-columns:88px 44px minmax(110px,1fr) auto 80px;align-items:center;gap:var(--s2);min-height:68px;padding:var(--s2) var(--s3);border-top:1px solid var(--line);background:var(--card)}
#s-pick .pick-queue-row:first-child{border-top:0}
#s-pick .pick-queue-row.mine{border-left:4px solid var(--ok);background:var(--mine)}
#s-pick .pick-queue-target{display:flex;align-items:baseline;gap:var(--s2);white-space:nowrap}
#s-pick .pick-queue-target b{font:800 24px/1 var(--mono)}
#s-pick .pick-queue-target span{color:var(--acc);font-weight:750}
#s-pick .pick-queue-good{min-width:0}
#s-pick .pick-queue-good b{display:block;font:700 16px/1.25 var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#s-pick .pick-queue-good span{display:block;overflow:hidden;color:var(--dim);font-size:14px;text-overflow:ellipsis;white-space:nowrap}
#s-pick .pick-queue-art{font:600 13px/1.3 var(--mono)}
#s-pick .pick-queue-state{text-align:right;white-space:nowrap}
#s-pick .pick-open{min-width:56px;min-height:48px;padding:0;border:0;background:none;color:var(--acc);font:650 14px/1.2 var(--ui);cursor:pointer}
#s-pick .pick-open::after{content:'›';margin-left:var(--s1);font-size:20px;vertical-align:-1px}
#s-pick .pick-last{padding:var(--s5);color:var(--dim);text-align:center}
#s-pick .pick-help{margin-top:var(--s3);max-width:72ch;color:var(--dim);font-size:14px}
#s-pick .pick-help summary{display:inline-flex;align-items:center;min-height:44px;color:var(--acc);font-weight:650;cursor:pointer}
#s-pick .pick-help>div{padding:0 var(--s3) var(--s3);line-height:1.5}
@media(hover:hover){#s-pick .pick-queue-row:hover{background:var(--row-hi)}#s-pick .pick-open:hover{text-decoration:underline}}
/* Рабочий стол: текущая точка маршрута и две следующие стоят рядом одного размера, список
   начинается с четвёртой. Ровно три колонки, а не auto-fit: на маршруте из двух точек карточки
   обязаны остаться прежнего размера, а не растянуться на всю ширину. Липкость здесь ни к чему —
   ряд и так наверху, а прокручивается длинный список под ним вместе со страницей. */
@media(min-width:1200px){
 #s-pick .pick-work{grid-template-columns:minmax(0,1fr)}
 #s-pick .pick-head{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4)}
 #s-pick .pick-focus{position:static}
 #s-pick .pick-list{max-height:none;overflow:visible}
}
@media(max-width:760px){
 #s-pick .pick-title{align-items:flex-start;flex-direction:column;gap:var(--s2)}
 #s-pick .pick-title-side{align-self:stretch;justify-content:space-between}
 #s-pick .pick-progress{white-space:normal}
 #s-pick .pick-work{grid-template-columns:1fr}
 #s-pick .pick-focus{position:static}
 #s-pick .pick-list{max-height:60dvh;overflow:auto}
 #s-pick .pick-queue-row{grid-template-columns:78px 44px minmax(0,1fr) 56px}
 #s-pick .pick-queue-state{display:none}
}
@media(max-width:420px){
 #s-pick .pick-title h1{font-size:21px}
 #s-pick .pick-purpose{font-size:14px}
 #s-pick .pick-card{padding:var(--s3)}
 #s-pick .pick-cell strong{font-size:44px}
 #s-pick .pick-take strong{font-size:34px}
 #s-pick .pick-good{grid-template-columns:64px minmax(0,1fr);margin:var(--s3) 0}
 #s-pick .pick-good .photo{width:64px;height:64px}
 #s-pick .pick-actions{flex-direction:column}
 #s-pick .pick-queue-row{grid-template-columns:72px minmax(0,1fr) 54px;min-height:64px;padding-inline:var(--s2)}
 #s-pick .pick-queue-row>.photo{display:none}
 #s-pick .pick-queue-target{gap:var(--s1)}
 #s-pick .pick-queue-target b{font-size:21px}
 #s-pick .pick-queue-target span{font-size:14px}
 #s-pick .pick-queue-good span{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}
 #s-pick .pick-open{font-size:0}
 #s-pick .pick-open::after{font-size:24px}
}
@media(forced-colors:active){#s-pick .pick-focus,#s-pick .pick-queue,#s-pick .pick-scan-cue{border:2px solid ButtonBorder}}

/* Экран «Новые заказы». Правила намеренно изолированы #s-new: остальные четырнадцать
   экранов продолжают пользоваться общей таблицей, KPI и липким подвалом без изменений. */
#s-new{
 --nz-control-border:#858d99;
 --nz-list-bg:var(--row);
 container:nz-screen/inline-size;
 min-width:0;
}
#s-new.on{display:block}
#s-new [hidden]{display:none!important}
#s-new .vh,
#s-new .nz-table-view caption{
 position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;
 overflow:hidden!important;clip:rect(0 0 0 0)!important;white-space:nowrap!important;border:0!important
}
#s-new .nz-head{margin-bottom:var(--s2)}
#s-new .nz-title-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:var(--s2)}
#s-new .nz-title-copy{min-width:0}
#s-new h1{font-size:1.375rem;line-height:1.2;font-weight:700;margin:0;text-wrap:balance}
#s-new .nz-purpose{margin:2px 0 0;color:var(--dim);font-size:.875rem;line-height:1.4}
#s-new .nz-total{margin:var(--s1) 0 var(--s2);font-size:1rem;font-weight:600;line-height:1.3}
#s-new .nz-help{position:relative;font-size:.875rem}
#s-new .nz-help summary{display:inline-flex;align-items:center;gap:var(--s1);min-height:44px;padding:0 var(--s2);color:var(--acc);text-decoration:underline;cursor:pointer}
/* Свой значок вместо нативного треугольника: display:inline-flex снимает маркер списка, и
   подсказка выглядела просто ссылкой — не было видно, что она раскрывается прямо здесь. */
#s-new .nz-help summary::after{content:'▾';font-size:.75em;text-decoration:none}
#s-new .nz-help[open] summary::after{content:'▴'}
/* Селектор по обёртке, а не по абзацу: в подсказке теперь несколько абзацев, и всплывашкой
   обязан быть весь блок целиком, иначе абзацы разъезжаются каждый в свой слой. */
#s-new .nz-help>:not(summary){position:absolute;z-index:6;inset-inline-end:0;width:min(320px,calc(100vw - 24px));margin:0;padding:var(--s3);background:var(--card);border:1px solid var(--nz-control-border);border-radius:var(--r1);box-shadow:0 10px 24px rgba(16,24,40,.14);color:var(--txt);line-height:1.5}
#s-new .nz-pane p{margin:0}
#s-new .nz-pane p+p{margin-top:var(--s2)}
#s-new .nz-kpis{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2)}
#s-new .nz-kpis button{position:relative;min-width:0;min-height:56px;padding:var(--s2);border:2px solid transparent;border-radius:var(--r1);background:var(--row);color:var(--txt);text-align:left;font:inherit;cursor:pointer}
#s-new .nz-kpis button.hot{background:var(--badbg)}
#s-new .nz-kpis button.hot .v{color:var(--bad)}
#s-new .nz-kpis button.soft .v{color:var(--warn)}
#s-new .nz-kpis button.on{border-color:var(--acc);box-shadow:inset 0 0 0 1px var(--card)}
#s-new .nz-kpis button.on::after{content:'✓';position:absolute;inset-block-start:5px;inset-inline-end:7px;font-weight:700;color:var(--acc)}
#s-new .nz-kpis button:disabled{cursor:default;opacity:.58}
#s-new .nz-kpis .v{display:block;font:700 1.375rem/1.05 var(--mono)}
#s-new .nz-kpis .l{display:block;margin-top:2px;color:var(--txt);font-size:var(--f1);line-height:1.2}
/* Подпись про нажатие стоит на экране, а не в раскрывашке: без неё и плитки читались как табло,
   и часы под ними — как ещё одни кнопки. */
#s-new .nz-nazhmi{margin:var(--s2) 0 0;color:var(--dim);font-size:var(--f1);line-height:1.35}
/* Часы до отгрузки — не карточка, а подпись к плиткам: строка во всю ширину под ними. Карточка
   справа разводила верх экрана на три разные ширины и оставляла под плитками пустое место.
   Полосы распределения нет вовсе: на живой очереди (249 · 2 · 2) она вырождалась в сплошную
   ленту с двумя огрызками и не добавляла ничего к числам, стоящим тут же. */
#s-new .nz-srok{position:relative;display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s3);margin-top:var(--s2)}
#s-new .nz-srok-tema{margin:0;color:var(--txt);font:var(--w-ctl) var(--f2)/1.3 var(--ui)}
#s-new .nz-srok-zony{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s3);min-width:0}
/* Зона внутри себя не рвётся: число и порог, к которому оно относится, обязаны остаться в одной
   строке — иначе при переносе «2» и «дольше 18 ч» окажутся на разных строках и соврут. */
#s-new .nz-srok .z{display:inline-flex;align-items:baseline;gap:var(--s1);white-space:nowrap;color:var(--txt);font-size:var(--f2);line-height:1.3}
#s-new .nz-srok .z b{font:var(--w-b) var(--f4)/var(--lh-tight) var(--mono)}
#s-new .nz-srok .z small{color:var(--dim);font-size:var(--f1)}
#s-new .nz-srok .z.z-ok b{color:var(--ok)}
#s-new .nz-srok .z.z-warn b{color:var(--warn)}
#s-new .nz-srok .z.z-bad b{color:var(--bad)}
/* Пустая зона гаснет до серого: красный ноль в «дольше 18 ч» тревожит ровно там, где всё сошлось. */
#s-new .nz-srok .z.nol b{color:var(--dim)}
#s-new .nz-srok-hvost{color:var(--dim);font-size:var(--f1);line-height:1.3}
/* Свои имена, а не голые ok/warn/bad: в приложении это классы плашек сообщений с заливкой
   и полями, и вердикт по медиане превращался в жёлтый прямоугольник во всю строку. */
#s-new .nz-srok-hvost.h-ok{color:var(--ok)}
#s-new .nz-srok-hvost.h-warn{color:var(--warn);font-weight:var(--w-ctl)}
#s-new .nz-srok-hvost.h-bad{color:var(--bad);font-weight:var(--w-ctl)}
/* Всплывашка держится за всю строку, а не за свою ссылку: у ссылки правый край гуляет по ширине
   экрана, и панель в 320 px уезжала бы за левый край телефона. */
#s-new .nz-srok .nz-help{position:static;font-size:var(--f1)}
/* Тач-цель 44 px набирается полями наружу: иначе одна ссылка растянула бы строку вдвое. */
#s-new .nz-srok .nz-help summary{min-height:0;padding:var(--s4) var(--s2);margin-block:calc(var(--s4) * -1)}
@media(min-width:641px){
 /* Разделитель — только между зонами. Точка после всей группы висела в конце строки, когда
    хвост с медианой переносился ниже: строка заканчивалась знаком в пустоте. */
 #s-new .nz-srok .z:not(:last-child)::after{content:'·';margin-inline-start:var(--s1);color:var(--line2)}
}
/* На телефоне заголовок и зоны идут столбиком: в строку они не помещаются, а без разделителей
   (их там нет) число следующей зоны примыкало к проценту предыдущей и читалось как одно целое. */
@media(max-width:640px){
 #s-new .nz-srok-tema{flex:1 0 100%}
 #s-new .nz-srok-zony{flex-direction:column;gap:var(--s1)}
}
/* Автоотмена — отдельная строка и только когда есть о чём говорить: заливка ради одной фразы
   вернула бы на экран плашку, от которой мы и уходим. */
#s-new .nz-srok-avto{margin:var(--s1) 0 0;color:var(--bad);font-size:var(--f1);font-weight:var(--w-ctl);line-height:1.3}
#s-new #newUnsure>.warn,#s-new #newUnsure>.note{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin:var(--s2) 0;padding:var(--s2) var(--s3)}
#s-new #newFlash>div{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);margin:var(--s2) 0;padding:var(--s2) var(--s3)}
#s-new .nz-work{display:flex;flex-direction:column;min-width:0;min-height:0;margin-bottom:var(--s2);padding:var(--s3);border-color:var(--line2)}
#s-new .nz-tools{display:grid;gap:var(--s2);margin-bottom:var(--s2)}
#s-new .nz-search-field,#s-new .nz-brand-field{display:grid;grid-template-columns:58px minmax(0,1fr);align-items:center;gap:var(--s2);min-width:0}
#s-new .nz-tools label{margin:0;color:var(--txt);font-size:.875rem;font-weight:600}
#s-new .nz-tools :is(input.txt,select.txt),#s-new input.qty{border-color:var(--nz-control-border)}
#s-new .nz-tools input.txt{min-width:0}
#s-new .nz-bulk{display:flex;align-items:center;gap:var(--s1) var(--s2);flex-wrap:wrap}
#s-new .nz-bulk .btn{flex:1 1 auto}
#s-new .nz-bulk .link-btn{padding-inline:var(--s2);font-size:.875rem}
#s-new .nz-jump{display:inline-flex;align-items:center;min-height:44px;padding-inline:var(--s2);color:var(--acc)}
/* На 390 px два разных сообщения стояли двумя рваными столбиками и читались как одна сломанная
   фраза: на телефоне они идут строками, а в ряд разводятся только на широком экране. */
#s-new .nz-result-line{display:grid;gap:2px;margin-bottom:var(--s2);color:var(--dim);font-size:var(--f1);line-height:1.35}
#s-new .nz-sort{text-align:start}
#s-new .nz-list{flex:1;min-width:0;min-height:0;overflow:hidden;background:var(--nz-list-bg);border-radius:var(--r1)}
#s-new .nz-state{min-height:132px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:var(--s2);padding:var(--s4);background:var(--row);border-radius:var(--r1);font-size:1rem}
#s-new .nz-state.bad{margin:0;color:var(--bad)}
#s-new .nz-table-view{display:none}
#s-new .nz-card-view{max-height:min(52svh,520px);overflow:auto;overscroll-behavior:contain;contain:layout paint;scroll-padding:var(--s2) 0 60px;background:var(--card);border:1px solid var(--line2);border-radius:var(--r1)}
#s-new .nz-mobile-group+.nz-mobile-group{border-top:2px solid var(--line2)}
#s-new .nz-wh{display:grid;gap:var(--s2);padding:var(--s3);background:var(--row)}
#s-new .nz-wh-copy{display:flex;align-items:baseline;gap:var(--s1) var(--s2);flex-wrap:wrap;min-width:0}
#s-new .nz-wh-copy :is(b,h3){margin:0;font-size:.9375rem;line-height:1.3;font-weight:700}
#s-new .nz-wh-copy>span{font-size:.8125rem;color:var(--dim)}
#s-new .nz-wh-copy .nz-picked-wh{font-weight:600;color:var(--acc)}
#s-new .nz-wh-signals{display:inline-flex;gap:var(--s1);flex-wrap:wrap}
#s-new .nz-wh-signals .tag{margin:0;font-size:var(--f1)}
#s-new .nz-wh-actions{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);flex-wrap:wrap}
#s-new .nz-wh-actions label{margin:0;color:var(--txt);font-size:.875rem;font-weight:600}
#s-new .nz-orders{list-style:none;margin:0;padding:0}
#s-new .nz-order-card{padding:var(--s3);background:var(--card);border-top:1px solid var(--line2)}
#s-new .nz-order-card.sel{background:var(--sel)}
#s-new .nz-card-head{display:grid;grid-template-columns:64px minmax(0,1fr) auto;align-items:start;gap:var(--s2)}
#s-new .nz-card-check{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-width:60px;min-height:56px;margin:0;color:var(--txt);font-size:.75rem;font-weight:600}
#s-new .nz-product{display:grid;grid-template-columns:44px minmax(0,1fr);align-items:center;gap:var(--s2);min-width:0}
#s-new .nz-product-copy{min-width:0}
/* Артикул режется многоточием, а не переносится: перенос по любому месту рвал название посреди
   слова («ЛАМПАДА_СЕРЕБРО_П / РАВОСЛАВНАЯ») и качал высоту строк списка. */
#s-new .nz-product-copy b{display:block;font:700 .9375rem/1.25 var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#s-new .nz-product-copy span{display:block;color:var(--txt);font-size:.875rem;line-height:1.35;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#s-new .nz-product-copy small{display:block;color:var(--dim);font-size:.75rem;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#s-new .nz-card-due{min-width:82px;text-align:end}
#s-new .nz-due{display:inline-block;padding:var(--s1) var(--s2);border-radius:var(--r3);background:var(--row);color:var(--txt);font:600 .875rem/1.3 var(--ui);white-space:nowrap}
#s-new .nz-due.late{background:var(--badbg);color:var(--bad)}
#s-new .nz-due.soon{background:var(--warnbg);color:var(--warn)}
#s-new .nz-card-due small,#s-new td.n small{display:block;margin-top:2px;color:var(--dim);font:400 var(--f1)/1.3 var(--ui)}
#s-new .nz-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2);margin:var(--s2) 0}
#s-new .nz-facts div{min-width:0}
#s-new .nz-facts dt{color:var(--dim);font-size:.75rem;font-weight:600}
#s-new .nz-facts dd{margin:2px 0 0;font-size:.875rem;overflow-wrap:anywhere}
/* Ячейки идут столбиком в порядке обхода: три места читаются сверху вниз, а не собираются
   глазами из строки, и трёхзначный номер не тянет колонку вширь. */
#s-new .nz-cells{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0}
#s-new .nz-cell{display:inline-block;max-width:100%;padding:1px var(--s2);border-radius:var(--r3);background:var(--row);color:var(--txt);font-size:.8125rem;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#s-new .nz-cell b{font:700 .8125rem/1.4 var(--mono)}
#s-new .nz-cell.missing{color:var(--dim)}
/* Ниже общих 44 px намеренно: кнопка второстепенная и стоит в плотной строке списка,
   а 44 px раздували бы каждую позицию на треть высоты. */
#s-new .nz-cells-more{min-height:32px;padding:0 var(--s1);font-size:var(--f1);text-align:start}
#s-new .nz-card-qty{display:grid;grid-template-columns:auto 80px auto;align-items:center;justify-content:end;gap:var(--s2);padding-top:var(--s2);border-top:1px solid var(--line)}
#s-new .nz-card-qty label{margin:0;color:var(--txt);font-size:.875rem;font-weight:600}
#s-new input.qty{font-size:1rem}
#s-new input.qty.partial{border-color:var(--warn);background:var(--warnbg)}
#s-new .nz-send{position:static;z-index:4;bottom:0;display:flex;align-items:center;justify-content:space-between;gap:var(--s2);min-height:52px;padding:var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom,0px));background:var(--card);border-top:1px solid var(--line2);box-shadow:0 -8px 14px -14px rgba(16,24,40,.5);scroll-margin-block:var(--s4);font-size:.9375rem}
#s-new .nz-send.ready{position:sticky}
#s-new .nz-send>.note{width:100%;margin:0}
#s-new .nz-send-summary{display:flex;flex-direction:column;min-width:0;line-height:1.3}
#s-new .nz-send-summary span{color:var(--dim);font-size:.8125rem}
#s-new .nz-send-summary progress{width:min(180px,42vw);height:8px;margin-top:var(--s1)}
#s-new .nz-send .btn{flex:0 0 auto;padding-inline:var(--s3);font-size:.9375rem}

/* Блок Ozon в «Новых» держит своё окно с прокруткой, как основной список. Без ограничения он
   растягивал карточку по числу отправлений: список Wildberries при свёрнутых складах занимает
   одну строку, и Ozon занимал собой весь экран. Шапка внутри окна липкая — иначе, прокрутив
   пять строк, перестаёшь понимать, где срок, а где статус. */
#s-new #ozonNew .nz-ozon-okno{max-height:min(26dvh,300px);overflow:auto;overscroll-behavior:contain;border:1px solid var(--line2);border-radius:var(--r1);background:var(--card)}
#s-new #ozonNew .nz-ozon-okno--svodka{max-height:min(18dvh,200px)}
/* Список Wildberries держит своё место всегда. При свёрнутых складах в нём остаётся одна строка
   шапки, высота падала до 40 px — и блок Ozon оказывался сразу под заголовком экрана, как будто
   заказов нет вовсе. Место под список резервируется независимо от того, раскрыты склады или нет. */
#s-new .nz-list{min-height:min(26dvh,280px)}
#s-new #ozonNew .nz-ozon-okno thead th{position:sticky;top:0;z-index:3;background:var(--row)}

/* Таблица включается по фактической ширине экрана, а не viewport. На планшете 1024 px
   после бокового меню контейнер всё равно узкий, поэтому бренд остаётся внутри товара. */
@supports (container-type:inline-size){
 @container nz-screen (min-width:700px){
  #s-new .nz-card-view{display:none}
  #s-new .nz-table-view{display:block;height:100%;max-height:100%;overflow:auto;overscroll-behavior:contain;contain:layout paint;border:1px solid var(--line2);border-radius:var(--r1);background:var(--card);scroll-padding-block:44px}
  #s-new #tNew{table-layout:fixed;font-size:.9375rem}
  #s-new #tNew th,#s-new #tNew td{padding:var(--s2);border-bottom-color:var(--line2)}
  #s-new #tNew thead th{top:0;height:42px;z-index:4;background:var(--row);color:var(--txt);font-size:.8125rem}
  #s-new #tNew .nz-group-row th{position:static;padding:0;background:var(--row);text-transform:none;letter-spacing:0;white-space:normal}
  #s-new #tNew .nz-group-open .nz-group-row th{position:sticky;top:42px;z-index:3}
  #s-new #tNew .nz-group-head:not(:first-of-type) .nz-group-row th{border-top:2px solid var(--line2)}
  #s-new #tNew .nz-wh{grid-template-columns:minmax(0,1fr) auto;align-items:center;padding:var(--s2) var(--s3)}
  #s-new #tNew .nz-wh-actions{justify-content:end}
  #s-new #tNew .nz-order-row{height:60px}
  #s-new #tNew .nz-order-row.sel{background:var(--sel)}
  #s-new #tNew .nz-order-row>td:first-child{width:52px;text-align:center}
  #s-new #tNew .nz-product-copy span{font-size:.8125rem}
  #s-new #tNew .photo.sm{width:44px;height:44px}
  #s-new #tNew .nz-qty-cell{white-space:nowrap}
  #s-new #tNew .nz-qty-cell input{width:64px;min-height:44px;padding:var(--s2)}
  #s-new #tNew th:nth-child(1){width:52px}
  /* 140 px — под самый длинный вид «№245 · 120 шт»: на 116 px трёхзначный номер вместе
     с трёхзначным остатком обрезался многоточием. */
  #s-new #tNew th:nth-child(4){width:140px}
  #s-new #tNew th:nth-child(5){width:148px}
  #s-new #tNew th:nth-child(6){width:154px}
 }
 @container nz-screen (min-width:1000px){
  #s-new #tNew .nz-brand-col{display:table-cell;width:120px}
 }
}

@media(min-width:641px){
 #s-new.on{display:grid;grid-template-rows:auto auto auto minmax(0,1fr) auto;height:100%;min-height:0}
 #s-new .nz-head{margin-bottom:var(--s2)}
 #s-new .nz-purpose{font-size:1rem}
 #s-new .nz-total{margin-top:0}
 /* Ряд плиток идёт до того же края, что таблица под ним: прежние 680 px оставляли справа
    пустое поле, и верх экрана распадался на разные ширины. */
 #s-new .nz-kpis button{min-height:58px;padding:var(--s2) var(--s3)}
 #s-new .nz-result-line{display:flex;justify-content:space-between;gap:var(--s2)}
 #s-new .nz-sort{text-align:end}
 #s-new .nz-work{height:100%;overflow:hidden}
 #s-new .nz-tools{grid-template-columns:minmax(260px,1fr) minmax(180px,240px) auto;align-items:center}
 #s-new .nz-bulk{justify-content:end;flex-wrap:nowrap}
 #s-new .nz-bulk .btn{flex:0 0 auto}
 #s-new .nz-jump{white-space:nowrap}
 #s-new .nz-send,#s-new .nz-send.ready{position:static;min-height:60px;padding:var(--s2) var(--s3);box-shadow:none;border:1px solid var(--line2);border-radius:var(--r1)}
 #s-new .nz-send-summary{flex-direction:row;align-items:baseline;gap:var(--s2)}
}

@media(hover:hover){
 #s-new .nz-kpis button:not(:disabled):hover,#s-new .nz-wh-actions .btn:hover{filter:none;box-shadow:inset 0 0 0 2px var(--acc)}
 #s-new .nz-order-row:not(.sel):hover,#s-new .nz-order-card:not(.sel):hover{background:var(--row-hi)}
}

@media(forced-colors:active){
 #s-new .nz-kpis button,#s-new .nz-card-view,#s-new .nz-table-view,#s-new .nz-order-card,#s-new :is(input.txt,select.txt,input.qty){border:1px solid ButtonBorder}
 #s-new .nz-kpis button.on{outline:3px solid Highlight;outline-offset:-3px}
 #s-new .nz-order-row,#s-new .nz-order-card{border-block-end:1px solid CanvasText}
 #s-new .nz-order-row.sel,#s-new .nz-order-card.sel{outline:2px solid Highlight;outline-offset:-2px}
 /* При системной палитре цвет числа пропадает — просроченную зону метим подчёркиванием, иначе
    три зоны становятся неотличимы друг от друга. */
 #s-new .nz-srok .z.z-bad:not(.nol) b{text-decoration:underline}
}

/* Прототип «Единый контур» (экраны s-pr-*). Подписи таблиц набраны для диктора и не должны
   показываться глазами — в приложении общего класса для этого нет, только свои у s-new и s-pick. */
.screen[id^="s-pr-"] .sr{
 position:absolute;width:1px;height:1px;padding:0;margin:-1px;
 overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0
}
/* Поля ввода в макетах помечены .inp: в боевых экранах этот класс живёт только внутри #s-ret,
   поэтому здесь он приводится к виду обычного текстового поля приложения (input.txt). */
.screen[id^="s-pr-"] .inp{
 min-height:var(--h);padding:var(--s2) var(--s3);border:1px solid var(--line);border-radius:var(--r2);
 background:var(--card);color:inherit;font:var(--f3)/var(--lh) var(--ui);box-sizing:border-box;max-width:100%
}
/* Свод остатков: таблица шире экрана и листается вправо. width:100% из общего правила заставлял
   её ужиматься в контейнер, из-за чего артикулы переносились по слогам. */
.screen[id^="s-pr-"] .tw-scroll{overflow-x:auto;overflow-y:auto}
.screen[id^="s-pr-"] .tw-scroll table{width:auto;min-width:100%}
.screen[id^="s-pr-"] .tw-scroll th,.screen[id^="s-pr-"] .tw-scroll td{white-space:nowrap;vertical-align:top}
.screen[id^="s-pr-"] .tw-scroll td.wrap{white-space:normal;min-width:210px;max-width:320px}
.screen[id^="s-pr-"] .tw-scroll .col-foto{width:56px}
.screen[id^="s-pr-"] .tw-scroll .col-list{min-width:140px}
.screen[id^="s-pr-"] .tw-scroll .col-mesta{min-width:150px}
.screen[id^="s-pr-"] .tw-scroll .link-btn{margin-top:2px;font-size:12px}
/* ── Приход от поставщика ──────────────────────────────────────────────────
   Экран рабочий и телефонный: приёмщик стоит у стола со сканером в одной руке. Поэтому крупные
   цифры, кнопки в палец и один шаг на виду — тот же приём, что на сборке, где это уже прижилось. */
#s-prihod .pr-title{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
#s-prihod .pr-title h1{margin:0}
#s-prihod .pr-sub{margin-top:var(--s1);color:var(--dim);font-size:15px}
#s-prihod .pr-prog{color:var(--dim);font-size:15px;white-space:nowrap}
#s-prihod .pr-prog b{color:var(--txt);font:750 18px/1 var(--mono)}
/* Шаги: пройденное гаснет, текущее держит взгляд. Ряд прокручивается вбок, а не ломает страницу. */
#s-prihod .pr-steps{display:flex;gap:var(--s2);margin:var(--s3) 0;overflow-x:auto;padding-bottom:2px}
#s-prihod .pr-step{display:flex;align-items:center;gap:var(--s2);min-height:40px;padding:0 var(--s3);
  border:1px solid var(--line2);border-radius:999px;background:var(--card);color:var(--dim);
  font:650 14px/1 var(--ui);white-space:nowrap}
#s-prihod .pr-step i{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;
  background:var(--row);color:var(--dim);font:700 12px/1 var(--mono);font-style:normal}
#s-prihod .pr-step.done{border-color:var(--ok);color:var(--ok-ink)}
#s-prihod .pr-step.done i{background:var(--okbg);color:var(--ok)}
#s-prihod .pr-step.now{border-color:var(--acc);background:var(--sel);color:var(--acc)}
#s-prihod .pr-step.now i{background:var(--acc);color:var(--card)}
/* Карточка шага: тёмная шапка, как «Сейчас» на сборке — глаз сразу находит рабочее место экрана. */
#s-prihod .pr-card{border:1px solid var(--line2);border-radius:var(--r2);background:var(--card);
  overflow:hidden;box-shadow:0 8px 24px rgba(16,24,40,.08);margin-bottom:var(--s3)}
#s-prihod .pr-card>h2{margin:0;padding:var(--s2) var(--s4);background:var(--dark);color:var(--card);
  font-size:13px;font-weight:750;letter-spacing:.08em;text-transform:uppercase}
#s-prihod .pr-card.calm>h2{background:var(--row);color:var(--dim)}
/* Колонка сетки по умолчанию не уже своего содержимого, поэтому поле ввода вместе со списком
   привозов (150-210 px) распирало карточку до 476 px при экране 390: правый край поля и кнопка
   «Начать приёмку» уходили за экран без всякой прокрутки, то есть были недоступны. */
#s-prihod .pr-body{padding:var(--s4);display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s3)}
#s-prihod .pr-box{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s3);
  padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
#s-prihod .pr-box b{font:700 18px/1.2 var(--ui)}
#s-prihod .pr-box .mono{font:650 14px/1.3 var(--mono);color:var(--dim)}
#s-prihod .pr-count{text-align:right;white-space:nowrap}
#s-prihod .pr-count strong{display:block;font:800 40px/.95 var(--mono);letter-spacing:-.04em}
#s-prihod .pr-count span{color:var(--dim);font-size:13px;font-weight:650;text-transform:uppercase}
/* Плашка «сканируйте»: то же обещание, что на сборке, — сюда смотрит человек с пистолетом. */
#s-prihod .pr-cue{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  min-height:88px;padding:var(--s3);border:2px solid var(--acc);border-radius:var(--r2);
  background:var(--sel);color:var(--acc);text-align:center}
#s-prihod .pr-cue b{font-size:19px;line-height:1.25}
#s-prihod .pr-cue span{color:var(--txt);font-size:14px}
#s-prihod .pr-cue.ready{border-color:var(--ok);background:var(--okbg);color:var(--ok-ink)}
#s-prihod .pr-cue .mono{font:800 22px/1.2 var(--mono)}
/* Поля тянутся на всю карточку: общий стиль ограничивает их шириной строки текста, а здесь
   в них целятся пальцем, а не читают. */
#s-prihod .pr-field input,#s-prihod input#prBar{width:100%;max-width:none;min-height:52px;font-size:18px}
#s-prihod input#prQty{min-height:64px;font:800 30px/1 var(--mono);text-align:center;letter-spacing:.04em}
#s-prihod .pr-row{display:flex;gap:var(--s2);flex-wrap:wrap}
#s-prihod .pr-row>.pr-field{flex:1 1 130px;min-width:0}
#s-prihod .pr-field label{display:block;margin-bottom:4px;color:var(--dim);font-size:13px;font-weight:650;
  text-transform:uppercase;letter-spacing:.04em}
/* Строка штрихкода: поле и кнопка камеры на одной линии. Пистолет и камера делают одно и то же,
   поэтому и стоять должны рядом — отдельная полоса под полем читалась как другое действие. */
#s-prihod .pr-vvod{display:flex;gap:var(--s2);align-items:stretch;flex-wrap:wrap}
/* width:100% из общего правила полей распирал ввод на всю строку, и кнопка отодвигалась пустотой.
   В строке поле тянется флексом, а не своей шириной. */
#s-prihod .pr-vvod>input#prBar,#s-prihod .pr-vvod>input#prNaval{flex:1 1 auto;width:auto;min-width:0}
/* Выбор привоза рядом с полем: список того, что в работе, не отнимая места у ручного ввода. */
#s-prihod .pr-vybor{flex:0 0 auto;width:auto;min-width:150px;max-width:210px;min-height:52px}
#s-prihod .pr-kam{flex:none;width:64px;min-height:64px;display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--acc);border-radius:var(--r1);background:var(--sel);color:var(--acc);
  transition:background .15s,color .15s,transform .1s}
#s-prihod .pr-kam svg{width:30px;height:30px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linejoin:round;stroke-linecap:round}
#s-prihod .pr-kam:hover{background:var(--acc);color:#fff}
#s-prihod .pr-kam:active{transform:scale(.94)}
#s-prihod .pr-kam:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
/* Камера работает — кнопка залита цветом: видно, что объектив включён, и вторым нажатием он гасится. */
#s-prihod .pr-kam.idet{background:var(--acc);color:#fff;border-color:var(--acc)}
/* Низ экрана: главное действие всегда на одном месте и во всю ширину, второстепенные — рядом
   под ним, одинаковой ширины. Так палец находит нужную кнопку не глядя. */
/* Ячейка действий в таблице поставок: кнопки одной ширины в ряд, перенос по месту.
   Печать свёрнута — её жмут раз в жизнь поставки, а место занимала как рабочие кнопки. */
/* Кнопки одной ширины и одной высоты: при переносе по одной они вставали лесенкой разной длины,
   и глазу приходилось каждый раз искать нужную. Сетка держит их ровным столбцом. */
/* Ровно две колонки одинаковой ширины: auto-fit в узкой ячейке давал то один столбец, то два,
   и кнопки выходили разного размера. Главное действие занимает оба столбца и не переезжает. */
/* Три вспомогательных действия в один ряд, главное — во всю ширину под ними. Прежняя сетка два
   на два растила строку на три ряда кнопок: при пяти поставках таблица не помещалась на экран,
   хотя данных в строке на две строчки. */
#s-postavki .pr-tbl-act{display:grid;grid-template-columns:1fr 1fr;gap:6px;align-items:stretch}
#s-postavki .pr-tbl-act>.wide{grid-column:1/-1}
/* margin:0 обязателен: общее правило таблиц даёт каждой следующей кнопке в ячейке левый отступ
   (td .btn+.btn) и вертикальные поля (td .btn). В столбце это складывалось в лесенку — три кнопки
   печати уезжали вправо ступеньками и казались разной ширины. */
#s-postavki .pr-tbl-act .btn,#s-postavki .pr-pech>summary{
  width:100%;min-width:0;margin:0;padding:0 var(--s2);min-height:36px;white-space:nowrap;
  display:inline-flex;align-items:center;justify-content:center}
#s-postavki .pr-tbl-act>.tag{display:inline-flex;align-items:center;justify-content:center;min-height:36px}
#s-postavki .pr-pech{grid-column:1/-1}
/* Внутри «Этикеток» те же правила: одна ширина, одна высота, ровный ряд. */
#s-postavki .pr-pech>summary{min-height:40px;font-size:14px;border:1px solid var(--line2);border-radius:var(--r1);
  background:var(--card);color:var(--dim);font-size:14px;font-weight:650;cursor:pointer;list-style:none}
/* Внутри «Этикеток» — тот же столбец той же ширины: иначе три кнопки печати вставали лесенкой
   рядом с ровными рабочими. */
#s-postavki .pr-pech>div{display:grid;grid-template-columns:1fr;gap:6px;margin-top:6px;
  position:absolute;z-index:3;min-width:200px;padding:var(--s2);background:var(--card);
  border:1px solid var(--line);border-radius:var(--r1);box-shadow:0 10px 24px rgba(16,24,40,.14)}
#s-postavki .pr-pech{position:relative}
/* Ширины колонок заданы прямо, иначе их назначало содержимое: длинный артикул отбирал место
   у действий, а числа расползались по половине таблицы. Резиновая колонка ровно одна —
   комментарий: свободное место уходит туда, где текст, а не в код поставки и не в кнопки. */
#s-postavki table th.col-post{width:1%;min-width:150px}
#s-postavki .pr-kod{display:flex;align-items:center;gap:var(--s2);cursor:pointer}
/* Площадь нажатия галочки — только вокруг неё: номер поставки рядом открывает ход приёмки. */
#s-postavki .pr-vyb-box{display:flex;align-items:center;justify-content:center;
  min-width:var(--h);min-height:var(--h);margin:calc(var(--s2) * -1) 0;cursor:pointer}
#s-postavki .pr-tovar{display:flex;align-items:center;gap:var(--s3)}
#s-postavki .pr-str-act{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s2)}

/* Миниатюра карточки WB: мелкая в строке, по нажатию открывается крупно. */
#s-postavki .pr-foto{width:44px;height:44px;flex:0 0 44px;object-fit:cover;border-radius:var(--r1);border:1px solid var(--line);background:var(--card);cursor:zoom-in}

/* У строк, которые массово не выбрать, вместо дырки — тот же квадрат, только бледный
   и неактивный: колонка держит одну вертикаль. Курсор обычный, а не «запрещено», —
   это не отказ в действии, а просто нечего нажимать. */
#s-postavki .pr-vyb-box input:disabled{cursor:default}
#s-postavki .pr-vyb-panel{flex-wrap:wrap}

#s-postavki table th.col-num{width:96px}
/* Разбор и приёмка — колонки для монитора: там пустовала половина ширины. На планшете и
   телефоне их прячем, те же сведения идут строкой в карточке поставки. */
#s-postavki table .col-hod{width:190px;font-size:var(--f2);vertical-align:top;white-space:normal;line-height:1.35}
#s-postavki table .col-hod .tag{margin-bottom:2px}
/* Код и метка приёмки — один столбик рядом с галочкой, чтобы левый край был общий. */
#s-postavki .pr-kod{align-items:flex-start}
#s-postavki .pr-kod>div{min-width:0}
/* Кто завёл и когда — две узкие колонки подряд: имя в одну строку, дата коротким «25.08 10:30».
   Врозь по разным краям таблицы их читали бы как несвязанные. */
#s-postavki table .col-kto{width:1%;min-width:96px}
#s-postavki table .col-kogda{width:1%;min-width:88px;font-size:var(--f2)}
/* Комментарий — единственная колонка, которой отдана свободная ширина: остальные встают по своему
   содержимому. Текст переносится, кегль мельче строки — это приписка, а не данные приёмки. */
#s-postavki table .col-note{width:auto;min-width:150px;white-space:normal}
/* Пустая ячейка тоже нажимается: пунктирная рамка обещает поле для записи, а не просто прочерк. */
#s-postavki .pr-note{display:block;width:100%;margin:0;padding:var(--s2);border:1px dashed var(--line2);
  border-radius:var(--r1);background:none;color:var(--txt);font:inherit;font-size:var(--f2);
  line-height:1.35;text-align:left;white-space:pre-wrap;overflow-wrap:anywhere;cursor:text}
#s-postavki .pr-note:hover{border-style:solid;border-color:var(--acc)}
#s-postavki .pr-note-vvod{width:100%;padding:var(--s3);border:1px solid var(--edge);border-radius:var(--r1);
  background:var(--card);color:var(--txt);font:inherit;font-size:var(--f3);resize:vertical}
/* Порог поднят с 1399 до 1599: колонок стало девять, и на ноутбуке 1440 таблица уезжала за край.
   Первыми уступают «Разбор» и «Приёмка» — на телефоне их и так нет, а те же сведения идут
   строкой в карточке поставки. Комментарий остаётся: его сюда и просили. */
@media(max-width:1599px){#s-postavki table .col-hod{display:none}}

#s-postavki table td.n .dim{white-space:nowrap}
#s-postavki table th.col-act{width:288px}   /* 260 не хватало: «Ход приёмки» и «Скачать» в ряд касались рамки */
#s-postavki table td{padding-top:var(--s2);padding-bottom:var(--s2);vertical-align:top}
#s-postavki table td.n>b{font-size:var(--f4)}
#s-postavki .pr-pech[open]>summary{border-color:var(--acc);color:var(--acc)}
/* Итог хода приёмки: числа и действия одной строкой, не вперемешку с метками. */
#s-postavki .pr-hod-itog{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s3)}
#s-postavki .pr-hod-itog .btn{min-height:40px}
#s-prihod .pr-nizh{display:grid;gap:var(--s2);margin-top:var(--s3)}
#s-prihod .pr-nizh>.pr-go{min-height:60px;font-size:18px;font-weight:750}
#s-prihod .pr-nizh-ryad{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
#s-prihod .pr-nizh-ryad>.btn{min-height:48px;white-space:normal}
#s-prihod .pr-fast{display:flex;gap:var(--s2);flex-wrap:wrap}
#s-prihod .pr-fast .btn{flex:1 1 84px;min-height:48px;font-size:16px}
/* Кнопка обновления в шапке. Обычно спокойная, а когда сервер сообщил о новой версии — заметная:
   иначе смена неделями работает по коду из кэша и ловит уже починенные ошибки. */
.chip#updChip.act{background:var(--acc);border-color:var(--acc);color:#fff;font-weight:700}

#s-prihod .pr-go{min-height:56px;font-size:18px;font-weight:750}
/* Кнопка, сменившая роль: тот же палец, другое действие — цвет обязан это показать, иначе
   человек жмёт по привычке и уходит с шага, не сделав того, что держит в руках. */
#s-prihod .btn.pr-go.ok{background:var(--ok);border-color:var(--ok);color:#fff}
#s-prihod .btn.pr-go.ok:hover{filter:brightness(1.05)}
#s-prihod .pr-go.wide{width:100%}
/* Список позиций: строка читается за один взгляд — товар слева, числа справа. */
#s-prihod .pr-list{border:1px solid var(--line2);border-radius:var(--r2);background:var(--card);overflow:hidden}
#s-prihod .pr-list-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);
  min-height:44px;padding:var(--s2) var(--s3);background:var(--row)}
#s-prihod .pr-list-head h2{margin:0;font-size:16px}
#s-prihod .pr-list-head span{color:var(--dim);font:650 14px/1 var(--mono)}
#s-prihod .pr-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--s2);align-items:center;
  padding:var(--s3);border-top:1px solid var(--line)}
#s-prihod .pr-item:first-of-type{border-top:0}
#s-prihod .pr-item b{display:block;font:700 16px/1.25 var(--ui);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#s-prihod .pr-item .mono{color:var(--dim);font:600 13px/1.35 var(--mono)}
#s-prihod .pr-item-num{text-align:right;white-space:nowrap}
#s-prihod .pr-item-num strong{font:800 26px/1 var(--mono)}
#s-prihod .pr-item-num span{display:block;color:var(--dim);font-size:12px}
#s-prihod .pr-item-wide{grid-column:1/-1}
#s-prihod .pr-places{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s2)}
#s-prihod .pr-places .btn{flex:1 1 150px;min-height:52px;justify-content:flex-start;text-align:left;font-size:15px}
#s-prihod .pr-done{display:grid;gap:var(--s2);padding:var(--s5);text-align:center}
#s-prihod .pr-done strong{font:800 44px/1 var(--mono)}
#s-prihod .pr-hint{color:var(--dim);font-size:14px;line-height:1.45}
@media(min-width:900px){
 #s-prihod .pr-work{display:grid;grid-template-columns:minmax(320px,420px) minmax(0,1fr);gap:var(--s4);align-items:start}
 #s-prihod .pr-card{margin-bottom:0}
}

.camera-capture{display:none;margin-top:var(--s3)}
.camera-capture[hidden],.camera-view[hidden],.camera-capture [hidden]{display:none}
.camera-kadr{position:relative;margin-bottom:var(--s2)}
.camera-view video{display:block;width:100%;max-height:50dvh;border-radius:var(--r1);background:var(--txt);object-fit:cover}
/* Прицел: затемняем всё, кроме окна под код, — глазу сразу видно, куда наводить. Тень наружу
   рисуется одним box-shadow, поэтому лишних слоёв над видео нет. */
.camera-pricel{position:absolute;left:12%;right:12%;top:28%;bottom:28%;border-radius:var(--r1);
  box-shadow:0 0 0 100vmax rgba(0,0,0,.45);outline:2px solid rgba(255,255,255,.9);pointer-events:none}
.camera-pricel::before,.camera-pricel::after{content:"";position:absolute;width:22px;height:22px;
  border:3px solid var(--acc)}
.camera-pricel::before{left:-3px;top:-3px;border-right:0;border-bottom:0;border-radius:var(--r1) 0 0 0}
.camera-pricel::after{right:-3px;bottom:-3px;border-left:0;border-top:0;border-radius:0 0 var(--r1) 0}
/* Линия ходит по окну прицела: это единственный признак, что камера не замерла. */
.camera-luch{position:absolute;left:6px;right:6px;height:2px;border-radius:2px;background:var(--acc);
  box-shadow:0 0 8px var(--acc);animation:camera-luch 1.8s ease-in-out infinite}
@keyframes camera-luch{0%,100%{top:8%}50%{top:92%}}
.camera-podskazka{position:absolute;left:0;right:0;bottom:8px;text-align:center;color:#fff;
  font-size:13px;text-shadow:0 1px 3px rgba(0,0,0,.8);pointer-events:none}
/* Код взят: рамка зеленеет на полсекунды — вместе с вибрацией это и есть ответ «сработало». */
.camera-kadr.vzyat .camera-pricel{outline-color:var(--ok);box-shadow:0 0 0 100vmax rgba(15,120,63,.35)}
.camera-kadr.vzyat .camera-luch{display:none}
@media(prefers-reduced-motion:reduce){.camera-luch{animation:none;top:50%}}
.camera-status:empty{display:none}
.camera-status{max-width:none;margin-bottom:0}
@media(max-width:640px){.camera-capture{display:block}}
/* «Разложено» — история приёмки, «сейчас» — остаток после правок. Второе набрано мельче и цветом
   акцента: это не то же число, и путать их нельзя. */
#s-postavki .pr-seychas{margin-top:var(--s1);color:var(--acc);font-size:var(--f2)}

/* ── Левое меню: ежедневный цикл отдельным блоком ──────────────────────────
   Смена девяносто процентов дня работает в четырёх шагах, а искала их в общем списке наравне
   со справочниками. Цикл выделен своей карточкой и цветной полосой слева: взгляд находит его
   первым, а всё остальное читается как «по делу, но не сейчас». */
.nav .navgroup{padding-bottom:var(--s2)}
.nav .navgroup+.navgroup{padding-top:var(--s1);border-top:1px solid var(--nav-border)}
.nav .navgroup--cikl{margin:0 0 var(--s3);padding:var(--s1) var(--s2) var(--s2) var(--s2);overflow:hidden;
  border:1px solid var(--nav-border);border-radius:var(--r2);background:var(--nav-surface);
  box-shadow:none}
.nav .navgroup--cikl .grp{color:var(--nav-accent)}
.nav .navgroup--cikl .nav-punkt{padding-left:calc(var(--s3) + 28px);font-size:var(--f3);font-weight:var(--w-ctl)}
.nav .navgroup--cikl .nav-punkt.has-icon{padding-left:calc(var(--s3) + 28px)}
.nav .navgroup--cikl .navicon{left:var(--s2)}
.nav .navgroup--cikl .nav-punkt.on{background:var(--nav-active)}

/* Шаг и его подразделы — одна ячейка: стрелка не должна разъезжаться с названием. */
.nav .nav-shag{position:relative}
/* Собственный счётчик шага стоит в общей правой колонке. Свод хвостов и раскрытие получают
   отдельные места левее — три элемента не перекрывают друг друга даже на трёхзначных числах.
   С иконкой слева отступ увеличен: 12 (padding) + 16 (иконка) + 8 (gap) = 36px. */

/* Подразделы уступают шагу: с отступом и своей линией — видно, что это его хвосты.
   Высота тач-цели та же 44px, что и у родителя: подпункты тоже пункты. */
.nav .nav-deti{margin:0 0 var(--s1) var(--s3);padding-left:var(--s2);border-left:2px solid var(--nav-border)}
.nav .nav-deti button{height:var(--nav-h);min-height:var(--nav-h);padding-left:var(--s3);padding-right:52px;
 margin-left:var(--s1);color:var(--nav-muted);font-size:var(--f3)}
.nav .nav-deti button.on{color:var(--nav-accent);background:var(--nav-active)}
/* Сводное число хвостов стоит там же, где обычный счётчик, но левее стрелки. */
.nav .badge.svod{right:38px;min-width:26px;padding:2px var(--s1)}
/* Готовящиеся разделы: серым и с меткой, чтобы никто не принял их за рабочие. */
.nav .navgroup--soon .grp{color:var(--dim)}
.nav .navgroup--soon button{color:var(--dim)}
@media(min-width:641px) and (max-width:1199px){
 .nav .navgroup+.navgroup{border-top:0}
}

/* ── Приёмка на телефоне (правка 22.08) ────────────────────────────────────
   Таблицы хода приёмки в 340 px экрана разворачивались на 700 и листались вбок одной рукой,
   пока во второй товар. На узком экране те же данные идут карточками, на мониторе остаётся
   таблица — переключение уже описано классами admin-table / admin-mobile. */
/* Общее правило прячет мобильный список в окно 70dvh с собственной прокруткой — своду это
   подходит, а здесь два скролла в одном экране: список поставок короткий, пусть едет страницей. */
#s-postavki .admin-mobile{max-height:none;overflow:visible}
/* Колонок в списке стало девять, и на планшете таблица перестала помещаться: кнопки «Ход приёмки»
   и «Привоз принят» уезжали за край, а приёмщик листал их вбок, держа короб. Карточки здесь
   включаются с планшета, а не только с телефона, — тот же приём, что в истории отгрузок. */
@media(max-width:1199px){
  #s-postavki .admin-table{display:none}
  #s-postavki .admin-mobile{display:block}
}
#s-postavki .pr-mob{margin-bottom:var(--s3)}
#s-postavki .pr-mob:last-child{margin-bottom:0}
#s-postavki .pr-mob-ryad{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;
  margin-top:var(--s2);color:var(--dim);font-size:var(--f3)}
#s-postavki .pr-mob-ryad b{color:var(--txt)}
#s-postavki .pr-mob-mesta{margin-top:var(--s2);font-size:var(--f2)}
/* Комментарий в карточке стоит над кнопками: его читают вместе с данными привоза, а не жмут
   как действие. Поле отбито от ряда «завёл · разбор», иначе слипается с ним в одну строку. */
#s-postavki .pr-mob>.pr-note{margin-top:var(--s3)}
/* Действия в карточке: два в ряд, главное во всю ширину — тем же приёмом, что в строке таблицы. */
#s-postavki .pr-mob-knopki{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:var(--s3)}
#s-postavki .pr-mob-knopki>.btn,#s-postavki .pr-mob-knopki .pr-pech>summary{
  width:100%;margin:0;min-height:44px;display:inline-flex;align-items:center;justify-content:center;
  /* «Ход приёмки» вставало в две строки и растило кнопку вдвое против соседней — подпись держим
     в одну строку, кегль на шаг мельче. */
  white-space:nowrap;font-size:var(--f2)}
/* Заголовок раскрывающихся коробов был высотой 25 px — пальцем в него попадают не с первого раза. */
#s-postavki details.card>summary{display:flex;align-items:center;min-height:44px;cursor:pointer}
#s-postavki .pr-mob-knopki>.wide,#s-postavki .pr-mob-knopki>.pr-pech{grid-column:1/-1}
/* Кнопка приёмки отдаёт и метки «принял …», «ждём приёмку» — они стоят на месте кнопки и
   выравниваются так же, иначе ряд под ними едет. */
#s-postavki .pr-mob-knopki>.tag{display:flex;align-items:center;justify-content:center;
  min-height:44px;margin:0;text-align:center}
#s-postavki .pr-mob-knopki .pr-pech>div{display:grid;gap:6px;margin-top:6px}
#s-postavki .pr-mob-knopki .pr-pech .btn{width:100%;margin:0;min-height:40px}
/* Вводный текст занимал полэкрана телефона при каждом входе — теперь он свёрнут. */
#s-postavki .pr-spravka>summary{cursor:pointer;color:var(--acc);font-weight:var(--w-ctl);
  padding:var(--s2) 0;list-style:none}
#s-postavki .pr-spravka[open]>summary{color:var(--dim)}
@media(min-width:641px){
  /* На мониторе места хватает: справка раскрыта, прятать её незачем. */
  #s-postavki .pr-spravka>summary{display:none}
  #s-postavki .pr-spravka>.sub{display:block}
}

/* Разбор незнакомых кодов. На мониторе три поля стоят в ряд, как стояли; на телефоне ряд из трёх
   оставлял каждому по 90 px — подсказки обрезались на середине слова, а количество съезжало
   к центру, потому что правый столбец сжимался вместе с ними. */
#s-postavki .rz-pole{flex:1;min-width:90px}
#s-postavki .rz-shire{flex:2;min-width:140px}
#s-postavki .rz-kolvo{text-align:right;flex:0 0 auto}
#s-postavki .rz-kolvo>b{font-size:var(--f3)}
@media(max-width:640px){
  #s-postavki .rz-ryad{display:grid;grid-template-columns:1fr 1fr;align-items:end}
  #s-postavki .rz-shire,#s-postavki .rz-ryad>.btn{grid-column:1/-1}
  #s-postavki .rz-ryad>.btn{min-height:44px}
  #s-postavki .rz-pole .txt{width:100%}
  /* Количество не помещается в строку с кодом и переносится вниз. Столбиком оно вставало числом
     посередине экрана и подписью слева — на узком экране кладём их в одну строку. */
  #s-postavki .rz-kolvo{display:flex;gap:6px;align-items:baseline;width:100%;text-align:left}
}

/* На телефоне поле и список встают друг под другом во всю ширину: рядом им нужно 360 px, а на
   узком экране остаётся около 300. */
@media(max-width:520px){
  #s-prihod .pr-vvod>input,#s-prihod .pr-vybor{flex:1 1 100%;max-width:none}
}

/* Строка поставки и её карточка на телефоне открывают ход приёмки целиком, а не только кнопкой:
   курсор и подсветка показывают это до нажатия, обводка — тем, кто ходит с клавиатуры. */
#s-postavki tr[data-post],#s-postavki .pr-mob[data-post]{cursor:pointer}
#s-postavki tr[data-post]:hover{background:var(--sel)}
#s-postavki .pr-mob[data-post]:hover{background:var(--sel);
  box-shadow:0 0 0 var(--s2) var(--sel);border-radius:var(--r1)}
#s-postavki [data-post]:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
/* Подсветка строки не должна просвечивать сквозь кнопки, но красить их все подряд нельзя:
   заливка белым съедала синюю «Привоз принят» вместе с её белым текстом — кнопка выглядела
   пустой рамкой. Возвращаем фон только серым кнопкам, у цветных он свой. */
#s-postavki tr[data-post]:hover .btn.gray{background:var(--card)}

/* Снимки короба в разборе открывают пальцем: строчная ссылка высотой 25 px для этого мала. */
#s-postavki .rz-media{display:inline-flex;align-items:center;min-height:44px;padding:0 var(--s2)}

/* ── приёмка россыпи ─────────────────────────────────────────────────────── */
/* Номер места читается с метра: приёмщик стоит боком к монитору с вещью в руках, и мелкий
   текст он просто не смотрит. Поэтому цифра занимает пол-экрана, а подписи уходят вниз. */
#s-rossyp .rs-plita{margin:var(--s3) 0;padding:var(--s4) var(--s3);border-radius:var(--r2);
  text-align:center;border:2px solid var(--line)}
#s-rossyp .rs-mesto{background:var(--okbg);border-color:var(--ok)}
#s-rossyp .rs-razbor{background:var(--badbg);border-color:var(--bad)}
#s-rossyp .rs-zhdyom{color:var(--dim);font-size:var(--f4)}
#s-rossyp .rs-nomer{font:var(--w-b) clamp(72px,18vw,180px)/1 var(--mono);letter-spacing:2px}
#s-rossyp .rs-slovo{font:var(--w-b) clamp(40px,9vw,84px)/1.1 var(--font);color:var(--bad)}
#s-rossyp .rs-melko{margin-top:var(--s2);font-size:var(--f3);color:var(--dim)}
#s-rossyp #rsBar{font-size:var(--f4);min-height:var(--h-lg);text-align:center}

/* ── отгрузка: заметки над блоком коробов ────────────────────────────────── */
/* Мера чтения в 65 знаков верна для сплошного текста, но эти две заметки — перечисление складов
   и пояснение к хвосту. На мониторе они сжимались в колонку шириной в четверть экрана, росли
   на дюжину строк, а справа оставалось пустое поле. На широком экране ставим их рядом и даём
   каждой полноценную ширину; на планшете и телефоне остаётся прежний столбец. */
.ship-zametki{display:grid;gap:var(--s3);margin-top:var(--s3)}
.ship-zametki .note{margin:0;max-width:none}
@media(min-width:1200px){
  .ship-zametki{grid-template-columns:2fr 1fr;align-items:start}
  /* Одна заметка занимает ряд целиком: в двух колонках она оставляла справа пустое поле. */
  .ship-zametki:has(>:only-child){grid-template-columns:1fr}
}

/* Кто ещё разбирает россыпь: строка на человека — имя, поставка и сколько он уже принял. Число
   набрано тем же кеглем, что счётчики смены: на него смотрят издалека, оценивая, много ли осталось. */
/* Число слева, имя справа: на экране шириной в монитор счёт, отброшенный к правому краю, читался
   как отдельная колонка неизвестно чего. */
#s-rossyp .rs-chuzhoy{display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) 0;border-top:1px solid var(--line)}
#s-rossyp .rs-chuzhoy>b{flex:0 0 auto;min-width:4ch;text-align:right}
#s-rossyp .rs-chuzhoy:first-child{border-top:0}
#s-rossyp .rs-chuzhoy>div:first-child{min-width:0}

/* Списание и перевод в дубль. Ячейку выбирают из тех, где товар лежит: набранный руками номер —
   это списание не с той полки, а отменить его нельзя, журнал только дописывается. */
#s-spis .spis-cells,#s-spis-dubl .spis-cells{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s3) 0}
#s-spis .spis-cell,#s-spis-dubl .spis-cell{display:inline-flex;align-items:center;gap:var(--s2);
  min-height:var(--h);margin:0;padding:var(--s2) var(--s3);border:1px solid var(--line2);
  border-radius:var(--r1);background:var(--card);cursor:pointer}
#s-spis .spis-cell:has(input:checked),#s-spis-dubl .spis-cell:has(input:checked){
  border-color:var(--acc);background:var(--sel)}
#s-spis .spis-cell b,#s-spis-dubl .spis-cell b{font:var(--w-b) var(--f3)/1 var(--mono)}
#s-spis .spis-forma,#s-spis-dubl .spis-forma{display:grid;gap:var(--s3);max-width:520px}
#s-spis .spis-tovar .ok,#s-spis-dubl .spis-tovar .ok{margin-bottom:var(--s3)}

/* Свод дублей против МоегоСклада. Коды группы идут списком в одной ячейке таблицы: их бывает
   до двух десятков, и колонка на код разнесла бы таблицу вширь. Расхождение красит строку,
   а не только число, — глазами ищут строку целиком. */
#s-spis-dubl .sverka-dubli td{vertical-align:top}
#s-spis-dubl .sd-kody{min-width:260px}
#s-spis-dubl .sd-kod{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2);
  padding:2px 0;font:var(--f2)/1.4 var(--sans)}
#s-spis-dubl .sd-kod b{font:var(--w-b) var(--f2)/1.4 var(--mono);margin-left:auto}
#s-spis-dubl .sd-kod .dim{font:var(--f1)/1.4 var(--sans)}
/* Вид «Комплекты»: карточка набора с составом — отдельная таблица раздела, не строки групп. */
#s-spis-dubl .sd-komplekt{margin-bottom:var(--s2)}
#s-spis-dubl .sd-komplekt .sd-kody{margin-top:var(--s2)}
/* Артикул — ссылка на карточку маркетплейса. Цвет наследуем, чтобы строка не рябила синим:
   подчёркивание появляется под курсором, и этого хватает, чтобы понять, что это ссылка. */
#s-spis-dubl .sd-wb{color:inherit;text-decoration:none;border-bottom:1px dotted currentColor}
#s-spis-dubl .sd-wb:hover,#s-spis-dubl .sd-wb:focus-visible{color:#cb11ab;border-bottom-style:solid}
/* Справка о разделе: свёрнута, пока не нужна. Ширину текста держим в пределах читаемой строки —
   на мониторе абзац во всю ширину таблицы глазами не берётся. */
#s-spis-dubl .sd-spravka{margin-bottom:var(--s3)}
#s-spis-dubl .sd-spravka summary{cursor:pointer;font:var(--f3)/1.4 var(--sans)}
#s-spis-dubl .sd-spravka p{max-width:78ch;margin:var(--s3) 0 0;font:var(--f2)/1.55 var(--sans)}
#s-spis-dubl .sd-spravka p:first-of-type{margin-top:var(--s3)}

/* Шапка свода: заголовок слева, кнопки справа, на телефоне переносятся. */
#s-spis-dubl .sd-golova{display:flex;justify-content:space-between;align-items:center;
  gap:var(--s2);flex-wrap:wrap;margin-bottom:var(--s3)}
#s-spis-dubl .sd-golova h2{margin:0}

/* Итоги строкой: сколько групп, сколько горит. Читается за секунду, ради этого и стоит наверху. */
#s-spis-dubl .sd-itogi{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:baseline;
  margin-bottom:var(--s3);font:var(--f2)/1.4 var(--sans)}
#s-spis-dubl .sd-itog--dobit{color:var(--warn)}
#s-spis-dubl .sd-itog--razlit{color:var(--ok,#1a7f37)}

/* Панель отбора: поиск занимает всё свободное место, отборы рядом. */
#s-spis-dubl .sd-panel{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;
  margin-bottom:var(--s3)}
#s-spis-dubl .sd-poisk{flex:1 1 280px;min-width:0}
#s-spis-dubl .sd-men{flex:0 1 220px}
#s-spis-dubl .sd-flag{display:flex;align-items:center;gap:6px;font:var(--f2)/1 var(--sans);
  white-space:nowrap}
#s-spis-dubl .sd-pusto{padding:var(--s4) 0;text-align:center}

/* Метка «что делать»: цвет тот же, что у итогов, чтобы строка и счётчик читались как одно. */
#s-spis-dubl .sd-delo{display:inline-block;padding:1px 8px;border-radius:999px;
  font:var(--w-ctl) var(--f1)/1.6 var(--sans);vertical-align:middle}
#s-spis-dubl .sd-delo--dobit{background:var(--warnbg);color:var(--warn-ink,#7a4a00)}
#s-spis-dubl .sd-delo--razlit{background:#e8f5ec;color:#1a7f37}
#s-spis-dubl .sd-delo--rovno{background:var(--fon2,#f4f5f7);color:var(--dim)}

/* Кнопки действий держим справа и в одну колонку: так строка не прыгает по ширине. */
#s-spis-dubl .sd-deystviya{white-space:nowrap;text-align:right}
#s-spis-dubl .sd-deystviya .btn{margin-left:var(--s1)}
#s-spis-dubl .sd-detali td{background:var(--fon2,#f8f9fb)}

#s-spis-dubl .sd-rashod{background:var(--warnbg)}
#s-spis-dubl .sd-rashod .sd-znak{color:var(--warn-ink)}
#s-spis-dubl .warn-text{color:var(--warn);font-weight:var(--w-ctl)}
#s-spis-dubl .sd-mob{display:none}
@media(max-width:640px){
  /* Пять колонок на телефон не влезают, и разница уезжает за край — там же, где её и ищут.
     Таблицу прячем, те же данные показываем карточками. */
  #s-spis-dubl .tw:has(.sverka-dubli){display:none}
  #s-spis-dubl .sd-mob{display:grid;gap:var(--s3)}
  #s-spis-dubl .sd-karta{padding:var(--s3);border:1px solid var(--line2);border-radius:var(--r1)}
  #s-spis-dubl .sd-shapka{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s2)}
  #s-spis-dubl .sd-shapka .sd-znak{font:var(--w-b) var(--f3)/1 var(--mono)}
  #s-spis-dubl .sd-itog{margin:var(--s2) 0;font:var(--f2)/1.4 var(--sans)}
  #s-spis-dubl .sd-kod{font-size:var(--f1)}
  #s-spis-dubl .sd-kody{min-width:0}
}

/* История отгрузок: слева одна колонка со сведениями об отгрузке, справа строки её поставок.
   Пять узких столбцов под одну запись отбирали ширину у того, ради чего в историю и заходят.
   Экран смонтирован в контейнер #s-hist (его создаёт app.mjs), а прежний префикс #s-ship
   не совпадал с ним ни разу: весь блок был мёртвым, и таблицу рисовали одни глобальные
   правила — отсюда и ширины поровну, и капс в ячейке сведений, и её липкость. */
#s-hist .hist-otg{display:grid;gap:2px;font-size:var(--f1);line-height:1.4;white-space:normal}
/* Номер отгрузки — то, по чему запись ищут и на что ссылаются в споре: он крупнее остальных
   строк блока и набран цветом основного текста, а не приглушённым. */
#s-hist .hist-otg>b{font-size:var(--f3);font-weight:var(--w-b);color:var(--txt)}
#s-hist .hist-otg .dim b{color:var(--txt)}
/* Шесть однотипных приглушённых строк подряд читались как один серый абзац: глаз цеплялся
   только за номер. Делим блок надвое — «кто и когда отгрузил» и «что из этого вышло у WB», —
   и отделяем вторую половину линией: итоги приёмки ищут отдельно от исполнителя. */
#s-hist .hist-otg-itogi{display:grid;gap:2px;margin-top:var(--s2);padding-top:var(--s2);
  border-top:1px solid var(--line)}
#s-hist .warn-text{color:var(--warn);font-weight:var(--w-ctl)}
/* Кегль таблицы 14px: при базовых 16px семь колонок с моноширинными идентификаторами не
   помещались в 1280, и «WB-GI-268357750» рвался по дефису — а его сверяют посимвольно. */
#s-hist #tHist{width:auto;font-size:var(--f2)}
/* Границу рисуем только там, где начинается новая отгрузка: строки её поставок читаются одним
   блоком, а не двумя десятками отдельных записей. В прежнем селекторе стояло лишнее слово
   «table» (#tHist и есть таблица), поэтому линии внутри группы оставались, а разделителя между
   отгрузками не было вовсе. */
/* Все ячейки строк — у верха своей строки: при единственной поставке высоту строки задаёт блок
   сведений, и номер поставки повисал по центру шести строк текста. */
#s-hist #tHist tbody td,#s-hist #tHist tbody th{border-bottom:0;padding-block:var(--s1);vertical-align:top}
/* Поле ячейки по горизонтали уже общего: при 12px семи колонкам не хватало ширины на 1280,
   обёртка оставалась скроллпортом и резала нижнюю строку пополам. */
#s-hist #tHist td,#s-hist #tHist thead th{padding-inline:var(--s2)}
#s-hist #tHist thead th::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--line2)}
/* Заголовок первой колонки встаёт над номером отгрузки, а не правее его: у ячейки сведений
   левого поля нет (текст держит край карточки), и «ОТГРУЗКА» уезжала от «ОТГ-…» на 8px. */
#s-hist #tHist thead th:first-child{padding-inline-start:0}
/* Правый край «ЗАКАЗОВ» и правый край числа — по одной линии: у числа поле справа шире (оно
   отставлено от номера поставки), и без такого же поля у заголовка они расходились на 8px. */
#s-hist #tHist thead th:nth-child(2){padding-inline-end:var(--s4)}
/* Глобальное .mono задаёт свои 16px и перебивает кегль таблицы на каждой ячейке: номера поставок
   и время приёмки шли крупнее соседнего «в пути», а колонка «Поставка» из-за этого не сужалась. */
#s-hist #tHist .mono{font-size:inherit}
/* Кнопка выгрузки набрана кеглем таблицы: базовые 16px держали колонку «Состав» шире её
   заголовка на треть. */
#s-hist #tHist .btn.sm{font-size:var(--f2);padding-inline:var(--s3)}
/* Карточка истории — во всю ширину контента, как все прочие карточки приложения. По ширине
   таблицы (fit-content) она обрывалась на 1600 около x=1170, а заголовок и пояснение шли дальше:
   читалось как незаконченная вёрстка. Колонки при этом остаются узкими по содержимому — свободное
   место лежит внутри карточки справа от таблицы, а не режет её край. */
#s-hist .hist-shell{width:fit-content;max-width:100%;overflow:clip}
#s-hist .hist-otg .nowrap{white-space:nowrap}
/* Обёртка .tw перестаёт быть скроллпортом только с классом fits, а его ставит ui.mjs по замеру
   при открытии экрана — история же приходит с сервера позже, и класс не появлялся: таблицу
   резало по max-height ровно посреди строки, у второй отгрузки виднелась половина кнопки.
   Ширины подобраны так, чтобы таблица помещалась и в самой узкой точке с боковым меню (1200px,
   на контент остаётся 900), поэтому ограничение снимаем сами везде, где таблица вообще видна:
   прокрутка становится страничной, а липкой остаётся одна шапка. */
@media(min-width:1024px){#s-hist .hist-table{max-height:none;overflow:visible}}
#s-hist #tHist tbody tr.hist-nachalo>td,#s-hist #tHist tbody tr.hist-nachalo>th{border-top:1px solid var(--line2)}
/* Ячейка сведений — заголовок группы, но по содержанию данные. Снимаем с неё липкость: своим
   непрозрачным фоном она уезжала при прокрутке поверх строк чужих отгрузок. Заодно снимаем капс
   с разрядкой и серый цвет шапки — имя сборщика и дата так читаются вдвое медленнее. */
#s-hist #tHist tbody th[scope=rowgroup]{position:static;z-index:auto;width:204px;
  padding:var(--s3) var(--s3) var(--s3) 0;background:transparent;
  vertical-align:top;text-align:start;text-transform:none;letter-spacing:normal;
  font-weight:var(--w-txt);color:var(--txt)}
/* Ширины назначены по содержимому колонок, а не поровну: иначе «Отгрузка» занимала 445px под
   текст в 275px, а соседней «Поставке» доставалось меньше её же номера. */
#s-hist #tHist th:nth-child(2){width:74px}
#s-hist #tHist th:nth-child(3){width:142px}
#s-hist #tHist th:nth-child(4){width:112px}
#s-hist #tHist th:nth-child(5){width:96px}
/* Ширина колонки фото считается от кадра, а не на глаз: 64px при кадре 44px не давали второму
   кадру встать рядом, и миниатюры вставали лесенкой в два ряда. */
#s-hist #tHist th:nth-child(6){width:108px}
#s-hist #tHist th:nth-child(7){width:104px}
/* Два кадра в ряд всегда, сколько бы их ни было: у гибкой раскладки ширину ряда решала бы
   таблица, и число кадров в ряду плавало от отгрузки к отгрузке — на 1600 два в ряд, на 1280
   столбиком. В карточке телефона тот же .hist-kadry остаётся гибким рядом. */
#s-hist #tHist .hist-kadry{display:grid;grid-template-columns:repeat(2,44px)}
/* Идентификаторы и времена переносить нельзя: браузер всегда рвёт после дефиса. Перенос
   разрешён только строке «скан задним числом» — она втрое длиннее числа и в колонку не влезает;
   само время в пути обёрнуто в <b> и потому неразрывно. */
#s-hist #tHist tbody td.mono{white-space:nowrap}
#s-hist #tHist tbody td.n b{white-space:nowrap}
#s-hist #tHist thead th{white-space:nowrap;background:var(--card);font-size:var(--f1)}
/* Прокручивается страница (.page), а у неё есть внутреннее поле: липкая шапка встаёт по его
   нижнему краю, и в полосе над ней строки продолжали ехать на виду — сверху висела половина
   чужой строки, ровно то «непонятно зачем удерживается». Полосу закрашивает вставка над шапкой;
   при непрокрученной таблице её обрезает карточка (overflow:clip выше), и она невидима.
   Тенью это не сделать: в таблице с border-collapse:collapse Chrome тень ячейки не рисует. */
#s-hist #tHist thead th::before{content:"";position:absolute;left:0;right:0;bottom:100%;
  height:var(--s6);background:var(--card)}
/* Колонки, растянутые на все поставки отгрузки, держатся у верха: строка высотой в два десятка
   поставок иначе оставляет число заказов и кнопку висеть по центру пустоты. */
#s-hist #tHist tbody td[rowspan]{vertical-align:top;padding-top:var(--s3)}
/* Число заказов — показатель всей отгрузки, а не строки поставки: набрано крупнее строк таблицы
   и отставлено от соседнего номера, иначе «222» читалось началом «WB-GI-268357750». */
#s-hist #tHist tbody td.n[rowspan]{font-size:var(--f3);font-weight:var(--w-b);padding-inline-end:var(--s4)}

/* ---------- Управление людьми ---------- */
/* Галочки — главная работа раздела: им отдана ширина, разделы идут группами меню, операции
   отдельным блоком. Карточка раскрывается под шапкой человека. */
#s-upravlenie .upr-panel{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin-bottom:var(--s3)}
#s-upravlenie .upr-poisk{flex:1 1 260px;min-width:0}
#s-upravlenie .upr-flag{display:flex;align-items:center;gap:6px;white-space:nowrap}
#s-upravlenie .upr-chel{margin-bottom:var(--s2)}
#s-upravlenie .upr-chel--arhiv{opacity:.6}
#s-upravlenie .upr-shapka{display:flex;justify-content:space-between;align-items:center;gap:var(--s2);cursor:pointer}
/* Длинная строка «роль · вход · галочки» не сжималась и выталкивала кнопку за край карточки
   на телефоне: текст переносится, кнопка не ужимается. */
#s-upravlenie .upr-shapka>div{min-width:0}
#s-upravlenie .upr-shapka>.btn{flex-shrink:0}
#s-upravlenie .upr-telo{margin-top:var(--s3);border-top:1px solid var(--line);padding-top:var(--s3)}
#s-upravlenie .upr-deystviya{gap:var(--s2);flex-wrap:wrap;align-items:center;margin-bottom:var(--s3)}
#s-upravlenie .upr-pole{display:flex;align-items:center;gap:8px}
#s-upravlenie .upr-pole select{width:auto}
#s-upravlenie .upr-gr{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:4px var(--s3);margin:var(--s2) 0 var(--s3)}
#s-upravlenie .upr-chek{display:flex;align-items:baseline;gap:8px;font:var(--f2)/1.45 var(--sans);cursor:pointer}
#s-upravlenie .upr-chek input{flex:none}
#s-upravlenie .upr-chek--op span{font-weight:var(--w-ctl)}
#s-upravlenie .upr-chek--op small{font-weight:400}
#s-upravlenie .upr-form{display:grid;gap:var(--s3);margin-bottom:var(--s3)}
#s-upravlenie .upr-form label,.modal .upr-form label{display:grid;gap:6px}
#s-upravlenie .upr-pusto{padding:var(--s4) 0;text-align:center}

/* ---------- Проверка ячеек ---------- */
/* Раздел рисует экран свода с двумя добавленными колонками и блоком расхождений над таблицей.
   Три обязательных шага окна идут сверху вниз, фото расхождения — крупно: по нему решают. */
/* Колонок девять против семи у свода, а его сетка — auto (svod.css:748): там ширины лишь
   рекомендация, и «Ещё лежит» с nowrap растягивала таблицу за прокрутку — кнопку «Проверить»
   никто не находил. Здесь сетка жёсткая, содержимому разрешён перенос. */
#s-check #svodTabl{table-layout:fixed;min-width:1000px}
#s-check #svodTabl th,#s-check #svodTabl td{white-space:normal}
#s-check .svod-drugie{display:flex;flex-wrap:wrap;gap:4px}
#s-check #svodTabl th:nth-child(2),#s-check #svodTabl td:nth-child(2){width:88px}
#s-check #svodTabl th:nth-child(3),#s-check #svodTabl td:nth-child(3){width:64px}
#s-check #svodTabl th:nth-child(5),#s-check #svodTabl td:nth-child(5){width:138px}
#s-check #svodTabl th:nth-child(6),#s-check #svodTabl td:nth-child(6){width:150px}
#s-check #svodTabl th:nth-child(7),#s-check #svodTabl td:nth-child(7){width:64px}
#s-check #svodTabl th:nth-child(8),#s-check #svodTabl td:nth-child(8){width:110px}
#s-check #svodTabl th:nth-child(9),#s-check #svodTabl td:nth-child(9){width:140px}
/* На планшете девять колонок не помещаются: «Ещё лежит» наименее важна при обходе — те же
   места видны в карточке по клику на название. Прячем её, и кнопка остаётся на экране. */
@media (max-width:1300px){
  #s-check #svodTabl th:nth-child(6),#s-check #svodTabl td:nth-child(6){display:none}
  #s-check #svodTabl{min-width:840px}
}
#s-check .prv-knopki{text-align:right;white-space:nowrap}
#s-check .prv-kogda{white-space:normal}
#s-check .prv-ist{display:block;padding:0;border:0;background:transparent;color:inherit;
  font:inherit;text-align:left;cursor:pointer}
#s-check .prv-ist:hover{color:var(--acc)}
.modal .prv-ist-zapis{margin-bottom:var(--s2)}
.modal .prv-foto-sm{max-width:160px;max-height:120px}
#s-check .prv-rash{margin-bottom:var(--s2)}
#s-check .prv-rash-blok{margin-bottom:var(--s3)}
#s-check .prv-foto{max-width:280px;max-height:200px;border-radius:var(--r1);display:block}
.modal .prv-shagi{display:grid;gap:var(--s3);margin-bottom:var(--s3)}
.modal .prv-shag{display:grid;gap:6px}
.modal .prv-shag input[type="file"]{padding:var(--s2)}

/* Системная кнопка выбора файла (поставки, фото проверки) не выглядела своей: красим её
   под обычную кнопку приложения; подпись даёт браузер на языке системы. */
input[type="file"]::file-selector-button{margin-right:var(--s2);padding:6px 14px;
  border:1px solid var(--line2);border-radius:var(--r1);background:var(--card);
  color:var(--txt);font:inherit;cursor:pointer}
input[type="file"]::file-selector-button:hover{background:var(--sel)}
