/* Design Palette v1 — источник значений цвета для интерфейса.
   Семантика: teal — интерактив (ссылка, primary, active, focus); зелёный — успех;
   красный — ошибка и деструктивное действие; янтарный — предупреждение;
   серый — нейтральное/неизвестное. Teal не означает «хороший показатель». */
:root{
  /* поверхности */
  --bg:#f6f7f9; --card:#ffffff; --surface-muted:#f0f2f5; --line:#e4e7ec;
  /* текст */
  --fg:#101828; --muted:#667085; --off:#6b7185;
  /* интерактив */
  --accent:#0f766e; --accent-hover:#115e59; --accent-fg:#ffffff; --focus-ring:#0f766e38;
  /* состояния */
  --ok-bg:#e6f6ec; --ok-fg:#146c34;
  --err-bg:#fdeaea; --err-fg:#b42318;
  --warn-bg:#fdf3e3; --warn-fg:#b54708;
  --danger:#d92d20;
  /* Статусы прогонов монитора: график в routers/dashboard.py и легенда в
     dashboard.html. У каждой темы своё значение — см. dark-блок ниже. */
  --run-ok:#16a34a; --run-partial:#d97706; --run-running:#2563eb; --run-unknown:#6b7185;
  /* Серии графиков. Независимы от семантики состояний: зелёный и красный сюда
     намеренно не входят, иначе «третья серия» читалась бы как оценка.
     --chart-5 (fuchsia) — цвет серии и только серии: ни кнопок, ни навигации,
     ни карточек, ни статусов. Привязка «серия → chart-N» делается на этапе
     редизайна графиков; сейчас существующие графики их ещё не используют. */
  --chart-1:#0f766e; --chart-2:#2563eb; --chart-3:#7c3aed;
  --chart-4:#d97706; --chart-5:#c026d3; --chart-6:#475569;
  /* Типографика. Системный стек: CSP запрещает внешние шрифты, self-hosted
     файлы того не стоят. base — основной текст страницы и тело таблиц:
     14px оставлен намеренно, замер показал, что 13px даёт 3–5px ширины на
     самых широких таблицах и ни одной дополнительной колонки. */
  --font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --text-2xs:11px; --text-xs:12px; --text-sm:13px;
  --text-base:14px; --text-lg:15px; --text-xl:22px;
  --leading-tight:1.25; --leading-normal:1.45;
  --weight-normal:400; --weight-medium:500; --weight-semibold:600; --weight-bold:700;
  --radius-sm:8px; --radius-md:12px; --radius-lg:16px;
  --shadow-sm:0 1px 2px rgba(16,24,40,.04), 0 1px 2px rgba(16,24,40,.06);
  --shadow-md:0 2px 4px rgba(16,24,40,.04), 0 4px 8px rgba(16,24,40,.05);
}
@media (prefers-color-scheme: dark){
  :root{
    /* Тот же набор токенов и тот же смысл, другой регистр яркости.
       Карточка отделяется от фона тоном и границей, а не тенью. */
    --bg:#0e1116; --card:#151a21; --surface-muted:#1b212a; --line:#262e3a;
    --fg:#e6eaf0; --muted:#97a3b4; --off:#7c8899;
    /* на ярком teal текст обязан быть тёмным; hover в тёмной теме светлеет */
    --accent:#2dd4bf; --accent-hover:#5eead4; --accent-fg:#062522; --focus-ring:#2dd4bf40;
    --ok-bg:#10291c; --ok-fg:#7ee2a8;
    --err-bg:#341417; --err-fg:#fca5a5;
    --warn-bg:#33260f; --warn-fg:#fbbf24;
    --danger:#f87171;
    --run-ok:#22c55e; --run-partial:#f59e0b; --run-running:#60a5fa; --run-unknown:#7c8899;
    --chart-1:#2dd4bf; --chart-2:#60a5fa; --chart-3:#a78bfa;
    --chart-4:#fbbf24; --chart-5:#e879f9; --chart-6:#94a3b8;
    --shadow-sm:none; --shadow-md:none;
  }
}
*{box-sizing:border-box}
/* Явные свойства вместо shorthand font: тот незаметно сбрасывал остальные
   font-* и мешал бы управлять типографикой через токены. */
body{margin:0;font-family:var(--font-sans);font-size:var(--text-base);
  line-height:var(--leading-normal);background:var(--bg);color:var(--fg)}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
/* .app-content — контент внутри shell (есть sidebar/header, ширину даёт grid).
   .app-content--plain — рендер без shell (сейчас только /login): сохраняет
   прежнее поведение .wrap, включая центрирующий max-width. */
.app-content{padding:20px 16px 48px;max-width:none}
.app-content--plain{max-width:1600px;margin:0 auto;padding:20px 20px 48px}
h1{font-size:var(--text-xl);font-weight:var(--weight-bold);line-height:var(--leading-tight);
  letter-spacing:-.01em;margin:.2em 0 .5em}
h2{font-size:var(--text-lg);font-weight:var(--weight-semibold);line-height:var(--leading-tight);
  margin:0 0 14px}
/* Раньше h3 не имел правила и брал размер из UA-стилей (17.55px), из-за чего
   был крупнее h2. Отступы намеренно оставлены браузерные — они em-относительные
   и меняются пропорционально; фиксировать их — задача этапа компонентов. */
h3{font-size:var(--text-base);font-weight:var(--weight-semibold);line-height:var(--leading-tight)}
.muted{color:var(--muted)}
.small{font-size:var(--text-xs)}

/* Application shell: постоянный sidebar + узкий header. #nav-toggle лежит
   прямо в <body>, соседом .app-shell — это даёт комбинатору ~ доступ к
   .app-shell из чекбокса независимо от того, где внутри дерева стоит сам
   переключатель (у <label for> связь идёт по id, а не по DOM-соседству). */
.app-shell{display:grid;grid-template-columns:220px minmax(0,1fr);min-height:100vh}
/* Desktop: чекбокс отмечен -> sidebar скрыт, контенту возвращается вся ширина.
   minmax(0,1fr) обязателен — без него широкая таблица растянет grid-колонку
   и потянет за собой прокрутку всей страницы вместе с sidebar. */
#nav-toggle:checked ~ .app-shell{grid-template-columns:0 minmax(0,1fr)}
#nav-toggle:checked ~ .app-shell .sidebar{display:none}

.sidebar{grid-column:1;background:var(--card);border-right:1px solid var(--line);
  padding:12px 10px;position:sticky;top:0;height:100vh;align-self:start;overflow-y:auto}
.brand{display:flex;align-items:center;height:44px;padding:0 10px;
  font-size:var(--text-base);font-weight:var(--weight-bold);color:var(--fg)}
/* Кнопка закрытия mobile-оверлея. На desktop не существует визуально; sidebar
   уже position:sticky (desktop) / position:fixed (mobile open) — оба значения
   уже «positioned», поэтому .sidebar сам по себе служит containing block для
   абсолютного позиционирования, отдельный position:relative не нужен. */
.sidebar-close{display:none}
.side-nav{display:flex;flex-direction:column;gap:2px}
.side-group{font-size:var(--text-2xs);text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);padding:10px 10px 4px}
.side-link{display:flex;align-items:center;gap:8px;min-height:32px;padding:6px 10px;
  border-radius:var(--radius-sm);font-size:var(--text-sm);font-weight:var(--weight-medium);
  color:var(--muted)}
.side-link:hover{background:var(--surface-muted);color:var(--fg);text-decoration:none}
/* Полоса слева, не заливка всей строки: активный пункт заметен, но не читается
   как кнопка действия (accent — это интерактив, а не «текущее место»). */
.side-link.is-active{background:var(--surface-muted);color:var(--fg);
  box-shadow:inset 2px 0 0 var(--accent)}

/* grid-column закреплён явно: без него, когда .sidebar уходит в display:none
   при collapse, она полностью выпадает из grid-раскладки, и .app-main
   авто-размещается в освободившуюся первую (нулевую) колонку вместо второй. */
.app-main{grid-column:2;min-width:0}
.app-header{display:flex;align-items:center;gap:12px;min-height:48px;padding:0 16px;
  background:var(--card);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:5}
.app-header .spacer{flex:1}
.app-header .who{color:var(--muted);font-size:var(--text-xs)}
.app-header .logout{color:var(--danger)}

/* Один и тот же переключатель служит и desktop-сжатием, и mobile-раскрытием
   sidebar — смысл состояния checked меняет медиазапрос ниже. */
.nav-toggle{display:none}
.burger{display:flex;flex-direction:column;justify-content:center;gap:4px;
  width:32px;height:32px;padding:8px;border-radius:var(--radius-sm);cursor:pointer}
.burger:hover{background:var(--surface-muted)}
.burger span{display:block;width:100%;height:2px;background:var(--fg);border-radius:1px}

.health-dots{display:flex;gap:7px;margin-right:14px}
.health-dot{width:9px;height:9px;border-radius:50%;background:var(--muted);display:inline-block;
  transition:transform .12s}
.health-dot:hover{transform:scale(1.3)}
.health-dot.ok{background:#22c55e}
.health-dot.warn{background:#f59e0b}
.health-dot.off{background:var(--muted)}

.flash{padding:12px 16px;border-radius:var(--radius-sm);margin:14px 0;font-size:var(--text-base)}
.flash.ok{background:var(--ok-bg);color:var(--ok-fg)}
.flash.err{background:var(--err-bg);color:var(--err-fg)}
.flash.warn{background:var(--warn-bg);color:var(--warn-fg)}
/* Сообщение об ошибке сразу под формой фильтра: тот же отступ, что раньше
   задавался инлайном в пяти шаблонах. Нижний отступ остаётся от .flash. */
.flash.after-form{margin-top:8px}

.notice{background:var(--card);border:1px solid var(--line);border-radius:var(--radius-md);
  padding:12px 14px;color:var(--muted);font-size:var(--text-base);margin:12px 0;box-shadow:var(--shadow-sm)}
.notice b{color:var(--fg)}

.login-box{max-width:420px;margin:8vh auto;background:var(--card);padding:36px;
  border:1px solid var(--line);border-radius:var(--radius-lg);text-align:center;box-shadow:var(--shadow-md)}
.login-box h1{margin-top:0}

.search{display:flex;gap:8px;margin:16px 0}
.search input{flex:1}
input,select{border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--card);color:var(--fg);font-size:var(--text-sm);transition:box-shadow .12s,border-color .12s}
/* Единая высота контролов в строке фильтров. checkbox и radio исключены: это
   нативные choice-контролы, floor их бы раздул (radio в проекте пока нет, но
   правило должно быть верным заранее). date и file остаются чуть выше —
   у них своя интринсивная высота в WebKit, форсировать height нельзя. */
input:not([type=checkbox]):not([type=radio]),select,textarea{
  min-height:32px;padding:6px 10px;line-height:18px}
input:focus,select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--focus-ring)}
textarea{width:100%;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--card);color:var(--fg);font-size:var(--text-sm);font-family:inherit;resize:vertical;
  transition:box-shadow .12s,border-color .12s}
textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--focus-ring)}
button{min-height:32px;padding:6px 12px;line-height:18px;border:0;border-radius:var(--radius-sm);
  background:var(--accent);color:var(--accent-fg);font-size:var(--text-sm);font-weight:var(--weight-medium);
  cursor:pointer;transition:opacity .12s,transform .06s}
button:hover{opacity:.9}
/* Primary — единственная кнопка с акцентной заливкой, поэтому её hover теперь
   реальный цвет, а не приглушение прозрачностью. Варианты с другой семантикой
   (.danger, .tab, .btn-link) исключены и сохраняют прежнее поведение. */
button:not(.tab):not(.danger):not(.btn-link):hover{background:var(--accent-hover);opacity:1}
button:active{transform:translateY(1px)}
button.mini{min-height:26px;padding:3px 8px;font-size:var(--text-sm)}
button.danger{background:var(--danger)}
.btn-link{display:inline-block;color:var(--muted)}

.table-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius-md);background:var(--card);
  box-shadow:var(--shadow-sm);scrollbar-color:var(--muted) transparent;scrollbar-width:thin}
.table-wrap::-webkit-scrollbar{height:10px;width:10px}
.table-wrap::-webkit-scrollbar-track{background:transparent}
.table-wrap::-webkit-scrollbar-thumb{background:var(--muted);border-radius:6px}
.table-wrap.scroll-y{max-height:70vh;overflow-y:auto}
.table-wrap.scroll-y thead th{position:sticky;top:0;background:var(--card);z-index:1;box-shadow:0 1px 0 var(--line)}
table.freeze-col th:first-child,
table.freeze-col td:first-child{position:sticky;left:0;background:var(--card);z-index:1;
  box-shadow:1px 0 0 var(--line)}
table.freeze-col thead th:first-child{z-index:2}
tbody tr:hover td:first-child{background:var(--surface-muted)}
table{width:100%;border-collapse:collapse;font-size:var(--text-base)}
th,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--line);white-space:nowrap}
/* Заголовок мельче тела и с меньшим трекингом: ширину колонок в широких
   таблицах задаёт именно он, а не содержимое ячеек. */
th{font-weight:var(--weight-semibold);color:var(--muted);font-size:var(--text-2xs);
  text-transform:uppercase;letter-spacing:.02em}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover td{background:var(--surface-muted)}
td.name{white-space:normal;max-width:260px;color:var(--fg)}
td.sku{white-space:normal;max-width:170px}
table.compact th,table.compact td{padding:5px 10px}
table.compact td.name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:340px}
table.compact td.sku{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:150px}
.muted-row{opacity:.72}
/* Только плотность .compact (5×10), БЕЗ его мобильного card-stack —
   расписание ставок биддера (25 колонок-часов) на mobile должно остаться
   обычной прокручиваемой таблицей с видимым thead, а не превращаться в
   карточки без подписи часа (Stage 4 review, IMPORTANT 4). */
.bidder-schedule-table th,.bidder-schedule-table td{padding:5px 10px}
.num{text-align:right;font-variant-numeric:tabular-nums}
th.sortable{cursor:pointer;user-select:none}
th.sortable:hover{color:var(--fg)}
th.sortable::after{content:'\2195';margin-left:4px;opacity:.4}
th.sortable.sort-asc::after{content:'\2191';opacity:1}
th.sortable.sort-desc::after{content:'\2193';opacity:1}
.cur-hour{background:var(--ok-bg);font-weight:700}
th.cur-week,td.cur-week{background:var(--ok-bg)}
table.freeze-col th.cur-week:first-child,table.freeze-col td.cur-week:first-child{background:var(--card)}
tr.off td{color:var(--off)}
.pct-good{color:var(--ok-fg);font-weight:600}
.pct-warn{color:var(--warn-fg);font-weight:600}
.pct-bad{color:var(--err-fg);font-weight:600}
.pct-none{color:var(--off)}

.badge{font-size:var(--text-xs);font-weight:var(--weight-medium);padding:2px 8px;border-radius:20px;white-space:nowrap}
.badge.on{background:var(--ok-bg);color:var(--ok-fg)}
.badge.off{background:var(--line);color:var(--muted)}
.badge.warn{background:var(--warn-bg);color:var(--warn-fg)}
.badge.err{background:var(--err-bg);color:var(--err-fg)}

/* .product-section — раздел KPI-дашборда товара (Stage 4): та же поверхность,
   что .card, объединена общим селектором (не byte-copy), чтобы будущая правка
   .card не разъезжалась с разделами страницы товара (Stage 4 review, MINOR 2).
   Именуется отдельно от .card, т.к. это конкретно «аналитический раздел
   страницы товара», а не произвольный card где угодно в проекте. */
.card,.product-section{background:var(--card);border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:16px 18px;margin:16px 0;box-shadow:var(--shadow-sm)}

/* Глобальный выключатель биддера. Цветная полоса слева — единственный элемент
   на странице, который меняет вид от состояния: остальное сознательно нейтрально,
   чтобы «выключен» читалось как факт, а не как ошибка. */
.bidder-power{display:flex;flex-wrap:wrap;gap:14px 20px;align-items:center;
  justify-content:space-between;border-left:4px solid var(--ok-fg)}
.bidder-power.is-off{border-left-color:var(--warn-fg)}
.bidder-power-state{display:flex;gap:12px;align-items:flex-start;min-width:0;flex:1 1 340px}
.bidder-power-form{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
/* Выключенный товар в списке: приглушаем, но оставляем читаемым — это рабочее
   состояние, а не ошибка. */
a.bidder-item.is-off .bidder-item-name{color:var(--muted)}

/* Размер задаётся не якорю, а самому названию: 15px нужны только заголовку
   элемента, а бейджи и подписи внутри имеют свои размеры. */
a.bidder-item{display:flex;align-items:center;flex-wrap:wrap;gap:8px;font-weight:var(--weight-semibold);
  color:var(--fg);text-decoration:none;transition:border-color .12s,background .12s}
a.bidder-item:hover{border-color:var(--muted);background:var(--bg);text-decoration:none}
.bidder-item-name{color:var(--fg);font-size:var(--text-lg);font-variant-numeric:tabular-nums}

details.toggle > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  padding:6px 12px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--card);
  font-size:var(--text-base);font-weight:var(--weight-medium);color:var(--fg);user-select:none}
details.toggle > summary::-webkit-details-marker{display:none}
details.toggle > summary:hover{background:var(--bg)}
details.toggle > summary::after{content:'\25B8';color:var(--muted)}
details.toggle[open] > summary::after{content:'\25BE'}
details.toggle[open] > summary{margin-bottom:14px}
.grid{display:flex;flex-wrap:wrap;gap:10px;align-items:end}
.grid label{display:flex;flex-direction:column;gap:4px;font-size:var(--text-xs);color:var(--muted)}
.grid input,.grid select{min-width:150px}
.grid label.check-inline{flex-direction:row;align-items:center;gap:6px;padding-bottom:9px;white-space:nowrap}
.grid label.check-inline input[type=checkbox]{width:auto;min-width:0}

.tabs{display:flex;flex-wrap:wrap;gap:6px;margin:14px 0}
.tab{background:var(--card);border:1px solid var(--line);color:var(--muted);
  padding:5px 12px;line-height:18px;border-radius:20px;font-size:var(--text-sm);
  font-weight:var(--weight-medium);cursor:pointer;transition:all .12s}
.tab:hover{color:var(--fg);border-color:var(--muted)}
.tab.active{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}
.tab .count{opacity:.75;margin-left:2px}

.addrow{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}
.addrow input[name=value]{flex:1;min-width:240px}
.w-prio{width:80px}
.w-note{width:140px}
form.inline{display:flex;gap:6px;align-items:center;margin:0}
.hist{margin-left:6px;color:var(--muted)}
.meta{font-size:var(--text-base);color:var(--muted)}
.meta b{color:var(--fg)}

td.sel-cell{cursor:cell}
td.sel-cell.is-selected{outline:2px solid var(--accent);outline-offset:-2px;
  box-shadow:inset 0 0 0 2px var(--accent)}
body.sel-noselect{user-select:none}
.sel-stats{margin-top:10px;padding:8px 12px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius-sm);font-size:var(--text-sm);color:var(--muted)}
.sel-stats b{color:var(--fg);font-variant-numeric:tabular-nums}
.sel-stats .sel-copy-btn{margin-left:12px}

.unit-toolbar{margin-bottom:10px}
table.unit-table td.detail-col,
table.unit-table th.detail-col{display:none}
table.unit-table.show-detail td.detail-col,
table.unit-table.show-detail th.detail-col{display:table-cell}
.unit-group-row th{text-align:center;font-size:var(--text-2xs);text-transform:uppercase;letter-spacing:.04em;
  border-bottom:1px solid var(--line)}
/* Группа колонок ≠ статус: единый нейтральный фон вместо трёх decorative
   color-mix оттенков (Stage 4 table-audit) — colspan-заголовок и так называет
   группу текстом, красить её акцентным/danger/ok было чистым декором. */
.unit-group-price,.unit-group-expense,.unit-group-total{background:var(--surface-muted)}
tr.good td:nth-last-child(6),tr.good td:nth-last-child(5){color:var(--ok-fg)}
tr.warn td:nth-last-child(6),tr.warn td:nth-last-child(5){color:var(--warn-fg)}
tr.bad td:nth-last-child(6),tr.bad td:nth-last-child(5){color:var(--err-fg);font-weight:600}
/* .total-row — тот же паттерн «Итого», что unit-totals-row уже задавал только
   для /unit; вынесен в общий селектор, чтобы /sales и /supply не дублировали
   его инлайновым style. Свойства объединены группировкой, не переименованием —
   .unit-totals-row остаётся собственным именем, обе просто делят правила. */
.unit-totals-row,.total-row{font-weight:700;background:var(--surface-muted)}
/* Замороженная первая ячейка красится собственным фоном (table.freeze-col
   td:first-child), иначе строка «Итого» распадалась бы на две поверхности. */
table.freeze-col .unit-totals-row td:first-child,
table.freeze-col .total-row td:first-child{background:var(--surface-muted)}
.unit-totals-row td,.total-row td{border-bottom:2px solid var(--line)}
/* Ячейка с единственным действием (кнопка/форма-в-ячейке без другого контента):
   выравнивание вправо, без декоративной рамки-разделителя. */
.cell-actions{text-align:right}
.unit-summary-grid{display:flex;flex-wrap:wrap;gap:20px 32px;margin:10px 0}
/* Значение KPI: намеренно крупнее подписи и h3 — иерархия здесь
   «заголовок раздела → контекст → число», а не «заголовок всегда крупнее». */
.unit-summary-grid b{font-size:var(--text-lg)}
/* KPI-дельта vs предыдущий период (Stage 4): намеренно нейтральный цвет, не
   зелёный/красный — направление "лучше/хуже" не всегда однозначно (ДРР ↓ это
   хорошо, продажи ↓ это плохо), Stage 4 не берётся судить за все метрики сразу. */
.delta{color:var(--muted);font-size:var(--text-sm);font-variant-numeric:tabular-nums;
  margin-left:6px;white-space:nowrap}

/* Текстовая кнопка-ссылка: общий 32px floor её бы превратил в блок.
   Размер намеренно не задаётся — 13px приходят от общего button, а класс
   .small на такой кнопке остаётся рабочим и даёт свои 12px. */
button.btn-link{background:none;color:var(--muted);min-height:0;padding:2px 0;line-height:inherit;
  font-weight:var(--weight-normal)}
button.btn-link:hover{color:var(--accent);text-decoration:underline;opacity:1}

.unit-whatif-row td{background:color-mix(in srgb, var(--accent) 4%, var(--bg));padding:14px 16px}
.whatif-panel{max-width:680px}
.whatif-inputs{display:flex;flex-wrap:wrap;gap:14px;align-items:end;margin-bottom:6px}
.whatif-inputs label{display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--muted)}
.whatif-inputs input{width:120px}
.wi-vol-note{min-height:1.2em;margin:2px 0 10px}
table.whatif-compare{background:var(--card)}
table.whatif-compare td{font-variant-numeric:tabular-nums}
table.whatif-compare td:first-child{color:var(--muted)}
table.whatif-compare tr.wi-key td{font-weight:700}
.wi-delta{font-variant-numeric:tabular-nums}
.wi-delta.wi-up{color:var(--ok-fg)}
.wi-delta.wi-down{color:var(--err-fg)}
.wi-delta.wi-same{color:var(--muted)}

.unit-whatif-checkbox{display:inline-flex;align-items:center;gap:5px;font-size:12px;
  color:var(--muted);white-space:nowrap;cursor:pointer;margin-top:2px}
.unit-whatif-checkbox input[type=checkbox]{width:auto;min-width:0;margin:0}

.summary-datebar{display:flex;flex-wrap:wrap;gap:10px;align-items:end;margin:10px 0 4px}
.summary-datebar label{font-size:12px;color:var(--muted)}
.summary-datebar input,.summary-datebar select{display:block;margin-top:2px}
.block-datebar{display:flex;flex-wrap:wrap;gap:8px;align-items:end;margin:6px 0 2px}
.block-datebar label{font-size:11px;color:var(--muted)}
.block-datebar input{display:block;margin-top:2px}
/* Локальный compact-вариант: высоту задаёт собственный padding, а не общий
   32px floor от button — иначе padding здесь становится инертным. */
.block-datebar button{min-height:0;font-size:12px;padding:3px 8px}
.block-override-badge{color:var(--warn-fg);font-weight:600}
/* --- Единая система графиков карточки товара (Chart UX pass) ---------------
   Геометрия самих SVG живёт в svg_charts.py (там она нужна для расчёта
   отступов под подписи осей); здесь — только обвязка: заголовок, подпись,
   ширина контейнера, легенда. */
.chart-row{display:flex;flex-wrap:wrap;gap:24px;margin:12px 0;align-items:flex-start}
.chart-box svg{display:block;max-width:100%;height:auto}
.chart-box{min-width:0}
/* Заголовок/подпись графика — одна типографика для всех графиков карточки,
   вместо разнобоя из <span class="muted small"> + <br>. */
.chart-title{display:block;font-size:var(--text-sm);font-weight:var(--weight-semibold);
  color:var(--fg);line-height:var(--leading-tight)}
.chart-caption{display:block;font-size:var(--text-2xs);color:var(--muted);margin:1px 0 8px}
/* Главные аналитические графики (продажи по дням, мы vs конкуренты) — на всю
   ширину секции, а не узкой полоской слева: ширину задаёт viewBox SVG,
   контейнер только не даёт растянуться сверх осмысленного. */
/* Primary-графики (продажи по дням, мы vs конкуренты) — во всю доступную ширину
   секции: собственный потолок задаёт viewBox SVG (1100), поэтому здесь кап не
   нужен, иначе на широком мониторе справа оставалась пустота. */
.chart-box-main{margin:12px 0}
/* flex-basis обязателен: внутри .chart-row у SVG с width="100%" нет собственной
   ширины, и flex-item схлопывается до самой длинной строки подписи (полоса
   разложения цены сжималась до ~330px вместо 560). */
.chart-box-wide{margin:12px 0;max-width:620px;flex:1 1 520px}
/* Тренд доли делит .chart-row с donut: без basis его SVG с width="100%" так же
   схлопывается до ширины подписи. Потолок 560 — он намеренно подчинён
   primary-графикам и не должен разрастаться на всю строку. */
.chart-box-trend{flex:1 1 460px;max-width:560px}
/* Hover-подсказка (static/js/chart_tooltip.js). Контейнер становится системой
   координат для абсолютно позиционированного tooltip. */
.chart-hoverable{position:relative}
.chart-hoverable svg{cursor:crosshair}
.chart-hover-guide{stroke:var(--muted);stroke-width:1;stroke-dasharray:3 3;opacity:.7}
.chart-hover-dot{stroke:var(--card);stroke-width:2}
.chart-tooltip{position:absolute;z-index:4;pointer-events:none;min-width:120px;max-width:280px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:0 4px 14px rgba(0,0,0,.18);padding:8px 10px;font-size:var(--text-xs);color:var(--fg)}
.chart-tooltip[hidden]{display:none}
.chart-tooltip-date{font-weight:var(--weight-semibold);margin-bottom:5px;color:var(--fg)}
.chart-tooltip-row{display:flex;align-items:center;gap:6px;line-height:1.7;white-space:nowrap}
.chart-tooltip-row i{flex:none;width:9px;height:9px;border-radius:2px}
.chart-tooltip-label{overflow:hidden;text-overflow:ellipsis;color:var(--muted)}
.chart-tooltip-row b{margin-left:auto;font-variant-numeric:tabular-nums}
.chart-tooltip-row.is-empty b{color:var(--muted);font-weight:var(--weight-medium)}
.chart-legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:var(--text-2xs);
  color:var(--muted);margin:8px 0 0}
.chart-legend i{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:5px;vertical-align:middle}

@media (max-width:760px){
  .app-content,.app-content--plain{padding:16px 12px 50px}
  h1{font-size:21px}

  /* Тот же #nav-toggle, обратный смысл: по умолчанию sidebar скрыт оверлеем,
     чекбокс его показывает поверх контента. Один явный трек: без сброса
     .app-main{grid-column:1} унаследованный desktop-овый grid-column:2 создаёт
     неявную вторую колонку — контент уезжает вправо, слева пустой трек. */
  .app-shell{grid-template-columns:minmax(0,1fr)}
  #nav-toggle:checked ~ .app-shell{grid-template-columns:minmax(0,1fr)}
  .app-main{grid-column:1}
  .sidebar{display:none;position:fixed;top:0;left:0;z-index:10;width:220px;box-shadow:var(--shadow-md)}
  #nav-toggle:checked ~ .app-shell .sidebar{display:block}
  /* Sidebar-оверлей (z-index:10) лежит поверх .app-header (z-index:5), поэтому
     существующий burger там недоступен для клика, пока меню открыто — нужна
     отдельная точка закрытия внутри самого sidebar. */
  .sidebar-close{display:flex;align-items:center;justify-content:center;
    position:absolute;top:8px;right:8px;width:28px;height:28px;z-index:1;
    border-radius:var(--radius-sm);color:var(--muted);background:transparent;
    font-size:var(--text-lg);line-height:1;cursor:pointer}
  .sidebar-close:hover{background:var(--surface-muted);color:var(--fg)}
  .app-header{padding:10px 14px}
  .app-header .who{display:none}
  .health-dots{margin-right:6px}

  table.compact{display:block}
  table.compact thead{display:none}
  table.compact tbody{display:block}
  table.compact tr{display:block;margin:10px;border:1px solid var(--line);
    border-radius:var(--radius-md);padding:4px 12px}
  table.compact td{display:flex;justify-content:space-between;align-items:center;gap:10px;
    white-space:normal;max-width:none;text-align:left;overflow:visible;text-overflow:clip}
  table.compact td::before{content:attr(data-label);color:var(--muted);font-size:var(--text-2xs);
    font-weight:600;text-transform:uppercase;letter-spacing:.03em;flex:0 0 auto}
  table.compact td.name,table.compact td.sku{white-space:normal}
  .table-wrap.scroll-y{max-height:none}
}

/* Выбор диапазона дат одним календарём (js/date_range.js). Без скрипта блок
   остаётся парой обычных полей type=date и стилей ниже не касается. */
.daterange{position:relative;display:inline-block}
.daterange-field{min-width:150px;text-align:left}
.daterange-pop{position:absolute;z-index:20;top:calc(100% + 4px);left:0;padding:10px;
  border:1px solid var(--line);border-radius:var(--radius-md);background:var(--card);
  box-shadow:0 8px 24px rgba(0,0,0,.35)}
.daterange-head{display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin-bottom:8px;font-size:var(--text-sm);white-space:nowrap}
.daterange-grid{display:grid;grid-template-columns:repeat(7,32px);gap:2px}
.daterange-dow{display:flex;align-items:center;justify-content:center;height:24px;
  color:var(--muted);font-size:var(--text-sm)}
.daterange-day{min-height:30px;padding:0;background:transparent;color:var(--fg);
  border-radius:var(--radius-sm)}
.daterange-day:hover:not(:disabled){background:var(--accent-hover);color:var(--accent-fg)}
.daterange-day:disabled{color:var(--muted);opacity:.4;cursor:default}
.daterange-day.is-inside{background:var(--focus-ring)}
.daterange-day.is-edge{background:var(--accent);color:var(--accent-fg);font-weight:var(--weight-medium)}

/* Тип и режим заявки: две колонки кнопок, выбранная — акцентная */
.choice-grid{display:flex;gap:32px;flex-wrap:wrap;margin:8px 0 4px}
.choice-grid > div{display:flex;flex-direction:column;gap:6px;align-items:flex-start}
