/* ============ WB Analyzer — светлая тема (CS) ============ */

/* ============ Шрифт Inter (локально, frontend/fonts) ============
   Файлы взяты с гугл-статики (v20). Это ВАРИАТИВНЫЙ шрифт: один woff2 на подмножество
   символов содержит всю ось веса, поэтому файла два — кириллица и латиница, — а весов
   он даёт сколько угодно.

   БЫЛО И ПОЧЕМУ ЭТО ПОРТИЛО ВИД. Объявлялись ровно два веса, 400 и 600, оба на тот же
   файл. А в стилях используется ПЯТЬ: 400 (8 мест), 500 (12), 600 (60), 700 (69) и
   800 (31), плюс 38 мест прямо в разметке. По правилам подбора шрифта браузер брал
   ближайшее объявленное начертание: всё, что задумано жирным (700 и 800) — заголовки,
   крупные числа, шапки таблиц — рисовалось полужирным, а «средний» 500 проваливался
   в обычный. Разница в весе между заголовком и текстом почти исчезала, и интерфейс
   выглядел плоским.

   СТАЛО: диапазон font-weight: 100 900 — правильное объявление вариативного шрифта.
   Ни одного лишнего байта: файлы те же самые. Разделение по unicode-range оставлено —
   латиница и кириллица грузятся независимо; font-display: swap — текст виден сразу. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-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;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ВИЗУАЛЬНЫЙ ЯЗЫК (24.08.2026). Полное обоснование — ВИЗУАЛЬНЫЙ-ЯЗЫК.md.

   Четыре слоя цвета, которые НЕ ПЕРЕСЕКАЮТСЯ:
     1) НЕЙТРАЛЬ  — весь хром: фон, поверхности, текст, линии
     2) АКЦЕНТ    — только интерактив: кнопка, фокус, ссылка, активная вкладка
     3) СЕМАНТИКА — только оценка: хорошо / внимание / плохо / нейтрально
     4) ПЛОЩАДКА  — только принадлежность: точка 8px, рейка 3px, ряд графика

   ЧТО ЛЕЧИМ. Старая нейтраль была лавандовой: --bg #f3f4f8, --text #1c2030
   (разброс каналов 20), --muted #6c7390 (разброс 36) — тон 265°, то есть то же
   семейство, что акцент #6c3fff и метка Wildberries #8b5cf6. Весь холст был
   подкрашен акцентом, поэтому ничто ни от чего не отделялось, и перекраска
   одного акцента этого не чинила. Теперь нейтраль обесцвечена втрое (разброс
   17–18), акцент уведён в бирюзу — единственный холодный тон, не занятый ни
   площадкой, ни семантикой, — а фиолетовый навсегда отдан Wildberries.

   Слой совместимости со старыми именами (--bg, --text, --accent…) жил здесь
   с 24.08 и удалён 02.09.2026 (этап 7 «Уборка»): все ~870 обращений к старым
   именам в CSS, разметке и инлайн-стилях JS переведены на новые токены,
   статическая проверка стережёт, чтобы осиротевшие имена не вернулись.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* Браузерной отрисовке (скроллбар, select, календарь, чекбоксы) тему токенами
     не объяснишь — ей нужен color-scheme, иначе в тёмной теме эти элементы
     остаются светлыми островами. Тёмные ветки ниже переключают его на dark. */
  color-scheme: light;

  /* ── 1. НЕЙТРАЛЬ «Сталь» ── тон 228°, цветность втрое ниже прежней ── */
  --n-0:#ffffff; --n-25:#fafbfc; --n-50:#f4f6f9; --n-100:#eceef2; --n-150:#e3e6eb;
  --n-200:#d5d9e0; --n-300:#bcc1ca; --n-400:#9aa0ab; --n-500:#6e7480; --n-600:#4a505c;
  --n-700:#363b45; --n-900:#171a20;

  /* поверхности: 4 ступени, выбирается роль, а не число */
  --bg:        var(--n-100);  /* холст страницы                       */
  --surface:   var(--n-0);    /* карточка, панель, строка таблицы      */
  --surface-2: var(--n-50);   /* врезка, ховер строки, вложенный блок  */
  --surface-3: var(--n-150);  /* утопленное: итог, счётчик, скелет     */

  /* текст: 4 ступени. Четвёртая намеренно не проходит AA — это цвет
     прочерка «—» и выключенного, то есть «сюда смотреть не надо» */
  --text-1: var(--n-900); --text-2: var(--n-600);
  --text-3: var(--n-500); --text-4: var(--n-400);

  /* линии: 4 ступени */
  --line: var(--n-150); --line-2: var(--n-200); --line-3: var(--n-300);
  --line-dash: var(--n-300); --bw: 1px;

  /* подложки строк — НЕПРОЗРАЧНЫЕ: альфа внутри строки складывается
     с заливкой плашки и выделением и даёт три оттенка одного статуса */
  --row-hover: var(--n-50); --row-sel: #e9f4f8; --row-alt: var(--n-25);
  --tint-hover: rgba(23,26,32,.035); --tint-sel: rgba(23,26,32,.060);

  /* ── 2. АКЦЕНТ «Бирюза» (193°) ── только кнопка, фокус, ссылка,
     активная вкладка и выбранная строка. В данные не заходит никогда ── */
  --ac-50:#e6f6fa; --ac-100:#c7ebf3; --ac-300:#46bfd6;
  --ac-500:#0e93af; --ac-600:#0a7a93; --ac-700:#086377; --ac-fg:#ffffff;
  --focus: var(--ac-500);

  /* ── 3. СЕМАНТИКА ── ровно четыре тона. «Info» синим не существует:
     он конфликтовал бы с Ozon. Разница warn/bad — по обязанности:
     warn «нужно посмотреть», bad «нужно решить» ── */
  --ok-50:#e8f6ef;   --ok-100:#c6e9d6;   --ok-500:#12945c;
  --ok-fill:#0c7c4b; --ok-ink:#086139;   --ok-on:#ffffff;
  --warn-50:#fbf2e0; --warn-100:#f3dfb4; --warn-500:#d08a00;
  --warn-fill:#e9b451; --warn-ink:#8c5a08; --warn-on:#4a3300;
  --bad-50:#fcecec;  --bad-100:#f7d2cf;  --bad-500:#d93025;
  --bad-fill:#c42020; --bad-ink:#9b1b14; --bad-on:#ffffff;
  --neu-50:var(--n-50); --neu-100:var(--n-150); --neu-500:var(--n-400);
  --neu-fill:var(--n-600); --neu-ink:var(--n-600); --neu-on:#ffffff;

  /* ── 4. ПЛОЩАДКИ ── разрешены в трёх местах и больше нигде: точка 8px,
     рейка 3px слева, линия ряда графика. Никогда — фон плашки и текст.
     WB оставлен тем же hex, что в services/marketplaces.js ── */
  --mp-wb:#8b5cf6;   --mp-wb-ink:#6d3cd4;
  --mp-ozon:#1668dc; --mp-ozon-ink:#0f52ae;
  --mp-ym:#ffcc00;   --mp-ym-ink:#8a5a00; --mp-ym-line:#c98a00;
  --mp-ring: inset 0 0 0 1px rgba(23,26,32,.16);

  /* ── 5. ГРАФИКИ ── три ряда закреплены за площадками ПО ИМЕНИ, четыре
     свободных выданы по удалённости от семантики. Зелёный/красный/янтарный
     в категориальном ряду не используются — они заняты смыслом ── */
  --ch-wb:var(--mp-wb); --ch-ozon:var(--mp-ozon); --ch-ym:var(--mp-ym-line);
  --ch-1:#c43c7b; --ch-2:#0e8f7a; --ch-3:#6c8f1e; --ch-4:#5b6472;
  /* ещё три свободных: при пяти и более рядах четырёх не хватало, и пятый повторял
     первый. Оттенки подобраны так, чтобы не задеть ни семантику (зелёный/красный/
     янтарный), ни метки площадок (фиолетовый WB / синий Ozon / жёлтый ЯМ). */
  --ch-5:#8a5a3c; --ch-6:#6b4a7a; --ch-7:#45688a;
  /* восьмой свободный: chartPalette(8) на семи токенах выдавал восьмому ряду
     цвет первого (7 % 7 = 0) — два ряда одного графика сливались. Тёмный
     циан-петроль из семьи акцента: запрет «акцент в данные не заходит» — про
     интерактив интерфейса, ряд графика им не является. От соседей отделён
     проверкой ΔE: ближайшие --ch-2 (зеленее), --ch-4 и --ch-7 (серее) ≥ 20. */
  --ch-8:#257783;
  --ch-x:var(--n-400); --ch-grid:var(--line); --ch-axis:var(--text-3); --ch-zero:var(--line-2);

  /* ── 6. ТЕНИ ── три, привязаны к слою (было 15 значений) ── */
  --sh-1: 0 1px 2px rgba(23,26,32,.05);
  --sh-2: 0 2px 6px rgba(23,26,32,.08), 0 12px 28px -8px rgba(23,26,32,.16);
  --sh-3: 0 24px 56px -12px rgba(23,26,32,.26);
  --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--focus);

  /* ── 7. РАДИУСЫ ── пять по роли (было 13 значений) ── */
  --r-xs:4px; --r-chip:6px; --r-ctl:8px; --r-card:10px; --r-pill:999px;

  /* ── 8. ОТСТУПЫ ── */
  --sp-2:2px; --sp-4:4px; --sp-6:6px; --sp-8:8px; --sp-12:12px;
  --sp-16:16px; --sp-20:20px; --sp-24:24px; --sp-32:32px;

  /* ── 9. ДЛИТЕЛЬНОСТИ ── четыре ступени: микро (ховер), переход (поповер,
     тема), развёртка (панель), цикл (бегущая полоса загрузки). Цвета не несут,
     в тёмной ветке не дублируются — статическая проверка знает об этом. */
  --dur-1:120ms; --dur-2:200ms; --dur-3:320ms; --dur-4:1200ms;

  /* ── 10. ТАБЛИЦЫ ── одна плотность на весь продукт (этап 5): 9+18+9 ── */
  --row-h:36px; --head-h:32px; --cell-px:10px; --col-min:72px; --col-max:320px; --foot-h:32px;

  /* ── 11. РЕДИЗАЙН-СЛОЙ по референсам дизайнера (19.09.2026, этап A) ──
     Источник: «последние версии/gerts-full-site-architecture.html» (токены макета)
     и gerts-dashboard-v2.png. НАМЕРЕННЫЕ отступления от макета (решение владельца —
     «меньше взрыва по check-visual-tokens»): акцент дизайнера #087d89 ≈ наш канон
     --ac-600 #0a7a93 — оставлен наш; подложка контента #f4f7fa ≈ наш --bg #f4f6f9,
     бордеры #dce8ec ≈ наш --line #e3e6eb, вторичный текст #657985 ≈ наш --text-3
     #6e7480 — оставлены наши, разница ниже порога глаза. Шрифт Inter — уже канон. */

  /* Сайдбар — тёмный В ОБЕИХ темах: контраст «тёмная навигация / светлый контент» —
     сама суть оболочки референса. В тёмной ветке не переопределяются (в check-visual-tokens
     внесены в shared: тема им безразлична). */
  --side-bg:#101b24;      /* основа сайдбара                                  */
  --side-bg-2:#132b37;    /* ховер пункта меню                                */
  --side-bg-3:#173044;    /* плашка активного пункта                          */
  --side-text:#aec0c8;    /* приглушённый текст на тёмном                     */
  --side-dim:#7e939d;     /* подписи секций меню (производная, темнее текста) */
  --side-ink:#ffffff;     /* активный пункт и логотип                         */
  --side-line:rgba(174,192,200,.16); /* волослинии на тёмном (от --side-text) */

  /* Шесть статусов (§5 правил нового языка): статус = светлая пастельная плашка
     ЦЕЛИКОМ + обязательная текстовая подпись; цветных точек и галочек нет.
     Пары «фон плашки / текст на ней». В тёмной теме переворачиваются (ниже). */
  --st-ok-bg:#e5f5eb;      --st-ok-ink:#183c2d;      /* норма    */
  --st-warn-bg:#fff2d9;    --st-warn-ink:#49371b;    /* внимание */
  --st-bad-bg:#fdebea;     --st-bad-ink:#492729;     /* проблема */
  --st-work-bg:#e8f1ff;    --st-work-ink:#173847;    /* в работе */
  --st-nodata-bg:#f4f7fa;  --st-nodata-line:#dce5ea; --st-nodata-ink:#304653; /* нет данных */
  --st-project-bg:#f0eafd; --st-project-ink:#302746; /* проект / оценка */

}

/* ── ТЁМНАЯ ТЕМА ──────────────────────────────────────────────────────
   Переопределяются ЗНАЧЕНИЯ, а не правила: ни один цвет не объявлен
   только здесь. Две ветки: системная настройка и явный выбор. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;  /* браузерные элементы (скроллбар, select, календарь) красятся под тему */
    --n-0:#12151a; --n-25:#161a20; --n-50:#1b1f26; --n-100:#0e1116; --n-150:#252a33;
    --n-200:#2f3542; --n-300:#414855; --n-400:#727a88; --n-500:#98a0ac; --n-600:#c2c8d1;
    --n-700:#dde1e7; --n-900:#f2f4f7;
    --ac-50:#0b2a33; --ac-100:#0f3d4a; --ac-300:#2ba7c0;
    --ac-500:#35b7d1; --ac-600:#0a7a93; --ac-700:#7fd8e8;
    --ok-50:#0e2a1f;  --ok-100:#14402e;  --ok-ink:#5cc490;
    --warn-50:#2e2413; --warn-100:#45361a; --warn-ink:#e0a93b; --warn-on:#2a1d00;
    --bad-50:#2e1616;  --bad-100:#452020; --bad-ink:#f27a6e;
    /* нейтральная пилюля: --neu-fill наследовал --n-600, а в перевёрнутой шкале
       это светло-серый #c2c8d1 — белый текст --neu-on на нём пропадал
       (контраст ~1.7:1). --n-300 здесь тёмный серо-синий #414855: с белым 9.2:1. */
    --neu-fill: var(--n-300);
    --row-sel:#0f3d4a;
    /* Редизайн-слой (19.09.2026): статусные пары перевёрнуты — фон плашки тёмный,
       текст пастельный. Сайдбар не переопределяется: он тёмный в обеих темах. */
    --st-ok-bg:#183c2d;     --st-ok-ink:#e5f5eb;
    --st-warn-bg:#49371b;   --st-warn-ink:#fff2d9;
    --st-bad-bg:#492729;    --st-bad-ink:#fdebea;
    --st-work-bg:#173847;   --st-work-ink:#e8f1ff;
    --st-nodata-bg:#1b232c; --st-nodata-line:#304653; --st-nodata-ink:#aec0c8;
    --st-project-bg:#302746; --st-project-ink:#f0eafd;
    --tint-hover: rgba(255,255,255,.04); --tint-sel: rgba(255,255,255,.07);
    --mp-ring: inset 0 0 0 1px rgba(255,255,255,.22);
    --sh-1: none;
    --sh-2: 0 2px 6px rgba(0,0,0,.5), 0 12px 28px -8px rgba(0,0,0,.7);
    --sh-3: 0 24px 56px -12px rgba(0,0,0,.8);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;  /* браузерные элементы (скроллбар, select, календарь) красятся под тему */
  --n-0:#12151a; --n-25:#161a20; --n-50:#1b1f26; --n-100:#0e1116; --n-150:#252a33;
  --n-200:#2f3542; --n-300:#414855; --n-400:#727a88; --n-500:#98a0ac; --n-600:#c2c8d1;
  --n-700:#dde1e7; --n-900:#f2f4f7;
  --ac-50:#0b2a33; --ac-100:#0f3d4a; --ac-300:#2ba7c0;
  --ac-500:#35b7d1; --ac-600:#0a7a93; --ac-700:#7fd8e8;
  --ok-50:#0e2a1f;  --ok-100:#14402e;  --ok-ink:#5cc490;
  --warn-50:#2e2413; --warn-100:#45361a; --warn-ink:#e0a93b; --warn-on:#2a1d00;
  --bad-50:#2e1616;  --bad-100:#452020; --bad-ink:#f27a6e;
  /* нейтральная пилюля: --neu-fill наследовал --n-600, а в перевёрнутой шкале
     это светло-серый #c2c8d1 — белый текст --neu-on на нём пропадал
     (контраст ~1.7:1). --n-300 здесь тёмный серо-синий #414855: с белым 9.2:1. */
  --neu-fill: var(--n-300);
  --row-sel:#0f3d4a;
  /* Редизайн-слой (19.09.2026): статусные пары перевёрнуты — фон плашки тёмный,
     текст пастельный. Сайдбар не переопределяется: он тёмный в обеих темах. */
  --st-ok-bg:#183c2d;     --st-ok-ink:#e5f5eb;
  --st-warn-bg:#49371b;   --st-warn-ink:#fff2d9;
  --st-bad-bg:#492729;    --st-bad-ink:#fdebea;
  --st-work-bg:#173847;   --st-work-ink:#e8f1ff;
  --st-nodata-bg:#1b232c; --st-nodata-line:#304653; --st-nodata-ink:#aec0c8;
  --st-project-bg:#302746; --st-project-ink:#f0eafd;
  --tint-hover: rgba(255,255,255,.04); --tint-sel: rgba(255,255,255,.07);
  --mp-ring: inset 0 0 0 1px rgba(255,255,255,.22);
  --sh-1: none;
  --sh-2: 0 2px 6px rgba(0,0,0,.5), 0 12px 28px -8px rgba(0,0,0,.7);
  --sh-3: 0 24px 56px -12px rgba(0,0,0,.8);
}

/* ═══ РЕДИЗАЙН: компоненты новой системы (19.09.2026, этап A) ═══
   Новые классы РЯДОМ со старыми: экраны мигрируют по одному (этап B+).
   Статус передаётся пастельной плашкой ЦЕЛИКОМ + текстовой подписью (§5 правил
   нового языка); цветных точек и галочек нет. */

/* Статус-плашка: шесть статусов. */
.st-badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: var(--r-pill); font-size: 12px; font-weight: 600; line-height: 1.5; white-space: nowrap; }
.st-badge--ok { background: var(--st-ok-bg); color: var(--st-ok-ink); }
.st-badge--warn { background: var(--st-warn-bg); color: var(--st-warn-ink); }
.st-badge--bad { background: var(--st-bad-bg); color: var(--st-bad-ink); }
.st-badge--work { background: var(--st-work-bg); color: var(--st-work-ink); }
.st-badge--nodata { background: var(--st-nodata-bg); color: var(--st-nodata-ink); box-shadow: inset 0 0 0 1px var(--st-nodata-line); }
.st-badge--project { background: var(--st-project-bg); color: var(--st-project-ink); }

/* KPI-карточка (§5: название, значение, период, источник, свежесть, статус проверки,
   «факт/оценка»). Мета-строки печатаются только при наличии данных: источника нет —
   подпись не фабрикуется (правило владельца). */
.kpi-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 8px; min-width: 0; box-shadow: var(--sh-1); }
.kpi-card .kpi-name { font-size: 13px; font-weight: 600; color: var(--text-2); }
.kpi-card .kpi-value { font-size: 24px; font-weight: 700; color: var(--text-1); font-variant-numeric: tabular-nums; line-height: 1.15; }
.kpi-card .kpi-meta { font-size: 11px; color: var(--text-3); display: flex; flex-direction: column; gap: 2px; }
.kpi-card .kpi-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
/* Плашка дельты в узкой карточке: текст переносится на вторую строку, а не уходит
   за край (скриншот волны 1, «Деньги»: «▲ +2 788 453 · +25,4% к прошлой н…» — 19.09.2026) */
.kpi-foot .st-badge { white-space: normal; line-height: 1.3; max-width: 100%; }
/* Плитка с подтверждённой проблемой (promotion.js, x.danger): фон и рамка семантики
   «плохо» — бейджа у такой метрики нет, поэтому вся карточка (как плашка §5). */
.kpi-card[data-tone="bad"] { background: var(--bad-50); border-color: var(--bad-100); }

/* Карточка решения (очередь «Что требует решения»): плашка целиком в статусной
   пастели; внутри — заголовок, мета (источник/свежесть), ответственный. */
.decision-card { border-radius: var(--r-card); padding: 12px 16px; display: flex; flex-direction: column; gap: 4px; border: 1px solid transparent; }
.decision-card .dc-title { font-size: 13px; font-weight: 700; }
.decision-card .dc-meta { font-size: 11px; }
.decision-card .dc-owner { font-size: 11px; font-weight: 600; }
.decision-card--ok { background: var(--st-ok-bg); color: var(--st-ok-ink); }
.decision-card--warn { background: var(--st-warn-bg); color: var(--st-warn-ink); }
.decision-card--bad { background: var(--st-bad-bg); color: var(--st-bad-ink); }
.decision-card--work { background: var(--st-work-bg); color: var(--st-work-ink); }
.decision-card--nodata { background: var(--st-nodata-bg); color: var(--st-nodata-ink); border-color: var(--st-nodata-line); }
.decision-card--project { background: var(--st-project-bg); color: var(--st-project-ink); }
/* Лента карточек решений: колонка с зазором, без линий-разделителей */
.decision-list { display: flex; flex-direction: column; gap: 10px; }
/* Баннер качества данных: жёлтая плашка «внимание» сверху экрана (референс §5) */
.dq-banner { display: flex; align-items: baseline; gap: 10px; background: var(--st-warn-bg); color: var(--st-warn-ink); border-radius: var(--r-card); padding: 10px 16px; margin-bottom: 20px; }
.dq-banner .dq-text { font-size: 12px; line-height: 1.5; }

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 13px;    /* БАЗА. Всё, что не объявило кегль, живёт здесь */
  line-height: 1.4;   /* безразмерный: наследуется пропорционально кеглю */
  font-variant-numeric: normal;  /* tnum включается ступенями, не глобально:
     на кириллическом абзаце табличные цифры разъезжаются с текстом */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--bg);
  color: var(--text-1);
  min-height: 100vh;
}

/* ============ Оболочка 2.0: сайдбар + шапка экрана + контент ============
   Раскладка: .shell (flex) → .sidebar (256px, липкий, своя прокрутка) + .main (flex:1).
   В .main — .topbar (липкая шапка экрана: бургер, заголовок, действия экрана) и
   .container с вкладками. Пункты сайдбара — .nav-tab (класс и data-tab сохранены:
   их читают gotoTab() и smoke-тест). На экранах < 900px сайдбар уезжает за левый край
   и выезжает поверх контента по классу body.sidebar-open (бургер в шапке). */

/* --ui-zoom дублирует html{zoom} из медиа-блоков 2К/4К (в конце файла): zoom НЕ масштабирует
   vh-единицы, и элемент высотой 100vh при zoom 1.15 рендерится в 115% экрана (низ сайдбара
   уезжал за край на 2К — проверено замером). Всё, что должно быть «высотой в экран»,
   пишется как calc(100vh / var(--ui-zoom)). */
:root { --sidebar-w: 256px; --topbar-h: 60px; --ui-zoom: 1; }

/* ═══ ТИПОГРАФИКА ═══ восемь кеглей, двенадцать ступеней, три веса ══════════
   Шкала введена 24.08.2026 (этап 2 плана ВИЗУАЛЬНЫЙ-ЯЗЫК.md). До неё в файле
   жили 25 кеглей и пять весов без правила выбора; после — восемь и три.

   ВЕС ГОВОРИТ О РОЛИ: 400 — то, что читают; 600 — интерфейс (заголовки, метки,
   кнопки, шапки); 700 — только числа от 18px и итоговая строка. Акцент внутри
   одного кегля задаётся весом, а не размером — это правило и убрало половину
   прежних ступеней.

   ВЕРХНЕГО РЕГИСТРА В ПРОДУКТЕ НЕТ вообще, кроме .t-nano (2–4 знака: «WB»,
   «ОЗ», «A/B/C», «п. п.»). У кириллицы нет развитых выносных элементов: капсом
   слово теряет силуэт, а русские слова и без того на 10–15 % длиннее.

   ПРО ss02. В плане стояло включить Inter Disambiguation (различимые 1/l/I и
   0/O) — при проверке 24.08.2026 выяснилось, что в наших сабсетах его нет:
   Google Fonts вырезает стилистические наборы (ss01–ss03, zero, calt мертвы,
   работает только tnum — проверено попиксельным сравнением отрисовки).
   Пересобрать нечем: fontTools на машине нет. Поэтому строку с ss02 НЕ пишем —
   она была бы мёртвой. Артикулы, nmID и ID кампаний различаются моноширинным
   шрифтом, как и предписано планом, а не подменой глифов.                    */

.t-nano  { font-size:10px; line-height:14px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; }
.t-micro { font-size:11px; line-height:16px; font-weight:600; font-variant-numeric:tabular-nums; }
.t-small { font-size:12px; line-height:16px; font-weight:400; font-variant-numeric:tabular-nums; }
.t-small-em { font-size:12px; line-height:16px; font-weight:600; font-variant-numeric:tabular-nums; }
.t-base  { font-size:13px; line-height:18px; font-weight:400; font-variant-numeric:tabular-nums; }
.t-base-em { font-size:13px; line-height:18px; font-weight:600; font-variant-numeric:tabular-nums; }
.t-head  { font-size:15px; line-height:20px; font-weight:600; }
.t-screen { font-size:18px; line-height:24px; font-weight:600; }
.n-sub   { font-size:18px; line-height:24px; font-weight:700; font-variant-numeric:tabular-nums; }
.n-kpi   { font-size:24px; line-height:28px; font-weight:700; font-variant-numeric:tabular-nums; letter-spacing:-.01em; }
.n-hero  { font-size:32px; line-height:36px; font-weight:700; font-variant-numeric:tabular-nums; letter-spacing:-.02em; }
/* Читательские ступени: tnum выключен намеренно — разряды тут не выравнивают */
.read      { font-size:13px; line-height:20px; font-weight:400; font-variant-numeric:normal; }
.read-lead { font-size:15px; line-height:24px; font-weight:400; font-variant-numeric:normal; }

/* Моноширинный — только там, где смысл в моноширинности: артикул, nmID,
   ID кампании, ID запроса в ошибке. Для денег он не годится: разъедет метрику
   относительно кириллической подписи в той же строке. */
.t-mono { font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
          font-size:12px; line-height:16px; }


.shell { display: flex; align-items: stretch; min-height: calc(100vh / var(--ui-zoom)); }

/* --- Сайдбар --- */
.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  /* Редизайн (19.09.2026, этап A): сайдбар тёмный в ОБЕИХ темах — токены --side-*
     не переопределяются в тёмной ветке намеренно. */
  background: var(--side-bg);
  border-right: 1px solid var(--side-line);
  position: sticky;
  top: 0;
  height: calc(100vh / var(--ui-zoom));
  /* Прокручивается ТОЛЬКО .sidebar-nav (ниже), а шапка и низ (Пользователи/Выйти) всегда
     на экране. Раньше скроллился весь сайдбар целиком — на 2К с zoom 1.15 и развёрнутым
     разделом «Выйти» уходил под нижний край, и до него приходилось долистывать. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  z-index: 60;
}
.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 16px 20px 12px;
}
/* Логотип-слово, как в референсе (GERTS / BUSINESS OS): крупное белое слово на
   тёмном + подпись капсом. Слово — из /api/branding (white-label), подпись —
   семейство продукта. Картинок не добавляем (решение владельца 19.09.2026). */
.brand-wordmark { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sidebar-brand h1 {
  font-size: 24px;
  font-weight: 700;
  color: var(--side-ink);
  letter-spacing: 0.02em;
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.brand-caption {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.18em;
  /* БЕЗ text-transform:uppercase — правило языка (капс разрешён только .t-nano);
     в референсе подпись капсом, у нас — малый кегль с разрядкой (19.09.2026). */
  color: var(--side-dim);
}
.sidebar-close {
  display: none;
  border: none;
  background: none;
  font-size: 24px;
  line-height: 1;
  color: var(--side-text);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 6px;
}
.sidebar-close:hover { color: var(--side-ink); background: var(--side-bg-2); }

.sidebar-nav {
  padding: 4px 12px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Единственная прокручиваемая часть сайдбара (см. .sidebar): min-height:0 обязателен,
     иначе flex-ребёнок не ужимается и прокрутка не появляется */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.nav-tab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--side-text);
  cursor: pointer;
  user-select: none;
  transition: background 0.15s, color 0.15s;
}
.nav-tab:hover { color: var(--side-ink); background: var(--side-bg-2); }
.nav-tab.active { color: var(--side-ink); background: var(--side-bg-3); font-weight: 600; }
.nav-tab .nav-icon { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.85; }
.nav-tab.active .nav-icon { opacity: 1; }
.nav-tab > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Группы с подпунктами (.nav-group: Реклама → Оптимизация рекламы; Товары и склад → Мои
   товары; Рынок и конкуренты → Оценка ниши / Разбор конкурентов / Запуск новинок / Готовые
   анализы). Шапка группы — пункт + шеврон; подпункты (.nav-sub) свёрнуты по умолчанию и
   плавно раскрываются у .nav-group.open (grid 0fr → 1fr; visibility прячет их от Tab и
   скринридера). Кто раскрыт — решает app.js (renderNavGroups). */
/* Подписи-разделители меню (аудит 27.08): отделяют аналитику от рабочих экранов */
.nav-sec-label {
  padding: 14px 14px 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--side-dim);
  user-select: none;
}
.nav-sec-label:first-child { padding-top: 4px; }

.nav-group { display: flex; flex-direction: column; }
.nav-group-head { display: flex; align-items: center; gap: 2px; }
.nav-group-head .nav-tab { flex: 1 1 auto; min-width: 0; padding-right: 6px; } /* место под шеврон */
.nav-chevron {
  flex: 0 0 auto;
  width: 26px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; padding: 0;
  color: var(--side-dim);
  border-radius: 7px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.nav-chevron svg { width: 16px; height: 16px; transition: transform 0.2s ease; }
.nav-chevron:hover { color: var(--side-ink); background: var(--side-bg-2); }
.nav-chevron:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }
.nav-group.open .nav-chevron svg { transform: rotate(90deg); }
.nav-group.open .nav-chevron { color: var(--text-3); }

.nav-sub {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  margin: 0 0 0 21px;
  padding-left: 6px;
  border-left: 1px solid var(--line);
  transition: grid-template-rows 0.2s ease, margin 0.2s ease, visibility 0s linear 0.2s;
}
.nav-group.open .nav-sub {
  grid-template-rows: 1fr;
  visibility: visible;
  margin-bottom: 4px;
  transition: grid-template-rows 0.2s ease, margin 0.2s ease, visibility 0s;
}
.nav-sub-list { min-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: 1px; }
.nav-sub .nav-tab { font-size: 13px; padding: 7px 10px; border-radius: 7px; }
.nav-sub .nav-tab:focus-visible { outline-offset: -2px; } /* список обрезает overflow — обводка внутрь */
.nav-sub .nav-tab::before {
  content: '';
  width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: 0.45; flex-shrink: 0;
}
.nav-sub .nav-tab.active::before { opacity: 1; }

/* Подпункт с подписью-хинтом (.has-hint): название + серая строка «что здесь» под ним;
   хинт может занять две строки, дальше обрезается.
   19.09.2026: хинт красится ТОКЕНАМИ САЙДБАРА, а не общими --text-4/--ac-700 — сайдбар
   тёмный в обеих темах, и на нём светло-темный хинт читался «наполовину съеденным»
   (дефект осмотра vizC-promo-light.png). */
.nav-sub .nav-tab.has-hint { align-items: flex-start; padding-top: 6px; padding-bottom: 6px; }
.nav-sub .nav-tab.has-hint::before { margin-top: 7px; }
.nav-tab .nav-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; white-space: normal; overflow: visible; }
.nav-tab .nav-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-tab .nav-hint {
  font-size: 11px; line-height: 1.25; font-weight: 400;
  color: var(--side-text); opacity: 0.75;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.nav-tab.active .nav-hint { color: var(--side-ink); opacity: 0.8; }

/* Низ сайдбара: компания, пользователь, «Пользователи» (admin), «Выйти» */
.sidebar-foot {
  margin-top: auto;
  padding: 12px 12px 14px;
  border-top: 1px solid var(--side-line);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-user { display: flex; flex-direction: column; gap: 6px; padding: 4px 12px 10px; min-width: 0; }
.header-company { font-size: 12px; color: var(--side-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.header-company:empty { display: none; }
.sister-sites { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.sister-sites[hidden] { display: none; }
.sister-link { font-size: 12px; color: var(--side-dim); text-decoration: none; padding: 2px 8px; border: 1px solid var(--side-bg-2); border-radius: 8px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sister-link:hover, .sister-link:focus-visible { color: var(--side-ink); background: var(--side-bg-2); outline: none; }
.sister-link::after { content: " \2197"; }
.header-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--side-ink);
  background: var(--side-bg-2);
  padding: 6px 10px;
  border-radius: 8px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  align-self: flex-start;
  max-width: 100%;
}
.header-logout {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--side-text);
  cursor: pointer;
  padding: 9px 12px;
  border-radius: 9px;
  transition: all 0.15s;
}
.header-logout .nav-icon { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.85; }
.header-logout:hover { color: var(--side-ink); background: var(--side-bg-2); }
.header-logout:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }

/* --- Основная область --- */
.main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* Шапка экрана: заголовок слева, действия экрана справа (.page-head активной вкладки
   переносится сюда из вкладки — см. mountPageHead в app.js) */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  min-height: 60px;                 /* не через --topbar-h: её пишет JS по факту (иначе замкнётся) */
  padding: 9px 28px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.topbar-title { font-size: 18px; font-weight: 700; color: var(--text-1); margin-right: auto; white-space: nowrap; }
/* Действия экрана: держим на строке заголовка, пока хватает места; не хватает —
   ряд действий переносится ЦЕЛИКОМ на свою строку (flex-basis: auto: перенос
   решается по ширине содержимого). 19.09.2026: раньше было flex:1 1 0 — перенос
   никогда не наступал (базис 0 «всегда помещается»), ряд сжимался до ~180px и
   кнопки выстраивались ВЕРТИКАЛЬНО в 5 строк, раздувая шапку до 225px; а до
   введения переноса вложенного ряда содержимое вообще наезжало на ось площадок. */
.topbar-actions { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.topbar-actions:empty { display: none; }
/* 22.09.2026: сам по себе flex при нехватке места переносит ПОСЛЕДНИЙ элемент строки —
   тумблер темы (иногда с «Работами»), и он висел один на второй строке, а между осью и
   действиями оставалась дыра (skus/history/«Сегодня» на 1440). Перенос ряда действий
   целиком делает syncTopbarStack в app.js: по замеру ставит .topbar--stack. */
.topbar--stack .topbar-actions { flex: 1 1 100%; order: 1; }
/* Ось площадки в шапке (шаг 2 перестройки; сегмент-контрол 19.09.2026):
   четыре сегмента «Все площадки | WB | Ozon | ЯМ» с фирменными маркерами,
   активный — teal-заливка (.seg-btn.active из базовой палитры). */
.mp-axis { margin-left: 14px; flex: none; }
.mp-axis .seg-btn { display: inline-flex; align-items: center; height: 26px; padding: 0 10px; }
.mp-axis .mp-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; vertical-align: 0;
                   box-shadow: 0 0 0 1px rgba(255,255,255,.35); /* точка читается и на teal-заливке активного сегмента */ }
/* «Все площадки»: маркер из трёх фирменных цветов — WB фиолетовый, ЯМ жёлтый, Ozon синий
   (токены --mp-*; градиент здесь, потому что точка рисуется без класса площадки) */
.mp-axis .mp-dot--all { background: conic-gradient(var(--mp-wb) 0 120deg, var(--mp-ym) 120deg 240deg, var(--mp-ozon) 240deg 360deg); }
.topbar .page-head { margin: 0; gap: 10px; justify-content: flex-end; flex-wrap: nowrap; min-width: 0; }
.topbar .page-head > h2 { display: none; }         /* заголовок уже в шапке (#pageTitle) */
/* Подсказка экрана в шапке (например, «План запуска линейки собирается во вкладке…»):
   не шире 360px и в две строки внутри 60px шапки — иначе одной строкой в 415px она
   выталкивала ряд действий на вторую строку на 1440 (22.09.2026) */
.topbar .page-head > span { font-size: 13px; color: var(--text-3); max-width: 360px; white-space: normal; line-height: 1.3; text-align: right; }
/* Действия дашборда: подпись «дней … последний …» + селект + кнопки */
.an-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; justify-content: flex-end; min-width: 0; }
.topbar #anMeta { flex: 0 1 auto; min-width: 0; max-width: 360px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Порог переноса поднят 28.08: ось площадки, сег периода и «Работы» добавили шапке
   ~300px, и на 1400px действия дашборда рисовались ПОВЕРХ оси (замер: кнопку оси
   закрывал «7 дн» сега периода). Перенос дешевле наезда: высоту шапки JS меряет по факту.
   19.09.2026: переносить надо и ВЛОЖЕННЫЙ ряд .page-actions (сегмент площадок
   «Продвижения» живёт в нём): .page-head уже переносился, а внутренний ряд — нет
   и наезжал на ось площадки левее (клик по оси попадал в чужую кнопку — владелец
   читал это как «ось сломалась»). */
@media (max-width: 1680px) {
  .topbar .page-head, .an-head-actions { flex-wrap: wrap; }
  .topbar .page-head .page-actions { flex-wrap: wrap; }
}
/* Подпись «дней: N · последний …» — первая жертва тесноты: та же правда есть на самом
   дашборде, а кнопки и ось терять нельзя */
@media (max-width: 1600px) {
  .topbar #anMeta { display: none; }
}
/* Кнопки действий в шапке — компактнее обычных, чтобы ряд умещался в одну строку */
.topbar .page-head .btn { padding: 8px 14px; font-size: 13px; }
/* Селекты в шапке экрана — по содержимому, а не на всю ширину (глобальное select{width:100%}) */
.topbar select { width: auto; max-width: 240px; }

/* Бургер — только на узких экранах */
.burger {
  display: none;
  width: 38px; height: 38px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-2);
  background: var(--surface);
  border-radius: 9px;
  color: var(--text-1);
  cursor: pointer;
  flex-shrink: 0;
}
.burger svg { width: 20px; height: 20px; }
.burger:hover { background: var(--bg); }

.sidebar-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: rgba(28, 32, 48, 0.4); /* штора: полупрозрачное затемнение работает поверх любой темы, непрозрачного токена у него нет */
  z-index: 55;
}

.container { width: 100%; max-width: 1280px; margin: 0 auto; padding: 24px 28px 40px; }


.tab-content { display: none; }
.tab-content.active { display: block; }

/* ============ Карточки ============ */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 24px;
  margin-bottom: 20px;
  box-shadow: var(--sh-1);
}

.card-title {
  font-size: 15px;
  line-height: 20px;
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: 16px;
}

/* Заголовок карточки + контрол справа (сортировка/переключатель) в одну строку */
.card-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.card-title-row .card-title { margin-bottom: 0; }
.card-title-row select {
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text-1);
}

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  flex-wrap: wrap;
  gap: 10px;
}
.page-head h2 { font-size: 18px; font-weight: 700; color: var(--text-1); }
.page-actions { display: flex; gap: 10px; }

/* ============ Формы ============ */

input, textarea, select {
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 10px 14px;
  color: var(--text-1);
  font-size: 13px;
  font-family: inherit;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  width: 100%;
}
input::placeholder, textarea::placeholder { color: var(--text-4); }
input[type="file"] { padding: 8px 14px; cursor: pointer; }
input:focus, textarea:focus, select:focus {
  border-color: var(--ac-600);
  box-shadow: 0 0 0 3px var(--ac-50);
}

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
.form-row.three { grid-template-columns: 1fr 1fr 1fr; }
label { font-size: 12px; font-weight: 600; color: var(--text-3); margin-bottom: 6px; display: block; }

/* ============ Кнопки ============ */

.btn {
  padding: 10px 18px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  border: 1px solid transparent;
  transition: all 0.15s;
  white-space: nowrap;
}
.btn-primary { background: var(--ac-600); color: var(--ac-fg); }
.btn-primary:hover { background: var(--ac-700); }
.btn-primary:disabled { background: var(--line-2); color: var(--text-4); cursor: not-allowed; }
.btn-secondary { background: var(--surface); color: var(--text-1); border-color: var(--line-2); }
.btn-secondary:hover { border-color: var(--ac-600); color: var(--ac-700); background: var(--ac-50); }
.btn-danger { background: var(--surface); color: var(--bad-500); border-color: var(--bad-100); }
.btn-danger:hover { background: var(--bad-50); }
.btn-sm { padding: 7px 13px; font-size: 13px; }

/* Микровзаимодействия: нажатие «продавливает» кнопку, фокус с клавиатуры виден */
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:focus-visible, .nav-tab:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }

/* Inline SVG-иконки в кнопках (ICONS в shared.js), рисуются currentColor */
.icon {
  width: 15px;
  height: 15px;
  vertical-align: -2.5px;
  flex-shrink: 0;
}

/* Кнопка ОК в danger-подтверждениях (showConfirmModal({danger:true})) — сплошная красная,
   в отличие от «мягких» btn-danger в списках */
.modal-actions .btn-danger { background: var(--bad-fill); border-color: var(--bad-fill); color: var(--bad-on); }
.modal-actions .btn-danger:hover { background: var(--bad-ink); }

/* Карточка ошибки (замена inline color:var(--bad-500) в analyze/history) */
.error-card { background: var(--bad-50); border-color: var(--bad-100); color: var(--bad-ink); }

.search-row { display: flex; gap: 12px; }
.search-row input { flex: 1; }
/* На телефоне поле запроса и «Анализировать» — в колонку: в одну строку поле ужималось
   до ~200px и подсказка рубилась посреди слова (22.09.2026) */
@media (max-width: 720px) {
  .search-row { flex-direction: column; }
  .search-row input { min-width: 0; width: 100%; }
  .search-row .btn { width: 100%; }
}

/* ============ Статус долгих операций (longOpStatus в shared.js) ============ */

.long-op {
  background: var(--ac-50);
  border: 1px solid var(--ac-100);
  border-radius: 12px;
  padding: 16px 20px;
  margin: 4px 0 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ac-700);
  font-weight: 600;
}
.long-op-time {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  flex-shrink: 0;
}

.spinner {
  width: 20px; height: 20px;
  border: 2.5px solid var(--ac-100);
  border-top-color: var(--ac-600);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2s; } }

/* Заглушка загрузки списков вкладок (listLoadingHtml в shared.js) */
.list-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 20px;
  color: var(--text-3);
  font-size: 13px;
}

/* ============ Тосты (showToast в shared.js) ============ */

.toast-container {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 3000;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  max-width: min(380px, calc(100vw - 40px));
  pointer-events: none; /* пустой контейнер не перекрывает клики */
}
.toast {
  pointer-events: auto;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(28, 32, 48, 0.14); /* легаси-тень тоста: в три ступени --sh-1..3 не укладывается, перевод сменил бы вид */
  cursor: pointer;
  animation: toast-in 0.25s ease;
  transition: opacity 0.4s;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
/* Крестик у error-тостов: они не автоскрываются — закрытие только по клику */
.toast-close { flex-shrink: 0; font-weight: 700; opacity: 0.55; }
.toast:hover .toast-close { opacity: 1; }
.toast-error { background: var(--bad-50); border-color: var(--bad-100); color: var(--bad-ink); }
.toast-ok { background: var(--ok-50); border-color: var(--ok-100); color: var(--ok-500); }
.toast-hide { opacity: 0; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ============ Результаты анализа ============ */

.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; }
/* Колонка 1fr = minmax(auto, 1fr), и её минимум — ШИРИНА СОДЕРЖИМОГО. Chart.js ставит
   canvas в 1552 px, из-за чего на 2К колонки разъезжались (1400 px и 446 px), карточка
   не влезала в свою колонку и уезжала на 200 px за правый край экрана вместе с
   горизонтальной прокруткой (замер 24.08: scrollWidth 2616 при ширине окна 2560).
   min-width: 0 разрешает колонке сжаться — канонический приём для canvas в grid. */
.grid > * { min-width: 0; }
.full { grid-column: 1 / -1; }

.stat-big {
  font-size: 32px;
  font-weight: 700;
  color: var(--text-1);
  margin-bottom: 4px;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.stat-label { font-size: 13px; color: var(--text-3); }
.summary { font-size: 13px; line-height: 1.7; color: var(--text-1); margin-top: 14px; }

.target-banner {
  background: var(--ac-50);
  border: 1px solid var(--ac-100);
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.target-banner .tb-label { font-size: 12px; color: var(--ac-700); font-weight: 700; }
.target-banner .tb-value { font-size: 13px; color: var(--text-1); font-weight: 600; }

.view-banner {
  background: var(--warn-50);
  border: 1px solid var(--warn-100);
  border-radius: 12px;
  padding: 12px 18px;
  margin-bottom: 20px;
  font-size: 13px;
  color: var(--warn-500);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Акцентный вариант баннера (сохранён в историю / доработать план) */
.view-banner.banner-accent {
  background: var(--ac-50);
  border-color: var(--ac-100);
  color: var(--ac-700);
}

.tags { display: flex; flex-wrap: wrap; gap: 8px; }
.tag {
  background: var(--ac-50);
  color: var(--ac-700);
  border: 1px solid var(--ac-100);
  border-radius: 7px;
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 600;
}

.insight-box {
  margin-top: 14px;
  font-size: 13px;
  color: var(--text-3);
  line-height: 1.65;
  padding: 14px;
  background: var(--bg);
  border-radius: 10px;
}

/* ============ Ценовые варианты ============ */

.price-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.price-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  position: relative;
}
.price-card.recommended {
  border-color: var(--ac-600);
  background: linear-gradient(0deg, var(--ac-50), var(--surface) 70%);
}
.price-card.recommended::before {
  content: '';
  position: absolute;
  left: 0; top: 12px; bottom: 12px;
  width: 4px;
  border-radius: 0 4px 4px 0;
  background: var(--ac-600);
}
.price-card-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.price-label { font-size: 11px; line-height: 16px; color: var(--text-3); font-weight: 600; }
.price-badge { font-size: 11px; font-weight: 700; background: var(--ac-600); color: var(--ac-fg); padding: 2px 8px; border-radius: var(--r-chip); }
.price-value { font-size: 24px; font-weight: 700; color: var(--text-1); font-variant-numeric: tabular-nums; }
.price-old { font-size: 13px; color: var(--text-4); text-decoration: line-through; margin-left: 8px; font-weight: 400; }
.price-discount { font-size: 12px; color: var(--ok-500); font-weight: 700; margin-left: 6px; }
.price-strategy { font-size: 13px; color: var(--ac-700); font-weight: 600; margin-top: 4px; }
.price-reason { font-size: 12px; color: var(--text-3); margin-top: 8px; line-height: 1.55; }

.corridor-note {
  font-size: 12px;
  color: var(--text-3);
  margin-top: 12px;
  padding: 8px 12px;
  background: var(--bg);
  border-radius: 8px;
  display: inline-block;
}

.recommendation {
  margin-top: 16px; padding: 16px;
  background: var(--ac-50);
  border: 1px solid var(--ac-100);
  border-radius: 10px;
  font-size: 13px;
  color: var(--text-1);
  line-height: 1.65;
}

.title-result { font-size: 18px; font-weight: 700; color: var(--text-1); margin-bottom: 6px; line-height: 1.35; }
.title-len { font-size: 12px; color: var(--text-4); }
/* Счётчик длины заголовка при превышении лимита WB (60 символов) */
.title-len.over, .cardgen-len.over { color: var(--bad-500); font-weight: 700; }
.description-text {
  font-size: 13px; line-height: 1.75; color: var(--text-1);
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line);
}

/* ============ Таблицы ============ */

/* Обёртка широких таблиц из JS-шаблонов: скролл внутри блока, а не всей страницы */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll table { min-width: 560px; }

table { width: 100%; border-collapse: collapse; }
th {
  text-align: left;
  font-size: 11px;
  line-height: 16px;
  color: var(--text-3);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
}
td {
  padding: 11px 12px;
  font-size: 13px;
  border-bottom: 1px solid var(--bg);
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--bg); }
td a { color: var(--ac-700); text-decoration: none; font-weight: 600; }
td a:hover { text-decoration: underline; }
.rating { color: var(--warn-500); font-weight: 600; }

.thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); }
.thumb-empty { width: 48px; height: 48px; background: var(--bg); border-radius: 8px; border: 1px solid var(--line); }

/* ============ Мои товары ============ */

.group-title {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.group-count {
  background: var(--ac-50);
  color: var(--ac-700);
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
}
.sku-group { margin-bottom: 32px; }

.sku-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.sku-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 18px;
  display: flex;
  flex-direction: column;
  box-shadow: var(--sh-1);
  transition: border-color 0.15s;
}
.sku-card:hover { border-color: var(--ac-100); }

.sku-photos { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 12px; }
.sku-photo { width: 100%; aspect-ratio: 1; height: auto; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); cursor: pointer; transition: transform 0.12s, border-color 0.12s; }
.sku-photo:hover { transform: scale(1.04); border-color: var(--ac-600); }
/* В превью модалки фото фиксированного размера (контейнер не grid) */
#photoPreview .sku-photo { width: 64px; height: 64px; aspect-ratio: auto; }
.sku-photo-empty {
  width: 100%; height: 72px;
  background: var(--bg);
  border-radius: 8px;
  border: 1px dashed var(--line-2);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 12px; font-size: 24px; color: var(--text-4);
}

.sku-name { font-size: 15px; font-weight: 700; color: var(--text-1); margin-bottom: 4px; }
.sku-article { font-size: 12px; color: var(--text-4); margin-bottom: 8px; }
.sku-price { font-size: 18px; font-weight: 700; color: var(--ac-700); margin-bottom: 8px; font-variant-numeric: tabular-nums; }
.sku-price .price-missing { color: var(--warn-500); font-size: 11px; font-weight: 600; }
/* Цена витрины WB рядом с РРЦ: разные вещи, поэтому и вид разный —
   РРЦ крупная (политика компании), витрина мелкая справочная (факт на сегодня). */
.sku-wbprice { font-size: 12px; color: var(--text-3); margin: -6px 0 8px; font-variant-numeric: tabular-nums; }
.sku-meta { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.sku-badge { font-size: 11px; font-weight: 600; background: var(--bg); color: var(--text-3); padding: 3px 8px; border-radius: 5px; border: 1px solid var(--line); }
/* Дефицит: «нет остатка» — тревожный бейдж */
.sku-badge-danger { background: var(--bad-50); color: var(--bad-ink); border-color: var(--bad-100); }

.feature-chips { display: flex; flex-wrap: wrap; gap: 4px; margin: 8px 0; }
.feature-chip {
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--text-3);
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 10px;
}

.sku-desc {
  font-size: 12px; color: var(--text-3); line-height: 1.6;
  margin-bottom: 14px; padding: 10px;
  background: var(--bg); border-radius: 8px; flex: 1;
}
.sku-actions { display: flex; gap: 8px; margin-top: auto; flex-wrap: wrap; }

.photo-dropzone {
  border: 2px dashed var(--line-2);
  border-radius: 10px;
  padding: 24px;
  text-align: center;
  cursor: pointer;
  transition: all 0.15s;
  background: var(--bg);
}
.photo-dropzone:hover { border-color: var(--ac-600); background: var(--ac-50); }

.empty-state { text-align: center; padding: 60px 20px; color: var(--text-4); }
/* Иконка пустого состояния — это div с эмодзи, а не SVG: общее .icon { 15×15 } (для иконок
   кнопок) делало из него 15-px блок у левого края, глиф вылезал из бокса и садился на
   текст («Шаблонов пока нет», 22.09.2026). Сбрасываем размеры — блок на всю ширину,
   эмодзи по центру, абзац под ним. */
.empty-state .icon { display: block; width: auto; height: auto; font-size: 48px; line-height: 1; margin: 0 auto 16px; }
.empty-state p { font-size: 15px; line-height: 1.6; }

.import-row { display: flex; gap: 12px; align-items: center; margin-top: 10px; }
.import-row input { flex: 1; }

/* ============ История ============ */

/* Без min-height/margin: в обычном сценарии (фильтра по товару нет) контейнер пуст и
   резервировал 54px пустоты между шапкой и списком (22.09.2026). Отступ — у самого чипа. */
.history-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.history-controls .filter-chip { margin-bottom: 16px; }

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--ac-50);
  border: 1px solid var(--ac-100);
  color: var(--ac-700);
  font-size: 13px;
  font-weight: 600;
  padding: 7px 12px;
  border-radius: 20px;
}
.filter-chip .chip-close { cursor: pointer; font-weight: 700; opacity: 0.6; }
.filter-chip .chip-close:hover { opacity: 1; }

.history-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 14px;
  cursor: pointer;
  transition: all 0.15s;
  box-shadow: var(--sh-1);
}
.history-item:hover { border-color: var(--ac-600); }
/* 22.09.2026: заголовку — не меньше 220px, колонка бейджей ужимается и переносит бейджи
   внутри себя. Раньше flex-shrink:0 у бейджей растягивал их в одну строку (~1030px с
   двумя полными названиями победителей плана), а заголовок переносился по одному слову. */
.history-main { flex: 1 1 auto; min-width: min(220px, 100%); }
.history-category { font-size: 15px; font-weight: 700; color: var(--text-1); }
/* Дата — информация (ею различаются одноимённые записи), а не прочерк: третья ступень,
   не четвёртая (та намеренно не проходит AA) */
.history-date { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.history-badges { display: flex; gap: 8px; align-items: center; flex: 0 1 auto; min-width: 0; justify-content: flex-end; flex-wrap: wrap; }
/* Род записи — это КЛАССИФИКАЦИЯ, а не оценка: раньше «сравнение» было зелёным,
   и запись читалась как «всё хорошо», хотя зелёный там значил только «вид записи».
   Теперь все виды выглядят одинаково тихо и различаются точкой. */
.history-badge {
  display: inline-flex; align-items: center; gap: var(--sp-6);
  font-size: 11px; line-height: 16px; font-weight: 600;
  color: var(--text-2); background: transparent;
  border: 1px solid var(--line-2); padding: 2px 9px; border-radius: var(--r-pill);
  max-width: 100%; min-width: 0;
}
.history-badge::before { content: ""; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%;
  background: var(--dot, var(--n-400)); }
/* Длинный текст бейджа (победители плана запуска — полные названия товаров) режется
   многоточием; полный список есть в самом отчёте по клику */
.history-badge .hb-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.history-badge.is-winners { max-width: 360px; }
.history-badge.type-compare { --dot: var(--ch-1); }
.history-badge.type-neutral { --dot: var(--n-400); }
/* Состояние фоновой операции в списках (analysisStateBadge в shared.js) */
.history-badge.type-pending { color: var(--warn-ink); background: var(--warn-50); border-color: var(--warn-100); --dot: var(--warn-500); }
.history-badge.type-error { color: var(--bad-ink); background: var(--bad-50); border-color: var(--bad-100); --dot: var(--bad-500); }
/* На телефоне запись истории складывается в колонку: заголовок сверху, бейджи ниже */
@media (max-width: 720px) {
  .history-item { flex-direction: column; align-items: flex-start; gap: 8px; }
  .history-badges { width: 100%; justify-content: flex-start; }
}

/* ============ Сравнение ============ */

.compare-winner {
  border: 1px solid var(--ok-500);
  background: var(--ok-50);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 12px;
}
.compare-winner .cw-label { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--ok-ink); margin-bottom: 4px; }
.compare-winner .cw-name { font-size: 18px; font-weight: 700; color: var(--text-1); }

.score-pill {
  display: inline-block;
  min-width: 44px;
  text-align: center;
  font-weight: 700;
  font-size: 13px;
  padding: 4px 10px;
  border-radius: 8px;
  background: var(--ac-50);
  color: var(--ac-700);
  font-variant-numeric: tabular-nums;
}

.pros-cons { font-size: 12px; line-height: 1.6; }
.pros-cons .pro { color: var(--ok-500); }
.pros-cons .con { color: var(--bad-500); }

/* ============ Модалки ============ */

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(28, 32, 48, 0.45); /* штора модалки: полупрозрачное затемнение поверх любой темы */
  z-index: 100;
  align-items: center;
  justify-content: center;
}
.modal-overlay.visible { display: flex; }
.modal {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 32px;
  width: 480px;
  max-width: 90vw;
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: 0 24px 64px rgba(28, 32, 48, 0.18); /* легаси-тень модалки: в три ступени --sh-1..3 не укладывается */
}
.modal h2 { font-size: 18px; font-weight: 700; color: var(--text-1); margin-bottom: 8px; }
.modal p { font-size: 13px; color: var(--text-3); margin-bottom: 24px; }
.modal-field { margin-bottom: 16px; }

.modal-actions { display: flex; gap: 12px; margin-top: 24px; }
.modal-actions .btn { flex: 1; }

.field-hint { font-size: 12px; color: var(--text-4); margin-top: 8px; }

/* ============ Адаптив ============ */

@media (max-width: 900px) {
  .container { padding: 16px 14px 32px; }
  .grid, .sku-grid, .price-grid { grid-template-columns: 1fr; }
  .form-row, .form-row.three { grid-template-columns: 1fr; }

  /* Сайдбар за левым краем; выезжает поверх контента по body.sidebar-open */
  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    height: 100vh;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: none;
    z-index: 70;
  }
  .sidebar-open .sidebar { transform: none; box-shadow: 0 12px 40px rgba(28, 32, 48, 0.25); /* тень выехавшего поверх шторы сайдбара: в ступени --sh-1..3 не укладывается */ }
  .sidebar-open .sidebar-backdrop { display: block; }
  .sidebar-open { overflow: hidden; }
  .sidebar-close { display: inline-flex; }
  .burger { display: inline-flex; }

  /* На телефоне шапка экрана не липнет: с действиями она высокая и съедала бы треть экрана;
     чипы разделов дашборда липнут к самому верху */
  .topbar { position: static; padding: 8px 14px; gap: 10px; }
  .an-subnav { top: 0; }
  .an-section { scroll-margin-top: 58px; }
  .topbar-title { font-size: 18px; }
  .topbar-actions { flex: 1 1 100%; justify-content: flex-start; }
  .topbar .page-head { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
  .topbar #anMeta { max-width: 100%; white-space: normal; flex-basis: 100%; }
  .an-head-actions { justify-content: flex-start; flex-wrap: wrap; }
}

@media (max-width: 720px) {
  .topbar-title { font-size: 15px; }
  /* Сравнение стратегий не влезает в ряд — складываем в колонку */
  .strat-compare { flex-direction: column; }
  .strat-arrow { align-self: center; transform: rotate(90deg); }
}
/* === Переключатель режимов в модалке товара (вручную / из WB) === */
.sku-mode-tabs {
  display: flex;
  gap: 0;
  margin: 18px 0 4px;
  background: var(--bg);
  border-radius: 10px;
  padding: 4px;
}
.sku-mode-tab {
  flex: 1;
  padding: 8px;
  text-align: center;
  font-size: 13px;
  color: var(--text-3);
  cursor: pointer;
  border-radius: 8px;
  transition: all 0.15s;
  user-select: none;
}
.sku-mode-tab.active {
  background: var(--surface);
  color: var(--ac-700);
  font-weight: 600;
  box-shadow: var(--sh-1);
}

/* Строка ввода артикула WB */
.wb-import-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 14px 0 6px;
  padding: 14px;
  background: var(--ac-50);
  border: 1px solid var(--ac-100);
  border-radius: var(--r-card);
}
.wb-import-row input {
  flex: 1;
  min-width: 220px;
}
.wb-import-status {
  flex-basis: 100%;
  font-size: 13px;
  color: var(--text-3);
  min-height: 18px;
}
.wb-import-status.ok { color: var(--ok-500); }
.wb-import-status.err { color: var(--bad-500); }

/* === Лайтбокс просмотра фото === */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(20, 22, 34, 0.88); /* лайтбокс: подложка постоянно тёмная в обеих темах, тема ни при чём */
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(2px);
}
.lightbox.visible { display: flex; }
.lightbox__img {
  max-width: 86vw;
  max-height: 86vh;
  border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5); /* тень на постоянно тёмной подложке лайтбокса — токены теней сюда не про то */
  object-fit: contain;
  background: #fff;  /* подложка под фото товара: белая в любой теме */
}
.lightbox__close {
  position: absolute;
  top: 20px;
  right: 24px;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12); /* полупрозрачная кнопка на постоянно тёмной подложке лайтбокса */
  color: #fff;  /* лайтбокс: всегда тёмная подложка, тема ни при чём */
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s;
}
.lightbox__close:hover { background: rgba(255, 255, 255, 0.24); /* ховер кнопки лайтбокса: та же белая полупрозрачность, вдвое плотнее */ }
.lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12); /* полупрозрачная кнопка на постоянно тёмной подложке лайтбокса */
  color: #fff;  /* лайтбокс */
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s;
  user-select: none;
}
.lightbox__nav:hover { background: rgba(255, 255, 255, 0.24); /* ховер кнопки лайтбокса: та же белая полупрозрачность, вдвое плотнее */ }
.lightbox__nav--prev { left: 24px; }
.lightbox__nav--next { right: 24px; }
.lightbox__counter {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;  /* лайтбокс */
  font-size: 13px;
  background: rgba(0, 0, 0, 0.4); /* подпись на постоянно тёмной подложке лайтбокса */
  padding: 6px 14px;
  border-radius: 20px;
}
.lightbox__nav.hidden, .lightbox__counter.hidden { display: none; }

/* Кнопки выбора при дубле артикула */
.wb-dup-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

/* === Оптимизация рекламы (sales): форма === */
.sales-form { display: flex; flex-direction: column; gap: 16px; }

/* Подзаголовки-группы длинных форм («1. Модели», «2. Бюджет и сроки», «3. Реклама») */
.form-group-title {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--text-1);
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.sales-field { display: flex; flex-direction: column; gap: 6px; }
.sales-field label { font-size: 13px; color: var(--text-3); }
.budget-control { display: flex; align-items: center; gap: 14px; }
/* Ползунок рисуем сами: с одним accent-color Chromium красит незаполненную часть трека
   контрастным светлым цветом независимо от color-scheme — в тёмной теме это была
   чисто-белая полоса (launch, 22.09.2026). Заполненную часть в Chromium при
   appearance:none браузер не рисует — трек ровный, положение показывает бегунок. */
.budget-control input[type="range"] { flex: 1; -webkit-appearance: none; appearance: none; height: 4px; padding: 0; border: 0; border-radius: 2px; background: var(--line-3); outline: 0; accent-color: var(--ac-600); }
.budget-control input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--ac-600); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--ac-600); cursor: pointer; }
.budget-control input[type="range"]::-moz-range-track { height: 4px; background: var(--line-3); border-radius: 2px; border: 0; }
.budget-control input[type="range"]::-moz-range-progress { height: 4px; background: var(--ac-600); border-radius: 2px; }
.budget-control input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--ac-600); border: 2px solid var(--surface); }
.budget-control input[type="range"]:focus-visible { box-shadow: var(--focus-ring); }
.sales-check { flex-direction: row !important; align-items: center; gap: 8px; font-size: 13px; color: var(--text-3); margin-top: 4px; cursor: pointer; }
.sales-check input { width: auto; }
.sales-actions { display: flex; align-items: center; gap: 14px; margin-top: 4px; }
.sales-status { font-size: 13px; color: var(--text-3); }
.sales-status.err { color: var(--bad-500); }

/* === Оптимизация рекламы (sales): рендер === */
.verdict { padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.verdict-go { background: var(--ok-50); color: var(--ok-500); }
.verdict-fix { background: var(--warn-50); color: var(--warn-ink); }
.verdict-stop { background: var(--bad-50); color: var(--bad-ink); }

.strat-compare { display: flex; align-items: stretch; gap: 16px; margin: 12px 0; }
.strat-col { flex: 1; padding: 14px 16px; border-radius: var(--r-card); border: 1px solid var(--line); }
.strat-old { background: var(--bad-50); }
.strat-new { background: var(--ok-50); }
.strat-label { font-weight: 700; margin-bottom: 8px; }
.strat-row { font-size: 13px; color: var(--text-3); margin: 3px 0; }
.strat-row b { color: var(--text-1); }
.strat-arrow { display: flex; align-items: center; font-size: 24px; color: var(--ac-600); }

.budget-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; margin-top: 8px; }
.budget-card { padding: 14px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--bg); }
.budget-reserve { border-style: dashed; }
.budget-media { background: var(--ac-50); border-color: var(--ac-100); }
.budget-sku { font-weight: 600; margin-bottom: 6px; }
.budget-amount { font-size: 18px; font-weight: 700; color: var(--ac-700); }
.budget-share { font-size: 13px; color: var(--text-3); font-weight: 600; }
.budget-meta { font-size: 12px; color: var(--text-3); margin-top: 6px; }
.budget-reason { font-size: 12px; color: var(--text-1); margin-top: 6px; }

.fix-item { padding: 10px 0; border-bottom: 1px solid var(--line); }
.fix-item:last-child { border-bottom: none; }
.econ-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-top: 10px; }
.stat-mid { font-size: 18px; font-weight: 700; color: var(--text-1); }

/* === Пикер анализов WB в форме продаж === */
.wb-picker { max-height: 220px; overflow-y: auto; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--bg); }
.wb-pick-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--line); cursor: pointer; font-size: 13px; }
.wb-pick-row:last-child { border-bottom: none; }
.wb-pick-row:hover { background: var(--ac-50); }
.wb-pick-row input { width: auto; flex-shrink: 0; }
.wb-pick-name { flex: 1; color: var(--text-1); }
.wb-pick-meta { font-size: 11px; color: var(--text-3); white-space: nowrap; }
.wb-picker-count { font-size: 12px; color: var(--ac-700); margin-top: 6px; }
.wb-pick-sub { color: var(--text-3); font-weight: 400; font-size: 12px; }

/* === Готовые карточки для менеджера === */
.cardgen { border: 1px solid var(--line); border-radius: var(--r-card); padding: 16px; margin-bottom: 14px; background: var(--bg); }
.cardgen-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.cardgen-sku { font-weight: 700; font-size: 15px; }
.cardgen-prio { font-size: 11px; padding: 2px 8px; border-radius: 12px; }
.cardgen-prio-hi { background: var(--bad-50); color: var(--bad-ink); }
.cardgen-prio-mid { background: var(--warn-50); color: var(--warn-ink); }
.cardgen-reason { font-size: 12px; color: var(--text-3); margin-bottom: 12px; }
.cardgen-field { margin-bottom: 12px; }
.cardgen-label { font-size: 12px; color: var(--text-3); margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }
.cardgen-len { color: var(--text-4); }
.cardgen-copy { margin-left: auto; font-size: 11px; padding: 2px 10px; border: 1px solid var(--ac-100); background: var(--ac-50); color: var(--ac-700); border-radius: 12px; cursor: pointer; }
.cardgen-copy:hover { background: var(--ac-600); color: var(--ac-fg); }
.cardgen-title { font-size: 15px; font-weight: 600; color: var(--text-1); padding: 8px 12px; background: var(--surface); border-radius: 8px; border: 1px solid var(--line); }
.cardgen-desc { font-size: 13px; line-height: 1.55; color: var(--text-1); padding: 10px 12px; background: var(--surface); border-radius: 8px; border: 1px solid var(--line); white-space: pre-wrap; }
.cardgen-bullets { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.6; }

/* === Выпадающее меню скачивания PDF === */
.pdf-menu-wrap { position: relative; display: inline-block; }
.pdf-menu {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(20,22,34,0.15); /* легаси-тень выпадающего меню: в три ступени --sh-1..3 не укладывается */
  z-index: 100;
  min-width: 180px;
  overflow: hidden;
}
.pdf-menu.open { display: block; }
.pdf-menu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  border: none;
  background: none;
  font-size: 13px;
  color: var(--text-1);
  cursor: pointer;
}
.pdf-menu button:hover { background: var(--ac-50); color: var(--ac-700); }
.pdf-menu button + button { border-top: 1px solid var(--line); }

/* Выбор формата кампании */
.format-choice { display: flex; flex-direction: column; gap: 8px; }
.format-choice label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-1); cursor: pointer; font-weight: 400; }
.format-choice input { width: auto; }
/* Класс задуман контейнером колонки вариантов, но им размечали и ОДИНОЧНЫЙ label —
   тогда column складывал чекбокс НАД текстом, и он висел в воздухе по центру
   (форма «Оптимизации рекламы», поймано 25.08.2026). Одиночному label — строка. */
label.format-choice { flex-direction: row; align-items: baseline; }
/* Аналитика — дашборд */
/* 176, а не 140: «21 460 308 ₽» в 24px — фактических 158px (замерено), и в минимальной
   резался краем (поймано владельцем на «Общем по всем РК», 25.08.2026) */
.an-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); gap: 12px; }
/* Шесть плиток ЯМ на «Продажах»: auto-fit в ~1080px давал 5 + 1 (одна плитка в пустом ряду) —
   кладём 3 + 3; на телефоне побеждает override .an-stats из блока ≤900 (22.09.2026) */
#anYmDynTiles { grid-template-columns: repeat(3, 1fr); }
.an-stat { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 12px 10px; }
.an-stat-label { font-size: 12px; color: var(--text-3); margin-bottom: 4px; }
.an-stat-value { font-size: 24px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; letter-spacing: -0.01em; }
.an-stat-sub { font-size: 12px; margin-top: 6px; min-height: 16px; }
.an-delta { font-weight: 700; font-size: 12px; }
.an-note { font-size: 12px; color: var(--text-4); margin-top: 12px; }
/* дозревание свежего дня (meta.maturity): жёлтая плашка ПОСЛЕ .an-note — тот же элемент, цвет должен победить */
.an-note.an-maturity { background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: var(--r-chip); padding: 8px 12px; color: var(--warn-ink); margin-top: 8px; font-size: 13px; }

/* Разделы дашборда: чипы-фильтры (показать один раздел / все) + заголовки-линейки.
   Липнут ПОД шапкой экрана (.topbar sticky, высота в --topbar-h — её пишет app.js).
   Числа в таблицах дашборда — табличной ширины, столбики не «пляшут». */
.an-subnav {
  position: sticky; top: var(--topbar-h, 60px); z-index: 30;
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 12px 2px; margin: 0 -2px 14px;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(6px);
}
.an-subnav a {
  font-size: 13px; font-weight: 600; color: var(--text-3); text-decoration: none;
  padding: 7px 16px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--sh-1); /* было 0 1px 2px rgba(20,24,50,.04) — та же тень слоя 1, но из токена: в тёмной теме гаснет вместе с остальными */
  transition: color .15s, background .15s, border-color .15s;
}
.an-subnav a:hover { color: var(--ac-700); border-color: var(--ac-100); }
.an-subnav a.active { color: var(--ac-fg); background: var(--ac-600); border-color: var(--ac-600); }
.an-section { scroll-margin-top: calc(var(--topbar-h, 60px) + 58px); }
.an-sec-head {
  display: flex; align-items: center; gap: 12px;
  margin: 26px 0 14px;
  font-size: 13px; line-height: 18px; font-weight: 600;
  color: var(--text-2);
}
.an-section:first-of-type .an-sec-head { margin-top: 4px; }
/* Паспорт свежести: из какого забора WB собраны числа секции. warn — забор пропущен */
.an-sec-fresh { font-size: 12px; font-weight: 400; color: var(--text-3); }
.an-sec-fresh.warn { color: var(--warn-ink); }
.an-sec-head::after { content: ''; flex: 1; height: 1px; background: var(--line); }
#tab-analytics table td, #tab-analytics table th { font-variant-numeric: tabular-nums; }

/* Юнит-экономика финансов: маржа окрашена статусно (плюс/минус), не серийно */
.an-fin-pos { color: var(--ok-500); font-weight: 700; }
.an-fin-neg { color: var(--bad-500); font-weight: 700; }

/* Заголовок карточки с управлением справа (переключатель/селект) */
.an-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.an-toggle { display: inline-flex; border: 1px solid var(--line-2); border-radius: 8px; overflow: hidden; }
.an-tg { border: none; background: var(--surface); color: var(--text-3); font-size: 12px; font-weight: 600; padding: 5px 12px; cursor: pointer; text-transform: none; letter-spacing: 0; }
.an-tg.active { background: var(--ac-600); color: var(--ac-fg); }
.an-select { border: 1px solid var(--line-2); border-radius: 8px; padding: 5px 10px; font-size: 13px; font-weight: 600; color: var(--text-1); background: var(--surface); cursor: pointer; text-transform: none; letter-spacing: 0; }
/* Выбор чата и «Отправить в Telegram» прячутся атрибутом hidden, пока чатов нет
   (loadSendTargets в analytics/actions.js) — предохранитель от display в классах */
.an-select[hidden], #anSendBtn[hidden] { display: none; }

/* Общий вывод агента */
.an-overall { background: var(--ac-50); border: 1px solid var(--ac-100); border-radius: var(--r-card); padding: 16px 20px; margin-bottom: 20px; line-height: 1.5; }
.an-overall-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 8px; }
.an-overall-head .an-overall-title { margin-bottom: 0; }
.an-overall-note { font-size: 11px; color: var(--text-3); margin-top: 10px; }
.an-overall-toggle { margin-top: 8px; font-size: 12px; }
.an-overall-title { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--ac-700); margin-bottom: 8px; }

/* Карточки «вывод по товару» */
.an-products { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.an-product { border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; background: var(--bg); }
.an-product-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.an-product-name { font-weight: 700; font-size: 15px; }
.an-product-nm { font-size: 11px; color: var(--text-4); white-space: nowrap; }
.an-product-metrics { display: flex; flex-wrap: wrap; gap: 10px 14px; font-size: 13px; color: var(--text-3); margin-bottom: 10px; }
.an-product-metrics b { color: var(--text-1); }
/* Вторая строка метрик — воронка (переходы → корзины → заказы): чуть мельче и приглушённее */
.an-product-funnel { font-size: 12px; color: var(--text-4); margin-top: -4px; }
.an-product-funnel b { color: var(--text-3); }
.an-product-note { font-size: 13px; line-height: 1.45; color: var(--text-1); border-top: 1px dashed var(--line); padding-top: 10px; }
.an-product-note.muted { color: var(--text-4); font-style: italic; }

/* Таблица товаров дашборда: поиск/фильтр, сортируемые заголовки, раскрывашки, ABC */
.an-prod-controls { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.an-prod-controls input[type="search"] {
  border: 1px solid var(--line-2); border-radius: 8px; padding: 6px 10px;
  font-size: 13px; min-width: 220px; background: var(--surface); color: var(--text-1);
}
.an-sort-th { cursor: pointer; user-select: none; white-space: nowrap; }
.an-sort-th:hover, .an-sort-th.active { color: var(--text-1); }
.an-prod-row { cursor: pointer; }
.an-prod-row:hover td { background: var(--bg); }
.an-prod-detail td { background: var(--bg); font-size: 12px; }
.an-abc-badge { display: inline-flex; align-items: center; gap: var(--sp-4); min-width: 22px; padding: 1px 7px;
  border-radius: var(--r-pill); border: 1px solid var(--line-2); background: transparent;
  font-size: 11px; line-height: 16px; font-weight: 700; color: var(--text-2); }
.an-abc-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--dot, var(--n-400)); }
.an-abc-a { --dot: var(--ch-2); }
.an-abc-b { --dot: var(--ch-4); }
.an-abc-c { --dot: var(--n-400); }
.an-link { background: none; border: none; color: var(--ac-600); cursor: pointer; font-size: 13px; font-weight: 600; padding: 6px 0; text-transform: none; letter-spacing: 0; }
.an-link:hover { text-decoration: underline; }

/* Контроль качества (агент-босс) */
.qc-banner { border-radius: 12px; padding: 12px 16px; margin-bottom: 16px; border: 1px solid; }
.qc-banner.qc-ok { background: var(--ok-50); border-color: var(--ok-100); }
.qc-banner.qc-warn { background: var(--warn-50); border-color: var(--warn-100); }
.qc-banner.qc-err { background: var(--bad-50); border-color: var(--bad-100); }
.qc-head { display: flex; justify-content: space-between; align-items: center; font-weight: 700; font-size: 13px; }
.qc-score { font-size: 13px; color: var(--text-3); }
.qc-sum { font-size: 13px; line-height: 1.5; margin-top: 6px; }
.qc-issues { margin: 8px 0 0; padding-left: 20px; }
.qc-issues li { font-size: 13px; line-height: 1.5; margin-bottom: 4px; }
.qc-issues li.qc-error { color: var(--bad-500); }
.qc-issues li.qc-warning { color: var(--warn-500); }

/* Реклама — анализ и рекомендации */
.adv-health { font-size: 13px; line-height: 1.5; background: var(--ac-50); border: 1px solid var(--ac-100); border-radius: 10px; padding: 12px 16px; margin-bottom: 16px; }
.adv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 8px; }
.adv-block { margin-bottom: 12px; }
.adv-h { font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.adv-h.good { color: var(--ok-500); }
.adv-h.bad { color: var(--bad-500); }
.adv-h.act { color: var(--ac-700); }
.adv-h.scale { color: var(--warn-500); }
.adv-list { margin: 0; padding-left: 20px; }
.adv-list li { font-size: 13px; line-height: 1.5; margin-bottom: 6px; }
@media (max-width: 720px) { .adv-grid { grid-template-columns: 1fr; } }

/* === Роли пользователей (auth.js вешает на body role-admin / role-manager / role-viewer):
   staff-only — рабочая часть (запуск/удаление анализов, формы, действия отзывов/товаров/отчётов,
                вкладки «Запуск новинок» и «Оптимизация рекламы»): видят admin и manager, скрыто viewer;
   admin-only — только admin: «Пользователи» (команда, сессии), «Данные и интеграции», расходы.
   Классы ставятся в index.html и JS-шаблонах; права всё равно проверяет бэкенд. === */
.role-viewer .staff-only,
.role-viewer .admin-only,
.role-manager .admin-only { display: none !important; }

/* Обратный класс: блоки только для viewer (например заглушка на «Анализе ниши»).
   Без !important — inline style.display из JS (enterReportView) должен побеждать. */
.viewer-only { display: none; }
.role-viewer .viewer-only { display: block; }
/* Блоки для всех, кроме админа (manager и viewer): подсказки «подключение — у администратора»
   там, где для админа показана инструкция по интеграциям (niche.js, reviews.js) */
.non-admin { display: none; }
.role-viewer .non-admin,
.role-manager .non-admin { display: block; }

/* Бейдж роли «менеджер» (users.js; админ — type-compare, просмотр — type-neutral) */
.history-badge.type-manager { --dot: var(--ch-7); }
/* Выбор роли в строке таблицы «Команда» (users.js) — компактный select вместо кнопки-переключателя */
.user-role-select { width: auto; padding: 5px 28px 5px 10px; font-size: 13px; border-radius: 8px; cursor: pointer; }
.user-role-select:disabled { cursor: not-allowed; opacity: 0.6; }
/* Колонка «Действия» команды — ровно по своим пяти кнопкам (как .sku-col-actions), иначе
   авторасклад отдавал ей меньше, и корзина падала на вторую строку (22.09.2026).
   Только десктоп: в блоке ≤720 td.u-actions — display:block внутри карточки. */
@media (min-width: 721px) {
  #usersList td.u-actions { width: 1%; white-space: nowrap; }
}

/* «Пользователи» → «Активные сессии» (users.js): таблица сессий компании */
.sessions-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 24px 0 12px; }
.sessions-head h3 { margin: 0; }
.sessions-head .sessions-meta { font-size: 12px; color: var(--text-3); }
.sessions-table td, .sessions-table th { vertical-align: middle; white-space: nowrap; }
.sessions-table .sess-user { font-weight: 600; }
.sessions-table .sess-login { color: var(--text-3); font-size: 12px; font-weight: 400; }
.sessions-table .sess-ip { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.sessions-table .sess-ip-changed { color: var(--warn-ink); }
.sessions-table .sess-muted { color: var(--text-3); font-size: 12px; }
.sessions-table tr.sess-current td { background: var(--ac-50); }

/* QC-баннер: проверка качества не выполнена (verdict: 'skipped') — серый, см. shared.js */
.qc-banner.qc-skipped { background: var(--bg); border-color: var(--line); color: var(--text-3); }

/* Вкладка «Пользователи»: блок с кредами созданного пользователя (users.js) */
.invite-result { margin-top: 14px; padding: 12px 16px; border: 1px solid var(--ac-100); background: var(--ac-50); border-radius: 10px; font-size: 13px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ============ Экран входа ============ */

#authScreen {
  display: none;
  position: fixed;
  inset: 0;
  /* Лёгкие пятна акцентного тона поверх --bg — экран входа не выглядит голым */
  background:
    radial-gradient(640px 420px at 18% 12%, rgba(108, 63, 255, 0.09), transparent 70%), /* декорация до входа: фикс. тон с альфой, к слоям цвета не относится */
    radial-gradient(560px 400px at 84% 82%, rgba(108, 63, 255, 0.06), transparent 70%), /* второе пятно той же декорации */
    var(--bg);
  z-index: 1000;
  align-items: center;
  justify-content: center;
}

.auth-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 40px;
  width: 420px;
  max-width: 90vw;
  box-shadow: var(--sh-1);
}

.auth-logo {
  font-size: 22px;
  font-weight: 700;
  color: var(--text-1);
  margin-bottom: 8px;
}
.auth-logo span { color: var(--ac-600); }

.auth-subtitle {
  font-size: 13px;
  color: var(--text-3);
  margin-bottom: 10px;
}

/* Строка ценности под подзаголовком (index.html, универсальный текст без брендов) */
.auth-value {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-4);
  margin-bottom: 28px;
}

.auth-title {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 16px;
}

.auth-field { margin-bottom: 14px; }

/* Поле пароля с кнопкой-глазом (togglePasswordVisibility в auth.js) */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 44px; }
.pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: none;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 6px;
  border-radius: 8px;
  color: var(--text-3);
}
.pw-toggle:hover { background: var(--ac-50); }
.pw-toggle:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }

.auth-error {
  color: var(--bad-500);
  font-size: 13px;
  margin-top: 8px;
  min-height: 20px;
}

/* Ссылка-переключатель «вход ↔ регистрация» (видна только при открытой регистрации) */
.auth-switch {
  margin-top: 16px;
  font-size: 13px;
  color: var(--text-3);
  text-align: center;
}
.auth-switch a { color: var(--ac-600); text-decoration: none; font-weight: 600; }
.auth-switch a:hover { text-decoration: underline; }

/* Контейнер виджета Turnstile: пустой (капча выключена) места не занимает */
.auth-captcha { margin-top: 4px; }
.auth-captcha:empty { display: none; }

/* ============ Мои товары: поиск/фильтр/пагинация (skus.js) ============ */

.sku-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 14px 18px; }
.sku-toolbar input[type="text"], .sku-toolbar input[type="search"] { flex: 1 1 220px; min-width: 200px; }
.sku-toolbar select { width: auto; max-width: 340px; }

/* Комбобокс с поиском (фильтр категорий в «Моих товарах»): кнопка как select + выпадающая
   панель со строкой поиска и списком. Разметка в index.html, логика в skus.js. */
.combo { position: relative; }
.combo-btn {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-1);
  border-radius: 10px;
  padding: 9px 30px 9px 12px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  max-width: 340px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* стрелка как у select */
  background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%), linear-gradient(135deg, var(--text-3) 50%, transparent 50%);
  background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}
.combo-btn:hover { border-color: var(--ac-600); }
.combo-btn-active { border-color: var(--ac-600); color: var(--ac-700); font-weight: 600; }
/* ВАЖНО: display:flex ниже перебил бы атрибут hidden (UA-стиль) — без этого правила
   панель была бы открыта всегда и перехватывала клики по таблице под ней */
.combo-drop[hidden] { display: none; }
.combo-drop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 80;
  width: 300px;
  max-width: 84vw;
  max-height: 360px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(28, 32, 48, 0.16); /* легаси-тень выпадашки комбобокса: в три ступени --sh-1..3 не укладывается */
  overflow: hidden;
}
.combo-drop input[type="search"] { margin: 8px; width: auto; flex: 0 0 auto; }
.combo-list { overflow-y: auto; overscroll-behavior: contain; padding: 0 4px 6px; }
.combo-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 13px;
  cursor: pointer;
}
.combo-item:hover { background: var(--bg); }
.combo-item.sel { background: var(--ac-50); color: var(--ac-700); font-weight: 600; }
.combo-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.combo-count { color: var(--text-3); font-size: 12px; flex: 0 0 auto; }
.combo-item.sel .combo-count { color: var(--ac-700); opacity: 0.75; }
.combo-empty { padding: 12px; font-size: 13px; color: var(--text-3); text-align: center; }
.sku-toolbar-count { font-size: 13px; color: var(--text-3); white-space: nowrap; margin-left: auto; }

.sku-pager { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 4px 0 24px; }
.sku-pager-info { font-size: 13px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* Результат массового импорта / загрузки шаблона в модалках */
.bulk-result { margin-top: 12px; font-size: 13px; line-height: 1.55; padding: 10px 14px; border-radius: 10px; border: 1px solid; }
.bulk-result.ok { background: var(--ok-50); border-color: var(--ok-100); color: var(--ok-500); }
.bulk-result.warn { background: var(--warn-50); border-color: var(--warn-100); color: var(--warn-ink); }
.bulk-result.err { background: var(--bad-50); border-color: var(--bad-100); color: var(--bad-ink); }
.bulk-errors { margin: 8px 0 0; padding-left: 18px; font-size: 12px; color: var(--bad-ink); }
.bulk-errors li { margin-bottom: 3px; }
.bulk-errors-more { font-size: 12px; color: var(--text-3); margin-top: 4px; }

/* Инструкция «какие выгрузки грузить» в модалке создания карточек из ВБ */
.import-paths { margin: 6px 0 12px; padding-left: 18px; font-size: 12px; color: var(--text-3); line-height: 1.5; }
.import-paths li { margin-bottom: 8px; }
.import-paths b { color: var(--text-1); font-weight: 600; }
.import-paths .import-path { color: var(--text-4); font-size: 11px; }
.import-hint { margin: 0 0 14px; font-size: 12px; color: var(--text-3); line-height: 1.5; }

/* Блок «Распознанные файлы» в результате создания карточек */
.bulk-recognized { margin-top: 10px; }
.bulk-recognized-title { font-size: 12px; font-weight: 600; color: var(--text-1); margin-bottom: 2px; }

/* ============ Отчёты: карточки шаблонов и модалка сборки (reports.js) ============ */

.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.tpl-card { border: 1px solid var(--line); border-radius: 12px; padding: 16px; background: var(--bg); display: flex; flex-direction: column; gap: 6px; }
.tpl-name { font-size: 15px; font-weight: 700; color: var(--text-1); }
.tpl-purpose { font-size: 13px; color: var(--text-3); line-height: 1.5; }
.tpl-meta { font-size: 11px; color: var(--text-4); }
.tpl-actions { display: flex; gap: 8px; margin-top: auto; padding-top: 10px; }
.report-cats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; max-height: 170px; overflow-y: auto; }

/* ============ Onboarding-чеклист «С чего начать» (renderOnboarding в analyze.js) ============ */

.onb-card { position: relative; padding-right: 48px; }
.onb-close {
  position: absolute;
  top: 14px;
  right: 14px;
  border: none;
  background: none;
  color: var(--text-4);
  font-size: 15px;
  line-height: 1;
  padding: 6px;
  border-radius: 8px;
  cursor: pointer;
}
.onb-close:hover { color: var(--bad-500); background: var(--bad-50); }
.onb-step { display: flex; align-items: center; gap: 12px; padding: 7px 0; }
.onb-check {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid var(--line-2);
  color: var(--text-3);
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.onb-step.done .onb-check {
  background: var(--ok-fill);
  border-color: var(--ok-fill);
  color: var(--ok-on);
}
.onb-link {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 13px;
  color: var(--text-1);
  cursor: pointer;
  text-align: left;
}
.onb-link:hover { color: var(--ac-700); text-decoration: underline; }
.onb-step.done .onb-link { color: var(--text-3); text-decoration: line-through; }
.onb-step.done .onb-link:hover { text-decoration: line-through underline; }

/* ============ Печать (Ctrl+P): только содержимое отчёта ============ */

@media print {
  header,
  .sidebar,
  .topbar,
  .sidebar-backdrop,
  .an-subnav,
  .nav-tab,
  .page-actions,
  .btn,
  .toast-container,
  .modal-overlay,
  .lightbox,
  .pdf-menu,
  .cardgen-copy,
  .sku-pager,
  .onb-card,
  #onboardingCard,
  .history-controls,
  .sales-actions,
  .long-op { display: none !important; }

  body { background: #fff; }
  .container { max-width: none; padding: 0; }

  /* Карточки без теней, с серой рамкой; не рвём карточку между страницами */
  .card, .history-item, .sku-card, .an-stat, .budget-card, .tpl-card {
    box-shadow: none !important;
    border: 1px solid #bbb;
    break-inside: avoid;
  }

  /* Отчётные блоки — на всю ширину в одну колонку */
  .grid, .sku-grid, .price-grid, .an-products, .budget-grid, .adv-grid, .tpl-grid {
    display: block;
  }
  .grid > .card, .price-card, .an-product, .budget-card, .tpl-card { margin-bottom: 12px; }
  .table-scroll { overflow: visible; }
  .table-scroll table { min-width: 0; }
  .wb-picker { max-height: none; overflow: visible; }

  /* Плашки статусов на ч/б принтере (этап 5, обещано спекой ВИЗУАЛЬНЫЙ-ЯЗЫК.md:737):
     сплошные заливки выходят серыми кляксами, в которых «хорошо» неотличимо от
     «плохо». На печати плашка становится контурной — читается текстом, а рейки
     принадлежности и семантики — тонкими чёрными. Экран это не трогает. */
  .st, .dg, .mp, .src, .per, .role, .dl, .cnt, .note, .seg, .chip {
    background: #fff !important;
    color: #000 !important;
    border: 1px solid #000 !important;
    box-shadow: none !important;
  }
  .dg--warn, .dg--bad, .dg--ok, .note--warn { box-shadow: inset 3px 0 0 #000 !important; }
  .mp-dot, .st::before, .src::before { color: #000 !important; background: #000 !important; }
}

/* ============ Экраны «Отзывы и вопросы» (rv-*, frontend/js/reviews.js) и
   «Данные и интеграции» (src-*, frontend/js/sources.js) — оболочка 2.0 ============ */

/* --- Отзывы и вопросы --- */
.rv-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.rv-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.rv-chip {
  font-size: 13px; font-weight: 600; color: var(--text-3); text-decoration: none;
  padding: 7px 16px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--sh-1); /* было 0 1px 2px rgba(20,24,50,.04) — та же тень слоя 1, но из токена: в тёмной теме гаснет вместе с остальными */
  transition: color .15s, background .15s, border-color .15s;
}
.rv-chip:hover { color: var(--ac-700); border-color: var(--ac-100); }
.rv-chip.active { color: var(--ac-fg); background: var(--ac-600); border-color: var(--ac-600); }
.rv-toolbar-right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--text-3); }
.rv-warn { color: var(--warn-ink); background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: 6px; padding: 3px 8px; }
.rv-gen { display: inline-flex; align-items: center; gap: 8px; color: var(--ac-700); font-weight: 600; }
.rv-gen .spinner { width: 14px; height: 14px; border-width: 2px; }
#rvList.rv-dim { opacity: .55; pointer-events: none; }

.rv-item { padding: 18px 20px; }
.rv-item-done { border-color: var(--ok-100); }
.rv-head { display: flex; align-items: flex-start; gap: 12px; }
.rv-check { display: flex; align-items: center; padding-top: 2px; cursor: pointer; }
.rv-check input { width: 16px; height: 16px; accent-color: var(--ac-600); cursor: pointer; margin: 0; }
.rv-prod { flex: 1; min-width: 0; }
.rv-prod-name { font-size: 15px; font-weight: 700; color: var(--text-1); overflow-wrap: anywhere; }
.rv-prod-meta { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.rv-when { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: 12px; color: var(--text-4); white-space: nowrap; flex-shrink: 0; }
.rv-kind { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--ac-700); }
.rv-user { color: var(--text-3); }
.rv-body { margin: 12px 0 0 28px; font-size: 13px; line-height: 1.55; }
.rv-rating { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.rv-stars { font-size: 16px; letter-spacing: 1px; line-height: 1; }
.rv-stars.good { color: var(--warn-500); }
.rv-stars.mid { color: var(--warn-500); }
.rv-stars.bad { color: var(--bad-500); }
.rv-flag { font-size: 11px; font-weight: 600; color: var(--text-3); background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; }
.rv-flag.warn { color: var(--warn-ink); background: var(--warn-50); border-color: var(--warn-100); }
.rv-text { color: var(--text-1); white-space: pre-wrap; overflow-wrap: anywhere; }
.rv-text-none { color: var(--text-4); font-style: italic; }
.rv-pc { margin-top: 4px; overflow-wrap: anywhere; }
.rv-pc span { font-weight: 700; }
.rv-pros span { color: var(--ok-500); }
.rv-cons span { color: var(--bad-ink); }
.rv-photos { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.rv-photo { width: 72px; height: 72px; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); cursor: zoom-in; background: var(--bg); }
.rv-video { position: relative; display: inline-block; margin-top: 10px; }
.rv-video .rv-photo { cursor: default; }
.rv-video-tag { display: inline-block; font-size: 11px; font-weight: 600; color: var(--text-3); background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; margin-top: 8px; }
.rv-video .rv-video-tag { position: absolute; left: 6px; bottom: 6px; margin: 0; background: rgba(28, 32, 48, .75); color: #fff; /* метка поверх фотографии */ border-color: transparent; }

.rv-answer { margin: 14px 0 0 28px; padding-top: 12px; border-top: 1px dashed var(--line); }
.rv-answer-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; line-height: 18px; font-weight: 600; color: var(--text-2); margin-bottom: 8px; }
.rv-badge { font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0; padding: 3px 9px; border-radius: 6px; max-width: 100%; overflow-wrap: anywhere; }
.rv-badge.ok { color: var(--ok-500); background: var(--ok-50); border: 1px solid var(--ok-100); }
.rv-badge.err { color: var(--bad-ink); background: var(--bad-50); border: 1px solid var(--bad-100); }
.rv-badge.muted { color: var(--text-3); background: var(--bg); border: 1px solid var(--line); }
.rv-none { font-size: 13px; color: var(--text-4); font-style: italic; }
.rv-ta { min-height: 88px; resize: vertical; font-size: 13px; line-height: 1.5; }
.rv-ta[readonly] { background: var(--bg); }
.rv-pub-text { font-size: 13px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; background: var(--ok-50); border: 1px solid var(--ok-100); border-radius: 10px; padding: 10px 14px; }
.rv-note { font-size: 12px; color: var(--text-3); margin-top: 8px; white-space: pre-wrap; overflow-wrap: anywhere; }
.rv-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.rv-len { font-size: 12px; color: var(--text-4); margin-right: auto; font-variant-numeric: tabular-nums; }

.rv-empty { text-align: center; padding: 48px 20px; }
.rv-empty-icon { font-size: 40px; margin-bottom: 10px; }
.rv-empty-text { font-size: 18px; font-weight: 700; color: var(--text-1); }
.rv-empty-sub { font-size: 13px; color: var(--text-3); margin-top: 6px; }
.rv-off p { font-size: 13px; line-height: 1.6; color: var(--text-1); margin-top: 10px; }
.rv-off-title { font-size: 15px; font-weight: 700; color: var(--text-1); }
.rv-off-reason { color: var(--warn-ink) !important; background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: 8px; padding: 8px 12px; font-size: 13px !important; }
.rv-link { color: var(--ac-700); font-weight: 600; text-decoration: none; }
.rv-link:hover { text-decoration: underline; }
/* Текст ответа в модалке подтверждения публикации — с переносами строк, длинный — с прокруткой */
#confirmModalText { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 50vh; overflow: auto; }

@media (max-width: 720px) {
  .rv-head { flex-wrap: wrap; }
  .rv-when { flex-direction: row; gap: 8px; width: 100%; align-items: center; white-space: normal; padding-left: 28px; }
  .rv-body, .rv-answer { margin-left: 0; }
}

/* --- Данные и интеграции --- */
.src-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.src-grid .card { margin-bottom: 0; }
.src-grid + .card { margin-top: 20px; }
@media (max-width: 1000px) { .src-grid { grid-template-columns: 1fr; } }
.src-state { font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 999px; }
.src-state.ok { color: var(--ok-500); background: var(--ok-50); border: 1px solid var(--ok-100); }
.src-state.off { color: var(--text-3); background: var(--bg); border: 1px solid var(--line); }
.src-lead { font-size: 13px; line-height: 1.55; color: var(--text-1); margin-bottom: 14px; }
.src-muted { font-size: 12px; color: var(--text-3); line-height: 1.5; }
.src-rows { display: grid; grid-template-columns: max-content 1fr; gap: 8px 16px; font-size: 13px; align-items: baseline; margin-bottom: 16px; }
.src-row { display: contents; }
.src-k { color: var(--text-3); font-size: 13px; white-space: nowrap; }
.src-v { color: var(--text-1); min-width: 0; overflow-wrap: anywhere; }
.src-tag { font-size: 11px; font-weight: 600; color: var(--text-3); background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; }
.src-tag.ok { color: var(--ok-500); background: var(--ok-50); border-color: var(--ok-100); }
.src-tag.warn { color: var(--warn-ink); background: var(--warn-50); border-color: var(--warn-100); }
.src-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.src-chip { font-size: 12px; font-weight: 600; color: var(--ac-700); background: var(--ac-50); border: 1px solid var(--ac-100); border-radius: 7px; padding: 3px 9px; }
.src-plates { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.src-plate { display: block; font-size: 13px; line-height: 1.5; border-radius: 8px; padding: 8px 12px; }
.src-plate.warn { color: var(--warn-ink); background: var(--warn-50); border: 1px solid var(--warn-100); }
.src-plate.danger { color: var(--bad-ink); background: var(--bad-50); border: 1px solid var(--bad-100); }
.src-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.src-how { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; font-size: 13px; line-height: 1.55; }
.src-how-title { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--text-2); margin-bottom: 8px; }
.src-how ol, .src-how ul { padding-left: 20px; margin: 0 0 8px; }
.src-how li { margin-bottom: 6px; }
.src-how li:last-child { margin-bottom: 0; }
.src-how code { font-family: ui-monospace, Consolas, monospace; font-size: 12px; background: var(--surface); border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px; }
.src-how .src-muted { margin-top: 8px; }
.src-link { font-size: 13px; font-weight: 600; color: var(--ac-700); text-decoration: none; }
.src-link:hover { text-decoration: underline; }

/* Ссылка «в кабинет WB» у кампании (adCampaigns.js, 19.09.2026): название и id —
   ссылки на advert.wildberries.ru. Не вырвиглаз: наследует текстовый цвет ячейки,
   teal только по ховеру + подчёркивание; значок ↗ — тихий, тем же teal, в обеих темах. */
.rk-lk { color: inherit; text-decoration: none; }
.rk-lk::after { content: '↗'; margin-left: 3px; font-size: 10px; color: var(--ac-600); opacity: 0.45; transition: opacity .12s; }
.rk-lk:hover { color: var(--ac-700); text-decoration: underline; }
.rk-lk:hover::after { opacity: 1; }

/* «Расход токенов» — первая карточка «Данных и интеграций» (sources.js: srcBillCardHtml) */
.src-bill-ctl { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.src-bill-ctl select { width: auto; max-width: 220px; cursor: pointer; }
.src-bill-from { white-space: nowrap; }
.src-bill-stats { margin-bottom: 18px; }
.src-bill-stats .an-stat.src-bill-main .an-stat-value { font-size: 32px; }
.src-bill-stats .an-stat.src-bill-accent { background: var(--ac-50); border-color: var(--ac-100); }
.src-bill-stats .an-stat.src-bill-accent .an-stat-value { color: var(--ac-700); }
.src-bill-section { margin-top: 16px; }
.src-bill-section .src-how-title { margin-bottom: 6px; }
.src-bill-table th.num, .src-bill-table td.num { text-align: right; white-space: nowrap; }
.src-bill-table td { padding: 9px 12px; }
.src-bill-table td:first-child { min-width: 180px; }
.src-bill-table tr.total td { font-weight: 700; border-top: 2px solid var(--ac-100); }
.table-scroll .src-bill-table-days { min-width: 420px; }
.src-bill-days { margin-top: 14px; font-size: 13px; }
.src-bill-days summary { cursor: pointer; font-weight: 600; color: var(--ac-700); font-size: 12px; }
.src-bill-days[open] summary { margin-bottom: 6px; }
.src-bill-actions { margin-top: 18px; margin-bottom: 0; }
.src-bill-files { margin-bottom: 0; }
.src-bill-note { margin-top: 16px; }
.src-bill-empty { margin-bottom: 0; }

/* ============ Мои товары 2.0: плашки, чипы, таблица-реестр, панель товара ============ */
/* Плашки-счётчики над списком: кнопки (клик = фильтр), «активная» — с акцентной рамкой */
.sku-summary { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; margin-bottom: 14px; }
.sku-plate {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  min-width: 96px; padding: 10px 14px; cursor: pointer; text-align: left;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--sh-1);
  font-family: inherit; color: var(--text-1); transition: border-color .15s, background .15s;
}
.sku-plate:hover { border-color: var(--ac-100); }
.sku-plate:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }
.sku-plate.active { border-color: var(--ac-600); background: var(--ac-50); }
.sku-plate.warn .sku-plate-val { color: var(--warn-ink); }
.sku-plate.danger .sku-plate-val { color: var(--bad-ink); }
.sku-plate.na { cursor: default; opacity: .6; }
.sku-plate.na .sku-plate-val { color: var(--text-4); }
.sku-plate-val { font-size: 18px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.sku-plate-label { font-size: 11px; color: var(--text-3); font-weight: 600; white-space: nowrap; }
.sku-plate-period { align-self: center; margin-left: auto; font-size: 12px; color: var(--text-3); white-space: nowrap; }

/* Переключатель вида Таблица | Карточки */
.sku-view-toggle { display: inline-flex; border: 1px solid var(--line-2); border-radius: 9px; overflow: hidden; }
.sku-view-btn {
  padding: 8px 12px; font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer;
  background: var(--surface); color: var(--text-3); border: none; border-right: 1px solid var(--line-2);
}
.sku-view-btn:last-child { border-right: none; }
.sku-view-btn:hover { color: var(--text-1); background: var(--bg); }
.sku-view-btn.active { background: var(--ac-50); color: var(--ac-700); }
.sku-view-btn:focus-visible { outline: 2px solid var(--ac-600); outline-offset: -2px; }

/* Фильтр-чипы «где проблема» под тулбаром (мультивыбор) */
.sku-chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: -8px 0 14px; }
.sku-chip {
  font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  padding: 5px 11px; border-radius: 999px;
  background: var(--surface); color: var(--text-3); border: 1px solid var(--line-2);
  transition: border-color .15s, background .15s, color .15s;
}
.sku-chip:hover { border-color: var(--ac-600); color: var(--ac-700); }
.sku-chip.active { background: var(--ac-50); border-color: var(--ac-600); color: var(--ac-700); }
.sku-chip:disabled { opacity: .5; cursor: default; }
.sku-chip:disabled:hover { border-color: var(--line-2); color: var(--text-3); }
.sku-chip-clear { border-style: dashed; }
.sku-chip:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }

/* Таблица-реестр: своя вертикальная прокрутка с липкой шапкой (внутри overflow-x:auto
   sticky относительно страницы не работает — поэтому прокрутка внутри контейнера) */
.sku-table-note { font-size: 12px; color: var(--text-3); margin-bottom: 8px; }
.sku-table-wrap.card { padding: 0; overflow: auto; max-height: calc(100vh - var(--topbar-h, 60px) - 40px); }
.sku-table { width: 100%; min-width: 1242px; table-layout: fixed; border-collapse: separate; border-spacing: 0; }
.sku-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--surface);
  padding: 10px 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: inset 0 -1px 0 var(--line);
  font-size: 11px;
}
.sku-table th.sku-th-sort { cursor: pointer; user-select: none; }
.sku-table th.sku-th-sort:hover { color: var(--ac-700); }
.sku-table th.sku-th-sort.active { color: var(--ac-700); }
.sku-table th.sku-th-sort:focus-visible { outline: 2px solid var(--ac-600); outline-offset: -2px; }
.sku-sort-mark { font-size: 9px; margin-left: 3px; }
.sku-table td { padding: 7px 6px; font-size: 12px; vertical-align: middle; border-bottom: 1px solid var(--bg); overflow: hidden; }
.sku-table tr.sku-row { cursor: pointer; }
.sku-table tr.sku-row:hover td { background: var(--bg); }
.sku-table tr.sku-row:focus-visible { outline: 2px solid var(--ac-600); outline-offset: -2px; }
.sku-table th.sku-num, .sku-table td.sku-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sku-table td.sku-num { font-size: 12px; }
.sku-col-cat span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sku-tbrand { font-size: 11px; color: var(--text-4); margin-top: 1px; }
.sku-twb { font-size: 11px; color: var(--text-4); margin-top: 1px; }
.sku-col-health { white-space: nowrap; }
.sku-col-actions { width: 1%; white-space: nowrap; }
/* Десктоп: 15 колонок (1314px по colgroup) шире карточки на 1440 (1128px), а полоса
   прокрутки лежит у низа блока высотой в экран — кнопки действий не было видно вовсе
   (22.09.2026). Колонка действий липнет к правому краю (по образцу липких первых двух
   колонок из блока ≤900), а тень на ней — подсказка «правее есть ещё колонки»
   (data-scroll на .sku-table-wrap ставит app.js и на десктопе — только для этого блока). */
@media (min-width: 901px) {
  .sku-table th.sku-col-actions, .sku-table td.sku-col-actions { position: sticky; right: 0; z-index: 1; background: var(--surface); box-shadow: -1px 0 0 var(--line); }
  .sku-table thead th.sku-col-actions { z-index: 3; }
  .sku-table tr.sku-row:hover td.sku-col-actions { background: var(--bg); }
  .sku-table-wrap[data-scroll="start"] .sku-col-actions, .sku-table-wrap[data-scroll="mid"] .sku-col-actions {
    box-shadow: -1px 0 0 var(--line), -12px 0 10px -10px rgba(28, 32, 48, 0.18); /* затенение края прокрутки, как у .table-scroll на телефоне: альфа-градиент в токен не переводится */
  }
}
/* Колонка фото объявлена в skus.js шириной 44px, а обычные паддинги ячейки 6+6
   оставляли миниатюре 32px — при её 40px правый край срезался на 2px
   (на td стоит overflow:hidden). Арифметика: 2 + 40 + 2 = 44. */
.sku-table td.sku-col-photo { padding-left: 2px; padding-right: 2px; }
.sku-thumb { width: 40px; height: 40px; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); cursor: zoom-in; display: block; }
.sku-thumb-empty { display: flex; align-items: center; justify-content: center; background: var(--bg); color: var(--text-4); font-size: 18px; cursor: default; }
.sku-tname { font-weight: 600; color: var(--text-1); line-height: 18px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sku-tart { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-3); margin-top: 2px; min-width: 0; }
.sku-tart-t { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sku-tnm { color: var(--text-4); }
.sku-tflag { flex: 0 0 auto; font-size: 10px; font-weight: 700; color: var(--warn-ink); background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: 5px; padding: 0 5px; margin-left: 4px; }
/* Бейдж размерной семьи: ЯМ/Ozon заводят SKU на каждый размер, строка списка
   склеивает их в карточку — бейдж говорит «36–47 · 12 разм.», поповер несёт
   артикулы. Нейтральный вид: это не проблема, а свойство товара. */
.sku-tsizes { flex: 0 0 auto; font-size: 10px; color: var(--text-3); border: 1px solid var(--line-2); border-radius: 999px; padding: 0 6px; margin-left: 4px; cursor: pointer; white-space: nowrap; }
.sku-na { color: var(--text-4); }
.sku-stock-zero { color: var(--text-3); }
.sku-stock-alarm { color: var(--bad-ink); font-weight: 700; }
.sku-trend { font-weight: 700; font-size: 12px; white-space: nowrap; }
.sku-trend-up { color: var(--ok-500); }
.sku-trend-down { color: var(--bad-ink); }
.sku-trend-flat { color: var(--text-4); }
.sku-health { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg); color: var(--text-3); white-space: nowrap; }
.sku-health-issue { color: var(--bad-ink); background: var(--bad-50); border-color: var(--bad-100); }
.sku-health-ok { color: var(--ok-500); background: var(--ok-50); border-color: var(--ok-100); }
.sku-health-low { color: var(--text-3); }
.sku-health-none { color: var(--text-4); border-style: dashed; }
.sku-row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.sku-row-actions .btn { padding: 4px 6px; }
.sku-row-actions .btn .icon { width: 15px; height: 15px; }
/* Карточки: имя кликабельно (панель), строка среза */
.sku-name-link { cursor: pointer; }
.sku-name-link:hover { color: var(--ac-700); }
.sku-card-sales { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; font-size: 12px; color: var(--text-3); background: var(--bg); border-radius: 8px; padding: 8px 10px; margin-bottom: 10px; cursor: pointer; }
.sku-card-sales b { color: var(--text-1); font-variant-numeric: tabular-nums; }

/* Панель товара: правый drawer поверх страницы */
.sku-drawer-overlay { display: none; position: fixed; inset: 0; z-index: 120; background: rgba(28, 32, 48, 0.4); /* штора: полупрозрачное затемнение поверх любой темы */ }
.sku-drawer-overlay.visible { display: block; }
.sku-drawer {
  position: absolute; top: 0; right: 0; bottom: 0; width: 620px; max-width: 100vw;
  background: var(--surface); border-left: 1px solid var(--line); box-shadow: -12px 0 40px rgba(28, 32, 48, 0.18); /* тень drawer'а влево: направленная, в вертикальные ступени --sh-1..3 не переводится */
  display: flex; flex-direction: column;
  animation: skuDrawerIn .18s ease-out;
}
@keyframes skuDrawerIn { from { transform: translateX(24px); opacity: .6; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sku-drawer { animation: none; } }
.sku-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px; border-bottom: 1px solid var(--line); }
.sku-drawer-title { font-size: 15px; line-height: 20px; font-weight: 600; color: var(--text-1); }
.sku-drawer-close { width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--line-2); background: var(--surface); color: var(--text-3); font-size: 20px; line-height: 1; cursor: pointer; }
.sku-drawer-close:hover { color: var(--text-1); background: var(--bg); }
.sku-drawer-close:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }
.sku-drawer-body { flex: 1 1 auto; overflow-y: auto; padding: 18px 20px 32px; }
.sku-panel-photos { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin-bottom: 12px; }
.sku-panel-more { border: 1px dashed var(--line-2); background: var(--bg); color: var(--text-3); border-radius: 8px; font-weight: 700; cursor: pointer; aspect-ratio: 1; }
.sku-panel-photo { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); cursor: zoom-in; }
.sku-panel-photo.main { grid-column: span 2; grid-row: span 2; }
.sku-panel-photo:hover { border-color: var(--ac-600); }
.sku-panel-name { font-size: 18px; font-weight: 700; color: var(--text-1); line-height: 1.3; margin-bottom: 6px; }
.sku-panel-arts { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; font-size: 12px; color: var(--text-3); margin-bottom: 12px; }
.sku-panel-arts b { color: var(--text-1); font-weight: 600; }
.sku-panel-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.sku-panel-actions .btn { padding: 8px 12px; font-size: 13px; }
.sku-panel-sec { border-top: 1px solid var(--line); padding: 14px 0; }
.sku-panel-sec-title { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); margin-bottom: 10px; }
.sku-kv { display: flex; gap: 12px; align-items: baseline; font-size: 13px; padding: 4px 0; }
.sku-k { flex: 0 0 140px; color: var(--text-3); }
.sku-v { color: var(--text-1); font-variant-numeric: tabular-nums; }
.sku-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin-bottom: 12px; }
.sku-tile { background: var(--bg); border-radius: 10px; padding: 10px 12px; }
.sku-tile-v { font-size: 18px; font-weight: 700; color: var(--text-1); font-variant-numeric: tabular-nums; line-height: 1.15; }
.sku-tile-l { font-size: 11px; color: var(--text-3); margin-top: 2px; }
.sku-chart-wrap { position: relative; height: 110px; }
.sku-funnel { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
.sku-funnel-step { flex: 1 1 100px; min-width: 100px; background: var(--bg); border-radius: 10px; padding: 8px 10px; font-size: 11px; }
.sku-funnel-v { font-size: 18px; font-weight: 700; color: var(--text-1); font-variant-numeric: tabular-nums; }
.sku-funnel-l { color: var(--text-3); font-weight: 600; margin: 2px 0; }
.sku-funnel-arrow { align-self: center; color: var(--text-4); font-size: 14px; }
.sku-health-box { font-size: 13px; line-height: 1.5; border-radius: 10px; padding: 10px 12px; border: 1px solid var(--line); background: var(--bg); color: var(--text-1); }
.sku-health-box.issue { background: var(--bad-50); border-color: var(--bad-100); }
.sku-health-box.ok { background: var(--ok-50); border-color: var(--ok-100); }
.sku-health-box.low { color: var(--text-3); }
.sku-quote { font-size: 13px; line-height: 1.6; color: var(--text-1); border-left: 3px solid var(--ac-100); background: var(--ac-50); padding: 10px 14px; border-radius: 0 10px 10px 0; margin: 0; }
body.sku-drawer-open { overflow: hidden; }
@media (max-width: 720px) {
  .sku-drawer { width: 100vw; }
  .sku-plate { min-width: 80px; padding: 8px 10px; }
  .sku-plate-period { margin-left: 0; width: 100%; white-space: normal; }
  .sku-table-wrap.card { max-height: none; }
  .sku-k { flex-basis: 110px; }
  /* Липкие фото 44px + «Товар» 240px съедали 284 из 376px, под остальные 13 колонок
     оставалась щель ~92px (22.09.2026). Колонка имени — 150px (название и так режется
     многоточием, артикул 11px влезает); !important перебивает инлайн width из colgroup
     (skus.js), потому что при table-layout:fixed ширину задаёт только <col>. */
  .sku-table col:nth-child(2) { width: 150px !important; }
  /* Затенение края у таблицы товаров уже общего 28px: окно прокрутки на 400 всего ~180px */
  .sku-table-wrap[data-scroll="start"], .sku-table-wrap[data-scroll="mid"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 14px), rgba(0, 0, 0, 0.15)); /* маска-градиент: цвет тут — только альфа-канал затухания */
    mask-image: linear-gradient(to right, #000 calc(100% - 14px), rgba(0, 0, 0, 0.15)); /* тот же градиент без префикса */
  }
}
@media print { .sku-drawer-overlay, .sku-summary, .sku-chips, .sku-view-toggle { display: none !important; } }

/* ============ Оценка ниши (вкладка niche, frontend/js/niche.js) ============
   Форма с подсказками категорий MPSTATS, чип выбранной категории, KPI-сетка,
   score-бейдж вердикта (цвет по значению), компактные таблицы с overflow-x. */
.history-badge.type-niche { --dot: var(--ch-2); }
.niche-form { display: flex; flex-direction: column; gap: 10px; }
.niche-query-wrap { position: relative; }
.niche-query-wrap input[type="text"] { width: 100%; font-size: 15px; }
.niche-suggest {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(28, 32, 48, 0.12); /* легаси-тень подсказок поиска: в три ступени --sh-1..3 не укладывается */ max-height: 320px; overflow-y: auto;
}
.niche-suggest-item { padding: 9px 14px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; border-bottom: 1px solid var(--bg); }
.niche-suggest-item:last-child { border-bottom: none; }
.niche-suggest-item:hover { background: var(--ac-50); }
.niche-suggest-name { font-size: 13px; font-weight: 600; color: var(--text-1); }
.niche-suggest-path { font-size: 12px; color: var(--text-3); }
.niche-chip-row { min-height: 20px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.niche-chip { max-width: 100%; }
.niche-chip-hint { font-size: 12px; color: var(--text-4); }
.niche-form-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.niche-form-row .sales-check { margin-top: 0; }
.niche-form-row .btn { margin-left: auto; }
.niche-inline { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 13px; }
.niche-status-line { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--line); font-size: 12px; color: var(--text-4); }
.niche-candidates { margin-top: 6px; padding: 12px 14px; background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: 10px; }
.niche-candidates-title { font-size: 13px; font-weight: 600; color: var(--warn-ink); margin-bottom: 8px; }
.niche-candidates-list { display: flex; flex-wrap: wrap; gap: 8px; }
.niche-candidate { white-space: normal; text-align: left; line-height: 1.3; }
.niche-off-title { font-size: 18px; font-weight: 700; margin-bottom: 8px; }
.niche-off-text { font-size: 13px; color: var(--text-3); line-height: 1.6; }
.niche-off-text code { background: var(--bg); border: 1px solid var(--line); border-radius: 5px; padding: 1px 6px; font-size: 13px; }
.niche-recent .history-item { margin-bottom: 8px; }
.niche-recent .history-item:last-child { margin-bottom: 0; }

/* Шапка отчёта */
.niche-head-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.niche-head-main { min-width: 0; flex: 1; }
.niche-head-title { font-size: 24px; font-weight: 700; letter-spacing: -0.01em; margin-bottom: 8px; line-height: 1.2; }
.niche-head-meta { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: var(--text-3); }
.niche-head-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* Вердикт ИИ */
.niche-verdict-row { display: flex; gap: 20px; align-items: flex-start; }
.niche-verdict-main { flex: 1; min-width: 0; }
.niche-score { flex: 0 0 auto; width: 84px; height: 84px; border-radius: 16px; display: flex; flex-direction: column; align-items: center; justify-content: center; border: 1px solid transparent; }
.niche-score-num { font-size: 32px; font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
.niche-score-of { font-size: 11px; font-weight: 600; opacity: 0.8; margin-top: 3px; }
.niche-score-good { background: var(--ok-50); color: var(--ok-500); border-color: var(--ok-100); }
.niche-score-mid { background: var(--warn-50); color: var(--warn-ink); border-color: var(--warn-100); }
.niche-score-bad { background: var(--bad-50); color: var(--bad-ink); border-color: var(--bad-100); }
.niche-score-na { background: var(--bg); color: var(--text-3); border-color: var(--line); }
.niche-decision { text-transform: none; letter-spacing: 0; font-size: 12px; color: var(--ac-700); }
.niche-verdict-headline { font-size: 18px; font-weight: 700; line-height: 1.35; margin-bottom: 8px; }
.niche-verdict-summary { font-size: 13px; line-height: 1.65; color: var(--text-1); }
.niche-verdict-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 4px; }
.niche-verdict-cols .insight-box { margin-top: 10px; }
.niche-verdict-off .niche-dim { font-size: 13px; }

/* KPI-плитки */
.niche-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.niche-kpi { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; min-width: 0; }
.niche-kpi-label { font-size: 12px; color: var(--text-3); margin-bottom: 4px; }
.niche-kpi-value { font-size: 18px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.niche-kpi-sub { font-size: 12px; color: var(--text-3); margin-top: 6px; line-height: 1.4; }
.niche-up { color: var(--ok-500); font-weight: 700; }
.niche-down { color: var(--bad-500); font-weight: 700; }
.niche-flat { color: var(--text-3); font-weight: 600; }
.niche-kpi-sub .niche-up, .niche-kpi-sub .niche-down { font-weight: 600; }

/* Графики */
.niche-grid { align-items: start; }
.niche-grid > .card { margin-bottom: 0; min-width: 0; }
.niche-chart { position: relative; height: 260px; }
.niche-chart canvas { max-width: 100%; }
.niche-chart-sm { height: 140px; }
.niche-demand { display: grid; grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr); gap: 20px; align-items: start; }
.niche-demand > * { min-width: 0; }
.niche-demand-table .table-scroll { max-height: 460px; overflow-y: auto; }
.niche-demand-table thead th { position: sticky; top: 0; background: var(--surface); z-index: 1; }
.niche-demand-side .tag { font-size: 12px; padding: 3px 8px; }
.niche-note { font-size: 12px; color: var(--text-3); margin-top: 12px; line-height: 1.5; }
.niche-note b { color: var(--text-1); }

/* Таблицы: компактные, прокрутка по горизонтали внутри карточки */
.niche-table table { min-width: 640px; }
.niche-table-narrow table { min-width: 420px; }
.niche-table-items table { min-width: 960px; }
.niche-table th { white-space: nowrap; }
.niche-table td { padding: 8px 10px; font-size: 13px; vertical-align: middle; white-space: nowrap; }
.niche-table td.niche-wrap { white-space: normal; min-width: 180px; }
.niche-table .niche-item-name { font-weight: 600; line-height: 1.3; max-width: 340px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.niche-thumb { width: 40px; height: 40px; }
.niche-dim { color: var(--text-3); }
.niche-small { font-size: 11px; }
.niche-yes { color: var(--warn-ink); font-weight: 600; }
.niche-more { margin-top: 12px; text-align: center; }
.niche-table .history-badge { white-space: nowrap; font-size: 11px; padding: 3px 8px; }

/* Вход в нишу */
.niche-entry-grid { margin-bottom: 4px; }
.niche-lvl { display: inline-block; padding: 2px 10px; border-radius: var(--r-chip); font-size: 12px; line-height: 16px; font-weight: 600; }
.niche-lvl-high { background: var(--bad-50); color: var(--bad-ink); }
.niche-lvl-mid { background: var(--warn-50); color: var(--warn-ink); }
.niche-lvl-low { background: var(--ok-50); color: var(--ok-500); }
.niche-entry-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; margin-top: 16px; }
.niche-entry-block { background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.niche-entry-risks { background: var(--bad-50); border-color: var(--bad-100); }
.niche-entry-h { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); margin-bottom: 8px; }
.niche-entry-big { font-size: 24px; font-weight: 700; letter-spacing: -0.01em; margin-bottom: 6px; font-variant-numeric: tabular-nums; }
.niche-entry-text { font-size: 13px; line-height: 1.55; color: var(--text-3); margin-top: 6px; }
.niche-kv { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; padding: 4px 0; border-bottom: 1px dashed var(--line); }
.niche-kv:last-of-type { border-bottom: none; }
.niche-kv span { color: var(--text-3); }
.niche-kv b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.niche-list { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.55; color: var(--text-1); }
.niche-list li { margin-bottom: 5px; }
.niche-list li:last-child { margin-bottom: 0; }

@media (max-width: 900px) {
  .niche-grid { grid-template-columns: 1fr; }
  .niche-demand { grid-template-columns: 1fr; }
  .niche-verdict-cols { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .niche-verdict-row { flex-direction: column; }
  .niche-head-row { flex-direction: column; }
  .niche-head-main { width: 100%; }
  .niche-form-row .btn { margin-left: 0; width: 100%; }
  .niche-head-title { font-size: 18px; }
}

/* Оценка ниши: документы поставщика (наши товары для входа) */
.niche-docs { margin: 12px 0 6px; padding: 12px 14px; border: 1px dashed var(--line); border-radius: 10px; background: var(--bg); }
.niche-docs-label { display: block; font-size: 13px; font-weight: 600; color: var(--text-1); margin-bottom: 8px; }
.niche-docs-row { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
.niche-docs-row input[type=file] { font-size: 13px; max-width: 100%; }
.niche-docs-row .niche-small { flex: 1 1 260px; }
.niche-context { display: block; width: 100%; margin-top: 10px; font: inherit; font-size: 13px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--text-1); resize: vertical; }
.niche-ours .niche-feats .tag { margin: 0 4px 4px 0; font-size: 11px; }
.niche-ours-table table { min-width: 900px; }
.niche-ours-table td { vertical-align: top; }
.niche-ours-table th:nth-child(4), .niche-ours-table td:nth-child(4) { min-width: 240px; white-space: normal; }
.niche-ours-table th:nth-child(5), .niche-ours-table td:nth-child(5) { min-width: 260px; white-space: normal; }
.niche-note-warn { border-color: var(--warn-100); background: var(--warn-50); color: var(--warn-ink); }
.niche-kind { display: inline-block; font-size: 11px; line-height: 16px; font-weight: 600; padding: 1px 6px; border-radius: 6px; background: var(--bg); border: 1px solid var(--line); color: var(--text-3); vertical-align: middle; }
.niche-kind-subject { color: var(--ac-700); background: var(--ac-50); border-color: var(--ac-100); }
.niche-outside-list { display: flex; flex-direction: column; gap: 6px; }
.niche-outside-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; }
.niche-outside-row .btn { margin-left: auto; }

/* ============ Портфель предметов (frontend/js/niche.js → renderNichePortfolio) ============
   Все классы с префиксом .pf-: форма (чекбокс портфеля), шапка, вердикт по портфелю,
   сводная матрица позиционирования, карточки предметов и сравнительная таблица с конкурентами. */
.history-badge.type-portfolio { --dot: var(--ch-5); }
.niche-portfolio-opts { margin: 4px 0 8px; padding: 10px 14px; border: 1px solid var(--ac-100); border-radius: 10px; background: var(--ac-50); display: flex; flex-direction: column; gap: 6px; }
.niche-portfolio-opts .sales-check { margin-top: 0; color: var(--text-1); }
.niche-portfolio-opts .sales-check.pf-sub { font-size: 12px; color: var(--text-3); padding-left: 24px; }
.niche-portfolio-opts .sales-check.disabled { color: var(--text-4); cursor: not-allowed; }
.pf-opts-note { font-size: 12px; color: var(--text-3); line-height: 1.45; }
.pf-opts-note b { color: var(--ac-700); }

/* шапка */
.pf-head-title { font-size: 18px; font-weight: 700; line-height: 1.25; margin-bottom: 8px; }
.pf-head-title small { display: block; font-size: 13px; font-weight: 400; color: var(--text-3); margin-top: 4px; }
.pf-facts { display: flex; flex-wrap: wrap; gap: 8px 10px; margin-top: 4px; }
.pf-fact { font-size: 12px; color: var(--text-3); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px; }
.pf-fact b { color: var(--text-1); font-weight: 700; }
.pf-context { margin-top: 10px; font-size: 13px; color: var(--text-3); line-height: 1.5; }
.pf-context b { color: var(--text-1); }

/* бейджи оценки SKU (зелёный/жёлтый/красный) и волн запуска */
.pf-score { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 700; padding: 3px 9px; border-radius: 8px; white-space: nowrap; border: 1px solid transparent; }
.pf-score-green { background: var(--ok-50); color: var(--ok-500); border-color: var(--ok-100); }
.pf-score-yellow { background: var(--warn-50); color: var(--warn-ink); border-color: var(--warn-100); }
.pf-score-red { background: var(--bad-50); color: var(--bad-ink); border-color: var(--bad-100); }
.pf-score-na { background: var(--bg); color: var(--text-4); border-color: var(--line); }
.pf-wave { display: inline-block; font-size: 11px; line-height: 16px; font-weight: 600; padding: 3px 9px; border-radius: 7px; white-space: nowrap; }
.pf-wave-1 { background: var(--ok-50); color: var(--ok-500); }
.pf-wave-2 { background: var(--warn-50); color: var(--warn-ink); }
.pf-wave-3 { background: var(--bg); color: var(--text-3); border: 1px solid var(--line); }
.pf-delta-neutral { color: var(--text-3); font-weight: 600; }
.pf-delta-low { color: var(--ok-500); font-weight: 700; }
.pf-delta-high { color: var(--warn-ink); font-weight: 700; }
.pf-delta-vhigh { color: var(--bad-500); font-weight: 700; }

/* вердикт по портфелю */
.pf-verdict-summary { font-size: 13px; line-height: 1.65; color: var(--text-1); margin-bottom: 14px; }
.pf-verdict-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; margin-top: 14px; }
.pf-block { background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; min-width: 0; }
.pf-block-risks { background: var(--bad-50); border-color: var(--bad-100); }
.pf-block-budget { background: var(--ac-50); border-color: var(--ac-100); }
.pf-block .niche-list li { margin-bottom: 8px; }
.pf-block .niche-list li b { color: var(--text-1); }
.pf-rank-table table { min-width: 720px; }
.pf-rank-table td { white-space: normal; vertical-align: top; }
.pf-rank-table td.pf-why { min-width: 320px; font-size: 13px; line-height: 1.5; color: var(--text-3); }
.pf-rank-table td.pf-why b { color: var(--text-1); }
.pf-rank-num { color: var(--text-4); font-weight: 700; }

/* сводная матрица позиционирования */
.pf-matrix table { min-width: 980px; }
.pf-matrix td { white-space: normal; vertical-align: top; }
.pf-matrix td.pf-subject { font-weight: 700; white-space: normal; min-width: 110px; }
.pf-matrix td.pf-num { white-space: nowrap; font-variant-numeric: tabular-nums; }
.pf-matrix td.pf-list { min-width: 190px; font-size: 12px; line-height: 1.45; }
.pf-matrix td.pf-comment { min-width: 200px; font-size: 12px; line-height: 1.45; color: var(--text-3); }
.pf-matrix ul { margin: 0; padding-left: 16px; }
.pf-matrix ul li { margin-bottom: 3px; }
.pf-matrix ul li:last-child { margin-bottom: 0; }
.pf-matrix ul.pf-plus li::marker { color: var(--ok-500); }
.pf-matrix ul.pf-minus li::marker { color: var(--bad-500); }
.pf-matrix tr.pf-group-first td { border-top: 2px solid var(--line); }
.pf-legend { font-size: 12px; color: var(--text-3); margin-top: 10px; line-height: 1.5; }

/* карточка предмета */
.pf-group { border-left: 4px solid var(--ac-600); }
.pf-group-error { border-left-color: var(--bad-500); }
.pf-group-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.pf-group-title { font-size: 18px; font-weight: 700; line-height: 1.25; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pf-group-title .niche-kind { font-size: 11px; }
.pf-group-sub { font-size: 12px; color: var(--text-3); margin-top: 4px; }
.pf-group-sub b { color: var(--text-1); }
.pf-group-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pf-error { padding: 10px 14px; background: var(--bad-50); border: 1px solid var(--bad-100); border-radius: 10px; color: var(--bad-ink); font-size: 13px; margin: 8px 0 12px; }
.pf-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 8px; margin: 10px 0 14px; }
.pf-kpi { background: var(--bg); border: 1px solid var(--line); border-radius: 9px; padding: 8px 10px; min-width: 0; }
.pf-kpi-l { font-size: 11px; color: var(--text-3); line-height: 1.3; }
.pf-kpi-v { font-size: 15px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; line-height: 1.2; }
.pf-kpi-s { font-size: 11px; color: var(--text-4); margin-top: 2px; }
.pf-h { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--text-2); margin: 14px 0 8px; }
.pf-h:first-child { margin-top: 0; }

/* сравнительная таблица: липкий первый столбец, наши строки подсвечены, лучшие ячейки зелёные */
.pf-cmp table { min-width: 860px; border-collapse: separate; border-spacing: 0; }
.pf-cmp th, .pf-cmp td { border-bottom: 1px solid var(--line); }
.pf-cmp th { white-space: normal; line-height: 1.3; vertical-align: bottom; min-width: 84px; }
.pf-cmp th small { display: block; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--text-4); font-size: 10px; margin-top: 2px; }
.pf-cmp td { padding: 8px 10px; font-size: 13px; vertical-align: middle; white-space: nowrap; }
.pf-cmp th:first-child, .pf-cmp td:first-child { position: sticky; left: 0; z-index: 2; background: var(--surface); min-width: 220px; max-width: 320px; white-space: normal; box-shadow: 1px 0 0 var(--line); }
.pf-cmp th:first-child { z-index: 3; }
.pf-cmp td.pf-val { text-align: center; }
.pf-cmp td.pf-num { text-align: right; font-variant-numeric: tabular-nums; }
.pf-cmp tr.pf-our td { background: var(--ac-50); }
.pf-cmp tr.pf-our td:first-child { background: var(--ac-50); font-weight: 600; }
.pf-cmp tr.pf-our:hover td { background: var(--ac-50); }
.pf-cmp tr td.pf-best, .pf-cmp tr.pf-our td.pf-best, .pf-cmp tr:hover td.pf-best { background: var(--ok-50); color: var(--ok-500); font-weight: 700; }
.pf-cmp tr.pf-our-last td { border-bottom: 2px solid var(--ac-100); }
.pf-cmp td.pf-yes { color: var(--ok-500); font-weight: 600; }
.pf-cmp td.pf-no { color: var(--text-4); }
.pf-cmp .pf-item { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pf-cmp .pf-item-name { font-weight: 600; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pf-cmp .pf-item-sub { font-size: 11px; color: var(--text-3); line-height: 1.3; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.pf-src { display: inline-block; font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 6px; white-space: nowrap; background: var(--bg); color: var(--text-3); border: 1px solid var(--line); }
.pf-src-top { color: var(--ac-700); background: var(--ac-50); border-color: var(--ac-100); }
.pf-src-band { color: var(--warn-ink); background: var(--warn-50); border-color: var(--warn-100); }
.pf-src-live { color: var(--ok-ink); background: var(--ok-50); border-color: var(--ok-100); }
.pf-cmp td.pf-feats { white-space: normal; min-width: 320px; max-width: 520px; line-height: 1.6; }
.pf-cmp td.pf-feats .tag { font-size: 11px; padding: 2px 7px; margin: 0 3px 3px 0; display: inline-block; }
.pf-cmp-note { font-size: 12px; color: var(--text-3); margin-top: 8px; line-height: 1.5; }

/* выводы по нашим SKU */
.pf-skus { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.pf-sku { background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; min-width: 0; }
.pf-sku-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.pf-sku-name { font-size: 13px; font-weight: 700; }
.pf-sku-list { margin: 0; padding-left: 18px; font-size: 12px; line-height: 1.5; }
.pf-sku-list li { margin-bottom: 4px; }
.pf-sku-list.pf-plus li::marker { color: var(--ok-500); }
.pf-sku-list.pf-minus li::marker { color: var(--bad-500); }
.pf-sku-l { font-size: 11px; line-height: 16px; font-weight: 600; margin: 8px 0 4px; }
.pf-sku-l.pf-plus { color: var(--ok-500); }
.pf-sku-l.pf-minus { color: var(--bad-500); }
.pf-sku-comment { font-size: 13px; line-height: 1.5; color: var(--text-1); margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line); }
.pf-summary { margin-top: 12px; padding: 12px 14px; background: var(--ac-50); border: 1px solid var(--ac-100); border-radius: 10px; font-size: 13px; line-height: 1.6; color: var(--text-1); }
.pf-summary b { color: var(--ac-700); }
.pf-mini-verdict { display: flex; gap: 12px; align-items: flex-start; margin-top: 12px; padding: 12px 14px; background: var(--bg); border: 1px solid var(--line); border-radius: 10px; }
.pf-mini-verdict .niche-score { width: 60px; height: 60px; border-radius: 12px; }
.pf-mini-verdict .niche-score-num { font-size: 24px; }
.pf-mini-verdict-text { font-size: 13px; line-height: 1.55; min-width: 0; }
.pf-mini-verdict-text b { display: block; font-size: 13px; margin-bottom: 4px; }

/* низ: не отнесённые, пропущенные */
.pf-unassigned-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; padding: 6px 0; border-bottom: 1px dashed var(--line); }
.pf-unassigned-row:last-child { border-bottom: none; }
.pf-unassigned-row .btn { margin-left: auto; }
.pf-meta { font-size: 12px; color: var(--text-4); margin-top: 6px; line-height: 1.5; }

@media (max-width: 720px) {
  .pf-group-head { flex-direction: column; }
  .pf-verdict-cols, .pf-skus { grid-template-columns: 1fr; }
  .pf-cmp th:first-child, .pf-cmp td:first-child { min-width: 160px; }
}
/* печать из браузера: таблицы без принудительной ширины и липких колонок (см. общий @media print выше) */
@media print {
  .pf-cmp table, .pf-matrix table, .pf-rank-table table { min-width: 0; }
  .pf-cmp th:first-child, .pf-cmp td:first-child { position: static; box-shadow: none; }
  .pf-group { break-before: page; }
}

/* === «Разбор конкурентов» 2.0 (analyze.js): подложка MPSTATS, SEO-ядро, продажи в таблице карточек, сравнение по ТТХ === */
.an-niche { margin-bottom: 20px; }
.an-niche-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 4px; }
.an-niche-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 2px; }
.an-niche-title .niche-kind { font-size: 10px; }
.an-niche-sub { font-size: 12px; color: var(--text-3); line-height: 1.4; }
.an-niche-kpis { margin: 10px 0 10px; grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1100px) { .an-niche-kpis { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); } }
.an-niche-row { display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; padding: 6px 0; border-top: 1px dashed var(--line); font-size: 13px; line-height: 1.5; }
.an-niche-row-l { flex: 0 0 96px; font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); padding-top: 3px; }
.an-niche-row-v { flex: 1 1 320px; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
.an-niche-row-v.tags { gap: 6px; }
.an-niche-seg { white-space: nowrap; }
.an-niche-seg b { color: var(--ac-700); }
.an-niche-row .tag b { color: var(--ac-700); font-weight: 700; margin-left: 2px; }
.an-market-size { margin-top: 12px; padding: 10px 12px; background: var(--ac-50); border: 1px solid var(--ac-100); border-radius: 10px; }
.an-market-size-text { font-size: 13px; line-height: 1.6; color: var(--text-1); }
.an-market-size-meta { font-size: 11px; color: var(--text-3); margin-top: 6px; line-height: 1.5; }
.an-market-size-text + .an-market-size-meta { padding-top: 6px; border-top: 1px dashed var(--ac-100); }
.an-zones { margin-top: 12px; font-size: 13px; }
.an-zones summary { cursor: pointer; font-weight: 600; color: var(--ac-700); font-size: 12px; }
.an-zone { margin-top: 8px; padding-left: 10px; border-left: 3px solid var(--ac-100); }
.an-zone-text { font-size: 12px; color: var(--text-3); line-height: 1.55; margin-top: 2px; }
.an-seo-core table { min-width: 560px; }
.an-seo-core td { padding: 8px 10px; font-size: 13px; vertical-align: middle; }
.an-tier { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 8px; white-space: nowrap; border: 1px solid var(--line); background: var(--bg); color: var(--text-3); }
/* Селектор составной: базовое правило миграции (.an-tier в конце файла) при равной
   специфичности побеждало бы как более позднее, и уровни спроса красились одинаково */
.an-tier.an-tier-hi { color: var(--ac-700); background: var(--ac-50); border-color: var(--ac-100); }
.an-tier.an-tier-mid { color: var(--warn-ink); background: var(--warn-50); border-color: var(--warn-100); }
.an-tag-minus { color: var(--bad-ink); background: var(--bad-50); border-color: var(--bad-100); text-decoration: line-through; text-decoration-color: rgba(211, 51, 51, 0.45); /* зачёркивание вполсилы: сплошной --bad-500 забивал бы текст минус-слова */ }
.an-patterns { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.55; }
.an-patterns li { margin-bottom: 4px; }
td.an-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.an-th-sub { display: block; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--text-4); font-size: 10px; }
.an-ad { color: var(--warn-ink); font-weight: 700; }
.an-compare .pf-cmp { margin-top: 4px; }
@media (max-width: 720px) {
  .an-niche-row-l { flex-basis: 100%; padding-top: 0; }
  .an-niche-seg { white-space: normal; }
}

/* ============ Мобильный проход (только ≤900 / ≤720 px; десктоп не трогаем) ============
   1) Страница не уезжает вбок: страховка overflow-x на html/body, контейнер не шире экрана,
      картинки/канвасы не шире контейнера, сетки из одной колонки — minmax(0,1fr), чтобы
      широкая таблица внутри карточки не растягивала колонку (карточка «Рынок» в разборе
      конкурентов была 610px из-за .table-scroll table{min-width:560px}).
   2) Широкие таблицы листаются внутри .table-scroll / .sku-table-wrap: тонкая полоса
      прокрутки + затенение у края, за которым есть ещё содержимое (data-scroll ставит
      app.js → wireScrollHints; без JS — просто прокрутка), первая колонка липкая.
   3) Шапка экрана: заголовок + бургер в одну строку, действия — одна прокручиваемая строка,
      первичная кнопка первой; подпись #anMeta дашборда — мелкая строка над кнопками.
   4) «Пользователи»: таблицы команды и сессий складываются в карточки (data-label у td). */
@media (max-width: 900px) {
  html { overflow-x: hidden; }
  body { overflow-x: clip; }
  .container { max-width: 100%; }
  .tab-content img, .tab-content canvas, .sku-drawer img { max-width: 100%; }
  .grid, .adv-grid, .niche-grid, .src-grid { grid-template-columns: minmax(0, 1fr); }
  .grid > *, .an-stats > *, .an-products > *, .src-grid > * { min-width: 0; }
  .an-stats { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)) !important; } /* inline repeat(3,1fr) у #anBudgetStats */
  .an-products { grid-template-columns: minmax(0, 1fr); }
  /* Записи списков (история, оптимизация рекламы) — заголовок не шире карточки */
  .history-main { width: 100%; max-width: 100%; }
  .history-category, .history-date { overflow-wrap: anywhere; }

  /* --- Горизонтальная прокрутка внутри блока: тонкая полоса + затенение края (data-scroll от JS) --- */
  .table-scroll, .sku-table-wrap.card, .topbar .page-actions, .topbar .an-head-actions, .an-subnav {
    scrollbar-width: thin;
    scrollbar-color: var(--line-2) transparent;
  }
  .table-scroll::-webkit-scrollbar, .sku-table-wrap.card::-webkit-scrollbar,
  .topbar .page-actions::-webkit-scrollbar, .topbar .an-head-actions::-webkit-scrollbar, .an-subnav::-webkit-scrollbar { height: 5px; }
  .table-scroll::-webkit-scrollbar-thumb, .sku-table-wrap.card::-webkit-scrollbar-thumb,
  .topbar .page-actions::-webkit-scrollbar-thumb, .topbar .an-head-actions::-webkit-scrollbar-thumb, .an-subnav::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 3px; }
  /* затенение справа — пока справа есть ещё содержимое; слева — когда прокрутили от начала */
  [data-scroll="start"], [data-scroll="mid"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), rgba(0, 0, 0, 0.15)); /* маска-градиент: цвет тут — только альфа-канал затухания */
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), rgba(0, 0, 0, 0.15)); /* тот же градиент без префикса */
  }
  .table-scroll[data-scroll="start"], .table-scroll[data-scroll="mid"], .sku-table-wrap[data-scroll="start"], .sku-table-wrap[data-scroll="mid"] {
    background:
      linear-gradient(to left, rgba(28, 32, 48, 0.09), rgba(28, 32, 48, 0)) right center / 18px 100% no-repeat; /* альфа-градиент затенения края прокрутки: в непрозрачный токен не переводится */
  }
  .table-scroll[data-scroll="mid"], .table-scroll[data-scroll="end"], .sku-table-wrap[data-scroll="mid"], .sku-table-wrap[data-scroll="end"] {
    box-shadow: inset 12px 0 10px -10px rgba(28, 32, 48, 0.12); /* внутреннее затенение прокрученного края — не тень слоя, ступени --sh не годятся */
  }
  .sku-table-wrap.card[data-scroll="mid"], .sku-table-wrap.card[data-scroll="end"] { box-shadow: var(--sh-1), inset 12px 0 10px -10px rgba(28, 32, 48, 0.12); /* то же затенение края плюс штатная тень карточки */ }
  /* Липкая первая колонка (идентификатор строки): фон карточки, тонкая линия-разделитель справа */
  .table-scroll th:first-child, .table-scroll td:first-child:not([colspan]) {
    position: sticky; left: 0; z-index: 1;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--line);
  }
  .table-scroll thead th:first-child { z-index: 2; }
  /* Итоговая строка: липкая первая ячейка наследует фон итога, а не карточки — иначе
     «Итого» белое, остальные ячейки серые, строка выглядит разорванной (22.09.2026) */
  .table-scroll .src-bill-table tr.total td:first-child,
  .table-scroll .pf-cmp tr.pf-our-last td:first-child { background: var(--surface-3); }
  .sku-table th:first-child, .sku-table td:first-child,
  .sku-table th:nth-child(2), .sku-table td:nth-child(2) { position: sticky; left: 0; z-index: 1; background: var(--surface); }
  .sku-table th:nth-child(2), .sku-table td:nth-child(2) { left: 44px; box-shadow: 1px 0 0 var(--line); }
  .sku-table thead th:first-child, .sku-table thead th:nth-child(2) { z-index: 3; }
  .sku-table tr.sku-row:hover td:first-child, .sku-table tr.sku-row:hover td:nth-child(2) { background: var(--bg); }
  /* Сравнение (оценка ниши/разбор): первая колонка уже липкая своими стилями — не даём ей съесть экран */
  .pf-cmp th:first-child, .pf-cmp td:first-child { max-width: 46vw; }
  .niche-table .niche-item-name { max-width: 180px; }

  /* --- Чипы разделов дашборда: одна строка с прокруткой вместо двух рядов --- */
  .an-subnav { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; padding: 10px 2px 8px; margin: 0 -10px 12px; padding-left: 10px; padding-right: 10px; scroll-padding: 0 10px; }
  .an-subnav a { flex: 0 0 auto; padding: 6px 13px; }
}

@media (max-width: 720px) {
  .container { padding: 12px 10px 32px; }
  .card { padding: 16px 14px; margin-bottom: 14px; }
  .card-title { margin-bottom: 12px; }
  h3 { font-size: 18px; }
  .page-head h2 { font-size: 18px; }

  /* --- Шапка экрана: заголовок + бургер в одну строку, действия — одна прокручиваемая строка --- */
  .topbar { padding: 8px 12px; gap: 6px 10px; min-height: 0; }
  .topbar-title { font-size: 18px; flex: 1 1 0; min-width: 0; margin-right: 0; overflow: hidden; text-overflow: ellipsis; }
  .topbar-actions { flex: 1 1 100%; min-width: 0; justify-content: flex-start; }
  .topbar .page-head { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 6px; width: 100%; min-width: 0; margin: 0; }
  .topbar .page-head > span { font-size: 12px; line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; max-width: 100%; text-align: left; }
  .topbar .page-actions, .topbar .an-head-actions {
    display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-start; gap: 8px;
    width: 100%; min-width: 0; overflow-x: auto; overflow-y: hidden;
    padding: 2px 0 4px; margin: -2px 0 -4px;
    scroll-padding-inline: 8px 32px; /* фокус/scrollIntoView выводит кнопку из-под 28px затухания края */
  }
  .topbar .page-actions > *, .topbar .an-head-actions > * { flex: 0 0 auto; }
  .topbar .page-head .btn { padding: 7px 12px; font-size: 13px; }
  .topbar .page-head .btn-primary { order: -1; }
  /* Дашборд: сегмент периода — первым (в DOM он раньше «Обновить», при равном order идёт
     первым): «7 дн … всё» и «Обновить» помещаются в 400px целиком, а под затухание края
     попадает начало следующей кнопки — подсказка «дальше есть ещё». Раньше под маску
     ложилась активная кнопка «всё», и она выглядела обрезанной (22.09.2026). */
  .topbar .an-head-actions #anDaysSeg { order: -1; }
  .topbar select { padding: 6px 28px 6px 10px; font-size: 13px; max-width: 160px; }
  /* Подпись дашборда «дней … последний …» — мелкая строка над кнопками: позиционируется от
     .page-head (не листается вместе с рядом), место под неё — padding-top ряда (внутри его
     рамки, иначе mask-image ряда её спрячет) */
  /* display:block возвращает подпись: блок ≤1600 прячет её, а место под неё (padding-top
     ряда) оставалось пустой полосой 20px над кнопками (22.09.2026) */
  .topbar #anMeta { display: block; position: absolute; top: 2px; left: 0; right: 0; flex: none; font-size: 11px; line-height: 16px; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .topbar .an-head-actions { padding-top: 20px; margin-top: 0; }
  .an-section { scroll-margin-top: 54px; }

  /* --- KPI-плитки и сетки компактнее --- */
  .an-stats { gap: 8px; }
  .an-stat { padding: 10px 12px; }
  .an-stat-value { font-size: 18px; }
  /* KPI-карточки в две колонки на 400px — ~171px на плитку: восьмизначная «13 305 491 ₽»
     в 24px вылезала за рамку, а бейдж дельты «▼ -1 090 479 · -28%» рвался на две строки
     (22.09.2026). Кегль — как у .an-stat-value, отступы плитки уже. */
  .kpi-card { padding: 12px 14px 12px; }
  .kpi-card .kpi-value { font-size: 18px; }
  .kpi-foot .st-badge { font-size: 11px; padding: 2px 8px; }
  /* Плитки «Продвижения»/«Продаж» на телефоне — всегда две в ряд (auto-fit с минимумом
     180px дал бы одну колонку в карточке шириной 350px) */
  .promo-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sku-tiles { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
  .an-niche-kpis { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
  .stat-big { font-size: 24px; }
  .sku-toolbar { padding: 12px; gap: 10px; }
  .sku-toolbar select { max-width: 100%; }
  .combo-btn { max-width: 100%; }
  .combo-drop { width: min(300px, 84vw); }
  .sku-summary { gap: 6px; }

  /* --- Модалки и панель товара на всю ширину --- */
  .modal { width: 100%; max-width: calc(100vw - 16px); padding: 20px 16px; border-radius: 14px; max-height: 92vh; }
  .modal-actions { gap: 8px; }
  .sku-drawer { width: 100vw; border-left: none; }
  .sku-drawer-head { padding: 12px 14px; }
  .sku-drawer-body { padding: 14px 14px 32px; }
  .sku-panel-photos { grid-template-columns: repeat(4, 1fr); }
  .sku-panel-photo.main { grid-column: span 2; grid-row: span 2; }

  /* --- «Пользователи»: команда и активные сессии — карточками вместо таблиц (десктоп — таблицы) --- */
  #usersList .table-scroll, #sessionsList .table-scroll { overflow: visible; -webkit-mask-image: none; mask-image: none; background: none; box-shadow: none; }
  #usersList table, #sessionsList table { display: block; min-width: 0; width: 100%; }
  #usersList thead, #sessionsList thead { display: none; }
  #usersList tbody, #sessionsList tbody { display: block; }
  #usersList tr, #sessionsList tr { display: block; border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px 12px; margin-bottom: 10px; background: var(--surface); }
  #usersList tr:last-child, #sessionsList tr:last-child { margin-bottom: 0; }
  #sessionsList tr.sess-current { background: var(--ac-50); border-color: var(--ac-100); }
  #usersList td, #sessionsList td {
    display: flex; align-items: center; gap: 10px;
    /* height:auto: контракт плотности ниже по файлу даёт td height:var(--row-h) — для
       table-cell это минимум, а для flex/block-ячейки карточки стало жёсткой высотой,
       и второй ряд кнопок вылезал из карточки на соседнюю (22.09.2026) */
    height: auto; padding: 4px 0; border-bottom: none; font-size: 13px; white-space: normal;
    position: static; box-shadow: none; background: transparent;
  }
  #usersList tr:hover td, #sessionsList tr:hover td, #sessionsList tr.sess-current td { background: transparent; }
  #usersList td[data-label]::before, #sessionsList td[data-label]::before {
    content: attr(data-label); flex: 0 0 88px;
    font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3);
  }
  #usersList td.u-name, #sessionsList td.u-name { display: block; font-size: 15px; padding: 0 0 6px; }
  #usersList td.u-name .history-badge, #sessionsList td.u-name .history-badge { vertical-align: middle; }
  #sessionsList td.u-name .sess-login { display: inline; margin-left: 6px; }
  #usersList td.u-actions, #sessionsList td.u-actions { display: block; padding-top: 8px; }
  #usersList td.u-actions > div, #sessionsList td.u-actions > div { justify-content: flex-start !important; flex-wrap: wrap; }
  /* Бейдж роли и список — в одну строку: с базисом 140px у списка Chrome переносил его,
     и бейдж «прилипал» к строке логина, а подпись «Роль» висела между ними (22.09.2026).
     Последние два правила — страховка на очень узких экранах: если перенос всё же
     случится, подпись остаётся наверху рядом с бейджем. */
  #usersList td.u-role > div { flex: 1 1 auto; min-width: 0; flex-wrap: wrap; }
  #usersList td.u-role .user-role-select { flex: 1 1 auto; min-width: 0; }
  #usersList td.u-role { align-items: flex-start; }
  #usersList td.u-role::before { padding-top: 7px; }
}

/* === Телефон: полоса разделов дашборда — самой первой и липнет к верху экрана (18.08.2026) ===
   Владелец: «полоса с разделами не на самом верху». На телефоне шапка не липкая (static), поэтому
   липнуть надо к 0, а не под --topbar-h (общее правило .an-subnav ниже по файлу перебивало top:0
   из блока ≤900). И сама полоса на телефоне идёт ПЕРВОЙ — до контроля качества и итога за период,
   которые на узком экране занимают полтора экрана текста. */
@media (max-width: 900px) {
  #tab-analytics.active { display: flex; flex-direction: column; }
  #tab-analytics > * { min-width: 0; }
  #tab-analytics > .page-head { order: -2; }
  #anSubnav { order: -1; top: 0; margin-top: 0; }
  .an-subnav { top: 0; }
  .an-section { scroll-margin-top: 58px; }
}

/* === Широкие экраны (2K/4K) === */
/* На 2560 px контент был зажат в 1280 px посередине, шрифт 13–14 px — «ужато». Даём контенту
   больше ширины, а на очень широких мониторах слегка увеличиваем весь интерфейс (zoom — как
   Ctrl+«+» в браузере, все пропорции сохраняются). Ноутбуки/FullHD (≤1799) не затронуты. */
@media (min-width: 1800px) {
  .container { max-width: 1600px; }
}
@media (min-width: 2200px) {
  html { zoom: 1.15; }
  :root { --ui-zoom: 1.15; }
  .container { max-width: 1720px; }
}
@media (min-width: 3000px) {
  html { zoom: 1.5; }
  :root { --ui-zoom: 1.5; }
}


/* ============ Раздел «Продвижение» (frontend/js/promotion.js) ============
   Кампании со ставками, графики расхода/заказов и таблица поисковых фраз. */
/* Модули раздела (19.09.2026, модульная перестройка): «ИИ в рекламе» / «Кабинет
   в целом» / «Фразы». Заголовок модуля + серая подпись «что это и откуда данные»
   (как в референсе дизайнера), отделение друг от друга — воздухом и шапкой. */
.promo-mod { margin-bottom: 28px; }
.promo-mod-head { margin: 4px 2px 12px; }
.promo-mod-title { font-size: 15px; font-weight: 700; color: var(--text-1); margin: 0 0 3px; }
.promo-mod-sub { font-size: 12px; font-weight: 400; color: var(--text-3); line-height: 1.45; max-width: 900px; }
/* Модуль «ИИ в рекламе»: карточки кампаний агента */
/* Список кампаний под ИИ — свёрнутой таблицей внизу модуля (22.09.2026, раньше — карточки сверху) */
.promo-ai-list { margin-top: 16px; }
.promo-ai-list > summary { cursor: pointer; font-weight: 600; font-size: 15px; color: var(--text-1); padding: 8px 0; }
.promo-ai-list > summary:focus-visible { outline: 2px solid var(--ac-500, currentColor); outline-offset: 2px; border-radius: 4px; }
.promo-ai-list .btn { margin-top: 10px; }
.promo-ai-last { font-size: 12px; color: var(--text-2); }
/* «Итоги ИИ» (22.09.2026) — таблица до/после и правила подсчёта */
.itogi-table td { vertical-align: top; }
.itogi-table td .st-badge { margin-top: 3px; }
/* min-width — единственное, что табличная раскладка Chrome честно учитывает (max-width на td
   она игнорирует): без него колонка «Что сделал ИИ» ужималась до ~95px и числа отрывались
   от подписей; пара «подпись число» — неразрывный span (22.09.2026) */
.itogi-done { font-size: 12px; color: var(--text-2); min-width: 150px; max-width: 170px; }
.itogi-act { white-space: nowrap; }
.itogi-turnover { white-space: nowrap; }
/* подписи под числами (контроль, пропущенные дни) переносятся: иначе 9 колонок не влезают в 1440 */
.itogi-table td .t-micro { white-space: normal; }
.itogi-table td.c-num .t-micro { max-width: 150px; margin-left: auto; }
.itogi-how ul { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 6px; font-size: 13px; color: var(--text-2); line-height: 1.45; }
/* 180, а не 150: при 150 на 1440 выходило 7 плиток по ~152px, и «2 670 180 ₽» (≈143px в 24px)
   не влезало во внутренние 115px — «₽» уезжал на вторую строку (22.09.2026); при 180 — пять в ряд */
.promo-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; margin-bottom: 12px; }
.promo-tile { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.promo-tile-v { font-size: 18px; font-weight: 700; color: var(--ac-700); }
.promo-tile-l { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.promo-tile.danger { border-color: var(--bad-500); }
.promo-tile.danger .promo-tile-v { color: var(--bad-ink); }
.promo-yesterday { background: var(--ac-50); border-radius: 10px; padding: 10px 14px; margin-bottom: 10px; font-size: 13px; color: var(--ac-700); }
.promo-yesterday .sku-na { font-size: 12px; }
.promo-name { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.promo-name b, .promo-name span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.promo-note-top { margin-bottom: 6px; }
.promo-note { font-size: 12px; color: var(--text-3); margin: 8px 0 12px; }
.chart-wrap { position: relative; height: 260px; min-width: 0; }
/* Графики раздела «Продвижение»: своя сетка, чтобы на широком мониторе они вставали
   по три в ряд, а на ноутбуке — по одному, без ручных брейкпоинтов. */
.promo-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); gap: 16px; margin-bottom: 16px; }
.promo-charts > .card { min-width: 0; margin-bottom: 0; }
.promo-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.promo-sortable { cursor: pointer; user-select: none; }
.promo-sortable:hover { color: var(--ac-700); }
.promo-table th { text-align: left; font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); padding: 7px 6px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.promo-table th.n, .promo-table td.n { text-align: right; white-space: nowrap; }
.promo-table td { padding: 7px 6px; border-bottom: 1px solid var(--line); vertical-align: top; }
.promo-table td.b { font-weight: 700; }
.promo-table tr.promo-off td { opacity: 0.55; }
.promo-table .nm { display: block; color: var(--text-4); font-size: 11px; font-weight: 400; margin-top: 1px; }
/* Поле лимита дня в «Кампаниях»: 104 − 2 (рамка) − 16 (отступы) − 15 (спиннер) = 71px под
   текст — плейсхолдер «не задан» (~58px) целиком; с глобальными отступами 14px при
   96px он резался до «не зада» (22.09.2026) */
.promo-table input.adc-limit { width: 104px; padding: 6px 8px; text-align: right; }
.promo-table input.adc-date { width: 150px; padding: 6px 8px; }   /* «Под ИИ с» — дата передачи для «Итогов ИИ» */
.promo-bad { color: var(--bad-ink); font-weight: 700; }
.promo-good { color: var(--ok-ink); font-weight: 700; }
/* Редизайн 19.09.2026 (этап B, волна 1): promo-badge переехала на палитру статусов
   нового языка (--st-*) — форма прежняя (пилюля с подписью), цвета — §5. */
.promo-badge { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--st-nodata-bg); color: var(--st-nodata-ink); border: 1px solid var(--st-nodata-line); }
.promo-badge.on { background: var(--st-work-bg); color: var(--st-work-ink); border-color: transparent; }
.promo-badge.bad { background: var(--st-bad-bg); color: var(--st-bad-ink); border-color: transparent; }
.promo-badge.good { background: var(--st-ok-bg); color: var(--st-ok-ink); border-color: transparent; }
.promo-row { cursor: pointer; }
.promo-row:hover { background: var(--bg); }
.promo-row.sel { background: var(--ac-50); }
.promo-search { width: 100%; max-width: 340px; margin: 8px 0 4px; }
.promo-top { color: var(--text-3); font-size: 12px; }
@media (max-width: 900px) {
  .chart-wrap { height: 220px; }
  .promo-table { font-size: 12px; }
}
/* Дневник агента рекламы / опыты со ставкой на телефоне (22.09.2026): таблица была прибита к
   560px общим .table-scroll table, четвёртая колонка («Почему»/«Вердикт», до 160 символов)
   получала ~200px ЗА правым краем экрана и, перенесённая в 6–9 строк, растягивала ряд —
   на экране оставались 2–3 строки текста и пустота. Ряд складываем сеткой: «Когда | Что |
   Было → стало» в первой строке, четвёртая колонка — под ними на всю ширину. Специфичность
   .table-scroll .promo-table.ap-log … нужна, чтобы перебить липкую первую колонку и липкую
   шапку .table-scroll (блок ≤900 и контракт таблиц ниже по файлу). */
@media (max-width: 720px) {
  .table-scroll .promo-table.ap-log { min-width: 0; }
  .table-scroll .promo-table.ap-log tr { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: 8px; align-items: start; }
  .table-scroll .promo-table.ap-log th, .table-scroll .promo-table.ap-log td { position: static; box-shadow: none; background: transparent; border-bottom: none; padding: 7px 0; white-space: normal; }
  .table-scroll .promo-table.ap-log thead tr, .table-scroll .promo-table.ap-log tbody tr { border-bottom: 1px solid var(--line); }
  .table-scroll .promo-table.ap-log th:nth-child(4) { display: none; }
  .table-scroll .promo-table.ap-log td:nth-child(4) { grid-column: 1 / -1; padding-top: 0; font-size: 12px; line-height: 1.4; color: var(--text-3); }
}

/* Автопилот: сводка цикла агента (01.10.2026, «что агент сделал» блоками по типам) и поиск за 7 дн по РК.
   Блок — строка «значок + что», под ней — по РК с числами; РК поиска — раскрывающийся список с таблицей фраз. */
.ap-digest-list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; font-size: 13px; line-height: 1.5; }
.ap-digest-list > li > b { font-weight: 600; color: var(--text-1); }
.ap-digest-items { list-style: none; margin: 2px 0 0; padding: 0 0 0 22px; color: var(--text-2); }
.ap-digest-items .ap-why { color: var(--text-3); }
.ap-digest-rk { border-top: 1px solid var(--line); padding: 8px 0; }
.ap-digest-rk > summary { cursor: pointer; font-size: 13px; line-height: 1.5; color: var(--text-1); }
.ap-digest-rk > summary .nm { display: inline; color: var(--text-3); font-size: 12px; margin-left: 6px; }
.ap-digest-prev > summary { cursor: pointer; font-weight: 600; color: var(--ac-700); font-size: 12px; margin-top: 10px; }
/* 01.10.2026, встречная проверка: записи журнала дня — равными подблоками по времени (цикл, сторож, сверка…), ответ
   «что агент сделал с фразами» — первой строкой поиска обычным жирным текстом, не серой заметкой; у ставки фразы — автор
   и дата, под фразой со ставкой агента — продажи с её дня. Ячейка фразы переносится (бейджи и подстрока не режутся). */
.ap-digest-rec { margin-top: 10px; }
.ap-digest-rec-head { font-size: 13px; line-height: 1.5; font-weight: 600; color: var(--text-1); }
.ap-digest-empty { font-size: 13px; line-height: 1.5; color: var(--text-2); margin-top: 6px; }
.ap-digest-lead { font-size: 13px; line-height: 1.5; font-weight: 600; color: var(--text-1); margin: 4px 0 2px; }
.ap-digest-own { font-size: 13px; line-height: 1.5; color: var(--text-2); margin-bottom: 6px; }
.ap-digest-sub { font-size: 12px; line-height: 1.4; color: var(--text-3); white-space: normal; }
.ap-digest-src { color: var(--text-3); font-size: 12px; }
td.ap-digest-ph { white-space: normal; min-width: 180px; max-width: 360px; color: var(--text-1); }
/* Фразы по деньгам (правило T, 01.10.2026): строки ⭐/🌱/✖/🏷 над таблицей и метка класса у фразы. */
.ap-digest-gold { list-style: none; margin: 4px 0 6px; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; line-height: 1.5; color: var(--text-1); }
.ap-digest-gold-mark { margin-right: 4px; }

/* Продвижение: предупреждение над таблицей товаров (запас кончается) и жёлтый бейдж запаса */
.promo-note.bad-note { color: var(--warn-ink); background: var(--warn-50); border: 1px solid var(--warn-100); border-radius: 8px; padding: 8px 10px; }
.promo-badge.warn { background: var(--st-warn-bg); color: var(--st-warn-ink); border-color: transparent; }

/* Переключатель площадок (Мои товары): «чей это список». Выглядит как вкладки, а не как
   ещё один фильтр-чип, — потому что это не сужение выборки, а смена витрины. */
.mp-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; }
.mp-tab { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--surface); color: var(--text-3); font-size: 13px; cursor: pointer; }
.mp-tab:hover { color: var(--text-1); border-color: var(--ac-100, var(--line)); }
.mp-tab.active { background: var(--ac-50); color: var(--ac-700); border-color: transparent; font-weight: 600; }
.mp-tab .mp-n { font-variant-numeric: tabular-nums; opacity: .7; font-size: 12px; }
.mp-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

/* Разбор документа до запуска оценки ниши (niche.js: _nichePreflight).
   Смысл блока — снять вопрос «ставить портфель или нет»: человек видит, на сколько
   предметов раскладывается его файл, и выбирает кнопкой, а не догадкой. */
.pf-pre { border: 1px solid var(--line); border-radius: 10px; background: var(--bg); padding: 12px 14px; margin: 10px 0 12px; }
.pf-pre-loading, .pf-pre-err { font-size: 13px; color: var(--text-3); }
.pf-pre-err { color: var(--bad-ink); }
.pf-pre-head { font-size: 13px; margin-bottom: 8px; }
.pf-pre-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.pf-pre-row { display: grid; grid-template-columns: 44px minmax(140px, 1fr) 2fr; gap: 10px; align-items: baseline; font-size: 13px; padding: 3px 0; border-bottom: 1px solid var(--line); }
.pf-pre-row:last-child { border-bottom: none; }
.pf-pre-n { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.pf-pre-name { font-weight: 600; }
.pf-pre-kind { font-weight: 400; color: var(--text-3); font-size: 11px; margin-left: 6px; }
.pf-pre-ex { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-pre-warn .pf-pre-n, .pf-pre-warn .pf-pre-name { color: var(--warn-ink); }
.pf-pre-advice { font-size: 13px; color: var(--text-1); margin-bottom: 10px; }
.pf-pre-choice { display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 720px) { .pf-pre-row { grid-template-columns: 36px 1fr; } .pf-pre-ex { display: none; } }

/* Остаток квоты MPSTATS в строке статуса «Оценки ниши»: единственное число там, которое
   ограничивает работу — узнавать об его исчерпании из ошибки посреди расчёта нельзя. */
.niche-quota { font-weight: 600; }
.niche-quota.low { color: var(--warn-ink); }

/* === Раскладка дашборда в две колонки на широких экранах (24.08.2026) ===
   Замер до правки: 17 карточек в ОДНУ колонку — 24,6 экрана прокрутки, а на 2К одна
   карточка растягивалась на 1914 px, то есть строка длиной в два метра. Ширина контейнера
   при этом была ограничена правильно (1280 → 1600 → 1720) — не хватало именно колонок.
   Широкое содержимое (таблицы по дням, комбо-графики) остаётся на всю ширину: класс
   .an-wide ставится там, где две колонки сделали бы только хуже. */
@media (min-width: 1500px) {
  .an-section .card { break-inside: avoid; }
  .an-section-cols { column-count: 2; column-gap: 20px; }
  .an-section-cols > .card { display: inline-block; width: 100%; margin-bottom: 20px; }
  /* column-span действует только на блочные боксы: inline-block из правила выше
     молча его игнорирует — карточка оставалась в полколонки (поймано замером 25.08) */
  .an-section-cols > .card.an-wide { display: block; column-span: all; }
  /* Заголовок секции — во всю ширину, НАД колонками: иначе он ложится в первую
     колонку и правая стартует на 36px выше левой — рваная верхняя кромка
     (замечание владельца 28.08 «съехало»; замер: y=262 против y=298). */
  .an-section-cols > .an-sec-head { column-span: all; }
}

/* ── Переключатель темы в шапке ──────────────────────────────────────────
   Три состояния: светлая / как в системе / тёмная. Нужен именно выбор:
   тёмная тема появилась 24.08.2026 и включилась у всех, у кого система
   тёмная, — а часть людей привыкла читать чёрным по белому независимо от
   настроек системы. Выбор хранится в localStorage и применяется до первой
   отрисовки (скрипт в <head>), поэтому страница не моргает. */
.theme-sw { display: inline-flex; gap: 2px; padding: 2px; margin-left: 8px; flex: none;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-ctl); }
.theme-sw button { display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 26px; padding: 0; border: 0; border-radius: 6px;
  background: none; color: var(--text-3); cursor: pointer; }
.theme-sw button:hover { color: var(--text-1); background: var(--tint-hover); }
.theme-sw button[aria-pressed="true"] { background: var(--surface); color: var(--ac-700);
  box-shadow: var(--sh-1); }
.theme-sw svg { width: 15px; height: 15px; }
.theme-sw button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── Волна при смене темы ────────────────────────────────────────────────
   Стандартный переход вида — это растворение старого кадра в новый; нам нужен
   круг, растущий из кнопки. Поэтому оба кадра держим неподвижными (анимацию
   задаёт JS через clip-path на новом), а новый кладём поверх старого. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) { z-index: 2; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ПЛАШКИ: восемь родов, одна геометрия                     введено 24.08.2026
   ───────────────────────────────────────────────────────────────────────────
   Разных плашек в кабинете было 26, и это не помогало: ни одна не значила
   ничего конкретного. Триада «хорошо / внимание / плохо» была реализована
   одиннадцать раз независимо, с радиусами 20, 8, 16, 8, 7, 12, 999, 6, 999,
   999 и 6 пикселей. Здесь восемь ПРАВИЛ, дающих 27 внешне различимых плашек.

   Род выбирается по вопросу, на который плашка отвечает:
     .st   — «в каком состоянии объект сейчас»   ровно одна на объект
     .dg   — «что именно не так или хорошо»       может быть несколько
     .mp   — «чья это площадка»                   оценки не несёт никогда
     .src  — «откуда взято число»                 правило честности
     .per  — «за какой период посчитано»
     .role — «к какому классу относится»          без оценки
     .dl   — «насколько изменилось к базе»
     .cnt  — «сколько штук»

   ГЛАВНОЕ ПРАВИЛО СТРОКИ: одна сплошная заливка на строку. Состояние — solid,
   всё остальное в строке — контур или вовсе без фона. Иначе таблица на 466
   строк превращается в светофор и перестаёт читаться.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Геометрия: три размера, общие для всех восьми родов ── */
.st, .dg, .mp, .per, .role, .dl, .cnt {
  display: inline-flex; align-items: center; gap: var(--sp-4);
  height: 20px; padding: 0 var(--sp-6);
  font-size: 12px; line-height: 16px; font-weight: 400;
  white-space: nowrap; vertical-align: middle; box-sizing: border-box;
}
/* Внутри ячейки таблицы: не растягивает строку 36px */
.pl--nano { height: 16px; padding: 0 var(--sp-4); font-size: 10px; line-height: 14px; font-weight: 700; }
/* Шапка экрана, единственная плашка блока, вердикт */
.pl--md   { height: 24px; padding: 0 var(--sp-8); font-size: 12px; line-height: 16px; font-weight: 600; }
/* Место под плашку, которой нет: колонка не схлопывается, строка не прыгает */
.pl--missing { background: none !important; border-color: transparent !important; color: transparent !important; padding-left: 20px; }

/* ── 1. .st — состояние объекта. Сплошная заливка, читается с трёх метров ── */
.st { border-radius: var(--r-pill); min-width: 72px; justify-content: center;
      background: var(--neu-fill); color: var(--neu-on); font-weight: 600; }
.st--ok      { background: var(--ok-fill);   color: var(--ok-on); }
.st--warn    { background: var(--warn-fill); color: var(--warn-on); }
.st--bad     { background: var(--bad-fill);  color: var(--bad-on); }
.st--neutral { background: var(--neu-fill);  color: var(--neu-on); }
/* «Ждём»: точка пульсирует — иначе «в работе» и «готово» неразличимы взглядом */
.st--wait::before { content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; animation: st-wait 1.6s ease-in-out infinite; }
@keyframes st-wait { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
/* «Выключено»: пунктир — состояние есть, но объект вне игры */
.st--off { background: none; border: 1px dashed var(--line-dash); color: var(--text-3); font-weight: 400; }

/* ── 2. .dg — диагноз: вывод, а не состояние. Рейка слева вместо рамки ── */
.dg { border-radius: var(--r-chip); height: auto; min-height: 20px; padding: 2px var(--sp-8) 2px 11px;
      background: var(--neu-50); color: var(--text-2); box-shadow: inset 3px 0 0 var(--neu-500); white-space: normal; }
.dg--ok   { background: var(--ok-50);   color: var(--ok-ink);   box-shadow: inset 3px 0 0 var(--ok-500); }
.dg--warn { background: var(--warn-50); color: var(--warn-ink); box-shadow: inset 3px 0 0 var(--warn-500); }
.dg--bad  { background: var(--bad-50);  color: var(--bad-ink);  box-shadow: inset 3px 0 0 var(--bad-500); }

/* ── 3. .mp — принадлежность площадке. Цвет площадки живёт ТОЛЬКО в точке,
      рейке и линии графика: заливкой он спорил бы с семантикой ── */
.mp { border-radius: var(--r-chip); background: var(--surface-2); border: 1px solid var(--line); color: var(--text-2); }
.mp::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--mp, var(--n-400)); box-shadow: var(--mp-ring); }
.mp--wb { --mp: var(--mp-wb); }
.mp--ozon { --mp: var(--mp-ozon); }
.mp--ym { --mp: var(--mp-ym); }
.mp-rail { box-shadow: inset 3px 0 0 var(--mp, var(--n-400)); }
.mp-dot.mp--wb, .mp-dot.mp--ozon, .mp-dot.mp--ym { background: var(--mp); box-shadow: var(--mp-ring); }

/* ── 4. .src — откуда взято число. Без фона и рамки: это подпись, не метка.
      Заменяет 223 подсказки в title=, которых нет ни на проекторе, ни в шеринге ── */
/* display/gap — как у остальных родов (.st, .dg, …): без них глиф ::before прилипал к тексту
   («Σсрез», «◦API Wildberries» читались как опечатка), а точка .src--stale::after без
   flex-родителя вовсе не получала бокса (22.09.2026) */
.src { display: inline-flex; align-items: center; gap: var(--sp-4); vertical-align: middle; padding: 0; height: 16px; font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); cursor: pointer; background: none; border: none; }
.src--api::before    { content: "\25E6"; }
.src--file::before   { content: "\25A4"; }
.src--calc::before   { content: "\2211"; }
.src--manual::before { content: "\270E"; }
.src--stale::after   { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--warn-500); }
.src:hover { color: var(--text-2); }

/* ── 5. .per — за какой период. Формат строго один: «7 дн · 18–24.08» ── */
.per { border-radius: var(--r-chip); height: 16px; border: 1px solid var(--line-2); background: none;
       font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* ── 6. .role — классификация без оценки. Как только роль получает зелёный
      или красный, она перестаёт быть ролью и становится диагнозом ── */
.role { border-radius: var(--r-pill); border: 1px solid var(--line-2); background: none;
        font-size: 11px; line-height: 16px; font-weight: 700; color: var(--text-2); }
.role.has-dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--dot, var(--n-400)); }
.role--key { border-color: var(--ac-300); color: var(--ac-700); }

/* ── 7. .dl — изменение к базе. Полярность задаёт МЕТРИКА, а не знак:
      выросший ДРР — это плохо, выросшая выручка — хорошо ── */
.dl { border-radius: var(--r-xs); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.dl--up   { background: var(--ok-50);  color: var(--ok-ink); }
.dl--down { background: var(--bad-50); color: var(--bad-ink); }
.dl--flat { background: var(--surface-2); color: var(--text-3); }
.dl--up::before   { content: "\25B2"; font-size: 8px; }
.dl--down::before { content: "\25BC"; font-size: 8px; }
.dl[data-polarity="inverse"].dl--up   { background: var(--bad-50); color: var(--bad-ink); }
.dl[data-polarity="inverse"].dl--down { background: var(--ok-50);  color: var(--ok-ink); }

/* ── 8. .cnt — только количество. Плашка несёт значение, счётчик несёт число ── */
.cnt { border-radius: var(--r-pill); background: var(--surface-3); color: var(--text-2);
       height: 18px; min-width: 18px; padding: 0 var(--sp-6); justify-content: center;
       font-size: 11px; line-height: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cnt--accent { background: var(--ac-600); color: var(--ac-fg); }

/* ── Не плашки, но их постоянно путают с плашками ────────────────────────── */

/* .note — врезка-баннер. Заменяет 28 нынешних классов врезок.
   Фиолетовых «информационных» врезок больше нет: «просто важное» — нейтраль. */
.note { display: block; border-radius: var(--r-chip); padding: 12px 14px;
        background: var(--surface-2); color: var(--text-1); box-shadow: inset 3px 0 0 var(--neu-500);
        font-size: 12px; line-height: 16px; }
.note--ok   { background: var(--ok-50);   color: var(--ok-ink);   box-shadow: inset 3px 0 0 var(--ok-500); }
.note--warn { background: var(--warn-50); color: var(--warn-ink); box-shadow: inset 3px 0 0 var(--warn-500); }
.note--bad  { background: var(--bad-50);  color: var(--bad-ink);  box-shadow: inset 3px 0 0 var(--bad-500); }
.note--neutral { background: var(--surface-2); color: var(--text-1); box-shadow: inset 3px 0 0 var(--neu-500); }

/* .seg — сегментированный переключатель, .chip — съёмный фильтр. Это КОНТРОЛЫ:
   на них нажимают. Плашка состояние показывает, контрол его меняет. */
.seg { display: inline-flex; gap: 2px; padding: 2px; background: var(--surface-2);
       border: 1px solid var(--line); border-radius: var(--r-ctl); }
.seg-btn { height: 28px; padding: 0 12px; border: none; background: none; border-radius: var(--r-chip);
           font-size: 13px; line-height: 28px; font-weight: 400; color: var(--text-2); cursor: pointer;
           white-space: nowrap; /* «7 дн» в тесной шапке переносил «дн» на вторую строку (28.08) */ }
.seg-btn:hover { background: var(--row-hover); color: var(--text-1); }
.seg-btn.active, .seg-btn[aria-pressed="true"] { background: var(--ac-600); color: var(--ac-fg); font-weight: 600; }
.chip { display: inline-flex; align-items: center; gap: var(--sp-6); height: 24px; padding: 0 var(--sp-8);
        border: 1px solid var(--line-2); border-radius: var(--r-pill); background: var(--surface);
        font-size: 12px; color: var(--text-2); cursor: pointer; }
.chip.active { border-color: var(--ac-300); color: var(--ac-700); background: var(--ac-50); }
.chip-x { width: 12px; height: 12px; opacity: .6; }
.chip:hover .chip-x { opacity: 1; }

/* ═══ МИГРАЦИЯ СТАРЫХ ИМЁН НА ВОСЕМЬ РОДОВ ══════════════════════════════════
   Старые классы не переименовываются — на девятнадцать имён опирается дымовой
   тест, и молчаливый провал теста уже случался (24.08, панель чипов #anSubnav:
   семь проверок перестали выполняться, а итог остался «проблем 0»). Поэтому
   старые имена просто получают новый вид, а сами правила выше остаются мёртвым
   грузом до седьмого этапа, когда их удалят вместе с правкой теста.

   Одиннадцать независимых реализаций триады «хорошо / внимание / плохо»
   сводятся здесь к одной геометрии. Блок стоит в конце файла намеренно: при
   равной специфичности побеждает то, что ниже.

   ДВА ОТСТУПЛЕНИЯ ОТ ПЛАНА, СДЕЛАННЫЕ ПО ФАКТУ, А НЕ ПО КАРТЕ МИГРАЦИИ:

   1. `.sku-health-low` в карте значился как `--warn`. В коде он был нейтральным
      (`--muted`), и означает он «мало данных», а не «нужно посмотреть». Перевод
      в жёлтый добавил бы тревогу там, где её не было. Оставлен нейтральным.

   2. `.promo-badge` НЕ переведён в сплошную заливку. В «Продвижении» он служит
      сразу двум делам: в колонке статуса кампании это состояние (одно на
      строку), а в числовых ячейках — диагноз («остатка на 3 дня»), и таких в
      строке бывает несколько. Сплошная заливка на каждом сломала бы правило
      цветового бюджета строки. Он остаётся мягкой заливкой до тех пор, пока
      генератор в promotion.js не разведёт эти два случая по `.st` и `.dg`.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Геометрия — та же, что у восьми родов */
.verdict, .pf-score, .sku-health, .src-state, .rv-badge, .niche-lvl {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-4);
  height: 20px; min-width: 72px; padding: 0 var(--sp-8);
  border: none; border-radius: var(--r-pill);
  font-size: 12px; line-height: 16px; font-weight: 600;
  white-space: nowrap; vertical-align: middle; box-sizing: border-box;
  background: var(--neu-fill); color: var(--neu-on);
}
/* В плотной таблице ширину диктует текст: колонка уже минимальной ширины плашки */
.sku-table .sku-health, .promo-table .st, td .sku-health { min-width: 0; }
/* Колонка «Здоровье» — 72px, а надпись «не в срезе» шире: в узкой колонке плашка
   берёт размер .pl--nano, иначе она вылезает под кнопки действий соседней ячейки. */
.sku-table .sku-health { height: 16px; padding: 0 6px; font-size: 10px; line-height: 14px; max-width: 100%; }
/* Вердикт — единственная плашка блока, поэтому крупный размер */
.verdict { height: 24px; padding: 0 var(--sp-12); }

/* Хорошо */
.verdict-go, .pf-score-green, .sku-health-ok, .src-state.ok, .rv-badge.ok, .niche-lvl-low {
  background: var(--ok-fill); color: var(--ok-on); border: none;
}
/* Нужно посмотреть */
.pf-score-yellow, .niche-lvl-mid {
  background: var(--warn-fill); color: var(--warn-on); border: none;
}
.verdict-fix { background: var(--warn-fill); color: var(--warn-on); }
/* Нужно решить */
.verdict-stop, .pf-score-red, .sku-health-issue, .rv-badge.err, .niche-lvl-high {
  background: var(--bad-fill); color: var(--bad-on); border: none;
}
/* Факт без оценки */
.sku-health-low, .rv-badge.muted {
  background: var(--neu-fill); color: var(--neu-on); border: none;
}
/* Вне игры: пунктир, а не бледная заливка — «состояние есть, объект отключён» */
.pf-score-na, .sku-health-none, .src-state.off {
  background: none; border: 1px dashed var(--line-dash); color: var(--text-3); font-weight: 400;
}

/* Счётчики: плашка несёт значение, счётчик несёт число — вид у них разный */
.group-count, .score-pill {
  display: inline-flex; align-items: center; justify-content: center;
  height: 18px; min-width: 18px; padding: 0 var(--sp-6);
  border-radius: var(--r-pill); background: var(--surface-3); color: var(--text-2);
  font-size: 11px; line-height: 18px; font-weight: 700; font-variant-numeric: tabular-nums;
  border: none;
}

/* Метки без оценки: были три попиксельных двойника под тремя именами */
.src-tag, .rv-flag, .rv-video-tag, .sku-badge, .feature-chip, .pf-fact, .an-tier {
  display: inline-flex; align-items: center; gap: var(--sp-4);
  height: 16px; padding: 0 var(--sp-6);
  border: 1px solid var(--line-2); border-radius: var(--r-pill); background: none;
  font-size: 10px; line-height: 14px; font-weight: 700; color: var(--text-2);
  white-space: nowrap; vertical-align: middle; box-sizing: border-box;
}
/* Метка поверх фотографии живёт на своей подложке и в общее правило не входит */
.rv-video .rv-video-tag { border-color: transparent; }

/* ═══ ПОПРАВКИ ПОСЛЕ МИГРАЦИИ (ревью 24.08.2026) ═══════════════════════════
   Базовые правила миграции стригут старые классы под одну геометрию, но
   некоторым из них геометрия «одна строка фиксированной высоты» противопоказана:
   в них попадает текст непредсказуемой длины или собственная семантика.
   Частные случаи восстанавливаются здесь — НИЖЕ базовых правил, потому что при
   равной специфичности побеждает то, что позже. */

/* В эту плашку reviews.js кладёт произвольный текст ошибки публикации WB —
   он обязан переноситься, а не вылезать за карточку отзыва (легаси max-width:100%
   и overflow-wrap:anywhere из блока отзывов продолжают действовать). */
.rv-badge { height: auto; min-height: 20px; white-space: normal; text-align: center; }

/* «Нет остатка» — тревога, а не метка без оценки: базовое правило миграции
   гасило красный, и дефицит выглядел как обычный факт. */
.sku-badge-danger { background: var(--bad-50); color: var(--bad-ink); border-color: var(--bad-100); }

/* Сюда рендерится склейка имён ВСЕХ загруженных файлов одной строкой —
   nowrap и фиксированные 16px не дают списку ни переноситься, ни расти. */
.pf-fact { height: auto; min-height: 16px; white-space: normal; max-width: 100%; overflow-wrap: anywhere; }

/* Значения характеристик товара бывают длиннее строки — обязаны переноситься. */
.feature-chip { height: auto; min-height: 16px; white-space: normal; overflow-wrap: anywhere; }

/* ═══════════════════════════════════════════════════════════════════════════
   СОСТОЯНИЯ БЛОКА И ЧЕСТНОСТЬ ЧИСЕЛ (этап 4)               введено 25.08.2026
   ───────────────────────────────────────────────────────────────────────────
   Скелет один: шапка карточки стоит на месте во всех состояниях, меняется
   только тело — интерфейс не прыгает, когда приходят данные.

   Правило честности: у каждого числа видно, откуда оно, за какой период и
   когда посчитано. Носитель — строка .blk-meta и поповер по КЛИКУ (не по
   наведению: на проекторе, таче и с клавиатуры наведения не существует).
   Подсказка title= остаётся только декоративной — полное имя при усечении,
   пояснение к иконке.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Строка происхождения данных ── */
.blk-meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-8);
  margin: var(--sp-8) 0;
  font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3);
}
.blk-meta .src, .blk-meta .per { flex: 0 0 auto; }
.blk-age { color: var(--text-3); }
.lnk { border: none; background: none; padding: 0; font: inherit; color: var(--ac-700); cursor: pointer; }
.lnk:hover { text-decoration: underline; }

/* ── Поповер по клику ──
   Ровно один на страницу, живёт в конце body, позиционируется скриптом.
   Четыре строки: Источник / Период / Формула / Обновлено. */
.pop {
  position: absolute; z-index: 1200; max-width: 340px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-chip); box-shadow: var(--sh-2);
  padding: 12px; opacity: 0;
  /* Прозрачность НЕ отключает попадание кликов: без visibility и pointer-events
     закрытый поповер оставался невидимым перехватчиком 340px над таблицей.
     visibility прячется с задержкой в длительность растворения, иначе исчезает рывком. */
  visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-2), visibility 0s var(--dur-2);
}
.pop.show { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity var(--dur-2); }
.pop-row { display: flex; flex-direction: column; gap: 2px; }
.pop-row + .pop-row { margin-top: var(--sp-8); }
.pop-k { font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); }
.pop-v { font-size: 12px; line-height: 16px; font-weight: 400; color: var(--text-2); overflow-wrap: anywhere; }
.pop-v-mono { font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace; }

/* Всё, что открывает поповер, выглядит нажимаемым */
[data-pop] { cursor: pointer; }
/* Значок формулы в шапке колонки: не перехватывает сортировку заголовка —
   скрипт останавливает всплытие на самом значке */
.th-i {
  border: none; background: none; padding: 0 2px; margin-left: 2px;
  font: inherit; font-size: 11px; color: var(--text-4); cursor: pointer;
  vertical-align: baseline;
}
.th-i:hover { color: var(--ac-700); }

/* ── 1. Загрузка: скелет, не спиннер ──
   Заголовок остаётся, сверху бежит полоса 2px, в теле пять полос-строк.
   Не shimmer: блики мельтешат на плотном экране, дыхание прозрачностью — нет. */
.blk--loading { position: relative; overflow: hidden; }
.blk--loading::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--ac-500), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: blk-run var(--dur-4) linear infinite;
}
@keyframes blk-run { from { background-position: -40% 0; } to { background-position: 140% 0; } }
.blk-skel { display: flex; flex-direction: column; gap: var(--sp-8); padding: var(--sp-8) 0; }
.blk-skel i {
  display: block; height: 20px; border-radius: var(--r-xs);
  background: var(--surface-3);
  animation: blk-breathe 1.2s ease-in-out infinite;
}
.blk-skel i:nth-child(1) { width: 100%; }
.blk-skel i:nth-child(2) { width: 78%; animation-delay: .1s; }
.blk-skel i:nth-child(3) { width: 92%; animation-delay: .2s; }
.blk-skel i:nth-child(4) { width: 64%; animation-delay: .3s; }
.blk-skel i:nth-child(5) { width: 84%; animation-delay: .4s; }
@keyframes blk-breathe { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .blk--loading::before { animation: none; background: var(--ac-500); background-size: 100% 100%; }
  .blk-skel i { animation: none; opacity: .7; }
}

/* ── 2. Нет по природе: одна строка, без заглушки и кнопки.
   «Возвратов не было» — это не проблема, и подавать её как проблему нельзя. */
.blk-none { font-size: 13px; line-height: 18px; color: var(--text-2); padding: var(--sp-8) 0; }

/* ── 3. Не подключено: самое громкое из состояний ── */
.blk--off {
  background: var(--surface-2); border: 1px dashed var(--line-dash);
  border-radius: var(--r-card); padding: var(--sp-24);
  box-shadow: inset 3px 0 0 var(--mp, var(--n-400));
}
.blk-off-glyph { font-size: 40px; line-height: 1; color: var(--text-4); margin-bottom: var(--sp-8); }
.blk-off-title { font-size: 15px; line-height: 20px; font-weight: 600; color: var(--text-1); margin-bottom: var(--sp-4); }
.blk-off-text { font-size: 12px; line-height: 16px; color: var(--text-3); margin-bottom: var(--sp-12); max-width: 420px; }
.blk-off-link { display: inline-block; margin-top: var(--sp-8); font-size: 11px; line-height: 16px; color: var(--ac-700); }

/* ── 4. Подключено, но пусто: рамка сплошная — подключение есть, мы ЗНАЕМ,
   что данных нет. Кнопка вторичная и маленькая. */
.blk--empty { border: 1px solid var(--line); border-radius: var(--r-card); padding: var(--sp-16); }

/* ── 5. Дозревает: числа показываются ВСЕГДА, только тише. Дельты в этом
   состоянии не показываются вовсе — сравнивать незакрытый период с закрытым
   это враньё. */
.blk--maturing .blk-body { opacity: .78; }
.blk--maturing .dl { display: none; }
tr.row-maturing td { opacity: .55; }

/* ── 6. Устарело: данные целиком, но карточка помечена ── */
.blk--stale { border-top: 2px solid var(--warn-500); }
.blk--stale .blk-meta { color: var(--warn-ink); }

/* ── 7. Ошибка: локальна для блока, остальной экран работает ── */
.blk--error {
  background: var(--bad-50); border: 1px solid var(--bad-100);
  border-radius: var(--r-card); box-shadow: inset 3px 0 0 var(--bad-500);
  padding: var(--sp-16);
}
.blk-err-title { font-size: 15px; line-height: 20px; font-weight: 600; color: var(--bad-ink); margin-bottom: var(--sp-4); }
.blk-err-text { font-size: 13px; line-height: 20px; color: var(--text-2); margin-bottom: var(--sp-8); }
/* Копируемая техническая строка: человек шлёт её нам, не переписывая руками */
.blk-err-tech {
  display: inline-block; font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
  font-size: 11px; line-height: 16px; color: var(--text-3);
  border: 1px solid var(--line-2); border-radius: var(--r-chip);
  padding: 3px var(--sp-8); cursor: pointer; user-select: all;
}

/* ── Восьмое, вне списка: ничего не нашлось ПО ФИЛЬТРУ. Это не «нет по
   природе»: тут виноват фильтр, и лечится он одной кнопкой. */
.tbl-empty { font-size: 13px; line-height: 18px; color: var(--text-2); padding: var(--sp-12) 0; }
.tbl-empty .lnk { margin-left: var(--sp-8); }

/* ═══════════════════════════════════════════════════════════════════════════
   ТАБЛИЦЫ: ОДНА ПЛОТНОСТЬ (этап 5, первый заход)          введено 25.08.2026
   ───────────────────────────────────────────────────────────────────────────
   До этого в продукте жили десять самостоятельных наборов оформления и пять
   фактических плотностей (39 / 30 / 31 / 33 / 35), а line-height в таблицах
   не был задан нигде. Здесь — один контракт, надетый ГРУППОВЫМИ селекторами
   на существующие имена: переименований нет, дымовой тест держится за них.

   Строка 36 px — совпадение двух независимых систем (Metabase ROW_HEIGHT=36,
   Grafana Sm=36): формула 9 + 18 + 9. В таблице height на td работает как
   минимум — строка с переносом или миниатюрой 40 px честно вырастает, и
   проверка плотности допускает ровно две высоты.

   ЧТО НАМЕРЕННО НЕ ЗДЕСЬ (по мере перевода экранов, не одним махом):
   nowrap/ellipsis на все ячейки (сломал бы двухстрочные имена в дашборде),
   липкие первая/последняя колонки, группировка tr.grp вместо зебры, подвал
   «Показано N из M», классы .c-name/.c-num в генераторах 44 таблиц.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Дефолт ячейки — ВТОРИЧНЫЙ цвет: при 14 колонках взгляд опирается на то,
   что первичный получает только колонка-имя. Красить всё одинаково — значит
   не выделить ничего. */
td,
.sku-table td,
.promo-table td,
.niche-table td,
.pf-cmp td,
.an-seo-core td,
.src-bill-table td {
  height: var(--row-h);
  padding: 6px var(--cell-px);
  font-size: 13px; line-height: 18px; font-weight: 400;
  color: var(--text-2);
  /* Разделитель был цветом фона страницы — на белой карточке почти невидим */
  border-bottom: var(--bw) solid var(--line);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
/* Таблица товаров: 15 колонок в жёсткой ширине 1242 px — горизонтальный отступ
   остаётся 6 px до перевода на липкие колонки, иначе таблица не помещается.
   Осознанное отступление от --cell-px, а не забытое место. */
.sku-table td { padding-left: 6px; padding-right: 6px; }

/* Имена и ссылки в ячейках остаются первичными: их красят свои классы ниже
   по файлу (.sku-tname, .promo-name b, td a) — контракт их не перебивает,
   потому что у них выше специфичность или позднее правило. */
td a, .promo-table td b { color: var(--text-1); }

/* Шапка: 32 px, обычный регистр (капс снят этапом 2), вторичный серый.
   Липкость — ТОЛЬКО внутри прокручиваемых контейнеров: на таблице, которую
   прокручивает сама страница, sticky-шапка въезжала бы под топбар. */
th,
.sku-table thead th,
.promo-table th,
.niche-table th,
.pf-cmp th,
.an-seo-core th,
.src-bill-table th {
  height: var(--head-h);
  padding: 4px var(--cell-px);
  font-size: 11px; line-height: 16px; font-weight: 600;
  color: var(--text-3);
  vertical-align: middle;
}
.sku-table td { vertical-align: middle; }
.sku-table-wrap .sku-table thead th,
.table-scroll .promo-table th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface);
  border-bottom: none;
  /* не border: липкая шапка теряет его при прокрутке */
  box-shadow: inset 0 -1px 0 var(--line);
}
.sku-table thead th { padding-left: 6px; padding-right: 6px; }

/* Ховер и выбор — непрозрачные подложки из токенов: альфа складывалась бы
   с заливками плашек и давала бы три оттенка одного статуса. */
tbody tr:hover > td { background: var(--row-hover); }
tr.sel > td, tr.sess-current > td { background: var(--row-sel); }
tr.sel > td:first-child { box-shadow: inset 3px 0 0 var(--ac-600); }

/* Итог тяжелее ВЕСОМ и ФОНОМ, а не акцентной линией: цвет там, где он ничего
   не значит, — потраченный впустую цветовой бюджет. */
.src-bill-table tr.total td,
.pf-cmp tr.pf-our-last td {
  background: var(--surface-3);
  border-top: 2px solid var(--line-2);
  border-bottom: none;
  font-weight: 600; color: var(--text-1);
}

/* Прочерк «нет данных» был цветом --faint — четвёртой ступенью, которая
   намеренно не проходит AA («сюда смотреть не надо»). Но «данных нет» — это
   информация, а не пустое место: ей положена третья ступень. */
.sku-na { color: var(--text-3); }

/* Полоса прокрутки 8 px: пятипиксельную не поймать мышью на ширине 1120+ */
.table-scroll::-webkit-scrollbar, .sku-table-wrap.card::-webkit-scrollbar { height: 8px; width: 8px; }
.table-scroll::-webkit-scrollbar-thumb, .sku-table-wrap.card::-webkit-scrollbar-thumb {
  background: var(--line-2); border-radius: 4px;
}

/* ── ОТКАТ ПЛОТНОСТИ ДЛЯ ДВУХ ФЛАГМАНОВ — по замеру, не по вкусу ────────────
   Проверка 25.08.2026 показала: контракт 36px, надетый на таблицы с
   ДВУХСТРОЧНЫМИ ячейками (имя + артикул у товаров, фраза + кампания у
   продвижения), раздул строки до 70 и 104 px — кегль 13/18 и отступ 10px
   умножились на вторые строки, которых контракт не предусматривает.
   Плотность 36px честно работает только после перевода этих таблиц на
   однострочную колонку-имя с многоточием (.c-name) — это отдельная работа
   в генераторах, а не в CSS. До неё флагманы остаются в своей компактной
   геометрии; от контракта им достаются видимые разделители, ховеры из
   токенов и липкие шапки. */
.sku-table td {
  height: auto; padding: 6px; font-size: 12px; line-height: 1.35;
}
.promo-table td {
  height: auto; padding: 7px 6px; font-size: 13px; line-height: 1.35; /* 1.4 давал +6px на четырёхстрочных ячейках фраз — сверено с базой до этапа 5 */
}
/* Шапка promo-таблицы — те же 6px по бокам, что у её ячеек: с --cell-px (10px) таблица
   «Кампаний» на 1440 выходила на 21px шире обёртки и «Конкурентная» резалась краем
   (замер 22.09.2026: при 6px — ровно ширина обёртки) */
.promo-table th { padding-left: 6px; padding-right: 6px; }

/* ── ЭТАП 5, ВТОРОЙ ЗАХОД (01.09.2026): классы колонок в генераторах ─────────
   .c-num — числовая колонка: выравнивание вправо и табличные цифры, чтобы
   разряды стояли в столбик; правило накрывает и th — шапка выравнивается
   вместе со своими числами. .c-name — колонка-имя: одна строка с многоточием;
   полное значение показывает панель/поповер своего экрана. Двухстрочные имена
   флагманов (товар с артикулом в .sku-table, фраза с кампанией в .promo-table)
   на .c-name НЕ переводятся до отдельного решения — их держит откат плотности
   выше по файлу. */
/* Подвал таблицы/карточки («Показано N из M», «полный список в Excel»):
   один класс вместо инлайн-стилей с --faint. Четвёртая ступень намеренно не
   проходит AA («сюда смотреть не надо»), а «куда делись остальные строки» —
   это информация: ей положена третья, как и прочерку .sku-na. */
.tbl-foot { margin-top: 8px; font-size: 12px; line-height: 16px; color: var(--text-3); }
.tbl-foot--tight { margin-top: 6px; }

th.c-num, td.c-num { text-align: right; font-variant-numeric: tabular-nums; }
td.c-name, th.c-name {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 340px;
}
td.c-name { color: var(--text-1); }

/* Первая колонка дневных матриц — имя ряда: одна строка с многоточием, полное
   значение есть в легенде графика над таблицей. Без этого артикулы ЯМ-колонок
   ломались на три строки и раздували ряды (замечание владельца, 25.08). */
#anCatTable td:first-child, #anModelsTable td:first-child, #anBrandsTable td:first-child,
#anCatTable th:first-child, #anModelsTable th:first-child, #anBrandsTable th:first-child {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px;
}

/* Юнит-экономика (#anFinUnit, 22.09.2026): 14 колонок в 1080px — имя ужималось до ~130px,
   артикул рвался по дефису («yndx-» / «00075»), проценты — на «30,24» / «%». Шапкам nowrap
   не даём: «К перечислению», «Платф. скидка» должны переноситься. На телефоне первая
   колонка .table-scroll липкая — минимум снимаем, иначе 200px съели бы половину экрана. */
#anFinUnit td, #anFinUnit th { padding-left: 8px; padding-right: 8px; }
#anFinUnit td.c-num { white-space: nowrap; }
#anFinUnit td.an-fin-name { min-width: 200px; }
#anFinUnit .an-fin-art { color: var(--text-4); white-space: nowrap; }
@media (max-width: 900px) { #anFinUnit td.an-fin-name { min-width: 0; max-width: 46vw; } }

/* «Оборачиваемость» на телефоне: в 560px «Хватит на» («~0 дн. (к 22 сент.) ⚠», жирным)
   ломалась на 3–4 строки за правым краем и раздувала ряд до 85px (22.09.2026) */
.table-scroll .an-turnover-tbl { min-width: 640px; }
.an-turnover-tbl th:last-child, .an-turnover-tbl td:last-child { white-space: nowrap; }

/* ── «Обзор»: динамика + топ-5 (25.08.2026, по замечанию владельца) ────────── */
/* minmax(0,1fr), а не 1fr: голый 1fr это minmax(auto,1fr) — несжимаемое содержимое
   (легенда графика в одну строку) распирает трек и карточка уезжает за контейнер
   (поймано на 2К, 25.08.2026). min-width:0 у карточек — из той же оперы. */
.an-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; margin-bottom: 20px; }
.an-two > .card { min-width: 0; }
@media (max-width: 1100px) { .an-two { grid-template-columns: 1fr; } }
.an-two .card { margin-bottom: 0; }
.an-top-tbl { width: 100%; border-collapse: collapse; }
.an-top-tbl td { height: 36px; padding: 4px 8px; border-bottom: var(--bw) solid var(--line); }
.an-top-tbl tr:last-child td { border-bottom: none; }
.an-top-n { width: 24px; color: var(--text-4); font-weight: 700; font-variant-numeric: tabular-nums; }
.an-top-name { color: var(--text-1); font-weight: 600; max-width: 0; width: 55%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.an-top-tbl td.n { text-align: right; white-space: nowrap; }
/* Доля выручки: полоса длиной в процент — быстрее числа читается соотношение */
.an-top-share { width: 88px; position: relative; }
.an-top-share i { display: block; height: 6px; border-radius: 3px; background: var(--ac-100); min-width: 3px; }
.an-top-share span { font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* Выпадашка категории в шапке «Моделей по дням»: без предела она растягивалась
   на всю карточку и сминала заголовок в две строки (2К, 25.08.2026) */
.an-card-head .an-select { max-width: 420px; }

/* Пара дневных графиков «Продаж» на узком экране складывается в столбик,
   на широком (там, где раньше были колонки) — в два */
.an-two-wide { grid-template-columns: 1fr; }
/* У дневных карточек класс .full = grid-column: 1 / -1 (наследие сетки дашборда):
   внутри пары он растягивал каждую на оба трека — из-за него пара и не вставала */
.an-two-wide > .card.full { grid-column: auto; }
@media (min-width: 1500px) { .an-two-wide { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* ── Чипы категорий в «Оптимизации рекламы» (25.08.2026) ─────────────────────
   Вместо стены из 141 чекбокса на три экрана: живые категории чипами в один
   блок, нулевые — за кнопкой. Отмеченность — состоянием скрытого чекбокса. */
.chip-wrap { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.chip-wrap > span:not([hidden]) { display: contents; }
.chip-wrap .lnk { font-size: 12px; }
.chip > input[type="checkbox"] { display: none; }
.chip:has(> input:checked) { border-color: var(--ac-300); color: var(--ac-700); background: var(--ac-50); }
.chip:has(> input:checked) .cnt { background: var(--ac-100); color: var(--ac-700); }

/* ── Вводные других площадок в карточке «Вводные» (25.08.2026, ночь) ────────
   Тот же вид плиток, что у WB; блок площадки отделён линией и бейджем. */
.an-mp-today { margin-top: 16px; padding-top: 12px; border-top: var(--bw) solid var(--line); }
.an-mp-today-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.an-mp-today .blk-none { margin-top: 8px; }

/* ── Лента площадки в разделе (26.08.2026): бейдж + линия до края ─────────── */
.mp-band { display: flex; align-items: center; gap: 12px; margin: 22px 0 14px; }
.mp-band:first-of-type { margin-top: 4px; }
.mp-band::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* ── Панель «Работы» в шапке (шаг 3 перестройки) ─────────────────────────────
   Кнопка с бейджем активных операций после действий экрана; панель — поповер
   под кнопкой, тот же слой и тень, что у .pop. Всё на токенах — тёмная тема
   достаётся бесплатно. */
.works { position: relative; flex: 0 0 auto; }
.works-btn {
  display: inline-flex; align-items: center; gap: 6px;
  border: var(--bw) solid var(--line-2); background: var(--surface); color: var(--text-2);
  border-radius: var(--r-ctl); padding: 6px 10px;
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.works-btn:hover { background: var(--surface-2); }
.works-btn:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }
.works-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill); background: var(--ac-600); color: var(--ac-fg);
  font-size: 11px; line-height: 16px; font-weight: 700;
}
/* display в классах выше перебивает браузерное [hidden] — возвращаем ему силу */
.works-badge[hidden], .works-panel[hidden] { display: none; }
.works-panel {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 1200;
  width: 340px; max-width: calc(100vw - 24px); max-height: 60vh; overflow: auto;
  background: var(--surface); border: var(--bw) solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--sh-2); padding: 10px;
}
.works-row { display: flex; gap: 8px; align-items: flex-start; padding: 7px 6px; border-radius: var(--r-chip); }
.works-row + .works-row { border-top: var(--bw) solid var(--line); }
/* Точка состояния — как у history-badge: цвет несёт статус, текст — смысл */
.works-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; background: var(--n-400); }
.works-running .works-dot { background: var(--warn-500); }
.works-error .works-dot { background: var(--bad-500); }
.works-done .works-dot { background: var(--ok-500); }
.works-body { min-width: 0; }
.works-label { font-size: 13px; line-height: 18px; font-weight: 600; color: var(--text-1); overflow-wrap: anywhere; }
.works-meta { font-size: 12px; line-height: 16px; color: var(--text-3); overflow-wrap: anywhere; }
.works-error .works-meta { color: var(--bad-ink); }
.works-sep { margin: 8px 6px 2px; font-size: 11px; line-height: 16px; font-weight: 600; color: var(--text-3); }
.works-empty { padding: 10px 6px; font-size: 12px; line-height: 18px; color: var(--text-3); }
/* На телефоне шапка ужимается — панель прижимается к правому краю экрана */
@media (max-width: 720px) {
  .works-panel { position: fixed; top: auto; right: 12px; left: 12px; width: auto; margin-top: 6px; }
}

/* ── «Остатки по складам» (sec-stocks, frontend/js/analytics/stocks.js) ──
   Всё на токенах: тёмная тема через них же. Классы .sku-*/.promo-* не трогаем —
   по ним смоук меряет геометрию «Товаров». */
.an-stocks-matrix th.lvl2 { font-weight: 400; color: var(--text-3); white-space: nowrap; }
td.an-stocks-mm { background: var(--warn-50); box-shadow: inset 3px 0 0 var(--warn-500); }
.an-stocks-site { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 4px 0; }
.an-stocks-tag { display: inline-flex; align-items: center; height: 18px; padding: 0 var(--sp-6); border-radius: var(--r-chip);
  border: 1px solid var(--line); background: var(--surface-2); color: var(--text-2); font-size: 11px; line-height: 16px; white-space: nowrap; }
/* Перестройка 08.09.2026 (таблица первой, потребность к заказу). Старые классы выше не переименованы. */
.an-stocks-stats { margin-bottom: 8px; }
.an-stocks-stats .an-stat { padding: 8px 10px; }
.an-stocks-stats .an-stat-value { font-size: 22px; }
.an-stocks-stats .an-stat-sub { margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* подпись в одну строку: на 1366 плитка росла до 101 px */
.an-stat--btn { cursor: pointer; }
.an-stat--btn:hover { border-color: var(--ac-300); }
.an-stat--btn:focus-visible { outline: 2px solid var(--ac-600); outline-offset: 2px; }
.an-stat--active { background: var(--ac-50); border-color: var(--ac-300); }
.an-stat--skel { min-height: 84px; background: var(--surface-3); border-color: transparent; animation: blk-breathe 1.2s ease-in-out infinite; }
/* Полоса адресов: строка на адрес, только предупреждения; детали — в поповерах и drawer */
.an-stocks-strip { border-top: 1px solid var(--line); padding: 4px 0 0; }
.an-stocks-strip-head { display: flex; align-items: center; gap: 10px; min-height: 20px; }
.an-stocks-strip-row { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; line-height: 24px; font-size: 13px; color: var(--text-2); }
.an-stocks-strip-row > b { color: var(--text-1); }
.an-stocks-strip-num { font-weight: 700; color: var(--text-1); font-variant-numeric: tabular-nums; }
.an-stocks-strip-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.an-stocks-tag--pri { border-color: var(--ac-300); color: var(--ac-700); background: var(--ac-50); }
.an-stocks-tag--warn { border-color: var(--warn-100); background: var(--warn-50); color: var(--warn-ink); }
/* Панель фильтров */
.an-stocks-toolbar { display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; margin: 8px 0; }
.an-stocks-toolbar .chip b { font-weight: 700; margin-left: 4px; font-variant-numeric: tabular-nums; }
.an-stocks-toolbar .chip:disabled { opacity: .45; cursor: default; }
.an-stocks-toolbar .chip.chip--off { opacity: .45; }
.an-stocks-toolbar .chip input[type="checkbox"] { margin: 0 2px 0 0; accent-color: var(--ac-600); }
.an-stocks-toolbar .seg-btn b { font-weight: 700; margin-left: 4px; }
.an-stocks-chipgrp { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.an-stocks-sep { width: 1px; height: 20px; background: var(--line-2); }
.an-stocks-search { width: 180px; max-width: 100%; }
.an-stocks-sel { font-weight: 400; padding: 3px 8px; font-size: 12px; max-width: 180px; }
.an-stocks-cols { display: inline-flex; gap: 6px; align-items: center; margin-left: 6px; }
.an-stocks-cols .chip { height: 20px; font-size: 11px; }
/* Скролл-бокс таблицы: липкая шапка (top:0) и липкая колонка «Товар» (left:0) */
.an-stocks-wrap { --cell-px: 8px; overflow: auto; max-height: max(320px, calc(100vh - var(--topbar-h, 60px) - 150px)); border: 1px solid var(--line); border-radius: var(--r-card); }
.an-stocks-wrap table { min-width: 720px; width: 100%; }
.an-stocks-wrap thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); box-shadow: inset 0 -1px 0 var(--line); border-bottom: none; white-space: nowrap; height: var(--head-h); padding: 0 var(--cell-px); }
.an-stocks-wrap thead th.c-name, .an-stocks-wrap td.c-name { position: sticky; left: 0; background: var(--surface); box-shadow: 1px 0 0 var(--line); min-width: 240px; max-width: 300px; }
.an-stocks-wrap thead th.c-name { z-index: 3; box-shadow: inset 0 -1px 0 var(--line), 1px 0 0 var(--line); }
.an-stocks-wrap td.c-name { z-index: 1; white-space: normal; }
.an-stocks-wrap thead.two th { top: 0; }
.an-stocks-wrap thead.two th.l2 { top: var(--head-h); white-space: nowrap; line-height: 14px; }
.an-stocks-wrap thead th.an-stocks-th--hi { background: var(--ac-50); color: var(--ac-700); }
.an-stocks-wrap thead th.an-stocks-th--dim { color: var(--text-4); }
.an-stocks-wrap td.an-stocks-td--hi { background: var(--ac-50); }
.an-stocks-wrap td { padding: 3px var(--cell-px); height: auto; white-space: nowrap; }
.an-stocks-wrap td .t-micro { white-space: nowrap; }
.an-stocks-wrap tbody tr:last-child td { border-bottom: none; }
.an-stocks-arrow { font-size: 9px; margin-left: 3px; color: var(--ac-700); }
.an-stocks-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; color: var(--text-1); line-height: 18px; }
.an-stocks-sub { color: var(--text-4); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-stocks-badge { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--r-chip); color: var(--text-3); font-weight: 600; }
.an-stocks-row { cursor: pointer; }
.an-stocks-row:hover td { background: var(--row-hover); }
.an-stocks-row:hover td.c-name { background: var(--row-hover); }
.an-stocks-row:focus-visible { outline: 2px solid var(--ac-600); outline-offset: -2px; }
tr.an-stocks-grp td { background: var(--surface-3); font-weight: 600; color: var(--text-1); position: sticky; top: var(--head-h); z-index: 1; cursor: pointer; }
tr.an-stocks-grp td.c-name { z-index: 2; background: var(--surface-3); }
.an-stocks-caret { color: var(--text-3); font-size: 11px; margin-right: 2px; }
tr.an-stocks-sum td { position: sticky; bottom: 0; background: var(--surface); font-weight: 600; box-shadow: inset 0 1px 0 var(--line); }
tr.an-stocks-sum td.c-name { z-index: 2; }
.an-stocks-mark { font-size: 11px; margin-right: 3px; color: var(--warn-ink); }
.an-stocks-mark--fb { color: var(--text-3); }
.an-stocks-days--danger { color: var(--bad-ink); font-weight: 600; }
.an-stocks-days--warn { color: var(--warn-ink); font-weight: 600; }
.an-stocks-days--over { color: var(--text-4); }
.an-stocks-need { color: var(--ac-700); font-weight: 700; }
.an-stocks-pen { font-size: 12px; color: var(--text-4); margin-left: 2px; }
.an-stocks-pen:hover { color: var(--ac-700); text-decoration: none; }
.an-stocks-note { display: flex; gap: 4px; align-items: baseline; flex-wrap: wrap; }
/* Drawer «Адреса складов» */
.an-stocks-sitehead { margin-bottom: 6px; }
.an-stocks-sitenote { width: 100%; }
textarea.an-stocks-sitenote { width: 100%; min-height: 28px; margin-top: 4px; padding: 4px 8px; font-size: 12px; line-height: 18px; border: 1px solid var(--line); border-radius: var(--r-chip); background: var(--bg); color: var(--text-2); resize: vertical; }
.an-stocks-whrow { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; padding: 6px 0; border-top: 1px dashed var(--line); font-size: 13px; }
.an-stocks-whrow-l { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; flex: 1 1 260px; }
.an-stocks-whrow-r { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; }
.an-stocks-whname { font-weight: 600; color: var(--text-1); }
.an-stocks-radio { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text-2); cursor: pointer; white-space: nowrap; }
.an-stocks-radio input { margin: 0; accent-color: var(--ac-600); }
.an-stocks-whrow .an-stocks-sel { width: 180px; }
/* Карточка товара */
.an-stocks-formula { font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace; font-size: 12px; line-height: 20px; color: var(--text-2); background: var(--bg); border-radius: var(--r-chip); padding: 8px 10px; }
.an-stocks-formula b { color: var(--ac-700); }
.an-stocks-psite { padding: 6px 0; border-top: 1px dashed var(--line); font-size: 13px; }
.an-stocks-psite:first-child { border-top: none; }
.an-stocks-pwh { display: flex; gap: 8px; align-items: center; padding: 2px 0 2px 8px; font-size: 12px; color: var(--text-2); }
.an-stocks-sizes th, .an-stocks-sizes td { padding: 4px 8px; height: auto; font-size: 12px; }
.an-stocks-bars { display: flex; flex-direction: column; gap: 4px; }
.an-stocks-bars svg { display: block; max-width: 100%; }
/* ≤ 1440 (ноутбук 1366×768): уже колонка «Товар» и отступы ячеек, чтобы «К заказу»/«В пути» влезали в бокс без прокрутки;
   заголовки адресов режутся до 10 симв. в JS, полоса адресов свёрнута по умолчанию, панель фильтров — плотнее */
@media (max-width: 1440px) {
  .an-stocks-wrap { --cell-px: 6px; }
  .an-stocks-wrap thead th.c-name, .an-stocks-wrap td.c-name { min-width: 200px; max-width: 240px; }
  .an-stocks-toolbar { gap: 4px 6px; }
  .an-stocks-search { width: 150px; }
}
@media (max-height: 700px) { .an-stocks-wrap { max-height: none; } }
