@charset "UTF-8";
/* ───────── #46 (23.09.2026): шрифт IBM Plex Sans со своего сервера (лицензия OFL, fonts/OFL-LICENSE.txt; @fontsource 5.3.0).
   Политика безопасности сайта (deploy/nginx.conf, default-src 'self') шрифты с Google Fonts не пропускает. ───────── */
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/ibm-plex-sans-cyrillic-400-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/ibm-plex-sans-latin-ext-400-normal.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/ibm-plex-sans-latin-400-normal.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/ibm-plex-sans-cyrillic-500-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/ibm-plex-sans-latin-ext-500-normal.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/ibm-plex-sans-latin-500-normal.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/ibm-plex-sans-cyrillic-600-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/ibm-plex-sans-latin-ext-600-normal.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/ibm-plex-sans-latin-600-normal.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}
:root{
  --hdr-h:42px; --row-h:24px;
  --grid:#c5c9cf; --week:#E8E8E8; --month:#D7D7D7;   /* 20.10.2026 (#160): было #F4CCCC / #EA9999 */
  --panel-w:230px;
}
*{box-sizing:border-box;margin:0;padding:0}
/* TODO #38: страница — колонка «шапка + плашки + рабочая область». Рабочая область забирает остаток высоты,
   поэтому плашки под шапкой (сбой синка, подписи недель, видимость столбцов) её укорачивают, а не выталкивают
   низ за окно. Шапка и плашки не сжимаются (без этого шапка сплющивалась 44 → ~20 px). */
body{font:13px/1.35 'IBM Plex Sans',system-ui,sans-serif;color:#1c1e22;background:#f4f4f1;overflow:hidden;height:100vh;display:flex;flex-direction:column}
body>*{flex-shrink:0}
/* анти-FOUC: пока не проверена авторизация — прячем внутренний интерфейс, чтобы он не мигал при загрузке */
body.booting .bar1,body.booting .bar2,body.booting #content{display:none}
body>.tablewrap{flex:1 1 auto;min-height:0;overflow:auto;background:#fff;position:relative}
table{border-collapse:separate;border-spacing:0;table-layout:fixed}
th,td{border-right:1px solid var(--grid);border-bottom:1px solid var(--grid);padding:2px 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:var(--row-h);text-align:right;font-size:11px}
th{font-weight:bold;text-align:center;white-space:normal;line-height:1.1}
thead th{position:sticky;z-index:5}
thead tr.grp th{top:0;height:var(--hdr-h);font-size:15px}
thead tr.met th{top:var(--hdr-h);height:56px;font-size:12px;font-weight:normal;vertical-align:middle}   /* 21.09.2026: 15 → 12 px (владелец) */
tbody td:first-child, thead th:first-child{position:sticky;left:0;background:#fff;z-index:6;text-align:left;font-weight:bold;width:168px;min-width:168px;max-width:168px;border-right:2px solid #888}
thead tr.grp th:first-child{z-index:9;background:#FFF2CC;text-align:center}
thead tr.met th:first-child{z-index:9;background:#FFF2CC}
/* Угловая ячейка: диагональ «Дата ╲ Метрика» — подписывает обе оси сводной таблицы.
   Линия — inline-SVG, а не linear-gradient: полоса градиента перпендикулярна его оси и на
   неквадратной ячейке (168×56) не совпадает с диагональю бокса. preserveAspectRatio=none тянет
   линию точно из угла в угол, non-scaling-stroke держит её в 1px. Правила идут ПОСЛЕ :first-child —
   там background-шорткат обнуляет background-image. Абсолютные подписи цепляются за sticky-предка. */
thead tr.met th.corner{background-color:#FFF2CC;background-repeat:no-repeat;background-size:100% 100%;
  background-image:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20preserveAspectRatio='none'%20viewBox='0%200%20168%2056'%3E%3Cline%20x1='9'%20y1='3'%20x2='159'%20y2='53'%20stroke='%23c4b072'%20stroke-width='1'%20vector-effect='non-scaling-stroke'/%3E%3C/svg%3E");
  padding:0}
/* Каждая подпись центрируется по обеим осям внутри СВОЕЙ половины угла (флекс-бокс 58%×50%,
   прижатый к своему углу), а не отступами от края — иначе «Метрика» и «Дата» не читались бы как
   подписи осей. 58% ширины хватает 15px-жирному тексту и оставляет ≥23px зазора до диагонали. */
thead tr.met th.corner span{position:absolute;display:flex;align-items:center;justify-content:center;
  width:58%;height:50%;font-size:14px;font-weight:bold;line-height:1;color:#111}
thead tr.met th.corner .cn-col{top:0;right:0}
thead tr.met th.corner .cn-row{bottom:0;left:0}
tr.week td{background:var(--week);font-weight:bold}
tr.month td{background:var(--month);font-weight:bold}
tr.year td{background:#9fc5e8;font-weight:bold}
tr.cumul td{background:#cfe2f3;font-weight:bold}
tr.yr-sep td{border-top:2px solid #9199a3}   /* «Все года»: ненавязчивый разделитель между годами */
/* строка прогноза на следующий день — подсвечена под последним днём */
tr.forecast td{background:#ffe49c;font-weight:bold;border-top:2px dashed #d98a00;color:#5a3d00}
tr.forecast td:first-child{background:#ffe49c}
/* строка «Итого за период» — суммы за выбранный период; серая (отличать от жёлтого прогноза).
   Первый столбец переносит длинную подпись (диапазон дат) внутри 168px — height:auto под 2 строки. */
tr.period-total td{background:#dfe3e8;font-weight:bold;border-top:2px solid #9aa3ad;color:#2b3038}
tr.period-total td:first-child{background:#dfe3e8;white-space:normal;line-height:1.2;height:auto}
/* 16.09.2026: «Доля продаж за период» — между итогом периода и прогнозом. Голубая, чтобы не сливаться с серым итогом. */
/* 21.10.2026 (#163): строки «Доля продаж за период» (tr.share-total) больше нет */
.wktoggle{display:inline-block;width:14px;height:14px;line-height:12px;text-align:center;border:1px solid #888;border-radius:2px;background:#fff;color:#333;font-weight:bold;cursor:pointer;margin-right:6px;font-size:11px;user-select:none}
.wktoggle:hover{background:#1f6feb;color:#fff;border-color:#1f6feb}
.wkchild{display:inline-block;width:16px}
tr.child td:first-child{padding-left:10px;color:#555;font-weight:normal}
/* Подсветка строки под курсором — полупрозрачный слой ПОВЕРХ фона ячейки (16.09.2026).
   Было filter:brightness(.96): у ячеек без своего фона (белые — данные из API) затемнять было нечего, и строка
   подсвечивалась «через одну ячейку». Цвета происхождения (ручные/формулы) под слоем сохраняются.
   Итоговые строки внизу не подсвечиваем: они одни, а затемнение сливало «Долю продаж» с «Итого за период». */
tbody tr:hover td{box-shadow:inset 0 0 0 9999px rgba(31,111,235,.08)}
tbody tr.period-total:hover td,tbody tr.forecast:hover td{box-shadow:none}
.pbtn{display:block;width:100%;text-align:left;padding:8px 10px;border:1px solid var(--grid);background:#fff;border-radius:4px;font-size:12px;cursor:pointer}
.pbtn:hover{background:#eef2f7}
.pbtn.active{background:#1f6feb;color:#fff;border-color:#1f6feb;font-weight:bold}
.pbtn .dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:7px}
.pbtn.chan{padding:5px 9px;font-size:11px}
.pbtn.chan.active{border:2px solid #1f6feb;font-weight:bold;color:#000}
.placeholder{padding:30px;font-size:13px;color:#555}
.placeholder table{margin-top:14px}
.placeholder th,.placeholder td{padding:4px 10px}
.modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;align-items:center;justify-content:center;z-index:50}
.modal{background:#fff;border-radius:8px;width:560px;max-height:80vh;overflow-y:auto;padding:20px 24px}
.modal h2{font-size:15px;margin-bottom:12px}
.modal .grpset{border:1px solid var(--grid);border-radius:6px;padding:10px 12px;margin-bottom:10px}
.modal .grpset b{display:block;margin-bottom:6px;font-size:12px}
.modal label{display:block;font-size:11px;color:#555;margin:6px 0 2px}
.modal input,.modal select{width:100%;padding:6px 8px;border:1px solid var(--grid);border-radius:4px;font-size:12px}
.modal .ok{color:#1a7f37;font-size:11px}
.modal .actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}
.modal .actions button{padding:7px 16px;border-radius:4px;border:1px solid var(--grid);background:#fff;cursor:pointer}
/* Плавающий футер модалок «Видимость столбцов» и «Описание колонок»: заголовок и кнопки фиксированы, скроллится только список */
#colmodal .modal, #docmodal .modal{display:flex;flex-direction:column;overflow:hidden}
#colmodal .cvscroll, #docmodal .cvscroll{flex:1 1 auto;min-height:0;overflow-y:auto}
#colmodal .actions, #docmodal .actions{flex:0 0 auto;margin-top:0;padding-top:10px;border-top:1px solid var(--grid)}

/* Фаза 5: подсветка ДРР */
td.drr-hot{background:#fbeeec !important;color:#a3261c;font-weight:500}   /* 20.10.2026 (#160 Д1): было #f8c8c8 / #a40000 / bold */

/* Тип колонки — только на строках-днях (недели/месяцы держат свой фон tr.week/tr.month).
   Оттенки бледные; `!important` НЕ ставим, иначе фон итоговых строк перебивается.
   Порядок значимости: .drr-hot (тревога, !important) > тип колонки.
     c-hand    — ручной ввод: сюда можно и нужно писать;
     c-formula — вычисляется из соседних колонок группы: не кликается;
     авто-колонки (API/UTM) фона не имеют — намеренно. */
td.c-hand{background:#fff3cd}
td.c-formula{}   /* 20.10.2026 (#160 Ф3): без фона (было #eef4fb) */
/* 18.09.2026: пустая ячейка ручного ввода, которую пора заполнить (перечень TODO_BLOCKS в app.js) — плавно «дышит»
   от цвета ручной ячейки к янтарному, пока не внесено число. Кто просит браузер не анимировать — видит ровную заливку. */
@keyframes todoPulse{0%,100%{background-color:#fff3cd}50%{background-color:#ffc266}}
td.c-todo{animation:todoPulse 2.4s ease-in-out infinite;cursor:cell}
@media (prefers-reduced-motion:reduce){td.c-todo{animation:none;background:#ffc266}}
/* 18.09.2026 (_07): неполная сумма — в нее входит не внесенная ручная часть (значок «?» в правом верхнем углу, причина — в подсказке) */
td.c-partial{position:relative;padding-right:15px !important}
td .pq{position:absolute;top:50%;margin-top:-6px;right:2px;width:11px;height:11px;border-radius:50%;background:#e8a317;color:#fff;
  font:bold 8px/11px Arial,sans-serif;text-align:center;pointer-events:none}
/* 18.09.2026: ввод числа прямо в ячейке (вместо окна браузера) + строка подсказки под ячейкой */
td.c-editing{padding:0 !important;animation:none;background:#fff}
td.c-saving{opacity:.55;font-style:italic;animation:none}   /* 22.09.2026 (#41): введено, ждет ответа сервера */
td.c-failed{outline:2px solid #c0392b;outline-offset:-2px;animation:none}   /* не сохранилось — двойной щелчок повторить */
td.c-editing .cell-input{width:100%;box-sizing:border-box;height:100%;min-height:20px;border:2px solid #1f6feb;
  font:inherit;text-align:right;padding:0 3px;outline:none;background:#fff}
td.c-editing .cell-input:disabled{background:#f3f3f3;color:#888}
.cell-hint{position:fixed;z-index:1000;max-width:420px;padding:3px 7px;font-size:11px;line-height:1.35;background:#1f2937;
  color:#fff;border-radius:4px;box-shadow:0 2px 6px rgba(0,0,0,.25);pointer-events:none}
.cell-hint.warn{background:#8a5a00}
.cell-hint.err{background:#a40000}
/* #27: «Заметки» (kind='text') — без заливки, текст слева, клик открывает попап;
   полный текст — в title и попапе. Обрезка — через .notecell (см. ниже), НЕ через td:
   таблица width:auto ⇒ auto-layout ⇒ td растягивается контентом, а div — нет. */
td.c-note{cursor:pointer;text-align:left;font-size:10px;color:#444}
/* ~15 букв при 10px + место под многоточие (заказ владельца 17.07, было 52px ≈ 7 букв) */
td.c-note .notecell{max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Ячейка авто/формульной колонки, перебитая руками: синк её больше не обновляет
   (manual-guard). Уголок в нижнем правом углу + подсказка в title. */
td.c-frozen{position:relative}
td.c-frozen::after{content:'';position:absolute;right:0;bottom:0;width:0;height:0;
  border:4px solid transparent;border-right-color:#c77b00;border-bottom-color:#c77b00}
/* #32: эра-исключение (в таблице была другая формула, движок посчитал верно) — СИНИЙ уголок
   в ВЕРХНЕМ ЛЕВОМ углу (не путать с оранжевой «заморозкой» снизу-справа) + подсказка в title. */
td.c-exc{position:relative}
td.c-exc::before{content:'';position:absolute;left:0;top:0;width:0;height:0;
  border:4px solid transparent;border-left-color:#1f6feb;border-top-color:#1f6feb}

/* Кнопка «Обновить» + строка статуса синка */
/* #46: ход обновления данных — короткой строкой в шапке рядом с «Обновлено …»; пусто — не видно. */
.syncstatus{font-size:12px;white-space:nowrap;max-width:300px;overflow:hidden;text-overflow:ellipsis}
.syncstatus:empty{display:none}
.syncstatus.run{color:#8a6d00}
.syncstatus.ok{color:#1a7f37}
.syncstatus.err{color:#c0392b}

/* Фаза 4: доп-вкладки */
.abcard{display:inline-block;vertical-align:top;margin:0 12px 12px 0;border:1px solid var(--grid);border-radius:6px;padding:8px 10px;background:#fff}
.abcard .abdate{font-weight:bold;margin-bottom:4px;color:#444}
table.mini{table-layout:auto}
table.mini th,table.mini td{padding:3px 10px}
table.mini tr.best td{background:#d9ead3;font-weight:bold}
/* #46: переключатели «Баннеров» и окна столбцов — только там; .seg шапки — по макету (ниже) */
.placeholder .seg,.modal .seg{display:flex;gap:6px;margin:6px 0 12px}
.placeholder .seg button,.modal .seg button{padding:6px 14px;border:1px solid var(--grid);background:#fff;border-radius:5px;cursor:pointer;font-size:12px}
.placeholder .seg button.on{background:#1f6feb;color:#fff;border-color:#1f6feb;font-weight:bold}
.placeholder.utmwrap{padding:16px 22px}
table.utm{table-layout:fixed;width:100%}
table.utm col.c-label{width:300px}
table.utm col.c-act{width:130px}
table.utm td{padding:5px 8px;border-color:#e3e6ea;vertical-align:middle}
td.utm-label{text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#111}
td.utm-url{text-align:left;overflow:hidden}
.utm-url-in{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#1f6feb}
td.utm-act{text-align:right;white-space:nowrap}
tr.utm-row:hover td{background:#f3f7ff}
button.copy{padding:3px 10px;border:1px solid var(--grid);background:#f7f8fa;border-radius:4px;cursor:pointer;font-size:11px}
button.copy:hover{background:#eef2f7}
.utmgen{display:flex;flex-direction:column;gap:6px;max-width:640px;border:1px solid var(--grid);border-radius:6px;padding:12px;background:#fafbfc}
.utmgen label{font-size:11px;color:#555}
.utmgen input{width:100%;padding:6px 8px;border:1px solid var(--grid);border-radius:4px;font-size:12px;margin-top:2px}
.utmgen button{align-self:flex-start;padding:7px 18px;border:1px solid #1f6feb;background:#1f6feb;color:#fff;border-radius:5px;cursor:pointer}
.utmgen .gout{font-size:12px;margin-top:4px}
.cmpbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:12px}
.cmpbar input{padding:4px;border:1px solid var(--grid);border-radius:4px;font-size:11px}
.cmpbar button{padding:6px 16px;border:1px solid #1f6feb;background:#1f6feb;color:#fff;border-radius:5px;cursor:pointer}
table.cmp{table-layout:auto}
table.cmp th,table.cmp td{padding:5px 14px}
table.cmp tr.grp-top td{border-top:2px solid #888}
.up{color:#1a7f37;font-weight:bold}
.down{color:#c0392b;font-weight:bold}

/* Фаза 1: всплывающие подсказки */
#tip{position:fixed;z-index:100;max-width:340px;background:#1f2530;color:#fff;font-size:14px;line-height:1.4;padding:8px 12px;border-radius:6px;box-shadow:0 6px 18px rgba(0,0,0,.28);pointer-events:none;opacity:0;display:none;transition:opacity .12s}
[data-tip]{cursor:help}
.pbtn[data-tip]{cursor:pointer}
/* #46 (владелец 23.09: «курсор pointer как при наведении на другие кнопки»): у кнопок с подсказкой — указатель, а не вопрос;
   вопрос остается у заголовков таблицы (подсказка там — толкование столбца) */
button[data-tip],button [data-tip]{cursor:pointer}
thead tr.met th[data-tip]{cursor:help}

/* Фаза 1: меню видимости столбцов */
#cv_list{columns:2;column-gap:18px;font-size:12px}
#cv_list input{width:auto;margin-right:5px}
/* модалка столбцов: чекбоксы сгруппированы по группам (видно к какому разделу относится) */
.cvgrp{break-inside:avoid;margin-bottom:10px;border:1px solid #dfe3ea;border-radius:6px;overflow:hidden}
.cvgrp-h{padding:4px 8px;font-size:11.5px;display:flex;align-items:center;gap:6px;justify-content:space-between;border-bottom:1px solid rgba(0,0,0,.12)}
.cvgrp-h label{display:flex;align-items:center;gap:5px;margin:0;cursor:pointer}
.cvcol{display:block;padding:2px 8px 2px 24px;cursor:pointer}

/* Фаза 4: вкладка Посевы — KPI-карточки + бар-чарт */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;max-width:900px}
.kpi{border:1px solid var(--grid);border-radius:8px;padding:12px 14px;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.05)}
.kpi-v{font-size:20px;font-weight:bold;line-height:1.1}
.kpi-l{font-size:11px;color:#777;margin-top:5px;text-transform:uppercase;letter-spacing:.3px}
.kpi.good .kpi-v{color:#1a7f37}
.kpi.bad .kpi-v{color:#c0392b}
.seedchart{display:flex;align-items:flex-end;gap:2px;height:140px;max-width:900px;border-bottom:1px solid var(--grid);padding-top:6px}
.seedchart .sbar{flex:1;min-width:2px;background:linear-gradient(#5b9bf6,#1f6feb);border-radius:2px 2px 0 0}
.seedchart .sbar:hover{filter:brightness(1.18)}

/* Фаза 5 #6: глоссарий толкований колонок */
dl.docs{font-size:12px;margin:0}
dl.docs dt{font-weight:bold;margin-top:10px;color:#111}
dl.docs dd{color:#555;margin:2px 0 0;line-height:1.4}

/* Фаза C: авторизация, история, пользователи */
/* значок роли в шапке (15.09.2026, вариант 2): цвет по роли, подсказка — data-tip */
.rolebadge{display:inline-block;padding:1px 8px;border:1px solid;border-radius:10px;font-size:11px;font-weight:600;line-height:16px}
.rolebadge.role-viewer{background:#eef0f3;color:#4a5160;border-color:#d3d8e0}
.rolebadge.role-editor{background:#e7f0ff;color:#1d5bbf;border-color:#b8d0f5}
.rolebadge.role-admin{background:#fff1df;color:#9a5300;border-color:#f0c995}
.rolebadge.role-other{background:#f4f4f4;color:#555;border-color:#ddd}
#loginbox{position:fixed;inset:0;z-index:200;display:none;align-items:center;justify-content:center;background:linear-gradient(135deg,#1f3a5f,#2c5282)}
#loginform{background:#fff;border-radius:12px;padding:32px 34px;width:320px;box-shadow:0 18px 50px rgba(0,0,0,.35);display:flex;flex-direction:column;gap:10px}
#loginform .li-logo{font-size:18px;font-weight:bold}
#loginform .li-sub{font-size:12px;color:#777;margin-bottom:10px}
#loginform input{padding:9px 11px;border:1px solid var(--grid);border-radius:6px;font-size:13px}
#loginform button{margin-top:6px;padding:10px;border:0;background:#1f6feb;color:#fff;border-radius:6px;font-size:14px;font-weight:bold;cursor:pointer}
#loginform button:hover{background:#1a5fcc}
#loginform .li-err{color:#c0392b;font-size:12px;min-height:14px}
#users_list table{width:100%;border-collapse:collapse}
#users_list td{padding:4px 6px;border-bottom:1px solid var(--grid);text-align:left}
#users_list select,#users_list button{font-size:11px;padding:2px 6px}
#hist_list table{width:100%;border-collapse:collapse}
#hist_list td{padding:3px 6px;border-bottom:1px solid #eee;text-align:left}
#hist_list tr.undone td{color:#aaa;text-decoration:line-through}
.modal{position:relative}
.modal-x{position:absolute;top:8px;right:10px;width:30px;height:30px;border:0;background:transparent;font-size:24px;line-height:1;color:#888;cursor:pointer;border-radius:6px;z-index:2}
.modal-x:hover{background:#eee;color:#111}
/* Лог сверки (несоответствия синка) */
table.conf{width:100%;border-collapse:collapse;font-size:11px}
table.conf th,table.conf td{border:1px solid var(--grid);padding:4px 7px;text-align:left}
table.conf th{background:#eef3fb}
table.conf tr.k1 td{background:#fff7e6}
table.conf tr.k2 td{background:#eaf2ff}
table.conf tr.ack td{background:#eef9f0;color:#8a8a8a}
/* 2026-07-08 (_01): модалки «История правок» / «Лог сверки» — отменяем глобальную обрезку ячеек
   (стр.18 th,td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}) и разрешаем перенос,
   чтобы «лист·дата», «колонка», «было → стало», «кто» не резались под «…». Скоуп — только эти окна. */
#histmodal .modal{width:720px;max-width:92vw}
#conflictmodal .modal{max-width:92vw}
#hist_list th,#hist_list td,
table.conf th,table.conf td{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:break-word;height:auto;vertical-align:top;text-align:left}
/* 21.09.2026 (_02): подпись кампании под названием блока; переключатель «только активные за период» */
thead tr.grp th .bid{font-size:10px;font-weight:normal;opacity:.8;line-height:1.1;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rkseg{display:flex;gap:3px;margin:2px 0 6px}
.rkseg button{flex:1;padding:4px 2px;border:1px solid var(--grid);background:#fff;border-radius:4px;cursor:pointer;font-size:11px}
.rkseg button.on{background:#1f6feb;color:#fff;border-color:#1f6feb;font-weight:bold}

/* 22.09.2026 (_06): окно «Пользователи» — шире и со своими правилами таблицы: общие правила листа (fixed-раскладка, закрепленный
   первый столбец 168 px с толстой чертой, обрезание «…», закрепленная шапка) сжимали столбцы (владелец: «слишком мало ужаты»). */
#usermodal .modal{width:min(1040px,96vw)}
.utable{width:100%;table-layout:auto;border-collapse:collapse;margin-bottom:6px}
.utable th,.utable td,.utable tbody td:first-child,.utable thead th:first-child{position:static;width:auto;min-width:0;max-width:none;
  height:auto;padding:7px 8px;border:0;border-bottom:1px solid var(--grid);white-space:nowrap;overflow:visible;text-overflow:clip;
  text-align:left;vertical-align:middle;font-size:13px;font-weight:normal;background:none;line-height:1.3}
.utable thead th,.utable thead th:first-child{font-size:12px;font-weight:bold;color:#555;border-bottom:2px solid var(--grid)}
.utable tbody td:first-child{font-weight:bold}
.utable tbody tr:hover td{box-shadow:none;background:#f6f8fa}
.utable tr.u-off td{color:#999}
.utable .u-name{width:100%;min-width:200px;box-sizing:border-box;padding:4px 6px;font-size:13px}
.utable select{padding:3px 4px;font-size:13px}
.utable td.u-actions{text-align:right}
.utable td.u-actions button{margin-left:4px;padding:3px 8px;font-size:12px;cursor:pointer}
.nu-passrow{display:flex;gap:6px;align-items:center}
.nu-passrow input{flex:1;font-family:monospace}
.nu-passrow button{padding:5px 10px;cursor:pointer;white-space:nowrap}

/* ───────── #46 (23.09.2026): шапка и меню по макету (import/redant-dashboard-mockups/WB.dc.html, стили — как есть).
   Имена .seg, .grp, .dot на странице уже заняты (переключатели «Баннеров», строка шапки таблицы, точки каналов) — поэтому
   правила макета ограничены шапкой (.bar1, .bar2) и меню (.menu). ───────── */
.bar1 button,.bar2 button,.menu button{font:inherit;color:inherit}
.bar1 button:focus-visible,.bar2 button:focus-visible,.menu button:focus-visible,.menu input:focus-visible{outline:2px solid #1f4fb8;outline-offset:1px}
.bar1{height:52px;flex-shrink:0;display:flex;align-items:center;gap:12px;padding:0 16px;background:#ffffff;border-bottom:1px solid #e4e4df;position:relative;z-index:30}
.bar2{height:48px;flex-shrink:0;display:flex;align-items:center;gap:18px;padding:0 16px;background:#fafaf8;border-bottom:1px solid #e0e0da;position:relative;z-index:29}
.bar1 .title{display:flex;align-items:center;gap:10px;font-weight:600;font-size:15px;white-space:nowrap;margin-right:8px}
.bar1 .logo{display:flex;align-items:center}
.bar1 .logo img{height:30px;width:auto;display:block}
.bar1 .spacer,.bar2 .spacer{flex-grow:1}
.bar1 .seg,.bar2 .seg,.menu .seg{display:flex;padding:2px;background:#ebebe6;border-radius:7px;gap:2px;position:relative}
/* #46 порция 4 (README «Плавное переключение сегментов»): все кнопки сегмента толщины 500 — активная отличается только цветом, иначе ширина
   меняется и соседи дергаются; белая плашка — отдельный .seg-thumb (ставит app.js segThumb), у кнопки фона нет */
.seg-b{display:inline-flex;align-items:center;gap:6px;border:0;background:transparent;height:28px;padding:0 12px;border-radius:5px;font-size:13px;font-weight:500;color:#4a4e55;cursor:pointer;white-space:nowrap;position:relative;z-index:1;transition:color .2s}
.seg-b:hover{color:#1c1e22}
.seg-b.active,.seg-b.on{background:#ffffff;color:#1c1e22;font-weight:500;box-shadow:0 1px 2px rgba(0,0,0,.14)}
.seg.has-thumb .seg-b.active,.seg.has-thumb .seg-b.on{background:transparent;box-shadow:none}
.bar1 .seg-b,.bar2 .seg-b,.menu .seg-b{font-weight:500}   /* перебивает .bar1 button{font:inherit} (там 400) — у всех кнопок сегмента 500 */
/* 02.10.2026 (TODO #82, владелец: «нет анимации при наведении на кнопки листов»): цвет текста — так же, как толщина строкой выше.
   .bar1/.bar2/.menu button{color:inherit} (вес 0,1,1) перебивал .seg-b{color:#4a4e55} (0,1,0): невыбранные кнопки всех сегментов (листы,
   «Группировка», год в «Периоде», «Артикулы / Склейки / Склад») были черными, как при наведении, — наведение ничего не меняло. Теперь как
   в макете (WB.dc.html; README «Плавное переключение сегментов»): невыбранная #4a4e55, наведение и выбранная #1c1e22, смена цвета 0,2 с
   (переход — у .seg-b выше; «меньше движения» — без перехода). Неактивная «Товаров» (#prodseg .seg-b[disabled], вес 1,2,0) — серая, как была */
.bar1 .seg-b,.bar2 .seg-b,.menu .seg-b{color:#4a4e55}
.bar1 .seg-b:hover,.bar2 .seg-b:hover,.menu .seg-b:hover,.bar1 .seg-b.active,.bar2 .seg-b.active,.menu .seg-b.active,.bar1 .seg-b.on,.bar2 .seg-b.on,.menu .seg-b.on{color:#1c1e22}
.seg-thumb{position:absolute;top:2px;left:0;bottom:2px;width:0;background:#ffffff;border-radius:5px;box-shadow:0 1px 2px rgba(0,0,0,.14);opacity:0;pointer-events:none;transition:transform .24s cubic-bezier(.3,.7,.2,1),width .24s cubic-bezier(.3,.7,.2,1),opacity .15s}
@media (prefers-reduced-motion: reduce){.seg-thumb,.seg-b{transition:none}}
.seg.sm .seg-b{height:26px;padding:0 10px;font-size:12.5px}
.btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 10px;border:1px solid #d6d6d0;background:#ffffff;border-radius:6px;cursor:pointer;white-space:nowrap;font-size:13px}
.btn:hover{background:#f3f3ef}
.dd.open > .btn,.btn.on{border-color:transparent;box-shadow:0 0 0 2px rgba(31,79,184,.15)}   /* 24.09.2026 (#46, макет 3-й версии, README «Открытая кнопка с меню»): рамка прозрачная, только кольцо — как у «Еще» и аккаунта; было #1f4fb8 — резче */
/* 28.09.2026 (TODO #60): «Внутр. трафик ▾» — кнопка сегмента листов (.seg-b), не .btn; README «Открытая кнопка с меню» — кольцо у всех
   кнопок с меню, «включая внутренний трафик» — то же кольцо и у нее. */
.dd.open > .seg-b{box-shadow:0 0 0 2px rgba(31,79,184,.15)}
.btn.ib{width:32px;padding:0;justify-content:center}
.btn.ghost{border-color:transparent;background:transparent}
.btn.ghost:hover{background:#f0f0ec}
.btn[disabled]{color:#b3b5b9;cursor:default;background:transparent}
.btn.xl svg{color:#1d7a45}
.btn.primary{align-self:flex-end;background:#1f4fb8;border-color:#1f4fb8;color:#ffffff}
.btn.primary:not([disabled]):hover{background:#2f61cc;border-color:#2f61cc}   /* 24.09.2026 (#46, вариант Б): светлее; было темнее #163a88 — почти незаметно */
/* ───────── 24.09.2026 (#46, макет 2-й версии — README «Кнопки: наведение и нажатие», Buttons.dc.html, выбран вариант Б): у всех кнопок
   сайта наведение плавное 0,14 с, нажатие мгновенное (иначе клик «ватный»); белая при наведении — фон #f3f3ef и рамка #c9c9c3, без рамки —
   фон #f0f0ec, нажата — #ebebe6; синяя — #1f4fb8 → наведение #2f61cc (светлее) → нажата #173c8c. Неактивные не реагируют (раньше неактивная
   «Вернуть» подсвечивалась). Наш класс синей — .primary (у дизайнера .pri). Кнопки окон, входа, «Карты меток» и «Сравнения» — не .btn:
   их вид в restyle.css с !important (перебивает встроенный style="…"), там же их наведение (исключает :active) — нажатие здесь. ───────── */
.btn,.modal .actions button,#mapload,.modal .seg button,#cv_save,#note_save,#ue_save,#drrsave,#utmupload,#loginform button,button.copy,.utmgen button,.cmpbar button,.modal-x{
  transition:background-color .14s ease-out,border-color .14s ease-out,box-shadow .14s ease-out,color .14s ease-out}
/* рамка при наведении — через :where() (специфичность одного :hover), чтобы не перебивать рамку открытой кнопки (.dd.open > .btn, .btn.on) */
:where(.btn:not([disabled]):not(.ghost)):hover{border-color:#c9c9c3}
.btn:not([disabled]):not(.primary):active{background:#ebebe6;transition-duration:0s}
.btn.primary:not([disabled]):active{background:#173c8c;border-color:#173c8c;transition-duration:0s}
.btn.ghost[disabled]:hover{background:transparent}
.modal .actions button:not([disabled]):active,#mapload:not([disabled]):active,.modal .seg button:not([disabled]):active,button.copy:not([disabled]):active{
  background:#ebebe6 !important;border-color:#c9c9c3 !important;transition-duration:0s}
#cv_save:not([disabled]):active,#note_save:not([disabled]):active,#ue_save:not([disabled]):active,#drrsave:not([disabled]):active,#utmupload:not([disabled]):active,
#loginform button:not([disabled]):active,.utmgen button:not(.copy):not([disabled]):active,.cmpbar button:not([disabled]):active{
  background:#173c8c !important;border-color:#173c8c !important;transition-duration:0s}
.modal-x:not([disabled]):active{background:#ebebe6;transition-duration:0s}   /* крестик окна — как кнопка без рамки */
@media (prefers-reduced-motion: reduce){
  .btn,.modal .actions button,#mapload,.modal .seg button,#cv_save,#note_save,#ue_save,#drrsave,#utmupload,#loginform button,button.copy,.utmgen button,.cmpbar button,.modal-x{transition:none}}
.bar2 .lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:#6f737a;font-weight:600;margin-right:8px;white-space:nowrap}
.bar2 .grp{display:flex;align-items:center;gap:6px}
.bar1 .sync{display:flex;align-items:center;gap:6px;color:#5a5e65;font-size:12.5px;white-space:nowrap;cursor:default}
.bar1 .sync i{width:7px;height:7px;border-radius:50%;background:#2e9e5b;display:block;flex-shrink:0}
.bar1 .vsep,.bar2 .vsep{width:1px;height:24px;background:#e2e2dc;flex-shrink:0;display:block}
/* 06.10.2026 «шапка 06.10»: ↶ ↷ — во второй строке (макет HeaderUnit: группа через 6 px), прижаты вправо вместо «Столбцов» */
.bar2 .histctl{display:flex;align-items:center;gap:6px;margin-left:auto;flex-shrink:0}
.bar2 .histctl ~ #colsbtn{margin-left:0}
.bar2 #wbfsep,.bar2 #wbfunbtn{flex-shrink:0}
body.ro-noact #histctl,body.ro-noact #wbfsep,body.ro-noact #wbfunbtn{display:none}body.ro-noact .bar2 #colsbtn{margin-left:auto}   /* зрителю без ↶ ↷ и «Показов WB» — app.js HDR_VIEWER_HIDE_ACT */
.muted{color:#6f737a;font-weight:400}
.tnum{font-variant-numeric:tabular-nums}
.bar1 .dot,.menu .dot{width:9px;height:9px;border-radius:50%;display:block;flex-shrink:0}
.bar1 .dot[hidden]{display:none}   /* скрытая точка «Внутр. трафик» не должна занимать место (display:block выше перебивал hidden) */
.dd{position:relative}
.dd > .menu{display:none}
.dd.open > .menu{display:block}
.menu{position:absolute;top:calc(100% + 6px);left:0;background:#ffffff;border:1px solid #d9d9d3;border-radius:8px;box-shadow:0 10px 30px rgba(20,20,19,.16);padding:6px;z-index:40;min-width:230px}
.menu.right{left:auto;right:0}
/* #46 порция 4 (README «Появление выпадающих меню»): opacity 0→1 и сдвиг -4 px → 0 за 0,16 с; конечный кадр = обычный стиль меню
   (translateY(0), не none — иначе в последнем кадре текст прыгает на полпикселя); закрытие мгновенное (display:none) */
.menu{transform:translateY(0);animation:menuIn .16s cubic-bezier(.2,.8,.3,1) both}
@keyframes menuIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion: reduce){.menu{animation:none}}
/* 28.09.2026 (владелец: «все меню плавно сделай»): закрытие — как у меню «Столбцы» (#colmenu.closing): 0,12 с, opacity 1→0 и сдвиг
   0→-4 px; класс .closing на обертке .dd ставит и снимает app.js (hideDd). Щелчки сквозь уходящее меню проходят (pointer-events:none). */
.dd.closing > .menu{display:block;animation:menuOut .12s cubic-bezier(.4,0,1,1) both;pointer-events:none}
/* раскладка уходящего меню — как у открытого: у «Периода» (grid) и «Каналов» (flex) она задана через .dd.open, поэтому рядом с
   ними — .dd.closing (владелец 28.09 после выкладки: «при закрытии окна с периодом, карточка перед исчезновением становится больше») */
@keyframes menuOut{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-4px)}}
@media (prefers-reduced-motion: reduce){.dd.closing > .menu{display:none;animation:none}}
/* #46 порция 4 (README «Плавная смена листа»): старая таблица гаснет за 0,12 с, новая проявляется за 0,18 с со сдвигом 4 px снизу; вбок —
   нет. Данные дольше 150 мс — каркас листа с бликом (23.10.2026, grid.css; было — серые полосы #eeeeea на месте строк) */
.tablewrap.sw-leave{opacity:0;transition:opacity .12s linear}
.tablewrap.sw-enter{animation:swEnter .18s cubic-bezier(.2,.8,.3,1) both}
@keyframes swEnter{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion: reduce){.tablewrap.sw-leave{transition:none}.tablewrap.sw-enter{animation:none}}
/* [SUPERSEDED 2026-10-23: серые полосы во всю ширину (.sw-skel .sk-hd / .sk-r) — вместо них каркас листа той же сеткой (grid.js, grid.css .sk /
   .glint; README макетов «Загрузка таблицы: каркас с бликом»). Класс .sw-skel теперь у корня каркаса .gt] */
.mh{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:#6f737a;font-weight:600;padding:8px 10px 4px}
.mi{display:flex;align-items:center;gap:8px;width:100%;height:32px;padding:0 10px;border:0;background:transparent;border-radius:5px;text-align:left;cursor:pointer;font-size:13px;white-space:nowrap}
.mi:hover{background:#f2f2ee}
.mi.active,.mi.on{background:#eaf0fb;color:#173c8c;font-weight:600}
.mi svg{color:#6f737a;flex-shrink:0}
/* 24.09.2026 (#46, макет 3-й версии, README «Меню аккаунта: иконки и наведение», снимок 06b): пункты меню — плавно 0,12 с (фон и цвет);
   «Админка» (.adm) при наведении оранжевая, как метка роли admin; «Выйти» (.danger) — красная, значок цвета текста. .mi.danger с цветом —
   потому что .menu button{color:inherit} (0,1,1) перебивал .danger (0,1,0): «Выйти» была черной (замер 24.09: rgb(28,30,34)) */
.mi{transition:background-color .12s ease-out,color .12s ease-out}
.mi svg{transition:color .12s ease-out}
.mi.adm:hover{background:#fdf1e6;color:#8a4210}
.mi.adm:hover svg{color:#b35a17}
.mi.danger{color:#a8231b}
.mi.danger svg{color:currentColor}
.mi.danger:hover{background:#fdecea;color:#8c1d15}
@media (prefers-reduced-motion: reduce){.mi,.mi svg{transition:none}}
.msep{height:1px;background:#ebebe6;margin:6px 4px}
.badge{margin-left:auto;font-size:11px;background:#fbe6d4;color:#8a4210;border-radius:9px;padding:1px 7px;font-weight:600}
.danger{color:#a8231b}
.sw{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;white-space:nowrap;position:relative;border:0;background:transparent;padding:0}
.track{width:30px;height:18px;border-radius:9px;background:#c9c9c3;position:relative;transition:background .15s;flex-shrink:0}
.track::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#ffffff;transition:left .15s;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.sw.active .track{background:#1f4fb8}
.sw.active .track::after{left:14px}
.sw:focus-visible .track{outline:2px solid #1f4fb8;outline-offset:2px}
.field{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:#6f737a;flex:1 1 0;min-width:0}
.field input{width:100%;min-width:0;box-sizing:border-box;height:30px;border:1px solid #d6d6d0;border-radius:5px;padding:0 8px;font:inherit;font-size:13px;color:#1c1e22}
.stack{display:inline-flex}
.stack i{width:10px;height:10px;border-radius:50%;border:1.5px solid #ffffff;margin-left:-4px;display:block}
.stack i:first-child{margin-left:0}
/* ───────── 06.10.2026 «Период» (макет PeriodMenu.dc.html, README дизайнера «Период: кнопка и меню» §1–3, снимки 51): меню 380 px одной
   колонкой — «Год» (сегмент по ширине подписей, прижат влево, 6 px от края меню) · «Быстрый выбор» сеткой 2 × 4 (ячейки одной ширины,
   порядок сверху вниз по колонкам, как на сайте) · «Свой диапазон» одной строкой: поля, «Применить», строка ошибки и свой календарь —
   10 px от края меню (padding 0 4px внутри padding 6px меню). Было: 500 px в две колонки (быстрый выбор слева, год и поля справа). Если меню
   с открытым календарем не помещается по высоте окна — прокрутка внутри (max-height ставит app.js periodFit). ───────── */
.periodmenu{width:380px}
.periodmenu .pm-yr{padding:0 0 4px}
.periodmenu .pm-yr .seg{display:inline-flex;vertical-align:top}
.periodmenu .pm-yr .seg-b{flex:none}
.periodmenu .pm-grid{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:repeat(4,32px);grid-auto-flow:column;gap:2px}
.periodmenu .pm-rng{display:flex;align-items:center;gap:6px;padding:0 4px 4px}
.periodmenu .pm-dash{flex:none;width:8px;text-align:center;color:#8a8e95;font-size:13px}
.periodmenu .pm-rng .btn.primary{margin-left:2px;align-self:auto;font-weight:500;padding:0 14px}
.periodmenu .btn.primary[disabled]{background:#c9d3ea;border-color:#c9d3ea;color:#ffffff;cursor:default}   /* 07.10.2026: #c9d3ea, как в окне заметок (ответ дизайнера 07.10: один цвет неактивной синей кнопки на сайте); было #a9b9de */
/* поля дат — как поле окна заметок (.nd-ta): рамка #d6d6d0, наведение #c9c9c3, фокус — синяя рамка и кольцо; «активное» поле (выбирается
   этот конец в календаре, .on) держит синюю рамку и без фокуса; ошибка — красная рамка */
.periodmenu .pm-in{flex:1 1 0;width:100%;min-width:0;height:32px;border:1px solid #d6d6d0;border-radius:5px;padding:0 8px;font:inherit;font-size:13px;color:#1c1e22;
  font-variant-numeric:tabular-nums;background:#ffffff;outline:none;transition:border-color .14s ease-out,box-shadow .14s ease-out}
.periodmenu .pm-in::placeholder{color:#9a9ea5}
.periodmenu .pm-in:hover{border-color:#c9c9c3}
.periodmenu .pm-in:focus,.periodmenu .pm-in.on{border-color:#1f4fb8;box-shadow:0 0 0 2px rgba(31,79,184,.15)}
.periodmenu .pm-in:focus-visible{outline:none}
.periodmenu .pm-in.err,.periodmenu .pm-in.err:focus{border-color:#c0392b;box-shadow:0 0 0 .5px #c0392b}
.periodmenu .pm-err{margin:4px;display:flex;gap:6px;align-items:flex-start;font-size:12.5px;line-height:18px;color:#a3261c}
.periodmenu .pm-err[hidden]{display:none}
.periodmenu .pm-err svg{margin-top:2px;flex-shrink:0}
/* свой календарь: раскрытие — высота 0 → своя за 0,24 с и прозрачность за 0,16 с (ставит app.js periodCalOpen; как раскрытие строк) */
.periodmenu .pm-calw{overflow:hidden;height:0;opacity:0}
.pcal{padding:8px 4px 2px}
.pcal-h{display:flex;align-items:center;justify-content:space-between;height:32px;margin:0 0 2px}
.pcal-h b{font-size:13px;font-weight:600}
.pcal-h .btn:not([disabled]){color:#4a4e55}   /* неактивная стрелка — серая, как .btn[disabled] (в макете правило шло после и перебивало ее) */
.pcal-w{display:grid;grid-template-columns:repeat(7,1fr);font-size:11px;line-height:20px;color:#8a8e95;text-align:center}
.pcal-w .we{color:#b4473f}
.pcal-g{display:grid;grid-template-columns:repeat(7,1fr);row-gap:2px;padding-bottom:2px}
/* день: обычный · чужой месяц (.out, можно выбрать) · сегодня (.tdy) · недоступный (после сегодня и до начала данных) · начало (.s) и конец (.e)
   синие, скругление только с внешней стороны · между ними полоса (.in) · предпросмотр, пока выбирается конец (.pv), день под курсором (.h) */
.pcal-g .pcd{height:32px;border:0;background:transparent;font:inherit;font-size:13px;font-variant-numeric:tabular-nums;color:#1c1e22;cursor:pointer;border-radius:5px;
  padding:0;transition:background-color .12s ease-out,color .12s ease-out}
.pcal-g .pcd:hover{background:#f2f2ee}
.pcal-g .pcd.out{color:#9a9ea5}
.pcal-g .pcd.tdy{box-shadow:inset 0 0 0 1px #c9c9c3;font-weight:600}
.pcal-g .pcd[disabled],.pcal-g .pcd[disabled]:hover{color:#c9c9c3;cursor:default;background:transparent}
.pcal-g .pcd.in{border-radius:0;background:#eaf0fb;color:#173c8c}
.pcal-g .pcd.in:hover{background:#dde7f8}
.pcal-g .pcd.pv{border-radius:0;background:#f2f2ee}
.pcal-g .pcd.s,.pcal-g .pcd.e{background:#1f4fb8;color:#ffffff;font-weight:600}
.pcal-g .pcd.s:hover,.pcal-g .pcd.e:hover{background:#2f61cc}
.pcal-g .pcd.s{border-radius:5px}
.pcal-g .pcd.s.r{border-radius:5px 0 0 5px}
.pcal-g .pcd.e{border-radius:0 5px 5px 0}
.pcal-g .pcd.s.e{border-radius:5px}
.pcal-g .pcd.h{border-radius:0 5px 5px 0;background:#f2f2ee;box-shadow:inset 0 0 0 1px #1f4fb8}
.pcal-g .pcd:focus-visible{outline:2px solid #1f4fb8;outline-offset:-2px}
/* смена месяца — сетка появляется за 0,16 с со сдвигом 12 px со стороны стрелки (--dx ставит app.js) */
.pcal-g.ga{animation:pcalA .16s cubic-bezier(.2,.8,.3,1) both}
.pcal-g.gb{animation:pcalB .16s cubic-bezier(.2,.8,.3,1) both}
@keyframes pcalA{from{opacity:0;transform:translateX(var(--dx,0))}to{opacity:1;transform:translateX(0)}}
@keyframes pcalB{from{opacity:0;transform:translateX(var(--dx,0))}to{opacity:1;transform:translateX(0)}}
@media (prefers-reduced-motion: reduce){.pcal-g.ga,.pcal-g.gb{animation:none}.periodmenu .pm-calw,.periodmenu .pm-in,.pcal-g .pcd{transition:none !important}}
/* кнопка «Каналы»: подкрашена, если выбрано не все (.flt), янтарная — «Блоки не выбраны» (.none); #55, макет Channels.dc.html */
.chanbtn{min-width:160px;max-width:260px;flex-shrink:1;justify-content:flex-start}
.chanbtn.flt{background:#eaf0fb;border-color:#c9d6f0;color:#173c8c}
.chanbtn.flt:hover{background:#e0e9f8;border-color:#b9c9ec}
.chanbtn.flt .muted{color:#4a6bb0}
.chanbtn.flt .stack i{border-color:#eaf0fb}
.chanbtn.none{color:#8a4b0a;background:#fff4e5;border-color:#f0d49a}
.chanbtn.none:hover{background:#ffeed6;border-color:#e8c57f}
.chanbtn > svg:last-child{color:#6f737a;flex-shrink:0}
.chanbtn .muted{font-variant-numeric:tabular-nums}
/* «Столбцы» прижаты вправо отступом, а не пустой вставкой: у вставки промежуток .bar2 (18 px) считался с двух сторон —
   вторая строка на 1536 px выходила за экран на 11 px (замер 23.09, выбран период с датами) */
#colsbtn{margin-left:auto}
/* 24.09.2026: число «N из M» приходит с листом — до того место под него держит невидимый образец, кнопка не растет рывком */
#colcnt:empty::before{content:'000 из 000';visibility:hidden}
.chanbtn .chanlbl{flex-grow:1;text-align:left;overflow:hidden;text-overflow:ellipsis}
/* ───── #55 (24.09.2026): меню «Каналы» — 440 px, строки без заливки, флажки, поиск, переключатель, низ закреплены (Channels.dc.html) ───── */
.chanmenu{width:440px;padding:0;overflow:hidden}
.dd.open > .chanmenu,.dd.closing > .chanmenu{display:flex;flex-direction:column}
.chanmenu [hidden],.chanbtn [hidden]{display:none !important}
.chanmenu .cm-top{padding:8px 8px 6px;display:flex;flex-direction:column;gap:8px;border-bottom:1px solid #ebebe6}
.chanmenu .srch{position:relative;display:flex;align-items:center}
.chanmenu .srch > svg{position:absolute;left:9px;color:#8a8e95;pointer-events:none}
.chanmenu .srch input{width:100%;height:32px;border:1px solid #d6d6d0;border-radius:6px;padding:0 30px 0 32px;font:inherit;font-size:13px;color:#1c1e22;background:#ffffff;outline:none;transition:border-color .14s,box-shadow .14s}
.chanmenu .srch input::placeholder{color:#9a9ea5}
.chanmenu .srch input:focus,.chanmenu .srch input:focus-visible{border-color:#1f4fb8;box-shadow:0 0 0 2px rgba(31,79,184,.15);outline:none}
.chanmenu .srch .clr{position:absolute;right:4px;width:24px;height:24px;border:0;background:transparent;border-radius:4px;display:flex;align-items:center;justify-content:center;color:#8a8e95;cursor:pointer}
.chanmenu .srch .clr:hover{background:#f0f0ec;color:#1c1e22}
.chanmenu .cseg{display:flex;padding:2px;background:#efefeb;border-radius:6px}
.chanmenu .cseg button{flex:1 1 0;border:0;background:transparent;height:26px;border-radius:4px;font-size:12.5px;font-weight:500;color:#5a5e65;cursor:pointer;white-space:nowrap;transition:color .15s,background-color .15s}
.chanmenu .cseg button:hover{color:#1c1e22}
.chanmenu .cseg button.on{background:#ffffff;color:#1c1e22;box-shadow:0 1px 2px rgba(0,0,0,.12)}
.chanmenu .cseg button i{font-style:normal;color:#8a8e95;font-variant-numeric:tabular-nums;margin-left:4px}
.chanmenu .clist{overflow-y:auto;padding:4px;max-height:min(420px,calc(100vh - 260px));scroll-padding:4px}
.chanmenu .row{display:flex;align-items:flex-start;gap:9px;padding:6px 8px;border-radius:5px;cursor:pointer;position:relative;min-height:30px;user-select:none}
.chanmenu .row:hover,.chanmenu .row.act{background:#f2f2ee}
.chanmenu .row.act{box-shadow:inset 0 0 0 1px #d6d6d0}
.chanmenu .row.all{align-items:center;font-weight:500}
.chanmenu .row.all .cnt{margin-left:auto;color:#8a8e95;font-weight:400;font-variant-numeric:tabular-nums;font-size:12px}
.chanmenu .cb{position:relative;width:16px;height:16px;border-radius:4px;border:1.5px solid #b3b6bc;background:#ffffff;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#ffffff;transition:background-color .1s,border-color .1s}
.chanmenu .row.all .cb{margin-top:0}
.chanmenu .cb svg{position:absolute;opacity:0}
.chanmenu .cb.on,.chanmenu .cb.mix{background:#1f4fb8;border-color:#1f4fb8}
.chanmenu .cb.on svg.ck,.chanmenu .cb.mix svg.mx{opacity:1}
.chanmenu .main{min-width:0;flex:1 1 auto;display:flex;flex-direction:column;gap:1px}
.chanmenu .nm{font-size:13px;line-height:18px;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;word-break:break-word}
.chanmenu .meta{font-size:11.5px;line-height:16px;color:#7a7e85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.chanmenu .meta.hit{color:#33373d}
.chanmenu mark{background:#ffe38a;color:inherit;border-radius:2px;padding:0 1px}
.chanmenu .rt{position:relative;flex-shrink:0;display:flex;justify-content:flex-end;min-width:56px;height:18px}
.chanmenu .st{flex-shrink:0;display:flex;align-items:center;gap:5px;font-size:11.5px;line-height:18px;white-space:nowrap;color:#6f737a}
.chanmenu .st i{width:6px;height:6px;border-radius:50%;display:block;background:#b3b5b9}
.chanmenu .st.ok{color:#1d6b3f}.chanmenu .st.ok i{background:#2e9e5b}
.chanmenu .st.stop{color:#8a6d1a}.chanmenu .st.stop i{background:#e0a100}
.chanmenu .st.off{color:#8a8e95}
/* «Только этот» — ссылка в правом нижнем углу строки, под статусом; слева плавный переход в фон строки; появление — только opacity */
.chanmenu .only{position:absolute;right:6px;bottom:3px;height:22px;display:flex;align-items:center;padding:0 6px;border:0;border-radius:4px;background:#f2f2ee;font-size:12px;font-weight:500;color:#1f4fb8;cursor:pointer;opacity:0;pointer-events:none;transition:opacity .1s,color .12s;white-space:nowrap}
.chanmenu .only::before{content:"";position:absolute;right:100%;top:0;bottom:0;width:18px;background:linear-gradient(to right,rgba(242,242,238,0),#f2f2ee);pointer-events:none}
.chanmenu .row:hover .only,.chanmenu .row.act .only{opacity:1;pointer-events:auto}
.chanmenu .only:hover{color:#163a88;text-decoration:underline;text-underline-offset:2px}
.chanmenu .cempty{padding:28px 20px 30px;display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;color:#5a5e65;font-size:12.5px;line-height:1.45}
.chanmenu .cempty > svg{color:#b3b6bc}
.chanmenu .cempty b{color:#1c1e22;font-weight:600;font-size:13px;word-break:break-all}
.chanmenu .lnk{border:0;background:transparent;padding:0;color:#1f4fb8;cursor:pointer;font-size:12.5px;font-weight:500}
.chanmenu .lnk:hover{color:#163a88;text-decoration:underline}
.chanmenu .cm-f{display:flex;align-items:center;gap:8px;padding:8px 8px 8px 12px;border-top:1px solid #ebebe6;background:#fafaf8}
.chanmenu .cm-f .sel{font-size:12px;color:#5a5e65;font-variant-numeric:tabular-nums;flex-grow:1}
.chanmenu .btn.sm{height:28px;padding:0 10px;font-size:12.5px}
.chanmenu .btn.pri{background:#1f4fb8;border-color:#1f4fb8;color:#ffffff;font-weight:500}
.chanmenu .btn.pri:hover{background:#2f61cc;border-color:#2f61cc}
/* 28.09.2026 (TODO #60, сверка с README «Кнопки: наведение и нажатие»): «Готово» — синяя с классом .pri, а общее нажатие синей написано для
   .primary; без этого правила при нажатии кнопка оставалась цвета наведения #2f61cc (или серела под общим нажатием). Нажата — #173c8c. */
.chanmenu .btn.pri:not([disabled]):active{background:#173c8c;border-color:#173c8c;transition-duration:0s}
@media (prefers-reduced-motion: reduce){.chanmenu .cseg button,.chanmenu .cb,.chanmenu .only,.chanmenu .srch input{transition:none}}
.placeholder.chan-empty{color:#8a4b0a}
.bar1 .userlabel{white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis}

/* ───────── #46 (23.09.2026): шапка на узких экранах — макет HeaderWidths.dc.html и README дизайнера. Шаги накопительные, высота
   шапки везде 52 + 48 px, кнопки на местах, в меню ничего не переносится. Уже 1280 px дизайнер не прорабатывал. ───────── */
.bar1 .sync{max-width:280px;min-width:0}
.bar1 .sync #synctext{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
#accbtn{max-width:220px;min-width:0}
#accbtn svg,.bar2 .btn svg,.bar1 .btn svg{flex-shrink:0}
.seg-b svg{flex-shrink:0}   /* 24.09.2026 (#46, макет 3-й версии): стрелка «Внутр. трафик» — тоже значок внутри кнопки (README шапки: flex-shrink 0) */
.bar1 .userlabel,.bar1 .usershort{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.bar1 .usershort,.swl-short{display:none}
/* 25.09.2026 (владелец: «группировку сразу как на узких экранах… редкоиспользуемая функция»): на ВСЕХ ширинах — кнопка-список
   «Группировка: Все ▾» (#granfold, пояснение режимов — в ее подсказке); шесть кнопок #granularity скрыты, но остаются в разметке
   (общий обработчик выбора в initGranularity; тесты переключают через JS). Подпись «ГРУППИРОВКА» убрана — она на самой кнопке. */
#granularity{display:none}
/* 23.09.2026 (дизайнер, вариант 2): шапка меню аккаунта — имя 13 px полужирным, под ним серым «логин · роль» */
.acc-head{padding:7px 10px 3px;max-width:320px}
.acc-name{font-size:13px;font-weight:600;color:#1c1e22;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acc-sub,.acc-inl{font-size:12px;font-weight:400;color:#6f737a}
.acc-sub{margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acc-sub[hidden]{display:none}
/* 28.09.2026 (#58 п. 3, владелец: «Кнопка "Все" в селекторе группировка жирным шрифтом… в других селекторах она не жирным»):
   подпись «Группировка: Все» — обычным начертанием, как «Период» и «Каналы» (было #granlbl{font-weight:600}) */
/* ───────── 06.10.2026 «шапка 06.10» (макет HeaderUnit.dc.html, README дизайнера «Шапка: «Юнит-экономика» видна на всех ширинах» §2–5;
   владелец 06.10: «дизайнер может ошибаться, поэтому нужно проверять за ним» — пороги по замеру на сайте, таблица замера —
   docs/header/temp/agent_header_impl.md). Шаги — только по ширине окна, накопительные, одинаковые у всех ролей; посчитаны с «Помощником»,
   самой длинной подписью «Юнит-экономика» (открытый «Юнит WB» шапку не перестраивает) и самым длинным именем учетки, запас не меньше 16 px.
   Подпись → значок 32×32: подпись остается в aria-label и data-tip / title (как у «Помощника»). Страховки app.js fitHeader — только когда
   строка все равно не помещается: первая (необычно длинное имя учетки) — шаги первой строки раньше порога, последним — «Юнит-экономика»
   значком calculator (body.hwux); вторая (длинная подпись периода: свой диапазон, «все годы») — ее шаги раньше порога. Прежние шаги
   hw1–hw4, hwai, hwwb, hwun, hwunx сняты. */
/* [SUPERSEDED 2026-10-19] пороги первой строки 1595 / 1517 / 1418 / 1360 — по замеру 06.10 (макет: 1599 / 1535 / 1519 / 1429 / 1365):
   суперадмин, имя 115 px, «Озон медийка» (+12 px к «Внутр. трафик»): 1567 / 1489 / 1390 / 1332 / 1248 px + 12 + 16 запаса. Причина замены:
   замер 06.10 — со статусом «сбор прошел» (коротко «06:41»); не учтены полный статус на пределе (строки до 230 px: «Обновляю… N из M · шаг»,
   «Сбой: … · дата» — кнопка 264 px против 248) и длинный короткий («Обновляю…» 185 px, «с дд.мм» 159 против 149) — запас падал до 0,8 px.
   [CURRENT] 19.10.2026 (#140, владелец «1 - а»: шапка сворачивает подписи раньше, запас первой строки ≥ 16 px; замер на копии —
   docs/header/temp/agent_V.md): первая строка — суперадмин, имя «Ярослав» 115 px (и в «Правка … · имя»), «Озон медийка», худший статус:
   1595 / 1517 / 1438 / 1380 / 1296 px (состояния: без шагов / «Помощник» значком / + статус коротко / + «Еще» значком / + листы) + 15 → пороги
   1611 / 1533 / 1454 / 1396 (на «порог + 1» запас 16,8). Предел: со всеми шагами строка 1296 px («Обновляю…») / 1270 («с дд.мм») /
   1260 («чч:мм») — запас < 16 только там, где все шаги уже включены: 1280–1312 во время сбора кнопкой (на 1280–1296 не помещается —
   страховка hwux, «Юнит-экономика» значком, пока идет сбор), 1280–1286 — когда сбора не было > 30 ч; сбор прошел / сбой — ≥ 16 везде.
   Владелец 19.10 («1 да, 2 да»): пороги — эти («Еще» значком на 1440 — да); где включены все шаги первой строки — предел строки, запас < 16
   принят (только без переполнения; проверка test_header_unit.py judge — «предел строки: N px на W»).
   Вторая строка — «Последние 30 дней»: 1492 / 1361 / 1236 px + 16 (без изменений).
   Каждый шаг — правилом @media и тем же правилом с классом body.hs1…hs4 (первая строка) / hb1, hb2 (вторая): классы — страховка app.js
   fitHeader, включает шаги раньше порога, по порядку (тогда при сужении окна ничего не возвращается); последней — body.hwux. */
@media (max-width:1611px){#aibtn{width:32px;padding:0;justify-content:center}#aibtn .ai-lbl{display:none}}   /* «Помощник» — значок */
body.hs1 #aibtn{width:32px;padding:0;justify-content:center}body.hs1 #aibtn .ai-lbl{display:none}
@media (max-width:1533px){.bar1 #sync .two{display:none}.bar1 #sync .ico{display:flex}}   /* статус коротко: точка + cloud-download + время, pencil + время */
body.hs2 .bar1 #sync .two{display:none}body.hs2 .bar1 #sync .ico{display:flex}
@media (max-width:1454px){#morebtn{width:32px;padding:0;justify-content:center}#morebtn .more-lbl,#morebtn .more-chev{display:none}}   /* «Еще» — значок layout-grid */
body.hs3 #morebtn{width:32px;padding:0;justify-content:center}body.hs3 #morebtn .more-lbl,body.hs3 #morebtn .more-chev{display:none}
@media (max-width:1396px){#tabs .seg-b{padding:0 10px}#tabs #prodtab{padding:0 8px}#tabs #prodtab .pt-lbl{display:none}}   /* листы: отступы 12 → 10, «Товары» — значок package */
body.hs4 #tabs .seg-b{padding:0 10px}body.hs4 #tabs #prodtab{padding:0 8px}body.hs4 #tabs #prodtab .pt-lbl{display:none}
body.hwux #tabs #unitbtn{padding:0 8px}body.hwux #unitbtn .un-lbl,body.hwux #unitbtn .un-chev{display:none}body.hwux #unitbtn .un-ico{display:inline-block}   /* последний шаг — только по факту */
/* 07.10.2026 (_09, ответ дизайнера 07.10: «пороги второй строки — вернуть к макету 1535 / 1365; с короткой кнопкой периода места хватает»):
   вторая строка 1507 / 1376 → 1535 / 1365. Замер после короткой кнопки «Период» и «Выгрузки WB» (все листы × пресеты × годы × «Каналы»):
   худшая строка целиком 1465 px — подписи помещаются с запасом 16 px от 1481, без подписей 1334 — от 1350; проход 1280–1920 (шаг 8, у
   порогов 1 px) — нигде не вылезает, страховка hb1/hb2 не включается. Отчет — maintenance/stage_2026-10-07_09/temp/agent_icons.md. */
@media (max-width:1535px){.bar2 .lbl{display:none}}                          /* подписи «Период», «Каналы» (на «Товарах» — «Товары») */
body.hb1 .bar2 .lbl{display:none}
@media (max-width:1365px){
  .bar2 .swl-full{display:none}.bar2 .swl-short{display:inline}                                  /* «Только расход / ДРР» → «Расход / ДРР» */
  .bar2 #wbfunbtn{width:32px;padding:0;justify-content:center}.bar2 #wbfunbtn .wbf-lbl{display:none}   /* «Показы WB» — значок */
  .bar2 .chanbtn{max-width:210px}}   /* «Каналы» не шире 210 (как прежний шаг hw3; подпись длинного блока — с «…», полная — в меню и aria-label) */
body.hb2 .bar2 .swl-full{display:none}body.hb2 .bar2 .swl-short{display:inline}body.hb2 .bar2 .chanbtn{max-width:210px}
body.hb2 .bar2 #wbfunbtn{width:32px;padding:0;justify-content:center}body.hb2 .bar2 #wbfunbtn .wbf-lbl{display:none}
/* последняя страховка второй строки — «Каналы» не шире 160 (их наименьшая ширина): лист WB, свой диапазон · все годы, самый длинный блок —
   на 1280 строке не хватало 59 px (замер 06.10; кнопка «Каналы» на сайте не сжимается сама — ее группа держит ширину содержимого) */
body.hb3 .bar2 .chanbtn{max-width:160px}
