/* CRM Китай: оболочка и компоненты. Цвета и размеры — только токены tokens.css;
   здесь допустимы 0, 1px и 2px (линии, рамки, кольцо) и доли. Движутся только
   transform и opacity; наведение — только у точного указателя. */

@font-face { font-family: 'Golos Text'; font-style: normal; font-weight: 400; font-display: swap; src: url(../fonts/golos-text-400.woff2) format('woff2'); }
@font-face { font-family: 'Golos Text'; font-style: normal; font-weight: 600; font-display: swap; src: url(../fonts/golos-text-600.woff2) format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url(../fonts/ibm-plex-mono-400.woff2) format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url(../fonts/ibm-plex-mono-600.woff2) format('woff2'); }

/* --- Основа ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  font-family: var(--font-sans); font-size: var(--fs-body); line-height: var(--lh-body);
  font-variant-numeric: tabular-nums; color: var(--c-text); background: var(--c-page);
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
body { margin: 0; min-height: 100vh; min-height: 100dvh; background: var(--c-page); display: flex; flex-direction: column; }
h1, h2, h3, p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: var(--c-accent); text-decoration: none; }
img, svg { display: block; }
img { max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; letter-spacing: inherit; }
b { font-weight: var(--fw-semibold); }
[hidden] { display: none !important; }
:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.nowrap { white-space: nowrap; }

.icon { width: var(--icon-md); height: var(--icon-md); flex: none; stroke-width: var(--icon-stroke); }
.icon-xs { width: var(--icon-xs); height: var(--icon-xs); }
.icon-sm { width: var(--icon-sm); height: var(--icon-sm); }
.icon-md { width: var(--icon-md); height: var(--icon-md); }
.icon-nav { width: var(--icon-nav); height: var(--icon-nav); }
.icon-lg { width: var(--icon-lg); height: var(--icon-lg); }
.icon-xl { width: var(--icon-empty); height: var(--icon-empty); }

/* --- Полоса загрузки: 3 px акцента вверху, сразу при переходе ------------ */
.loading-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100; height: var(--h-loading);
  background: var(--c-accent); transform: scaleX(0); transform-origin: left; opacity: 0; pointer-events: none;
}
.loading-bar.is-loading { opacity: 1; animation: loading var(--t-loading) cubic-bezier(.1, .7, .2, 1) forwards; }
/* Полоса видна с первого кадра: из нуля её не видно, а отклик нужен сразу. */
@keyframes loading { from { transform: scaleX(.06); } 10% { transform: scaleX(.4); } to { transform: scaleX(.92); } }

/* --- Шапка -------------------------------------------------------------- */
.topbar { position: sticky; top: 0; z-index: 20; background: var(--c-surface); border-bottom: 1px solid var(--c-line); padding-top: var(--safe-top); view-transition-name: topbar; }
.topbar-row { display: flex; align-items: center; gap: var(--sp-3); height: var(--h-header-phone); padding: 0 var(--sp-4); }
.topbar-title { font-size: var(--fs-caption); color: var(--c-text-quiet); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Блоком, а не флексом: многоточие у длинного имени работает только у блочного текста. */
.topbar-back { display: block; line-height: var(--h-tap); min-height: var(--h-tap); font-size: var(--fs-body); color: var(--c-accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: var(--h-tap); }
.topbar-brand, .topbar-nav, .topbar .topbar-lang, .page-back-row { display: none; }
/* Есть ссылка назад — в левом слоте шапки стоит она, название экрана уступает место.
   На экранах с полосой объекта ссылки в шапке нет вовсе: она стоит в полосе. */
.topbar-back ~ .topbar-title { display: none; }
.topbar-spacer { flex: 1; }

/* --- Полоса объекта: прилипает под шапкой и всё время говорит, где ты --------
   (правка 13.09: «не понятно, что где происходит»). Одна строка 44: возврат,
   номер, имя и чип этапа; имя обрывается многоточием, остальное не жмётся. */
.objbar {
  position: sticky; top: calc(var(--safe-top) + var(--h-header-phone) + 1px); z-index: 19;
  background: var(--c-surface); border-bottom: 1px solid var(--c-line); view-transition-name: objbar;
}
.objbar-inner { display: flex; align-items: center; gap: var(--sp-1); min-height: var(--h-objbar); padding: 0 var(--sp-4); }
.objbar-name { flex: 0 1 auto; min-width: 0; font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--c-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Имя-ссылка в полосе объекта — зона 44 по высоте полосы, текст на месте (проход 13.09). */
a.objbar-name { color: var(--c-text); line-height: var(--h-tap); }
/* Мелкие ссылки и кнопки меньше 44 — невидимый слой вокруг до зоны 44; вид не меняется
   (проход 13.09: наклейка номера 26–38, имя клиента 22–25, чип-ссылка 28, «CRM» 31, 入库 в
   шапке 32, язык 38, короткая вкладка 28). */
a.sticker, a.box-client, a.chip, .topbar-brand, .topbar-nav a, .segment-option, .tab, .row-link, .row-box-number { position: relative; }
a.sticker::after, a.box-client::after, a.chip::after, .topbar-brand::after, .topbar-nav a::after, .segment-option::after, .tab::after, .row-link::after, .row-box-number::after {
  content: ""; position: absolute;
  top: min(0px, calc((100% - var(--h-tap)) / 2)); bottom: min(0px, calc((100% - var(--h-tap)) / 2));
  left: min(0px, calc((100% - var(--h-tap)) / 2)); right: min(0px, calc((100% - var(--h-tap)) / 2));
}
.objbar .sticker, .objbar .chip, .objbar .code { flex: none; align-self: center; }
.objbar-gap { flex: 1; }
.objbar .page-back-row { display: flex; flex: none; width: auto; max-width: none; margin: 0; padding: 0; }
/* На телефоне в полосе только стрелка: место дороже слова, адрес тот же.
   Зона нажатия у неё всё равно 44×44 — стрелка сама по себе шириной в 6 px. */
.objbar .page-back-text { display: none; }
.objbar .page-back { min-width: var(--h-tap); justify-content: center; padding-inline: 0; margin-inline-start: calc(-1 * var(--sp-3)); }
.page-back {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  min-height: var(--h-tap); padding-inline: var(--sp-2); margin-inline-start: calc(-1 * var(--sp-2));
  border-radius: var(--r-control); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  color: var(--c-accent); transition: background-color var(--t-hover) ease;
}
.page-back-mark { font-size: var(--fs-body); line-height: 1; }

.menu { position: relative; flex: none; }
.menu > summary { list-style: none; cursor: pointer; }
.menu > summary::-webkit-details-marker { display: none; }
.menu-button { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); padding: 0 var(--sp-1); border-radius: var(--r-control); color: var(--c-text); }
.avatar { display: flex; align-items: center; justify-content: center; width: var(--avatar-phone); height: var(--avatar-phone); border-radius: var(--r-round); background: var(--c-fill); font-size: var(--fs-avatar); font-weight: var(--fw-semibold); color: var(--c-text-2); }
.menu-name, .menu-icon { display: none; }
.menu-icon { color: var(--c-text-2); }
.menu-panel {
  position: absolute; right: 0; top: calc(100% + var(--sp-2)); z-index: 30;
  width: min(var(--menu-width), calc(100vw - 2 * var(--sp-4)));
  display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-4);
  background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); box-shadow: var(--shadow-card);
}
.menu-user-name { font-weight: var(--fw-semibold); overflow-wrap: anywhere; }
.menu-user-role { font-size: var(--fs-caption); color: var(--c-text-quiet); }
.menu-sections { display: flex; flex-direction: column; }
.menu-sections a { display: flex; align-items: center; min-height: var(--h-tap); padding: 0 var(--sp-3); border-radius: var(--r-control); color: var(--c-text); }
.menu-sections a[aria-current="page"] { font-weight: var(--fw-semibold); }
.menu-lang { align-self: flex-start; }

/* --- Страница, липкая панель, нижняя панель ------------------------------ */
/* Снизу у листа всегда 24: это и воздух над липкой панелью (DESIGN.md, «Слой
   приложения» п. 15), и поля под последним блоком там, где панели нет — без него
   «Отправленных коробок пока нет» упиралось в нижний край экрана (правка 13.09). */
.page { flex: 1 0 auto; width: 100%; padding: var(--sp-4) var(--sp-4) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-4); }
.page-flush, .page-wide { padding: 0 0 var(--sp-6); gap: 0; }
.page-title { font-size: var(--fs-title-phone); font-weight: var(--fw-semibold); }
.lang-ru .page-title { letter-spacing: var(--ls-cyrillic); }
.page-count { font-size: var(--fs-caption); font-weight: var(--fw-regular); color: var(--c-text-quiet); margin-left: var(--sp-2); letter-spacing: 0; }

.actionbar { position: sticky; bottom: 0; z-index: 15; background: var(--c-surface); border-top: 1px solid var(--c-line); box-shadow: var(--shadow-sticky); padding: var(--sp-3) var(--sp-4) calc(var(--sp-3) + var(--safe-bottom)); }
.actionbar:not(:has(.actionbar-inner > *)) { display: none; }
.has-bottom-nav .actionbar { bottom: calc(var(--h-nav-item) + 1px + var(--safe-bottom)); padding-bottom: var(--sp-3); }
.actionbar-inner { display: flex; flex-direction: column; gap: var(--sp-3); }
.actionbar-inner:empty { display: none; }
/* Область ответа поиска по ходу ввода: для раскладки её нет, строки стоят там же, где стояли. */
.live-results { display: contents; }
/* Два действия — в один ряд: столбиком второе уезжало под нижний край экрана
   (правка 13.09, формы клиента, позиции и привязки). Главное растягивается,
   второстепенное идёт по содержимому и остаётся целиком видимым. */
.actionbar-pair { flex-direction: row; align-items: center; }
.actionbar-pair > .btn-primary { flex: 1 1 auto; min-width: 0; }
.actionbar-pair > .btn-secondary, .actionbar-pair > .btn-quiet { flex: 0 0 auto; width: auto; }

.bottom-nav { position: sticky; bottom: 0; z-index: 16; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; background: var(--c-surface); border-top: 1px solid var(--c-line); padding-bottom: var(--safe-bottom); view-transition-name: bottom-nav; }
.bottom-nav-item { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-1); min-height: var(--h-nav-item); padding: var(--sp-2) var(--sp-1); font-size: var(--fs-label); color: var(--c-text-quiet); text-align: center; }
.bottom-nav-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bottom-nav-item[aria-current="page"] { color: var(--c-accent); font-weight: var(--fw-semibold); }

/* --- Кнопки ------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--h-tap); padding: var(--sp-2) var(--sp-4); border: 1px solid transparent; border-radius: var(--r-control);
  font-size: var(--fs-body); font-weight: var(--fw-semibold); line-height: var(--lh-button); text-align: center;
  cursor: pointer; user-select: none; text-decoration: none; background: none; color: var(--c-text-2);
  transition: background-color var(--t-hover) ease, transform var(--t-press) ease;
}
.btn:active { transform: scale(var(--press-scale)); }
.btn-primary { min-height: var(--h-button); background: var(--c-accent); color: var(--c-on-accent); font-size: var(--fs-button); }
.btn-primary:active, .btn-primary.is-pressed { background: var(--c-accent-active); }
.btn-secondary { background: var(--c-surface); color: var(--c-text); border-color: var(--c-field); }
.btn-secondary:active, .btn-secondary.is-pressed { background: var(--c-fill); }
.btn-quiet { background: none; color: var(--c-text-2); }
.btn-quiet:active, .btn-quiet.is-pressed { background: var(--c-fill-strong); }
.btn-small { font-size: var(--fs-answer); padding: var(--sp-2) var(--sp-3); gap: var(--sp-1); }
.btn-primary.btn-small { min-height: var(--h-button-desktop); }
.btn-block { display: flex; width: 100%; }
.btn[disabled], .btn.is-busy { background: var(--c-fill); color: var(--c-text-quiet); border-color: transparent; cursor: not-allowed; transform: none; }
.btn-primary .icon { color: var(--c-on-accent); }
.is-pressed { transform: scale(var(--press-scale)); }
.is-focus { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover:not([disabled]), .btn-primary.is-hover { background: var(--c-accent-hover); }
  .btn-primary:active:not([disabled]) { background: var(--c-accent-active); }
  .btn-secondary:hover:not([disabled]), .btn-secondary.is-hover { background: var(--c-page); }
  .btn-secondary:active:not([disabled]) { background: var(--c-fill); }
  .btn-quiet:hover:not([disabled]), .btn-quiet.is-hover { background: var(--c-fill); }
  .btn-quiet:active:not([disabled]) { background: var(--c-fill-strong); }
  .menu-button:hover, .menu-sections a:hover { background: var(--c-fill); }
  .row:hover, .row.is-hover, .recent-open:hover { background: var(--c-row-hover); }
  .row-client .row-box-number:hover { color: var(--c-accent-hover); text-decoration: underline; }
  .topbar-nav a:hover, .tab:hover, .tab.is-hover { color: var(--c-accent); }
  .segment-option:not([aria-pressed="true"]):hover { background: var(--c-fill-strong); }
  .camera:hover { background: var(--c-page); }
  .page-back:hover, .found-back:hover { background: var(--c-fill); }
  .row-go:hover { background: var(--c-fill); color: var(--c-text-2); }
  a.sticker:hover { background: var(--c-row-hover); }
}

/* --- Выделение текста (проход 13.09) ---------------------------------------
   Нажатие на подпись, заголовок, кнопку, чип этапа, узел линейки, шапку и нижнюю
   панель не выделяет текст и не открывает меню долгого нажатия: на телефоне палец
   держит кнопку чуть дольше — и вместо действия всплывало «Копировать / Поиск».
   Выделять и копировать можно то, чем пользуются: номер клиента и коробки, трек,
   телефон, описание товара, суммы, адрес склада, логин и пароль на экране выдачи,
   поля ввода. Меню долгого нажатия на ссылках Android глушит app.js (contextmenu). */
.field-label, .field-hint, .page-title, .section-title, .page-count, h1, h2, h3,
.btn, button, summary, .segment, .toggle, .kb-toggle, .row-go, .camera, .chip, .tabs, .tab,
.rail, .rail-name, .rail-date, .row-head, .item-photo-caption, .today-line, .scale-label, .scale-rest,
.topbar, .menu-button, .menu-sections, .bottom-nav, .actionbar, .page-back, .sticker-word, .answer-title {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.code, .sticker-code, .track, .phone, .qty, .item-desc, .item-title, .rcv-card-desc, .row-desc, .recent-desc,
.item-price, .row-price, .receipt-row > span, .fact-row > span, .sheet-num, .row-address .row-main, .cred-value,
.row-name, .client-name, .client-facts, .objbar-name,
input, textarea, output {
  -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}

/* --- Поля --------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: var(--sp-1); }
.field-label { font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--c-text-2); }
.input {
  width: 100%; height: var(--h-field); padding: 0 var(--sp-3); background: var(--c-surface);
  border: 1px solid var(--c-field); border-radius: var(--r-control); font-size: var(--fs-body); color: var(--c-text);
  caret-color: var(--c-accent); appearance: none;
}
.input:focus, .input.is-focus { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-color: var(--c-accent); }
.input::placeholder { color: var(--c-text-quiet); opacity: 1; }
.input-mono { font-family: var(--font-mono); font-size: var(--fs-button); letter-spacing: var(--ls-track); }
.input-multiline { height: auto; min-height: var(--h-multiline); padding: var(--sp-3); resize: none; line-height: var(--lh-body); }
.field-hint { font-size: var(--fs-caption); color: var(--c-text-quiet); }
.field-error { font-size: var(--fs-caption); color: var(--err-text); }
.field.is-error .input { border: var(--field-border-error) solid var(--err-text); padding: 0 calc(var(--sp-3) - 1px); }
.field.is-error .input-multiline { padding: calc(var(--sp-3) - 1px); }

/* Зона снимка: пунктир, иконка и слово; выбранный снимок — превью или отметка. */
.camera {
  position: relative; display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  min-height: var(--h-camera); padding: var(--sp-3); background: var(--c-surface);
  border: var(--camera-border) dashed var(--c-field); border-radius: var(--r-control);
  font-size: var(--fs-button); font-weight: var(--fw-semibold); color: var(--c-text); cursor: pointer;
  transition: background-color var(--t-hover) ease;
}
.camera:active { background: var(--c-fill); }
.camera:has(input:focus-visible) { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.camera-empty, .camera-chosen { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; white-space: nowrap; }
.camera-chosen { display: none; }
.camera.has-photo .camera-empty { display: none; }
.camera.has-photo .camera-chosen { display: inline-flex; }
/* Две зоны рядом: «Камера» и «Галерея» (проход 13.09). Внутри зоны — столбиком:
   без скриптов под словом стоит имя выбранного файла, со скриптами — превью над именем. */
.camera-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
.camera-pair > .camera { flex-direction: column; gap: var(--sp-1); min-width: 0; text-align: center; }
.camera-pair .camera-native { order: 2; max-width: 100%; }
.camera-pair .camera-chosen { max-width: 100%; }
.camera-preview { width: var(--thumb-panel); height: var(--thumb-panel); object-fit: cover; border-radius: var(--r-control); border: 1px solid var(--c-line); background: var(--c-photo-bg); }
.camera-field.is-error .camera { border-color: var(--err-text); }
/* Нажатие возврата видно сразу, как у тихой кнопки. */
.page-back:active { background: var(--c-fill-strong); }
/* Необязательный снимок: та же зона камеры. Без скриптов состояние показывает сам
   выбор файла: кнопку выбора прячем, остаётся имя файла («Файл не выбран» до
   выбора). Когда скрипт ожил (is-enhanced), вместо него идут превью, имя и «Убрать». */
/* Имя файла идёт после кнопки, а не перед ней: сначала действие, потом состояние. */
.camera-native { order: 1; flex: 0 1 auto; min-width: 0; overflow: hidden; font-size: var(--fs-caption); font-weight: var(--fw-regular); color: var(--c-text-2); }
.camera-native::file-selector-button { display: none; }
.camera-native::-webkit-file-upload-button { display: none; }
.camera-field.is-enhanced .camera-native { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.camera-chosen-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.camera-clear { align-self: flex-start; }

/* --- Поле трека (приём) ------------------------------------------------- */
.track-bar { background: var(--c-surface); border-bottom: 1px solid var(--c-line); padding: var(--sp-2) var(--sp-4) var(--sp-3); }
.track-field { display: flex; flex-direction: column; gap: var(--sp-1); }
/* Поле и кнопка раскладки — в одной строке; кнопка своя, зона 44 (правка 12.09). */
.track-row { display: flex; align-items: center; gap: var(--sp-2); }
.track-box {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--sp-1); height: var(--h-field); padding: 0 var(--sp-2) 0 var(--sp-3);
  background: var(--c-surface); border: 1px solid var(--c-field); border-radius: var(--r-control);
}
.track-box:focus-within, .track-box.is-focus { border-color: var(--c-accent); outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.track-input {
  flex: 1; min-width: 0; height: 100%; padding: 0; border: 0; outline: none; background: none;
  font-family: var(--font-mono); font-size: var(--fs-input); letter-spacing: var(--ls-track); color: var(--c-text); caret-color: var(--c-accent);
}
/* Подсказка 14, а не 16: «Трек или 4 цифры с конца» при 16 не входила в поле рядом с
   «ABC» и лупой на 360 (проход 13.09: нужно 213 px, есть 195). */
.track-input::placeholder { font-family: var(--font-sans); font-size: var(--fs-caption); letter-spacing: 0; color: var(--c-text-quiet); opacity: 1; }
.track-input:focus-visible { outline: none; }
/* Кнопка раскладки — второстепенная, зона 44×44 (SPEC «Кнопка второстепенная»). */
.kb-toggle {
  flex: none; display: flex; align-items: center; justify-content: center;
  min-width: var(--h-tap); height: var(--h-tap); padding: 0 var(--sp-3);
  background: var(--c-surface); border: 1px solid var(--c-field); border-radius: var(--r-control);
  font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--c-text);
  transition: background-color var(--t-hover) ease, transform var(--t-press) ease;
}
.kb-toggle:active { background: var(--c-fill); transform: scale(var(--press-scale)); }
.track-search { flex: none; display: flex; align-items: center; justify-content: center; width: var(--h-tap); height: var(--h-tap); padding: 0; border: 0; border-radius: var(--r-control); background: none; color: var(--c-text-2); cursor: pointer; }
@media (hover: hover) and (pointer: fine) {
  .track-search:hover { background: var(--c-fill); }
  .kb-toggle:hover { background: var(--c-page); }
  /* Экранной клавиатуры нет — переключать её раскладку незачем. */
  .kb-toggle { display: none; }
}

/* --- Наклейка, номер, трек, количество ----------------------------------- */
.sticker {
  display: inline-flex; align-items: baseline; align-self: flex-start;
  font-family: var(--font-mono); font-weight: var(--fw-semibold); letter-spacing: var(--ls-sticker); line-height: var(--lh-number);
  color: var(--c-text); border: 1px solid var(--c-text); border-radius: var(--r-control); padding: var(--sp-1) var(--sp-2); white-space: nowrap;
}
.sticker-lg { font-size: var(--fs-sticker); border-width: var(--sticker-border); border-radius: var(--r-sticker); }
.sticker-md { font-size: var(--fs-input); border-width: var(--sticker-border); border-radius: var(--r-sticker); }
.sticker-sm { font-size: var(--fs-caption); }
/* По-русски слово перед номером через пробел, по-китайски «118号箱» — без зазора. */
.sticker-word { font-family: var(--font-sans); font-weight: var(--fw-regular); letter-spacing: 0; }
.sticker-word:first-child { margin-right: var(--sp-1); }
.code { font-family: var(--font-mono); font-weight: var(--fw-semibold); letter-spacing: var(--ls-track); white-space: nowrap; color: var(--c-text); }
.code-row { font-size: var(--fs-code-row); }
.code-sm { font-size: var(--fs-caption); }
.track { font-family: var(--font-mono); color: var(--c-text-quiet); white-space: nowrap; }
.track-md { font-size: var(--fs-caption); }
.track-lg { font-size: var(--fs-answer); }
.track-sm { font-size: var(--fs-label); }
.track-tail { font-weight: var(--fw-semibold); color: var(--c-text); }
.qty { font-weight: var(--fw-semibold); white-space: nowrap; }
.qty-lg { font-size: var(--fs-quantity); line-height: 1.1; }
.qty-row { font-size: var(--fs-qty-row); }
.qty-md { font-size: var(--fs-body); }

/* --- Чип этапа: мягкий фон, значок и слово; контур только у «Ждём» ------- */
.chip { display: inline-flex; align-items: center; gap: var(--sp-2); flex: none; padding: var(--sp-1) var(--sp-2); border-radius: var(--r-control); font-size: var(--fs-label); font-weight: var(--fw-semibold); line-height: var(--lh-body); white-space: nowrap; }
.chip .icon { width: var(--icon-sm); height: var(--icon-sm); }
.chip-new { background: var(--st-new-bg); color: var(--st-new-text); border: 1px solid var(--st-new-line); }
.chip-arrived { background: var(--st-arrived-bg); color: var(--st-arrived-text); }
.chip-packed { background: var(--st-packed-bg); color: var(--st-packed-text); }
.chip-boxpacked { background: var(--st-boxpacked-bg); color: var(--st-boxpacked-text); }
.chip-transit { background: var(--st-transit-bg); color: var(--st-transit-text); }
.chip-received { background: var(--st-received-bg); color: var(--st-received-text); }

/* --- Фото и заглушки ---------------------------------------------------- */
.ph { background: var(--c-photo-bg); }
.ph.is-shown { animation: fadein var(--t-fade) ease-out; }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
.ph-open { display: block; width: 100%; height: 100%; }
.ph-empty { width: 100%; height: 100%; }
/* Формы заглушек один раз на странице (ui.placeholder_shapes): не видны и не занимают места. */
.ph-shapes { position: absolute; width: 0; height: 0; overflow: hidden; }
.ph-bg { fill: var(--c-photo-bg); }
.ph-shape { fill: var(--c-photo-shape); }
.ph-detail { fill: var(--c-photo-detail); }
.ph-card { fill: var(--c-surface); }
.thumb { position: relative; flex: none; display: block; width: var(--thumb-row); height: var(--thumb-row); border: 1px solid var(--c-line); border-radius: var(--r-control); overflow: hidden; background: var(--c-photo-bg); }
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.thumb-panel { width: var(--thumb-panel); height: var(--thumb-panel); overflow: visible; }
.thumb-panel > .ph-open, .thumb-panel > .ph-empty, .thumb-panel > img { border-radius: calc(var(--r-control) - 1px); overflow: hidden; }

.photo-dialog { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; padding: 0; border: 0; background: var(--c-viewer); color: var(--c-on-accent); }
.photo-dialog::backdrop { background: var(--c-viewer); }
.photo-dialog[open] { display: flex; flex-direction: column; }
.photo-dialog form { display: flex; justify-content: flex-end; padding: calc(var(--sp-2) + var(--safe-top)) var(--sp-2) var(--sp-2); }
.photo-dialog-close { color: var(--c-on-accent); }
.photo-dialog-img { flex: 1; min-height: 0; width: 100%; height: 100%; object-fit: contain; }

/* --- Карточка ----------------------------------------------------------- */
.card { background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); box-shadow: var(--shadow-card); }

/* --- Ответ под полем, полоса сообщения, пустое состояние ------------------ */
.answer { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-3); border: 1px solid; border-radius: var(--r-card); animation: rise var(--t-answer) ease-out both; }
.answer-icon { margin-top: var(--sp-1); }
.answer-body { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1; min-width: 0; }
.answer-title { font-size: var(--fs-body); font-weight: var(--fw-semibold); }
.answer-line { font-size: var(--fs-answer); }
.answer-body > form { margin-top: var(--sp-2); }
.answer-body > .btn { align-self: flex-start; margin-top: var(--sp-2); }
.answer-ok { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok-text); }
.answer-warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-text); }
.answer-err { background: var(--err-bg); border-color: var(--err-line); color: var(--err-text); }
.answer-info { background: var(--c-fill); border-color: var(--c-neutral-line); color: var(--c-text-2); }
.answer-info .answer-line { font-size: var(--fs-body); }
.check-draw path { fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 0; animation: draw var(--t-check) ease-out var(--t-answer) both; }
@keyframes rise { from { opacity: 0; transform: translateY(var(--answer-shift)); } to { opacity: 1; transform: none; } }
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

.banner { padding: var(--sp-3) var(--sp-4); border: 1px solid; border-radius: var(--r-control); display: flex; flex-direction: column; gap: var(--sp-1); }
.banner-iconed { flex-direction: row; align-items: flex-start; gap: var(--sp-3); }
.banner-lines { display: flex; flex-direction: column; gap: var(--sp-1); }
.banner-icon { flex: none; }
.banner-warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-text); }
.banner-err { background: var(--err-bg); border-color: var(--err-line); color: var(--err-text); }
.banner-ok { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok-text); }

.empty { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); padding: var(--sp-8) var(--sp-4); text-align: center; color: var(--c-text-2); }
.empty-icon { color: var(--c-text-quiet); }

/* --- Строки списка (телефон) -------------------------------------------- */
.rows { background: var(--c-surface); border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); }
.row { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--h-row-phone); padding: var(--sp-3) var(--sp-4); color: inherit; transition: background-color var(--t-hover) ease; }
.row + .row { border-top: 1px solid var(--c-line); }
/* Нажатие видно сразу, до ответа сервера: строка темнеет на тон глубже наведения.
   Размер строки при этом не меняется — двигаются только кнопки. */
.row:active, .row.is-pressed, .row:has(.row-open:active) { background: var(--c-fill); transform: none; transition-duration: var(--t-press); }
.row:focus-visible, .row:has(.row-open:focus-visible) { outline: var(--focus-ring); outline-offset: -2px; }
.row-main { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1; min-width: 0; }
/* Строка ведёт дальше — это видно и по курсору, и по шеврону справа (SPEC
   «Строка списка, телефон»; правка 13.09: строки выглядели неподвижным текстом). */
a.row, .row:has(> .row-open), .row:has(> .check-input:not(:disabled)), label.row:has(.check-input:not(:disabled)) { cursor: pointer; }
.row-go { flex: none; display: flex; align-items: center; justify-content: center; width: var(--h-tap); min-height: var(--h-tap); margin-inline-end: calc(-1 * var(--sp-2)); border-radius: var(--r-control); color: var(--c-field); transition: background-color var(--t-hover) ease; }
.row-go:active { background: var(--c-fill-strong); color: var(--c-text-2); }
/* В строке-сетке шеврон выведен из потока и стоит в правом поле: колонкой он
   отнимал у описания 44 px, и на 360 описание рассыпалось на четыре строки. */
.row-client, .row-client-item { position: relative; padding-inline-end: calc(var(--sp-4) + var(--icon-md)); }
.row-client > .row-go, .row-client-item > .row-go {
  position: absolute; right: var(--sp-1); top: 50%; transform: translateY(-50%);
  width: var(--icon-md); min-height: 0; margin: 0;
}
/* Вся строка ведёт дальше: главная ссылка строки накрывает её, кроме галочки выбора. */
.row-client-item > .row-desc::after { content: ''; position: absolute; inset: 0 0 0 calc(var(--h-tap) + var(--sp-3)); }
.row-desc { font-size: var(--fs-caption); color: var(--c-text-2); overflow-wrap: anywhere; }
.row-pick { gap: var(--sp-2); padding-left: var(--sp-2); cursor: pointer; }
.row-pick.is-disabled { cursor: default; }
.check-slot { flex: none; width: var(--h-tap); }

/* Галочка: настоящий checkbox поверх нарисованного квадрата. */
.check { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; width: var(--h-tap); height: var(--h-tap); }
.check-input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.check-box { display: flex; align-items: center; justify-content: center; width: var(--check-box); height: var(--check-box); border: 1px solid var(--c-field); border-radius: var(--r-check); background: var(--c-surface); color: var(--c-on-accent); }
/* Нарисованный квадрат нажатие не ловит — оно доходит до поля: галочка вне строки-label
   (список клиентов, коробки у владельца, 14.09) иначе не отмечалась. */
.check-box { pointer-events: none; }
.check-box .icon { width: var(--icon-sm); height: var(--icon-sm); stroke-width: var(--mark-stroke); opacity: 0; }
.check-input:checked + .check-box { background: var(--c-accent); border-color: var(--c-accent); }
.check-input:checked + .check-box .icon { opacity: 1; }
.check-input:focus-visible + .check-box { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.check-input:disabled + .check-box { background: var(--c-fill); border-color: var(--c-line-quiet); }
.check-round .check-box { border-radius: var(--r-round); }

/* --- Переключатель, вкладки, сегмент языка -------------------------------- */
.toggle { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--c-text-2); }
.toggle-track { display: flex; align-items: center; width: var(--w-toggle); height: var(--h-toggle); padding: 2px; border-radius: var(--h-toggle); background: var(--c-line-quiet); transition: background-color var(--t-hover) ease; }
.toggle-knob { width: var(--toggle-knob); height: var(--toggle-knob); border-radius: var(--r-round); background: var(--c-surface); transition: transform var(--t-hover) ease; }
.toggle.is-on .toggle-track { background: var(--c-accent); }
.toggle.is-on .toggle-knob { transform: translateX(calc(var(--w-toggle) - var(--toggle-knob) - 2 * 2px)); }

/* Вкладки — всегда одна строка: на телефоне она прокручивается вбок, перенос на
   вторую и третью строку отжимал список (замер 12.09). Полоса прокрутки скрыта:
   строка вкладок и так 44, лишние 8–15 px под полосу съедали бы список.
   Затухание у краёв ставит скрипт (data-edge), пока есть куда прокручивать.
   В маске black и transparent — не цвета из палитры, а непрозрачность: где
   black — ряд виден целиком, где transparent — растворяется. */
.tabs { display: flex; flex-wrap: nowrap; align-items: stretch; column-gap: var(--sp-4); padding: 0 var(--sp-4); border-bottom: 1px solid var(--c-line); font-size: var(--fs-caption); overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -ms-overflow-style: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs[data-edge="start"] { mask-image: linear-gradient(to right, transparent 0, black var(--tabs-fade), black 100%); }
.tabs[data-edge="end"] { mask-image: linear-gradient(to right, black 0, black calc(100% - var(--tabs-fade)), transparent 100%); }
.tabs[data-edge="both"] { mask-image: linear-gradient(to right, transparent 0, black var(--tabs-fade), black calc(100% - var(--tabs-fade)), transparent 100%); }
.tab { display: flex; align-items: center; min-height: var(--h-tab); color: var(--c-text-2); border-bottom: 2px solid transparent; white-space: nowrap; scroll-margin-inline: var(--sp-4); }
.tab[aria-current="page"] { color: var(--c-text); font-weight: var(--fw-semibold); border-bottom-color: var(--c-accent); }

.segment { display: inline-flex; align-items: stretch; gap: 2px; padding: 2px; background: var(--c-fill); border-radius: var(--r-control); }
.segment-option { display: flex; align-items: center; min-height: var(--h-tap); padding: 0 var(--sp-4); border: 0; border-radius: var(--r-segment); background: none; font-size: var(--fs-body); color: var(--c-text-2); cursor: pointer; transition: background-color var(--t-hover) ease; }
.segment-option[aria-pressed="true"] { background: var(--c-surface); color: var(--c-text); font-weight: var(--fw-semibold); cursor: default; }

/* --- Шкала, чек, телефон ------------------------------------------------- */
.scale { display: flex; flex-direction: column; gap: var(--sp-1); }
.scale-label { font-size: var(--fs-caption); color: var(--c-text-2); }
.scale-bar { width: 100%; height: var(--h-scale); overflow: visible; }
.scale-track { fill: var(--c-line); }
.scale-fill { fill: var(--scale-calm); transform-box: fill-box; transform-origin: left; animation: fill var(--t-scale) ease-out both; }
.scale-near .scale-fill { fill: var(--scale-near); }
.scale-over .scale-fill { fill: var(--scale-over); }
.scale-over .scale-label, .scale-over .scale-rest { color: var(--scale-over); }
.scale-tick { fill: var(--c-field); }
.scale-rest { font-size: var(--fs-label); color: var(--c-text-quiet); }
@keyframes fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.receipt { display: flex; flex-direction: column; gap: var(--sp-3); }
.receipt-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.receipt-row > span:first-child { color: var(--c-text-2); }
.receipt-total { padding-top: var(--sp-3); border-top: 1px solid var(--c-line); font-size: var(--fs-body); font-weight: var(--fw-semibold); }
.receipt-total > span:first-child { color: var(--c-text); }
.receipt-note { font-size: var(--fs-label); color: var(--c-text-quiet); }

.phone { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); font-size: var(--fs-answer); color: var(--c-accent); }

/* --- Линейка этапов «по палочкам» ---------------------------------------- */
.rail { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); column-gap: var(--sp-2); align-items: start; }
/* Пять этапов позиции на 390 в строку не встают с зазором 8 — им 4. */
.rail:has(> :nth-child(5)) { column-gap: var(--sp-1); }
.rail-node { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); min-width: 0; }
.rail-top { position: relative; width: 100%; height: var(--rail-dot-current); display: flex; align-items: center; justify-content: center; }
.rail-bar { position: absolute; top: calc((var(--rail-dot-current) - var(--rail-bar)) / 2); height: var(--rail-bar); background: var(--c-rail-idle); }
.rail-bar-in { left: calc(-1 * var(--rail-gap)); right: calc(50% + var(--rail-dot-current) / 2 + var(--rail-gap)); border-radius: 0 var(--r-rail) var(--r-rail) 0; }
.rail-bar-out { left: calc(50% + var(--rail-dot-current) / 2 + var(--rail-gap)); right: calc(-1 * var(--rail-gap)); border-radius: var(--r-rail) 0 0 var(--r-rail); }
.rail-bar.is-filled { background: var(--c-accent); }
.rail-dash { position: absolute; top: calc(var(--rail-dot-current) / 2 - 1px); border-top: 2px dashed var(--c-line-quiet); }
.rail-dash.rail-bar-in { right: calc(50% + var(--rail-dot-future) / 2 + var(--rail-gap)); }
.rail-dot { position: relative; display: flex; align-items: center; justify-content: center; border-radius: var(--r-round); color: var(--c-on-accent); }
.rail-dot .icon { stroke-width: var(--mark-stroke); }
.is-done .rail-dot { width: var(--rail-dot-done); height: var(--rail-dot-done); background: var(--c-accent); }
.is-done .rail-dot .icon { width: var(--rail-check-done); height: var(--rail-check-done); }
.is-current .rail-dot { width: var(--rail-dot-current); height: var(--rail-dot-current); background: var(--c-accent); }
.is-current .rail-dot .icon { width: var(--rail-check-current); height: var(--rail-check-current); }
.is-future .rail-dot { width: var(--rail-dot-future); height: var(--rail-dot-future); background: var(--c-surface); border: 2px solid var(--c-line-quiet); }
.rail-halo { position: absolute; width: var(--rail-halo); height: var(--rail-halo); border-radius: var(--r-round); background: var(--c-halo); }
.rail-truck { position: absolute; left: 100%; top: calc((var(--rail-dot-current) - var(--rail-truck)) / 2); width: var(--rail-truck); height: var(--rail-truck); margin-left: var(--rail-truck-shift); color: var(--c-text-quiet); }
.rail-name { font-size: var(--fs-small); line-height: var(--lh-button); text-align: center; white-space: nowrap; color: var(--c-text-quiet); }
.is-done .rail-name { color: var(--c-text-2); }
.is-current .rail-name { color: var(--c-text); font-weight: var(--fw-semibold); }
.rail-date { font-size: var(--fs-small); color: var(--c-text-quiet); white-space: nowrap; }
/* Заливка и въезд грузовика — только если этап сменился с прошлого просмотра. */
.rail.is-anim .rail-bar-in.is-lead { transform-origin: left; animation: fill var(--t-rail) ease-out both; }
.rail.is-anim .rail-halo { animation: halo var(--t-halo) ease-out var(--t-halo-delay) both; }
.rail.is-anim .rail-truck { animation: drive var(--t-rail) ease-out both; }
@keyframes halo { from { opacity: 0; } to { opacity: 1; } }
@keyframes drive { from { opacity: 0; transform: translateX(calc(-1 * var(--sp-2))); } to { opacity: 1; transform: none; } }

/* --- Приём --------------------------------------------------------------- */
.rcv-results { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-3) 0 var(--sp-4); }
.rcv-results > :not(.rows):not(.recent) { margin-inline: var(--sp-4); }
.rcv-results > .rcv-card:first-child { margin-top: calc(-1 * var(--sp-2)); }
.rcv-results > .found-line + .rows { margin-top: calc(-1 * var(--sp-1)); }
.found-line { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-caption); color: var(--c-text-quiet); }
/* Возврат к списку совпадений ведёт себя как ссылка назад на страницах:
   слева, зона 44, отклик на нажатие (правка 12.09). */
.found-back { align-self: flex-start; min-height: var(--h-tap); padding-inline: var(--sp-2); margin-inline-start: calc(-1 * var(--sp-2)); border-radius: var(--r-control); font-weight: var(--fw-semibold); color: var(--c-accent); transition: background-color var(--t-hover) ease; }
.found-back:active { background: var(--c-fill-strong); }
.rcv-card { display: flex; flex-direction: column; gap: var(--sp-1); padding: var(--sp-3); }
.rcv-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.rcv-card-photo { width: 100%; aspect-ratio: 1 / 1; border: 1px solid var(--c-line); border-radius: var(--r-control); overflow: hidden; background: var(--c-photo-bg); }
.rcv-card.is-short .rcv-card-photo { aspect-ratio: auto; height: var(--photo-card-short); }
.rcv-card-photo img { width: 100%; height: 100%; object-fit: cover; }
.rcv-card-desc { font-size: var(--fs-caption); color: var(--c-text-2); overflow-wrap: anywhere; }
.rcv-card-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.today-line { font-size: var(--fs-caption); color: var(--c-text-quiet); }
/* На телефоне подпись стояла вплотную к краю экрана (проход 13.09): те же поля, что на компьютере. */
.rcv-today > .today-line { padding: 0 var(--sp-4) var(--sp-2); }
.recent { background: var(--c-surface); border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); }
.recent-row { display: flex; align-items: stretch; min-height: var(--h-tap); }
/* Строка — ссылка в карточку позиции с шевроном; «Отменить» — своя зона за чертой
   (проход 13.09): нажатие на строку и на кнопку палец не путает. */
.recent-open { display: flex; align-items: center; gap: var(--sp-3); flex: 1; min-width: 0; padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-4); color: inherit; transition: background-color var(--t-hover) ease; }
.recent-open:active { background: var(--c-fill); transition-duration: var(--t-press); }
.recent-open.is-split { border-inline-end: 1px solid var(--c-line); }
/* Ссылка — вся строка, шеврону своя зона 44 не нужна: эти 24 px отданы описанию. */
.recent-open > .row-go { width: var(--icon-md); min-height: 0; margin: 0; }
.recent-row > .inline-form > .btn { align-self: center; margin-inline: var(--sp-3) var(--sp-4); }
.recent-row + .recent-row { border-top: 1px solid var(--c-line); }
/* Строка называет и посылку, и вещь: номер с хвостом трека сверху, описание под
   ними (правка 13.09 — по одному хвосту не понять, что приняли). */
.recent-main { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1; min-width: 0; }
.recent-head { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; white-space: nowrap; }
/* Описание — до двух строк: в одну строку рядом с «Отменить» на 360 от вещи
   оставалось «Чехол для планшета, …» (проход 13.09). */
.recent-desc { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: var(--fs-caption); color: var(--c-text-2); overflow-wrap: anywhere; }
.recent-tail { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--c-text-quiet); }
/* Время — в строке номера, справа: описанию под ним остаётся вся ширина (проход 13.09). */
.recent-time { flex: none; margin-inline-start: auto; font-size: var(--fs-caption); color: var(--c-text-quiet); }
/* Отменить нельзя — объясняем словами, а не чипом чужого этапа. */
.recent-note { flex: none; max-width: 45%; font-size: var(--fs-label); color: var(--c-text-quiet); text-align: right; }
.inline-form { display: contents; }
.answer-body > .inline-form > .btn { align-self: flex-start; margin-top: var(--sp-2); }
.is-moving { transition: transform var(--t-move) ease-out; }

/* Панель снимка склада: idle → preparing → uploading → failed | done. */
.upl { display: flex; flex-direction: column; gap: var(--sp-3); }
.upl > form { display: contents; }
.upl-row { display: flex; align-items: center; gap: var(--sp-3); }
.upl-thumb { position: relative; }
.upl-preview { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: calc(var(--r-control) - 1px); }
.upl-badge { position: absolute; top: calc(-1 * var(--sp-2)); right: calc(-1 * var(--sp-2)); display: none; align-items: center; justify-content: center; width: var(--icon-lg); height: var(--icon-lg); border-radius: var(--r-round); background: var(--err-text); color: var(--c-on-accent); }
.upl-badge .icon { stroke-width: var(--mark-stroke); }
.upl-label { flex: 1; min-width: 0; font-size: var(--fs-caption); color: var(--c-text-quiet); }
/* Кнопка «Ещё снимок» — зона 44 с одной иконкой (SPEC, «Кнопка камеры»): со словом
   ряд не вставал на 390 и наезжал на подпись (правка 12.09). */
.upl-retake { flex: none; width: var(--h-tap); min-height: var(--h-tap); padding: 0; }
.upl-retake span:not(.icon) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.upl-delete { flex: none; }
.upl-error { display: none; flex: 1; min-width: 0; font-size: var(--fs-answer); color: var(--err-text); }
.upl-progress { position: relative; overflow: hidden; display: none; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--h-button); padding: var(--sp-2) var(--sp-4); background: var(--c-page); border: 1px solid var(--c-line-quiet); border-radius: var(--r-control); color: var(--c-text-2); }
.upl-bar { position: absolute; left: 0; bottom: 0; width: 100%; height: var(--sp-1); background: var(--c-accent); transform: scaleX(0); transform-origin: left; transition: transform var(--t-scale) ease-out; }
.upl-main { display: flex; flex-direction: column; gap: var(--sp-2); }
/* «Сфотографировать» и «Галерея» одним рядом, как пара в липкой панели (п. 29). */
.upl-take { display: flex; align-items: center; gap: var(--sp-2); }
.upl-take > .btn-primary { flex: 1 1 auto; min-width: 0; }
.upl-take > .btn-secondary { flex: 0 0 auto; }
/* На телефоне «Галерея» — квадрат со значком, как «Ещё снимок» в строке снимка: со
   словом «Сфотографировать» обрезался уже на 390 (замер 13.09). Слово читает голос. */
@media (max-width: 479px) {
  .upl-take > .btn-secondary { width: var(--h-button); padding: 0; }
  .upl-take > .btn-secondary > span:not(.icon) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
/* Что сделать первым — строкой над камерой, только пока снимка нет (показ 14.09). */
.upl-hint { display: none; margin: 0; font-size: var(--fs-caption); color: var(--c-text-2); }
.upl-retry, .upl-accept, .upl-retake, .upl-delete { display: none; }
.upl[data-state="idle"] .upl-row { display: none; }
.upl[data-state="idle"] .upl-hint { display: block; }
.upl-preparing { display: none; }
.upl[data-state="uploading"] .upl-progress, .upl[data-state="preparing"] .upl-progress { display: flex; }
.upl[data-state="uploading"] .upl-main, .upl[data-state="preparing"] .upl-main { display: none; }
.upl[data-state="preparing"] .upl-sending, .upl[data-state="preparing"] .upl-pct { display: none; }
.upl[data-state="preparing"] .upl-preparing { display: inline; }
.upl[data-state="failed"] .upl-badge, .upl[data-state="failed"] .upl-error { display: flex; }
.upl[data-state="failed"] .upl-label, .upl[data-state="failed"] .upl-take { display: none; }
.upl[data-state="failed"] .upl-retry { display: flex; }
.upl[data-state="done"] .upl-take { display: none; }
.upl[data-state="done"] .upl-accept, .upl[data-state="done"] .upl-retake, .upl[data-state="done"] .upl-delete { display: inline-flex; }
.upl[data-state="done"] .upl-accept { display: flex; }

/* Вход (3a, 3b): сегмент языка над формой, форма карточкой. */
.page-auth { padding: var(--sp-8) var(--sp-4) var(--sp-4); gap: var(--sp-6); }
.page-auth > .segment { align-self: flex-start; }
.auth-card { display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-4); }
.answer-compact { border-radius: var(--r-control); }

/* --- Списки экранов: заголовок, строки, «показать ещё» -------------------- */
.list-head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) var(--sp-4) var(--sp-2); }
.list-more { padding: var(--sp-4); display: flex; justify-content: center; }
.row-quiet { font-size: var(--fs-caption); color: var(--c-text-quiet); }
.row-chevron { color: var(--c-field); }
.parcel-head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.parcel-head-main { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
/* «Привязать» в строке посылки — видом кнопки: вся строка и есть это действие. */
.row-parcel-link { flex: none; pointer-events: none; }
.pick-bar { position: relative; display: block; padding: var(--sp-3) var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
/* Строка клиента при привязке: на телефоне номер, имя и телефон столбиком,
   «на складе» справа; на компьютере (ниже) — та же строка таблицей. */
@media (max-width: 1023px) {
  .row-link { display: grid; grid-template-columns: var(--h-tap) minmax(0, 1fr) auto; column-gap: var(--sp-3); align-items: center; }
  .row-link > .col-code, .row-link > .col-name, .row-link > .col-phone { grid-column: 2; }
  .row-link > .col-count { grid-column: 3; grid-row: 1 / -1; text-align: right; }
  .row-link > .check { grid-column: 1; grid-row: 1 / -1; }
  .rows-link .row-head { display: none; }
}
.pick-bar .input { padding-right: calc(var(--h-tap) + var(--sp-2)); }
.pick-search { position: absolute; right: var(--sp-4); bottom: calc(var(--sp-3) + (var(--h-field) - var(--h-tap)) / 2); }

/* Форма на белом листе (7f). */
.sheet { flex: 1; display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }

/* --- Коробка (4c–4f) ------------------------------------------------------ */
.box-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); padding: var(--sp-4) var(--sp-4) var(--sp-2); }
.box-client { font-size: var(--fs-caption); color: var(--c-text-2); }
.box-rail { margin: 0 var(--sp-4); padding: var(--sp-4) var(--sp-3); }
.box-scales { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); background: var(--c-surface); border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); margin-top: var(--sp-4); }
.fact-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-2); }
.fact-row > span:last-child { color: var(--c-text); }
.box-receipt { padding: var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.section-title { font-size: var(--fs-body); font-weight: var(--fw-semibold); }
/* «Выбрано: N» рядом с кнопкой, которая с этими строками работает. Считает скрипт;
   пока ничего не отмечено, надписи нет, а кнопка отвечает подсказкой, как прежде. */
.pick-count { font-size: var(--fs-caption); color: var(--c-text-quiet); white-space: nowrap; }
.pick-count:empty { display: none; }
/* Примечание о составе идёт своей строкой: рядом с заголовком оно ломало «В коробке»
   на две строки на 390 (правка 12.09). */
.box-items-head { flex-wrap: wrap; padding-bottom: var(--sp-2); }
.box-items-head .section-title { white-space: nowrap; }
.box-items-note { flex-basis: 100%; font-size: var(--fs-caption); color: var(--c-text-quiet); }
.row-numbers { display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-1); flex: none; }
.row-price { font-size: var(--fs-caption); color: var(--c-text-2); }
/* Состав коробки: на телефоне трек под описанием, цена под количеством (кадр 4c);
   на компьютере те же ячейки встают в колонки таблицы (кадр 4d). */
/* Трек идёт своей строкой во всю ширину: у настоящих номеров 15–16 знаков, и в
   колонке рядом с ценой они наезжали на неё (замер 13.09 на демо-данных). */
.row-box { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: "check thumbs desc qty" "check thumbs track track" "check thumbs price price"; column-gap: var(--sp-3); row-gap: var(--sp-1); }
.row-box > .check, .row-box > .check-slot { grid-area: check; align-self: center; }
.row-thumbs { grid-area: thumbs; display: flex; align-items: center; gap: var(--sp-2); align-self: center; }
/* Вторая миниатюра строки — только на компьютере: на телефоне в строке одна (SPEC). */
.thumb-wide { display: none; }
.row-box > .row-desc { grid-area: desc; align-self: end; }
.row-box > .track { grid-area: track; align-self: center; }
.row-box > .qty { grid-area: qty; justify-self: end; align-self: end; }
.row-box > .row-price { grid-area: price; justify-self: end; align-self: start; }
.rows-box .row-head { display: none; }
/* Телефон: правая колонка живёт в нижней панели, на листе её нет. */
.box-grid, .box-main, .box-aside { display: contents; }
.box-rail { order: 1; }
.box-scales { order: 2; }
.box-receipt { order: 3; }
.box-items { order: 4; }
.box-code, .box-aside-actions { display: none; }
/* Телефон: главное действие внизу панели, печать и шаг назад над ним (кадр 4e). */
.actionbar-inner > .act-print { order: 1; }
.actionbar-inner > .act-back { order: 2; }
.actionbar-inner > .act-main { order: 3; }
.hidden-form { display: none; }
.weigh { display: flex; flex-direction: column; gap: var(--sp-3); }
/* Телефон: вес и «Упаковать» — одним рядом (проход 13.09, панель в один ряд). Подпись
   поля остаётся для голосового доступа, глазами её заменяет подсказка «Вес, кг». */
.actionbar-weigh .weigh { flex-direction: row; align-items: flex-start; gap: var(--sp-2); }
.actionbar-weigh .weigh > .field { flex: 1 1 auto; min-width: 0; }
.actionbar-weigh .weigh .field-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.actionbar-weigh .weigh > .btn { flex: 0 0 auto; width: auto; }
/* «Вернуть на шаг назад» под линейкой, «Печать списка» у заголовка состава — только
   на телефоне: на компьютере оба в правой колонке, как в кадре 4d. */
.box-rail-back { order: 1; display: flex; justify-content: flex-end; padding: var(--sp-1) var(--sp-4) 0; }
.box-items-print { flex: none; }
/* Кнопка этапа — в форме: растягивается форма, а с ней и кнопка. */
.act-main > form { flex: 1; min-width: 0; }
.page-print { padding: 0; }
.box-actions { display: flex; flex-direction: column; gap: var(--sp-2); }

/* --- Кабинет клиента (7l, 7m) ---------------------------------------------- */
.my-code { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.my-code-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); }
/* Адрес для площадки свёрнут в строку с раскрытием (правка 12.09). */
.my-address { display: block; padding: var(--sp-4) 0 0; }
.my-address-head { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); padding: 0 var(--sp-4); cursor: pointer; list-style: none; }
.my-address-head::-webkit-details-marker { display: none; }
.my-address-chevron { margin-left: auto; color: var(--c-text-quiet); transition: transform var(--t-hover) ease; }
.my-address[open] .my-address-chevron { transform: rotate(90deg); }
.my-address .rows-address { margin-top: var(--sp-2); }
.row-address { justify-content: space-between; gap: var(--sp-3); min-height: var(--h-tap); }
/* На телефоне у строк адреса только значок копирования: место дороже слова (кадр 7l). */
.btn-icon-phone span:not(.icon) { display: none; }
.my-grid, .my-items, .my-aside { display: contents; }
.my-items-head { order: 2; }
.my-buttons { display: none; }
.my-items .tabs { order: 3; }
.rows-my-items, .my-items .list-more, .my-items .empty { order: 4; }
.my-aside .client-box { order: 1; }
.my-aside .client-sent { order: 5; }

/* --- Ошибка и «Нет связи» --------------------------------------------------- */
.page-error { justify-content: center; }
.error-sheet { flex: none; align-items: center; text-align: center; border-radius: var(--r-card); border: 1px solid var(--c-line); }
.error-code { font-size: var(--fs-label); color: var(--c-text-disabled); line-height: var(--lh-number); }
.error-sheet .page-title { font-size: var(--fs-title-phone); }
.offline-block { display: flex; flex-direction: column; gap: var(--sp-2); }

/* --- Журнал ---------------------------------------------------------------- */
.row-journal { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "who time" "what where"; column-gap: var(--sp-3); row-gap: var(--sp-1); }
.row-journal > .col-time { grid-area: time; justify-self: end; }
.row-journal > .col-who { grid-area: who; font-weight: var(--fw-semibold); }
.row-journal > .col-what { grid-area: what; color: var(--c-text-2); }
.row-journal > .col-where { grid-area: where; justify-self: end; }
.journal-key { font-family: var(--font-mono); overflow-wrap: anywhere; }

/* --- Настройки (7i) -------------------------------------------------------- */
.settings-form { display: flex; flex-direction: column; }
.settings-grid { display: flex; flex-direction: column; gap: var(--sp-4); }
.settings-card { flex: none; gap: var(--sp-4); }
.settings-note { font-size: var(--fs-caption); color: var(--c-text-quiet); }

/* --- Клиенты (7a, 7b) ------------------------------------------------------ */
/* Поиск: значок слева внутри поля, как в кадре; кнопка настоящая — без скриптов
   поиск идёт по ней и по клавише «Найти» на клавиатуре. */
.search-bar { display: block; padding: var(--sp-4) var(--sp-4) var(--sp-2); }
.search-box { position: relative; display: block; }
.search-input { padding-left: calc(var(--sp-4) + var(--icon-md) + var(--sp-3)); padding-right: var(--sp-2); }
/* Подсказка в поле поиска 14: в карточке клиента на 360 поле рядом с «Добавить позицию» узкое (82 px). */
.search-input::placeholder { font-size: var(--fs-caption); }
/* Пока поле пустое, место под крестик очистки не держится: «Трек, товар» на 360 обрезалось. */
.search-input:placeholder-shown::-webkit-search-cancel-button { display: none; }
.search-go { position: absolute; left: 0; top: 0; display: flex; align-items: center; justify-content: center; width: calc(var(--sp-4) + var(--icon-md) + var(--sp-2)); height: 100%; padding: 0; border: 0; background: none; color: var(--c-text-quiet); cursor: pointer; }
.clients-head { gap: var(--sp-4); padding-top: 0; }
.row-client { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "code count" "name box" "phone box"; column-gap: var(--sp-3); row-gap: var(--sp-1); align-items: center; }
.row-client > .col-code { grid-area: code; }
.row-client > .col-name { grid-area: name; }
.row-client > .col-phone { grid-area: phone; }
.row-client > .col-count { grid-area: count; justify-self: end; }
.row-client > .col-box { grid-area: box; display: flex; align-items: center; gap: var(--sp-2); justify-self: end; }
.row-name { color: var(--c-text); }
/* Главная ссылка строки накрывает её целиком: нажатие по всей строке остаётся,
   а отдельные ссылки внутри (номер коробки) лежат поверх неё. */
.row-open::after { content: ''; position: absolute; inset: 0; }
.row-client .col-box a { position: relative; z-index: 1; }
/* Номер текущей коробки — только на компьютере: на телефоне в строке и так три строки (кадр 7b). */
.row-box-number { display: none; font-size: var(--fs-caption); color: var(--c-text-2); white-space: nowrap; }
.rows-clients .row-head { display: none; }
.count-num { display: none; }
/* Уборка у владельца (14.09): галочка в строке клиента слева, поверх ссылки строки. */
.rows-pick .row-client { grid-template-columns: var(--h-tap) minmax(0, 1fr) auto; grid-template-areas: "check code count" "check name box" "check phone box"; padding-inline-start: var(--sp-2); }
.row-client > .check { grid-area: check; position: relative; z-index: 1; }
.row-head > .check-slot { grid-area: check; }
/* Тихая кнопка «Скрыть выбранные» и «Выбрано: N» — строкой над списком, справа. */
.list-tools { padding-top: 0; }
.client-items .list-tools { order: 4; }
.list-answer { margin-inline: var(--sp-4); }
.client-box-head > .check, .row-sent > .check { margin-inline-start: calc(-1 * var(--sp-3)); }
/* Телефон уже 480: галочка отнимает у строки 52 px — номер телефона клиента не рвётся
   посреди цифр, а «Привязать» у посылки уступает место шеврону. */
.rows-pick .row-client > .check { margin-inline-end: calc(-1 * var(--sp-2)); }
.row-client > .col-phone { white-space: nowrap; }
.parcel-link-narrow { display: none; }
/* «Скрыть выбранные» у заголовка коробок не рвёт ни заголовок, ни себя: не влезает —
   уходит вправо на следующую строку. */
.client-sent > .list-head { flex-wrap: wrap; row-gap: 0; }
.client-sent > .list-head > .section-title, .list-head > .btn-quiet { white-space: nowrap; }
.client-sent > .list-head > .btn-quiet { margin-inline-start: auto; }
@media (max-width: 479px) {
  .parcel-link-wide { display: none; }
  .parcel-link-narrow { display: flex; }
}

/* --- Свёрнутый блок: строка с раскрытием ---------------------------------- */
/* Раскрытие держит настоящая галочка, а не скрипт: без него блок всё равно
   открывается и закрывается. Ширина решает, нужна ли строка свёртки вообще:
   на компьютере блок стоит целиком (кадр 7c), на телефоне свёрнут (правка 13.09). */
.fold-head { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); cursor: pointer; }
/* Строка свёртки переносится, а не обрывается: «≈ €85 из 200» на 360 уходило в многоточие,
   и главное число коробки было не видно (проход 13.09). */
.fold-line { flex: 1; min-width: 0; padding-block: var(--sp-2); font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--c-text); overflow-wrap: anywhere; }
.fold-chevron { flex: none; color: var(--c-text-quiet); transition: transform var(--t-hover) ease; }
.fold-input:checked ~ .fold-head .fold-chevron { transform: rotate(90deg); }
.fold-body { display: none; }
.fold-input:checked ~ .fold-body { display: flex; }
.fold-input:focus-visible ~ .fold-head { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--r-control); }

/* --- Карточка клиента (7c, 7d) -------------------------------------------- */
.client-head { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.client-head-top { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); }
.client-name { font-size: var(--fs-title-phone); font-weight: var(--fw-semibold); flex-basis: 100%; }
.lang-ru .client-name { letter-spacing: var(--ls-cyrillic); }
.client-phone { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--h-tap); }
/* Без зазора между тихими кнопками: у каждой свои поля по 12, и так «Изменить / Сбросить
   пароль / Скрыть» встают в один ряд на 360 (проход 13.09: «Скрыть» уезжало вторым рядом). */
.client-actions { display: flex; flex-wrap: wrap; gap: 0; margin-inline: calc(-1 * var(--sp-3)); }
.client-actions form { display: contents; }
.client-facts { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-2); }
.client-grid, .client-items, .client-aside { display: contents; }
.client-box { order: 1; display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); background: var(--c-surface); border-bottom: 1px solid var(--c-line); }
.client-box-head { display: flex; align-items: center; gap: var(--sp-3); }
.client-box-weight { font-size: var(--fs-caption); color: var(--c-text-2); }
/* Телефон: поиск и «Добавить позицию» одним рядом (правка 13.09) — между шапкой
   клиента и первой позицией остаётся один блок. Заголовок раздела в ряд не влезает
   и остаётся только для голосового доступа: что это за список, говорят вкладки.
   В липкой панели остаётся одно главное действие. */
.client-items-head { order: 2; flex-wrap: nowrap; gap: var(--sp-2); }
.client-items-head > .section-title { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.client-search { order: 0; flex: 1 1 auto; min-width: 0; padding: 0; }
.client-buttons { display: flex; flex: none; }
.client-buttons > .act-main { display: none; }
.client-buttons .btn-block { width: auto; white-space: nowrap; }
.client-buttons .btn { font-size: var(--fs-answer); padding: var(--sp-2) var(--sp-3); }
/* Главное действие и «Выбрано: N» в одном ряду: кнопка называет, к чему относится. */
.act-main { display: flex; align-items: center; gap: var(--sp-3); }
.act-main > .btn { flex: 1; }
/* Свёрнутая коробка: одна строка на белом, раскрытое — прежний блок целиком. */
.client-box.fold { gap: 0; padding-block: 0; }
.client-box .fold-head { padding: 0 var(--sp-4); }
.client-box .fold-body { flex-direction: column; gap: var(--sp-3); padding: 0 var(--sp-4) var(--sp-4); }
.body-client .actionbar-inner > .act-second { display: none; }
/* На телефоне панель карточки клиента несёт только «В коробку». Нет его (класть
   нечего) — нет и панели: пустая белая полоса внизу не нужна (правка 12.09). */
.body-client .actionbar:not(:has(.act-main)) { display: none; }
.client-items .tabs { order: 4; }
.rows-client-items, .client-items .list-more, .client-items .empty { order: 5; }
.client-sent { order: 6; display: flex; flex-direction: column; }
.row-sent { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); }
.row-link { margin-left: auto; font-size: var(--fs-caption); }
/* Китайская подпись ссылки не рвётся посреди слова: не хватает места — ссылка уходит на
   следующую строку ряда целиком (「装箱清单」 на 360–390). Не nowrap: он растягивал ряд, и
   кабинет на ru уезжал вбок на 39 px. */
.row-sent .row-link { word-break: keep-all; }
/* Позиции клиента на телефоне: описание во всю ширину рядом с количеством, трек, и
   ряд «чип — цена» (переносится, если не влезает). Цена раньше стояла в колонке
   количества, раздвигала её до своей ширины, и на 360 описанию оставалось 96 px:
   «Кофеварка / капельная, / 0,6 л» (проход 13.09). Ряд заходит под шеврон: тот стоит
   посередине строки, а ряд — у нижнего края. */
.rows-client-items .row-client-item, .rows-my-items .row-client-item {
  grid-template-areas: "check thumbs desc qty" "check thumbs track track" "check thumbs meta meta";
}
.row-client-item > .row-meta { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-1) var(--sp-2); min-width: 0; margin-inline-end: calc(-1 * var(--icon-md)); }

/* --- Карточка позиции (5a–5c) --------------------------------------------- */
/* Позиция — один объект, поэтому на телефоне тоже карточкой (SPEC «Разделы и плотность»). */
.item-card { display: flex; flex-direction: column; margin: var(--sp-4); background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); box-shadow: var(--shadow-card); overflow: hidden; }
.item-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); padding: var(--sp-4) var(--sp-4) var(--sp-2); }
/* Имя клиента ссылкой рядом с наклейкой номера — на обеих ширинах (правка 12.09). */
.item-head .box-client { font-size: var(--fs-body); }
.item-head .sticker ~ .chip { margin-left: auto; }  /* у склада чип к правому краю, у клиента — под названием */
.item-title { font-size: var(--fs-title-phone); font-weight: var(--fw-semibold); flex-basis: 100%; }
.lang-ru .item-title { letter-spacing: var(--ls-cyrillic); }
.item-photos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); padding: var(--sp-2) var(--sp-4) var(--sp-4); }
.item-photo { display: flex; flex-direction: column; gap: var(--sp-2); margin: 0; min-width: 0; }
.item-photo-caption { font-size: var(--fs-caption); color: var(--c-text-2); }
.item-photo-box { aspect-ratio: 4 / 3; border-radius: var(--r-control); overflow: hidden; background: var(--c-photo-bg); }
.item-photo-box img, .item-photo-box .ph-open { width: 100%; height: 100%; }
.item-photo-box img { object-fit: cover; }
.item-photo-del { display: flex; flex-direction: column; gap: var(--sp-2); }
/* «Добавить фото» — отдельной строкой под парой снимков, во всю её ширину. */
.item-photo-tools { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--sp-2); }
.item-photo-add { display: flex; flex-direction: column; gap: var(--sp-2); }
/* Камера и галерея — две кнопки поровну одним рядом (проход 13.09). */
.item-photo-pick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
.item-photo-pick > .btn { width: 100%; min-width: 0; }
/* «Добавить фото» в половине кнопки на узком телефоне шло в две строки (ревью 5, D40):
   тексту нужно 123 px, со значком и полями 12 оставалось 108. Половины остаются
   поровну, у русской пары до 419 px — без значка и с полями 8 (у китайской подписи короткие). */
@media (max-width: 419px) {
  :lang(ru) .item-photo-pick > .btn { padding-inline: var(--sp-2); }
  :lang(ru) .item-photo-pick > .btn > .icon { display: none; }
}
.item-desc { padding: var(--sp-3) var(--sp-4) 0; border-top: 1px solid var(--c-line); }
.item-numbers { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-4); padding: var(--sp-2) var(--sp-4) var(--sp-4); }
.item-price { font-weight: var(--fw-semibold); }
/* Линейка на всю ширину листа: с полями 16 узел на 360 был 56 px, а «На складе» и
   «В коробке» — 63–64, и подписи налезали друг на друга (проход 13.09). */
.item-rail { padding: var(--sp-4) 0; border-top: 1px solid var(--c-line); }
.item-note { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-2); }
/* Строка о приёме и «Отменить приём» у неё; правка и сокрытие — строкой под ценой
   (проход 13.09: в нижней панели осталось одно главное действие). */
/* Отступ справа — у формы «Отменить приём», а не у строки: без кнопки (у клиента) строке
   о приёме нужна вся ширина, иначе «员。» уходит на вторую строку (ревью 5, D40). */
.item-note-row { display: flex; align-items: center; gap: var(--sp-2); }
.item-note-row > .item-note { flex: 1; min-width: 0; }
.item-note-row > form { flex: none; margin-inline-end: var(--sp-2); }
.item-tools { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: calc(-1 * var(--sp-3)); padding: 0 var(--sp-2) var(--sp-2); }
.item-box-line { display: block; padding: 0 var(--sp-4) var(--sp-4); }
.item-actions { display: none; }
.upload-status { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-caption); color: var(--c-text-2); }
.upload-status.is-failed { color: var(--err-text); }
.upload-text { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; flex: 1; }
.upload-preview { width: var(--thumb-row); height: var(--thumb-row); object-fit: cover; border-radius: var(--r-control); }
.upload-progress { width: 100%; height: var(--h-scale); }
.field-pair { display: flex; gap: var(--sp-3); }
.field-pair > .field { flex: 1; min-width: 0; }
.sheet-text { color: var(--c-text-2); }
/* Логин и пароль (кадр 7k): поле только для чтения и кнопка «Скопировать». */
.cred-head { display: flex; align-items: center; gap: var(--sp-3); padding-bottom: var(--sp-2); border-bottom: 1px solid var(--c-line); }
.cred-row { display: flex; align-items: flex-end; gap: var(--sp-3); }
.cred-field { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.cred-value { display: flex; align-items: center; background: var(--c-page); }
.sheet-quiet { font-size: var(--fs-caption); color: var(--c-text-quiet); }
.list-note { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-quiet); }

/* На телефоне «Сегодня принято» уходит, пока в поле что-то набрано: в руках
   посылка, и нужна одна карточка. Браузер без :has() покажет блок ниже карточки —
   это не мешает. */
@media (max-width: 1023px) {
  .rcv-grid:has(#rcv-results > *:not(.rcv-done)) > .rcv-today { display: none; }
}

/* --- Панель разработки --------------------------------------------------- */
/* Счётчик запросов стоит в ряду шапки, справа: он ничего не накрывает и не
   отнимает зону нажатия (правка 13.09 — внизу слева он лежал на кнопке склада,
   на нижней панели и на пустом состоянии карточки клиента). */
.dev-panel { flex: none; font-size: var(--fs-label); line-height: var(--lh-button); color: var(--c-text-quiet); background: var(--c-fill); border-radius: var(--r-control); padding: var(--sp-1) var(--sp-2); white-space: nowrap; pointer-events: none; }

/* --- Компьютер ----------------------------------------------------------- */
@media (min-width: 1024px) {
  .topbar-row { height: var(--h-header-desktop); gap: var(--sp-8); padding: 0 var(--sp-8); }
  .topbar-title, .topbar-back { display: none; }
  .topbar-brand { display: inline-flex; align-items: center; min-height: var(--h-tap); font-size: var(--fs-caption); color: var(--c-text-quiet); white-space: nowrap; }
  .topbar-nav { display: flex; align-items: stretch; gap: var(--sp-6); height: var(--h-header-desktop); }
  .topbar-nav a { display: flex; align-items: center; color: var(--c-text-2); border-bottom: 2px solid transparent; white-space: nowrap; }
  .topbar-nav a[aria-current="page"] { color: var(--c-text); font-weight: var(--fw-semibold); border-bottom-color: var(--c-accent); }
  .topbar .topbar-lang { display: inline-flex; }
  .topbar-lang .segment-option, .segment.is-compact .segment-option { min-height: 0; padding: var(--sp-2) var(--sp-3); font-size: var(--fs-caption); }
  .menu-button { gap: var(--sp-2); font-size: var(--fs-caption); }
  .avatar { width: var(--avatar-desktop); height: var(--avatar-desktop); font-size: var(--fs-caption); }
  .menu-name { display: inline; }
  .menu-icon { display: block; }
  .menu-panel .menu-lang, .menu-panel .menu-user-name { display: none; }  /* имя уже в кнопке шапки */
  .menu-panel .menu-user-role { font-weight: var(--fw-semibold); color: var(--c-text-2); }
  .page { padding: var(--sp-6) var(--sp-8); }
  .page-flush { padding: 0; }
  /* Списки разделов на компьютере — блоком в колонке, как в кадрах 7a и 7c. */
  .page-wide { padding: var(--sp-6) var(--sp-8); gap: var(--sp-4); max-width: var(--content-wide); margin-inline: auto; }
  .page-wide .list-head { padding: 0; }
  .page-wide .rows { border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .page-wide .empty { background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); }
  .page-auth { width: 100%; max-width: var(--content-auth); margin-inline: auto; justify-content: center; padding-block: var(--sp-8); }
  .body-auth .page { flex: 1 0 auto; }
  /* Возврат: один ряд на всё приложение. Ряд повторяет колонку содержимого
     (--back-col, --back-pad), ссылка стоит по её левому краю в зоне 44 и ведёт
     себя как действие, а не как текст (правка 12.09). */
  .page-back-row { display: flex; width: 100%; max-width: var(--back-col, none); margin-inline: auto; padding-inline: var(--back-pad, 0); }
  .objbar { top: calc(var(--safe-top) + var(--h-header-desktop) + 1px); }
  .objbar-inner { gap: var(--sp-4); padding-inline: var(--sp-8); width: 100%; max-width: var(--content-wide); margin-inline: auto; }
  .objbar .page-back-text { display: inline; }
  .objbar .page-back { min-width: 0; justify-content: flex-start; padding-inline: var(--sp-2); margin-inline-start: calc(-1 * var(--sp-2)); }
  .objbar-name { font-size: var(--fs-body); }
  .page-title { font-size: var(--fs-title-desktop); }
  .bottom-nav { display: none; }
  .has-bottom-nav .actionbar { bottom: 0; padding-bottom: calc(var(--sp-3) + var(--safe-bottom)); }
  .input { height: var(--h-field-desktop); }
  .btn-primary { min-height: var(--h-button-desktop); }
  .chip .icon { width: var(--icon-xs); height: var(--icon-xs); }
  /* Приём и формы склада на компьютере — колонкой по центру. */
  .page-flush { --back-col: var(--content-narrow); }
  .page-flush > .page-back-row { margin-top: var(--sp-6); }
  .page-flush > .page-back-row + .sheet { margin-top: var(--sp-3); }
  .page-flush > .sheet { width: 100%; max-width: var(--content-narrow); margin: var(--sp-6) auto; border: 1px solid var(--c-line); border-radius: var(--r-card); flex: none; }
  /* Приём на компьютере: слева карточка посылки, справа «Сегодня принято». */
  .page-rcv { --back-col: var(--content-receiving); --back-pad: var(--sp-8); padding: var(--sp-6) var(--sp-8) var(--sp-8); }
  .rcv-grid { display: grid; grid-template-columns: minmax(0, var(--content-narrow)) var(--col-aside); justify-content: center; align-items: start; gap: var(--sp-6); width: 100%; }
  .rcv-main { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
  .rcv-today { display: block; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .rcv-today .today-line { padding: var(--sp-4) var(--sp-4) var(--sp-2); }
  .rcv-today .recent { border: 0; }
  .rcv-today .empty { background: none; }
  .rcv-done:empty { display: none; }
  .page-rcv .track-bar { border: 1px solid var(--c-line); border-radius: var(--r-card); padding: var(--sp-3) var(--sp-4) var(--sp-4); background: var(--c-surface); }
  /* Панель приёма стоит ровно под левой колонкой: кнопка там же, где карточка. */
  .body-rcv .actionbar-inner { max-width: var(--content-receiving); }
  .body-rcv .actionbar-inner > * { width: 100%; max-width: var(--content-narrow); margin-inline-end: auto; }
  .rcv-results > :not(.rows):not(.recent) { margin-inline: 0; }
  .rcv-results > .rcv-card:first-child { margin-top: 0; }
  .rcv-results .rows, .rcv-results .recent { border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  /* Плоский список на компьютере: строка в одну линию, как в таблице. */
  .rows-flat .row { min-height: var(--h-row-desktop); }
  .rows-flat .row-main { flex-direction: row; align-items: baseline; gap: var(--sp-6); }
  .rows-flat .thumb { width: var(--thumb-row-desktop); height: var(--thumb-row-desktop); }
  .rows-flat .row-quiet { flex: none; }
  .rows-flat .code-row { min-width: var(--col-code); }
  .rcv-card-photo { aspect-ratio: auto; height: var(--photo-card-desktop); }
  /* Кабинет на компьютере (кадр 7m): позиции слева, коробки справа. */
  .page-my { padding: var(--sp-6) var(--sp-8); gap: var(--sp-4); max-width: var(--content-wide); margin-inline: auto; }
  .page-my, .page-client, .page-settings, .page-journal { --back-col: none; --back-pad: 0; }
  .my-code, .my-address { border: 1px solid var(--c-line); border-radius: var(--r-card); padding: var(--sp-6); }
  .my-code { flex-direction: row; align-items: center; gap: var(--sp-6); flex-wrap: wrap; }
  .my-address { padding: var(--sp-4) 0; }
  .my-address-head { padding: 0 var(--sp-6); }
  .my-address .rows-address { margin-top: var(--sp-3); }
  .my-grid { display: grid; grid-template-columns: minmax(0, 1fr) var(--col-aside); align-items: start; gap: var(--sp-4); }
  .my-items { display: flex; flex-direction: column; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .my-items-head { order: 0; padding: var(--sp-4); }
  .my-items .tabs { order: 0; padding: 0 var(--sp-4); }
  .my-items .rows { order: 0; border: 0; }
  .my-buttons { display: block; }
  .my-buttons .btn-block { width: auto; white-space: nowrap; }
  .btn-icon-phone span:not(.icon) { display: inline; }
  .my-aside { display: flex; flex-direction: column; gap: var(--sp-4); }
  .my-aside .client-box, .my-aside .client-sent { order: 0; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); }
  .body-my .actionbar { display: none; }
  /* Журнал на компьютере — строка в одну линию. */
  .rows-journal .row-journal { grid-template-columns: var(--col-time) var(--col-who) minmax(0, 1fr) auto; grid-template-areas: "time who what where"; align-items: center; min-height: var(--h-row-desktop); }
  .rows-journal .row-journal > .col-time { justify-self: start; }
  /* Настройки на компьютере: два листа рядом (кадр 7i). */
  .page-settings { padding: var(--sp-6) var(--sp-8); max-width: var(--content-wide); margin-inline: auto; }
  .page-settings .list-head { padding: 0 0 var(--sp-4); }
  .settings-grid { display: grid; grid-template-columns: 1fr 1fr; align-items: start; gap: var(--sp-4); }
  .settings-card { border: 1px solid var(--c-line); border-radius: var(--r-card); }
  /* Настройки идут во всю колонку 1376, а не в 720 одиночной формы. */
  .body-form .actionbar-inner.settings-bar { max-width: var(--content-wide); align-items: center; padding-inline: var(--sp-8); margin-inline: auto; }
  /* Формы на компьютере: лист слева под возвратом, кнопки строкой под ним (кадры 7j, 7k). */
  .page-form { --back-col: var(--content-form); padding: 0 var(--sp-8); }
  .page-form > .sheet { max-width: var(--content-form); margin-inline: auto; }
  .body-form .page { flex: 0 0 auto; }  /* лист не растягивается: кнопки идут сразу под ним */
  .body-form .actionbar { position: static; padding: 0 var(--sp-8) var(--sp-8); background: none; border-top: 0; box-shadow: none; }
  .body-form .actionbar-inner { flex-direction: row; align-items: center; gap: var(--sp-4); max-width: var(--content-form); margin-inline: auto; }
  .body-form .actionbar-inner .btn-block { width: auto; }
  /* «Кому эта посылка» на компьютере: колонка того же вида, что списки, кнопка
     под ней, а не липкой панелью во всю ширину (правка 12.09). */
  .page-link { --back-col: var(--content-form); --back-pad: 0; padding: 0 var(--sp-8) var(--sp-8); }
  .link-col { width: 100%; max-width: var(--content-form); margin-inline: auto; display: flex; flex-direction: column; gap: var(--sp-4); }
  .link-col > .parcel-head, .link-col > .pick-bar { border: 1px solid var(--c-line); border-radius: var(--r-card); }
  .link-col > .live-results > .rows { border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .body-link .actionbar { position: static; padding: var(--sp-4) var(--sp-8) var(--sp-8); background: none; border-top: 0; box-shadow: none; }
  .body-link .actionbar-inner { max-width: var(--content-form); margin-inline: auto; align-items: flex-start; }
  .body-link .actionbar-inner .btn-block { width: auto; }
  .rows-link .row-head { display: grid; padding: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-quiet); border-bottom: 1px solid var(--c-line); }
  .rows-link .row-head, .rows-link .row-link { display: grid; grid-template-columns: var(--h-tap) var(--col-code-link) minmax(0, 1fr) var(--col-phone-link) var(--col-count-link); align-items: center; column-gap: var(--sp-3); }
  .rows-link .row-link { min-height: var(--h-row-desktop); }
  .rows-link .row-head > *, .rows-link .row-link > * { grid-column: auto; grid-row: auto; }
  .rows-link .row-head .col-count, .rows-link .row-link > .col-count { justify-self: end; }
  /* Клиенты на компьютере — таблица (кадр 7a). */
  /* Поиск, «Скрытые» и «Новый клиент» — одной строкой над таблицей (кадр 7a). */
  .page-clients { display: grid; grid-template-columns: minmax(0, var(--search-wide)) 1fr; align-items: center; align-content: start; }
  .page-clients > .search-bar { grid-column: 1; padding: 0; }
  .page-clients > .live-results > .clients-head { grid-column: 2; padding: 0; }
  .page-clients > .live-results > .rows, .page-clients > .live-results > .list-more, .page-clients > .live-results > .empty { grid-column: 1 / -1; }
  .page-clients > .live-results > .list-tools, .page-clients > .live-results > .list-answer { grid-column: 1 / -1; }
  .list-answer { margin-inline: 0; }
  .rows-clients.rows-pick .row-head, .rows-clients.rows-pick .row-client { grid-template-columns: var(--h-tap) var(--col-code) minmax(0, 1fr) var(--col-phone) var(--col-count) var(--col-box); grid-template-areas: "check code name phone count box"; }
  .rows-clients.rows-pick .row-head, .rows-clients.rows-pick .row-client { padding-inline-start: var(--sp-2); }
  .client-items .list-tools { order: 0; padding: 0 var(--sp-4); }
  .count-full { display: none; }
  .count-num { display: inline; }
  .rows-clients .row-head { display: grid; padding: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-quiet); border-bottom: 1px solid var(--c-line); }
  .rows-clients .row-head, .rows-clients .row-client { grid-template-columns: var(--col-code) minmax(0, 1fr) var(--col-phone) var(--col-count) var(--col-box); grid-template-areas: "code name phone count box"; align-items: center; column-gap: var(--sp-4); }
  .rows-clients .row-head { padding-inline-end: calc(var(--sp-4) + var(--icon-md)); }
  .rows-clients .row-client { min-height: var(--h-row-desktop); }
  .rows-clients .row-head .col-count, .rows-clients .row-client > .col-count { justify-self: end; }
  .rows-clients .row-client > .col-box { justify-self: start; }
  /* В таблице номер клиента в рамке 1 px (SPEC «Наклейка номера»). */
  .rows-clients .row-client > .col-code { justify-self: start; padding: var(--sp-1) var(--sp-2); border: 1px solid var(--c-text); border-radius: var(--r-control); font-size: var(--fs-caption); letter-spacing: var(--ls-sticker); }
  .row-box-number { display: inline; }
  /* Наведение и нажатие на сам номер коробки: ссылка отличается от строки. */
  .row-client .row-box-number:active { color: var(--c-accent-active); }
  /* Карточка клиента на компьютере (кадр 7c): позиции слева, коробки справа. */
  .page-client { padding: var(--sp-6) var(--sp-8); gap: var(--sp-4); max-width: var(--content-wide); margin-inline: auto; }

  .client-head { border: 1px solid var(--c-line); border-radius: var(--r-card); padding: var(--sp-6); gap: var(--sp-4); }
  .client-head-top { gap: var(--sp-4); }
  .client-actions { gap: var(--sp-2); }  /* на компьютере место есть: зазор как в кадре 7c */
  .client-name { flex-basis: auto; font-size: var(--fs-title-desktop); }
  .client-grid { display: grid; grid-template-columns: minmax(0, 1fr) var(--col-aside); align-items: start; gap: var(--sp-4); }
  .client-items { display: flex; flex-direction: column; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .client-items-head { order: 0; display: flex; align-items: center; flex-wrap: nowrap; gap: var(--sp-4); padding: var(--sp-4); }
  .client-items-head > .section-title { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; }
  .client-search { order: 0; flex: 0 1 var(--search-wide); padding: 0; }
  .client-buttons { display: flex; gap: var(--sp-3); margin-left: auto; }
  .client-buttons .btn { font-size: var(--fs-body); padding: var(--sp-2) var(--sp-4); }
  /* На компьютере коробка в правой колонке стоит целиком: строка свёртки не нужна. */
  .client-box.fold > .fold-head { display: none; }
  .client-box.fold > .fold-body { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); }
  .client-buttons > .act-main { display: block; }
  .body-client .actionbar-inner > .act-second { display: block; }
  .client-buttons .btn-block { width: auto; white-space: nowrap; }
  .tabs { column-gap: var(--sp-6); }
  .client-items .tabs { order: 0; padding: 0 var(--sp-4); }
  .client-items .rows { order: 0; border: 0; }
  .client-aside { display: flex; flex-direction: column; gap: var(--sp-4); }
  .client-box, .client-sent { order: 0; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); border-bottom: 1px solid var(--c-line); }
  .client-sent .rows { border: 0; }
  .body-client .actionbar { display: none; }
  .rows.rows-client-items .row-head, .rows.rows-client-items .row-client-item,
  .rows.rows-my-items .row-client-item { grid-template-columns: var(--h-tap) auto minmax(0, 1fr) var(--col-qty) var(--col-price) var(--col-track) var(--col-stage); grid-template-areas: "check thumbs desc qty price track stage"; }
  .rows.rows-client-items .row-head .col-stage { grid-area: stage; }
  .row-client-item > .row-meta { display: contents; }
  .row-client-item > .row-meta > .col-stage { grid-area: stage; justify-self: start; }
  .row-client-item > .row-meta > .row-price { grid-area: price; justify-self: end; align-self: center; }
  /* Позиция на компьютере (кадр 5a): снимки слева, сведения и действия справа. */
  .page-print { --back-col: 210mm; --back-pad: var(--sp-4); }
  .page-print > .page-back-row { margin-top: var(--sp-6); }
  .page-item { --back-col: var(--content-wide); --back-pad: var(--sp-8); }
  .page-item > .page-back-row { margin-top: var(--sp-6); }
  .item-head .box-client { font-size: var(--fs-caption); }
  .item-head .sticker ~ .chip { margin-left: 0; }
  .item-card { width: 100%; max-width: var(--content-wide); margin: var(--sp-3) auto var(--sp-8); padding: var(--sp-6); box-shadow: none;
    display: grid; grid-template-columns: var(--col-photos) minmax(0, 1fr); grid-template-areas: "photos head" "photos desc" "photos numbers" "photos tools" "photos rail" "photos note" "photos actions"; column-gap: var(--sp-6); align-content: start; }
  .item-photos { grid-area: photos; padding: 0; border: 0; background: none; align-self: start; }
  .item-head { grid-area: head; padding: 0 0 var(--sp-3); }
  .item-desc { grid-area: desc; padding: 0; background: none; font-size: var(--fs-title-desktop); font-weight: var(--fw-semibold); }
  .item-numbers { grid-area: numbers; padding: var(--sp-2) 0 var(--sp-4); background: none; border: 0; }
  .item-rail { grid-area: rail; padding: var(--sp-4) 0; background: none; border-top: 1px solid var(--c-line); border-bottom: 1px solid var(--c-line); }
  .item-note-row { grid-area: note; }
  .item-note-row > form { margin-inline-end: 0; }
  .item-note { padding: var(--sp-3) 0; }
  .item-tools { grid-area: tools; justify-content: flex-start; margin: calc(-1 * var(--sp-3)) 0 var(--sp-2) calc(-1 * var(--sp-3)); padding: 0; }
  .item-actions { grid-area: actions; display: flex; align-items: center; gap: var(--sp-3); }
  .item-actions .act-main { flex: none; }
  .item-actions .btn-block { width: auto; }
  .body-item .actionbar { display: none; }
  /* Коробка на компьютере (кадр 4d): состав слева таблицей, расчёт и действия справа. */
  .page-box { --back-col: var(--content-wide); --back-pad: var(--sp-8); }
  .page-box > .banner, .page-box > .box-head, .page-box > .answer { width: 100%; max-width: var(--content-wide); margin-inline: auto; padding-inline: var(--sp-8); }
  .page-box > .page-back-row { margin-top: var(--sp-6); }
  /* Возврат ушёл в полосу объекта, а с ним и его отступ сверху: воздух под полосой держит сам лист. */
  .has-objbar .page-box { padding-top: var(--sp-4); }
  .has-objbar .page-item { padding-top: var(--sp-3); }
  .page-box .box-head { padding-block: var(--sp-2) var(--sp-4); }
  .page-box .box-head .chip { order: 1; }  /* на компьютере чип этапа после имени клиента (кадр 4d) */
  .box-code { display: inline-flex; align-items: center; height: var(--h-tap); padding: 0 var(--sp-3); border: 1px solid var(--c-line); border-radius: var(--r-control); }
  .box-grid { display: grid; grid-template-columns: minmax(0, 1fr) var(--col-aside); align-items: start; gap: var(--sp-6); width: 100%; max-width: var(--content-wide); margin-inline: auto; padding: 0 var(--sp-8) var(--sp-8); }
  .box-main { display: flex; flex-direction: column; gap: var(--sp-6); }
  .box-aside { display: flex; flex-direction: column; background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .box-rail, .box-scales, .box-receipt, .box-items { order: 0; }
  .box-rail { margin: 0; }
  .box-scales { margin: 0; padding: var(--sp-4); border-top: 0; border-bottom: 0; }
  .box-receipt { border-bottom: 0; padding-top: 0; }
  .box-aside-actions { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); }
  .box-rail-back, .box-items-print { display: none; }
  /* Компьютер: главное действие первым в правой колонке (кадр 4d). */
  .box-aside-actions > .act-main { order: 1; }
  .box-aside-actions > .act-print { order: 2; }
  .box-aside-actions > .act-back { order: 3; }
  .box-items { background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--r-card); overflow: hidden; }
  .box-items .list-head { padding: var(--sp-4); }
  .box-items .rows { border: 0; }
  .body-box .actionbar { display: none; }
  .rows-box .row-head { display: grid; padding: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); color: var(--c-text-quiet); border-bottom: 1px solid var(--c-line); }
  .rows-box .row-head, .rows-box .row-box { grid-template-columns: var(--h-tap) auto minmax(0, 1fr) var(--col-qty) var(--col-price) var(--col-track); grid-template-areas: "check thumbs desc qty price track"; align-items: center; column-gap: var(--sp-3); }
  .rows-box .row-box { min-height: var(--h-row-desktop); }
  .rows-box .row-head .col-photo { grid-area: thumbs; }
  .rows-box .row-head .col-desc { grid-area: desc; }
  .rows-box .row-head .col-qty { grid-area: qty; justify-self: end; }
  .rows-box .row-head .col-price { grid-area: price; justify-self: end; }
  .rows-box .row-head .col-track { grid-area: track; }
  .rows-box .thumb { width: var(--thumb-row-desktop); height: var(--thumb-row-desktop); }
  .thumb-wide { display: block; }
  .rows-box .row-box > .row-desc, .rows-box .row-box > .track, .rows-box .row-box > .qty, .rows-box .row-box > .row-price { align-self: center; }
  /* Описание в одну строку: строка списка на компьютере — сетка высотой 52 (SPEC),
     длинное описание обрывается многоточием, целиком оно в карточке и в печати. */
  /* Описание — до двух строк: в одну строку «Кроссовки зимние мужские, …» обрывалось
     уже на 1440 (проход 13.09); полное — в карточке позиции и на листе. */
  .rows-box .row-box > .row-desc { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: var(--c-text); }
  .actionbar-inner { width: 100%; max-width: var(--content-narrow); margin-inline: auto; }
  .track-box { height: var(--h-field); }
}

/* --- Переходы страниц: view transitions, 150 мс, только прозрачность ------ */
/* Только со скриптами: без них Chromium (1234, headless и полный) не снимает слой
   перехода после второго перехода по ссылке, и страница перестаёт принимать
   нажатия (замер 12.09). Без скриптов — без перехода, как у браузеров без поддержки. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
::view-transition-group(root), ::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--t-page); }
::view-transition-group(topbar), ::view-transition-group(bottom-nav), ::view-transition-group(objbar),
::view-transition-old(topbar), ::view-transition-new(topbar),
::view-transition-old(objbar), ::view-transition-new(objbar),
::view-transition-old(bottom-nav), ::view-transition-new(bottom-nav) { animation: none; }
::view-transition-old(topbar), ::view-transition-old(bottom-nav), ::view-transition-old(objbar) { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .check-draw path { stroke-dashoffset: 0; }
  .loading-bar.is-loading { transform: scaleX(.92); }
}
