/* Кабинет менеджера. Работает и на компьютере, и на телефоне:
   на узком экране таблицы превращаются в карточки, где каждая строка
   подписана заголовком колонки — иначе цифры невозможно читать. */

:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --text: #1b1f24;
  --muted: #6b7280;
  --line: #e3e6ea;
  --accent: #0b5fff;
  --warn: #c2410c;
  --ok: #15803d;
  --radius: 10px;
  /* Подсветка строки под курсором и коробка ошибки: в тёмной теме светлый
     фон светился бы дырой, поэтому они тоже переменные. */
  --hover: #fafbfc;
  --error-bg: #fee2e2;
  --error-line: #fecaca;
  --error-text: #991b1b;
  /* Высота верхней панели: она тоже прилипает, и шапка таблицы должна
     вставать под неё, а не прятаться за ней.
     Число здесь — только запасное значение на случай отключённых скриптов:
     настоящую высоту ставит `table.js::trackTopbar`, потому что она зависит
     от того, на сколько строк перенеслась навигация. Запас взят с избытком
     (замер 22.10.2026: на ноутбуке 1440 шапка занимает 104 px, на очень
     широком экране — 57): лишний отступ под шапкой безвреден, а нехватка
     прячет первую строку таблицы. */
  --topbar: 112px;
}

/* Тёмная тема. По умолчанию кабинет слушается системной настройки телефона
   и ноутбука, а выключатель в шапке её перебивает и запоминается
   (`static/theme.js`). Поэтому правил три: системное предпочтение действует
   только пока человек не выбрал светлую тему руками.

   Цвета не инвертированы, а подобраны: на чёрном фоне тот же синий слепит,
   а оранжевый предупреждения теряется. Поверхность чуть светлее фона —
   карточки и таблицы должны оставаться различимы без рамок. */
:root:not([data-theme="light"]) {
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #14161a;
    --surface: #1c1f25;
    --text: #e8eaed;
    --muted: #9aa1ab;
    --line: #2b2f37;
    --accent: #5b8cff;
    --warn: #ff8a4c;
    --ok: #4ade80;
    --hover: #22262e;
    --error-bg: #3b1d1d;
    --error-line: #5c2a2a;
    --error-text: #ffb4ab;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #14161a;
  --surface: #1c1f25;
  --text: #e8eaed;
  --muted: #9aa1ab;
  --line: #2b2f37;
  --accent: #5b8cff;
  --warn: #ff8a4c;
  --ok: #4ade80;
  --hover: #22262e;
  --error-bg: #3b1d1d;
  --error-line: #5c2a2a;
  --error-text: #ffb4ab;
}

/* Выключатель темы в шапке. Кнопка, а не ссылка: она ничего не открывает. */
.theme {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  border-radius: var(--radius);
  padding: 6px 10px;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  white-space: nowrap;
}
.theme:hover { color: var(--text); }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 -apple-system, "Segoe UI", Roboto, sans-serif;
}

.top {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 12px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  /* Прибита к окну, а не к документу. Разница видна только тогда, когда
     таблица шире экрана: страница в этом случае прокручивается вбок
     целиком (см. `.table-wrap`), и прилипшая шапка уезжала влево вместе
     с ней — прилипание держит её лишь по вертикали. Замер 22.10.2026
     на планшете 820 px: прокрутка вбок на 209 px открывала справа
     полосу ровно в 209 px, и под ней ехали строки товаров. Это и увидел
     менеджер.
     Расплата за `fixed` — шапка вне потока, и место под неё отводит
     отступ у `main` (`--topbar`). Высоту ставит `table.js::trackTopbar`:
     она зависит от того, на сколько строк перенеслась навигация. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
}


.brand {
  font-weight: 700;
  font-size: 17px;
  color: var(--text);
  text-decoration: none;
}

/* Навигация занимает всю свободную ширину, а выключатель темы и кто вошёл
   встают на ту же строку справа. Без `flex: 1` они уходят на отдельную
   третью строку, и шапка на планшете вырастает со 115 до 203 пикселей —
   четверть экрана пустоты, под которой прокручивается таблица. */
nav { display: flex; gap: 6px; flex-wrap: wrap; flex: 1 1 0; min-width: 0; }

nav a {
  padding: 7px 12px;
  border-radius: var(--radius);
  color: var(--muted);
  text-decoration: none;
}

nav a:hover { background: var(--bg); }
nav a.active { background: var(--accent); color: #fff; }

/* Страница начинается от левого края, как и верхняя панель, и занимает всё
   окно. Раньше здесь стояли 1200 пикселей по центру, и это стоило таблицам
   дважды: по сотне с лишним пикселей пустого поля слева и справа, а всё, что
   шире 1200, уезжало за правый край — на экране 1920 вбок прокручивались
   шесть страниц из двенадцати. Таблицы в кабинете широкие по существу
   (у калькулятора семнадцать колонок), и место им нужнее, чем симметрия.
   Потолок в 2000 — только ради очень широких мониторов: растянуть семь
   колонок на три с половиной тысячи пикселей значит развести взгляд
   по краям и потерять строку. */
/* Отступ сверху отводит место прибитой шапке: она вне потока, и без него
   первые строки таблицы оказались бы под ней. На странице входа `main`
   нет вовсе, поэтому форма входа от этого правила не страдает. */
main { padding: 20px; padding-top: calc(20px + var(--topbar)); max-width: 2000px; margin: 0; }

/* Поясняющий текст над таблицей и под ней — на 70% ширины окна (решение
   владельца 22.10.2026). Во всю ширину он не читается, а прежние 90ch
   (около 690 пикселей) забирали слишком много высоты: пояснение на вкладке
   закупки занимало семь строк там, где хватает четырёх.
   Исключения перечислены нарочно: `.alphabet` и `.filters` — тоже абзацы,
   но это не текст, а ряд кнопок, и ограничение ширины ломало им строку.
   `.totals` — числа, а не объяснение. */
main > p:not(.alphabet):not(.filters),
main > details,
main > dl:not(.totals),
main > ul {
  max-width: 70%;
}

h1 { font-size: 22px; margin: 4px 0 18px; }
h2 { font-size: 17px; margin: 24px 0 10px; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }

.muted { color: var(--muted); }
.small { font-size: 13px; }
.warn { color: var(--warn); font-weight: 600; }

/* Предупреждение во всю ширину: когда странице нельзя верить, это должно
   быть видно раньше её цифр, а не мелкой подписью под ними. */
p.warn {
  font-weight: 400;
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin: 0 0 14px;
  font-size: 14px;
  line-height: 1.5;
}
.ok { color: var(--ok); font-weight: 600; }
.strong { font-weight: 700; }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.card-value { font-size: 24px; font-weight: 700; }
.card-label { color: var(--muted); margin-top: 2px; }
.card-note { margin-top: 8px; font-size: 13px; color: var(--muted); }

.filters {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 16px;
}

.filters label { display: flex; gap: 6px; align-items: center; color: var(--muted); }

input, select, button, .button {
  font: inherit;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

input[type="search"] { min-width: 220px; flex: 1 1 220px; }

button, .button {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}

.button.secondary { background: var(--surface); color: var(--text); border-color: var(--line); }

.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }

.table-wrap {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* Здесь нельзя ставить overflow ни по одной оси. Прилипает шапка
     к ближайшему прокручиваемому предку, и стоило задать `overflow-x: auto`,
     как им становилась эта обёртка: шапка переставала держаться за окно
     и уезжала внутрь таблицы на высоту верхней панели — ровно под первую
     строку. `overflow-y: visible` не спасает: по спецификации, если одна ось
     не `visible`, вторая считается `auto`.
     Поэтому широкая таблица раздвигает страницу, а не прокручивается внутри
     коробки: горизонтальная полоса внизу страницы — меньшее зло, чем шапка,
     которую не видно. На узком экране таблиц нет вовсе — там карточки. */
  width: max-content;
  min-width: 100%;
}

table { width: 100%; border-collapse: collapse; }

/* Отступы в ячейках скромнее, чем были (10×14): на двенадцати колонках
   четыре лишних пикселя с каждой стороны — это сотня пикселей ширины,
   то есть разница между «влезает» и «прокручивается». */
th, td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--line); }
th {
  font-size: 13px;
  color: var(--muted);
  font-weight: 600;
  white-space: nowrap;
  /* Шапка остаётся на месте при прокрутке: таблицы длинные, и без этого
     к середине списка уже не помнишь, что за столбец перед глазами.
     Фон непрозрачный обязательно — иначе строки просвечивают сквозь шапку. */
  position: sticky;
  top: var(--topbar);
  z-index: 2;
  background: var(--surface);
  box-shadow: inset 0 -1px 0 var(--line);
}

/* Вложенная таблица прокручивается вместе со страницей, своей шапке
   прилипать некуда — иначе она встала бы поверх общей. */
table.inner th { position: static; box-shadow: none; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--hover); }

.num { text-align: right; white-space: nowrap; }
.name { display: block; }

.cluster { margin-bottom: 26px; }

/* Телефон: таблица не помещается по ширине, поэтому строка превращается
   в карточку, а подписи берутся из data-label. */
@media (max-width: 720px) {
  main { padding: 14px; }
  h1 { font-size: 19px; }

  /* 70% ширины на телефоне — это колонка в 270 пикселей, то есть три слова
     в строке. Текст тут занимает всю ширину, как и всё остальное. */
  main > p:not(.alphabet):not(.filters),
  main > details,
  main > dl:not(.totals),
  main > ul {
    max-width: none;
  }

  table, thead, tbody, tr, td { display: block; width: 100%; }
  thead { display: none; }

  /* Обёртке здесь не нужен `width: max-content`: таблицы на узком экране
     превращаются в карточки, раздвигать нечего, а max-content растягивают
     длинные названия товаров — страница уезжала вбок на две своих ширины. */
  .table-wrap { width: auto; min-width: 0; }

  tbody tr {
    border-bottom: 1px solid var(--line);
    padding: 10px 4px;
  }

  td {
    display: flex;
    /* Перенос обязателен: в ячейке бывает не одно значение, а три подряд
       («вне Ozon 1.49 · 1 698 ₽»), и без переноса они уезжали за правый
       край карточки — страница на телефоне прокручивалась вбок. */
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 2px 14px;
    border: none;
    padding: 4px 12px;
    text-align: right;
  }

  /* Перенесённые значения прижимаются к правому краю, под своё же число,
     а не уходят под подпись слева. */
  td > * { margin-left: auto; }
  td::before { margin-left: 0; }

  td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 13px;
    text-align: left;
  }

  td[data-label="Товар"] { flex-direction: column; text-align: left; }
  td[data-label="Товар"]::before { display: none; }
  /* Название идёт столбиком и от левого края: прижимать его вправо,
     как остальные значения, незачем — подписи слева у него нет. */
  td[data-label="Товар"] > * { margin-left: 0; align-self: stretch; }
}

/* Правка количества прямо в строке плана. */
.inline-edit {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

.inline-edit input[type="number"] {
  width: 84px;
  padding: 6px 8px;
  text-align: right;
  font-weight: 700;
}

.inline-edit button {
  padding: 6px 10px;
  line-height: 1;
}

.error {
  background: var(--error-bg);
  border: 1px solid var(--error-line);
  color: var(--error-text);
  padding: 10px 12px;
  border-radius: var(--radius);
}

body.centered {
  display: flex;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.login {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.login h1 { font-size: 19px; margin: 0 0 4px; }
.login label { display: flex; flex-direction: column; gap: 6px; color: var(--muted); }

/* Кто вошёл и выход — прижаты к правому краю шапки. */
.who {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--muted);
}

.who button {
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
}

.who button:hover { color: var(--text); }


/* Кнопка, которая меняет данные в Ozon: должна отличаться от остальных. */
button.danger {
  padding: 9px 16px;
  border: 0;
  border-radius: var(--radius);
  background: var(--warn);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}

button.danger:hover { filter: brightness(0.92); }


/* Форма в столбик: поля пропуска заполняют с телефона, рядом они не помещаются. */
form.stack {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 420px;
}

form.stack label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }

form.stack input {
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 15px;
}

/* Алфавитный указатель над списками: в каталоге полторы сотни позиций
   с похожими названиями, и прокруткой нужную не найти.
   Указатель идёт **одной строкой**: перенос отрывал «Ю» и «Я» от остального
   алфавита, и выглядело это как отдельный ряд кнопок, а не как хвост
   азбуки. Если строка в экран не влезает (планшет, телефон), она
   прокручивается вбок — это по-прежнему одна строка.
   Прокрутка здесь безопасна: прилипшая шапка таблицы живёт в другом месте
   дерева, и этот `overflow` её не перехватывает. */
.alphabet {
  display: flex;
  flex-wrap: nowrap;
  gap: 3px;
  margin: 8px 0 16px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.alphabet a {
  display: inline-block; min-width: 20px; padding: 2px 4px;
  text-align: center; border-radius: 4px; text-decoration: none;
  color: var(--muted); font-size: 13px;
  /* Без этого узкие буквы сжимаются ещё сильнее и строка едет. */
  flex: 0 0 auto;
}
.alphabet a:hover { background: var(--hover); color: inherit; }
.alphabet a.active { background: var(--accent, #2b5cff); color: #fff; }

/* Итоги приёмки: подпись и число в одной строке, пары — в ряд.
   Браузер по умолчанию ставит `dd` под `dt`, и число уезжало на вторую
   строку — «Заявлено» и «30 390 шт.» читались как два разных пункта.
   Обёртка `div` вокруг каждой пары здесь обязательна и уже есть в шаблоне:
   без неё `display: flex` на `dl` развалил бы порядок. */
dl.totals {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin: 12px 0 16px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
dl.totals > div { display: flex; align-items: baseline; gap: 8px; }
dl.totals dt { color: var(--muted); font-size: 14px; }
dl.totals dd { margin: 0; font-weight: 700; }
/* Доля недовоза идёт сразу за числом, а не отдельной строкой: это
   пояснение к нему, а не самостоятельный показатель. */
dl.totals dd .small { font-weight: 400; }

/* Ссылка на справку по вкладке — внизу страницы, отделена чертой:
   это не часть содержимого, а выход из него. */
.page-help {
  margin: 28px 0 8px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

/* Разделы справки: заголовок ведёт на саму вкладку, а якорь совпадает
   с её ключом — ссылка «как работает эта вкладка» попадает прямо в нужное
   место. */
h2.help-head a { text-decoration: none; }
h2.help-head a:hover { text-decoration: underline; }

/* Отступ под прибитую шапку при переходе по якорю. Без него заголовок
   раздела оказывается ровно под верхней панелью, и человек попадает
   на середину чужого абзаца. */
h2[id] { scroll-margin-top: calc(var(--topbar) + 14px); }

/* Оглавление справки. Переносится, в отличие от алфавита: названия разделов
   длинные, и одной строкой они не встанут ни на каком экране. */
.toc {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  margin: 14px 0 24px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.toc a {
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
  font-size: 13px;
  white-space: nowrap;
}
.toc a:hover { background: var(--hover); }

/* Рентабельность цветом: от целевой — зелёным, ниже нижней границы —
   красным, между ними — как обычно. Сотню процентов глазами не разобрать.
   Не только цвет: зелёное ещё и полужирное, красное подчёркнуто точками —
   при дальтонизме и на плохом экране одного цвета мало. */
.share-good { color: var(--ok); font-weight: 700; }
.share-bad {
  color: var(--warn);
  font-weight: 700;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}

/* «Нет остатка» в калькуляторе: товара нет ни на Ozon, ни в пути, ни у нас,
   и подбирать ему цену бессмысленно. Приглушённый, а не тревожный: это
   не ошибка, а состояние. */
.badge-empty {
  display: inline-block;
  padding: 0 7px;
  border: 1px dashed var(--line);
  border-radius: 999px;
  color: var(--muted);
  white-space: nowrap;
}

/* Штрихкод моноширинным: так видно, что коды разной длины, и легче сверять. */
td.code { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 12px; }

/* Сортировка по столбцам: заголовок кликабелен, направление видно стрелкой. */
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.sortable:hover { color: var(--accent, #2b5cff); }
th.sortable::after { content: ""; opacity: .35; margin-left: 4px; }
th.sortable[aria-sort="ascending"]::after { content: "▲"; opacity: 1; }
th.sortable[aria-sort="descending"]::after { content: "▼"; opacity: 1; }

/* Раскладка по кластерам под строкой товара: как в кабинете Ozon.
   Свёрнута по умолчанию — позиций под две сотни, разворачивают одну. */
tr.details > td { padding: 0 12px 10px; border-top: 0; }
tr.details summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 13px;
  padding: 4px 0;
}
table.inner { width: auto; min-width: 380px; margin: 6px 0 4px; font-size: 13px; }
table.inner th, table.inner td { padding: 4px 10px; }

/* «Прочее» в калькуляторе: сумма видна сразу, состав — по щелчку. Влиять
   на расход, не зная, что внутри, нельзя, а тринадцать колонок не читаются. */
details.parts { margin-top: 2px; }
details.parts summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 12px;
  font-weight: 400;
}
details.parts table.inner { min-width: 0; text-align: left; }
details.parts table.inner td { white-space: nowrap; }
form.inline { display: inline-flex; gap: 6px; align-items: center; margin: 0; }

/* Форма без своих полей: поля стоят в таблице и ссылаются на неё атрибутом
   form, потому что вложенную форму браузер выбрасывает молча. */
form.hidden-form { display: none; }

/* Справка «как считается» на калькуляторе: свёрнута, потому что читают её
   один раз, а место занимает постоянно. */
details.howto { margin: 0 0 14px; }
details.howto summary { cursor: pointer; color: var(--accent); padding: 4px 0; }
details.howto dl { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
details.howto dt { font-weight: 600; color: var(--text); margin-top: 8px; }
details.howto dd { margin: 2px 0 0 16px; }
td input[type="number"] { width: 72px; text-align: right; }

/* Дашборд. Две колонки на широком экране: слева динамика, справа то, что
   требует вмешательства. На узком они становятся друг под другом — кабинет
   открывают и с телефона. */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  align-items: start;
  margin-bottom: 18px;
}
.split > section { min-width: 0; }

/* Поля подбора закупочной цены: подпись слева, поле и пояснение справа.
   Пояснение обязательно рядом с каждым полем — числа в них измеренные,
   и без «откуда это» их правили бы наугад. */
dl.fields {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: 8px 14px;
  align-items: baseline;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
}
dl.fields dt { color: var(--muted); font-size: 14px; }
dl.fields dd { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
dl.fields input { width: 110px; padding: 7px 9px; text-align: right; }
dl.fields .small { flex: 1 1 14rem; }
dl.fields select { padding: 7px 9px; }

/* Габариты упаковки: три поля в строку через знак умножения. */
.sides { display: inline-flex; align-items: center; gap: 6px; }
.sides input { width: 68px; }

/* Подсказка у поля. Короткая видна всегда, длинная раскрывается по нажатию
   на «?»: только `title` не годится — на планшете его не вызвать, а кабинет
   открывают именно с планшета. */
.field-note { display: block; }
.hint-mark {
  display: inline-block;
  width: 17px;
  height: 17px;
  margin-left: 4px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  line-height: 15px;
  text-align: center;
  cursor: pointer;
  vertical-align: middle;
}
.hint-mark:hover, .hint-mark.open { border-color: var(--accent); color: var(--accent); }
/* Подсказка всплывает **над** значком при наведении, а не раздвигает
   форму. Раздвигала — и поля уезжали вниз, из-за чего соседнее поле
   приходилось искать заново.
   `:focus-within` нужен для клавиатуры, класс `open` — для планшета:
   там наведения нет вовсе, и подсказку открывает нажатие. */
.hint { position: relative; display: inline-block; }
.hint-text {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  display: none;
  width: max-content;
  max-width: 320px;
  padding: 9px 11px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 6px 18px rgb(0 0 0 / 18%);
  color: var(--text);
  text-align: left;
  white-space: normal;
}
.hint:hover .hint-text,
.hint:focus-within .hint-text,
.hint-text.open { display: block; }

/* Хвостик к значку: без него облачко висит в воздухе и непонятно,
   к какому полю оно относится. */
.hint-text::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -6px;
  border: 6px solid transparent;
  border-top-color: var(--line);
}

@media (max-width: 560px) {
  /* На телефоне подпись встаёт над полем: в две колонки они не помещаются,
     и пояснение сжималось бы в столбик по одному слову. */
  dl.fields { grid-template-columns: 1fr; gap: 2px; }
  dl.fields dd { margin-bottom: 10px; }
}

/* Карточка «требует внимания»: цветная полоса слева отделяет то, что надо
   делать сейчас, от того, на что достаточно посмотреть. */
.alert {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin-bottom: 10px;
}
.alert.action { border-left-color: var(--warn); }
.alert.watch { border-left-color: #d59f0f; }
.alert-head { display: flex; justify-content: space-between; gap: 10px; align-items: center; }
.alert-metric { color: var(--muted); font-size: 13px; margin-top: 2px; }
.alert-values { display: flex; gap: 10px; margin: 8px 0 4px; flex-wrap: wrap; }
.alert-values > div {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 4px 10px;
  min-width: 92px;
}
.alert-values dt { color: var(--muted); font-size: 11px; text-transform: uppercase; }
.alert-values dd { margin: 2px 0 0; font-weight: 600; }

.badge {
  font-size: 11px;
  text-transform: uppercase;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}

/* Динамика полосками, а не графиком: читается без скриптов и печатается.
   Числа рядом, потому что по длине полоски сумму не назовёшь. */
table.bars td { padding: 3px 8px; border-top: 0; }
table.bars td.day { color: var(--muted); font-size: 12px; white-space: nowrap; }
table.bars td.bar { width: 55%; }
table.bars td.bar span {
  display: block;
  height: 10px;
  min-width: 1px;
  border-radius: 3px;
  background: var(--accent);
  opacity: 0.75;
}

@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
}

/* На планшете шапка не держится наверху, и это не мелочь оформления.
   Навигация из тринадцати вкладок переносится там на три-четыре строки
   и занимает 190 пикселей — четверть экрана, которая стояла бы постоянно,
   пока под ней прокручивается таблица. Именно это и было видно: сверху
   полоса, под ней едут товары. На ноутбуке шапка умещается в одну-две
   строки и стоит дёшево, поэтому там она остаётся прибитой.
   `--topbar` здесь обнуляется: места резервировать не надо, а шапка
   таблицы встаёт к самому верху окна. То же значение ставит и скрипт —
   он смотрит на вычисленный стиль, чтобы порог жил в одном месте. */
@media (max-width: 1100px) {
  .top { position: static; }
  :root { --topbar: 0px; }
}

/* Названия товаров длинные — «Memories_lab COTTON SUNDAY духи женские…» —
   и без ограничения они растягивают таблицу шире экрана, уводя за правый
   край остаток и запас, ради которых в неё и смотрят. Правило общее
   на все списки, а не только на дашборд: название занимало по 860 пикселей
   в калькуляторе и по полтысячи в остатках.
   Только на широком экране: ниже 720px строка и так становится карточкой,
   а 420 пикселей там шире самого экрана и дают прокрутку вбок. */
@media (min-width: 721px) {
  td .name { display: block; max-width: 320px; white-space: normal; }
}

/* Калькулятор тесный по существу: семнадцать колонок, и в четырёх из них
   поля ввода. Чтобы он помещался в окно целиком, ему нужны свои мерки —
   иначе ради него пришлось бы ужимать все остальные страницы.
   Подписи под числом («тариф 48%, факт 46%», «расходится») встают
   отдельной строкой: в одну строку с числом они растягивали колонку
   вдвое, а читаются и сверху вниз. */
table[data-calculator] th, table[data-calculator] td { padding: 8px 6px; }
table[data-calculator] td .name { max-width: 260px; }
table[data-calculator] input[type="text"] { width: 62px; }
table[data-calculator] td.num .small { display: block; white-space: normal; }

/* Подсказанная цена под целевую рентабельность. Кнопка, а не ссылка: она
   никуда не ведёт, а подставляет число в поле рядом. Выглядит ссылкой,
   потому что это подсказка, а не действие с последствиями. */
button.hint {
  display: block;
  margin: 2px 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
button.hint:hover { text-decoration: underline; }

/* Название товара в карточке «требует внимания»: артикул сам по себе
   ничего не говорит, и по нему приходилось идти искать, о чём речь. */
.alert-name { margin-top: 2px; }

/* Индекс цены: вердикт строкой, под ним числа Ozon по каждому источнику. */
td.index { white-space: nowrap; }
td.index span { display: block; }

/* Значок индекса цены в калькуляторе: ведёт на страницу цены в кабинете
   Ozon — там индекс и правят, а здесь места на подробности нет. */
.index-badge {
  display: inline-block;
  font-size: 12px;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 0 7px;
  text-decoration: none;
  white-space: nowrap;
}
.index-badge:hover { text-decoration: underline; }
