/* ШРИФТЫ ЛЕЖАТ РЯДОМ С САЙТОМ, А НЕ У GOOGLE. Раньше здесь стоял @import с
   fonts.googleapis.com: чужой сервер, лишнее ожидание перед первой отрисовкой,
   и если он недоступен — надписи молча меняют облик. Файлы в этой же папке,
   поэтому путь короткий и работает в обеих копиях assets.

   ПОЧЕМУ ONEST, А НЕ ARCHIVO. У Archivo нет кириллицы — проверено замером
   25 августа 2026. Русские буквы он не рисовал вовсе, их давала операционная
   система, поэтому сайт выглядел по-разному на маке, Windows и телефоне. Хуже
   того, цифры и пробелы Archivo всё-таки отдавал, и строка «45 дней» была
   набрана двумя шрифтами сразу. Onest — русский гротеск того же характера,
   с кириллицей.

   ПЕРЕМЕННЫЙ, ОДИН ФАЙЛ НА ВСЕ ВЕСА. В стилях есть 550, 650 и 750 — таких
   начертаний не бывает у обычных шрифтов, их даёт только переменный. Отсюда
   font-weight: 100 900 в каждом правиле: это не опечатка, а диапазон. */

@font-face {
    font-family: 'Onest';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url(onest-latin.woff2) format('woff2');
    /* Латиница — но здесь же живут ВСЕ цифры, пробел и знаки препинания,
       поэтому без этого файла не обойтись даже на чисто русской странице */
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Onest';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url(onest-cyrillic.woff2) format('woff2');
    /* Русские буквы и знак № */
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
    font-family: 'Onest';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url(onest-latin-ext.woff2) format('woff2');
    /* Ради знака рубля: ₽ это U+20BD, он попадает сюда, а не в латиницу.
       Без этого файла цена набиралась бы системным шрифтом */
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ARCHIVO ОСТАВЛЕН ТОЛЬКО ДЛЯ ЛОГОТИПА. Он латиница, там шрифт работает как
   задумано дизайнером, и облик знака менять незачем.

   ВНИМАНИЕ: файл обрезан до букв слова EXPRESSMARKET и весит 1.4 КБ вместо 35.
   Других букв в нём НЕТ. Если однажды поменяется само слово в логотипе —
   новые буквы нарисуются шрифтом Onest, и это будет сразу видно. За этим
   следит проверка app/tests/run-shrift.php, она уронится раньше. */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 900;
    font-display: swap;
    src: url(archivo-logo.woff2) format('woff2');
    unicode-range: U+41, U+45, U+4B, U+4D, U+50, U+52-54, U+58;
}
/*
 * Express Market — оформление нового сайта.
 *
 * Палитра опирается на действующий сайт: красный #ec3013 и жёлтый #ffd60a взяты
 * из main.css старой темы. Направление — европейская логистика: жёлтое поле,
 * красный акцент, графит для текста, много воздуха. Знаки, шрифт и фирменные
 * диагональные полосы DHL не используются: это чужой товарный знак, берётся
 * только цветовое решение.
 *
 * Цвета графика цен подобраны не на глаз, а прогоном через проверку на
 * различимость. Столбики графитовые: прежний золотой владельцу не нравился, и
 * проверка это подтвердила с неожиданной стороны — при дальтонизме он почти
 * сливался с зелёным «лучшая цена» (ΔE 7.9 при пороге 8). Графит против
 * зелёного даёт 22.7, то есть втрое надёжнее.
 *
 * Брендовый красный внутри графика применять нельзя — он сливался с золотым, а
 * теперь ещё и спорит с кнопкой. Выбранный день отмечается обводкой и
 * подписью, а не цветом.
 */

:root {
    /* Модернист: почти-моно красный на белом, видимая сетка, нулевые скругления */
    --yellow: #f3f2f2;
    --yellow-deep: #201e1d;
    --yellow-wash: #eae9e9;
    --red: #ec3013;
    --red-dark: #a82a12;

    --ink: #201e1d;
    --ink-soft: #43403f;
    --muted: #6b6866;
    --line: #201e1d;
    --surface: #f3f2f2;
    --surface-soft: #eae9e9;
    --surface-dark: #201e1d;

    --bar: #201e1d;
    --bar-hover: #201e1d;
    --best: #ec3013;
    --best-hover: #a82a12;
    --best-wash: #fbe9e5;

    --r-sm: 0px;
    --r-md: 0px;
    --r-lg: 0px;

    --sh-2: none;
    --sh-3: 0 8px 24px rgba(32, 30, 29, .18);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font: 16px/1.6 "Onest", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
    color: var(--ink);
    background: var(--surface);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { letter-spacing: -.022em; line-height: 1.1; margin: 0; font-weight: 800; }

.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* Кабинет занимает весь экран, а не колонку в 1200 точек.
   На витрине узкая колонка правильна: строка текста длиннее восьмидесяти
   знаков перестаёт читаться. В кабинете текста нет — там таблицы, графики и
   плитки, и каждая лишняя сотня точек это ещё один столбец на виду вместо
   прокрутки вбок. Потолок всё же есть: на мониторе в три тысячи точек ряд
   плиток растягивается в ниточку. */
.container--wide { max-width: 2000px; padding: 0 28px; }

/* ── шапка ───────────────────────────────────────────────────────────────── */

.header {
    background: var(--yellow);
    border-bottom: 4px solid var(--red);
    position: sticky; top: 0; z-index: 40;
}
.header__inner { display: flex; align-items: center; gap: 32px; height: 66px; }
.logo {
    /* Единственное место с Archivo во всём файле — см. правило выше */
    font-family: "Archivo", "Onest", sans-serif;
    font-weight: 900; font-size: 22px; letter-spacing: -.03em;
    color: var(--ink); text-decoration: none; white-space: nowrap;
}
.logo b { color: var(--red); }
/* Стили меню жили здесь в первом варианте и переехали ниже, к .nav__link.
   Старые правила были на `.nav a` — по тегу внутри класса, а такой селектор
   ВЕСИТ БОЛЬШЕ, чем `.nav__link`, и молча перебивал новые: отступ, кегль и
   границу. Полгода в файле стояли два поколения сразу, и правка нижнего
   иногда просто не действовала. Если снова заведётся `.nav a` — будет то же
   самое, поэтому селекторов по тегу здесь быть не должно. */

/* ── герой ───────────────────────────────────────────────────────────────── */

.hero {
    position: relative;
    background: var(--yellow);
    padding: 56px 0 48px;
    overflow: hidden;
    border-bottom: 2px solid var(--ink);
}
/* Геометрический маршрут: две точки и линия между ними. Намеренно не полосы —
   фирменные диагональные полосы принадлежат чужому бренду. */
.hero::after { display: none; }
.hero__inner { position: relative; z-index: 1; max-width: 720px; }
.hero__eyebrow {
    display: inline-block; background: var(--ink); color: var(--yellow);
    font-size: 12.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
    padding: 7px 13px; border-radius: 0; margin-bottom: 20px;
}
.hero h1 { font-size: clamp(34px, 5.2vw, 58px); margin-bottom: 18px; }
.hero p { font-size: clamp(17px, 2vw, 20px); color: var(--ink-soft); margin: 0; max-width: 34em; }

/* ── карточка подбора, наезжает на герой ─────────────────────────────────── */

.finder-wrap { margin-top: 0; position: relative; z-index: 5; }
.finder { background: var(--surface); border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink); box-shadow: none; padding: 28px 0; }
.finder__row { display: grid; grid-template-columns: 1fr 1.15fr 1.7fr .8fr .6fr auto; gap: 12px; align-items: end; }

.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field label { font-size: 12.5px; font-weight: 700; color: var(--muted); }
.field select, .field input {
    height: 52px; padding: 0 14px; font-size: 16px; font-weight: 550;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink); appearance: none; width: 100%;
}
.field select {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1l5 5 5-5' stroke='%23767d88' stroke-width='2' fill='none' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat; background-position: right 14px center; padding-right: 36px;
}
.field select:focus, .field input:focus {
    outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(255, 214, 10, .55);
}

.btn {
    height: 52px; padding: 0 28px; font-size: 16px; font-weight: 750;
    border: 0; border-radius: var(--r-sm); cursor: pointer; white-space: nowrap;
    background: var(--red); color: #fff; transition: background .15s ease, transform .06s ease;
}
.btn:hover { background: var(--red-dark); }
.btn:active { transform: translateY(1px); }

/* Ссылка, одетая кнопкой. Кнопка сама по себе центрирует подпись и не носит
   подчёркивания, а ссылка носит: без этого правила «Зарегистрироваться»
   выглядело подчёркнутым текстом, прижатым к левому краю рамки */
a.btn {
    display: inline-flex; align-items: center; justify-content: center;
    text-decoration: none;
}
.btn--dark { background: var(--ink); }
.btn--lg { height: 58px; font-size: 17px; padding: 0 34px; }

/* ── секции ──────────────────────────────────────────────────────────────── */

.section { padding: 52px 0; }
.section h2 { font-size: clamp(24px, 3vw, 33px); }
.section__sub { color: var(--muted); font-size: 15px; margin: 10px 0 26px; }

/* ── график цен ──────────────────────────────────────────────────────────── */

.chart-card {
    background: var(--surface); border: 2px solid var(--ink);
    border-radius: var(--r-lg); box-shadow: var(--sh-2); padding: 30px 10px 16px;
}

.chart-body { display: flex; align-items: stretch; padding: 0 14px; }
/* Правил оси здесь больше нет: шкала стала относительной, и подписи цен
   рядом с ней врали бы. Цена живёт в подсказке и в таблице выездов. */
.chart-scroll {
    flex: 1 1 auto; min-width: 0; overflow-x: auto; overflow-y: visible;
    padding-left: 8px; scrollbar-width: thin;
    /* ПЛАВНОСТИ ЗДЕСЬ НЕТ НАМЕРЕННО. С scroll-behavior: smooth присвоение
       scrollLeft из скрипта в части браузеров просто не срабатывает — стрелки
       нажимались, а лента стояла. Мгновенный сдвиг работает везде, а красота
       не стоит неработающей кнопки. */
}
.chart-scroll::-webkit-scrollbar { height: 8px; }
.chart-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 0; }

/* Половина прежней высоты. Двести пятьдесят пикселей столбики занимали зря:
   разницу в цене видно и на ста двадцати, а экран телефона они съедали
   целиком, оставляя цену где-то под сгибом */
.chart { position: relative; display: flex; align-items: flex-end; gap: 3px; height: 170px; }

/* Сетка: тонкая, сплошная, отступает на шаг от поверхности */
.chart-grid { position: absolute; left: 0; right: 0; top: 0; bottom: 34px; pointer-events: none; }
.chart-grid i { position: absolute; left: 0; right: 0; height: 1px; background: var(--line); }

.bar {
    /* ШИРЕ, ЧЕМ БЫЛО. Сорок дней в одной ширине давали частокол из ниток,
       по которому ничего не сравнить. Теперь на экран помещается около двух
       недель, а остальные дни доступны стрелками — как в поиске билетов */
    position: relative; flex: 0 0 auto; width: 64px; height: 100%;
    display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
    background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
}
.bar__fill {
    /* СВЕТЛАЯ ЗАЛИВКА С ТЁМНОЙ ШАПКОЙ. Сплошной чёрный столбик на белом поле
       забирает весь экран себе, а сравнивать всё равно приходится по верхушкам —
       так пусть верхушка и будет заметной частью */
    width: 56px;
    /* Серый заметно темнее фона: на почти белой странице светлая заливка
       читалась как пустое место, а не как столбик */
    background: #c9c6c3;
    border-top: 3px solid var(--ink);
    border-radius: 0;
    min-height: 4px;
    transition: background .12s ease;
}
.bar:hover .bar__fill { background: #b3afac; border-top-color: var(--red); }
.bar__day { font-size: 11px; color: var(--muted); height: 34px; padding-top: 8px; line-height: 1.15; text-align: center; }
.bar__day b { display: block; color: var(--ink-soft); font-weight: 700; font-size: 12px; }

.bar--best .bar__fill { background: var(--best); border-top-color: var(--best-hover); }
.bar--best:hover .bar__fill { background: var(--best-hover); }
/* Подпись обязательна: пара золотой-зелёный проходит проверку различимости
   только при дополнительном, нецветовом признаке */
.bar__tag {
    position: absolute; top: 2px; left: 50%; transform: translateX(-50%);
    font-size: 10.5px; font-weight: 800; color: #fff;
    background: var(--red); border-radius: 0; padding: 3px 9px; white-space: nowrap;
    text-transform: uppercase; letter-spacing: .04em;
}
.bar--sel .bar__fill { outline: 2.5px solid var(--ink); outline-offset: 2px; }

.tip {
    position: fixed; z-index: 60; pointer-events: none;
    background: var(--surface-dark); color: #fff; border-radius: var(--r-sm);
    padding: 11px 13px; font-size: 13px; line-height: 1.5; max-width: 300px;
    box-shadow: var(--sh-3); opacity: 0; transition: opacity .12s ease;
}
.tip.is-on { opacity: 1; }
.tip b { color: var(--yellow); }
.tip i { display: block; color: #b9bec6; font-style: normal; font-size: 12px; margin-top: 5px; }

/* ── выбранный день ──────────────────────────────────────────────────────── */

.pick {
    margin: 22px 14px 0; display: grid; grid-template-columns: 1fr auto; gap: 20px; align-items: center;
    background: var(--surface-soft); border: 2px solid var(--ink); border-radius: var(--r-md); padding: 20px 22px;
}
.pick__date { font-size: 13px; color: var(--muted); font-weight: 650; }
.pick__price { font-size: 32px; font-weight: 900; letter-spacing: -.02em; margin: 2px 0 4px; }
.pick__why { color: var(--ink-soft); font-size: 14px; }
.pick__why em { font-style: normal; color: var(--best); font-weight: 700; }

/* ── мелочи ──────────────────────────────────────────────────────────────── */

.notice {
    background: var(--yellow-wash); border-left: 4px solid var(--yellow);
    padding: 16px 18px; border-radius: 0 var(--r-sm) var(--r-sm) 0; color: var(--ink-soft);
}
.legend { color: var(--muted); font-size: 13.5px; margin: 18px 14px 0; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
.card { border: 2px solid var(--ink); border-radius: var(--r-md); padding: 22px; }
.card h3 { font-size: 17px; margin-bottom: 8px; }
.card p { margin: 0; color: var(--ink-soft); font-size: 15px; }
.card__num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 0;
    background: var(--yellow); color: var(--ink); font-weight: 900; margin-bottom: 14px;
}

.footer { margin-top: 60px; background: var(--surface-dark); color: #9aa1ab; font-size: 14.5px; padding: 34px 0; }
.footer a { color: #fff; text-decoration: none; }

@media (max-width: 900px) {
    .finder__row { grid-template-columns: 1fr 1fr; }
    .finder__row > :last-child { grid-column: 1 / -1; }
    .hero::after { display: none; }
    .pick { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .finder__row { grid-template-columns: 1fr; }
    .nav { display: none; }
    .hero { padding: 44px 0 96px; }
}

/* ── вход и кабинет ──────────────────────────────────────────────────────── */

.container--narrow { max-width: 460px; }

.muted { color: var(--muted); font-size: 15px; }

.form { display: flex; flex-direction: column; gap: 18px; margin: 24px 0; }

/* «Выслать письмо заново»: поле и кнопка в строку, потому что это не форма,
   а одно действие — на узком экране всё равно перестраивается в столбик */
.form--row { flex-direction: row; flex-wrap: wrap; gap: 10px; align-items: center; }
.form--row input {
    flex: 1 1 200px; min-width: 0; padding: 11px 12px;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    font: inherit; font-size: 15px; background: var(--bg);
}

/* Ошибка входа: красная полоса слева, как у заметки жёлтая. Цветом не только
   заливка, но и рамка — при дальтонизме заливка одна не читается */
.alert {
    padding: 14px 16px; border-radius: 0 var(--r-sm) var(--r-sm) 0;
    font-size: 15px; font-weight: 600;
}
.alert--error { background: #fdecec; border-left: 4px solid var(--red); color: #8c1113; }

/* ПРЕДУПРЕЖДЕНИЕ — НЕ ОШИБКА, И ОКНОМ НЕ ВСПЛЫВАЕТ. Владелец, 17 сент 2026:
   «при каждом обновлении теперь вот это, зачем оно мне каждый раз?» Плашка
   «отчёт неполный» жила в отчёте по месяцам, но класс .alert--error в кабинете
   поднимается модальным окном (см. app.js), и окно про финотчёт вылезало поверх
   «Сборки» на каждой перезагрузке. Состояние данных — это не ошибка действия:
   ему место в своём разделе, спокойным цветом. */
.alert--vnimanie { background: #fff6ec; border-left: 4px solid #d98324; color: #8a4b0f; }

.cabinet__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; flex-wrap: wrap; margin-bottom: 28px;
}

.card--balance { background: var(--yellow-wash); border-color: var(--yellow-deep); margin-bottom: 34px; }
.balance__sum { display: block; font-size: clamp(30px, 5vw, 44px); line-height: 1.1; margin: 6px 0 12px; }

/* Таблица шире экрана телефона прокручивается внутри себя, а не тянет всю
   страницу вбок: горизонтальная прокрутка страницы ломает чтение */
.table-wrap { overflow-x: auto; margin-bottom: 34px; }
.table { width: 100%; border-collapse: collapse; font-size: 15px; }
.table th, .table td { padding: 12px 14px; text-align: left; border-bottom: 2px solid var(--ink); }
.table th { font-size: 12.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.table td .muted { font-size: 13px; }
.table code { font-size: 13.5px; background: var(--surface-soft); padding: 2px 6px; border-radius: 0; }

.badge {
    display: inline-block; padding: 3px 10px; border-radius: 0;
    font-size: 12.5px; font-weight: 700; white-space: nowrap;
    background: var(--surface-soft); color: var(--ink-soft);
}
.badge--confirmed { background: var(--best-wash); color: var(--best-hover); }
.badge--hold { background: var(--yellow-wash); color: #8a6d00; }
.badge--cancelled, .badge--expired { background: #f3f4f6; color: var(--muted); }

.sum--plus { color: var(--best-hover); font-weight: 700; white-space: nowrap; }
.sum--minus { color: var(--ink); font-weight: 700; white-space: nowrap; }

/* ── страница брони ──────────────────────────────────────────────────────── */

.alert--ok { background: var(--best-wash); border-left: 4px solid var(--best); color: var(--best-hover); }

/* Две колонки: подпись и значение. На телефоне подписи уезжают наверх, иначе
   на узком экране от значения остаётся полоска в два слова */
.facts { display: grid; grid-template-columns: 190px 1fr; gap: 14px 20px; margin: 26px 0 32px; }
.facts dt { color: var(--muted); font-size: 14px; font-weight: 650; }
.facts dd { margin: 0; font-size: 16px; }
@media (max-width: 560px) {
    .facts { grid-template-columns: 1fr; gap: 4px 0; }
    .facts dd { margin-bottom: 14px; }
}

.row-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-top: 28px; }

/* Отмена не должна выглядеть как основное действие: рядом с «оплатить» красная
   кнопка «отменить» ловит случайные нажатия */
/* Мелкая кнопка — для карточки счёта, где рядом стоят два действия и обычные
   кнопки занимают всю ширину узкой колонки */
.btn--small { padding: 7px 13px; font-size: 13.5px; }
.btn--quiet { background: transparent; color: var(--muted); border: 2px solid var(--ink); }
.btn--quiet:hover { background: var(--surface-soft); color: var(--ink); }

/* Компания добавлена, но ещё не подтверждена. Жёлтая рамка, а не красная:
   это не ошибка клиента, а следующий шаг, который он должен сделать сам */
.card--wait {
    border-color: var(--yellow-deep); background: var(--yellow-wash);
    padding: 22px 24px; margin-bottom: 22px;
}
.card--wait h2 { margin: 0 0 10px; }
.card--wait .todo { margin: 12px 0; }

/* Регистрация под формой входа: отделена чертой, чтобы не читалась как часть
   формы, и кнопкой во всю ширину — её ищут глазами, а не в тексте */
.login__signup {
    display: flex; flex-direction: column; gap: 10px; align-items: stretch;
    margin-top: 26px; padding-top: 22px; border-top: 2px solid var(--ink);
}
.login__signup span { color: var(--muted); font-size: 15px; }
.login__signup .btn { width: 100%; }

h1 code { font-size: .8em; background: var(--surface-soft); padding: 3px 10px; border-radius: 0; }

/* ── счёт на оплату ──────────────────────────────────────────────────────── */

.invoice { border: 2px solid var(--ink); border-radius: var(--r-md); padding: 30px; margin-bottom: 8px; }
.invoice h1 { font-size: clamp(22px, 3vw, 28px); }
.table--invoice th { width: 210px; text-transform: none; letter-spacing: 0; font-size: 14px; }
.table .right { text-align: right; }
.table tfoot th { font-size: 16px; color: var(--ink); text-transform: none; letter-spacing: 0; }

.badge--pending { background: var(--yellow-wash); color: #8a6d00; }
.badge--paid { background: var(--best-wash); color: var(--best-hover); }

/* Печать: на бумаге нужен только счёт. Всё остальное — шапка, подвал, кнопки,
   переключатель оформления — это экран, в платёжке они мешают */
@media print {
    .header, .footer, .no-print, nav { display: none !important; }
    body { background: #fff; }
    .section { padding: 0; }
    .invoice { border: 0; padding: 0; }
    .notice { border-left: 3px solid #000; }
    a[href]:after { content: ""; }
}

/* ── поиск по складам ────────────────────────────────────────────────────── */

.combo { position: relative; }
.combo__input {
    height: 52px; padding: 0 14px; font-size: 16px; font-weight: 550; width: 100%;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink);
}
.combo__input:focus {
    outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(255, 214, 10, .55);
}

/* Список ШИРЕ поля. Поле — одна из шести колонок формы, и в его ширину
   «Ozon Нижний Новгород РФЦ» не помещается: обрезанное «Ozon Нижн…» не даёт
   отличить его от «Ozon Нижний Новгород СЦ». Список абсолютный, он никому не
   мешает, поэтому растягиваем по содержимому — но не дальше края экрана */
.combo__list {
    position: absolute; z-index: 30; top: calc(100% + 6px); left: 0;
    min-width: 100%; width: max-content; max-width: min(540px, calc(100vw - 28px));
    max-height: 320px; overflow-y: auto; margin: 0; padding: 6px;
    list-style: none; background: var(--surface);
    border: 2px solid var(--ink); border-radius: var(--r-md); box-shadow: var(--sh-2);
}

.combo__item {
    display: flex; flex-direction: column; gap: 2px;
    padding: 9px 12px; border-radius: var(--r-sm); cursor: pointer;
}
.combo__row { display: flex; align-items: center; gap: 8px; }
.combo__item:hover, .combo__item.is-on { background: var(--surface-soft); }
.combo__name { font-weight: 650; }
.combo__meta { color: var(--muted); font-size: 13.5px; }
.combo__empty { padding: 14px 12px; color: var(--muted); font-size: 14.5px; }

/* Пометка способа поставки. Нужна не для красоты: сортировочные центры — это
   FBS, а его компания возит не везде, и человек должен видеть разницу до того,
   как забронирует */
 /* Пометка не сжимается и не уезжает за край никогда: она про то, повезём мы
    туда или нет, и обрезанное «FB» вместо «FBS» хуже, чем отсутствие подписи */
.combo__tags { margin-left: auto; display: flex; gap: 6px; flex: 0 0 auto; }
.combo__tag {
    padding: 2px 9px; border-radius: 0; white-space: nowrap;
    font-size: 12px; font-weight: 700; letter-spacing: .02em;
    background: var(--surface-soft); color: var(--ink-soft);
}
.combo__tag--order { background: var(--yellow-wash); color: #8a6d00; }
/* Сжимается сначала площадка с расстоянием, потом название: если места мало,
   «Wildberries · 190 км» можно и не дочитать, а название склада — нужно */
.combo__name {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── табло выездов ───────────────────────────────────────────────────────── */

/* Тёмное поле с янтарными буквами — как настоящее табло. Годится и по делу:
   строк много, и на светлом фоне таблица из тридцати рейсов выглядит как
   бухгалтерский отчёт, а не как расписание, которое читают на бегу */
.section--board { padding-top: 34px; }

.board__title {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.board__filter select {
    height: 46px; padding: 0 38px 0 14px; font-size: 15px; font-weight: 600;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink); appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1l5 5 5-5' stroke='%23767d88' stroke-width='2' fill='none' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat; background-position: right 14px center;
}

.board {
    background: #0f1114; border-radius: var(--r-md); overflow: hidden;
    font-variant-numeric: tabular-nums;
}

.board__head, .board__row {
    display: grid;
    grid-template-columns: 82px 138px minmax(140px, 1fr) 70px 92px 100px;
    gap: 12px; align-items: center; padding: 13px 16px;
}
.board__head {
    color: #6d757f; font-size: 11.5px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .09em;
    border-bottom: 1px solid #1e2228;
}

.board__row { border-bottom: 1px solid #1a1d22; color: #e8eaed; font-size: 15px; }
.board__row:last-child { border-bottom: 0; }
.board__row i { display: block; font-style: normal; font-size: 12.5px; color: #8f8b89; margin-top: 2px; }

.board__no { font-weight: 800; letter-spacing: .04em; color: var(--yellow); }
.board__from { font-weight: 600; line-height: 1.25; }
.board__to { font-weight: 600; line-height: 1.35; }
.board__at { font-weight: 700; }
.board__seats b { font-size: 13.5px; font-weight: 700; }
.board__seats--some { color: #f3f2f2; }
.board__seats--few { color: var(--yellow); }
.board__seats--none, .board__seats--gone { color: #6d757f; }

/* Разделитель дня: в аэропорту его нет, но там и не смотрят на две недели
   вперёд. Без него строки сливаются в сплошную ленту */
.board__day {
    padding: 14px 18px 9px; color: var(--yellow); font-size: 13px;
    font-weight: 800; text-transform: uppercase; letter-spacing: .1em;
    background: #201e1d;
}
.board__day span { color: #6d757f; margin-left: 6px; }
.board__day b { color: #fff; background: var(--red); padding: 1px 8px; border-radius: 0;
    margin-left: 10px; font-size: 11px; letter-spacing: .06em; }

.board__state { font-weight: 700; font-size: 13.5px; }
.board__row--open .board__state { color: #f3f2f2; }
.board__row--soon .board__state { color: var(--yellow); }
.board__row--closed .board__state, .board__row--flying .board__state,
.board__row--done .board__state { color: #6d757f; }
.board__row--closed, .board__row--flying, .board__row--done { color: #8b9299; }
.board__row--closed .board__no, .board__row--flying .board__no,
.board__row--done .board__no { color: #6d757f; }

.board__empty { padding: 40px 18px; color: #8b9299; text-align: center; }
.board__clock { color: var(--muted); font-size: 13px; margin: 12px 4px 0; }

/* Перемигивание строки при обновлении: короткая вспышка, чтобы было видно, что
   табло живое, но без мельтешения */
@keyframes board-flip { from { background: rgba(255, 214, 10, .16); } to { background: transparent; } }
.board__row--fresh { animation: board-flip 1.1s ease-out; }

@media (max-width: 820px) {
    .board__head { display: none; }
    .board__row {
        grid-template-columns: 84px 1fr auto; gap: 6px 12px;
        grid-template-areas: "no from state" "no to seats" "no at seats";
        padding: 14px 16px;
    }
    .board__no { grid-area: no; align-self: start; }
    .board__from { grid-area: from; }
    .board__to { grid-area: to; }
    .board__at { grid-area: at; font-size: 13px; color: #8b9299; }
    .board__seats { grid-area: seats; text-align: right; }
    .board__state { grid-area: state; text-align: right; }
}

/* ── меню в шапке ────────────────────────────────────────────────────────── */

/* СЛОВО ИЛИ ЗНАЧОК, НО НЕ ОБА СРАЗУ. Значок рядом со словом — второе имя того
   же пункта: место занимает, а нового не сообщает. Поэтому пока слово видно,
   значка нет, и наоборот — на узком экране, где слова не помещаются, значок
   остаётся один. Разметка не меняется, обе части всегда есть в HTML. */

.nav { display: flex; gap: 22px; align-items: center; margin-left: auto; }

.nav__link {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 8px 0; border-radius: 0;
    color: var(--ink); text-decoration: none; font-weight: 650; font-size: 14.5px;
    border-bottom: 2px solid transparent;
    transition: border-color .15s ease, color .15s ease;
}
.nav__link:hover { border-bottom-color: var(--ink); }

/* ТЕКУЩИЙ РАЗДЕЛ — ЧЕРТОЙ ПОД СЛОВОМ, А НЕ ЧЁРНОЙ ЗАЛИВКОЙ. Заливка пришла
   из файла дизайнера, но в светлой шапке чёрный прямоугольник перетягивает
   на себя всё внимание и читается как кнопка, хотя это всего лишь отметка
   «вы здесь». Черта говорит то же самое голосом пометки, а не кнопки, и
   красный у нас и так фирменный. */
.nav__link.is-here {
    background: none; color: var(--ink);
    font-weight: 750; border-bottom-color: var(--red);
}

.nav__link svg { flex-shrink: 0; display: none; }

/* В КАБИНЕТЕ ЗНАЧКИ НУЖНЫ ТОЛЬКО В УЗКОЙ ПОЛОСЕ ШИРИН, и границы у неё две.

   СВЕРХУ. В той же строке едут разделы кабинета и название юрлица. Замер по
   настоящей разметке: логотип 211 + полоса кабинета 531 + меню короткими
   словами 194 + отступы 56 = 992 точки. Выше этого слова помещаются, и ниже
   1100 порог не опускаем только ради запаса на длинное название юрлица —
   «ООО Экспресс Маркет» в замере короткое, бывают длиннее.

   СНИЗУ. Ниже 861 разделы кабинета уезжают на собственную строку (правило
   .header__cab { order: 3 } ниже по файлу), и в верхней остаются только
   логотип с меню — там словам снова просторно, значок не нужен.

   ЭТИ ЧИСЛА ОДНАЖДЫ УЖЕ БЫЛИ ВРАНЬЁМ. Первый замер я делал на выдуманной
   шапке с пятью разделами подряд, а их три, и две из них — выпадающие
   списки. Получилось 1455 вместо 1234, и вывод «слова в кабинете невозможны»
   был неверным. Если будете менять эти пороги — меряйте на настоящей
   разметке из parts/cabinet-nav.php, а не на своём представлении о ней. */
@media (min-width: 861px) and (max-width: 1100px) {
    .container--wide .nav { gap: 4px; }
    .container--wide .nav__text {
        position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
    }
    .container--wide .nav__link { padding: 9px 9px 7px; }
    .container--wide .nav__link svg { display: block; width: 27px; height: 27px; stroke-width: 1.4; }
    .container--wide .nav__link.is-here { color: var(--red); }
}

/* НА ОБЫЧНЫХ СТРАНИЦАХ СЛОВА ДЕРЖАТСЯ ДО ТЕЛЕФОНА. Короткими названиями всей
   шапке нужно 461 точку, поэтому планшету слов хватает — раньше здесь стоял
   порог 900, и слова зря пропадали на половине экранов. Ниже 560 их убираем:
   там уже тесно, и значок честно заработан. Название не пропадает — оно
   остаётся в title для мыши и в aria-label для голосовых читалок */
@media (max-width: 560px) {
    .nav, .container--wide .nav { gap: 4px; }
    .nav__text, .container--wide .nav__text {
        position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
    }
    .nav__link, .container--wide .nav__link { padding: 9px 9px 7px; }
    .nav__link svg, .container--wide .nav__link svg {
        display: block; width: 24px; height: 24px; stroke-width: 1.4;
    }
    .nav__link.is-here, .container--wide .nav__link.is-here { color: var(--red); }
}

/* ── условия клиента в кабинете ──────────────────────────────────────────── */

/* Поля в два столбца: четыре поля в колонку растягивают кабинет так, что
   поставки уезжают под сгиб, а они там главное */
.form--terms { display: grid; grid-template-columns: repeat(2, minmax(220px, 1fr)); gap: 16px 20px; }
.form--terms button { grid-column: 1 / -1; justify-self: start; }
@media (max-width: 620px) { .form--terms { grid-template-columns: 1fr; } }

/* ── переключатель схемы работы ───────────────────────────────────────────── */

/* Появляется только со скриптом: без него остаётся обычный список, и прятать
   в нём нечего. Поэтому разметки в шаблоне нет, всё создаётся в app.js */
.modes {
    display: flex; align-items: center; gap: 6px;
    margin: 0 0 8px;
}
.modes__btn {
    height: 30px; padding: 0 13px; font: inherit; font-size: 13px; font-weight: 650;
    color: var(--muted); background: transparent;
    border: 2px solid var(--ink); border-radius: 0;
    cursor: pointer; transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.modes__btn:hover { color: var(--ink); border-color: var(--ink-soft); }
.modes__btn--on,
.modes__btn--on:hover {
    color: var(--ink); background: var(--yellow); border-color: var(--yellow-deep);
}
.modes__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* Значок «обновить сейчас» у графика: маленький, рядом с выбором периода.
   Символ, а не слово — владелец просил именно значок */
.dash__svezhest { display: inline-flex; }
.dash__svezhest button {
    width: 34px; height: 34px; padding: 0;
    font-size: 18px; line-height: 1; cursor: pointer;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink);
}
.dash__svezhest button:hover { background: var(--surface-soft); }

/* Счётчик слева от края, чтобы не прыгал при смене числа складов */
.modes__count { margin-left: auto; font-size: 12.5px; color: var(--muted); }

@media (max-width: 560px) {
    .modes__count { display: none; }
}

/* ── карта продаж ─────────────────────────────────────────────────────────── */

/* Очертания настоящие: Natural Earth, общественное достояние. Округа собраны
   из регионов, поэтому внутри округа видны их границы — так карта читается
   лучше, чем сплошной заливкой, и не приходится склеивать полигоны */
.geo { margin: 6px 0 4px; }
.geo__svg { display: block; width: 100%; height: auto; }

.geo__region {
    fill: rgba(20, 22, 26, var(--tint));
    stroke: #fff; stroke-width: .6; stroke-linejoin: round;
    cursor: pointer; transition: fill .15s ease;
}
.geo__region--empty { fill: var(--surface-soft); cursor: default; }
.geo__region:hover { fill: var(--yellow-deep); }

/* Выбранный округ обводим, а не перекрашиваем: заливка занята долей продаж,
   и менять её значит врать про число */
.geo__region--on { stroke: var(--yellow-deep); stroke-width: 1.6; }

.geo__label { pointer-events: none; }
.geo__label text { text-anchor: middle; fill: #fff; paint-order: stroke; }
.geo__label--dark text { fill: var(--ink); }

.geo__label .geo__name  { font-size: 12px; font-weight: 700; }
.geo__label .geo__share { font-size: 17px; font-weight: 800; }
.geo__label .geo__sum   { font-size: 11px; opacity: .8; }

/* ── переключатель месяцев ───────────────────────────────────────────────── */

.months { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 12px; }

.months__btn {
    display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
    padding: 8px 14px; font: inherit; text-align: left; cursor: pointer;
    background: var(--surface); color: var(--ink);
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    transition: border-color .15s ease, background .15s ease;
}
.months__btn:hover { border-color: var(--ink-soft); }
.months__btn--on, .months__btn--on:hover {
    background: var(--yellow-wash); border-color: var(--yellow-deep);
}
.months__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.months__name { font-size: 12.5px; font-weight: 700; color: var(--muted); }
.months__btn--on .months__name { color: var(--ink); }
.months__sum  { font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }

/* Месяц, собранный не целиком: краем выборки или потому, что ещё идёт.
   Метка нужна рядом с суммой, иначе неполный месяц читается как провал */
.months__part {
    font-size: 11px; font-weight: 700; color: var(--muted);
    text-transform: lowercase; letter-spacing: .02em;
}

/* ── клик по округу ───────────────────────────────────────────────────────── */

.pair__where { color: var(--muted); font-weight: 500; }

/* ── кабинет по разделам ──────────────────────────────────────────────────── */

/* Меню наверху, счёт слева, содержимое справа.
   Боковое меню съедало 210 точек ширины у таблиц и графиков — а они здесь
   главное. Сверху оно занимает одну строку и содержимому не мешает. */
/* Кабинет начинается сразу под шапкой. Полсотни точек воздуха, уместные на
   витрине, здесь просто отодвигают графики вниз */
.section--cab { padding: 18px 0 40px; }

.cab {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    gap: 0;
}

/* Виден только читалке экрана. display:none её бы тоже спрятал — поэтому
   вырезаем в точку, а не убираем из потока */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* Меню кабинета стоит в жёлтой полосе, рядом с логотипом.
   Своей строкой оно занимало вторую полосу под шапкой: две полосы одна над
   другой, обе наполовину пустые, а содержимое из-за них начиналось ниже. */
.header__cab {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
}

.cabtop__nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }

/* Профиль справа, сразу за колокольчиком (вправо толкает уже колокольчик —
   .cabtop__bell margin-left:auto; здесь auto не нужен, иначе свободное место
   делится пополам и колокольчик уезжает от «ИП» влево). */
.cabtop__folder--co { margin-left: 0; }

/* На ЖЁЛТОМ, а не на белом: приглушённый серый на жёлтом читается плохо, а
   светлая подсветка при наведении не видна вовсе */
.cabtop__link {
    display: block;
    padding: 8px 13px;
    border-radius: var(--r-sm);
    font-size: 15px;
    font-weight: 650;
    color: var(--ink);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
}

.cabtop__link:hover { background: rgba(20, 22, 26, .08); }

/* Подчёркивание красным: жёлтым по жёлтому текущий раздел не отличить */
.cabtop__link--on, .cabtop__link--on:hover { border-bottom-color: var(--red); }

/* Группа раскрывается без скрипта. Раскрытое ЛОЖИТСЯ ПОВЕРХ содержимого, а не
   раздвигает его: иначе нажатие на «Аналитику» роняло бы страницу вниз. */
.cabtop__folder { position: relative; }
.cabtop__group { cursor: pointer; list-style: none; user-select: none; }
.cabtop__group::-webkit-details-marker { display: none; }
/* БЕЗ СТРЕЛКИ У РАЗДЕЛА. Владелец 17 сент 2026: «стрелочки рядом с названием
   давай уберём, выглядит доисторически». В шапке WB их тоже нет: разделы просто
   названы, а что там раскрывается — показывает само наведение. У выбора юрлица
   справа стрелка остаётся — там она и у WB, и означает выбор, а не раздел. */
.cabtop__folder[open] > .cabtop__group { background: rgba(20, 22, 26, .12); }

.cabtop__drop {
    position: absolute;
    z-index: 30;
    top: calc(100% + 4px);
    left: 0;
    min-width: 220px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 6px;
    background: var(--surface);
    border: 2px solid var(--ink);
    border-radius: var(--r-sm);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
}

.cabtop__drop--right { left: auto; right: 0; }

/* РАЗДЕЛЫ «ХРАНЕНИЯ» В БОКОВОЙ КОЛОНКЕ — столбиком, как этапы FBS (17 сент
   2026). Кнопки те же, что были шапкой экрана, поэтому наследуют .modes__btn;
   меняется только раскладка: вертикаль и одинаковая ширина, чтобы числа
   выстроились в колонку и взгляд ловил их сразу. */
.hran-tabs--bok { display: flex; flex-direction: column; gap: 6px; }
.hran-tabs--bok .modes__btn {
    width: 100%;
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    text-align: left;
}

/* СПИСОК РАЗДЕЛА — БЛОКАМИ В НЕСКОЛЬКО КОЛОНОК, КАК В ШАПКЕ WB.
   Владелец 17 сент 2026: «у вб в раскрывающемся списке товары идут не в один
   столбик, а по блокам». Девять пунктов подряд читаются построчно; три блока с
   подписями находятся взглядом сразу. Ширина по содержимому, но не шире окна:
   раскрытый список у правого края иначе уезжает за экран. */
.cabtop__drop--bloki {
    flex-direction: row;
    align-items: flex-start;
    gap: 26px;
    padding: 14px 18px;
    max-width: min(760px, calc(100vw - 32px));
}
.cabtop__blok { display: flex; flex-direction: column; gap: 1px; min-width: 176px; }
.cabtop__blok-podpis {
    padding: 2px 10px 6px;
    font-size: 11px; font-weight: 800; letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted, #6a7480);
    white-space: nowrap;
}

/* МОСТИК ЧЕРЕЗ ЗАЗОР. Список отстоит от заголовка на четыре пикселя, и на этом
   пустом месте курсор формально уходит из меню. При раскрытии наведением (17
   сент 2026) это давало мигание: список закрывался ровно в момент, когда к нему
   тянулись. Прозрачная полоса поверх зазора держит наведение непрерывным. */
.cabtop__drop::before {
    content: '';
    position: absolute;
    top: -6px; left: 0; right: 0;
    height: 6px;
}

.cabtop__sub {
    display: block;
    padding: 8px 12px;
    border-radius: var(--r-sm);
    font-size: 14.5px;
    color: var(--ink-soft);
    text-decoration: none;
    white-space: nowrap;
}

.cabtop__sub:hover { background: var(--surface-soft); color: var(--ink); }

/* СЧЁТ В ПОЛОСЕ — сокращённый вид, одна сумма.
   Он же прижимает вправо всю правую тройку (счёт, колокольчик, профиль):
   auto-отступ переехал сюда с колокольчика, иначе счёт остался бы висеть
   посреди полосы, оторванным и от меню, и от профиля. */
.cabtop__money {
    margin-left: auto;
    display: inline-flex; align-items: baseline; gap: 7px;
    padding: 6px 11px; border-radius: 8px;
    text-decoration: none; color: inherit; white-space: nowrap;
    background: rgba(20, 22, 26, .06);
}
.cabtop__money:hover { background: rgba(20, 22, 26, .12); }
.cabtop__money-podpis { font-size: 11.5px; opacity: .65; }
.cabtop__money-sum { font-size: 14px; font-weight: 700; }

/* КОЛОКОЛЬЧИК — системные оповещения (по образцу WB).
   Стоит между счётом и профилем; вправо всю тройку двигает счёт. */
.cabtop__bell { margin-left: 0; }
.cabtop__bell-btn {
    position: relative; cursor: pointer; list-style: none; user-select: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; color: var(--ink); border-radius: var(--r-sm);
}
.cabtop__bell-btn:hover { background: rgba(20, 22, 26, .08); }
.cabtop__bell-btn::-webkit-details-marker { display: none; }
.cabtop__bell-ico { display: block; }
.cabtop__folder[open] > .cabtop__bell-btn { background: rgba(20, 22, 26, .12); }
.cabtop__bell-count {
    position: absolute; top: -2px; right: -2px;
    min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 800; line-height: 1;
    color: #fff; background: #d92d20; border-radius: 9px;
}
.cabtop__opoves { min-width: 340px; max-width: 380px; max-height: 74vh; overflow-y: auto; gap: 0; }
.opoves__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; padding: 4px 8px 8px; border-bottom: 1px solid var(--line);
    position: sticky; top: 0; background: var(--surface);
}
.opoves__vse {
    border: none; background: none; cursor: pointer; padding: 2px 4px;
    font-size: 13px; color: var(--muted, #767d88); text-decoration: underline;
}
.opoves__vse:hover { color: var(--ink); }
.opoves__pusto { padding: 14px 8px; margin: 0; font-size: 13.5px; color: var(--muted, #767d88); }
.opoves__data {
    padding: 10px 8px 4px; font-size: 12px; font-weight: 700;
    color: var(--muted, #767d88);
}
.opoves__row { display: flex; gap: 8px; padding: 8px; border-radius: var(--r-sm); }
.opoves__row.is-new { background: var(--surface-soft, #f6f6f6); }
.opoves__znak { flex: 0 0 auto; width: 10px; height: 10px; margin-top: 5px; border-radius: 50%; }
.opoves__znak--error { background: #d92d20; }
.opoves__znak--warning { background: #e79c00; }
.opoves__znak--info { background: #4a7dff; }
.opoves__telo { min-width: 0; flex: 1 1 auto; }
.opoves__verh { display: flex; align-items: center; gap: 6px; }
.opoves__vremya { font-size: 11.5px; color: var(--muted, #767d88); }
.opoves__tochka { width: 7px; height: 7px; border-radius: 50%; background: #d92d20; }
.opoves__title { display: block; font-size: 14px; line-height: 1.3; margin-top: 1px; }
.opoves__text { margin: 3px 0 0; font-size: 13px; line-height: 1.35; color: var(--ink-soft); }
.opoves__link { display: inline-block; margin-top: 5px; font-size: 13px; font-weight: 600; }

/* Переключатель юрлиц */
.cabtop__co {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 13px;
    /* Белая плашка на жёлтом: обводка по светлой линии на жёлтом не видна */
    background: var(--surface);
    border-radius: var(--r-sm);
    font-weight: 700;
    font-size: 14.5px;
    max-width: 260px;
}

.cabtop__co::-webkit-details-marker { display: none; }
.cabtop__co::after { content: '▾'; font-size: 10px; margin-left: auto; }
.cabtop__co-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Профиль: реквизиты, юрлица, техническое, выход.
   Всё, что открывают раз в месяц, — здесь, чтобы не обходить его взглядом
   каждый день по дороге в аналитику. */
.cabtop__profile { min-width: 320px; padding: 4px; }

.cabtop__who { padding: 12px 14px 10px; display: flex; flex-direction: column; gap: 2px; }
.cabtop__who .muted { font-size: 13px; }

/* Разделители, а не отступы: без линии список юрлиц и список настроек
   сливаются в один, и «Выйти» читается как ещё одна компания */
.cabtop__section { padding: 6px 0; border-top: 2px solid var(--ink); }
.cabtop__section:first-child { border-top: 0; }

/* Кнопка, а не ссылка: переключение меняет состояние входа и идёт POST-ом */
.cabtop__pick {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    font: inherit;
    font-size: 14.5px;
    text-align: left;
    cursor: pointer;
}

.cabtop__pick:hover { background: var(--surface-soft); }
.cabtop__pick.is-on { background: var(--yellow-wash); }

.cabtop__pick-name { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cabtop__pick-name .muted { font-size: 12.5px; }
.cabtop__pick-sum { margin-left: auto; font-weight: 700; white-space: nowrap; }

/* Точка выбора: без неё не видно, какая компания открыта сейчас */
.cabtop__dot {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid var(--line);
}

.cabtop__pick.is-on .cabtop__dot { border-color: var(--yellow-deep); background: var(--yellow-deep); }

/* Выход — такая же строка списка, но кнопка формы, а не ссылка */
.cabtop__exit {
    width: 100%;
    border: 0;
    background: none;
    font: inherit;
    font-size: 14.5px;
    text-align: left;
    cursor: pointer;
}

/* Левая колонка целиком: счёт и оборот. ЛИПКАЯ ОНА, А НЕ ОТДЕЛЬНЫЕ КАРТОЧКИ
   ВНУТРИ — иначе под уехавшим счётом остаётся пустое место во всю высоту
   страницы, а это и была жалоба: «половина экрана пустая» */
.cab__rail {
    grid-column: 1;
    align-self: start;
    position: sticky;
    top: 84px;
    background: var(--yellow-wash);
    border-right: 2px solid var(--ink);
    padding: 20px 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
    /* Колонка выросла и на невысоком экране перестала помещаться. Липкий блок
       выше экрана — это блок с недоступным низом, поэтому лишнее прокручивается
       внутри колонки, а не пропадает */
    max-height: calc(100vh - 100px);
    overflow-y: auto;
    /* Прокрутку НЕ запираем внутри колонки: иначе колесо мыши над ней
       перестаёт листать страницу, как только колонка дошла до низа, — и
       человек решает, что кабинет завис */
    overscroll-behavior: auto;
    scrollbar-width: thin;
}

/* СЧЁТ РАЗВЁРНУТО — в профиле, по нажатию на ИП. Жёлтая заливка осталась от
   прежней карточки: деньги в кабинете всегда были жёлтыми. */
.cabtop__wallet { background: var(--yellow-wash); }
.cabtop__wallet-sum { display: block; font-size: 26px; font-weight: 800; line-height: 1.15; }
.cabtop__wallet-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }

/* ПУСТАЯ КОЛОНКА НЕ ЗАНИМАЕТ ШИРИНУ. На разделах без боковых блоков слева
   оставалось 280 точек воздуха, и широкая таблица в остаток не помещалась.
   Класс ставит скрипт при переключении раздела: без скрипта разделы идут
   подряд, и колонка не пустует никогда. */
.cab--bezrail { grid-template-columns: minmax(0, 1fr); }
.cab--bezrail .cab__rail { display: none; }
.cab--bezrail .cab__body { grid-column: 1; }

.cab__body { grid-column: 2; background: var(--surface); padding: 24px 28px; }
/* Колонка не запирает прокрутку и не превращается в окошко с ползунком */
@media (max-width: 1200px) { .cab__rail { max-height: none; overflow: visible; } }
.cab__aside { min-width: 0; }
.cab__link {
    /* Блочность задана здесь, а не наследуется от колоночного .cab__nav:
       внутри <details> браузер заворачивает содержимое в свой внутренний
       блок, ссылки перестают быть элементами флексбокса и становятся
       строчными — меню рассыпается в ряд */
    display: block;
    padding: 9px 13px; border-radius: var(--r-sm); font-size: 14.5px; font-weight: 600;
    color: var(--ink-soft); text-decoration: none; border-left: 3px solid transparent;
    transition: background .15s ease, color .15s ease;
}
.cab__link:hover { background: var(--surface-soft); color: var(--ink); }
.cab__link--on, .cab__link--on:hover {
    background: var(--yellow-wash); color: var(--ink); border-left-color: var(--yellow-deep);
}

/* Без скрипта разделы просто идут подряд — панель работает якорями */
.cab__pane + .cab__pane { margin-top: 40px; }
.cab__body h2:first-child { margin-top: 0; }

/* Со скриптом виден один раздел */
[data-cab].cab--tabs .cab__pane { display: none; }
[data-cab].cab--tabs .cab__pane--on { display: block; }

/* ── плитки сводки ────────────────────────────────────────────────────────── */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 14px; margin: 18px 0 8px; }
.card--tile { display: flex; flex-direction: column; gap: 4px; padding: 16px 18px; }
.tile__sum { font-size: 26px; font-weight: 800; line-height: 1.15; }
.tile__sum--quiet { color: var(--muted); font-weight: 700; }

/* Инструкция: текст, который читают один раз и потом ищут в нём глазами.
   Заголовки разделов крупнее обычных абзацев именно поэтому — по ним
   прокручивают, а не читают подряд */
.help h3 { font-size: 19px; margin: 28px 0 10px; }
.help p { font-size: 15px; line-height: 1.6; margin: 10px 0; }
.help > h2 { margin-bottom: 4px; }

.todo { list-style: none; padding: 0; margin: 12px 0 8px; display: grid; gap: 10px; }
.todo li {
    padding: 13px 16px; border: 2px solid var(--ink); border-left: 3px solid var(--yellow-deep);
    border-radius: var(--r-sm); font-size: 14.5px; line-height: 1.5;
}

/* Нумерация в шагах не украшение: «сначала ключ, потом себестоимость» —
   это порядок, а маркированный список порядка не обещает */
.todo--num { list-style: decimal; padding-left: 24px; display: block; }
.todo--num li { margin-bottom: 10px; padding-left: 6px; }


@media (max-width: 860px) {
    /* На телефоне колонок нет: счёт ложится над содержимым, и прилипать ему
       некуда — липкая карточка съела бы треть экрана */
    .cab { grid-template-columns: 1fr; gap: 16px; }
    /* На телефоне колонок нет: липкой колонке некуда прилипать, и она
       разворачивается обычной лентой над содержимым */
    .cab__rail { position: static; grid-column: 1; border-right: 0; border-bottom: 2px solid var(--ink); max-height: none; overflow: visible; }
    .cab__body { grid-column: 1; }
    .cabtop__co { max-width: 100%; }

    /* Шапка перестаёт быть строкой: логотип, меню и профиль не помещаются в
       одну. Высоту отпускаем, иначе они наезжают друг на друга */
    .header__inner { height: auto; flex-wrap: wrap; gap: 10px; padding: 10px 0; }
    .header__cab { order: 3; flex-basis: 100%; }
    .cabtop__link { padding: 7px 10px; font-size: 14px; }

    /* Выпадающий список по содержимому, но не шире экрана.
       «width: 100%» здесь не годится: сто процентов считаются от кнопки, а
       она узкая — список сжимался до 161 точки, и в него не влезали ни ИНН,
       ни сумма. Отсчёт ведём от ширины окна. */
    .cabtop__drop {
        left: 0;
        right: auto;
        min-width: 0;
        width: max-content;
        max-width: calc(100vw - 24px);
    }

    /* На телефоне блоки встают друг под друга: три колонки в 360 точек не
       помещаются, а подписи блоков остаются полезными и лентой */
    .cabtop__drop--bloki { flex-direction: column; gap: 10px; padding: 10px 12px; }
    .cabtop__blok { min-width: 0; }

    /* На телефоне профиль прижимаем к ЛЕВОМУ краю кнопки, а не к правому.
       На широком экране кнопка стоит у правого края и список раскрывается
       влево; на узком она переносится на свою строку и оказывается слева —
       тот же «right: 0» уводил список на 135 точек за левый край экрана. */
    .cabtop__drop--right { left: 0; right: auto; }
    .cabtop__profile { min-width: min(320px, calc(100vw - 24px)); }
}

/* ── Экономика товаров ───────────────────────────────────────────────────
   Полоса разложения рубля. Доли считаются на сервере и приходят в width:
   рисовать её скриптом нельзя — без него страница обязана остаться рабочей.
   Цвета проверены на протанопию и дейтеранопию, худшая пара ΔE 12,4 при
   пороге 8: зелёный и красный при дальтонизме сближаются, и порядок частей
   в полосе для читателя важнее самих оттенков. */
.unit { margin: 18px 0 26px; }

.unit__bar {
    display: flex;
    height: 26px;
    border-radius: var(--r-sm);
    overflow: hidden;
    background: var(--surface-soft);
}

.unit__part { display: block; height: 100%; }
.unit__part--payout { background: #ec3013; }
.unit__part--fee    { background: #201e1d; }
.unit__part--acq    { background: #8f8b89; }
.unit__part--other  { background: #ec3013; }

.unit__keys {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 22px;
}

.unit__keys li { display: flex; align-items: center; gap: 8px; }

.unit__dot {
    width: 11px;
    height: 11px;
    border-radius: 0;
    flex: 0 0 auto;
}

.unit__dot--payout { background: #ec3013; }
.unit__dot--fee    { background: #201e1d; }
.unit__dot--acq    { background: #8f8b89; }
.unit__dot--other  { background: #ec3013; }

.unit__total {
    margin: 14px 0 0;
    padding-top: 12px;
    border-top: 2px solid var(--ink);
}

/* Числа в таблице выравниваем по правому краю: так разряды стоят под
   разрядами и колонку можно читать сверху вниз, не сравнивая посимвольно */
.table .num { text-align: right; white-space: nowrap; }

@media (max-width: 640px) {
    .unit__keys { flex-direction: column; gap: 8px; }
}

/* ── Выкуп по неделям ────────────────────────────────────────────────────
   Столбики рисуются высотой в процентах от своей колонки: шкала начинается
   не с нуля, а чуть ниже худшей недели, иначе при выкупе 96–98% разница
   неразличима. Подпись об этом стоит под графиком — усечённая ось без
   оговорки врёт сильнее, чем её отсутствие. */
.ret {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    margin: 16px 0 10px;
    padding: 14px 12px 0;
    background: var(--surface-soft);
    border-radius: var(--r-md);
    overflow-x: auto;
}

.ret__col {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    flex: 1 0 64px;
    min-height: 150px;
}

.ret__val { font-size: 13px; font-weight: 600; margin-bottom: 6px; }

.ret__bar {
    width: 100%;
    max-width: 46px;
    background: #ec3013;
    border-radius: var(--r-sm) var(--r-sm) 0 0;
    min-height: 4px;
}

/* Последняя неделя ещё доберёт возвраты — показываем её штриховкой,
   чтобы столбик не читался как достигнутый результат */
.ret__col--fresh .ret__bar {
    background: repeating-linear-gradient(45deg,
        #ec3013, #ec3013 5px, #f08a76 5px, #f08a76 10px);
}

.ret__day { font-size: 12px; color: var(--muted); margin-top: 8px; }
.ret__cost { font-size: 12px; color: var(--muted); padding-bottom: 10px; }

/* ── Скорость доставки ───────────────────────────────────────────────────
   Полоса в строке таблицы: длина от нуля до самого медленного склада. Ноль
   у срока осмыслен, поэтому шкала здесь полная — в отличие от выкупа, где
   она усечена и об этом сказано под графиком. */
.spd__cell { width: 34%; min-width: 90px; }

.spd__bar {
    display: block;
    height: 8px;
    border-radius: 0;
    background: #201e1d;
    min-width: 3px;
}

/* Срок — это не «чем больше, тем лучше», поэтому графит, а не зелёный:
   зелёный столбик рядом с девятью днями ожидания читается как похвала */
.ret__bar--slow { background: #201e1d; }

/* ── Группы в панели кабинета ────────────────────────────────────────────
   Разделов стало девять, и плоский список читался как свалка. Заголовок
   группы не ссылка и не сворачивается: сворачивание прячет то, что человек
   уже нашёл, и заставляет искать заново. */
.cab__group {
    display: block;
    padding: 14px 12px 4px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--muted);
}

.cab__group:first-child { padding-top: 4px; }

.cab__link--sub { padding-left: 22px; }

/* Выбор филиала над таблицей направлений */
.hubpick {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 14px 0 18px;
}

.hubpick label { color: var(--muted); }

.hubpick select {
    padding: 8px 12px;
    border: 2px solid var(--ink);
    border-radius: var(--r-sm);
    background: var(--surface);
    font: inherit;
}

@media (max-width: 900px) {
    .cab__group { padding: 8px 10px 2px; }
    .cab__link--sub { padding-left: 12px; }
}

/* ── Выбор периода в аналитике ───────────────────────────────────────────
   Наборы сделаны ссылками, а не кнопками: их можно открыть в новой вкладке
   и отправить, и они работают без скрипта. Свои даты — обычной формой. */
.period {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 18px;
    margin: 14px 0 10px;
    padding: 12px 14px;
    background: var(--surface-soft);
    border-radius: var(--r-md);
}

.period__presets { display: flex; flex-wrap: wrap; gap: 6px; }

.period__btn {
    padding: 6px 12px;
    border-radius: var(--r-sm);
    border: 2px solid var(--ink);
    background: var(--surface);
    color: var(--ink-soft);
    text-decoration: none;
    font-size: 14px;
}

.period__btn:hover { border-color: var(--muted); }

.period__btn--on {
    background: var(--surface-dark);
    border-color: var(--surface-dark);
    color: #fff;
}

.period__own { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.period__own label { color: var(--muted); }

.period__own input[type="date"] {
    padding: 6px 10px;
    border: 2px solid var(--ink);
    border-radius: var(--r-sm);
    background: var(--surface);
    font: inherit;
}

/* Оговорка про задержку отчёта: приглушённая, но не спрятанная — без неё
   клиент решит, что после девятого числа у него не было продаж */
.period__note {
    margin: 0 0 16px;
    color: var(--muted);
    font-size: 14px;
}

/* ── Отчёт по месяцам ────────────────────────────────────────────────────
   Заголовки групп внутри таблицы: без них двадцать шесть строк подряд
   читаются как список, а не как отчёт с разделами. */
.pnl__group td {
    background: var(--surface-soft);
    font-weight: 600;
    font-size: 13px;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--muted);
}

.pnl__total td { font-weight: 700; border-top: 2px solid var(--ink); }

/* Первая колонка не должна уезжать при прокрутке вбок: без названия строки
   колонка месяца — это просто числа */
.pnl td:first-child, .pnl th:first-child {
    position: sticky;
    left: 0;
    background: var(--surface);
    z-index: 1;
}

.pnl .pnl__group td:first-child { background: var(--surface-soft); }

/* ── Решение о товарах без себестоимости ─────────────────────────────────
   Три выхода вместо одного упрёка: раздел, который только сообщает о
   проблеме и не даёт её решить, читают один раз. */
.form--rule {
    margin: 16px 0 24px;
    padding: 16px 18px;
    background: var(--surface-soft);
    border-radius: var(--r-md);
}

.rule {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin: 8px 0;
    line-height: 1.45;
}

.rule input[type="radio"] { margin-top: 5px; flex: 0 0 auto; }

.rule__pct {
    width: 76px;
    padding: 4px 8px;
    border: 2px solid var(--ink);
    border-radius: var(--r-sm);
    font: inherit;
}

/* Свёрнутый выбор решения: список товаров читают чаще, чем меняют правило */
.rulebox {
    margin: 12px 0 20px;
    border: 2px solid var(--ink);
    border-radius: var(--r-md);
    background: var(--surface-soft);
}

.rulebox > summary {
    padding: 10px 14px;
    cursor: pointer;
    list-style: none;
}

.rulebox > summary::-webkit-details-marker { display: none; }

/* Стрелка своя: у встроенного маркера разный вид в разных браузерах,
   и в одном из них он съезжает на вторую строку */
.rulebox > summary::before {
    content: '▸';
    display: inline-block;
    width: 14px;
    color: var(--muted);
}

.rulebox[open] > summary::before { content: '▾'; }

.rulebox .form--rule { margin: 0; padding: 4px 14px 14px 28px; background: none; }

.rulebox__act {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 12px;
}

/* Плитка-ссылка: увидев число, человек хочет тут же что-то с ним сделать.
   БЕЗ display — иначе перебивает колоночную раскладку .card--tile, и подпись,
   число и пояснение текут одной строкой. Наступил ровно на это. */
.card--act { text-decoration: none; color: inherit; }
.card--act:hover { border-color: var(--muted); }

/* ── Дашборд ─────────────────────────────────────────────────────────────
   Сетка в шесть колонок: число занимает две, половинный график три, широкий
   все шесть. Шесть — наименьшее число, которое делится и на два, и на три,
   поэтому ряд из чисел и ряд из графиков выравниваются по одной сетке. */
.dash {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 14px;
    margin: 4px 0 18px;
}

/* min-width: 0 обязателен: у элемента сетки минимальная ширина по умолчанию
   равна ширине содержимого, и длинная строка в плитке раздвигает колонку,
   а вместе с ней и всю сетку — она вылезает за экран */
.dash__cell { min-width: 0; }
.dash__cell--w2 { grid-column: span 2; }
.dash__cell--w3 { grid-column: span 3; }
.dash__cell--w4 { grid-column: span 4; }
.dash__cell--w6 { grid-column: span 6; }
.dash__cell > .card { height: 100%; }

/* Собственные классы дашборда с приставкой dchart: класс .chart в проекте
   УЖЕ ЗАНЯТ календарём цен на главной, и у него align-items: flex-end. В
   колонке это прижимает содержимое вправо — график уехал к правому краю
   карточки, и я полчаса искал причину в сетке. Чужое имя класса не
   переопределяют, а берут своё. */
.dchart { display: flex; flex-direction: column; }

.dchart__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.dchart__legend { display: flex; gap: 14px; font-size: 13px; color: var(--muted); }

/* В линейном графике первая линия — графит, вторая зелёная; в кольце первая
   доля зелёная. Ключи легенды подстраиваются под свой график */
.dchart .dchart__legend .dchart__key--0 { background: #201e1d; }
.dchart .dchart__legend .dchart__key--1 { background: #ec3013; }

.dchart__key {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 0;
    margin-right: 5px;
}

/* ЗАЛИВКУ И ОБВОДКУ У SVG ЗАДАЁМ ЯВНО. По умолчанию у фигуры заливка чёрная,
   а обводки нет: без этих правил ломаная превращается в чёрное пятно, а
   кольцо — в чёрный круг. Ровно так и вышло, когда стили не доехали.
   Цвета из проверенной палитры (протанопия и дейтеранопия, порог ΔE 8). */
.dchart__svg { width: 100%; height: auto; display: block; }
.dchart__grid { stroke: var(--line); stroke-width: 1; fill: none; }

.dchart__line {
    fill: none;
    stroke-width: 2.5;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.dchart__line--0 { stroke: #201e1d; }
.dchart__line--1 { stroke: #ec3013; }
.dchart__dot--0 { fill: #201e1d; stroke: none; }
.dchart__dot--1 { fill: #ec3013; stroke: none; }

.dchart__val { font-size: 13px; font-weight: 700; fill: var(--ink); stroke: none; }
.dchart__x { font-size: 12px; fill: var(--muted); stroke: none; }
.dchart__os { font-size: 13px; margin: 2px 0 0; }

/* Главный график: заказы / выкупы / доход.
   Переключатель сделан вкладками, а не кнопками: три режима показывают одно и
   то же поле зрения под разным углом, и вкладка честно говорит «это тот же
   экран», тогда как кнопка обещает действие.
   Классы свои, а не .dchart__*: тот блок живёт в сетке плиток и подстраивается
   под её ширину, а этот стоит во всю страницу. Переиспользовать чужой класс
   ради экономии четырёх строк уже стоило мне получаса поисков. */
.daychart { display: flex; flex-direction: column; gap: 14px; }

.daychart__tabs {
    display: flex;
    gap: 2px;
    flex-wrap: wrap;
    border-bottom: 2px solid var(--ink);
}

.daychart__tab {
    padding: 8px 16px;
    text-decoration: none;
    color: var(--muted);
    font-weight: 600;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.daychart__tab:hover { color: var(--ink); }
.daychart__tab.is-on { color: var(--ink); border-bottom-color: #ec3013; }

.daychart__nums { display: flex; gap: 36px; flex-wrap: wrap; }
.daychart__nums > div { display: flex; flex-direction: column; gap: 2px; }
.daychart__delta { font-size: 13px; }
.daychart__none { margin: 4px 0; }

/* Кольцо: доли одного целого читаются как части круга без пояснений */
.dchart__ringbox { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.dchart__ring { width: 140px; height: 140px; flex: 0 0 auto; }
.dchart__seg { fill: none; stroke-width: 22; }

.dchart__seg--0 { stroke: #ec3013; }
.dchart__seg--1 { stroke: #201e1d; }
.dchart__seg--2 { stroke: #8f8b89; }
.dchart__seg--3 { stroke: #ec3013; }

.dchart__shares { list-style: none; margin: 0; padding: 0; flex: 1 1 200px; }
.dchart__shares li { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; }
.dchart__share { font-weight: 700; min-width: 54px; }
.dchart__shares b { margin-left: auto; color: var(--muted); font-weight: 600; }

/* Ключи легенды кольца — теми же цветами, что сегменты */
.dchart__shares .dchart__key--0 { background: #ec3013; }
.dchart__shares .dchart__key--1 { background: #201e1d; }
.dchart__shares .dchart__key--2 { background: #8f8b89; }
.dchart__shares .dchart__key--3 { background: #ec3013; }

.dchart__more { display: inline-block; margin-top: 12px; font-size: 14px; }

/* Полосы «на чём держится оборот» */
.rank { width: 100%; border-collapse: collapse; }
.rank td { padding: 5px 0; vertical-align: middle; }
.rank__name { width: 34%; padding-right: 12px; }
.rank__val { width: 84px; padding-left: 12px; white-space: nowrap; }
.rank__bar span {
    display: block;
    height: 12px;
    border-radius: 0;
    background: #201e1d;
    min-width: 3px;
}

@media (max-width: 900px) {
    .dash { grid-template-columns: repeat(2, 1fr); }
    .dash__cell--w3, .dash__cell--w4, .dash__cell--w6 { grid-column: span 2; }
}

@media (max-width: 560px) {
    .dash { grid-template-columns: 1fr; }
    .dash__cell--w2, .dash__cell--w3, .dash__cell--w4, .dash__cell--w6 { grid-column: span 1; }
    .rank__name { width: 42%; }
}

.tune { margin: 4px 0 8px; }
.tune td { padding: 6px 10px; }
.tune__off td { color: var(--muted); }

.tune__btn {
    display: inline-block;
    min-width: 30px;
    padding: 3px 8px;
    margin-left: 4px;
    border: 2px solid var(--ink);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--ink-soft);
    text-decoration: none;
    text-align: center;
}

.tune__btn:hover { border-color: var(--muted); }
.tune__btn--wide { min-width: 78px; }

@media (max-width: 900px) {
    .cards--dash { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
    .cards--dash { grid-template-columns: 1fr; }
}

/* ── Сворачивание групп в меню кабинета ──────────────────────────────────
   Разделов стало пятнадцать, и список перестал помещаться на экран целиком.
   Свёрнутое помнится у клиента: сам <details> живёт до перезагрузки. */
.cab__folder {
    /* Ссылки внутри <details> НЕ становятся элементами флексбокса: браузер
       заворачивает содержимое в свой внутренний блок. Поэтому блочность
       ссылок задана у самого .cab__link, а не наследуется отсюда — меню
       рассыпалось в ряд именно на этом. */
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cab__folder > summary { cursor: pointer; list-style: none; }
.cab__folder > summary::-webkit-details-marker { display: none; }

.cab__folder > summary::after {
    content: '▾';
    margin-left: 6px;
    font-size: 10px;
    vertical-align: middle;
}

.cab__folder:not([open]) > summary::after { content: '▸'; }

/* Ссылка «свернуть» появляется по наведению: она нужна раз в месяц, а
   висит рядом с тем, чем пользуются каждый день */
.cab__fold {
    display: block;
    padding: 2px 12px 8px 22px;
    font-size: 12px;
    color: var(--muted);
    opacity: 0;
}

.cab__folder:hover .cab__fold, .cab__fold:focus { opacity: 1; }

@media (max-width: 900px) {
    .cab__fold { opacity: 1; }
}

/* ── подсказка на графике по дням ─────────────────────────────────────────── */

.daychart { position: relative; }

/* Полосы наведения прозрачны, но должны ловить курсор: fill:none его не ловит */
.dchart__hit { fill: transparent; }

.dchart__cursor { stroke: var(--ink-soft); stroke-width: 1; stroke-dasharray: 3 3; }

/* Подписи делений: мельче дат и приглушены — это опора для глаза, а не данные */
.dchart__scale { font-size: 11px; fill: var(--muted); }

.daychart__tip {
    position: absolute; transform: translateX(-50%);
    padding: 8px 12px; border-radius: var(--r-sm); pointer-events: none;
    background: var(--ink); color: #fff; font-size: 13px; line-height: 1.45;
    white-space: nowrap; z-index: 3;
}
.daychart__tip .muted { color: rgba(255, 255, 255, .65); }
.daychart__tip .is-up { color: #f3f2f2; }
.daychart__tip .is-down { color: #ff8a72; }

.daychart__trend { margin: 2px 0 14px; font-size: 15px; }
.daychart__trend-val { font-weight: 800; }
.daychart__trend-val.is-up { color: var(--green, #201e1d); }
.daychart__trend-val.is-down { color: var(--red); }

/* ДВЕ ЛИНИЯ — ДВА ЦВЕТА, а не один и тот же бледнее.
   Владелец сравнил с кабинетом Wildberries: там нынешняя неделя и прошлая
   нарисованы синим и розовым, и какая из них какая, видно без легенды.
   Пунктир у прошлой оставлен: цвет — для глаза, пунктир — для тех, кто цвет
   различает плохо. Сами цвета проверены на дальтонизм (tests/run-colors.php),
   а не подобраны на глаз: брендовый красный с золотым уже сливались. */
.daychart .dchart__line--0 { stroke: #201e1d; stroke-width: 2.5; }
.daychart .dchart__dot--0 { fill: #201e1d; }
.daychart .dchart__line--1 { stroke: #8f8b89; stroke-dasharray: 5 4; }
.daychart .dchart__dot--1 { fill: #8f8b89; display: none; }

/* Легенда под графиком: какого цвета что. Без неё вторую линию читают как
   «ещё какие-то деньги», а не как прошлый отрезок */
.daychart__legend { display: flex; gap: 18px; margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.daychart__legend i { display: inline-block; width: 14px; height: 3px; border-radius: 0; margin-right: 6px; vertical-align: middle; }
.daychart__legend .is-now i { background: #201e1d; }
.daychart__legend .is-was i { background: #8f8b89; }

/* Точки в подсказке — того же цвета, что линии: иначе строки «было/стало»
   приходится соотносить с графиком по памяти */
.daychart__tip-row i {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    margin-right: 7px; vertical-align: middle;
}
.daychart__tip-row i.is-now { background: #201e1d; }
.daychart__tip-row i.is-was { background: #8f8b89; }

/* ── выбор периода: набор списком, свои даты по требованию ────────────────── */

.period {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
    padding: 12px 14px; margin-bottom: 16px;
    background: var(--surface-soft); border-radius: var(--r-md);
}
.period__select {
    height: 38px; padding: 0 32px 0 12px; font: inherit; font-weight: 700;
    color: var(--ink); background: var(--surface); cursor: pointer;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
}
.period__own { display: inline-flex; align-items: center; gap: 8px; }
.period__own.is-off { display: none; }
.period__own input { height: 38px; }
.period__what { margin-left: auto; color: var(--muted); font-size: 13.5px; }

/* Выбор периода стоит в правом углу строки с вкладками графика — там же, где
   он у Wildberries. Отдельной полосой над карточкой он занимал место и висел
   в стороне от того, на что влияет */
.daychart__tabs { display: flex; align-items: center; gap: 4px; }
.daychart__tabs .period {
    margin: 0 0 0 auto; padding: 0; background: none; gap: 8px;
}
.daychart__tabs .period__what { display: none; }
.daychart__tabs .period__select { height: 34px; font-size: 14px; }

/* Третья линия — «неделю назад» на почасовом графике. Цвет проверен на
   дальтонизм вместе с двумя первыми (tests/run-colors.php) */
.daychart .dchart__line--2 { stroke: #ec3013; stroke-dasharray: 2 3; opacity: .8; }
.daychart .dchart__dot--2 { display: none; }
.daychart__legend .is-old i { background: #ec3013; }
.daychart__tip-row i.is-old { background: #ec3013; }

/* Столбики в узкой колонке: пары «ваша цена — вам за товар» по неделям.
   Высота задаётся процентом от самой большой величины, поэтому график не
   зависит ни от ширины колонки, ни от размера шрифта */
.dbars { padding: 14px 16px 12px; }
.dbars__legend { flex-wrap: wrap; gap: 4px 12px; margin: 2px 0 12px; font-size: 12px; }
.dbars__legend > span { display: inline-flex; align-items: center; gap: 5px; }
.dbars__plot {
    display: flex; align-items: flex-end; justify-content: space-between; gap: 10px;
}
.dbars__week { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1 1 0; min-width: 0; }
/* ВЫСОТА ЗАДАНА ЗДЕСЬ, И ЭТО ВАЖНО: столбики заданы долей от высоты пары, а
   доля от «сколько получится» — это ноль. Один раз уже получил пустой график
   ровно поэтому.
   Пара стоит вплотную: смысл графика в зазоре между своей ценой и выплатой,
   а разнесённые столбики этот зазор прячут */
.dbars__pair { display: flex; align-items: flex-end; gap: 3px; height: 112px; width: 100%; justify-content: center; }
.dbars__bar { display: block; width: 12px; border-radius: 0; }
.dbars__bar--0 { background: #201e1d; }
.dbars__bar--1 { background: #ec3013; }
.dbars__x { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
/* Итог столбиком, а не строкой: в колонке 240 точек «Последняя неделя» и
   сумма не помещаются рядом и ломаются каждая пополам */
.dbars__itog {
    display: flex; flex-direction: column; gap: 1px;
    margin: 12px 0 0; font-size: 12.5px;
}
.dbars__itog b { font-size: 18px; font-weight: 800; white-space: nowrap; }

/* Советы в колонке: тот же текст, что был внизу страницы, но набранный так,
   чтобы читаться в 240 точек. Факты — отдельной приглушённой строкой, вывод и
   ссылка — обычным текстом: глаз цепляется за «не хватает», а не за проценты */
.sovety { padding: 14px 16px 12px; }
.sovety__list { gap: 8px; margin: 10px 0 0; }
.sovety__list li { padding: 11px 13px; font-size: 13.5px; line-height: 1.45; }
.sovety__fakt { display: block; font-size: 12.5px; margin: 2px 0 4px; }
.sovety__note { font-size: 12px; line-height: 1.5; margin: 10px 0 0; }
.sovety__kak { margin-top: 10px; }
.sovety__kak summary { font-size: 12.5px; cursor: pointer; }

/* ФРОД-РАДАР В ЛЕВОЙ КОЛОНКЕ.
   Один случай крупно, остальные — стрелками. Красная полоса слева, как у
   ошибки входа: цвет читается и при дальтонизме, а сам блок не кричит —
   это повод посмотреть, а не сообщение о поломке. */
.radar { border-left: 3px solid var(--red); padding: 14px 16px 12px; }
.radar__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.radar__title { font-size: 15px; font-weight: 800; }
.radar__skolko { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* Виден только текущий случай: стопка из шести в узкой колонке не читается */
.radar__case { display: none; padding-top: 10px; }
.radar__case.is-on { display: block; }

.radar__glavnoe { font-size: 14.5px; line-height: 1.35; }
.radar__den { color: var(--muted); }
.radar__art { font-size: 13px; margin-top: 3px; }
.radar__art code { font-size: 12.5px; }
.radar__kuda { font-size: 12.5px; margin-top: 3px; line-height: 1.4; }
/* Почему это странно — единственная строка, которую нужно прочитать */
.radar__pochemu { font-size: 13px; font-weight: 700; margin-top: 7px; line-height: 1.4; }
.radar__case.is-silno .radar__pochemu { color: var(--red-dark); }
.radar__forma { margin-top: 9px; }

.radar__nav { display: flex; gap: 6px; margin-top: 10px; }
.radar__nav button {
    width: 34px; height: 30px; padding: 0; cursor: pointer;
    font: inherit; font-size: 15px; line-height: 1;
    color: var(--ink); background: var(--surface); border: 2px solid var(--ink);
}
.radar__nav button:hover:not(:disabled) { background: var(--ink); color: var(--surface); }
.radar__nav button:disabled { opacity: .3; cursor: default; }
.radar__esche { font-size: 12px; margin: 8px 0 0; }


/* ══ Главная в две колонки (макет «Табло») ═══════════════════════════════════
   Первый экран отвечает на вопрос «сколько это стоит»: расчёт слева, цены
   справа. Щель в 2 точки закрашена чернилами — так видна сетка, как во всём
   остальном оформлении. */

.lead {
    display: grid;
    grid-template-columns: 360px minmax(0, 1fr);
    gap: 2px;
    background: var(--ink);
    border-bottom: 2px solid var(--ink);
}

.lead__side { background: var(--yellow-wash); padding: 36px 32px; }
.lead__main { background: var(--surface); padding: 36px 40px; min-width: 0; }

.lead__kicker {
    display: block;
    font-size: 12px; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: var(--muted);
}

.lead__title { font-size: 30px; line-height: 1.1; margin: 14px 0 24px; }

/* Поля в колонку: 360 точек в ряд не делятся */
.finder--col {
    display: flex; flex-direction: column; gap: 18px;
    background: none; border: 0; padding: 0; box-shadow: none;
}

.finder__pair { display: grid; grid-template-columns: 1fr 88px; gap: 12px; }

.btn--block { width: 100%; }

.lead__note { margin: 4px 0 0; font-size: 14px; line-height: 1.5; color: var(--muted); }

.lead__head { margin-bottom: 20px; }
.lead__head h2 { font-size: 22px; }
.lead__head .section__sub { margin: 8px 0 0; }

/* График в правой колонке уже стоит в рамке страницы — своя рамка ему не нужна */
.chart-card--flat { border: 0; box-shadow: none; padding: 0; }

/* ── полоса чисел ─────────────────────────────────────────────────────────── */

.stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 2px;
    background: var(--ink);
    border: 2px solid var(--ink);
}

.stats__cell { background: var(--surface); padding: 22px 24px; display: flex; flex-direction: column; gap: 4px; }
.stats__cell strong { font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.stats__cell span { font-size: 14px; color: var(--muted); }

/* ── выгрузка в Excel ─────────────────────────────────────────────────────── */

/* Кнопка над таблицей, выбор колонок свёрнут: большинству нужны все, а
   восемнадцать галочек над отчётом загораживают сам отчёт */
.vygruzka { display: flex; align-items: baseline; gap: 16px; margin: 0 0 14px; flex-wrap: wrap; }

.vygruzka__knopka {
    font-size: 14px; font-weight: 700; color: var(--ink);
    text-decoration: none; border-bottom: 2px solid var(--red); padding-bottom: 1px;
}
.vygruzka__knopka:hover { color: var(--red); }

.vygruzka__vybor summary { font-size: 13.5px; cursor: pointer; }

.vygruzka__form { margin-top: 10px; padding: 12px; border: 2px solid var(--ink); }

.vygruzka__spisok {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 6px 14px;
}

.vygruzka__kolonka { display: flex; align-items: center; gap: 7px; font-size: 13.5px; }
.vygruzka__kolonka input { accent-color: var(--red); }

.vygruzka__note { font-size: 12.5px; margin: 10px 0; }

/* ── забор груза от адреса ────────────────────────────────────────────────── */

/* Галочка с ценой в одной строке: цена — часть решения, а не сноска под ним */
.field--zabor { display: flex; flex-direction: column; gap: 6px; }

.zabor__check {
    display: flex; align-items: center; gap: 8px;
    font-size: 14.5px; font-weight: 650; cursor: pointer;
}
.zabor__check input { width: 17px; height: 17px; accent-color: var(--red); cursor: pointer; }

/* Цена прижата вправо, чтобы взгляд ловил её сразу, не читая подпись */
.zabor__cena { margin-left: auto; font-weight: 800; }
.zabor__free { margin-left: auto; font-weight: 800; color: var(--red); }

.zabor__addr {
    width: 100%; padding: 10px 12px;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    font: inherit; font-size: 14.5px;
}

.zabor__sovet { font-size: 12.5px; line-height: 1.4; }

/* ── ближайшие выезды на главной ──────────────────────────────────────────── */

/* Светлым списком, а не тёмным табло: тёмный блок в этой колонке читается
   чужой вставкой. Строки-ссылки, потому что человек пришёл за ценой, а не
   за справкой. */

.vyezdy { margin-top: 28px; }
.vyezdy__title { font-size: 19px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 4px; }
.vyezdy__sub { font-size: 14px; margin: 0 0 14px; }

.vyezdy__list { border-top: 2px solid var(--ink); }

.vyezd {
    display: grid;
    grid-template-columns: 84px 1fr auto;
    align-items: baseline;
    gap: 14px;
    padding: 11px 4px;
    border-bottom: 1px solid rgba(32, 30, 29, .14);
    text-decoration: none; color: var(--ink);
}

/* Первая строка нового дня отделена сильнее: без этого восемь строк подряд
   читаются одним куском, и непонятно, где кончается день */
.vyezd--first { border-top: 1px solid rgba(32, 30, 29, .14); margin-top: -1px; }

.vyezd:hover { background: rgba(32, 30, 29, .05); }

.vyezd__date { font-size: 13px; color: var(--muted); white-space: nowrap; }
.vyezd__date b { font-size: 14px; color: var(--ink); font-weight: 700; }

.vyezd__dest { min-width: 0; }
.vyezd__dest b { font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.vyezd__mp { font-size: 13px; color: var(--muted); margin-left: 7px; }

.vyezd__state { font-size: 13px; font-weight: 700; white-space: nowrap; }

/* Цветом отмечаем только то, что требует действия: приём закрывается сегодня.
   Раскрасить все состояния значит не выделить ни одного */
.vyezd__state--soon { color: var(--red); }
.vyezd__state--open { color: var(--muted); font-weight: 650; }
.vyezd__state--closed,
.vyezd__state--flying,
.vyezd__state--done { color: var(--muted); font-weight: 650; }

.vyezdy__more {
    display: inline-block; margin-top: 12px;
    font-size: 14px; font-weight: 700; color: var(--ink);
    text-decoration: none; border-bottom: 2px solid var(--red);
}

/* На телефоне дата уезжает над строкой: в три колонки название склада
   сжимается до двух букв в строке */
@media (max-width: 560px) {
    .vyezd { grid-template-columns: 1fr auto; gap: 4px 10px; }
    .vyezd__date { grid-column: 1 / -1; }
    .vyezd__date:empty { display: none; }
}

/* ── три шага ─────────────────────────────────────────────────────────────── */

.steps {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2px;
    background: var(--ink);
    border-bottom: 2px solid var(--ink);
}

.steps__cell { background: var(--surface); padding: 32px 40px; }
.steps__num { font-size: 13px; font-weight: 800; letter-spacing: .14em; color: var(--red); }
.steps__cell h3 { font-size: 20px; margin: 10px 0 8px; }
.steps__cell p { margin: 0; font-size: 15px; line-height: 1.5; color: var(--ink-soft); }

@media (max-width: 900px) {
    .lead { grid-template-columns: 1fr; }
    .stats { grid-template-columns: repeat(2, 1fr); }
    .steps { grid-template-columns: 1fr; }
    .lead__side, .lead__main { padding: 24px 20px; }
}


/* ══ Вход и регистрация ══════════════════════════════════════════════════════
   Одна колонка по центру: на этой странице нет ничего, кроме формы, и растягивать
   её на всю ширину значит заставлять глаз ходить от подписи к полю через полэкрана. */

.auth { padding: 56px 0 64px; }

.auth__box { max-width: 460px; margin: 0 auto; padding: 0 24px; }
.auth__box h1 { font-size: 28px; }
.auth__lead { margin: 10px 0 28px; font-size: 14px; color: var(--muted); }

/* Разделитель перед регистрацией: без него кнопка читается как часть формы входа */
.auth__signup {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    margin-top: 28px; padding-top: 22px; border-top: 2px solid var(--ink);
}
.auth__signup span { font-size: 14px; color: var(--ink-soft); }
.auth__signup .btn { margin-left: auto; }

/* ══ Страница брони ══════════════════════════════════════════════════════════ */

.booking { padding: 48px 0 64px; }
.booking__box { max-width: 640px; margin: 0 auto; padding: 0 24px; }
.booking__box h1 { font-size: 28px; margin-bottom: 24px; }

/* Факты брони: два столбца, обведённые сверху и снизу — это выписка, а не карточка */
.facts {
    display: grid; grid-template-columns: 1fr 1fr; gap: 22px 32px;
    margin: 0 0 24px; padding: 24px 0;
    border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
}
.facts dt { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.facts dd { margin: 4px 0 0; font-size: 17px; font-weight: 600; }

.hold-tag {
    display: inline-block; margin-bottom: 16px; padding: 4px 10px;
    background: var(--red); color: #fff;
    font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}

/* Оплата: сумма слева, действие справа — одной строкой */
.pay {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin: 0 0 24px; padding: 20px 24px; background: var(--surface-soft);
}
.pay__sum { font-size: 22px; font-weight: 800; }

/* ══ Табло выездов ═══════════════════════════════════════════════════════════ */

.board__title {
    align-items: flex-end;
    padding-bottom: 22px; margin-bottom: 22px;
    border-bottom: 2px solid var(--ink);
}
.board__title h1 { font-size: 28px; }

@media (max-width: 560px) {
    .facts { grid-template-columns: 1fr; gap: 16px; }
    .auth__signup .btn { margin-left: 0; width: 100%; }
}


/* ══ Правки первого экрана главной ═══════════════════════════════════════════ */

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

/* Начало недели — тонкая линия: тридцать столбиков подряд читаются штрихкодом */
.bar--week { border-left: 1px solid var(--line); }

/* Каждая вторая дата прячется, когда дней много: подписи слипались в кашу */
.chart--dense .bar--skip .bar__day b { visibility: hidden; }
.chart--dense .bar--skip .bar__day { color: transparent; }

/* Выбранный день — чёрное поле: это итог расчёта, а не ещё одна карточка */
.pick {
    background: var(--ink); border: 0; color: #fff;
    margin: 22px 0 0; padding: 24px 26px;
}
.pick__date { color: rgba(255,255,255,.62); }
.pick__price { color: #fff; }
.pick__why { color: rgba(255,255,255,.82); }
.pick__why em { color: #ff8a72; font-style: normal; font-weight: 700; }
.pick .btn { background: var(--red); }
.pick .btn:hover { background: var(--red-dark); }

/* ── Ближайшие рейсы по направлению, под графиком ────────────────────────────
   Правая колонка обрывалась на середине экрана. Таблица отвечает на второй
   вопрос человека: «а когда машина физически едет». */
.trips { margin-top: 32px; }
.trips h3 { font-size: 17px; margin: 0 0 12px; }
.trips .table th, .trips .table td { padding: 11px 12px; }

/* Левая колонка: поля плотнее, пояснение ближе к кнопке */
.finder--col { gap: 15px; }
.lead__note { font-size: 13.5px; }

/* ══ Перелистывание дней ═════════════════════════════════════════════════════
   Дней в разметке все сорок с лишним — они нужны и поиску, и человеку без
   скрипта, который просто прокрутит полосу пальцем. Стрелки — надстройка:
   без скрипта они скрыты, потому что нажимать на них было бы некуда. */

.chart-nav {
    display: flex; align-items: center; gap: 8px;
    margin: 0 0 6px; justify-content: flex-end;
}
.chart-nav__note { margin-right: auto; font-size: 13px; color: var(--muted); }
.chart-nav button {
    width: 38px; height: 34px; padding: 0; cursor: pointer;
    font: inherit; font-size: 16px; line-height: 1;
    color: var(--ink); background: var(--surface);
    border: 2px solid var(--ink);
}
.chart-nav button:hover:not(:disabled) { background: var(--ink); color: var(--surface); }
/* Упёрлись в край — кнопка гаснет, а не молчит в ответ на нажатие */
.chart-nav button:disabled { opacity: .3; cursor: default; }

/* На телефоне столбик в шестьдесят точек оставляет на экране три дня — этого
   мало, чтобы вообще что-то сравнить. Ужимаем до сорока: помещается неделя */
@media (max-width: 860px) {
    .bar { width: 44px; }
    .bar__fill { width: 38px; }
    .chart { height: 150px; }
    .chart-nav__note { display: none; }
}

/* Таблица выездов должна умещаться на первом экране целиком: обрезанная
   снизу строка читается как «дальше ничего нет», хотя дальше есть */
.trips .table th, .trips .table td { padding: 9px 14px; }
.trips h3 { margin-bottom: 4px; }

/* ─────────────────────────────────────────────── Раздел ФБС

   СКЛАДЫ — СТРОКИ ТАБЛИЦЫ ПО ВИДУ, НО ФОРМЫ ПО СУТИ.

   Сначала это были карточки с рамкой у каждой. Владелец посмотрел на пять
   таких коробок подряд и сказал: «выглядит дешево» — и был прав: в кабинете
   всё остальное это таблицы со сплошной линией снизу, а тут вдруг пять
   отдельных ящиков.

   Настоящей таблицей сделать нельзя: форму не положить внутрь <tr>, браузер
   выносит её за пределы таблицы и поля перестают отправляться. Поэтому сетка
   повторяет вид таблицы — общая шапка, одинаковые колонки, линия снизу, — а
   каждая строка остаётся самостоятельной формой. */
.sklady { margin: 16px 0 24px; }

.sklady__shapka,
.sklad {
    display: grid;
    grid-template-columns: minmax(220px, 3fr) 180px;
    gap: 18px;
    align-items: center;
}

/* Шапка — как у обычной таблицы кабинета: мелкие прописные, приглушённые */
.sklady__shapka {
    padding: 12px 4px;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .03em;
    border-bottom: 2px solid var(--ink);
}

.sklad {
    padding: 14px 4px;
    border-bottom: 2px solid var(--ink);
}

.sklad__imya { display: grid; gap: 2px; }
.sklad__imya .muted { font-size: 13px; }

/* Подпись рядом с рубильником видна только на узком экране: в широком её роль
   играет шапка таблицы, и дублировать надпись в каждой строке значит
   превратить таблицу обратно в набор карточек */
.sklad__gal { display: flex; gap: 10px; align-items: center; cursor: pointer; }
.sklad__gal span { display: none; }

/* Кнопка одна на весь список и стоит под ним: настройку складов меняют
   целиком, и пять кнопок в строках означали пять шансов уйти со страницы,
   сохранив половину */
.sklady + button { margin-top: 18px; }

/* ─── Экран сборки: поле сканера главное на странице, и это видно

   Сканер это клавиатура: он «печатает» код и жмёт Enter. Значит поле должно
   быть крупным, в фокусе и первым — от человека не требуется ничего, кроме
   как поднести сканер к товару. */
.sborka__skan {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 12px;
    align-items: end;
    margin: 18px 0 10px;
    max-width: 720px;
}

.sborka__skan label {
    grid-column: 1 / -1;
    font-size: 12.5px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: .03em;
}

/* Крупный моноширинный ввод: длинный штрихкод читается посимвольно, когда
   надо сверить его глазами с наклейкой на коробке */
.sborka__skan input {
    font-size: 22px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: .04em;
    padding: 12px 14px;
}

/* Фотография в списке сборки: с ноготь величиной, но этого хватает, чтобы
   узнать коробку в руках. Ячейка держит ширину даже без картинки — иначе
   строки с фото и без него разъезжаются по вертикали */
.table--sborka td { vertical-align: middle; }

.sbor__foto { width: 56px; padding-right: 0; }
.sbor__foto a { display: block; line-height: 0; }
.sbor__foto img { display: block; width: 56px; height: 56px; object-fit: contain; }

/* Название — ссылка на карточку маркетплейса, но выглядит как обычный
   заголовок строки: подчёркивание у каждой строки списка превратило бы
   таблицу в синее полотно. Подчёркивается под курсором */
.sbor__imya { color: inherit; text-decoration: none; }
.sbor__imya:hover strong,
.sbor__imya:focus strong { text-decoration: underline; }

.sbor__net {
    display: block; width: 56px; height: 56px;
    background: var(--surface-soft); border: 2px solid var(--line);
}

/* ── сборка: шапка списка с переключателем сортировки ─────────────────────────
   Заголовок слева, три режима сортировки справа — над колонкой «Ждёт», как
   просил владелец. Кнопки в стиле переключателя месяцев: активная — жёлтая. */
.sborka__shapka { margin-bottom: 12px; }
.sborka__shapka h3 { margin: 0; }

/* Панель над списком: поиск слева (тянется), сортировка справа — одной ровной
   строкой; на узком экране складывается в столбик сама */
.sborka__panel {
    display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px;
    margin: 0 0 16px;
}
.sborka__sort { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.sborka__sort label { font-size: 13px; color: var(--muted); white-space: nowrap; }
.sborka__sort select, .sborka__filtr-pole select {
    height: 44px; padding: 0 34px 0 12px; font-size: 15px; font-weight: 550;
    color: var(--ink); background: var(--surface); border: 2px solid var(--ink);
    border-radius: var(--r-sm); appearance: none; cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1l5 5 5-5' stroke='%23767d88' stroke-width='2' fill='none' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat; background-position: right 12px center;
}
.sborka__sort select:focus, .sborka__filtr-pole select:focus {
    outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(255, 214, 10, .55);
}

/* ФИЛЬТР — один компактный блок (выпадающий), а не россыпь. */
.sborka__filtr { position: relative; flex: 0 0 auto; }
.sborka__filtr-knopka {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    list-style: none; height: 44px; padding: 0 14px; box-sizing: border-box;
    font-size: 15px; font-weight: 550; color: var(--ink);
    background: var(--surface); border: 2px solid var(--ink); border-radius: var(--r-sm);
}
.sborka__filtr-knopka::-webkit-details-marker { display: none; }
.sborka__filtr-knopka::after {
    content: '▾'; font-size: 10px; color: var(--muted); margin-left: 2px;
}
.sborka__filtr[open] > .sborka__filtr-knopka { box-shadow: 0 0 0 3px rgba(255, 214, 10, .55); }
.sborka__filtr-metka {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
    font-size: 11px; font-weight: 800; color: #fff; background: #d92d20; border-radius: 9px;
}
.sborka__filtr-pop {
    position: absolute; z-index: 30; top: calc(100% + 6px); left: 0;
    min-width: 240px; display: flex; flex-direction: column; gap: 12px;
    padding: 14px; background: var(--surface); border: 2px solid var(--ink);
    border-radius: var(--r-sm); box-shadow: 0 10px 30px rgba(0, 0, 0, .12);
}
.sborka__filtr-pole { display: flex; flex-direction: column; gap: 5px; }
.sborka__filtr-pole > span { font-size: 13px; color: var(--muted); }
.sborka__filtr-pole select { width: 100%; }
.sborka__filtr-knopki { display: flex; gap: 8px; margin-top: 2px; }
.sborka__filtr-knopki .btn { flex: 1 1 auto; }

/* ── Ozon: деление многотоварного заказа на отдельные этикетки ─────────────── */
.ozon-razdel { margin: 6px 0 22px; }
.ozon-razdel > h3 { margin: 0 0 4px; }
.ozon-razdel__zakaz {
    border: 2px solid var(--line); border-radius: var(--r-sm);
    padding: 12px 14px; margin: 10px 0; background: var(--surface);
}
.ozon-razdel__shapka {
    display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline;
    margin-bottom: 6px;
}
.ozon-razdel__spisok { margin: 0 0 10px; padding-left: 0; list-style: none; }
.ozon-razdel__spisok li { padding: 2px 0; font-size: 13.5px; }
.ozon-razdel__spisok code { margin-left: 2px; }

/* Отменённые Ozon — компактный список «не собирать» */
.ozon-otmena { margin: 6px 0 22px; padding-left: 0; list-style: none; }
.ozon-otmena li { padding: 3px 0; font-size: 13.5px; }

/* Кнопка печати этикетки ячейки — прямо в строке списка ячеек, справа */
.priyomka > summary .yach-pech { float: right; margin: -2px 0 0 8px; }

/* Форма «убрать из ячейки» — компактно в строке состава */
.yach-ubrat { display: flex; gap: 6px; align-items: center; }
.yach-ubrat input[type="number"] { width: 60px; padding: 6px; }

/* Значок Честного знака — как в МПФИТ: маленький, жёлтый, рядом с названием.

   ЗНАЧКОМ, А НЕ КОЛОНКОЙ. Товаров с маркировкой единицы, а колонка занимала
   место в каждой строке и у всех стояла прочерком. */
.chz {
    display: inline-block;
    background: #ffd60a;
    color: var(--ink);
    font-size: 11px; font-weight: 900; letter-spacing: .04em;
    padding: 2px 5px;
    vertical-align: middle;
}

/* Значки площадок — как просил владелец: «ВБ фиолетовая, озон синий».
   Ставятся у строки в общих списках: поток один, а площадки разные */
.pl {
    display: inline-block;
    font-size: 10.5px; font-weight: 900; letter-spacing: .04em;
    padding: 2px 6px; margin-right: 6px;
    vertical-align: middle; color: #fff; white-space: nowrap;
}
.pl--wb { background: #7b2fbe; }
.pl--ozon { background: #005bff; }

/* Товар в составе отправления Ozon: маленькое фото и имя в строку */
.ozon__tovar { display: flex; gap: 8px; align-items: center; padding: 2px 0; }
.ozon__tovar img { flex: none; }

/* Кнопки очереди печати стоят в строку: перепечатать и вернуть — одна пара
   действий об одной этикетке */
.ochered__vernut { display: inline-block; margin-left: 8px; }

/* «В наличии N» в очереди сборки: вещь уже лежит на полке, брать можно сейчас.
   Той же плашкой, что «хватит» в заказе — это одна и та же хорошая новость */
/* НАБОР ПЕРЕД ЭТИКЕТКОЙ — состав отправления со счётчиком по каждой позиции.
   Владелец: «либо сканируем штрихкоды товаров из комплекта, либо этикетка не
   выезжает, пока не отсканированы все». Надпись не защищает — защищает счётчик,
   который на глазах доходит до полного и только тогда отпускает печать. */
.sbor__nabor {
    margin: 6px 0 2px; padding: 8px 10px;
    background: #fff; border: 1px solid #f0c9c0; border-radius: 8px;
    max-width: 560px;
}
.sbor__nabor-shapka { font-size: 11.5px; font-weight: 700; color: #a82a12; margin-bottom: 6px; }
.sbor__nabor-str {
    display: flex; align-items: center; gap: 8px;
    font-size: 12.5px; padding: 3px 0; color: var(--ink);
}
.sbor__nabor-str + .sbor__nabor-str { border-top: 1px solid #f4f7fa; }
.sbor__nabor-str code { font-size: 11px; color: #6a7480; }
.sbor__nabor-str.is-ok { color: #6a7480; }
.sbor__nabor-schet {
    flex: 0 0 auto; min-width: 34px; text-align: center;
    font-weight: 800; font-size: 12px; padding: 1px 5px; border-radius: 5px;
    background: #fde3de; color: #a82a12;
}
.sbor__nabor-str.is-ok .sbor__nabor-schet { background: var(--best-wash); color: var(--best-hover); }
.sbor__nabor-sbros {
    margin-top: 6px; padding: 0; border: 0; background: none;
    font-size: 11.5px; color: #6a7480; text-decoration: underline; cursor: pointer;
}
.sbor__nabor-sbros:hover { color: var(--ink); }

/* «В отправлении 2 шт» — заголовок этого блока: сколько всего штук и позиций. */
.sbor__mnogo {
    display: inline-block;
    background: #fde3de; color: #a82a12;
    font-size: 11px; font-weight: 800; letter-spacing: .02em;
    padding: 2px 6px; margin-left: 4px;
    vertical-align: middle; white-space: nowrap;
}

/* Срок отгрузки Ozon под временем ожидания: обычный — серой подписью,
   прошедший — красным, как и само «ждёт давно» (16 сент 2026). */
.sbor__srok {
    font-size: 11px; color: #6a7480; white-space: nowrap; margin-top: 2px;
}
.sbor__srok--proshyol { color: #a82a12; font-weight: 700; }

.vnalichii {
    display: inline-block;
    background: var(--best-wash); color: var(--best-hover);
    font-size: 11px; font-weight: 700; letter-spacing: .02em;
    padding: 2px 6px; margin-left: 4px;
    vertical-align: middle; white-space: nowrap;
}

/* АДРЕС ЯЧЕЙКИ — отдельной строкой под названием, всегда на одном месте и
   заметно (владелец: «в строку не влезает; перенеси ниже, пожирнее»). Чип с
   лёгким фоном; подпись «Ячейка» приглушена, сам код — жирный. */
.sbor__adres {
    display: inline-block; margin-top: 5px; padding: 2px 9px;
    background: var(--surface-soft); border-radius: 6px;
    font-size: 13.5px; font-weight: 700; color: var(--ink);
    white-space: nowrap;
}
.sbor__adres-p { font-weight: 600; color: var(--muted); font-size: 12px; }

/* ЗАКАЗАН У ПОСТАВЩИКА — НОМЕР ПАРТИИ. Владелец: «под строчкой писать мелкими
   буквами, можно курсивом, РЦ и номер, чтобы я понимал, что этот товар заказан
   и в какой партии приедет». Мелко и курсивом, без фона: это справка, а не
   действие, и она не должна спорить с адресом ячейки за внимание. */
.sbor__partiya {
    margin-top: 3px;
    font-size: 12px; font-style: italic; line-height: 1.3;
    color: var(--muted); white-space: nowrap;
}

/* ОБЕСПЕЧЕНО С ПОЛКИ — СОБИРАТЬ СЕЙЧАС. Владелец: «подсвети зелёным те строки,
   товар под которые уже лежит; их и собираем в первую очередь». Зелёный, а не
   фирменный красный: тут он значит «готово, бери», а штука закреплена за этим
   заданием по FIFO — одна штука одному заданию, не двоится по нескольким. */
/* Подсветка «на полке» — в фирменной гамме (светло-красная строка), без
   зелёного: владелец «зелёный на нашем сайте ни туда ни сюда». Плашка
   .vnalichii и так фирменная красная по умолчанию — отдельно не красим. */
.sbor--nalichie td { background: var(--best-wash); }

/* ── СЕТКА ЯЧЕЕК ХРАНЕНИЯ ──────────────────────────────────────────────────
   Владелец: «как у MP Fit — большая сетка, занятые одним цветом, свободные
   другим, наглядно, без лишнего шума». Занятые — зелёные плитки, по клику
   раскрывают состав карточкой; свободные — светлые. */
.ysvod {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
    margin: 6px 0 4px; font-size: 14px;
}
.ysvod__zan strong { color: var(--best-hover); }
.ysvod__svob { color: #8a8a8a; }
.ydot {
    display: inline-block; width: 11px; height: 11px; border-radius: 3px;
    vertical-align: -1px; margin-right: 2px;
}
.ydot--zan { background: var(--best); }
.ydot--svob { background: #dcdce0; }
.ysvod__hint { margin: 0 0 14px; }

.yryad { margin: 0 0 18px; }
.yryad__imya {
    font-weight: 700; font-size: 13px; letter-spacing: .03em;
    text-transform: uppercase; color: var(--ink);
    margin: 0 0 8px; padding-bottom: 4px; border-bottom: 1px solid #ececec;
}
.yryad__imya .muted { font-weight: 400; text-transform: none; margin-left: 6px; }

/* Сетка ряда — стопкой линий: каждая линия (первый номер адреса) своей
   строкой, друг над другом, как коробки на палете. Владелец: «на европалете
   4 линии по 4 коробки — изобрази стопками». */
.ysetka { display: flex; flex-direction: column; gap: 7px; }
.ylinia { display: flex; align-items: stretch; gap: 7px; flex-wrap: wrap; }
.ylinia__n {
    flex: 0 0 22px; display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700; color: #b8b8bd;
}

/* Сетка-склад на CSS-grid: колонки — стеллажи (слева направо), строки — ярусы
   (верхний сверху, первый на полу). Grid даёт РАСТЯГИВАНИЕ: объединённая ячейка
   занимает несколько слотов (grid-column/row span) — одной «длинной» плиткой.
   Владелец: «покажи большую ячейку одной длинной плиткой». */
.ysetka--grid {
    display: grid; --yc: 66px; gap: 7px; justify-content: start;
    grid-auto-rows: minmax(50px, auto);
}
.ysetka--grid .ycell { width: auto; height: 100%; flex: none; }
.ysetka--grid .ycell > summary { height: 100%; }

/* Объединённая («большая») ячейка: рамка потолще и значок ×N */
.ycell--big > summary { box-shadow: inset 0 0 0 2px var(--best); }
.ycell--big.ycell--free > summary { box-shadow: inset 0 0 0 2px #b9b9bf; }
.ycell__big {
    display: block; font-size: 10px; font-weight: 800;
    color: var(--best-hover); line-height: 1;
}

/* Плитка ячейки: фиксированная ширина — столбцы линий встают друг под друга */
.ycell {
    flex: 0 0 66px; width: 66px;
    border-radius: 9px; min-height: 50px; position: relative;
}
.ycell__code { display: block; font-size: 11px; letter-spacing: .02em; }
.ycell__qty { display: block; font-size: 17px; font-weight: 800; line-height: 1.1; }

/* Общий вид плитки-summary: одинаковый размер у занятой и свободной */
.ycell > summary {
    list-style: none; cursor: pointer;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 1px; min-height: 50px; padding: 4px; border-radius: 9px;
    text-align: center; transition: background .12s, box-shadow .12s;
}
.ycell > summary::-webkit-details-marker { display: none; }

/* Свободная — светлая, тихая */
.ycell--free > summary {
    background: #f5f5f6; border: 1px dashed #dcdce0; color: #a6a6ab;
}
.ycell--free > summary:hover { background: #ececee; }
.ycell--free[open] > summary { border-style: solid; border-color: #b9b9bf; color: #6a6a70; }

/* Занятая — зелёная, ярче */
/* Занятая — в фирменной гамме (светло-красный), а не зелёная: владелец
   «зелёный на нашем сайте ни туда ни сюда». Открытая — насыщенный красный. */
.ycell--busy > summary {
    background: var(--best-wash); border: 1px solid #f0cbc3; color: var(--best-hover);
}
.ycell--busy > summary:hover { background: #f7ddd7; }
.ycell--busy[open] > summary {
    background: var(--best); color: #fff; border-color: var(--best);
    box-shadow: 0 3px 10px rgba(236, 48, 19, .26);
}

/* Карточка состава — всплывает под плиткой, не расталкивая сетку */
.ycell__pop {
    position: absolute; z-index: 30; left: 0; top: calc(100% + 6px);
    min-width: 300px; max-width: 380px;
    background: #fff; border: 1px solid #e2e2e4; border-radius: 12px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .14); padding: 12px; text-align: left;
}
.ycell__pop-head {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0;
}
.ycell__pop-head .yach-pech { margin-left: auto; }
.ycell__tabl { margin: 0; width: 100%; }
.ycell__tabl td { vertical-align: middle; }
.ycell__tabl .yach-ubrat { display: flex; gap: 4px; align-items: center; }
.ycell__tabl .yach-ubrat input { width: 56px; }

/* Правый край ряда: карточку прижимаем к правому краю плитки, чтобы не
   выезжала за экран (последние столбцы сетки) */
.ysetka .ycell--busy:nth-child(n) .ycell__pop { max-width: min(380px, 86vw); }

@media (max-width: 640px) {
    .ycell { flex-basis: 58px; width: 58px; }
    .ysetka--grid { --yc: 58px; }
    .ysetka--grid .ycell { width: auto; }
    .ycell__pop { position: fixed; left: 8px; right: 8px; min-width: 0;
        max-width: none; top: auto; }
}

/* ── ПОДСКАЗКИ «?» У ЗАГОЛОВКОВ ────────────────────────────────────────────
   Владелец: «навёл курсор — видно, что делать; страницу не перегружать».
   Маркер «?» открывает текст при наведении И при фокусе (на планшете — по
   тапу). Всё на CSS, без скрипта. */
.pods {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; margin-left: 6px; border-radius: 50%;
    background: var(--best-wash); color: var(--best-hover);
    font-size: 12px; font-weight: 700; line-height: 1; cursor: help;
    vertical-align: middle; position: relative; user-select: none;
    -webkit-user-select: none;
}
h2 .pods, h3 .pods { font-size: 11px; width: 17px; height: 17px; }
.pods:focus { outline: 2px solid var(--best); outline-offset: 1px; }
.pods__pop {
    position: absolute; z-index: 40; top: calc(100% + 8px); left: 0;
    width: max-content; max-width: min(320px, 80vw);
    background: var(--ink, #211f1d); color: #fff;
    font-size: 13px; font-weight: 400; line-height: 1.45; letter-spacing: 0;
    text-transform: none; text-align: left;
    padding: 9px 11px; border-radius: 9px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
    opacity: 0; visibility: hidden; transform: translateY(-3px);
    transition: opacity .12s, transform .12s, visibility .12s;
    pointer-events: none;
}
.pods__pop::before {
    content: ""; position: absolute; bottom: 100%; left: 12px;
    border: 6px solid transparent; border-bottom-color: var(--ink, #211f1d);
}
.pods:hover .pods__pop, .pods:focus .pods__pop {
    opacity: 1; visibility: visible; transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) { .pods__pop { transition: none; } }

/* ── БЛОК ИНСТРУКЦИИ ───────────────────────────────────────────────────────
   Владелец: «отдельный блок с примерами и разбором ситуаций». */
.instr__lead { max-width: 62ch; margin: 0 0 18px; }
.instr__blok { margin: 0 0 26px; }
.instr__cepochka { margin: 8px 0 0; padding-left: 22px; line-height: 1.7; }
.instr__case {
    background: #fff; border: 1px solid var(--line, #e9e9ea); border-radius: 12px;
    padding: 14px 16px 6px; margin: 12px 0;
}
.instr__case h4 {
    margin: 0 0 8px; font-size: 15px;
    padding-left: 24px; position: relative;
}
.instr__case h4::before {
    content: "▸"; position: absolute; left: 4px; top: 0;
    color: var(--best); font-weight: 700;
}
.instr__case ol { margin: 0 0 10px; padding-left: 22px; line-height: 1.6; }
.instr__case ol li { margin: 3px 0; }
.instr__case .muted { display: block; margin: 0 0 12px; }

/* ── ПОТЕНЦИАЛ ПО ТОВАРАМ: ставки и разбивка юнит-экономики ──────────────── */
.potstavki { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end;
    margin: 12px 0; }
.potstavki__p { display: flex; flex-direction: column; gap: 3px; font-size: 12px;
    color: var(--muted, #6a6a6a); }
.potstavki__in { display: flex; align-items: center; gap: 4px; }
.potstavki__in input { width: 72px; padding: 6px 8px; border: 1px solid var(--line, #d8d8dc);
    border-radius: 7px; font: inherit; font-size: 14px; }
.potstavki__in i { font-size: 11px; color: var(--muted, #9a9a9a); font-style: normal; }

/* Строка товара раскрывает разбивку по клику (details), без скрипта */
.unit-det > summary { cursor: pointer; list-style: none; }
.unit-det > summary::-webkit-details-marker { display: none; }
.unit-det > summary::before { content: "▸"; color: var(--best, #ec3013);
    font-weight: 700; margin-right: 6px; display: inline-block; }
.unit-det[open] > summary::before { transform: rotate(90deg); }
.unit-raz { width: auto; min-width: 260px; margin: 8px 0 4px 20px; font-size: 13px;
    border-collapse: collapse; }
.unit-raz td { padding: 3px 10px 3px 0; border: 0; }
.unit-raz td.num { text-align: right; }
.unit-raz__it td { border-top: 1px solid var(--line, #e6e6e8); padding-top: 6px; }

/* Коды не переносятся: артикул «RLF-203631», штрихкод и номер этикетки,
   разломанные пополам, читаются как два разных числа. Владелец: «сделаем так,
   чтобы всё влезало в одну строчку». Ячейка ожидания — по той же причине */
.table--sborka code { white-space: nowrap; }
.table--sborka td:last-child { white-space: nowrap; }

/* Заказ ждёт больше суток. Точного срока маркетплейс не присылает, поэтому
   отсечку выбрали мы — и на экране про это сказано прямо */
.zhdet--davno { color: var(--red); font-weight: 700; }

/* История приёмок: партия — строка с итогом, состав раскрывается на месте.
   Раскрытие обычным details: кабинет обязан работать и без скрипта */
.priyomki { display: grid; gap: 0; margin: 12px 0 26px; border: 2px solid var(--ink); }
.priyomka { border-bottom: 2px solid var(--ink); }
.priyomka:last-child { border-bottom: 0; }
.priyomka summary { cursor: pointer; padding: 12px 16px; font-size: 15px; }
.priyomka[open] summary { border-bottom: 1px solid var(--surface-soft); }
.priyomka .table-wrap { margin: 0; }
.priyomka .table td { border-bottom: 1px solid var(--surface-soft); }

/* Переключатель этапов FBS — как вкладки в кабинете WB: человек работает в
   двух кабинетах сразу, и одинаковое устройство означает, что учиться второму
   не надо */
.fbs-shagi {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 14px 0 20px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--ink);
}

/* ─── Поставки карточками, а не строкой таблицы

   Владелец про прежний вид: «он абсолютно не информативный, ничего не понятно,
   всё в кучу свалено». Таблица отвечала на вопрос «какие у поставки поля», а
   человеку нужен ответ на «что мне с ней сейчас делать» — и этот ответ не
   умещается в ячейку. */
.postavki { display: grid; gap: 16px; margin: 16px 0 18px; }

.postavka {
    border: 2px solid var(--ink);
    padding: 16px 18px 18px;
    background: var(--surface);
}

/* Готовая к отгрузке подсвечена: в списке из шести штук глаз должен сразу
   находить ту, с которой можно ехать */
.postavka--gotova { background: var(--best-wash); }

.postavka__shapka {
    display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap;
    margin-bottom: 10px;
}

.postavka__imya { font-size: 18px; font-weight: 750; }
.postavka__shapka .muted { font-size: 13px; }

.postavka__chuzhaya {
    margin-left: auto;
    font-size: 12px; font-weight: 700; color: var(--muted);
    border: 2px solid var(--line); padding: 2px 7px;
}

/* Факты в строку: их три, и каждый — короткая пара «что» и «сколько» */
.postavka__fakty {
    display: flex; flex-wrap: wrap; gap: 6px 28px;
    margin: 0 0 12px;
}

.postavka__fakty dt { font-size: 12px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: .03em; }
.postavka__fakty dd { margin: 0; font-size: 15px; font-weight: 650; }

/* Следующий шаг — единственная строка, ради которой открывают экран */
.postavka__shag { margin: 0 0 10px; font-size: 15px; font-weight: 600; }
.postavka__shag--ok { color: var(--best-hover); }
.postavka__shag--zhdet { color: var(--ink); }

/* Полоска говорит то же, что и строка, но её видно боковым зрением */
.postavka__polosa {
    height: 8px; background: var(--surface-soft);
    border: 2px solid var(--ink); margin-bottom: 12px;
}

.postavka__polosa span { display: block; height: 100%; background: var(--best); }

.postavka__akt { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.postavka__akt .sostav { flex: 1 1 100%; }

/* Готовность поставки: «всё собрано» и «без этикетки: N».

   ЦВЕТОМ ПОМЕЧЕНО ТОЛЬКО НЕСДЕЛАННОЕ. Красить зелёным готовое — значит
   разбавлять экран цветом там, где смотреть не на что: глаз должен цепляться
   за то, что осталось доделать, а не за то, что уже хорошо. */
.gotovo { color: var(--muted); }

.ostalos {
    color: var(--red);
    font-weight: 700;
}

/* Строка состава без этикетки подсвечена целиком: в списке из тридцати
   позиций взгляд ищет цветную полосу, а не читает каждую подпись */
.sostav--zhdet td { background: var(--best-wash); }

.sostav__stroka > td { padding-top: 0; border-bottom: 2px solid var(--ink); }
.sostav summary { cursor: pointer; padding: 6px 0; }
.sostav .table-wrap { margin: 8px 0 0; }
.sostav .table td { border-bottom: 1px solid var(--surface-soft); }
.sostav .sbor__foto { width: 40px; }
.sostav .sbor__foto img { width: 40px; height: 40px; }

/* Сколько штук удалось взять у поставщика. Поле короткое: там число от нуля
   до десятка, и растянутое на всю колонку оно бы врало про ожидаемое */
.zakaz__pole {
    width: 80px; height: 40px; padding: 0 10px;
    font: inherit; font-size: 16px; font-weight: 650; text-align: center;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink);
}

.zakaz__pole:focus { outline: none; box-shadow: 0 0 0 3px rgba(255, 214, 10, .55); }

/* Артикул под названием, а не хвостом за ним: в строке они сливаются в одну
   фразу, и глаз читает «Носки хлопковые женские, 5 пар Sofia NSK-5-36» */
.table--zakaz td .muted { display: block; }

/* «На полке» — хорошая новость, и она должна бросаться в глаза: ради неё
   человек и открыл экран, чтобы не купить лишнюю пачку */
.zakaz__est { color: var(--best-hover); }

.zakaz__hvatit {
    display: inline-block;
    background: var(--best-wash); color: var(--best-hover);
    font-size: 12.5px; font-weight: 700;
    padding: 3px 8px; white-space: nowrap;
}

/* Количество при приёмке стоит рядом с кнопкой, а не под полем сканера:
   сканер жмёт Enter сам, и до количества рука доходит только для пачки */
.priyom__skolko { display: flex; gap: 10px; align-items: center; }

/* Итог хранения — первое число в боковой карточке. Владелец пришёл сюда с
   вопросом «что у меня лежит», и отвечать на него таблицей, которую надо
   читать, значит не ответить */
.hran__itog {
    font-size: 20px; font-weight: 700;
    margin: 6px 0 4px;
}

/* Сумма полки — вторая строка итога хранения */
.hran__summa { font-size: 15px; font-weight: 650; margin: 2px 0 6px; }

/* Приёмка стоит в боковой колонке, под счётом — владелец показал стрелкой:
   «мне нужно, чтобы блок был здесь». Колонка узкая, поэтому поле сканера и
   количество складываются в столбик, а не жмутся в строку */
.hran__priyom {
    border: 2px solid var(--ink);
    padding: 16px 18px 18px;
}

.hran__priyom h3 { font-size: 16px; margin-bottom: 4px; }
.hran__priyom .sborka__skan { display: block; margin: 10px 0; max-width: none; }
/* ПОЛЕ ШТРИХКОДА ТЯНЕТСЯ ПО КОЛОНКЕ, А НЕ ПО СОДЕРЖИМОМУ.
   Без width поле берёт свою исходную ширину — около двадцати символов — и в
   узкой колонке вылезает за рамку: тринадцать цифр туда просто не помещаются.
   Заодно ужат кегль и разрядка, иначе штрихкод упирается в края */
.hran__priyom .sborka__skan input[type="text"] {
    width: 100%;
    font-size: 16px;
    letter-spacing: .01em;
    padding: 10px 12px;
}
.hran__priyom .priyom__skolko { margin-top: 10px; }
.hran__priyom .priyom__skolko .btn { flex: 1; padding: 0 14px; min-width: 0; }
.hran__priyom .priyom__skolko .zakaz__pole { width: 72px; flex: none; }
.hran__priyom .muted { margin-bottom: 0; font-size: 13px; }

/* ─── Боковая колонка FBS: этапы и сканер

   Владелец: «поле для сканирования и переключение между „К заказу“, „Сборка“
   и так далее перенеси сбоку, как ты делал в разделе хранения». Карточка та
   же, что у приёмки. Этапы столбиком: в узкой колонке пять кнопок в строку
   не помещаются и переламывались бы на середине слова. */
.fbs-bok {
    border: 2px solid var(--ink);
    padding: 16px 18px 18px;
}

.fbs-bok .fbs-shagi {
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding-bottom: 14px;
}

.fbs-bok .modes__btn { height: 34px; }

/* Число работы — у правого края кнопки: столбик чисел читается одним
   взглядом, а вразнобой после слов их пришлось бы выискивать */
.fbs-bok .fbs-shagi__n { margin-left: auto; padding-left: 10px; font-variant-numeric: tabular-nums; }

/* Выбор площадки над сканером: две кнопки во всю ширину колонки — их жмут
   перед каждой пачкой сканов, и целиться в маленькое было бы неудобно */
.fbs-bok .skan-pl { margin: 14px 0 0; }
.fbs-bok .skan-pl .modes__btn { flex: 1; justify-content: center; height: 34px; }

/* Размещение мышью: ячейка-select, количество и кнопка в одну строку */
.razm__row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.razm__row select { max-width: 140px; }
.razm__row .zakaz__pole { width: 64px; }

/* ─── Итоги склада отдельными квадратами

   Владелец просил вынести сумму и остаток из блока приёмки в отдельные
   карточки — «квадрат, просто цифра». Крупная цифра, под ней тихая подпись. */
.hran__kvadrat {
    border: 2px solid var(--ink);
    padding: 14px 16px;
    margin-top: 10px;
}
.hran__kvadrat-cifra { display: block; font-size: 24px; font-weight: 800; line-height: 1.1; }
.hran__kvadrat-podpis { display: block; margin-top: 4px; font-size: 13px; color: var(--muted); }

/* ─── Под-вкладки на «Хранении»: Товары · Приёмки

   Те же кнопки, что у этапов; панели прячет скрипт, без скрипта видны все. */
.hran-tabs {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 14px 0 18px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--ink);
}
.hran-pane--managed:not(.hran-pane--on) { display: none; }

/* Номер приёмки-документа: моноширинный ярлык рядом с датой */
.priyomka__nomer {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12.5px; color: var(--muted);
    margin-right: 8px;
}

/* ─── Вкладки внутри «Настроек» FBS

   Переключатель тех же кнопок, что у этапов; панели прячет скрипт, повесив
   на них класс managed. Без скрипта все панели видны подряд — панель
   настроек остаётся рабочей и так. */
.nastr-tabs {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 14px 0 20px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--ink);
}
a.nastr-tabs__stub { display: none; }
.nastr-pane--managed:not(.nastr-pane--on) { display: none; }
.nastr-pane + .nastr-pane { margin-top: 8px; }

/* ─── Мастер печати в настройках FBS

   Шаги гармошкой: человек делает один шаг за раз, а простыня из пяти
   инструкций сразу отпугивает. Команда — блоком с переносом: длинную строку
   надо видеть целиком, чтобы поверить кнопке «скопировать». */
.master { border: 2px solid var(--ink); margin: 0 0 10px; }
.master summary { cursor: pointer; padding: 10px 14px; font-size: 15px; }
.master[open] summary { border-bottom: 1px solid var(--surface-soft); }
.master p, .master ol, .master ul { margin: 10px 14px; }
.master ol, .master ul { padding-left: 20px; }
.master li { margin-bottom: 6px; }

.master--vlozh { margin: 10px 14px; border-width: 1px; }
.master--vlozh summary { font-size: 13.5px; }

.master__kod {
    display: block;
    padding: 10px 12px;
    background: var(--surface-soft);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12.5px;
    line-height: 1.5;
    word-break: break-all;
    user-select: all;
}

/* Кнопки в фирменных цветах площадок — просьба владельца, и цвета те же, что
   у бейджей WB/Ozon в списках: сборщик узнаёт площадку цветом раньше слова.
   Нажатая заливается цветом целиком, ненажатая держит цвет в рамке */
.skan-pl .skan-pl__wb { color: #7b2fbe; border-color: #7b2fbe; }
.skan-pl .skan-pl__ozon { color: #005bff; border-color: #005bff; }
.skan-pl .skan-pl__wb.modes__btn--on,
.skan-pl .skan-pl__wb.modes__btn--on:hover {
    background: #7b2fbe; border-color: #7b2fbe; color: #fff;
}
.skan-pl .skan-pl__ozon.modes__btn--on,
.skan-pl .skan-pl__ozon.modes__btn--on:hover {
    background: #005bff; border-color: #005bff; color: #fff;
}
/* Яндекс Маркет — жёлтый, и текст на нём остаётся тёмным: белым по жёлтому
   не читается, а кнопку сборщик ловит взглядом на бегу */
.skan-pl .skan-pl__yandex { color: #b07d00; border-color: #ffcc00; }
.skan-pl .skan-pl__yandex.modes__btn--on,
.skan-pl .skan-pl__yandex.modes__btn--on:hover {
    background: #ffcc00; border-color: #ffcc00; color: #14161a;
}

/* Поле и кнопки тянутся по колонке, как у приёмки: исходная ширина поля —
   около двадцати символов — вылезала бы за рамку */
.fbs-bok .sborka__skan { display: block; margin: 14px 0 8px; max-width: none; }
.fbs-bok .sborka__skan input {
    width: 100%;
    font-size: 16px;
    letter-spacing: .01em;
    padding: 10px 12px;
    margin-bottom: 10px;
}
.fbs-bok .sborka__skan .btn { width: 100%; }
.fbs-bok .muted { font-size: 13px; }
.fbs-bok .fbs__akt { margin: 12px 0 0; }
.fbs-bok .fbs__akt .btn { width: 100%; white-space: normal; }

/* Вес и объём читаются столбиком чисел, поэтому переносить их нельзя */
.table--zakaz td.num { white-space: nowrap; }

/* Колонок стало девять, и ужимать их нельзя: «1 уп. по 12» переломится
   пополам и станет двумя бессмысленными строками. Пусть таблица едет вбок */
.table--zakaz { min-width: 1000px; }
.table--zakaz td.num { white-space: nowrap; }

/* ─── Отбор в «Истории»

   ССЫЛКАМИ, А НЕ КНОПКАМИ. Отбор живёт в адресе: им можно поделиться, его не
   теряет кнопка «назад». Поэтому те же переключатели, что у графика, здесь
   надеты на ссылку — отсюда лишние строки про выравнивание и подчёркивание,
   которых кнопке не требовалось. */
a.modes__btn {
    display: inline-flex; align-items: center;
    text-decoration: none;
}

.modes { flex-wrap: wrap; }

/* Поиск и склад в одну строку, кнопки следом. На узком экране всё это
   складывается в столбик само — поля не ужимаются уже своего минимума */
.istor__poisk {
    display: flex; flex-wrap: wrap; gap: 12px; align-items: end;
    margin: 14px 0 18px;
}

.istor__poisk .field { flex: 1 1 260px; min-width: 200px; }
.istor__poisk .field:last-of-type { flex: 0 1 220px; }

/* Поиск по очереди сборки — мгновенный фильтр (app.js). Тянется в панели слева,
   оформлен как обычные поля: та же рамка и жёлтый фокус. */
.sborka__poisk { flex: 1 1 280px; min-width: 220px; }
.sborka__poisk input {
    width: 100%; box-sizing: border-box;
    height: 44px; padding: 0 14px; font-size: 15px; font-weight: 550;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface); color: var(--ink); appearance: none;
}
.sborka__poisk input:focus {
    outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(255, 214, 10, .55);
}
/* Только когда НЕ hidden: иначе явный display перебивал бы атрибут hidden и
   «Ничего не найдено» висело бы при пустом поиске (был такой баг) */
.sborka__poisk #sborkaPoiskNet:not([hidden]) { display: block; margin-top: 8px; }

/* Меню действий «⋯» в строках «Очереди печати» — компактное, на <details>.
   Владелец: «кнопка была большая и непонятная, легко задеть — сделай три точки
   как у WB/Ozon». Всплывашка позиционируется поверх (app.js): таблица
   прокручиваемая, обычный absolute обрезался бы по краю .table-wrap. */
.ochered__act { text-align: right; white-space: nowrap; }
.rowmenu { position: relative; display: inline-block; }
.rowmenu__tochki {
    list-style: none; cursor: pointer; user-select: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: 8px;
    font-size: 22px; line-height: 1; color: var(--ink);
    border: 2px solid transparent;
}
.rowmenu__tochki::-webkit-details-marker { display: none; }
.rowmenu__tochki::marker { content: ""; }
.rowmenu__tochki:hover { background: var(--surface-soft, #f0f0f0); }
.rowmenu[open] .rowmenu__tochki { border-color: var(--line); background: var(--surface-soft, #f0f0f0); }
.rowmenu__pop {
    position: absolute; right: 0; top: calc(100% + 4px); z-index: 40;
    min-width: 232px; padding: 6px;
    background: var(--surface, #fff); border: 2px solid var(--line);
    border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
    display: flex; flex-direction: column; gap: 2px; text-align: left;
}
.rowmenu form { margin: 0; }
.rowmenu__punkt {
    display: block; width: 100%; box-sizing: border-box;
    padding: 10px 12px; border: 0; border-radius: 8px;
    background: none; text-align: left; font: inherit; font-size: 14px;
    color: var(--ink); cursor: pointer; text-decoration: none;
}
.rowmenu__punkt:hover { background: var(--surface-soft, #f0f0f0); }
.rowmenu__punkt--opas { color: #b3261e; }

/* Пояснение вместо пункта: действие тут недоступно и почему. Владелец не должен
   гадать, куда делась кнопка — лучше строка серым, чем пустое меню. */
.rowmenu__punkt--tihiy {
    display: block; padding: 8px 12px; color: var(--muted);
    font-size: 12.5px; line-height: 1.35; cursor: default; white-space: normal;
}
/* ПОЗИЦИИ ОДНОГО ОТПРАВЛЕНИЯ — ОДНИМ БЛОКОМ. Владелец 14 сент 2026: «если это
   одно отправление, они должны быть обозначены одним блоком, между ними эту
   разделяющую линию убрать». Этикетка у них общая: черта между строками читается
   как две посылки. Убираем верхнюю границу у продолжения и метим блок слева. */
/* Границы в .table рисуются СНИЗУ ячейки, поэтому черту между строками одной
   посылки убирает ПЕРВАЯ строка пары, а не вторая.

   НО НЕ У ОБЪЕДИНЁННЫХ ЯЧЕЕК. Владелец 14 сент: «линия только наполовину
   нарисовалась». Так и было: первый заход снимал нижнюю границу у ВСЕХ ячеек
   первой строки, включая те, что растянуты на весь блок (rowspan) — а их
   граница и есть низ блока. В итоге линия под блоком оставалась только под
   колонками товара и штрихкода. Снимаем границу лишь у обычных ячеек. */
.ochered--sliyanie > td:not(.ochered__obshchee) { border-bottom: 0; padding-bottom: 4px; }
.ochered--vmeste > td { padding-top: 4px; }
/* Тонкая скоба слева по всему блоку — видно, что это одна коробка */
.ochered--sliyanie > td:first-child,
.ochered--vmeste > td:first-child { box-shadow: inset 3px 0 0 var(--border); }
/* Общие ячейки блока (номер посылки, этикетка, время, действия) — по центру
   высоты: они относятся ко ВСЕМ позициям, а не к первой. Владелец 14 сент:
   «выглядит так, как будто она относится только к нему». */
.ochered__obshchee { vertical-align: middle; }
/* Подпись посылки — спокойной строкой под названием, не красной плашкой */
.ochered__posylka {
    margin-top: 3px; font-size: 12px; font-style: italic;
    color: var(--muted); line-height: 1.3;
    /* Не даём подписи растягивать колонку: из-за неё съезжала колонка товара,
       и «1 шт» переносилось на вторую строку (владелец, 14 сент). */
    max-width: 170px; white-space: normal;
}

/* Колонка «⋯» в «Сборке»: узкая, к правому краю, не тянет таблицу */
.sbor__act { width: 1%; white-space: nowrap; text-align: right; vertical-align: top; }
.rowmenu__punkt--opas:hover { background: #fdecea; }

/* ОШИБКА ВСПЛЫВАЮЩИМ ОКНОМ ПО ЦЕНТРУ. Владелец: «ошибки не строчкой в углу, а
   окном по центру, чтобы видно было». Строчный .alert--error остаётся (работает
   без JS), а app.js в кабинете дублирует его этим окном с затемнением. */
.err-modal {
    position: fixed; inset: 0; z-index: 1000; padding: 20px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .45);
    animation: err-modal-vhod .12s ease-out;
}
@keyframes err-modal-vhod { from { opacity: 0; } to { opacity: 1; } }
.err-modal__card {
    max-width: 440px; width: 100%; box-sizing: border-box;
    background: var(--surface, #fff); color: var(--ink);
    border-radius: 14px; border-top: 6px solid var(--red, #c00);
    padding: 24px; text-align: center;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
}
.err-modal__title { font-size: 18px; font-weight: 800; color: var(--red, #c00); margin-bottom: 10px; }
.err-modal__text { font-size: 16px; line-height: 1.45; margin-bottom: 20px; }
.err-modal__ok { min-width: 150px; }

/* Строка поставки в «Очереди печати» — отдельной строкой со своим QR (как МПФИТ) */
.ochered__postavka { background: var(--surface-soft, #f6f6f6); }
.ochered__qr {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 6px;
    border: 2px solid var(--line); font-size: 11px; font-weight: 700;
    color: var(--muted, #767d88);
}

/* Подтверждение печати в «Очереди печати»: подтверждено принтером — тихо-зелёное,
   не подтверждено — заметно-красное (владелец должен сразу увидеть проскочившую). */
.ochered__podtv { font-size: 12px; font-weight: 600; color: #1b7f3b; white-space: nowrap; }
.ochered__ne-podtv {
    display: inline-block; margin-top: 2px; padding: 1px 6px; border-radius: 5px;
    font-size: 12px; font-weight: 800; color: #b3261e;
    background: #fdecea; border: 1px solid #f3b6ae; white-space: nowrap;
}

.istor__stranicy { align-items: center; gap: 12px; margin-top: 16px; }

/* Таблица истории не ужимается, а ЕДЕТ ВБОК.
   Колонок восемь, и на узком экране браузер начинал резать даты пополам:
   «30.08.202» — это не короче, это неправда. Полоса прокрутки честнее.

   Даты, номера и этапы переносить по словам тоже нельзя: «Заказан у
   поставщика» столбиком из трёх строк раздувает каждую строку таблицы */
.table--istor { min-width: 940px; }
.table--istor td:nth-child(n+3) { white-space: nowrap; }
.table--istor td:nth-child(4) .muted { display: block; white-space: normal; }

/* Название товара — единственное, чему перенос нужен, но не по буквам.
   Артикул уходит под название: рядом он читается как хвост наименования */
.table--istor td:nth-child(2) { min-width: 240px; white-space: normal; }
.table--istor td:nth-child(2) .muted { display: block; }

/* ─── Рубильник вместо галочки

   ВЛАДЕЛЕЦ ПРО ПРЕЖНИЕ ГАЛОЧКИ: «выглядит дёшево, плюс появляется странная
   штука, когда я навожу». Странная штука — всплывающая подсказка браузера,
   она убрана из разметки; сама галочка нарисована здесь, а не операционной
   системой, поэтому выглядит одинаково на маке, Windows и телефоне.

   ВНУТРИ ЭТО ВСЁ ТОТ ЖЕ CHECKBOX. Он так же отправляется формой, так же
   переключается пробелом с клавиатуры и так же читается голосовым доступом —
   изменился только вид. Ничего из этого нельзя было бы сказать про кнопку с
   картинкой, которой рубильник обычно подделывают. */
.tumbler {
    appearance: none; -webkit-appearance: none;
    position: relative; flex: none;
    width: 56px; height: 30px; margin: 0;
    border: 2px solid var(--ink); border-radius: var(--r-sm);
    background: var(--surface-soft);
    cursor: pointer;
}

.tumbler::after {
    content: "";
    position: absolute; top: 3px; left: 3px;
    width: 20px; height: 20px;
    background: var(--ink);
    transition: left .12s ease-out, background .12s ease-out;
}

.tumbler:checked { background: var(--best); border-color: var(--best-hover); }
.tumbler:checked::after { left: 29px; background: var(--surface); }

.tumbler:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(236, 48, 19, .35); }
.tumbler:disabled { cursor: not-allowed; opacity: .45; }

/* Кому анимация мешает — тому её и не будет: рубильник обязан только
   показывать положение, ехать он не обязан */
@media (prefers-reduced-motion: reduce) {
    .tumbler::after { transition: none; }
}

/* ─── Настройки списком: что это, зачем оно и рубильник справа

   УСТРОЙСТВО ВЗЯТО У МПФИТ. Раньше каждая настройка была отдельной формой со
   своим заголовком и своей кнопкой, и на вопрос «что у меня сейчас включено»
   приходилось читать страницу сверху донизу. Список отвечает за секунду:
   включённые строки подсвечены. */
.nastr {
    border: 2px solid var(--ink);
    background: var(--surface);
    margin: 14px 0 18px;
}

.nastr__stroka {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 12px 24px;
    align-items: center;
    padding: 16px 18px;
    border-bottom: 2px solid var(--ink);
}

.nastr__stroka:last-child { border-bottom: 0; }

/* Включённое видно фоном, а не только положением рубильника: положение надо
   разглядывать, полосу — нет */
.nastr__stroka--vkl { background: var(--best-wash); }

/* Подсветка едет за рукой сразу, не дожидаясь сохранения. Старые браузеры
   :has не знают — там правило целиком отбрасывается, и остаётся подсветка по
   сохранённому состоянию выше. Поэтому она и оставлена в разметке */
.nastr__stroka:has(.tumbler:checked) { background: var(--best-wash); }
.nastr__stroka:has(.tumbler:not(:checked)) { background: var(--surface); }

.nastr__imya {
    display: block;
    font-size: 16px; font-weight: 750;
    margin-bottom: 3px;
    cursor: pointer;
}

.nastr__zachem {
    margin: 0;
    font-size: 14px; line-height: 1.45; color: var(--ink-soft);
}

/* Поле ввода в строке настройки короткое: там час или число, а не текст.
   Растянутое на всю ширину, оно бы врало про то, сколько от него ждут */
.nastr__pole { width: 150px; }
.nastr__pole input { height: 44px; text-align: center; }

/* Кнопка одна на весь список, как и на складах: настройки правят целиком */
.nastr + .btn { margin-top: 2px; }

.fbs__akt { margin: 12px 0 20px; }
.fbs__zapas { margin: 12px 0 28px; }
.fbs__zapas summary { cursor: pointer; }
.fbs__zapas .form { margin-top: 12px; }

/* На узком экране таблица складывается в столбик: пять колонок в 375 точек не
   помещаются. Тогда шапка прячется, а подписи возвращаются к самим полям —
   иначе непонятно, что именно отмечаешь */
@media (max-width: 900px) {
    .sklady__shapka { display: none; }

    .sklad {
        grid-template-columns: 1fr;
        gap: 10px;
        padding: 16px 4px;
    }

    .sklad__gal span { display: inline; }

    .nastr__stroka { grid-template-columns: 1fr; }
    .nastr__pole { width: 100%; }
}

/* ─── РЕПРАЙСЕР: низкие блоки, таблица товаров, тумблеры ─── */
.rp-shapka { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 6px 0 12px; }
.rp-zapusk { display: flex; align-items: center; gap: 12px; }
.rp-otbor { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
.rp-otbor input[type=search] { min-width: 260px; }
.rp-blok { margin: 10px 0 14px; }
.rp-blok summary { cursor: pointer; font-weight: 700; }
.rp-forma { margin-top: 8px; }
.rp-forma__ryad { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: flex-end; margin: 6px 0 10px; }
.rp-forma__ryad label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--muted); }
.rp-forma__ryad label input, .rp-forma__ryad label select, .rp-forma__ryad > input, .rp-forma__ryad > select { font-size: 14px; color: var(--ink); }
.rp-flag { flex-direction: row !important; align-items: center !important; gap: 6px !important; color: var(--ink) !important; font-size: 13.5px !important; }
.rp-nastroyki textarea, .rp-forma textarea { width: 100%; max-width: 720px; font: 13px ui-monospace, Menlo, monospace; }
#repricer .rp-shirina { overflow: visible; }
.rp-tabl thead th { position: sticky; top: 66px; z-index: 2; background: var(--surface); }
.rp-tabl td { vertical-align: top; }
.rp-tovar { display: flex; gap: 10px; min-width: 320px; }
.rp-foto { width: 48px; height: 48px; object-fit: contain; border: 1px solid var(--line, #e6eaee); border-radius: 6px; background: #fff; flex: 0 0 auto; }
.rp-str--beda { background: #fff4f1; }
.rp-net { color: #a82a12; font-weight: 700; }
.rp-ok { color: #1f7a3d; font-weight: 700; }
.rp-minus { color: #a82a12; font-weight: 700; }
.rp-vverh { color: #1f7a3d; }
.rp-vniz { color: #a82a12; }
.rp-reshenie { min-width: 170px; }
.rp-pochemu summary, .rp-kartochka summary { cursor: pointer; font-size: 12.5px; color: var(--muted); text-decoration: underline dotted; }
.rp-pochemu div { max-width: 420px; font-size: 12.5px; margin-top: 4px; }
.rp-kartochka { margin-top: 6px; }
.rp-kartochka .rp-forma { border: 1px solid var(--line, #e6eaee); border-radius: 8px; padding: 8px 10px; background: var(--surface); }
.rp-razlozhenie { font-size: 12.5px; margin-top: 6px; max-width: 720px; }
.rp-tumbler { border: 2px solid var(--ink); background: #fff; color: var(--ink); font-weight: 800; font-size: 12px; padding: 4px 10px; border-radius: 999px; cursor: pointer; }
.rp-tumbler--on { background: var(--ink); color: #fff; }
.rp-tumbler--otpr { background: #1f7a3d; border-color: #1f7a3d; }
.rp-stranicy { display: flex; gap: 14px; align-items: center; margin-top: 12px; }
.rp-prichina { max-width: 460px; font-size: 12.5px; }
.rp-help h3 { margin-top: 18px; }
.rp-help dt { font-weight: 700; margin-top: 8px; }
.rp-help dd { margin: 2px 0 0 0; color: var(--muted); }
.rp-pauza { border: 2px solid #a82a12; color: #a82a12; background: #fff4f1; padding: 10px 14px; border-radius: 8px; margin: 8px 0 12px; font-weight: 700; }
/* Акции: ряд итогов теми же квадратами, что и в боковой колонке */
.rp-akc-itogi { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 14px; }
.rp-akc-itogi .hran__kvadrat { flex: 1 1 150px; min-width: 150px; }
.rp-stroka--vybrana { background: #f4f8ff; }
.rp-vest { border: 2px solid #1f7a3d; color: #1f7a3d; background: #e7f6ec; padding: 8px 14px; border-radius: 8px; margin: 8px 0 12px; }

/* ═══════════════ ПРОДВИЖЕНИЕ ═══════════════ */
.pv-period { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pv-din { font-size: 12px; font-weight: 700; white-space: nowrap; }
.pv-sort { color: inherit; text-decoration: none; border-bottom: 1px dotted currentColor; }
.pv-sort--on { font-weight: 800; border-bottom-style: solid; }
.pv-tabl td:nth-child(n+3) { white-space: nowrap; }
.pv-segmenty { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; margin: 8px 0 14px; }
.pv-seg { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border: 1px solid var(--line, #e6eaee); border-left-width: 5px; border-radius: 10px; background: var(--surface, #fff); color: inherit; text-decoration: none; }
a.pv-seg:hover { border-color: var(--ink-soft, #667); }
.pv-seg--pusto { opacity: .55; }
.pv-seg__cifra { font-size: 26px; font-weight: 800; line-height: 1.1; }
.pv-seg__imya { font-weight: 700; }
.pv-seg__pochemu { font-size: 13px; color: var(--muted); }
.pv-seg__chto { font-size: 13px; margin-top: 4px; }
.pv-seg__chto::before { content: "Что сделать: "; font-weight: 700; }
.pv-seg-poyasnenie { padding: 10px 14px; margin: 0 0 12px; border-left: 5px solid #999; border-radius: 8px; background: var(--surface, #fff); font-size: 14px; }
.pv-seg-poyasnenie em { display: block; margin-top: 4px; font-style: normal; color: var(--muted); }
.pv-cvet--kras { border-left-color: #a82a12; }
.pv-cvet--zhel { border-left-color: #c98a00; }
.pv-cvet--zel { border-left-color: #1f7a3d; }
.pv-cvet--ser { border-left-color: #999; }
.pv-sovet { font-size: 12px; margin-top: 3px; color: #1f7a3d; }
.pv-sovet strong { color: inherit; }
.pv-tezki { font-size: 12px; margin-top: 3px; color: #a82a12; }

/* ЯЧЕЙКА ТОВАРА В «ПРОДВИЖЕНИИ» — БЛОК, А НЕ ФЛЕКС (12 сент 2026).
   Класс .rp-tovar пришёл из репрайсера, где фотография лежит внутри той же
   ячейки, и потому там flex. В «Продвижении» фото стоит отдельной колонкой, и
   flex выстраивал название, артикул, «тёзок» и подсказку в одну строку — они
   наезжали на колонку видимости. Владелец: «всё выглядит криво». */
.pv-tabl .rp-tovar { display: block; min-width: 240px; max-width: 360px; }
.pv-tabl .rp-tovar > a { display: inline-block; margin-bottom: 2px; }
.pv-tabl .rp-tovar .muted { font-size: 12px; line-height: 1.35; white-space: normal; }
.pv-tabl .pv-tezki,
.pv-tabl .pv-sovet { white-space: normal; }
.pv-tabl th { vertical-align: bottom; }
.pv-tabl td { padding-top: 8px; padding-bottom: 8px; }
.pv-tabl td .muted { font-size: 12px; line-height: 1.3; }
.pv-tabl td { line-height: 1.3; }

/* МАССОВЫЙ ВЫБОР В «СБОРКЕ» (15 сент 2026). Владелец: «массово выбрать много
   товаров у нас неудобно». Колонка узкая — галочка не должна отодвигать фото
   и название; панель действий висит под таблицей и появляется только когда
   что-то выбрано, чтобы не занимать место зря. */
.sbor__vybor { width: 1%; white-space: nowrap; vertical-align: top; padding-top: 14px; }
.sbor__vybor input { width: 18px; height: 18px; cursor: pointer; }

.sbor__massovo {
    /* ПАНЕЛЬ НАД ТАБЛИЦЕЙ, А НЕ ПОД НЕЙ (15 сент 2026). Владелец выделил всё
       галочкой в шапке и написал: «я не понимаю, как вернуть к заказу
       обратно» — панель была под списком из 27 строк, то есть за экраном.
       Выбор начинается сверху, значит и кнопки должны быть сверху. */
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 12px 0 0;
    padding: 10px 14px;
    background: var(--best-wash);
    border: 1px solid var(--line);
    border-radius: 10px;
}
.sbor__massovo[hidden] { display: none; }
.sbor__schyot { margin-right: auto; }

/* СОСЕДНИЕ ШТРИХКОДЫ ТОВАРА (15 сент 2026). Владелец: «партии приходят под
   разными кодами, сканирую любой». Свой код задания обычный, остальные рядом
   бледнее: сканировать можно любой, но сверять глазами — сначала со своим. */
.shk--sosed { opacity: .55; }

/* ЧЕЙ СКЛАД: три положения рядом с периодом (15 сент 2026). Владелец просил
   ползунок «в базе посередине — всё»; радиокнопки честнее ползунка — видно
   все три состояния сразу, и работает без скрипта. */
.period__sklad { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.period__sklad-p { padding: 5px 12px; cursor: pointer; font-size: 13px; white-space: nowrap; }
.period__sklad-p + .period__sklad-p { border-left: 1px solid var(--line); }
.period__sklad-p input { position: absolute; opacity: 0; width: 0; height: 0; }
.period__sklad-p.is-on { background: var(--ink); color: #fff; }

/* ОПОЗНАНИЕ ТОВАРА ПО ФОТО НА ПЛАНШЕТЕ (16 сент 2026). Кладовщик не обязан
   помнить, как выглядит товар, которого он ни разу не видел: показываем то,
   что ждём, картинками и даём ткнуть пальцем. Кнопки крупные — работают в
   перчатках и на ходу. */
.term__zhdyom { display: grid; gap: 8px; margin-top: 10px; max-height: 60vh; overflow-y: auto; }
.term__zhdyom-poisk {
    width: 100%; margin-top: 10px; padding: 12px 14px; font-size: 17px;
    border: 1px solid var(--line); border-radius: 10px;
}
.term__zhdyom-p { margin: 0; }
.term__zhdyom-b {
    display: flex; align-items: center; gap: 14px; width: 100%;
    padding: 10px 12px; text-align: left; cursor: pointer;
    background: #fff; border: 1px solid var(--line); border-radius: 10px; font: inherit;
}
/* Место под фото держим всегда: без него строки без картинки съезжали и
   подпись уходила отдельным блоком (живой экран владельца, 16 сент) */
.term__zhdyom-foto { flex: 0 0 80px; width: 80px; height: 80px; display: block; }
.term__zhdyom-foto img { width: 80px; height: 80px; object-fit: contain; border-radius: 6px; }
.term__zhdyom-t { flex: 1 1 auto; min-width: 0; }
.term__zhdyom-b b { display: block; font-size: 16px; line-height: 1.3; }
.term__zhdyom-b i { display: block; font-style: normal; opacity: .6; font-size: 14px; margin-top: 4px; }

/* Поиск карточки при привязке кода: поле и кнопка в строку, крупные —
   планшет держат в перчатках (16 сент 2026). */
.term__isk { display: flex; gap: 8px; align-items: stretch; margin-top: 10px; }
.term__isk .term__zhdyom-poisk { margin-top: 0; flex: 1 1 auto; }
.term__isk .term__knopka { flex: 0 0 auto; width: auto; padding-left: 22px; padding-right: 22px; }

/* РАЗДЕЛ «ТОВАРЫ» — весь каталог карточек страницами (18 сент 2026).
   Отбор стоит одной строкой над таблицей: его трогают на каждом заходе, и
   прятать его под «Фильтры» значило бы добавить нажатие к самому частому
   действию. */
.tov__otbor {
    /* По нижнему краю, а не по центру: у полей появились подписи разной
       высоты, и по центру строка разъезжалась ступеньками. */
    display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;
    margin: 12px 0 16px;
}
.tov__otbor input[type=search], .tov__otbor select {
    padding: 9px 12px; border: 1px solid var(--line, #d9dee3);
    border-radius: 8px; font-size: 14px; background: #fff;
}
/* ШИРИНУ ЗАДАЁТ ОБЁРТКА С ПОДПИСЬЮ, А НЕ САМО ПОЛЕ (18 сент 2026).
   Правило `flex: 1 1 320px` стояло на самом поле и работало, пока поле лежало
   прямо в строке отбора. Когда у полей появились подписи, поле переехало внутрь
   колоночного блока — и те же 320px стали считаться по ВЕРТИКАЛИ: строка поиска
   выросла в короб высотой в треть экрана. Основу тянет обёртка
   (.tov__pole--shire), а поле просто занимает её ширину. */
.tov__otbor input[type=search] { flex: 0 0 auto; width: 100%; min-width: 0; }
.tov__gal { display: flex; align-items: center; gap: 6px; font-size: 14px; white-space: nowrap; }
.tov__sbros { font-size: 14px; }
.tov__foto {
    width: 44px; height: 44px; object-fit: contain;
    border-radius: 6px; background: #f6f7f9;
}
/* «Нет фото» — это не пустота, а работа, которую видно */
.tov__nefoto {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: 6px; text-align: center;
    background: #fdeeea; color: #a82a12; font-size: 10px; line-height: 1.1; padding: 2px;
}
.tov code { font-size: 12px; }
.tov__stranicy {
    display: flex; gap: 14px; align-items: center; justify-content: center;
    margin: 16px 0 4px;
}

/* «Похоже на» в карантине: кандидаты по соседним штрихкодам (18 сент 2026).
   Подсказка стоит НАД полем ввода, потому что читают её раньше, чем набирают. */
.hran__kar-pohozhe { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; }
.hran__kar-kand {
    border: 1px dashed var(--line, #c8d0d8); background: #fff; cursor: pointer;
    border-radius: 999px; padding: 3px 10px; font-size: 12px; color: #2b3540;
}
.hran__kar-kand:hover { border-style: solid; background: #f3f6f9; }

/* «ГДЕ»: ЗНАЧОК ПЛОЩАДКИ НА ОДНОЙ ЛИНИИ ВО ВСЕХ СТРОКАХ (18 сент 2026).
   Владелец: «логотип ВБ не по линии, каждый раз отступ разный». Колонка
   выключена вправо, и раньше значок с числом ехали одним куском: 138 отодвигало
   значок дальше, чем 3, и левый край значков получался рваным. Теперь строка
   собрана как две ячейки — значок и число своей ширины, — и значки стоят
   столбиком. Ширина числа в символах, а не в точках: так она не разъедется от
   другого шрифта. */
.gde { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }
.gde + .gde { margin-top: 3px; }
.gde .pl { margin-right: 0; flex: 0 0 auto; }
.gde__n { min-width: 4ch; text-align: right; font-variant-numeric: tabular-nums; }

/* Название товара — ссылка на его карточку у маркетплейса (18 сент 2026).
   Подчёркивание появляется при наведении: в плотной таблице постоянные линии
   под каждым названием рябят, а ссылку выдаёт курсор. */
.tov__ssylka { color: inherit; text-decoration: none; }
.tov__ssylka:hover strong { text-decoration: underline; }

/* ОТБОР ТОВАРОВ: подписи у полей и выбранное словами (18 сент 2026).
   Владелец, глядя прямо на строку отбора: «а где фильтр?» — строка читалась
   как поиск, потому что площадка стояла без подписи между полем ввода и
   сортировкой, а выбранное нигде не было названо. */
.tov__pole { display: flex; flex-direction: column; gap: 3px; }
.tov__pole--shire { flex: 1 1 320px; min-width: 220px; }
.tov__pole--shire input { width: 100%; box-sizing: border-box; }
.tov__podpis { font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: #6a7480; }
.tov__otbor .tov__gal { padding-bottom: 10px; }
.tov__vybrano { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: -6px 0 14px; }
.tov__chip {
    display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
    background: #eef2f6; border-radius: 999px; padding: 3px 10px;
    color: #2b3540; text-decoration: none;
}
.tov__chip:hover { background: #e2e8ef; }

/* БЛОК «ФИЛЬТРЫ» — набор условий (18 сент 2026). Владелец трижды спросил «где
   фильтр?», глядя на выбор площадки: фильтром он называет именно набор условий,
   а не один список. Раскрывается обычным <details>, без скрипта. */
.tov__filtry { flex: 1 0 100%; margin-top: 4px; }
.tov__filtry > summary {
    cursor: pointer; display: inline-block; font-weight: 700; font-size: 14px;
    padding: 6px 0; user-select: none;
}
.tov__filtry-telo {
    display: flex; gap: 22px; flex-wrap: wrap; align-items: flex-start;
    padding: 12px 14px; margin-top: 4px;
    border: 1px solid var(--line, #e6eaee); border-radius: 10px; background: #fafbfc;
}
.tov__usl { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.tov__usl legend {
    padding: 0; font-size: 11px; text-transform: uppercase;
    letter-spacing: .03em; color: #6a7480; margin-bottom: 2px;
}
.tov__usl label { display: flex; align-items: center; gap: 6px; font-size: 14px; white-space: nowrap; }
.tov__usl input[type=number] {
    width: 90px; padding: 7px 9px; border: 1px solid var(--line, #d9dee3); border-radius: 8px;
}
.tov__usl-knopki { display: flex; gap: 12px; align-items: center; align-self: flex-end; }

/* ЮНИТ-ЭКОНОМИКА В СТРОКУ (18 сент 2026). Владелец: «зачем ты сделал это в
   раскрывающемся списке? Я же должен это наглядно видеть — сделай в строчку».
   Смысл раздела — сравнивать товары между собой: у кого логистика съедает
   больше, у кого комиссия. Под раскрытием сравнивать нельзя, видно по одному.
   Таблица от этого шире экрана — она прокручивается вбок, а колонка с товаром
   остаётся на месте, иначе на середине строки уже не помнишь, чей это ряд. */
.table--unit td, .table--unit th { padding-left: 8px; padding-right: 8px; white-space: nowrap; }
.table--unit .unit-tovar {
    position: sticky; left: 0; z-index: 2; background: #fff;
    max-width: 260px; white-space: normal;
}
.table--unit thead th:first-child { position: sticky; left: 0; z-index: 3; background: #fff; }

/* ЮНИТ-ЭКОНОМИКА: СТАВКИ ПРЯМО В СТРОКЕ (19 сент 2026). Владелец: «основная
   возможность записи должна быть построчная, так как у всех товаров процент
   выкупа может быть разный». Поле узкое и без рамки, пока в нём общее значение:
   так строка остаётся таблицей, а не анкетой. Своё значение обведено — видно,
   где человек уже принял решение. */
.unit-in {
    width: 56px; padding: 3px 5px; font-size: 12px; text-align: right;
    border: 1px solid transparent; border-radius: 6px; background: #f4f6f8; color: #6a7480;
}
.unit-in:focus { border-color: var(--line, #b9c2cc); background: #fff; color: inherit; outline: none; }
.unit-in--svoyo { border-color: #7b2fbe; background: #fff; color: inherit; font-weight: 700; }
.unit-gal { width: 28px; text-align: center; }
.unit-mass {
    display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;
    padding: 10px 12px; margin: 10px 0; border: 1px solid var(--line, #e6eaee);
    border-radius: 10px; background: #fafbfc;
}
.unit-mass__z { font-weight: 700; font-size: 14px; padding-bottom: 8px; }
.unit-mass input { width: 92px; padding: 7px 9px; border: 1px solid var(--line, #d9dee3); border-radius: 8px; }
.unit-knopki { display: flex; gap: 12px; align-items: center; margin: 12px 0 4px; }

/* ВЫБОР КОЛОНОК В «ТОВАРАХ» (19 сент 2026). Владелец: «всё-всё-всё, что можно
   собрать про каждый товар, хочу вынести в отдельный столбик». Собрано всё, а
   показ выбирается: тридцать колонок сразу — это три экрана вширь, и таблица
   перестаёт читаться. Список свёрнут, потому что раскрытые галочки загораживают
   саму таблицу, ради которой сюда пришли. */
.tov__kolonki { margin: 0 0 14px; }
.tov__kolonki > summary { cursor: pointer; font-weight: 700; font-size: 14px; padding: 6px 0; user-select: none; }
.tov__kolonki-telo {
    display: flex; gap: 22px; flex-wrap: wrap; align-items: flex-start;
    padding: 12px 14px; margin-top: 4px;
    border: 1px solid var(--line, #e6eaee); border-radius: 10px; background: #fafbfc;
}
.tov__kol-gruppa { display: flex; flex-direction: column; gap: 3px; }
.tov__kol-knopki { display: flex; gap: 12px; align-items: center; align-self: flex-end; }

/* Срок отгрузки WB в «Сборке» (20 сент 2026). Владелец: «нам бы отдельным
   образом обозначать товары, по которым срок ожидания больше 48 часов».
   Жёлтый — время на исходе, красный — уже просрочено и штраф начислят. */
.sbor__srok--skoro { color: #a86b00; font-weight: 700; }

/* Блок «пора отменить своими руками» (20 сент 2026). Стоит над сборкой, потому
   что это про деньги, утекающие прямо сейчас: своя отмена стоит копейку,
   автоотмена маркетплейса — до 70% цены товара. */
.otmena-blok {
    border: 1px solid #f0b7a6; border-left: 4px solid #d14418; border-radius: 10px;
    background: #fff7f4; padding: 14px 16px; margin: 0 0 18px;
}
.otmena-blok__z { font-weight: 700; font-size: 15px; margin-bottom: 4px; }
.otmena-blok .otmena-tab { margin-top: 10px; background: transparent; }
.otmena-blok .otmena-tab th { font-size: 11px; }


/* «К заказу»: раскрытие строки товара в задания (23 сент 2026).
   Шеврон рядом с флажком, без цифры: число заказов и так стоит в «Нужно».
   Подстроки — тише строки товара: светлее, мельче, номер под названием. */
.sbor__vybor { white-space: nowrap; }
.zakaz__razv {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; margin-left: 6px; padding: 0; vertical-align: middle;
    color: var(--muted); background: none; border: 0; border-radius: 6px; cursor: pointer;
}
.zakaz__razv:hover { color: var(--ink); background: var(--surface-soft, #f0f0f0); }
.zakaz__razv svg { transition: transform .15s ease; }
.zakaz__razv[aria-expanded="true"] svg { transform: rotate(180deg); }
.zakaz__razv[aria-expanded="true"] { color: var(--ink); }
.zakaz__pod > td {
    background: transparent; font-size: 13px; color: var(--muted);
    padding-top: 8px; padding-bottom: 8px;
    border-bottom: 1px dashed var(--line, #d9dee3);
}
/* Последняя подстрока закрывается обычной чертой таблицы */
.zakaz__pod:has(+ tr:not(.zakaz__pod)) > td { border-bottom-style: solid; }
.zakaz__pod-imya { padding-left: 84px !important; }
.zakaz__pod-nomer { font: 13px ui-monospace, Menlo, Consolas, monospace; color: var(--ink); margin-right: 8px; }


/* АКТИВНЫЙ ЭТАП В БОКОВОЙ КОЛОНКЕ — КОНТРАСТНО (владелец, 23 сент 2026: «тусклая,
   непонятно, на какой вкладке»). Тёмная плашка с белым текстом и числом. */
.fbs-bok .fbs-shagi .modes__btn--on,
.fbs-bok .fbs-shagi .modes__btn--on:hover {
    background: var(--ink); color: #fff; border-color: var(--ink);
}
.fbs-bok .fbs-shagi .modes__btn--on .fbs-shagi__n { color: #fff; opacity: .85; }

/* «В доставке»: принято складом по заданиям поставки */
.dost__vse { color: var(--muted); }
.dost__net { display: block; color: #a82a12; font-size: 13px; }

/* «Открываю раздел…» — признак жизни, пока браузер идёт за разделом на сервер.
   Адрес в строке до ответа остаётся старым, и без этой плашки переход в
   тяжёлый раздел выглядел как зависший кабинет. */
.cab__gruz {
    position: fixed;
    left: 50%;
    bottom: 28px;
    transform: translateX(-50%);
    z-index: 60;
    padding: 10px 20px;
    border-radius: 100px;
    background: var(--ink, #14161a);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .25);
}
