/* Cron-inspired dark theme: obsidian canvas, single ember accent, Helvetica Neue.
   Reference: DESIGN.md (Cron Calendar style). Functional severity tones for the
   live block are kept in the warm ember family to preserve the monochrome feel. */
:root {
  --ember: #ff4700;
  --ember-glow: #8b2e09;
  --ember-smoke: #451e0e;
  --obsidian: #0f0d0a;
  /* Роли, отщеплённые от --obsidian 10.08.2026. Он один нёс ПЯТЬ смыслов сразу — холст,
     «прорезь» разделителя отделов, текст на акцентной заливке, обводку марок графика и
     внутреннее кольцо фокуса. Пока они смешаны, светлую тему переопределить нельзя:
     любое значение ломает половину применений. Значения совпадают с --obsidian, поэтому
     в тёмной теме не меняется ни пиксель. */
  --on-accent: #0f0d0a;   /* тёмный текст на акцентной заливке (.cmp-run, .b2b-ag, .hp-*) */
  /* СВЕТЛЫЙ текст на акцентной заливке — у главной кнопки он белый, а не тёмный.
     Раньше она брала --bone, но в светлой теме --bone стал графитом, и получилось
     2.4:1 на голубой заливке. Роли пришлось развести: у «текста на акценте» их две. */
  --on-brand: var(--bone);
  --mark-ring: #0f0d0a;   /* обводка точки графика и кольцо фокуса — цвет ПОДЛОЖКИ под маркой */
  /* ~10% transparent so the background brand watermark faintly shows through blocks. */
  --graphite: rgba(22, 20, 18, 0.9);
  --graphite-2: rgba(29, 26, 23, 0.9);
  --ash: #cccccc;
  --ash-dim: #8a857f;
  /* Ступени приглушённого текста. Раньше того же добивались прозрачностью (7 разных
     значений от .45 до .78, расставленных по месту). На тёмном фоне opacity уводит текст
     к чёрному и падение контраста незаметно; на светлом уводило бы к белому и текст
     пропадал бы. Плюс семь ступеней, различимых на 6-9/255, — это не шкала, а разнобой.
     Значения выведены из фактических композитов, максимальный сдвиг 7/255 (2.7%). */
  --ink-soft: #9d9c9c;
  --ink-muted: #7e7d7c;
  --ink-faint: #6c6b69;
  /* Отдельная, более тёмная ступень: два правила приглушали не --ash, а --ash-dim, и их
     фактический композит был #4a4642. Свести их к --ink-faint значило бы сдвиг 39/255
     (15%) — это уже видно, поэтому ступень оставлена точной. */
  --ink-dim: #4a4642;
  /* Холодные статусы графика смен и сравнения периодов. Раньше жили литералами и в
     светлой теме остались бы прежними — на белом все три ниже 3:1. */
  --sched-off: #a9bed6;        /* выходной */
  --sched-vacation: #6fd4c6;   /* отпуск */
  --sched-sick: #e9c37e;       /* больничный */
  --period-1: #7cc6ff;         /* первый период в сравнении (второй — ember) */
  --toast-ok: #6fe0a4;         /* успешное сохранение */
  /* Тёмные концы градиентов полос: «цвет серии → его затемнение». Не отдельные цвета,
     а вторая точка одной марки — потому и названы через серию. */
  --series-leads-deep: #2c69b3;
  --series-conv-deep: #147b57;
  --series-revenue-deep: #ff7a40;
  --bone: #ffffff;
  --hairline: rgba(204, 204, 204, 0.14);
  --hairline-strong: rgba(204, 204, 204, 0.28);
  --font: 'Helvetica Neue', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Ember в разложенном виде: нужен, чтобы писать rgba(var(--ember-rgb), α)
     вместо повторения литерала 255,71,0 по всему файлу. Менять оттенок бренда
     теперь можно в двух строках, а не в сорока. */
  --ember-rgb: 255, 71, 0;

  /* Служебные цвета, которые РАНЬШЕ использовались через var(), но нигде не
     объявлялись: --blue вовсе без фолбэка (ссылки в таблицах не красились),
     --muted и --warn держались на фолбэке в месте применения. Значения взяты
     равными этим фолбэкам, кроме --blue: он выровнен на цвет серии «Лиды». */
  --blue: #3987e5;
  /* Цвет присутствия («на линии»). Выведен в токен, когда зелёный кружок заменили
     короной: до этого он жил литералом в четырёх местах. */
  --online: #3ddc84;
  --online-rgb: 61, 220, 132;
  /* Статусные цвета. Зарезервированы под состояние и никогда не идут «ещё одной серией»
     графика — см. DESIGN.md. Вынесены в токены ради тем: без этого светлая тема
     оставила бы их прежними. */
  --status-good: #3ddc84;
  --status-bad: #ff5a5a;
  --status-warn: #ffb74d;
  /* Осветляющая подложка. Один токен вместо 60 литералов rgba(255,255,255,α): тема
     меняет ЕГО, и все полупрозрачные поверхности переворачиваются разом. На светлой
     теме белый тинт был бы не виден вовсе — тут он станет чёрным. */
  --tint-rgb: 255, 255, 255;
  --muted: #8b93a7;
  --warn: #f0a132;

  /* ---- Цвета серий графиков ----
     Подобраны валидатором палитр (skill dataviz) под ТЁМНУЮ подложку панели
     #151311: полоса светлоты OKLCH L 0.48–0.67, насыщенность C ≥ 0.10,
     разделимость при дальтонизме и при полном зрении, контраст ≥ 3:1.
     Прежний набор проверку проваливал: #b39ddb читался серым (C=0.091), а
     синий с фиолетовым были неразличимы (ΔE 11.3 при пороге 15).
     ВАЖНО: тройка leads/revenue/conv проходит проверку по ВСЕМ парам — только
     её можно брать для воронок, где три бара видны одновременно. Полный набор
     из четырёх проходит по соседним парам; там синий несёт ещё и разную форму
     марки (бар против линии), что и разводит его с фиолетовым. */
  --series-leads: #3987e5;
  /* Тот же синий покомпонентно: бар лидов рисуется полупрозрачным, и проверять
     надо не сам цвет, а то, что получается НА подложке. Прежний бар при альфе
     0.30 давал композит #344858 — насыщенность 0.037 (то есть серое пятно) и
     контраст 1.95:1. При 0.75 композит #306ab0 проходит все проверки. */
  --series-leads-rgb: 57, 135, 229;
  --series-revenue: var(--ember);
  --series-conv: #199e70;
  --series-wins: #9085e9;
  --series-speed: #c98500;
  /* Второй период в сравнении. Отдельным токеном, потому что в светлой теме он не может
     совпадать с --ember: там оба периода оказались бы синими. Значение ЛИТЕРАЛОМ —
     compare.js читает его getPropertyValue, а тот не разворачивает var(). */
  --series-period-2: #ff4700;

  /* Soft rounding for container blocks (panels, cards, live/status blocks). */
  --radius-block: 10px;
  /* Шкала радиусов. Уровень --radius-inner существует отдельно от --radius-card
     не для красоты: это «карточка внутри борда». Слить их — значит потерять
     различие поверхностей, вложенный блок с тем же радиусом читается круглее
     родителя. */
  --radius-xs: 4px;
  --radius-ctl: 8px;
  --radius-inner: 12px;
  --radius-card: 14px;
  --radius-pill: 9999px;

  /* Шкала кеглей. Семь текстовых ступеней + четыре дисплейные. До введения
     шкалы в файле жило 25 значений, включая половинные (10.5/11.5/12.5/13.5) —
     их подкручивали руками под конкретные блоки. */
  --fs-micro: 10px;
  --fs-2xs: 11px;
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-md: 14px;
  --fs-lg: 15px;
  --fs-xl: 17px;
  --fs-2xl: 20px;
  --fs-3xl: 24px;
  --fs-4xl: 28px;
  --fs-5xl: 30px;

  /* Elevation в этой системе — только свечение, цвет один. Значение заметно
     крупнее базовой тени .btn-cta (0 0 24px 4px), иначе на наведении свечение
     сжималось бы вместо роста. */
  --glow-hover: 0 0 0 1px var(--ember-smoke), 0 0 30px 6px rgba(var(--ember-rgb), 0.45);
  /* Тесный вариант для компактных контролов: у .seg внутренний отступ 3px и
     зазор 2px между сегментами, широкое свечение затекало бы на соседей и лента
     переключателя читалась бы как один горящий блок. */
  --glow-hover-sm: 0 0 0 1px var(--ember-smoke), 0 0 14px 2px rgba(var(--ember-rgb), 0.40);

  /* Shared height for all top-bar controls (date field, icon button, menu)
     so they line up exactly. */
  --control-h: 40px;
}

/* Точка входа для тем. Токенов здесь пока нет — это подготовленный каркас:
   светлая тема переопределит --tint-rgb (белый тинт → чёрный), холст, текст и
   статусные цвета, а всё остальное подхватится само, потому что уже ходит через
   токены. Пустой блок оставлен намеренно: он фиксирует контракт «тема меняет
   ТОЛЬКО :root», чтобы следующий автор не начал раскидывать переопределения по файлу. */
:root[data-theme="ibrat-light"] {
  /* Светлая тема в фирменном стиле Айбрат. Значения и обоснования — THEME_IBRAT_REFERENCE.md.
     ПЕРВЫЙ ПРОХОД: переопределены только токены. Правила, которым нужна вторая рецептура
     (стекло, глубина, фоновые слои), пока работают по-тёмному — это видно и это ожидаемо. */

  /* Поверхности. Имена остались от тёмной темы: --obsidian здесь не «обсидиан», а ХОЛСТ. */
  --obsidian: #eef1f5;              /* холст страницы */
  /* СЕРОЕ стекло. Три редакции ушло на то, чтобы понять главное: заливка обязана быть
     ТЕМНЕЕ холста, а не светлее. Я держал её у белого (rgba(240,244,249)) и опускал
     альфу — но белёсая дымка над светлым холстом остаётся белёсой дымкой при любой
     прозрачности, потому что тон никуда не сдвинут.
     В тёмной теме стекло rgba(29,26,23) ярче обсидианового холста, то есть уходит
     к СЕРЕДИНЕ шкалы. Зеркальный ход для светлой темы — уйти к середине сверху,
     то есть потемнеть. Отсюда серо-синяя пластина ниже: она заметно темнее холста,
     и именно поэтому читается стеклом, а не бликом. */
  --graphite: rgba(226, 233, 242, 0.15);   /* панели, карточки, блоки */
  /* Вторая поверхность — СВЕТЛЕЕ стекла, а не темнее. В непрозрачной теме «утопленное»
     делается затемнением, но на сером стекле затемнять уже некуда: замер дал шапке
     таблицы 3.98:1 при норме 4.5, а поднять её было нечем — сама пластина стоит почти
     на пороге. На стекле роль «другого уровня» берёт светлая матовая полоса: она и
     отделяет шапку от строк, и возвращает контраст (4.96:1). */
  /* Вторая поверхность работает подкладкой в том же смысле, что и строки: шапка
     таблицы и счётчики несут мелкий текст поверх 30%-стекла. На 0.42 «ВРЕМЯ»/«СТАТУС»
     давали 3.47:1; 0.72 — порог, за которым держится 5.07:1. */
  --graphite-2: rgba(255, 255, 255, 0.62); /* шапки таблиц, жёлоба, чипы */

  /* Текст. Стекло опущено до 0.24. Шкалу вторичного текста я сперва углубил ещё раз
     по РАСЧЁТНОМУ худшему случаю — и зря: сканирование всей площади блоков на пяти
     ширинах окна показало, что самый тёмный пиксель под текстом это внутренний
     разделитель строк (--hairline), а не тёмное пятно фотографии. Шкала возвращена;
     запас на разреженном стекле 4.6–4.7:1 при норме 4.5, замерено, а не выведено. */
  --bone: #30292f;                  /* графит — основной */
  --ash: #4f5a6e;                   /* вторичный, ≥5.1:1 на сером стекле */
  /* #808080 из образца давал 3.88:1 на стекле — ниже нормы 4.5 для 12px. В плотной
     аналитике это не «третьестепенная подсказка», а рабочие подписи бордов.
     Вторая правка: посеревшее стекло темнее прежнего почти-белого, и #6b7280 сполз
     до 4.17:1. Ступень углублена — плата за прозрачность вносится в текст, а не в норму.
     Третья правка: холст тянется background-size: cover, поэтому самый тёмный кластер
     текстуры может оказаться под ЛЮБОЙ панелью — это не краевой случай, а вопрос
     ширины окна. На нём #646b78 давал 4.41:1. Ступень углублена ещё раз: текст на
     светлой подложке от потемнения может только выиграть в контрасте. */
  --ash-dim: #575d68;               /* подсказки, ≥4.65:1; светлее --ash — иерархия сохранена */
  --ink-soft: #4f5a6e;
  --ink-muted: #575d68;
  --ink-faint: #575d68;
  --ink-dim: #9aa0a6;

  /* Бренд. #00BBF9 буквой даёт 2.22:1, а --ember в коде служит И заливкой, И текстом —
     поэтому здесь читаемая ступень 5.6:1, работающая в обеих ролях. Яркий фирменный
     голубой вводится вторым проходом точечно, на поверхности с графитовой подписью. */
  --ember: #007095;
  --ember-rgb: 0, 112, 149;
  --ember-glow: #b4dced;            /* мягкий кант вместо ореола */
  --ember-smoke: #cfe6f0;
  --blue: #007095;

  /* Роли, отщеплённые от холста */
  /* Фирменная ЗАЛИВКА — яркий корпоративный #00bbf9. Отдельным токеном, а не через
     --ember: тот служит ещё и цветом ТЕКСТА в 70 местах, и там #00bbf9 дал бы 2.22:1.
     Разделение ролей: --ember остаётся читаемой ступенью для букв, --brand-fill —
     для плашек, вкладок, переключателей и значков. */
  --brand-fill: #00bbf9;
  --brand-fill-rgb: 0, 187, 249;
  /* Подпись НА фирменной заливке обязана быть графитовой: белая на #00bbf9 даёт 2.22:1
     и прямо запрещена гайдбуком, графит — 6.39:1. Раньше здесь стоял белый, потому что
     заливкой была тёмная ступень #007095. */
  --on-accent: #30292f;
  --on-brand: #30292f;
  --mark-ring: #ffffff;             /* обводка точек графика = цвет ПАНЕЛИ, не холста */

  /* Структура. Хайрлайны уведены в холодный и углублены: прежние нейтрально-серые
     линии тонули в голубоватом стекле и рвали таблицы на бесшовные полосы. */
  --hairline: #d7dfe8;
  --hairline-strong: #b8c3d0;
  --tint-rgb: 48, 41, 47;           /* переворот: подложки становятся графитовыми */

  /* Статусы — тёмные ступени, светлые на белом нечитаемы. Зелёный углублён
     с #147b57: на разреженном стекле счётчик «на смене» 12px давал 4.34:1. */
  --online: #0f7050;
  --online-rgb: 15, 112, 80;
  --status-good: #0f7050;
  --status-bad: #b3261e;
  --status-warn: #a8620a;

  /* Скругления по гайдбуку: базовый корнер 25px */
  --radius-card: 25px;
  --radius-inner: 18px;
  --radius-block: 14px;
  --radius-ctl: 10px;
  --radius-xs: 6px;

  /* Фирменный шрифт: Graphik LC платный, взята ближайшая доступная замена с родной
     кириллицей и табличными цифрами. */
  --font: "Golos Text", "Inter", "Helvetica Neue", ui-sans-serif, system-ui, sans-serif;

  /* Глубина: у светлой темы своя рецептура (решение 10.08.2026) */
  --glow-hover: 0 4px 6px -1px rgba(0, 0, 0, 0.10), 0 2px 4px -2px rgba(0, 0, 0, 0.10);
  --glow-hover-sm: 0 1px 2px rgba(0, 0, 0, 0.08);
}

/* ---- Фоновые слои: первая ПАРНАЯ рецептура под светлую тему ----
   Тёмная тема собрана из трёх слоёв: фотоподложка low_fone.webp (opacity .35),
   ember-водяной знак и затемняющий градиент снизу. Ни один не переносится:
   фотография тёмная и на белом холсте даёт грязное серое пятно; водяной знак зашит
   цветом #ff4700 прямо в SVG, а гайдбук запрещает перекрашивать знак; затемняющий
   градиент на светлом фоне не имеет смысла — светлеть некуда.

   Здесь тема впервые меняет не токен, а ПРАВИЛО. Это осознанный выход за контракт
   «тема трогает только :root»: background-image в переменной не живёт. Отключаем
   через display:none, а не opacity:0 — иначе браузер продолжал бы держать
   композиторный слой и качать мегабайтную картинку впустую.

   Воздух в светлой теме держат холст и тени-шёпот на карточках, а не слои. */
/* ---- Слой тумана: панорамный дрейф слева направо (z-index -2) ----
   Ложится ровно между фотографией города (html::before, -3) и фирменным знаком
   (body::before, -1) — тот самый свободный слот.

   Двигаем ТОЛЬКО transform. Анимация background-position выглядит проще, но это
   параметр отрисовки: браузер перекрашивает полноэкранный слой каждый кадр и не
   отдаёт его композитору. transform двигает уже готовый растр на GPU.

   Петля: бокс шириной 200vw, тайл фона = 50% бокса = ровно один экран, repeat-x
   укладывает внутрь две копии. Сдвиг на -50% = ровно один тайл, поэтому кадр в конце
   цикла попиксельно совпадает с кадром в начале. Оба значения процентные, поэтому
   при изменении размера окна пересчитываются синхронно — JS не нужен.

   Направление: анимация идёт ОТ -50% К 0, то есть бокс едет вправо. Обе крайние
   позиции полностью накрывают экран.

   Строго linear: любое ускорение рвёт бесшовность в точке склейки. */
:root[data-theme="ibrat-light"] body::after {
  display: block;
  /* Базовое правило ставит inset:0; здесь ширина задаётся явно, поэтому правый край
     отпускаем, а верх/низ оставляем — так высота сама следует за вьюпортом. */
  inset: 0 auto 0 0;
  width: 200vw;
  z-index: -2;
  background-image: url("/static/fog-ibrat.webp");
  background-repeat: repeat-x;
  background-size: 50% 100%;
  background-position: 0 center;
  /* 0.35 не читалось: туман белый, а фотография под ним светлая и сама дымчатая —
     вклад в кадр был 9 единиц RGB. Плюс большая часть тумана лежит ПОД стеклом,
     которое его ещё и размывает. */
  opacity: 0.8;
  will-change: transform;
  /* 180 с давало 8.9 px/сек — за три секунды сдвиг 27 px, ниже порога заметности.
     60 с = 27 px/сек: движение читается, но остаётся спокойным. */
  animation: fog-drift 60s linear infinite;
  pointer-events: none;
}
@keyframes fog-drift {
  from { transform: translate3d(-50%, 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}
/* Бесконечное декоративное движение — под WCAG 2.2.2 попадает всё, что дольше 5 секунд.
   Останавливаем полностью: замирающий туман не выглядит поломкой, а для вестибулярных
   нарушений это однозначно безопаснее полумеры с замедлением. */
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="ibrat-light"] body::after { animation: none; transform: translate3d(-25%, 0, 0); }
}

/* Фотография города уезжает на НИЖНИЙ слой (html::before, z-index -3), чтобы над ней
   освободилось место под фирменный знак. Раньше она занимала body::before — тот же слот,
   где в тёмной теме живёт водяной знак, и знака в светлой теме не было вовсе. */
:root[data-theme="ibrat-light"]::before {
  display: block;
  background-image: url("/static/wall-ibrat.webp");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  /* Полная сила. Раньше стояло 0.13 — и это была настоящая причина, по которой
     заказчик четыре раза не видел стекла: за блоками не было ИЗОБРАЖЕНИЯ, только
     ровный холст. Размытие ровного холста не даёт ничего, сколько ни крути альфу
     пластины. Стекло видно тогда, когда сквозь него видно РАЗМЫТУЮ КАРТИНКУ. */
  opacity: 1;
}

/* Фирменная подложка светлой темы. Занимает тот же слот, что ember-водяной знак в тёмной
   (body::before), но это не логотип, а текстура — фотография заказчика (theme_ibrat_wall).

   БЕЗ ПЕРЕКРАСКИ. Первая версия была колоризована в корпоративный голубой, и весь
   интерфейс уехал в бирюзу: холст #d3ebf4, счётчики и акценты тонули в общем цыане.
   Оригинал сам по себе холодный серо-синий (средний цвет 140,163,187) и под серым
   стеклом работает без единой правки цвета. Из обработки осталась только конвертация
   в WebP: 2.4 МБ → 205 КБ, вес фона платят все посетители.

   Она же возвращает смысл стеклу: полупрозрачные поверхности снова показывают что-то
   за собой, а не ровный холст. Без подложки стекло было технически исправным и
   визуально пустым. */
/* Фирменный знак — МЕЖДУ фотографией и блоками (body::before, z-index -1).
   Позиция и размер один в один как в тёмной теме, чтобы знак стоял на своём месте;
   отличается только цвет: #00bbf9 вместо ember. Перекрасить фильтром нельзя — цвет
   зашит внутрь SVG, поэтому рядом лежит фирменная копия файла. */
:root[data-theme="ibrat-light"] body::before {
  display: block;
  background-image: url("/static/logo-watermark-ibrat.svg");
  background-position: 83% 78%;
  background-size: 77% auto;
  background-repeat: no-repeat;
  /* 0.2 — цифра тёмной темы, там знак лежит на почти чёрном холсте и читается.
     Здесь под ним фотография: замер показал разницу кадров со знаком и без всего
     в 29 единиц RGB, то есть знак был технически на месте и визуально отсутствовал. */
  /* Знак переехал в заголовок «На линии», фоновый слой выключен: два логотипа на
     одном экране спорят друг с другом. Вернуть — снять display:none. */
  display: none;
}

/* ---- Стекло: светлая рецептура (решение заказчика 10.08.2026) ----
   Тёмная собрана как «тёмное стекло, светлый кант» под обсидиан: тёмный градиент,
   blur + saturate(140%), тень rgba(0,0,0,.7). Переносить нельзя по трём причинам:
   saturate над белым усиливает любой цвет под попапом и даёт грязь; тень втрое темнее
   лимита воздушной темы; а «светлый кант» на белом фоне просто исчезает — край обязан
   быть ТЕМНЕЕ подложки, а не светлее. Это поправка к моему же референсу.

   Светлая рецептура: белый полупрозрачный, размытие без saturate, край хайрлайном,
   одна тень-шёпот плюс мягкий подъём для всплывающих. */
:root[data-theme="ibrat-light"] .topbar {
  /* Полоса была 61px при вертикальных отступах 18: вокруг кнопки оставалось по 21px
     сверху и снизу — воздуха больше, чем самой кнопки. Сжато до 9.
     Боковые 40px НЕ трогаю: ими логотип Capybara выровнен с логотипом Айбрат в секции
     ниже (оба ровно на 40). Уменьшить их — значит развалить вертикаль страницы. */
  padding: 9px 40px;
  /* Шапка прозрачнее блоков, но плотнее их: под ней ПРОКРУЧИВАЮТСЯ данные, и сквозь
     неё не должны читаться уезжающие строки таблиц. 0.56 — компромисс: фотография и
     туман за ней видны, а проезжающий контент превращается в размытое пятно. */
  background: linear-gradient(180deg, rgba(230, 237, 246, 0.72), rgba(222, 231, 243, 0.66));
  /* Размытие поднято 18 → 28px вместе с падением плотности. При альфе 0.24 заливка
     почти ничего не перекрывает, и «стеклом» поверхность делает уже не она, а сила
     размытия: матовое стекло узнаётся по тому, что за ним всё РАСПЛЫВАЕТСЯ. Побочно
     это поднимает и контраст — сильный blur усредняет тёмный кластер фотографии
     с соседями, и худший случай под панелью становится светлее. */
  -webkit-backdrop-filter: blur(28px);
  backdrop-filter: blur(28px);
  border-bottom: 1px solid rgba(84, 112, 143, 0.36);
}
/* Борды и всплывающие идут по ТОЙ ЖЕ рецептуре, что блоки дашборда: иначе половина
   интерфейса серо-стеклянная, а половина белая. Всплывающим оставлена бОльшая
   плотность (0.80): они ложатся ПОВЕРХ данных, и сквозь них не должно читаться то,
   что они перекрывают. */
:root[data-theme="ibrat-light"] .glass {
  background: var(--graphite);
  /* Размытие поднято 18 → 28px вместе с падением плотности. При альфе 0.24 заливка
     почти ничего не перекрывает, и «стеклом» поверхность делает уже не она, а сила
     размытия: матовое стекло узнаётся по тому, что за ним всё РАСПЛЫВАЕТСЯ. Побочно
     это поднимает и контраст — сильный blur усредняет тёмный кластер фотографии
     с соседями, и худший случай под панелью становится светлее. */
  -webkit-backdrop-filter: blur(28px);
  backdrop-filter: blur(28px);
  border: 1px solid rgba(84, 112, 143, 0.42);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 1px 2px rgba(16, 42, 67, 0.07),
    0 8px 18px -6px rgba(16, 42, 67, 0.18);
}
:root[data-theme="ibrat-light"] .menu-pop,
:root[data-theme="ibrat-light"] .cal-pop,
:root[data-theme="ibrat-light"] .arrivals-pop,
:root[data-theme="ibrat-light"] .emp-timesel-pop,
:root[data-theme="ibrat-light"] .an-tip,
:root[data-theme="ibrat-light"] .pulse-nav {
  background: linear-gradient(180deg, rgba(236, 241, 248, 0.93), rgba(228, 235, 245, 0.90));
  -webkit-backdrop-filter: blur(30px);
  backdrop-filter: blur(30px);
  border: 1px solid rgba(84, 112, 143, 0.42);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 2px 4px rgba(16, 42, 67, 0.08),
    0 16px 32px -10px rgba(16, 42, 67, 0.24);
}
/* Без поддержки размытия стекло превращается в плотную поверхность — полупрозрачный
   белый поверх белого холста иначе не читался бы вовсе. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root[data-theme="ibrat-light"] .topbar,
  :root[data-theme="ibrat-light"] .glass,
  :root[data-theme="ibrat-light"] .menu-pop,
  :root[data-theme="ibrat-light"] .cal-pop,
  :root[data-theme="ibrat-light"] .arrivals-pop,
  :root[data-theme="ibrat-light"] .emp-timesel-pop,
  :root[data-theme="ibrat-light"] .an-tip,
  :root[data-theme="ibrat-light"] .pulse-nav { background: #dbe4ee; }
}

/* ---- Стеклянность и объём БЛОКОВ светлой темы ----
   Рецептура `.glass` покрывала только борды и попапы, а дашборд собран из .panel/.card/
   .live-block/.status-block — они шли через --graphite и остались плотными.

   ВТОРАЯ РЕДАКЦИЯ (замеры на настоящем HTTP-стенде, не на about:blank).
   Первая версия правила была стеклянной только на бумаге, и заказчик вернул её трижды.
   Что было измерено внутри блока: цвет #f3f8fb (11 единиц до чистого белого), просвет 27%,
   кант rgba(255,255,255,.55) поверх почти белой заливки — контраст 1.02:1, то есть его
   попросту нет. Три ошибки, и все три исправлены здесь:

   1. Кант был СВЕТЛЕЕ поверхности. Тремя десятками строк выше, в рецептуре `.glass`,
      записано обратное правило — «край обязан быть ТЕМНЕЕ подложки». Своё же правило
      я и нарушил. Теперь край холодный и тёмный, а светлый блик ушёл внутрь (inset):
      именно эта пара «тёмный край снаружи + светлая кромка изнутри» и читается как
      толщина стекла, то есть как объём.
   2. Тень съедала сама себя: spread -16px при blur 24px утапливал ядро тени на 6px
      ВНУТРЬ блока, наружу выходило ~8px уже выцветшего края. Растяжение убрано.
      Цвет теней не чёрный, а глубокий синий: чёрный на голубом холсте даёт грязь.
   3. `.kpi` и `.mgr-card` отсюда УБРАНЫ. Они лежат внутри бордов `.board.glass`, и
      стекло на стекле складывает альфы (0.82 над 0.82 ≈ 0.97) — вместо прозрачности
      получается глухая плита. В базовом CSS этот запрет уже стоял (backdrop-filter:none
      на строках .kpi/.mgr-card), а правило темы его перебивало по специфичности.
      Их рецептура — ниже, отдельным правилом. */
:root[data-theme="ibrat-light"] .panel,
:root[data-theme="ibrat-light"] .card,
:root[data-theme="ibrat-light"] .live-block,
:root[data-theme="ibrat-light"] .status-block,
:root[data-theme="ibrat-light"] .conv-chip,
:root[data-theme="ibrat-light"] .field,
:root[data-theme="ibrat-light"] .live-total {
  /* Двухстопный градиент — структурно тот же приём, что у стекла первой темы
     (там rgba(29,26,23,.62) → rgba(18,16,14,.58)): плотнее сверху, разреженнее снизу.
     Так пластина получает лёгкий уклон и не выглядит ровной плёнкой. */
  background: linear-gradient(180deg, rgba(228, 235, 244, 0.17), rgba(219, 228, 240, 0.13));
  /* saturate НИЖЕ единицы, а не выше. Ранее в этом файле я записал отказ от saturate
     в светлой теме — но отказ был от saturate(140%), которая усиливает цвет под
     поверхностью и даёт грязь. Здесь обратная операция: фирменная синяя текстура,
     проходя сквозь пластину, обесцвечивается — холст остаётся синим, а стекло читается
     СЕРЫМ, как и просил заказчик. Разница «синее насквозь / серое сквозь стекло»
     и есть то, что глаз опознаёт как стекло. */
  /* Размытие поднято 18 → 28px вместе с падением плотности. При альфе 0.24 заливка
     почти ничего не перекрывает, и «стеклом» поверхность делает уже не она, а сила
     размытия: матовое стекло узнаётся по тому, что за ним всё РАСПЛЫВАЕТСЯ. Побочно
     это поднимает и контраст — сильный blur усредняет тёмный кластер фотографии
     с соседями, и худший случай под панелью становится светлее. */
  -webkit-backdrop-filter: blur(28px);
  backdrop-filter: blur(28px);
  border: 1px solid rgba(84, 112, 143, 0.42);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 1px 2px rgba(16, 42, 67, 0.07),
    0 8px 18px -6px rgba(16, 42, 67, 0.18);
}
/* Сетка карточек рисует линии зазором на фоне --hairline. Под стеклом фон должен
   пропускать подложку, иначе за карточками осталась бы серая плита. */
:root[data-theme="ibrat-light"] .cards { background: transparent; gap: 10px; }

/* Плотность стекла — по количеству данных на поверхности, а не одинаковая всюду.
   Карточка с одним числом остаётся почти воздушной; панель, под которой идёт таблица
   на десятки строк, обязана быть спокойнее — иначе строки читаются поверх окон здания.
   Замер: при общей рецептуре у панели просвет 71%, у карточек 55% — таблица страдала
   сильнее всех, потому что её собственный фон прозрачен и работает только стекло панели. */
:root[data-theme="ibrat-light"] .panel,
:root[data-theme="ibrat-light"] .board {
  background: linear-gradient(180deg, rgba(230, 236, 245, 0.19), rgba(222, 230, 241, 0.15));
}

/* ---- Счётчики и чипы с фирменным голубым ----
   #007095 на сером стекле даёт 4.18:1 — ниже нормы. Углублять бренд-цвет ещё на ступень
   я не стал: гайдбук Айбрат — закон, а #007095 уже затемнённая ступень фирменного
   #00BBF9. Контраст возвращается подложкой: под цифрой светлая матовая полоса, и та же
   #007095 держит 4.58:1. Заодно счётчик читается отдельным чипом, а не цифрой на воздухе. */
:root[data-theme="ibrat-light"] .live-count,
:root[data-theme="ibrat-light"] .status-count {
  background: var(--graphite-2);
}
/* ---- Фирменный знак вместо заголовка «На линии» (только светлая тема) ----
   Разметку не трогаем: тема обязана оставаться сменной, а «На линии» — это текстовый
   узел внутри <h1>, обёртки у него нет. Прячем его font-size:0 (текст остаётся в дереве
   доступности и озвучивается скринридером — в отличие от display:none) и рисуем знак
   псевдоэлементом.

   Секцию выбираем через :has(#statusPulse), а не по порядку элементов: корона с этим id
   есть только в шапке «На линии», и такой селектор не сломается, если выше по странице
   появится ещё одна секция. Вторая секция, «Пропущенные звонки», использует тот же
   класс .live-title и остаётся текстовой. */
/* Корону в этом заголовке убираем — знак остаётся один. Именно display:none, а НЕ
   удаление из разметки: селектор :has(#statusPulse) выше опирается на её присутствие
   в DOM, и вынь мы корону из HTML — правило перестало бы находить секцию. */
:root[data-theme="ibrat-light"] .live-title:has(#statusPulse) {
  font-size: 0;
  gap: 0;
}
:root[data-theme="ibrat-light"] .live-title #statusPulse { display: none; }

/* Знак вырос до 60px и раздвинул шапку страницы: от низа топбара до карточек стало
   106px (22 отступ секции + 60 знак + 24 под заголовком). Пустоты убираем, сам знак
   не трогаем — 22 → 4 и 24 → 8, итого 72px, из которых 68 занимает сама марка.

   Обе правки адресные: и по теме, и по секции (через ту же корону-якорь). Базовый
   ритм 12+12 между секциями = 24 под заголовком остаётся в силе везде остальном —
   он там осознанный, а здесь его ломает крупный логотип, которого в тёмной теме нет. */
:root[data-theme="ibrat-light"] .live-section:has(#statusPulse) { padding-top: 4px; }
:root[data-theme="ibrat-light"] .live-head:has(#statusPulse) { margin-bottom: 8px; }
:root[data-theme="ibrat-light"] .live-title:has(#statusPulse)::after {
  content: "";
  display: block;
  /* Пропорция взята из viewBox файла: 87364.58 × 13247.91 ≈ 6.594 : 1 — ширину
     не считаю руками, её выводит aspect-ratio, поэтому марку нельзя сплющить.
     Высота вдвое против прежних 30px, но через clamp: на узких окнах знак шириной
     под 390px вытеснил бы колокольчик и чип конверсии из строки заголовка. */
  height: clamp(34px, 4.2vw, 60px);
  aspect-ratio: 6.594;
  width: auto;
  background-image: url("/static/logo-watermark-ibrat.svg");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: contain;
  /* Тень именно drop-shadow: она строится по АЛЬФЕ картинки и повторяет контур букв.
     box-shadow обвёл бы прямоугольник псевдоэлемента — знак оказался бы в рамке.
     Тем же приёмом в этом файле сделано свечение короны.
     Две ступени по назначению: короткая даёт краю опору на фоне, длинная и мягкая
     отрывает знак от фотографии. Цвет — глубокий синий, а не чёрный: над голубой
     маркой и серо-синим фото чёрная тень грязнит. */
  filter:
    drop-shadow(0 1px 1px rgba(16, 42, 67, 0.28))
    drop-shadow(0 3px 9px rgba(16, 42, 67, 0.30));
}
/* Счётчик сотрудников убран по решению заказчика — место отдано знаку.
   Только в этой теме: в тёмной он остаётся. */
:root[data-theme="ibrat-light"] .live-total { display: none; }

/* ---- Палитра графиков для светлой темы ----
   Серии НЕ были переопределены и работали от тёмной темы. Валидатор на светлой
   поверхности стекла (#dbe3e9) показал контраст 2.37–2.80:1 при норме 3 — линии
   выцветали на светлом фоне у всех четырёх серий.

   Заодно исправлена ошибка распределения ролей: «Выручка» ходит через --series-revenue,
   а тот был псевдонимом --ember. В тёмной теме ember оранжевый, и всё было в порядке;
   в светлой я увёл ember в синий #007095 — и выручка стала синей рядом с синими лидами,
   ΔE 9.7 при норме 15. Здесь выручке возвращена её ТЁПЛАЯ роль отдельным значением.

   Набор подобран прогоном валидатора, а не на глаз. Итог на светлом стекле,
   проверка по ВСЕМ парам (не только соседним):
     светлота  — все 5 в полосе 0.43–0.77
     насыщенность — все 5 выше порога 0.1
     дальтонизм — худшая пара ΔE 9.3 (дейтеран) при цели 8
     обычное зрение — худшая пара ΔE 18.3 при пороге 15
     контраст к поверхности — все 5 выше 3:1

   Корпоративный #00bbf9 в сериях СОЗНАТЕЛЬНО не используется: линией на светлом стекле
   он даёт 1.71:1 — замерено. Фирменную семью держит #1a7fd0 на главной серии. */
:root[data-theme="ibrat-light"] {
  --series-leads: #1a7fd0;
  --series-leads-rgb: 26, 127, 208;
  --series-revenue: #a35f00;
  --series-conv: #0b8a63;
  --series-wins: #5a34ad;
  --series-speed: #9c2d5e;
  --series-leads-deep: #12578f;
  --series-conv-deep: #076b4c;
  --series-revenue-deep: #7a4600;
  --series-period-2: #a35f00;
  /* #7cc6ff — ступень тёмной темы, на светлом стекле давала около 1.9:1. */
  --period-1: #1a7fd0;
}

/* ---- График смен: ячейки дня и их метки ----
   Замер показал 1.14–1.23:1 у ВСЕХ четырёх меток — их физически не было видно.
   Две причины, и лечить надо обе.

   Первая: цвета меток достались от тёмной темы — время смены литералом #ffb596,
   отпуск #6fd4c6, больничный #e9c37e. Бледные тона, рассчитанные на обсидиан.
   (В комментарии к токенам у самих себя записано «в светлой теме остались бы прежними —
   на белом все три ниже 3:1», но переопределения так и не появились. Вот они.)

   Вторая: ячейка дня несёт мелкий текст, но подкладки не получила, когда я раздавал их
   остальным поверхностям. Сквозь неё шла фотография, и фон плыл от #9db9ca до #dcdbd5 —
   подобрать цвет под такой разброс невозможно. Ячейка получает ту же матовую подкладку,
   что таблицы и плитки, а состояние остаётся тонким тинтом ПОВЕРХ неё: фон становится
   предсказуемым, и метке хватает обычной тёмной ступени своего же оттенка. */
:root[data-theme="ibrat-light"] {
  --sched-off: #4f5a6e;
  --sched-vacation: #0b6b56;
  --sched-sick: #8a5a00;
}
:root[data-theme="ibrat-light"] .e-day { background-color: rgba(255, 255, 255, 0.62); }
/* Тинт состояния — фоновой КАРТИНКОЙ, а не цветом: цвет уже занят подкладкой, и два
   background-color на одном элементе не складываются. */
:root[data-theme="ibrat-light"] .e-day--work {
  background-image: linear-gradient(rgba(0, 120, 160, 0.13), rgba(0, 120, 160, 0.13));
  border-color: rgba(0, 120, 160, 0.34);
}
:root[data-theme="ibrat-light"] .e-day--off {
  background-image: linear-gradient(rgba(90, 110, 135, 0.13), rgba(90, 110, 135, 0.13));
  border-color: rgba(90, 110, 135, 0.34);
}
:root[data-theme="ibrat-light"] .e-day--vacation {
  background-image: linear-gradient(rgba(11, 138, 99, 0.13), rgba(11, 138, 99, 0.13));
  border-color: rgba(11, 138, 99, 0.34);
}
:root[data-theme="ibrat-light"] .e-day--sick {
  background-image: linear-gradient(rgba(163, 95, 0, 0.13), rgba(163, 95, 0, 0.13));
  border-color: rgba(163, 95, 0, 0.34);
}
/* Время смены было единственным литералом среди четырёх — остальные шли токенами. */
:root[data-theme="ibrat-light"] .e-day--work .e-day-tag { color: #0b5f80; }

/* ---- Фирменная заливка элементов управления ----
   Заказчик указал на три плашки — «Меню», активную вкладку отдела и переключатель
   «По дням»: они были залиты тёмной ступенью #007095, потому что тот же токен служит
   цветом текста. Здесь заливки переведены на корпоративный #00bbf9, а подписи на них
   уже графитовые (см. --on-brand / --on-accent выше).

   Графики и легенды СОЗНАТЕЛЬНО не тронуты: у них отдельная палитра, проверенная
   валидатором на различимость при дальтонизме, и перекраска одной серии в фирменный
   голубой ломает проверенные расстояния между сериями. Это отдельная работа. */
/* КНОПКИ — серые, фирменный цвет держат обводка и свечение (решение заказчика).
   Сплошная заливка #00bbf9 требовала графитовой подписи ради 6.39:1; на серой
   поверхности та же подпись даёт больше 10:1, а бренд никуда не девается — он
   в канте и ореоле. Побочно кнопки встали в один ряд с остальными по фактуре. */
:root[data-theme="ibrat-light"] .btn-cta,
:root[data-theme="ibrat-light"] .tab.active,
:root[data-theme="ibrat-light"] .seg-btn.active,
:root[data-theme="ibrat-light"] .cal-day.selected,
:root[data-theme="ibrat-light"] .cal-day.selected:hover,
:root[data-theme="ibrat-light"] .cal-month.selected,
:root[data-theme="ibrat-light"] .cal-month.selected:hover,
:root[data-theme="ibrat-light"] .emp-timesel-opt.selected,
:root[data-theme="ibrat-light"] .cmp-run {
  background: var(--graphite-2);
  color: var(--bone);
  border: 1px solid var(--brand-fill);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 0 0 1px rgba(var(--brand-fill-rgb), 0.16),
    0 2px 12px -2px rgba(var(--brand-fill-rgb), 0.48);
}
/* Точки и мелкие значки остаются ЗАЛИТЫМИ: у кружка 12px и счётчика на 18px нет
   площади, на которой обводка читалась бы как обводка — она съела бы весь элемент. */
:root[data-theme="ibrat-light"] .brand-dot,
:root[data-theme="ibrat-light"] .pulse,
:root[data-theme="ibrat-light"] .arrivals-badge,
:root[data-theme="ibrat-light"] .login-pro-badge {
  background: var(--brand-fill);
  border-color: var(--brand-fill);
}

/* ---- Бегущая кнопка сборки отчёта ----
   В тёмной теме у неё зашиты тёплая тёмная заливка rgba(34,20,13,.96) и оранжевые
   литералы в раскадровке (#ff6a2e → #ffa067). В светлой теме это выглядело чужой
   кнопкой из другой темы: тёмный чип, пульсирующий оранжевым. Хуже того, при этом
   действовало color: var(--bone) — а он здесь ГРАФИТОВЫЙ, то есть тёмный текст лежал
   на тёмной заливке и подпись «Собираем… 60%» почти не читалась.

   Здесь та же механика (пульс контура, период 2.8 с, alternate — рассвет и затухание
   зеркальны), но в фирменной гамме: заливка — та же матовая подкладка, что у ячеек
   с данными, свечение идёт от #00bbf9 к более яркой ступени. Свечение не гаснет
   в ноль, поэтому пульс не «прерывается». */
:root[data-theme="ibrat-light"] .recalc-btn.running {
  background: rgba(255, 255, 255, 0.72);
  border-color: #00bbf9;
  animation-name: recalc-shimmer-ibrat;
}
@keyframes recalc-shimmer-ibrat {
  from { border-color: #00bbf9;
         box-shadow: 0 0 0 1px rgba(0, 187, 249, 0.45), 0 0 16px 3px rgba(0, 187, 249, 0.34); }
  to   { border-color: #5fd8ff;
         box-shadow: 0 0 0 1px rgba(95, 216, 255, 0.70), 0 0 30px 7px rgba(95, 216, 255, 0.58); }
}
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="ibrat-light"] .recalc-btn.running {
    animation: none;
    border-color: #00bbf9;
    box-shadow: 0 0 0 1px rgba(0, 187, 249, 0.5), 0 0 18px 3px rgba(0, 187, 249, 0.4);
  }
}

/* Тем же поиском нашлись ещё два тёплых литерала из тёмной темы, попадавшие в текст:
   оранжевые #d98a5a и #ffb454 на светлом стекле давали около 2:1. Переведены на
   статусный токен темы (#a8620a), который для светлой уже посчитан. */
:root[data-theme="ibrat-light"] .live-age.sev-warning,
:root[data-theme="ibrat-light"] .cmp-warn { color: var(--status-warn); }

/* Подпись в шапке — единственное, что не выдержало её прозрачности: на 0.72 она давала
   4.21:1. Углубляем ТОЧЕЧНО эту подпись, а не общий токен --ash: он держит ещё десятки
   мест, где запас есть, и трогать их ради одной строки незачем. */
:root[data-theme="ibrat-light"] .brand-sub { color: #46505f; }

/* Ячейка скорости, посчитанная по одному-двум наблюдениям. Не «плохо» и не «ошибка» —
   предупреждение, что цифра не выдерживает веса кадрового решения. Пунктир снизу, а не
   цвет: цветом в этой таблице кодируются состояния дня. */
.hp-thin { border-bottom: 1px dashed rgba(168, 98, 10, 0.55); }

/* ---- Матовые подкладки под мелкий текст (30%-стекло, решение заказчика) ----
   Пластина 30% сама по себе текст не держит: под ней живая фотография, и на тёмных
   участках здания даже ЧЁРНЫЙ текст даёт 4.92:1 — то есть подобрать цвет шрифта
   невозможно в принципе, это не вопрос ступени серого.

   Поэтому разделяем роли: СТЕКЛО остаётся у контейнера (карточка, панель, борд — все
   на 0.30), а поверхности, НЕСУЩИЕ мелкий текст, получают собственную матовую
   подкладку. Между строками, в шапках, в отступах и зазорах стекло видно как прежде.

   Плотность 0.62 — по прямому решению заказчика: с рассчитанного порога 0.72 снято
   ещё 10 пунктов ради прозрачности. Норму контраста это местами пробивает, цифры
   в журнале правок. Число одно на всю тему: и строки, и шапки таблиц, и плитки,
   и счётчики — иначе поверхности разъезжаются по тону. */
:root[data-theme="ibrat-light"] .status-person,
:root[data-theme="ibrat-light"] .live-row,
:root[data-theme="ibrat-light"] .live-empty,
:root[data-theme="ibrat-light"] .status-empty,
:root[data-theme="ibrat-light"] tbody tr {
  background: rgba(255, 255, 255, 0.62);
}
/* Шапка борда — подкладка тут ФОРМА, а не только цвет. Когда я раздавал подкладки,
   этой достался голый фон: padding 0, радиус 0. Получился острый прямоугольник внутри
   скруглённого борда, текст лёг вплотную к краям (низ подзаголовка совпадал с низом
   плиты в ноль), а длинный подзаголовок «Август 2026 · … · CRM: 10 авг» переносился
   и ронял хвост за пределы ритма.

   Что добавлено: внутренние отступы и радиус — плита стала плитой; выравнивание по
   центру вместо верхнего края — кнопки встают вровень с текстовым блоком, а не
   прилипают к его первой строке; перенос строки — на узком окне правая группа
   уходит вниз целиком, вместо того чтобы дожимать подзаголовок до переноса;
   min-width:0 левой колонке — без него flex-элемент не сжимается ниже своего
   содержимого и выдавливает соседа. */
:root[data-theme="ibrat-light"] .board-head {
  background: rgba(255, 255, 255, 0.62);
  padding: 11px 15px;
  border-radius: var(--radius-inner);
  align-items: center;
  flex-wrap: wrap;
  row-gap: 10px;
}
:root[data-theme="ibrat-light"] .board-head > :first-child { min-width: 0; flex: 1 1 auto; }
/* Плитка KPI мелкая: подкладывать внутри неё нечего, подкладкой работает она сама.
   .kpi и .mgr-card настраиваются НЕ здесь, а в правиле вложенных поверхностей ниже:
   оно идёт позже по файлу при равной специфичности и перебивает эту строку. */
:root[data-theme="ibrat-light"] .card {
  background: rgba(255, 255, 255, 0.62);
}
/* Наведение на строку обязано остаться заметным поверх подкладки. */
:root[data-theme="ibrat-light"] tbody tr:hover { background: rgba(255, 255, 255, 0.76); }

:root[data-theme="ibrat-light"] .panel-title { color: var(--bone); }

/* Чип конверсии и счётчик смены висят ПРЯМО НА ФОТОГРАФИИ, а не внутри блока: под ними
   нет матовой пластины, которая подняла бы фон. Крупные поверхности могут позволить себе
   разреженность, мелкая плавающая пилюля — нет: на тёмном участке здания фирменный
   #007095 давал 4.07:1. Пилюля плотная, и это не спор с прозрачностью — сквозь неё
   всё равно идёт размытие, просто плотность подобрана под её собственный размер. */
:root[data-theme="ibrat-light"] .conv-chip,
:root[data-theme="ibrat-light"] .live-total {
  background: rgba(240, 245, 251, 0.92);
}

/* ---- Вложенные поверхности: стекло НЕ носят ----
   Правило иерархии светлой темы: стекло принадлежит верхнему уровню (борд, панель,
   блок), а всё, что лежит ВНУТРИ него, — плоское. Две полупрозрачные поверхности
   друг над другом перемножают альфы и гасят прозрачность; вдобавок backdrop-filter
   потомка размывает уже размытую родителем плоскость, то есть греет GPU впустую. */
:root[data-theme="ibrat-light"] .kpi,
:root[data-theme="ibrat-light"] .mgr-card {
  background: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border: 1px solid rgba(84, 112, 143, 0.26);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}
/* Без поддержки размытия — плотные поверхности, иначе прозрачное поверх подложки
   превратится в нечитаемую кашу. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root[data-theme="ibrat-light"] .panel,
  :root[data-theme="ibrat-light"] .card,
  :root[data-theme="ibrat-light"] .live-block,
  :root[data-theme="ibrat-light"] .status-block,
  :root[data-theme="ibrat-light"] .conv-chip,
  :root[data-theme="ibrat-light"] .field,
  :root[data-theme="ibrat-light"] .live-total { background: #dbe4ee; }
}

/* =====================================================================
   ТЕМА «НОВОГОДНЯЯ» (data-theme="new-year", 30.10.2026)
   Подложка — winter_night (двор ночью, окна, ёлка), стиль — theme_new_year.md
   (Frame.io «midnight cinema»): обсидиан с индиго, ОДИН хроматический акцент
   Iris Glow #6199f6, фиолетовая кайма #4f4f80, пилюли, карточки r10.
   Слои: html::before (-3) фото + ночной градиент; body::after (-2) дальний снег;
   body::before (-1) ближний снег — водяной знак в этой теме не нужен, его слот
   отдан второму плану снега. Обоснования и контраст — DESIGN.md, раздел 10.
   ===================================================================== */
:root[data-theme="new-year"] {
  /* Холст и поверхности. Пластины ПЛОТНЫЕ (0.86): под ними живая фотография, и
     разреженная плёнка положила бы текст на окна дома (glass-needs-a-backdrop). */
  --obsidian: #0a0a13;
  --graphite: rgba(14, 14, 30, 0.86);
  --graphite-2: rgba(24, 24, 44, 0.9);
  --mark-ring: #12121f;

  /* Текст. Smoke #757580 из референса на пластине даёт 3.6–4.2:1 — для мелкого
     текста мало, поэтому он ушёл в декоративную ступень --ink-dim, а «тихий» текст
     держит #8f8f9e (≥4.8:1 даже над самым светлым снегом под пластиной). */
  --bone: #fcfcfc;
  --ash: #a3a3b3;
  --ash-dim: #8f8f9e;
  --ink-soft: #a3a3b3;
  --ink-muted: #8f8f9e;
  --ink-faint: #8f8f9e;
  --ink-dim: #757580;
  --muted: #8f8f9e;

  /* Единственный акцент — Iris Glow. Подменяет ember везде, где тот ходит через токены:
     текст-акцент (≥5.4:1 на пластине), заливки, фокус, свечение. */
  --ember: #6199f6;
  --ember-rgb: 97, 153, 246;
  /* Тревога — праздничная пара (реш. 30.10.2026: коралл/янтарь рядом с голубым читались
     как «оранжевый»): красный ёлочного шара и золото гирлянды. На пластине ~5.5:1 и ~13:1. */
  --status-bad: #ff4d6d;
  --status-warn: #ffd166;
  --ember-glow: #4f4f80;            /* Twilight — ореол */
  --ember-smoke: #2b2b4d;
  --blue: #6199f6;
  /* Белый на iris — 2.77:1, поэтому подпись НА акцентной заливке тёмная (6.94:1). */
  --on-accent: #0a0a13;
  --on-brand: #0a0a13;

  /* Структура: хайрлайн Charcoal, кант контролов — Twilight, поднятый до 3:1. */
  --hairline: #2a2a32;
  --hairline-strong: #6a6aa6;
  --tint-rgb: 222, 223, 238;        /* Specter Lilac — холодный тинт вместо белого */

  /* Графики: серии — данные, а не бренд. Валидированный набор тёмной темы остаётся,
     кроме выручки: она ходила через --ember и стала бы синей рядом с синими лидами.
     Возвращаем ей проверенный тёплый ember литералом. */
  --series-revenue: #ff4700;
  --series-period-2: #ff4700;

  /* Радиусы по референсу: карточки 10, вложенное мельче родителя. */
  --radius-card: 10px;
  --radius-inner: 8px;
  --radius-block: 10px;

  --font: "Inter", "Helvetica Neue", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Свечение — iris, крупнее покоя (правило DESIGN.md §2). */
  --glow-hover: 0 0 0 1px #4f4f80, 0 0 30px 6px rgba(97, 153, 246, 0.38);
  --glow-hover-sm: 0 0 0 1px rgba(97, 153, 246, 0.85), 0 0 14px 2px rgba(97, 153, 246, 0.36);
}

/* ТВ-режим принудительно тёмный при ЛЮБОЙ теме. Его правила написаны литералами, но
   часть свойств (ореол пульса, радиусы, шрифт) всё равно читает токены — возвращаем
   им значения тёмной темы, чтобы телевизор выглядел одинаково. */
:root[data-theme="new-year"].tv-missed {
  /* Акцент ТВ в новогодней теме — iris, а не ember (реш. 30.10.2026: «пропущенный всё ещё
     оранжевый»); фон и плотность остаются тёмными, тревога — праздничной парой ниже. */
  --ember: #6199f6;
  --ember-rgb: 97, 153, 246;
  --ember-glow: #8b2e09;
  --ember-smoke: #451e0e;
  --obsidian: #0f0d0a;
  --bone: #ffffff;
  --ash: #cccccc;
  --hairline: rgba(204, 204, 204, 0.14);
  --hairline-strong: rgba(204, 204, 204, 0.28);
  --tint-rgb: 255, 255, 255;
  --radius-card: 14px;
  --radius-inner: 12px;
  --font: 'Helvetica Neue', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ---- Слой 1: фотография + ночной градиент (html::before, -3) ----
   Градиент лежит в ТОМ ЖЕ псевдоэлементе поверх фото (несколько background-image):
   отдельный слой ради него не нужен. Сверху плотнее и индиговее — там шапка и
   заголовки; к низу редеет, чтобы тёплые окна и ёлка оставались видны.
   Якорь 72% 62%: при обрезке cover на 16:9 и шире ёлка (≈84% по X) и двор не уезжают. */
:root[data-theme="new-year"]::before {
  display: block;
  background-image:
    radial-gradient(120% 70% at 50% 0%, rgba(12, 18, 52, 0.55), rgba(12, 18, 52, 0) 70%),
    linear-gradient(180deg,
      rgba(6, 6, 20, 0.80) 0%,
      rgba(8, 8, 26, 0.62) 30%,
      rgba(10, 10, 30, 0.42) 62%,
      rgba(10, 10, 24, 0.30) 100%),
    url("/static/winter-night.webp");
  background-position: center, center, 72% 62%;
  background-size: cover, cover, cover;
  background-repeat: no-repeat;
  opacity: 1;
}

/* ---- Слой 2: снег (body::after дальний -2, body::before ближний -1) ----
   Тот же принцип бесшовной петли, что у тумана, но с тайлом ФИКСИРОВАННОГО размера в
   пикселях, а не «один экран»: тайл, растянутый на экран, превращал бы снежинки в
   эллипсы при любом соотношении сторон. Бокс выше вьюпорта ровно на один тайл
   (top: -H), сдвиг 0 → H = ровно один тайл, кадр конца совпадает с кадром начала
   попиксельно. Строго linear.
   Двигаем только transform (падение) и независимое свойство translate (снос ветром):
   оба уходят в композитор, слой не перерисовывается ни разу за цикл.
   Скорости спокойные: дальний план 512px за 48 с ≈ 11 px/с, ближний 640px за 40 с
   = 16 px/с. Снос ±14px с периодом 20 с — половина цикла ближнего плана, то есть
   одно дыхание, а не два разнотемповых движения. */
:root[data-theme="new-year"] body::after,
:root[data-theme="new-year"] body::before {
  display: block;
  content: "";
  position: fixed;
  left: -24px;
  right: -24px;
  bottom: 0;
  background-repeat: repeat;
  background-position: 0 0;
  pointer-events: none;
  will-change: transform;
}
:root[data-theme="new-year"] body::after {
  z-index: -2;
  top: -512px;
  background-image: url("/static/snow-far.webp");
  background-size: 512px 512px;
  opacity: 0.55;
  animation: snow-fall-far 32s linear infinite;   /* 16 px/с (было 48s ≈ 11 px/с; реш. 30.10.2026 «немного ускорить») */
}
:root[data-theme="new-year"] body::before {
  z-index: -1;
  top: -640px;
  background-image: url("/static/snow-near.webp");
  background-size: 640px 640px;
  opacity: 0.7;
  animation:
    snow-fall-near 26s linear infinite,   /* ≈ 25 px/с (было 40s ≈ 16 px/с) */
    snow-sway 10s ease-in-out infinite alternate;
}
@keyframes snow-fall-far  { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, 512px, 0); } }
@keyframes snow-fall-near { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, 640px, 0); } }
@keyframes snow-sway      { from { translate: -14px 0; } to { translate: 14px 0; } }
/* WCAG 2.2.2: бесконечное декоративное движение останавливаем полностью. Снег при этом
   остаётся на месте — неподвижные хлопья, а не пустое небо. */
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="new-year"] body::after,
  :root[data-theme="new-year"] body::before { animation: none; transform: none; translate: none; }
}

/* ---- Шапка и стекло ---- */
:root[data-theme="new-year"] .topbar {
  background: rgba(6, 6, 16, 0.78);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hairline);
}
:root[data-theme="new-year"] .glass,
:root[data-theme="new-year"] .ftab.active {
  background: linear-gradient(180deg, rgba(16, 16, 34, 0.88), rgba(12, 12, 26, 0.86));
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
/* Контейнеры — тонкая фиолетовая кайма и мягкий ореол, без тяжёлой тени (референс:
   «inset 0 0 0 1px #4f4f80, 0 0 60px rgba(79,79,128,.15)»). */
:root[data-theme="new-year"] .glass,
:root[data-theme="new-year"] .panel,
:root[data-theme="new-year"] .live-block,
:root[data-theme="new-year"] .status-block {
  border: 1px solid rgba(79, 79, 128, 0.72);
  box-shadow: 0 0 60px rgba(79, 79, 128, 0.15);
}
:root[data-theme="new-year"] .panel,
:root[data-theme="new-year"] .live-block,
:root[data-theme="new-year"] .status-block,
:root[data-theme="new-year"] .card {
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
:root[data-theme="new-year"] .cards { border-color: rgba(79, 79, 128, 0.72); }
/* Пилюли, висящие прямо на фото, получают свою плотную подложку. */
:root[data-theme="new-year"] .conv-chip,
:root[data-theme="new-year"] .live-total,
:root[data-theme="new-year"] .arrivals-bell {
  background: rgba(12, 12, 26, 0.88);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
:root[data-theme="new-year"] .menu-pop,
:root[data-theme="new-year"] .cal-pop,
:root[data-theme="new-year"] .arrivals-pop,
:root[data-theme="new-year"] .emp-timesel-pop,
:root[data-theme="new-year"] .an-tip,
:root[data-theme="new-year"] .pulse-nav,
:root[data-theme="new-year"] .cc-tip,
:root[data-theme="new-year"] .cmpc-tip {
  background: rgba(12, 12, 26, 0.94);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  border: 1px solid rgba(79, 79, 128, 0.8);
  box-shadow: 0 0 0 1px rgba(10, 10, 19, 0.6), 0 16px 40px -12px rgba(0, 0, 0, 0.6);
}
:root[data-theme="new-year"] .panel-note { background: rgba(97, 153, 246, 0.08); border-color: rgba(79, 79, 128, 0.72); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root[data-theme="new-year"] .topbar,
  :root[data-theme="new-year"] .glass,
  :root[data-theme="new-year"] .panel,
  :root[data-theme="new-year"] .card,
  :root[data-theme="new-year"] .live-block,
  :root[data-theme="new-year"] .status-block,
  :root[data-theme="new-year"] .menu-pop,
  :root[data-theme="new-year"] .cal-pop { background: #0e0e1e; }
}

/* ---- Кнопки: пилюли ----
   Главная — светлая пилюля (Carbon Vellum, обсидиановая подпись 19:1), без тени в покое;
   на наведении — iris-ореол (охват свечения согласован: CTA + переключатели). */
:root[data-theme="new-year"]:not(.tv-missed) .btn,
:root[data-theme="new-year"]:not(.tv-missed) .field,
:root[data-theme="new-year"]:not(.tv-missed) .recalc-btn,
:root[data-theme="new-year"]:not(.tv-missed) .cmp-run { border-radius: var(--radius-pill); }
/* Главная кнопка — голубая пилюля с тёмной подписью (реш. 30.10.2026; тёмный на iris 6.9:1,
   белый на iris дал бы 2.77:1 — нечитаемо). */
:root[data-theme="new-year"] .btn-cta {
  background: #6199f6;
  color: #0a0a13;
  border-color: #6199f6;
  box-shadow: none;
}
:root[data-theme="new-year"] .btn-cta:hover {
  filter: none;
  background: #7fb0ff;
  color: #0a0a13;
  border-color: #7fb0ff;
  box-shadow: var(--glow-hover);
}
/* Призрачная кнопка: кант светлеет до текста, фон не меняется. */
:root[data-theme="new-year"] .btn:not(.btn-cta):hover { border-color: #a3a3b3; }

/* ---- Активные состояния: тонированная iris-пилюля с белой подписью (12.7:1) ----
   Сплошная iris-заливка с белым текстом дала бы 2.77:1. Тёмная подпись на iris прошла
   бы (6.9:1), но шесть горящих голубых плашек на экране — это уже не «акцент хирургически». */
:root[data-theme="new-year"] .tab.active,
:root[data-theme="new-year"] .seg-btn.active,
:root[data-theme="new-year"] .an-cat.on,
:root[data-theme="new-year"] .an-cat.on:hover,
:root[data-theme="new-year"] .an-cmp-btn.on,
:root[data-theme="new-year"] .emp-timesel-opt.selected,
:root[data-theme="new-year"] .cal-day.selected,
:root[data-theme="new-year"] .cal-day.selected:hover,
:root[data-theme="new-year"] .cal-month.selected,
:root[data-theme="new-year"] .cal-month.selected:hover {
  background: rgba(97, 153, 246, 0.2);
  color: #fcfcfc;
  border-color: #6199f6;
  box-shadow: inset 0 0 0 1px #6199f6, 0 0 12px -2px rgba(97, 153, 246, 0.45);
}
/* Наведение на активный сегмент — кольцо остаётся, ореол растёт (DESIGN.md §2, п.3). */
:root[data-theme="new-year"] .seg-btn.active:not(:disabled):hover {
  box-shadow: inset 0 0 0 1px #6199f6, 0 0 14px 2px rgba(97, 153, 246, 0.36);
}
:root[data-theme="new-year"] .cmp-run {
  box-shadow: none;
}
:root[data-theme="new-year"] .ftab.active {
  box-shadow: inset 0 2px 0 var(--ember), 0 -8px 18px -10px rgba(97, 153, 246, 0.45);
}

/* ---- Бегущая кнопка сборки: та же механика (2.8 с, alternate), гамма iris ---- */
:root[data-theme="new-year"] .recalc-btn.running {
  background: rgba(16, 20, 44, 0.96);
  border-color: #6199f6;
  animation-name: recalc-shimmer-ny;
}
@keyframes recalc-shimmer-ny {
  from { border-color: #6199f6;
         box-shadow: 0 0 0 1px rgba(97, 153, 246, 0.55), 0 0 16px 3px rgba(97, 153, 246, 0.32); }
  to   { border-color: #9dbefa;
         box-shadow: 0 0 0 1px rgba(157, 190, 250, 0.75), 0 0 30px 7px rgba(97, 153, 246, 0.5); }
}
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="new-year"] .recalc-btn.running {
    animation: none;
    box-shadow: 0 0 0 1px rgba(97, 153, 246, 0.6), 0 0 18px 3px rgba(97, 153, 246, 0.38);
  }
}

/* ---- Семантика состояний не перекрашивается в бренд ----
   Пропущенный звонок «горит» — это статус, а не акцент: в тёмной теме его нёс ember,
   здесь ember стал голубым, и тревога превратилась бы в «активный пункт». */
:root[data-theme="new-year"] .live-row.sev-danger { background: rgba(255, 77, 109, 0.12); border-left-color: var(--status-bad); }
:root[data-theme="new-year"] .live-row.sev-warning { background: rgba(255, 209, 102, 0.08); border-left-color: var(--status-warn); }
:root[data-theme="new-year"] .live-age.sev-danger { color: var(--status-bad); }
:root[data-theme="new-year"] .live-age.sev-warning,
:root[data-theme="new-year"] .cmp-warn { color: var(--status-warn); }
:root[data-theme="new-year"] .live-count.has { color: var(--status-bad); border-color: var(--status-bad); }
:root[data-theme="new-year"] .disp-forgot {
  color: #fcfcfc; background: rgba(255, 90, 90, 0.18); border-color: var(--status-bad); box-shadow: none;
}
/* Плашки с подписью прямо на iris-заливке — подпись тёмная (6.9:1). */
:root[data-theme="new-year"] .login-pro-badge,
:root[data-theme="new-year"] .b2b-ag-4 { color: #0a0a13; }
:root[data-theme="new-year"] .e-day--work .e-day-tag { color: #9dbefa; }
:root[data-theme="new-year"] .emp-toast--err { color: #ffb3b3; }
:root[data-theme="new-year"] .login-msg--err { color: #ffb3b3; }

/* ---- Выручка на графиках ----
   Марки выручки в базовом CSS берут var(--ember) напрямую, а не --series-revenue.
   В тёмной теме это одно и то же; здесь --ember голубой, и выручка слилась бы с лидами.
   Переводим марки на токен серии только в этой теме — базовые правила не трогаем,
   чтобы не сдвинуть ни пикселя в двух других темах. */
:root[data-theme="new-year"] .cc-rev { stroke: var(--series-revenue); }
:root[data-theme="new-year"] .cc-dot-rev,
:root[data-theme="new-year"] .cc-rev-dot { fill: var(--series-revenue); }
:root[data-theme="new-year"] .cc-d-rev,
:root[data-theme="new-year"] .b2b-lg-rev { background: var(--series-revenue); }
:root[data-theme="new-year"] .cc-rev-c,
:root[data-theme="new-year"] .fn-total-rev { color: #ff7a40; }
:root[data-theme="new-year"] .fn-bar-2,
:root[data-theme="new-year"] .b2b-bar { background: linear-gradient(90deg, var(--series-revenue), var(--series-revenue-deep)); }

/* ---- Элементы, висящие прямо на фото ----
   Лента вкладок отделов, подписи свежести и заголовки секций лежат не на пластине,
   а на фотографии с яркими окнами. Ленте — своя плотная подложка, тексту — тень-подложка. */
:root[data-theme="new-year"] .seg {
  background: rgba(12, 12, 26, 0.88);
  border-color: rgba(79, 79, 128, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
:root[data-theme="new-year"]:not(.tv-missed) .live-title {
  text-shadow: 0 1px 2px rgba(4, 4, 12, 0.9), 0 0 12px rgba(4, 4, 12, 0.85);
}
/* Мелкая подпись свежести тенью не спасается — на светлом окне за ней 2–3:1.
   Своя плотная пилюля, как у чипа конверсии. */
:root[data-theme="new-year"]:not(.tv-missed) .live-stamp:not(:empty) {
  opacity: 1;
  color: var(--ash);
  background: rgba(12, 12, 26, 0.88);
  border: 1px solid rgba(79, 79, 128, 0.5);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
}
/* Папка вкладок /analytics: в тёмной теме это плёнка 3% — над фотографией под ней
   читались окна. Шапке папки (контролы, текст) — плотная подложка; полю папки —
   затемнение без blur: борды внутри уже стеклянные, второй backdrop-filter лишний. */
:root[data-theme="new-year"] .an-folder-head { background: rgba(12, 12, 26, 0.88); }
:root[data-theme="new-year"] .ftab-panel { background: rgba(8, 8, 20, 0.6); }

/* Логотип в шапке — ember-капибара, нарисованная файлом. Перекраска в iris фильтром:
   ember (H≈17°) → iris (H≈218°). Подпись Capybara уже iris через --ember. */
:root[data-theme="new-year"] .brand-logo,
:root[data-theme="new-year"] .login-logo { filter: hue-rotate(200deg) saturate(0.85) brightness(1.15); }

/* ---- Ледяной козырёк под шапкой (garland.js, реш. заказчика 30.10.2026) ----
   Сплошной ледяной козырёк со снежной шапкой лежит на нижней кромке .topbar; из-под него
   местами свисают сосульки, торчат еловые ветки, висит гирлянда. Картинка генерируется
   процедурно под ширину (без повторяющегося модуля), статика — один SVG фоном; свет —
   <i class="ny-bulb"> на лампочку, мерцание — ТОЛЬКО opacity (композитор), один период на
   всю гирлянду (одно дыхание, ember-glow-ui-preference).
   Узел — абсолютный ребёнок шапки: вне потока (первая секция на своём месте), свисает
   поверх контента и едет вместе со sticky-шапкой. z-index 1 внутри шапки: выше контента
   (вся шапка z 20), но ниже её выпадашек (меню/календарь z 60). Сугробы заходят на
   12px в нижний отступ шапки (18px) — кнопки не задевают.
   Вне темы и в ТВ — display:none (ширина 0, garland.js ничего не строит). */
.ny-ledge { display: none; }
:root[data-theme="new-year"]:not(.tv-missed) .ny-ledge {
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% - 12px);
  height: 92px;
  z-index: 1;
  overflow-x: clip;               /* хвост картинки не даёт горизонтальной прокрутки */
  overflow-y: visible;            /* ореолы нижних лампочек свободно ложатся на контент */
  background-repeat: no-repeat;
  background-position: 0 0;
  pointer-events: none;
}
/* Козырёк вылетает под шапку на ~52px (лампочки, длинные сосульки, ветки). Чтобы он не
   висел на первой строке страницы («На линии», «Период отчёта»), шапка в этой теме
   отодвигает контент полем снизу: декор остаётся прикреплён к sticky-шапке, а при
   прокрутке содержимое уходит под него. Допустимый нахлёст — кончики сосулек ~10px. */
:root[data-theme="new-year"]:not(.tv-missed) .view > .topbar { margin-bottom: 32px; }
.ny-ledge-lights { position: absolute; inset: 0; }
.ny-bulb {
  position: absolute;
  width: 60px;
  height: 60px;
  margin: -30px 0 0 -30px;
  border-radius: 50%;
  opacity: 0.32;
  animation: ny-twinkle 3.6s ease-in-out infinite;
}
@keyframes ny-twinkle {
  0%, 100% { opacity: 0.32; }
  50%      { opacity: 1; }
}
@media (max-width: 768px) {
  /* картинка в масштабе 0.72; отступ шапки тут 16px, кнопки переносятся — сугробы
     поднимаются над кромкой не выше ~5px, чтобы не задевать «Меню» */
  :root[data-theme="new-year"]:not(.tv-missed) .ny-ledge { top: calc(100% - 5px); height: 66px; }
  :root[data-theme="new-year"]:not(.tv-missed) .view > .topbar { margin-bottom: 22px; }
}
/* WCAG 2.2.2: без мерцания лампочки горят ровно. */
@media (prefers-reduced-motion: reduce) {
  .ny-bulb { animation: none; opacity: 0.9; }
}
html.tv-missed .ny-ledge { display: none !important; }

* { box-sizing: border-box; }

html { background: var(--obsidian); }

/* ---- Background photo underlay (behind the brand watermark) ---- */
html::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -3;
  background-image: url("/static/low_fone.webp");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  opacity: 0.35;
  pointer-events: none;
}

body {
  margin: 0;
  font-family: var(--font);
  background: transparent;
  color: var(--ash);
  font-size: var(--fs-lg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ---- Background brand watermark ---- */
/* The iBrat wordmark stretched across the canvas, recolored ember, 90% transparent. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image: url("/static/logo-watermark.svg");
  background-repeat: no-repeat;
  /* Anchored over the metrics row, behind the foreground blocks. */
  background-position: 83% 78%;
  background-size: 77% auto;
  opacity: 0.2;
  pointer-events: none;
}
/* Darkening gradient from the bottom up — sits below the watermark so it darkens
   the canvas without washing out the logo. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background: linear-gradient(to top,
    var(--obsidian) 0%,
    rgba(15, 13, 10, 0.85) 22%,
    rgba(15, 13, 10, 0.35) 55%,
    rgba(15, 13, 10, 0) 100%);
  pointer-events: none;
}

/* ---- Top navigation ---- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 40px;
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(15, 13, 10, 0.85);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--hairline);
}
.brand { display: flex; align-items: center; gap: 11px; }
.brand-logo { height: 34px; width: auto; display: block; object-fit: contain; }
.brand-dot {
  width: 13px; height: 13px; border-radius: var(--radius-pill);
  background: var(--ember);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 16px 2px var(--ember-glow);
}
.brand-word {
  color: var(--ember);
  font-family: 'Baloo 2', var(--font);
  font-weight: 700;
  font-size: var(--fs-3xl);
  letter-spacing: 0.01em;
  line-height: 1;
}
.brand-sub { color: var(--ash); font-size: var(--fs-sm); letter-spacing: 0.01em; opacity: 0.7; }

.controls { display: flex; align-items: center; gap: 10px; }
.field {
  background: var(--graphite);
  border: 1px solid var(--hairline-strong);
  color: var(--bone);
  height: var(--control-h);
  padding: 0 11px;
  border-radius: var(--radius-xs);
  font-size: var(--fs-md);
  font-family: var(--font);
}
.btn {
  border: 1px solid var(--hairline-strong);
  background: transparent;
  color: var(--ash);
  border-radius: var(--radius-xs);
  height: var(--control-h);
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: var(--fs-md);
  font-weight: 500;
  font-family: var(--font);
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.btn:hover { color: var(--bone); border-color: var(--ash); }
.btn-sm { padding: 6px 12px; font-size: var(--fs-sm); }
.btn-cta {
  background: var(--ember);
  color: var(--on-brand);
  border-color: var(--ember);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 24px 4px var(--ember-glow);
  /* box-shadow добавлен в переход намеренно: у .btn его в списке нет, и без
     этого свечение на наведении включалось бы рывком, а гасло мгновенно. */
  transition: color 0.15s, border-color 0.15s, background 0.15s, box-shadow 0.22s ease;
}
/* Свечение на наведении ОБЯЗАНО быть крупнее базового (24px/4px), иначе на
   hover оно сжимается вместо роста — жест читается как «кнопка отодвинулась». */
.btn-cta:hover { filter: brightness(1.08); color: var(--bone); border-color: var(--ember); box-shadow: var(--glow-hover); }

/* Compact square icon button (refresh) — square at the shared control height. */
.btn-icon { width: var(--control-h); padding: 0; line-height: 0; }
.btn-icon svg { display: block; }

/* ---- Dropdown menu (glass, matches the calendar popup) ---- */
.menu { position: relative; }
.menu-caret { font-size: var(--fs-2xs); opacity: 0.9; margin-left: 2px; }
.menu-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  min-width: 220px;
  padding: 6px;
  border-radius: var(--radius-inner);
  background: rgba(20, 17, 14, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(var(--tint-rgb), 0.16);
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(var(--tint-rgb), 0.06);
  animation: cal-in 0.14s ease-out;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .menu-pop { background: rgba(29, 26, 23, 0.98); }
}
.menu-item {
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--radius-ctl);
  color: var(--bone);
  padding: 10px 12px;
  font-size: var(--fs-md);
  font-family: var(--font);
  cursor: pointer;
  /* Одна строка: попап растягивается под самый длинный пункт, а align-items:stretch делает
     все пункты равной ширины И высоты (длинный текст иначе переносился и был выше). */
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.menu-item:hover { background: rgba(var(--tint-rgb), 0.1); }

/* ---- Glassmorphism date picker ---- */
.datefield { position: relative; }
.date-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 0; cursor: pointer; white-space: nowrap;
}
.date-trigger #dateLabel { color: var(--bone); font-variant-numeric: tabular-nums; }
.date-trigger:hover { border-color: var(--ash); }
/* Заблокирован на время сборки отчёта (нельзя менять месяц, пока идёт джоб). */
.date-trigger:disabled { opacity: 0.45; cursor: not-allowed; }
.date-trigger:disabled:hover { border-color: var(--hairline); }

.cal-pop {
  position: absolute;
  top: -4px;
  right: 0;
  z-index: 60;
  width: 300px;
  padding: 16px;
  border-radius: var(--radius-card);
  color: var(--bone);
  /* Glassmorphism tuned for the obsidian canvas: dark-tinted glass, light edge. */
  background: rgba(20, 17, 14, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(var(--tint-rgb), 0.16);
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(var(--tint-rgb), 0.06);
  animation: cal-in 0.14s ease-out;
}
/* Fallback for browsers without backdrop-filter — keep it readable, not transparent. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cal-pop { background: rgba(29, 26, 23, 0.98); }
}
@keyframes cal-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}

.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-title { color: var(--bone); font-weight: 700; font-size: var(--fs-lg); letter-spacing: -0.01em; }
.cal-nav { display: flex; gap: 6px; }
.cal-nav button {
  width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: var(--radius-pill); cursor: pointer; font-size: var(--fs-lg); line-height: 1;
  color: var(--ash);
  background: rgba(var(--tint-rgb), 0.05);
  border: 1px solid rgba(var(--tint-rgb), 0.14);
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.cal-nav button:hover { color: var(--bone); border-color: rgba(var(--tint-rgb), 0.4); background: rgba(var(--tint-rgb), 0.12); }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cal-dow {
  text-align: center; font-size: var(--fs-2xs); padding-bottom: 4px;
  color: var(--ash-dim); text-transform: uppercase; letter-spacing: 0.04em;
}
.cal-day {
  aspect-ratio: 1 / 1; display: grid; place-items: center;
  border-radius: var(--radius-block); cursor: pointer; font-size: var(--fs-md);
  color: var(--bone); background: transparent; border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.cal-day:hover { background: rgba(var(--tint-rgb), 0.12); }
.cal-day.muted { color: var(--ink-dim); }
.cal-day.today { border-color: rgba(var(--tint-rgb), 0.35); }
.cal-day.selected {
  background: var(--ember); color: var(--bone); font-weight: 700;
  border-color: var(--ember);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 14px 2px var(--ember-glow);
}
.cal-day.selected:hover { background: var(--ember); }

.cal-foot { display: flex; justify-content: flex-end; margin-top: 12px; }
.cal-today {
  background: transparent; border: 1px solid rgba(var(--tint-rgb), 0.16);
  color: var(--ash); border-radius: var(--radius-pill); padding: 5px 14px;
  font-size: var(--fs-sm); cursor: pointer; font-family: var(--font);
  transition: color 0.12s, border-color 0.12s;
}
.cal-today:hover { color: var(--bone); border-color: var(--ash); }

/* Месяц-грид (выбор периода отчёта: месяц + год). Стиль наследует день-календарь. */
.cal-months { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.cal-month {
  display: grid; place-items: center; padding: 10px 6px;
  border-radius: var(--radius-block); cursor: pointer; font-size: var(--fs-md);
  color: var(--bone); background: transparent; border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.cal-month:hover { background: rgba(var(--tint-rgb), 0.12); }
.cal-month.today { border-color: rgba(var(--tint-rgb), 0.35); }
.cal-month.selected {
  background: var(--ember); color: var(--bone); font-weight: 700; border-color: var(--ember);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 14px 2px var(--ember-glow);
}
.cal-month.selected:hover { background: var(--ember); }

/* ---- Loading line ---- */
/* A thin ember bar sitting between the topbar and the content (just under the
   calendar/buttons row). Its width = real rebuild progress reported by
   /api/dashboard/progress. */
.progress {
  width: 100%;
  height: 3px;
  background: transparent;
  pointer-events: none;
}
.progress-bar {
  height: 100%;
  width: 0;
  background: var(--ember);
  box-shadow: 0 0 8px 1px var(--ember-glow);
  /* Eases between the discrete stage jumps for a smooth left→right fill. */
  transition: width 0.4s ease, opacity 0.3s ease;
}

.status { padding: 12px 40px 0; color: var(--ash); min-height: 14px; font-size: var(--fs-sm); }
.status.error { color: var(--ember); }
.status.loading { color: var(--ash); }

/* ---- LIVE section (primary) ---- */
/* Symmetric vertical rhythm: the gap between two sections (12+12) equals the
   gap below each heading (24), so each title sits centered between block groups. */
.live-section { padding: 12px 40px; }
.live-section:first-of-type { padding-top: 22px; }
.live-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px; margin-bottom: 24px;
}
.live-title {
  margin: 0;
  font-size: var(--fs-3xl);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1;
  color: var(--bone);
  display: flex; align-items: center; gap: 11px;
}
.pulse {
  width: 12px; height: 12px; border-radius: var(--radius-pill); background: var(--ember);
  box-shadow: 0 0 0 0 rgba(var(--ember-rgb), 0.6);
  animation: pulse 1.8s infinite;
}
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--ember-rgb), 0.55); }
  70% { box-shadow: 0 0 0 12px rgba(var(--ember-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--ember-rgb), 0); }
}
.live-meta { display: flex; align-items: center; gap: 16px; font-size: var(--fs-sm); color: var(--ash); }
.autorefresh { display: flex; align-items: center; gap: 7px; cursor: pointer; opacity: 0.85; }
.autorefresh input { accent-color: var(--ember); }
.live-stamp { color: var(--ash); opacity: 0.7; font-variant-numeric: tabular-nums; }

/* Day-conversion chip in the "На линии" head (won deals ÷ incoming leads). */
.conv-chip {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--graphite); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-pill); padding: 8px 16px;
  font-size: var(--fs-sm); color: var(--ash); white-space: nowrap;
}
.conv-chip b {
  color: var(--ember); font-weight: 700; font-size: var(--fs-xl);
  letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1;
}

/* Корона «на линии» — заменила зелёный кружок 10.08.2026. Свечение сделано
   drop-shadow, а не box-shadow: последний обвёл бы ПРЯМОУГОЛЬНИК вокруг иконки,
   а drop-shadow повторяет контур короны. Период 2.4 с — «спокойное дыхание» по
   доктрине движения, у элемента одна анимация. */
.crown-online {
  flex: none;
  color: var(--online);
  animation: crown-online 2.4s ease-in-out infinite;
}
@keyframes crown-online {
  0%, 100% { filter: drop-shadow(0 0 1px rgba(var(--online-rgb), 0.35)); }
  50%      { filter: drop-shadow(0 0 7px rgba(var(--online-rgb), 0.85)); }
}
@media (prefers-reduced-motion: reduce) {
  /* Здесь именно animation:none, а не длительность: это бесконечный пульс, а не переход. */
  .crown-online { animation: none; filter: drop-shadow(0 0 4px rgba(var(--online-rgb), 0.5)); }
}
.live-total {
  font-size: var(--fs-sm); font-weight: 500; color: var(--ash);
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-pill);
  padding: 2px 10px; letter-spacing: 0; align-self: center;
}

.live-blocks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 18px;
}

/* On-shift (status) blocks */
/* «На линии» — горизонтальная лента: показываем --status-visible карточек, остальные скрыты справа
   и доступны прокруткой (свайп на мобиле). Так «этаж» не растёт вниз и не грузит интерфейс.
   flex-grow:1 → когда карточек мало, они растягиваются на всю ширину (без пустоты справа);
   flex-shrink:0 + flex-basis под --status-visible → когда карточек много, ширина держится и включается
   горизонтальная прокрутка (≈5 видно, остальные листаются). */
.status-blocks {
  --status-gap: 18px;
  --status-visible: 5;
  display: flex;
  gap: var(--status-gap);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;      /* инерционный скролл на iOS */
  scrollbar-width: none;                  /* полосу прокрутки прячем — чище и современнее (скролл остаётся) */
  -ms-overflow-style: none;
}
.status-blocks::-webkit-scrollbar { display: none; }   /* WebKit/Blink */
.status-block {
  background: var(--graphite); border: 1px solid var(--hairline); border-radius: var(--radius-block);
  overflow: hidden; min-width: 0; scroll-snap-align: start;
  flex: 1 0 calc((100% - (var(--status-visible) - 1) * var(--status-gap)) / var(--status-visible));
}
.status-block-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 15px; border-bottom: 1px solid var(--hairline);
}
.status-dept { color: var(--bone); font-weight: 700; font-size: var(--fs-md); }
.status-count {
  font-size: var(--fs-xs); color: var(--online); border: 1px solid rgba(var(--online-rgb), 0.4);
  border-radius: var(--radius-pill); padding: 2px 9px;
}
.status-person {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 9px 15px; border-bottom: 1px solid var(--hairline);
}
.status-person:last-child { border-bottom: none; }
.status-name { color: var(--bone); font-size: var(--fs-md); }
.status-name .dot { color: var(--online); margin-right: 7px; }
.status-shift { color: var(--ash); font-size: var(--fs-sm); opacity: 0.7; white-space: nowrap; }
.status-empty { padding: 18px 15px; color: var(--ash); opacity: 0.5; font-size: var(--fs-sm); }
.live-block {
  background: var(--graphite);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-block);
  overflow: hidden;
}
.live-block-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px;
  border-bottom: 1px solid var(--hairline);
}
.live-block-title { color: var(--bone); font-weight: 700; font-size: var(--fs-lg); letter-spacing: -0.01em; }
.live-count {
  font-size: var(--fs-xs); color: var(--ash); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-pill); padding: 2px 10px;
}
.live-count.has { color: var(--ember); border-color: var(--ember); }
.live-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 12px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--hairline);
}
.live-row:last-child { border-bottom: none; }
.live-row.sev-danger { background: rgba(var(--ember-rgb), 0.10); border-left: 3px solid var(--ember); }
.live-row.sev-warning { background: rgba(139, 46, 9, 0.18); border-left: 3px solid var(--ember-glow); }
.live-crm { color: var(--bone); font-weight: 500; font-size: var(--fs-lg); }
.live-crm a { color: var(--bone); text-decoration: none; border-bottom: 1px solid var(--hairline-strong); }
.live-crm a:hover { color: var(--ember); border-color: var(--ember); }
.live-age { color: var(--ash); font-size: var(--fs-sm); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.live-age.sev-danger { color: var(--ember); font-weight: 700; }
.live-age.sev-warning { color: #d98a5a; font-weight: 600; }
.live-sub { grid-column: 1 / -1; color: var(--ink-soft); font-size: var(--fs-sm); }
.live-empty { padding: 22px 16px; color: var(--ink-muted); font-size: var(--fs-sm); }
.live-more {
  padding: 8px 16px; font-size: var(--fs-xs); color: var(--ash); opacity: 0.6;
  border-top: 1px dashed var(--hairline); letter-spacing: 0.02em;
}

/* ---- ТВ-режим пропущенных (30.10.2026) ----
   Дешёвый LG-телевизор на стене отдела продаж: блок «Пропущенные звонки» на весь экран.
   Браузер webOS — старый Chromium, поэтому здесь сознательно НЕТ :has(), container
   queries, вложенности, flex-gap (Chrome < 84) и inset (Chrome < 87): зазоры сделаны
   полями, позиционирование — top/right/bottom/left. Каждый clamp() идёт после фолбэка
   на vh: браузер без clamp() отбросит вторую строку и возьмёт первую.
   Цвета — ЛИТЕРАЛАМИ, а не токенами: ТВ всегда тёмный и контрастный, в какой бы теме ни
   сидел браузер, и не зависит от поддержки CSS-переменных. Стекла и blur нет: на дешёвой
   матрице размытие съедает буквы, а под оверлеем всё равно нет картинки. */
.tv-stamp { display: none; }
.tv-btn svg { flex: none; margin-right: 6px; }
.tv-btn[aria-pressed="true"] { color: var(--ember); border-color: var(--ember); }
/* Кнопка «ТВ» — в карточке отдела продаж, правее названия, перед счётчиком (30.10.2026). */
.live-block-head .tv-btn { margin-left: auto; margin-right: 10px; flex: none; }

html.tv-missed,
html.tv-missed body { overflow: hidden; height: 100%; }
/* Всё прочее на дашборде не рисуем: меньше работы старому ТВ-браузеру и никакой прокрутки. */
html.tv-missed #app-dashboard > :not(.live-missed) { display: none !important; }
/* Фоновые слои (фото, знак, анимированный туман светлой темы) под непрозрачным оверлеем не
   видны, но продолжали бы крутить композитор — гасим. !important: светлая тема включает
   body::after правилом с более тяжёлым селектором. */
html.tv-missed::before,
html.tv-missed body::before,
html.tv-missed body::after { display: none !important; animation: none !important; }

html.tv-missed .live-missed {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 100;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 2.4vh 2.2vw 2.2vh;
  background: #0f0d0a;
  color: #e6e2dd;
}
html.tv-missed .live-missed *,
html.tv-missed .live-missed *::before,
html.tv-missed .live-missed *::after {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
html.tv-missed .live-missed .live-head {
  flex: none;
  flex-wrap: nowrap;
  margin: 0 0 2.2vh;
}
html.tv-missed .live-missed .live-title {
  color: #ffffff;
  font-size: 4.6vh;
  font-size: clamp(26px, 4.6vh, 64px);
}
html.tv-missed .live-missed .pulse {
  background: #ff4700;
  width: 2vh; height: 2vh; min-width: 12px; min-height: 12px;
  margin-right: 1.4vh;
}
html.tv-missed .live-missed #statusStamp { display: none; }
html.tv-missed .live-missed .tv-stamp {
  display: inline;
  color: #d6d1cb;
  opacity: 1;
  font-size: 2.8vh;
  font-size: clamp(16px, 2.8vh, 38px);
  margin-right: 1.6vw;
  white-space: nowrap;
}
html.tv-missed .live-missed .tv-stamp.is-stale { color: #ff8a5c; font-weight: 700; }
/* Звук ТВ (31.10.2026, tv_sound.js). Пока браузер не разрешил звук (нужен жест) — заметная, но
   спокойная пилюля «Включить звук» (ember-кайма, без анимации); после — тихий переключатель
   «Звук вкл / выкл», приглушённый, как кнопка «ТВ». Вне ТВ не рисуется вовсе. */
.tv-sound { display: none; }
html.tv-missed .live-missed .tv-sound.is-locked,
html.tv-missed .live-missed .tv-sound.is-on,
html.tv-missed .live-missed .tv-sound.is-off {
  display: inline-flex;
  align-items: center;
  flex: none;
  font: inherit;
  font-weight: 600;
  font-size: 2.2vh;
  font-size: clamp(13px, 2.2vh, 30px);
  line-height: 1.2;
  padding: 0.7vh 1.2vw;
  border-radius: 9999px;
  border: 1px solid rgba(204, 204, 204, 0.35);
  background: transparent;
  color: #cccccc;
  cursor: pointer;
  white-space: nowrap;
  -webkit-transition: opacity 0.4s ease, border-color 0.4s ease;
  transition: opacity 0.4s ease, border-color 0.4s ease;
}
html.tv-missed .live-missed .tv-sound svg {
  width: 1.1em; height: 1.1em;
  flex: none;
  margin-right: 0.45em;
}
html.tv-missed .live-missed .tv-sound.is-on,
html.tv-missed .live-missed .tv-sound.is-off { opacity: 0.55; }
html.tv-missed .live-missed .tv-sound.is-off { opacity: 0.45; }
html.tv-missed .live-missed .tv-sound.is-locked {
  color: #ffd9c7;
  border-color: rgba(255, 71, 0, 0.75);
  background: rgba(255, 71, 0, 0.14);
}
html.tv-missed .live-missed .tv-sound:hover,
html.tv-missed .live-missed .tv-sound:focus { opacity: 1; outline: none; border-color: #ff8a4c; }
/* Кнопка выхода нужна пульту/мыши, но не должна спорить с цифрами. */
html.tv-missed .live-missed .tv-btn {
  opacity: 0.55;
  color: #cccccc;
  border-color: rgba(204, 204, 204, 0.35);
  background: transparent;
}
html.tv-missed .live-missed .tv-btn:hover,
html.tv-missed .live-missed .tv-btn:focus { opacity: 1; }
html.tv-missed .live-missed .arrivals { display: none; }

/* Колонки отделов: flex с отрицательным полем вместо gap. «Отдел продаж» — первым и шире:
   телевизор висит у них, остальные два отдела — для общего фона. */
html.tv-missed .live-missed .live-blocks {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: stretch;
  margin: 0 -0.8vw;
}
html.tv-missed .live-missed .live-block {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  margin: 0 0.8vw;
  display: flex;
  flex-direction: column;
  background: #1a1714;
  border: 1px solid rgba(204, 204, 204, 0.18);
  border-radius: 14px;
  box-shadow: none;
}
html.tv-missed .live-missed .live-block[data-key="sales"] {
  order: -1;
  flex-grow: 1.6;
  border-color: rgba(255, 71, 0, 0.55);
}
html.tv-missed .live-missed .live-block.tv-off { display: none; }
html.tv-missed .live-missed .live-block-head {
  flex: none;
  padding: 1.8vh 1.4vw;
  border-bottom: 1px solid rgba(204, 204, 204, 0.18);
}
html.tv-missed .live-missed .live-block-title {
  color: #ffffff;
  font-size: 3.4vh;
  font-size: clamp(19px, 3.4vh, 46px);
  line-height: 1.15;
  min-width: 0;
  margin-right: 1vw;
}
html.tv-missed .live-missed .live-count {
  flex: none;
  min-width: 2.2em;
  text-align: center;
  font-size: 5vh;
  font-size: clamp(26px, 5vh, 72px);
  font-weight: 800;
  line-height: 1.1;
  padding: 0.1em 0.5em;
  color: #9d9c9c;
  background: transparent;
  border: 2px solid rgba(204, 204, 204, 0.35);
  border-radius: 9999px;
  font-variant-numeric: tabular-nums;
}
html.tv-missed .live-missed .live-count.has {
  color: #ffffff;
  background: #ff4700;
  border-color: #ff4700;
}
/* Список отдела: растягивается на всю высоту карточки; если строк больше, чем влезает,
   прокручивается (на ТВ — автоматически, см. tvScrollTick в app.js), шапка стоит. */
html.tv-missed .live-missed .live-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}
html.tv-missed .live-missed .live-list::-webkit-scrollbar { display: none; }
html.tv-missed .live-missed .live-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  padding: 1.6vh 1.4vw;
  background: transparent;
  border-left: 0.5vw solid transparent;
  border-bottom: 1px solid rgba(204, 204, 204, 0.16);
}
html.tv-missed .live-missed .live-row.sev-danger { background: rgba(255, 71, 0, 0.16); border-left-color: #ff4700; }
html.tv-missed .live-missed .live-row.sev-warning { background: rgba(217, 138, 90, 0.14); border-left-color: #d98a5a; }
/* Имя/номер и «сколько ждёт» — в одну строку, пока колонка позволяет. Номер телефона
   неразрывен (.nb) и через min-width:auto держит свою ширину: если в узкой колонке он не
   помещается рядом с возрастом, возраст уходит отдельной строкой вправо, а номер целым. */
html.tv-missed .live-missed .live-crm {
  flex: 1 1 8em;
  margin-right: 1vw;
  color: #ffffff;
  font-weight: 700;
  font-size: 3.6vh;
  font-size: clamp(20px, 3.6vh, 50px);
  line-height: 1.2;
  word-wrap: break-word;
  overflow-wrap: break-word;
}
html.tv-missed .live-missed .live-crm a { color: #ffffff; border-bottom: none; }
html.tv-missed .live-missed .live-crm .nb { white-space: nowrap; }
html.tv-missed .live-missed .live-age {
  flex: none;
  margin-left: auto;
  color: #e6e2dd;
  font-size: 3.6vh;
  font-size: clamp(20px, 3.6vh, 50px);
  font-weight: 700;
  line-height: 1.2;
}
html.tv-missed .live-missed .live-age.sev-danger { color: #ff6a2b; }
html.tv-missed .live-missed .live-age.sev-warning { color: #f0a070; }
/* Новогодняя тема на ТВ: оверлей тёмный, но тревога — праздничной парой, как на дашборде. */
:root[data-theme="new-year"].tv-missed .live-missed .live-row.sev-danger { background: rgba(255, 77, 109, 0.16); border-left-color: #ff4d6d; }
:root[data-theme="new-year"].tv-missed .live-missed .live-row.sev-warning { background: rgba(255, 209, 102, 0.12); border-left-color: #ffd166; }
:root[data-theme="new-year"].tv-missed .live-missed .live-age.sev-danger { color: #ff4d6d; }
:root[data-theme="new-year"].tv-missed .live-missed .live-age.sev-warning { color: #ffd166; }
/* Счётчик пропущенных на ТВ: красная заливка, тёмная цифра (#0a0a13 на #ff4d6d — 6.4:1). */
:root[data-theme="new-year"].tv-missed .live-missed .live-count.has { color: #0a0a13; background: #ff4d6d; border-color: #ff4d6d; }
:root[data-theme="new-year"].tv-missed .live-missed .live-block[data-key="sales"] { border-color: rgba(97, 153, 246, 0.55); }
:root[data-theme="new-year"].tv-missed .live-missed .pulse { background: #6199f6; }
:root[data-theme="new-year"].tv-missed .live-missed .live-more { border-top-color: rgba(97, 153, 246, 0.45); color: #9cc0ff; }

/* ---- ТВ-режим в новогодней теме: козырёк, гирлянда-индикатор, иней, «так держать» ----
   (реш. заказчика 31.10.2026). Всё — только при data-theme="new-year" И html.tv-missed;
   в остальных темах ТВ строгий, как был. Узлы ставит garland.js в стабильную секцию
   #liveMissed (не в перерисовываемый #liveBlocks): анимации не рестартуют раз в минуту.
   Старый Chromium webOS: без inset/gap/:has(), только top/left/width/height. */
.ny-tv-ledge,
.ny-tv-frost,
.ny-empty-ico,
.ny-empty-cheer { display: none; }
/* Место под козырёк: верхнее поле экрана 2.4vh → 8.4vh (+~46 px на 768). Картинка козырька
   в масштабе s = высота узла / 92 = vh·12/92 ≈ innerHeight/767 (768 → 1.0, 1080 → 1.41);
   поднята на 1vh (≈ 7.7·s из 12·s сугробов) — верх экрана срезает макушки сугробов, кромка
   снега почти сплошная; лампы кончаются на ~54·s от верха экрана. */
:root[data-theme="new-year"].tv-missed .live-missed { padding-top: 8.4vh; }
:root[data-theme="new-year"].tv-missed .live-missed .live-head,
:root[data-theme="new-year"].tv-missed .live-missed .live-blocks { position: relative; z-index: 2; }
:root[data-theme="new-year"].tv-missed .ny-tv-ledge {
  display: block;
  position: absolute;
  top: -1vh;
  left: 0;
  width: 100%;
  height: 12vh;
  z-index: 1;
  overflow: hidden;
  background-repeat: no-repeat;
  background-position: 0 0;
  pointer-events: none;
}
:root[data-theme="new-year"].tv-missed .ny-tv-calm,
:root[data-theme="new-year"].tv-missed .ny-tv-alarm,
:root[data-theme="new-year"].tv-missed .ny-tv-breathe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
/* Индикатор: спокойно — разноцветное мерцание; есть пропущенные — за 1.8 с всё стекло
   становится красным (#ff4d6d) и медленно дышит одним общим пульсом. Переход — opacity
   двух слоёв; спрятанный слой ставит свои анимации на паузу (композитору нечего крутить). */
:root[data-theme="new-year"].tv-missed .ny-tv-calm { opacity: 1; transition: opacity 1.8s ease-in-out; }
:root[data-theme="new-year"].tv-missed .ny-tv-alarm {
  opacity: 0;
  transition: opacity 1.8s ease-in-out;
  background-repeat: no-repeat;
  background-position: 0 0;
}
:root[data-theme="new-year"].tv-missed .tv-alarm .ny-tv-calm { opacity: 0; }
:root[data-theme="new-year"].tv-missed .tv-alarm .ny-tv-alarm { opacity: 1; }
:root[data-theme="new-year"].tv-missed .tv-alarm .ny-tv-calm .ny-bulb { animation-play-state: paused; }
.ny-tv-red {
  position: absolute;
  width: 60px;
  height: 60px;
  margin: -30px 0 0 -30px;
  border-radius: 50%;
}
.ny-tv-breathe { animation: ny-breathe 3.6s ease-in-out infinite; animation-play-state: paused; }
:root[data-theme="new-year"].tv-missed .tv-alarm .ny-tv-breathe { animation-play-state: running; }
@keyframes ny-breathe {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 1; }
}
/* Иней в нижних углах: статичный SVG (garland.js, CapyFrost), растёт только в полосе
   без текста — поле слева/справа от строк (3.2vw) и поле под карточкой (2vh). Поверх
   карточки, мышь не ловит. Анимации нет. */
:root[data-theme="new-year"].tv-missed .ny-tv-frost {
  display: block;
  position: absolute;
  bottom: 0;
  width: 30vw;
  height: 58vh;
  z-index: 3;
  background-repeat: no-repeat;
  background-position: 0 0;
  pointer-events: none;
}
:root[data-theme="new-year"].tv-missed .ny-tv-frost-l { left: 0; }
:root[data-theme="new-year"].tv-missed .ny-tv-frost-r { right: 0; }
/* «Нет пропущенных — так держать!»: снежинка со статичным ореолом (радиальный градиент,
   без filter/blur) и крупный текст. #f2f6ff на #1a1714 — 16.9:1, #9cc0ff — 9.3:1. */
:root[data-theme="new-year"].tv-missed .live-missed .live-empty {
  flex-direction: column;
  color: #f2f6ff;
  font-weight: 700;
  font-size: 4.6vh;
  font-size: clamp(24px, 4.6vh, 64px);
  line-height: 1.25;
}
:root[data-theme="new-year"].tv-missed .live-missed .ny-empty-ico {
  display: block;
  width: 22vh;
  height: 22vh;
  margin-bottom: 2.4vh;
  padding: 4.5vh;
  color: #d9e8ff;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(97, 153, 246, 0.34) 0%, rgba(97, 153, 246, 0.14) 55%, rgba(97, 153, 246, 0) 100%);
}
:root[data-theme="new-year"].tv-missed .live-missed .ny-empty-ico svg { display: block; width: 100%; height: 100%; }
:root[data-theme="new-year"].tv-missed .live-missed .ny-empty-cheer { display: inline; color: #9cc0ff; }
@media (prefers-reduced-motion: reduce) {
  .ny-tv-breathe { animation: none; opacity: 0.9; }
}

/* ---- ТВ в новогодней теме: фон-фото и падающий снег (реш. заказчика 31.10.2026) ----
   Снег — те же слои, что на дашборде: body::after (-2) дальний, body::before (-1) ближний.
   Базовое ТВ-правило гасит их `display:none !important` — здесь включаем обратно тоже через
   !important и более тяжёлый селектор (только new-year + ТВ). Фото — фоном самого <html>.
   Оверлей .live-missed (fixed, z 100) становится прозрачным: фото и снег видны в полях,
   за шапкой и козырьком, а карточка отдела НЕПРОЗРАЧНА — снег идёт ПОД ней и через текст
   строк не просвечивает. Рубильники для слабых ТВ (app.js, помнятся в localStorage):
   &snow=0 → html.tv-nosnow (фон есть, снега нет); &bg=0 → html.tv-nobg (ТВ как до правки).
   Старый Chromium webOS: свойство `translate` (снос ветром) там не поддержано и просто не
   работает, падение (transform) — работает; боксы снега заданы top/left/right/bottom. */
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) {
  /* Фото — фоном САМОГО <html> (холст корневого слоя), а не html::before: псевдоэлемент
     на ТВ становился отдельным композитным слоем во весь экран (+4 МБ на 1366, +8 на 1920).
     Ночь гуще, чем на дашборде (там 0.80 → 0.30): фокус — карточка, фото — рама. Сверху
     плотнее всего — там заголовок и козырёк. Отдельная копия фото 1280×720 (~150 КБ): на ТВ
     оно затемнено и видно в полях, полный размер — лишняя память текстуры. */
  background-color: #07070f;
  background-image:
    radial-gradient(90% 60% at 50% 0%, rgba(8, 12, 40, 0.5), rgba(8, 12, 40, 0) 70%),
    linear-gradient(180deg,
      rgba(4, 4, 14, 0.84) 0%,
      rgba(5, 5, 18, 0.70) 24%,
      rgba(6, 6, 20, 0.54) 60%,
      rgba(6, 6, 18, 0.56) 100%),
    url("/static/winter-night-tv.webp");
  background-position: center, center, 72% 62%;
  background-size: cover, cover, cover;
  background-repeat: no-repeat;
}
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed { background: transparent; }
/* Карточка — плотная ночная плита (не стекло: под ней движется снег, а текст строк обязан
   стоять на ровном фоне). Без тени: размытая тень поднималась к козырьку, и композитор
   выносил весь список в отдельный слой (+4 МБ) из-за перекрытия с анимированной гирляндой. */
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed .live-block { background: #13131f; }
/* Заголовок и штамп стоят прямо на фото и снегу — тени мало (замер: хлопья и окна за
   буквами давали 4.4:1 у заголовка и 2.7:1 у штампа). Каждому — своя плотная пилюля,
   как у штампа/чипа на дашборде; сквозь 0.9 хлопья едва угадываются, текст на ровном. */
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed .live-title,
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed .tv-stamp {
  background: rgba(10, 10, 24, 0.9);
  border: 1px solid rgba(79, 79, 128, 0.55);
  border-radius: 9999px;
}
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed .live-title { padding: 0.5vh 1.8vw 0.5vh 1.3vw; }
/* Поле под шапкой (2.2vh) НЕ ужимать: при 0.6vh верх списка заходил в границы слоя
   «дышащей» гирлянды, и композитор поднимал весь список в отдельный слой во весь экран. */
:root[data-theme="new-year"].tv-missed:not(.tv-nobg) .live-missed .tv-stamp { padding: 0.6vh 1.2vw; }
/* Кнопка звука на фото — своя плотная пилюля, как у штампа; призыв — iris вместо ember. */
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound.is-locked,
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound.is-on,
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound.is-off {
  background: rgba(10, 10, 24, 0.9);
  border-color: rgba(79, 79, 128, 0.55);
}
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound.is-locked {
  color: #dbe6ff;
  border-color: rgba(97, 153, 246, 0.85);
  background: rgba(16, 22, 44, 0.92);
}
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound:hover,
:root[data-theme="new-year"].tv-missed .live-missed .tv-sound:focus { border-color: #9cc0ff; }
/* Снег: те же тайлы, бокс и скорости, что на дашборде (32 с / 26 с + снос 10 с). */
:root[data-theme="new-year"].tv-missed:not(.tv-nobg):not(.tv-nosnow) body::after {
  display: block !important;
  animation: snow-fall-far 32s linear infinite !important;
}
:root[data-theme="new-year"].tv-missed:not(.tv-nobg):not(.tv-nosnow) body::before {
  display: block !important;
  animation: snow-fall-near 26s linear infinite, snow-sway 10s ease-in-out infinite alternate !important;
}
/* reduced-motion: хлопья стоят на месте (как на дашборде), фон остаётся. */
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="new-year"].tv-missed:not(.tv-nobg):not(.tv-nosnow) body::after,
  :root[data-theme="new-year"].tv-missed:not(.tv-nobg):not(.tv-nosnow) body::before {
    animation: none !important;
    transform: none;
    translate: none;
  }
}
html.tv-missed .live-missed .live-sub {
  flex: 0 0 100%;
  margin-top: 0.5vh;
  color: #c4bfb9;
  font-size: 2.5vh;
  font-size: clamp(15px, 2.5vh, 34px);
  line-height: 1.3;
}
html.tv-missed .live-missed .live-more {
  flex: none;
  padding: 1.4vh 1.4vw;
  color: #ffb08a;
  opacity: 1;
  font-weight: 700;
  font-size: 2.8vh;
  font-size: clamp(16px, 2.8vh, 38px);
  border-top: 2px dashed rgba(255, 71, 0, 0.45);
  letter-spacing: 0;
}
html.tv-missed .live-missed .live-empty {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 3vh 1.4vw;
  color: #9fd8b8;
  opacity: 1;
  font-weight: 600;
  font-size: 3.2vh;
  font-size: clamp(18px, 3.2vh, 44px);
  background: transparent;
}

/* ---- ТВ отдела продаж: таймер регламента, чаты, утренняя очередь, план (31.10.2026) ----
   Экран: шапка → [утренний баннер 09–10] → две колонки «Пропущенные звонки | Чаты без ответа»
   → полоса плана месяца. Узлы баннера и плана стабильные (#tvMorning/#tvPlan вне #liveBlocks),
   таймеры обновляет tv_board.js раз в 5 с: textContent/className/transform — без анимаций и
   без перерисовки списка. Цвета — литералами (ТВ тёмный при любой теме), новогодняя пара ниже.
   Старый Chromium webOS: без gap/inset/:has(), шрифты — vh + clamp. */
.tv-morning,
.tv-plan,
.tv-title-alt,
.tv-reg { display: none; }
html.tv-missed .live-missed .live-title-main { display: none; }
html.tv-missed .live-missed .tv-title-alt { display: inline; }
/* Две равные колонки: звонки слева, чаты справа (прежний перекос 1.6 — когда рядом были
   карточки других отделов). */
html.tv-missed .live-missed .live-block[data-key="sales"],
html.tv-missed .live-missed .live-block.tv-chats { flex-grow: 1; border-color: rgba(255, 71, 0, 0.55); }
html.tv-missed .live-missed .live-block.tv-chats { order: 0; }
html.tv-missed .live-missed .tv-col-note {
  margin-left: 0.4em;
  color: #a9a39c;
  font-weight: 600;
  font-size: 0.7em;
}
html.tv-missed .live-missed .tv-pending { color: #a9a39c; }

/* Таймер регламента: полоса (scaleX от левого края) + подпись. Полоса — 100% ширины, длину
   задаёт transform: смена значения не трогает раскладку. */
html.tv-missed .live-missed .tv-reg {
  display: flex;
  flex: 0 0 100%;
  align-items: center;
  margin-top: 0.9vh;
}
html.tv-missed .live-missed .tv-reg-bar {
  flex: 1 1 auto;
  height: 1.1vh;
  min-height: 6px;
  margin-right: 1.2vw;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}
html.tv-missed .live-missed .tv-reg-fill {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 9999px;
  background: #3fbf7f;
  -webkit-transform-origin: 0 50%;
  transform-origin: 0 50%;
  -webkit-transform: scaleX(1);
  transform: scaleX(1);
}
html.tv-missed .live-missed .tv-reg-text {
  flex: none;
  color: #7fe0a8;
  font-weight: 700;
  font-size: 2.6vh;
  font-size: clamp(15px, 2.6vh, 36px);
  line-height: 1.2;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
html.tv-missed .live-missed .tv-reg-warn .tv-reg-fill { background: #f0b429; }
html.tv-missed .live-missed .tv-reg-warn .tv-reg-text { color: #ffd166; }
html.tv-missed .live-missed .tv-reg-over .tv-reg-fill { background: #ff4d6d; }
html.tv-missed .live-missed .tv-reg-over .tv-reg-text { color: #ff8197; }
html.tv-missed .live-missed .tv-reg-night .tv-reg-text { color: #b9b3c4; font-weight: 600; }

/* Утренняя очередь 09:00–10:00: спокойная плашка «рассвета», без мигания. */
html.tv-missed .live-missed .tv-morning {
  display: flex;
  flex: none;
  align-items: center;
  margin: 0 0 1.8vh;
  padding: 1.3vh 1.6vw;
  color: #ffe6cc;
  background: #261d14;
  border: 1px solid rgba(255, 176, 90, 0.5);
  border-radius: 14px;
  font-weight: 700;
  font-size: 3.2vh;
  font-size: clamp(18px, 3.2vh, 44px);
  line-height: 1.2;
}
html.tv-missed .live-missed .tv-morning.hidden { display: none; }
html.tv-missed .live-missed .tv-morning-ico {
  flex: none;
  width: 4.4vh;
  height: 4.4vh;
  margin-right: 1.2vw;
  color: #ffb05a;
}
html.tv-missed .live-missed .tv-morning-ico svg { display: block; width: 100%; height: 100%; }
html.tv-missed .live-missed .tv-morning-left { color: #ffb05a; white-space: nowrap; }

/* Полоса плана месяца: подпись слева, прогресс справа; заливка — transform с плавным
   переходом (значение меняется раз в 10 мин, при входе — один спокойный «налив»). */
html.tv-missed .live-missed .tv-plan {
  display: flex;
  flex: none;
  align-items: center;
  margin-top: 1.8vh;
  padding: 1.3vh 1.6vw;
  background: #1a1714;
  border: 1px solid rgba(204, 204, 204, 0.18);
  border-radius: 14px;
}
html.tv-missed .live-missed .tv-plan.hidden { display: none; }
html.tv-missed .live-missed .tv-plan-line {
  flex: none;
  max-width: 100%;
  margin-right: 1.6vw;
  white-space: nowrap;
  font-size: 3.2vh;
  font-size: clamp(18px, 3.2vh, 44px);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
html.tv-missed .live-missed .tv-plan-lead { color: #c4bfb9; font-weight: 600; }
html.tv-missed .live-missed .tv-plan-value { color: #ffffff; font-weight: 800; }
html.tv-missed .live-missed .tv-plan-pct { margin-left: 0.5em; color: #ff8a4c; font-weight: 800; }
html.tv-missed .live-missed .tv-plan-bar {
  flex: 1 1 auto;
  height: 1.8vh;
  min-height: 10px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}
html.tv-missed .live-missed .tv-plan-notarget .tv-plan-bar { display: none; }
html.tv-missed .live-missed .tv-plan-fill {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 9999px;
  background: #ff4700;
  -webkit-transform-origin: 0 50%;
  transform-origin: 0 50%;
  -webkit-transform: scaleX(0);
  transform: scaleX(0);
  -webkit-transition: -webkit-transform 2.4s ease-out;
  transition: transform 2.4s ease-out;
}
html.tv-missed .live-missed .tv-plan-done .tv-plan-fill { background: #3fbf7f; }
html.tv-missed .live-missed .tv-plan-done .tv-plan-pct { color: #7fe0a8; }
@media (prefers-reduced-motion: reduce) {
  html.tv-missed .live-missed .tv-plan-fill { -webkit-transition: none; transition: none; }
}

/* Новогодняя тема: плашки — те же ночные плиты, что карточка (#13131f), акцент — iris. */
:root[data-theme="new-year"].tv-missed .live-missed .live-block.tv-chats { border-color: rgba(97, 153, 246, 0.55); }
:root[data-theme="new-year"].tv-missed .live-missed .tv-morning {
  color: #f2f6ff;
  background: #13131f;
  border-color: rgba(97, 153, 246, 0.6);
}
:root[data-theme="new-year"].tv-missed .live-missed .tv-morning-ico,
:root[data-theme="new-year"].tv-missed .live-missed .tv-morning-left { color: #9cc0ff; }
:root[data-theme="new-year"].tv-missed .live-missed .tv-plan { background: #13131f; border-color: rgba(79, 79, 128, 0.75); }
:root[data-theme="new-year"].tv-missed .live-missed .tv-plan-fill { background: #6199f6; }
:root[data-theme="new-year"].tv-missed .live-missed .tv-plan-pct { color: #9cc0ff; }
:root[data-theme="new-year"].tv-missed .live-missed .tv-plan-done .tv-plan-fill { background: #3fbf7f; }

/* ---- Daily dashboard ---- */
/* Full-width like the topbar / LIVE sections (same 40px side gutters), so on
   wide (2K / 16:9) monitors the lower blocks reach the right edge instead of
   stopping at a fixed max-width and leaving an empty strip on the right. */
.dashboard { padding: 12px 40px 70px; }
.hidden { display: none; }

.cards {
  display: grid;
  grid-template-columns: repeat(11, minmax(0, 1fr));
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-block);
  overflow: hidden;
  /* Top gap (live-section 12 + dashboard 12 = 24) matches the bottom margin. */
  margin: 0 0 24px;
}
.card { background: var(--graphite); padding: 16px 14px; min-width: 0; }
.card .val { font-size: var(--fs-4xl); font-weight: 700; color: var(--bone); letter-spacing: -0.02em; line-height: 1; }
/* Исключение из шкалы: ступень НИЖЕ соседей по смыслу. Подписи 11 карточек
   живут в жёсткой сетке repeat(11, 1fr) и обрезаны через text-overflow. На
   ширинах 1490–1560px (рабочие ноутбуки) самая длинная подпись влезает впритык,
   и рост даже на 0.5px превращает её в «Исходящие звонк…». */
.card .lbl { font-size: var(--fs-2xs); color: var(--ink-soft); margin-top: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card.hot .val { color: var(--ember); }

.panel {
  background: var(--graphite);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-block);
  padding: 18px 20px;
  margin-bottom: 24px;
}
.panel-title {
  margin: 0 0 14px;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ash);
  font-weight: 700;
}

.panel-note {
  margin: -6px 0 12px;
  padding: 8px 12px;
  border-radius: var(--radius-block);
  border: 1px solid var(--ember-smoke);
  background: rgba(139, 46, 9, 0.12);
  color: var(--ash);
  font-size: var(--fs-sm);
  line-height: 1.45;
}

.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: var(--fs-md); }
th, td { text-align: left; padding: 8px 11px; border-bottom: 1px solid var(--hairline); white-space: nowrap; }
th {
  color: var(--ash); font-weight: 500; font-size: var(--fs-2xs); text-transform: uppercase;
  letter-spacing: 0.06em; position: sticky; top: 0; background: var(--graphite-2); opacity: 0.9;
}
tbody tr:hover { background: var(--graphite-2); }
td { color: var(--ash); }
td:first-child { color: var(--bone); }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
td a { color: var(--blue); text-decoration: none; border-bottom: 1px solid var(--hairline-strong); }
td a:hover { color: var(--ember); border-color: var(--ember); }
.dept-row td { background: var(--obsidian); color: var(--ember); font-weight: 700; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em; }

/* Disposition badge in incident tables (Обработан / В работе / Забыт) */
.disp { display: inline-block; padding: 1px 9px; border-radius: var(--radius-pill); font-size: var(--fs-xs); border: 1px solid var(--hairline-strong); white-space: nowrap; }
/* Палитра DESIGN.md (обсидиан/ash/ember), без посторонних цветов. */
.disp-ok { color: var(--ember); border-color: var(--ember); }        /* Обработан — ember-контур */
.disp-work { color: var(--ash); border-color: var(--hairline-strong); } /* В работе — нейтральный */
.disp-forgot {                                                        /* Забыт — залитый ember со свечением */
  color: var(--bone); background: var(--ember); border-color: var(--ember);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 12px 1px var(--ember-glow);
  font-weight: 600;
}
/* Реальная стадия лида (напр. «Брак / Спам») — нейтральный info-чип. */
.disp-stage {
  color: var(--bone); background: rgba(204, 204, 204, 0.08);
  border-color: var(--hairline-strong);
}
.empty { color: var(--ink-muted); padding: 16px; }

.tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.tab {
  background: transparent; border: 1px solid var(--hairline-strong); border-radius: var(--radius-pill);
  padding: 6px 14px; cursor: pointer; font-size: var(--fs-sm); color: var(--ash);
  transition: color 0.15s, border-color 0.15s, box-shadow 0.22s ease;
}
.tab:hover { color: var(--bone); border-color: var(--ember); box-shadow: var(--glow-hover-sm); }
.tab.active { background: var(--ember); color: var(--bone); border-color: var(--ember); }

.meta-footer {
  color: var(--ash); font-size: var(--fs-sm); border-top: 1px solid var(--hairline);
  padding-top: 14px; margin-top: 8px; line-height: 1.8; opacity: 0.8;
}
.badge {
  display: inline-block; border: 1px solid var(--hairline-strong); border-radius: var(--radius-pill);
  padding: 2px 10px; margin-right: 6px; font-size: var(--fs-xs);
}

/* =====================================================================
   Responsive — tablet (≤1024px) and phone (≤600px).
   Desktop (>1024px) keeps the tuned layout above untouched. The dashboard
   binds to 0.0.0.0 so it's opened from phones on the LAN — these queries
   make the LIVE blocks and metric cards (the primary mobile view) readable
   on a narrow screen. Mobile-first principle is applied via overrides only
   below the desktop default so nothing changes on large viewports.
   ===================================================================== */

/* ---- Tablet ---- */
@media (max-width: 1024px) {
  /* Tighter horizontal gutters than the 40px desktop margin. */
  .topbar { padding: 16px 24px; }
  .status { padding: 12px 24px 0; }
  .live-section { padding: 12px 24px; }
  .dashboard { padding: 12px 24px 60px; }

  /* 11 fixed columns become unreadable; switch to separated tiles that wrap.
     Drop the seamless 1px-gap border trick (it leaves stray empty cells when
     items don't fill the last row) for self-bordered cards. */
  .cards {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
    background: transparent;
    border: none;
    border-radius: 0;
    overflow: visible;
    margin-bottom: 20px;
  }
  .card { border: 1px solid var(--hairline); border-radius: var(--radius-block); }

  /* Планшет: в ленте «На линии» помещаем ~3 карточки, остальные — прокруткой. */
  .status-blocks { --status-visible: 3; }
}

/* ---- Phone ---- */
@media (max-width: 600px) {
  body { font-size: var(--fs-md); }

  /* Stack the topbar: brand row on top, full-width controls below. */
  .topbar {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 12px 14px;
  }
  .brand-word { font-size: var(--fs-2xl); }
  .brand-sub { font-size: var(--fs-xs); }
  .controls { width: 100%; }
  /* Date trigger and the menu button share the row; the refresh icon stays a
     compact square between them. */
  .controls { align-items: center; }
  .controls .datefield,
  .controls .menu { flex: 1 1 0; }
  /* Keep the shared --control-h; just let the menu button fill its share and
     the icon stay a fixed square. Content is centered via the .btn flex rules. */
  .controls .menu > .btn { width: 100%; padding: 0 8px; }
  .controls .btn-icon { flex: 0 0 auto; }
  .date-trigger { width: 100%; }

  /* Keep the calendar popup inside the viewport on narrow screens.
     The date trigger is now the leftmost ~1/3 of the controls row, so the
     desktop `right: 0` would open the popup off the left edge. Anchor it to
     the trigger's left edge instead so it expands rightward and stays in view. */
  .cal-pop { width: min(300px, calc(100vw - 28px)); left: 0; right: auto; }
  /* The menu button is rightmost, so right:0 already opens it leftward —
     just clamp the width so it can't exceed the viewport. */
  .menu-pop { min-width: 0; width: min(240px, calc(100vw - 28px)); }

  .status { padding: 8px 14px 0; }
  .live-section { padding: 10px 14px; }
  .live-section:first-of-type { padding-top: 16px; }
  .dashboard { padding: 10px 14px 48px; }
  .panel { padding: 14px 14px; margin-bottom: 16px; }

  /* LIVE blocks: force a single column so wide minmax() can't overflow. */
  .live-blocks { grid-template-columns: 1fr; gap: 12px; }
  /* «На линии» на телефоне НЕ схлопываем в столбец (это и грузило интерфейс) — оставляем
     горизонтальную ленту: одна карточка на ширину + «выглядывает» следующая, свайп листает. */
  .status-blocks { --status-visible: 1.15; --status-gap: 12px; }
  .live-head { margin-bottom: 16px; }
  .live-title { font-size: var(--fs-2xl); }

  /* Metric cards: two per row, smaller numerals. */
  .cards { grid-template-columns: repeat(2, 1fr); }
  /* An odd number of cards leaves the last one alone in its row — stretch it
     across both columns so it fills the width instead of sitting half-empty. */
  .card:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .card { padding: 14px 12px; }
  .card .val { font-size: var(--fs-3xl); }
  .card .lbl { font-size: var(--fs-2xs); }

  /* Tables stay horizontally scrollable; trim padding and enable momentum. */
  .table-wrap { -webkit-overflow-scrolling: touch; }
  table { font-size: var(--fs-sm); }
  th, td { padding: 7px 9px; }
}

/* ---------------- «Отчеты» page ---------------- */
/* Stylish back-to-dashboard pill in the topbar (replaces the plain text button). */
.back-btn {
  display: inline-flex; align-items: center; gap: 8px;
  height: var(--control-h); padding: 0 18px;
  border-radius: var(--radius-pill); text-decoration: none;
  background: var(--graphite); color: var(--ash);
  border: 1px solid var(--hairline);
  font-family: var(--font); font-size: var(--fs-md); font-weight: 600; letter-spacing: 0.01em;
  transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.15s, box-shadow 0.15s;
}
.back-btn svg { width: 16px; height: 16px; flex: none; }
.back-btn:hover {
  color: var(--bone); border-color: var(--ember); background: var(--graphite-2);
  transform: translateX(-2px); box-shadow: 0 0 0 1px var(--ember-smoke), 0 6px 18px -8px var(--ember-glow);
}

/* Two-column layout: left control sidebar + main chart area. */
.reports-layout { display: flex; gap: 18px; align-items: flex-start; padding: 20px 40px 60px; }
.reports-sidebar { flex: 0 0 320px; display: flex; flex-direction: column; gap: 16px; position: sticky; top: 18px; }
.reports-main { flex: 1 1 auto; min-width: 0; }
.reports-panel { padding: 18px; }
.reports-month { color: var(--ash); font-size: var(--fs-md); margin: 14px 0 0; }
.reports-month b { color: var(--bone); }

/* Calendar trigger fills the sidebar block; popup opens below-left within it. */
.datefield-block { display: block; }
.datefield-block .date-trigger { width: 100%; }
.datefield-block .cal-pop { top: calc(100% + 6px); left: 0; right: auto; width: 100%; min-width: 280px; }

/* «Отчёты» без сайдбара: инфографика на всю ширину, период отчёта — сверху. */
.reports-layout-full { display: block; padding: 20px 40px 60px; }
.reports-topbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
/* Колонка «Строка продажи» в таблице побед дня. Центрируем: номера иначе липнут вправо,
   а «Не указан» — влево, и колонка выглядит рваной. */
.order-row { text-align: center !important; }
/* Дубль — одна строка продажи у двух сделок. Не подписываем словом, только оранжевый номер
   (решение заказчика): подпись «· дубль» шумела в каждой строке. */
td.order-dup { color: var(--ember, #f0713a); font-weight: 700; cursor: help; }
/* «Не указан» — нарушение регламента, но не ошибка данных: приглушаем, не кричим красным. */
td.order-missing { color: var(--muted, #8b93a7); font-style: italic; }

/* Значки свежести в подзаголовке борда: короткие, с подсказкой при наведении. */
.src-chip { cursor: help; opacity: .85; }
/* Источник устарел (лист заморожен / снимок CRM не за сегодня) — раньше это было незаметно,
   и страница молча показывала числа многодневной давности. */
.stale-warn { color: var(--warn, #f0a132); font-weight: 600; cursor: help; }

/* Дельта неполного месяца: сравнение части месяца с ПОЛНЫМ предыдущим — не настоящее падение.
   Приглушаем, чтобы «−54%» в середине месяца не читалось как обвал продаж. */
.kpi-delta.kpi-partial { opacity: .6; font-style: italic; }

/* Две оси атрибуции («Отделы» — кто работал, «Филиалы» — какая точка заработала) стоят
   ОДНОЙ КОЛОНКОЙ, строка под строкой. Раньше ряд отделов был безымянным и уезжал вправо
   (space-between родителя), а подписанные «Филиалы» — влево: ряды читались как разные
   сущности, и вкладка «Отдел продаж» терялась из виду. */
.tab-axes { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 1 1 auto; }
/* Ряд «Отделы» — обычный flex (label + вкладки натуральной ширины), а НЕ равные колонки
   грид-сегмента: у него есть подпись, равноширокие колонки ломали бы вид. */
.dept-tabs { display: inline-flex; flex: 0 1 auto; flex-wrap: wrap; align-items: center; }
/* Подпись-ярлык строки: одинакова у обеих осей, поэтому селектор общий. */
.dept-tabs .seg-label {
  padding: 0 8px 0 4px; font-size: var(--fs-2xs); letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted, #8b93a7); white-space: nowrap; cursor: help; align-self: center;
}
.compare-link {
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  padding: 9px 14px; border-radius: var(--radius-block); font-weight: 700; font-size: var(--fs-md);
  color: var(--bone); background: var(--graphite-2); border: 1px solid var(--hairline);
  transition: border-color 0.15s, filter 0.15s;
}
.compare-link svg { color: var(--ember); flex: none; }
.compare-link:hover { border-color: var(--ember); filter: brightness(1.08); }
.reports-period {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 9px 14px; border-radius: var(--radius-block);
  background: var(--graphite-2); border: 1px solid var(--hairline);
}
.reports-period-cap {
  color: var(--ash-dim); font-size: var(--fs-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
}
/* План продаж на месяц (админ, 31.10.2026) — цель для полосы плана на ТВ отдела продаж. */
.plan-target {
  display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0;
  padding: 9px 14px; border-radius: var(--radius-block);
  background: var(--graphite-2); border: 1px solid var(--hairline);   /* плита, как у «Периода» */
}
.plan-target-input { width: 150px; font-variant-numeric: tabular-nums; }
.plan-target-note { color: var(--ash); font-size: var(--fs-xs); }
.plan-target-note.is-bad { color: var(--status-bad, #ff4d6d); }
.reports-period .datefield { position: relative; }
.reports-period .date-trigger svg { color: var(--ember); margin-right: 6px; flex: none; }
.reports-period .reports-month { margin: 0; }
.reports-topbar .cal-pop { top: calc(100% + 6px); left: 0; right: auto; }

/* «Выгрузки (РОП)» — пояснительная панель в основной области. */
.exports-hint { max-width: 640px; }
.exports-hint-text { color: var(--ash); font-size: var(--fs-md); line-height: 1.55; margin: 8px 0 0; }

/* ---------------- «Сравнение периодов» (/compare) ---------------- */
.compare-wrap { padding: 20px 40px 60px; display: flex; flex-direction: column; gap: 18px; }
/* position+z-index: панель (glass → свой стек-контекст) ВЫШЕ блока результатов (#c-results, z-auto),
   чтобы выпадающий календарь не уходил под KPI-карточки. Но НИЖЕ шапки (.topbar z-index:20), иначе
   панель перекрывает выпадающее «Меню». Отсюда 10: результаты < панель(10) < шапка(20). */
.compare-panel { position: relative; z-index: 10; padding: 16px 18px; border-radius: var(--radius-card); display: flex; flex-direction: column; gap: 14px; }
/* Верх панели: периоды слева, действия справа-вверху (Отчёты-ссылка + первичная «Сравнить»). */
.cmp-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.cmp-head .cmp-periods { flex: 1 1 auto; min-width: 0; }
.cmp-periods { display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap; }
.cmp-period { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
/* Капс периода = цвет + светящаяся точка (та же кодировка, что у линий графика: П1 синий, П2 ember). */
.cmp-period-cap {
  display: inline-flex; align-items: center; gap: 7px; align-self: center; white-space: nowrap;
  font-weight: 700; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.12em;
}
.cmp-period-cap::before {
  content: ""; width: 6px; height: 6px; border-radius: var(--radius-pill);
  background: currentColor; box-shadow: 0 0 8px currentColor;
}
.cmp-p1 { color: var(--period-1); }
.cmp-p2 { color: var(--ember); }
/* position: relative — якорь для glass-попапа календаря, который переносится в активное поле. */
.cmp-field { position: relative; display: inline-flex; align-items: center; gap: 6px; color: var(--ash-dim); font-size: var(--fs-xs); }
/* Поле даты — ЦЕЛИКОМ кликабельная кнопка (иконка + дата), а не узкий нативный пикер. */
.cmp-datefield {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font-family: var(--font); font-size: var(--fs-md); font-weight: 600; color: var(--bone);
  background: var(--graphite-2); border: 1px solid var(--hairline); border-radius: var(--radius-ctl);
  padding: 8px 12px; white-space: nowrap; min-width: 132px;
  transition: border-color 0.15s, box-shadow 0.15s, filter 0.12s;
}
.cmp-datefield:hover { border-color: var(--hairline-strong); }
.cmp-datefield[aria-expanded="true"] { border-color: var(--ember); box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 12px 1px var(--ember-glow); }
.cmp-datefield-ic { color: var(--ember); flex: none; }
.cmp-datefield-label { font-variant-numeric: tabular-nums; }
/* Попап календаря под активным полем; при вылете за правый край окна — прижать вправо. */
.cmp-field .cal-pop { top: calc(100% + 6px); left: 0; right: auto; }
.cmp-field .cal-pop.cal-pop--right { left: auto; right: 0; }
.cmp-vs { color: var(--ash-dim); font-weight: 800; font-size: var(--fs-sm); font-style: italic; align-self: center; padding: 0 2px; }
/* Кластер действий справа: «Отчёты» (вторичная .compare-link) + «Сравнить» (первичная ember). */
.cmp-head-actions { display: flex; align-items: center; gap: 10px; flex: none; }
.cmp-run {
  cursor: pointer; font-family: var(--font); font-size: var(--fs-md); font-weight: 700; color: var(--on-accent);
  background: var(--ember); border: 1px solid var(--ember); border-radius: var(--radius-block); padding: 9px 22px;
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 16px -2px var(--ember-glow);
  transition: box-shadow 0.15s, filter 0.12s, transform 0.1s;
}
.cmp-run:hover { filter: brightness(1.06); box-shadow: 0 0 0 1px var(--ember), 0 0 22px 2px var(--ember-glow); }
.cmp-run:active { transform: translateY(1px); }
.cmp-run:disabled { opacity: 0.55; cursor: default; box-shadow: none; }
/* Пресеты + статус в одну строку под верхом. */
.cmp-presets { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cmp-presets-cap { color: var(--ash-dim); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.12em; }
.cmp-chip {
  cursor: pointer; font-family: var(--font); font-size: var(--fs-sm); font-weight: 600;
  color: var(--ash); background: rgba(var(--tint-rgb), 0.04);
  border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: 6px 12px;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.cmp-chip:hover { color: var(--bone); border-color: var(--ember); background: rgba(var(--tint-rgb), 0.06); }
.cmp-note { color: var(--ash-dim); font-size: var(--fs-sm); margin-left: auto; }

.compare-results { display: flex; flex-direction: column; gap: 12px; }
.compare-table-wrap { border-radius: var(--radius-card); padding: 8px 4px; overflow-x: auto; }
.cmp-table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
.cmp-table th, .cmp-table td { padding: 10px 16px; text-align: right; white-space: nowrap; }
.cmp-table th:first-child, .cmp-table td:first-child { text-align: left; }
.cmp-table thead th {
  color: var(--ash-dim); font-weight: 700; font-size: var(--fs-sm); border-bottom: 1px solid var(--hairline);
  vertical-align: bottom;
}
.cmp-table thead th span { display: block; color: var(--ash); font-weight: 500; font-size: var(--fs-xs); margin-top: 2px; }
.cmp-p1head { color: var(--period-1) !important; }
.cmp-p2head { color: var(--ember) !important; }
.cmp-table tbody tr { border-bottom: 1px solid rgba(var(--tint-rgb), 0.04); }
.cmp-table tbody tr:hover { background: rgba(var(--tint-rgb), 0.02); }
.cmp-metric { color: var(--bone); font-weight: 600; }
.cmp-sub .cmp-metric { color: var(--ash); font-weight: 400; padding-left: 26px; font-size: var(--fs-sm); }
.cmp-val { color: var(--bone); font-variant-numeric: tabular-nums; }
.cmp-delta { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ash-dim); }
.cmp-delta.up-good { color: var(--status-good); }
.cmp-delta.down-bad { color: var(--status-bad); }
.cmp-delta.neutral { color: var(--ash-dim); }
.cmp-warn { color: #ffb454; font-size: var(--fs-sm); }
.cmp-source { color: var(--ash-dim); font-size: var(--fs-sm); line-height: 1.5; margin: 2px 0 0; max-width: 820px; }
.cmp-empty { color: var(--ash-dim); font-size: var(--fs-md); padding: 24px; text-align: center; }

/* KPI-карточки сравнения (П1/П2 + дельта). */
.cmpk-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; }
.cmpk-card { border-radius: var(--radius-card); padding: 14px 16px; min-width: 0; }
.cmpk-label { color: var(--ash-dim); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 10px; }
.cmpk-row { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.cmpk-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex: none; }
.cmpk-val { color: var(--bone); font-size: var(--fs-xl); font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cmpk-delta { margin-top: 10px; font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ash-dim); }
.cmpk-delta.up-good { color: var(--status-good); }
.cmpk-delta.down-bad { color: var(--status-bad); }

/* Наложенный подневный график П1 vs П2. */
.cmpc-board { border-radius: var(--radius-card); padding: 18px 20px; }
.cmpc-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.cmpc-legend { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 8px; }
.cmpc-key { display: inline-flex; align-items: center; gap: 7px; color: var(--ash); font-size: var(--fs-sm); }
.cmpc-wrap { position: relative; }
.cmpc-svg { display: block; width: 100%; height: auto; }
.cmpc-grid { stroke: rgba(var(--tint-rgb), 0.06); stroke-width: 1; }
.cmpc-axis { fill: var(--ash-dim); font-size: var(--fs-2xs); font-family: var(--font); }
.cmpc-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cmpc-cursor { stroke: rgba(var(--tint-rgb), 0.22); stroke-width: 1; stroke-dasharray: 3 3; }
.cmpc-dot { stroke: var(--mark-ring); stroke-width: 2; }
.cmpc-hit { cursor: crosshair; }
.cmpc-tip {
  position: absolute; z-index: 20; pointer-events: none;
  background: rgba(20, 17, 14, 0.94); border: 1px solid var(--hairline); border-radius: var(--radius-block);
  padding: 8px 12px; color: var(--bone); font-size: var(--fs-sm); line-height: 1.5; white-space: nowrap;
}
.cmpc-tip .cmpk-dot { width: 8px; height: 8px; margin-right: 5px; }

@media (max-width: 1240px) { .cmpk-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px) { .cmpk-grid { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 980px) {
  .compare-wrap { padding: 16px; }
  .cmp-periods { flex-direction: column; align-items: stretch; }
  .cmp-vs { align-self: flex-start; }
  /* Действия уходят на свою строку и прижимаются вправо; «Сравнить» не теряется. */
  .cmp-head-actions { width: 100%; justify-content: flex-end; }
}

/* Report-export buttons stacked in the sidebar. */
.report-actions-col { display: flex; flex-direction: column; gap: 10px; }
.report-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%;
  padding: 14px 16px; cursor: pointer; text-align: left;
  background: var(--graphite-2); color: var(--bone);
  border: 1px solid var(--hairline); border-radius: var(--radius-block);
  font-family: var(--font); font-size: var(--fs-lg); font-weight: 700;
  transition: border-color 0.15s, filter 0.15s, transform 0.1s;
}
.report-btn:hover { border-color: var(--ember); filter: brightness(1.07); }
.report-btn:active { transform: translateY(1px); }
.report-sub { color: var(--ink-soft); font-size: var(--fs-xs); font-weight: 400; }
.report-result { margin-top: 14px; color: var(--ash); font-size: var(--fs-md); min-height: 16px; line-height: 1.45; }
.report-result.info { color: var(--bone); }
.report-result.ok { color: var(--status-good); }
.report-result.error { color: var(--ember); }
.report-result a { color: var(--ember); font-weight: 700; white-space: nowrap; }
.report-btn:disabled { opacity: 0.5; cursor: default; filter: none; }
.reports-panel .progress { margin-top: 12px; border-radius: var(--radius-xs); }

/* Main area: prepared (empty) chart slots for future export-result graphs. */
.charts-head { margin: 0 0 14px; }
.charts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.chart-card {
  background: var(--graphite); border: 1px solid var(--hairline);
  border-radius: var(--radius-block); min-height: 220px;
  display: grid; place-items: center; padding: 20px;
}
.chart-card-wide { grid-column: 1 / -1; min-height: 280px; }
.chart-empty {
  color: var(--ash-dim); font-size: var(--fs-md); text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px; opacity: 0.7;
}
/* Вне шкалы намеренно: это глиф-иконка, а не текст. Её кегль не должен ездить
   вместе с типографикой. */
.chart-empty-icon { font-size: 30px; opacity: 0.6; }

@media (max-width: 980px) {
  .reports-layout { flex-direction: column; padding: 16px; }
  .reports-sidebar { flex: none; width: 100%; position: static; }
  .charts-grid { grid-template-columns: 1fr; }
}

/* Premium «Отчеты» item in the dashboard menu (stands out vs the placeholders). */
.menu-item-featured {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; font-weight: 700; margin-bottom: 4px;
  border: 1px solid rgba(var(--ember-rgb), 0.34);
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.16), rgba(var(--ember-rgb), 0.04));
}
.menu-item-featured .menu-ico { color: var(--ember); flex: none; }
.menu-item-featured:hover {
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.26), rgba(var(--ember-rgb), 0.08));
  border-color: var(--ember);
}

/* ---------------- Sales infographic boards (/reports) ---------------- */
.glass {
  background: linear-gradient(180deg, rgba(29, 26, 23, 0.62), rgba(18, 16, 14, 0.58));
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border: 1px solid var(--hairline);
  box-shadow: 0 10px 34px -16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(var(--tint-rgb), 0.04);
}
.boards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.board { padding: 18px 20px; border-radius: var(--radius-card); min-width: 0; }
.board-wide { grid-column: 1 / -1; }
.board-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.board-title { margin: 0; font-size: var(--fs-xl); font-weight: 800; color: var(--bone); letter-spacing: -0.01em; }
.board-sub { margin-top: 2px; font-size: var(--fs-sm); color: var(--ash-dim); }
.no-data { color: var(--ash-dim); font-style: italic; font-size: 0.92em; }
.empty, .mgr-empty { color: var(--ash-dim); font-size: var(--fs-md); padding: 24px; text-align: center; }

/* inline-grid с равными колонками: все сегменты одной ширины (= самому длинному лейблу). */
.seg { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; background: rgba(var(--tint-rgb), 0.04); border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: 3px; gap: 2px; }
/* Округлено ВНИЗ, а не по общему правилу шкалы: .seg — inline-grid с равными
   колонками, поэтому ширина ленты = самый длинный лейбл × число сегментов.
   У #deptTabs сегментов шесть, и рост кегля умножается на шесть — ряд вкладок
   перескакивал бы на вторую строку на ширинах, где сейчас помещается в одну. */
.seg-btn { border: none; background: transparent; color: var(--ash); font-family: var(--font); font-size: var(--fs-xs); font-weight: 600; padding: 5px 12px; border-radius: var(--radius-pill); cursor: pointer; text-align: center; transition: color 0.12s, background 0.12s, box-shadow 0.22s ease; }
.seg-btn:hover { color: var(--bone); }
.seg-btn.active { background: var(--ember); color: var(--bone); box-shadow: 0 0 12px -2px var(--ember-glow); }
/* Правило ОБЯЗАНО стоять ниже .seg-btn.active и иметь специфичность выше её:
   у .active своя подсветка, и при равном весе либо активный сегмент не
   засветился бы на наведении, либо hover стёр бы его собственную подсветку.
   :not(:disabled) сохраняет погашенными настоящие disabled-кнопки, а
   .emp-control--disabled гасит те, что выключены только визуально. */
.seg-btn:not(:disabled):hover { box-shadow: var(--glow-hover-sm); }
.emp-control--disabled .seg-btn:hover { box-shadow: none; }

.kpi-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-bottom: 18px; }
.kpi { padding: 14px 15px; border-radius: var(--radius-inner); backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(var(--tint-rgb), 0.025); border: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 8px; min-width: 0; box-shadow: none; }
.kpi-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.kpi-label { color: var(--ash); font-size: var(--fs-xs); line-height: 1.25; }
.kpi-delta { font-size: var(--fs-xs); font-weight: 700; white-space: nowrap; }
.kpi-up { color: var(--status-good); }
.kpi-down { color: var(--status-bad); }
.kpi-neu { color: var(--ash-dim); }
.kpi-val { color: var(--bone); font-size: var(--fs-3xl); font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; line-height: 1.05; }
.kpi-spark { height: 30px; }
.spark { width: 100%; height: 30px; display: block; }

.cc-legend { display: flex; gap: 16px; margin-bottom: 6px; }
.cc-chip { display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-xs); color: var(--ash); }
.cc-chip::before { content: ""; width: 12px; height: 3px; border-radius: var(--radius-xs); background: currentColor; }
.cc-bar-c { color: var(--series-leads); }
.cc-rev-c { color: var(--ember); }
.cc-conv-c { color: var(--series-conv); }
.cc-bar-c::before { width: 9px; height: 9px; }
/* ---- Боковые «лепестки» переключения месяца отчёта (слева ‹ пред, справа след ›) ----
   Матовое стекло: видимы как отдельный контрол, но спокойны; ember только на hover/фокусе. */
.pulse-chart { position: relative; }
.pulse-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 64px; padding: 0; border-radius: var(--radius-pill); cursor: pointer;
  color: var(--ash);
  background: linear-gradient(180deg, rgba(29, 26, 23, 0.5), rgba(22, 20, 18, 0.62));
  border: 1px solid rgba(var(--tint-rgb), 0.14);
  backdrop-filter: blur(12px) saturate(140%); -webkit-backdrop-filter: blur(12px) saturate(140%);
  box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(var(--tint-rgb), 0.05);
  transition: color 0.18s, border-color 0.18s, box-shadow 0.18s, transform 0.18s, opacity 0.18s;
}
.pulse-prev { left: -7px; }
.pulse-next { right: -7px; }
.pulse-nav:hover, .pulse-nav:focus-visible {
  color: var(--bone); border-color: rgba(var(--ember-rgb), 0.55); outline: none;
  box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.5), 0 0 18px -3px var(--ember-glow), inset 0 1px 0 rgba(var(--tint-rgb), 0.06);
}
.pulse-prev:hover, .pulse-prev:focus-visible { transform: translateY(-50%) translateX(-2px); }
.pulse-next:hover, .pulse-next:focus-visible { transform: translateY(-50%) translateX(2px); }
.pulse-nav:focus-visible { box-shadow: 0 0 0 2px var(--mark-ring), 0 0 0 3px var(--ember), 0 0 18px -3px var(--ember-glow); }
.pulse-nav:active { transform: translateY(-50%) scale(0.97); }
.pulse-nav:disabled { opacity: 0.32; cursor: default; color: var(--ash-dim); border-color: var(--hairline); box-shadow: none; }
.pulse-nav:disabled:hover { transform: translateY(-50%); color: var(--ash-dim); border-color: var(--hairline); box-shadow: none; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pulse-nav { background: linear-gradient(180deg, var(--graphite-2), var(--graphite)); }
}
@media (prefers-reduced-motion: reduce) {
  .pulse-nav, .pulse-prev:hover, .pulse-next:hover, .pulse-nav:active { transition: color 0.18s, border-color 0.18s, box-shadow 0.18s; transform: translateY(-50%); }
}
/* Узкие экраны: лепестки не должны залезать на данные — прижимаем ближе к краю и сужаем. */
@media (max-width: 640px) {
  .pulse-nav { width: 11px; height: 48px; }
  .pulse-prev { left: -5px; }
  .pulse-next { right: -5px; }
}
.cc-wrap { position: relative; }
/* Инфо-баннер вместо графика (напр. «По месяцам» при < 2 закрытых месяцев). */
.cc-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; text-align: center; min-height: 240px; padding: 28px 24px;
}
.cc-empty-ic { color: var(--ember); opacity: 0.9; margin-bottom: 2px; }
.cc-empty-t { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; }
.cc-empty-s { color: var(--ash-dim); font-size: var(--fs-sm); line-height: 1.5; max-width: 48ch; }
.cc-svg { width: 100%; height: auto; display: block; }
.cc-grid { stroke: rgba(var(--tint-rgb), 0.06); stroke-width: 1; }
.cc-bar { fill: rgba(var(--series-leads-rgb), 0.75); }
.cc-rev { fill: none; stroke: var(--ember); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
.cc-conv { fill: none; stroke: var(--series-conv); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cc-xlab { fill: var(--ash-dim); font-size: var(--fs-sm); font-family: var(--font); }
.cc-cursor { stroke: rgba(var(--tint-rgb), 0.3); stroke-width: 1; stroke-dasharray: 3 3; }
.cc-dot-rev { fill: var(--ember); stroke: var(--mark-ring); stroke-width: 1.5; }
.cc-dot-conv { fill: var(--series-conv); stroke: var(--mark-ring); stroke-width: 1.5; }
.cc-dot-won { fill: var(--series-wins); stroke: var(--mark-ring); stroke-width: 1.5; }
/* «Всего успешных» line + clickable/toggleable legend chips */
.cc-won-c { color: var(--series-wins); }
.cc-won { fill: none; stroke: var(--series-wins); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cc-won-dot { fill: var(--series-wins); }
.cc-d-won { background: var(--series-wins); }
.cc-chip-btn { cursor: pointer; transition: opacity 0.15s ease; }
.cc-chip-btn:hover { opacity: 0.8; }
.cc-chip.off { opacity: 0.38; }
.cc-hit { fill: transparent; cursor: crosshair; }
.cc-tip { position: absolute; top: 6px; pointer-events: none; background: rgba(15, 13, 10, 0.92); border: 1px solid var(--hairline-strong); border-radius: var(--radius-block); padding: 8px 11px; font-size: var(--fs-xs); color: var(--bone); min-width: 152px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); }
.cc-tip-d { color: var(--ash-dim); font-size: var(--fs-2xs); margin-bottom: 5px; }
.cc-tip div { display: flex; align-items: center; gap: 6px; line-height: 1.7; }
.cc-tip b { margin-left: auto; font-variant-numeric: tabular-nums; }
.cc-tip i { width: 9px; height: 9px; border-radius: var(--radius-xs); display: inline-block; }
.cc-tip-x { color: var(--ash-dim); font-size: var(--fs-xs); padding-left: 15px; }
.cc-d-bar { background: var(--series-leads); }
.cc-d-rev { background: var(--ember); }
.cc-d-conv { background: var(--series-conv); }

.fn-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 10px; margin: 4px 0 12px; }
.ms { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; background: rgba(var(--tint-rgb), 0.025); border: 1px solid var(--hairline); border-radius: var(--radius-block); }
.ms-l { color: var(--ash); font-size: var(--fs-xs); }
.ms-v { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; }
.fn-block { display: flex; flex-direction: column; gap: 12px; margin-bottom: 18px; }
.fn-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; }
.fn-label { color: var(--bone); font-size: var(--fs-md); font-weight: 600; }
/* Ступень ВЫШЕ соседей: .fn-label рядом стоит на --fs-md, и при --fs-lg разрыв
   между подписью и значением схлопывался бы до 1px — значение переставало
   читаться как значение. */
.fn-val { color: var(--bone); font-size: var(--fs-xl); font-weight: 800; font-variant-numeric: tabular-nums; }
.fn-track { height: 14px; background: rgba(var(--tint-rgb), 0.05); border-radius: var(--radius-ctl); overflow: hidden; }
.fn-bar { height: 100%; border-radius: var(--radius-ctl); transition: width 0.5s ease; }
.fn-bar-0 { background: linear-gradient(90deg, var(--series-leads), var(--series-leads-deep)); }
.fn-bar-1 { background: linear-gradient(90deg, var(--series-conv), var(--series-conv-deep)); }
.fn-bar-2 { background: linear-gradient(90deg, var(--ember), var(--series-revenue-deep)); }
.fn-sub { margin-top: 3px; font-size: var(--fs-xs); color: var(--ash-dim); }

/* Три воронки успешных сделок: Общая (итог всех воронок) + Обращения + Заказы сайта. */
.fn-total { padding: 14px 16px; margin-bottom: 16px; border: 1px solid var(--hairline); border-radius: var(--radius-inner);
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.09), rgba(var(--tint-rgb), 0.02)); }
.fn-total-cap { color: var(--ash); font-size: var(--fs-xs); letter-spacing: 0.02em; }
.fn-total-main { display: flex; align-items: baseline; gap: 12px; margin-top: 4px; }
.fn-total-val { color: var(--bone); font-size: var(--fs-5xl); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; }
.fn-total-rev { color: var(--ember); font-size: var(--fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; }
.fn-total-parts { margin-top: 9px; color: var(--ash-dim); font-size: var(--fs-xs); }
.fn-total-parts b { color: var(--bone); font-weight: 600; font-variant-numeric: tabular-nums; }

.fn-group { padding-top: 14px; margin-bottom: 14px; border-top: 1px solid var(--hairline); }
.fn-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
/* Ember + капс — чтобы разделение по воронкам сразу бросалось в глаза. */
.fn-group-title { color: var(--ember); font-size: var(--fs-md); font-weight: 700; text-transform: uppercase; letter-spacing: 0.045em; }
.fn-group-sub { color: var(--ash-dim); font-size: var(--fs-xs); }
.fn-group .fn-block { margin-bottom: 8px; }

.fn-note { color: var(--ash-dim); font-size: var(--fs-xs); margin: 2px 0 8px; }
.fn-note b { color: var(--ash); font-weight: 600; font-variant-numeric: tabular-nums; }
.fn-loss-line { color: var(--ash-dim); font-size: var(--fs-xs); margin-top: 6px; }
.fn-loss-line b { color: var(--bone); font-weight: 600; font-variant-numeric: tabular-nums; }
.fn-loss-note { color: var(--ash-dim); font-weight: 400; font-size: var(--fs-2xs); }

/* Source split context (by-source text/phone leads + CAT0/CAT20 won) under the funnel. */
.fn-source { margin: 14px 0 2px; padding: 12px 0; border-top: 1px solid var(--hairline); display: grid; gap: 8px; }
.fn-source-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.fn-source-row span { color: var(--ash-dim); font-size: var(--fs-xs); }
.fn-source-row b { color: var(--bone); font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

.loss-block { border-top: 1px solid var(--hairline); padding-top: 14px; }
.loss-pending { color: var(--ash-dim); font-size: var(--fs-sm); padding: 8px 0 2px; }
.loss-title { color: var(--ash); font-size: var(--fs-sm); margin-bottom: 12px; }
.loss-row { margin-bottom: 11px; }
.loss-row.loss-dim { opacity: 0.45; }
.loss-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; }
.loss-label { color: var(--bone); font-size: var(--fs-sm); }
.loss-meta { color: var(--ash); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; white-space: nowrap; }
.loss-track { height: 10px; background: rgba(var(--tint-rgb), 0.05); border-radius: var(--radius-xs); overflow: hidden; }
.loss-bar { height: 100%; background: linear-gradient(90deg, var(--status-bad), #ff8a5a); border-radius: var(--radius-xs); transition: width 0.5s ease; }

.mgr-grid { display: flex; flex-direction: column; gap: 12px; }
.mgr-card { padding: 15px 16px; border-radius: var(--radius-inner); backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(var(--tint-rgb), 0.025); border: 1px solid var(--hairline); box-shadow: none; }
.mgr-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mgr-name { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; }
.mgr-badges { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.mgr-badge { font-size: var(--fs-2xs); font-weight: 700; padding: 3px 8px; border-radius: var(--radius-pill); white-space: nowrap; }
.mgr-best { color: #ffd54a; background: rgba(255, 213, 74, 0.12); border: 1px solid rgba(255, 213, 74, 0.35); }
.mgr-help { color: #ffb074; background: rgba(255, 122, 64, 0.12); border: 1px solid rgba(255, 122, 64, 0.35); }
.mgr-revenue { color: var(--bone); font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -0.02em; margin-top: 8px; font-variant-numeric: tabular-nums; }
.mgr-revenue-sub { color: var(--ash-dim); font-size: var(--fs-xs); margin-bottom: 12px; }
.mgr-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 16px; }
.mgr-stat-top { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; margin-bottom: 4px; }
.mgr-stat-label { color: var(--ash); font-size: var(--fs-xs); }
.mgr-stat-val { color: var(--bone); font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mgr-stat-weak .mgr-stat-label, .mgr-stat-weak .mgr-stat-val { color: #ffb074; }
/* Дублирует смысл цвета буллета глифом: цвет не должен быть единственным
   носителем значения. Кегль ниже значения и приглушённая непрозрачность —
   чтобы метка читалась как пометка, а не спорила с самим числом. */
.mgr-stat-mark { margin-left: 5px; font-size: var(--fs-micro); opacity: 0.85; }
.mgr-stat-mark.good { color: var(--status-good); }
.mgr-stat-mark.bad { color: #ff7a5a; }
.mgr-bullet { position: relative; height: 7px; background: rgba(var(--tint-rgb), 0.06); border-radius: var(--radius-xs); }
.mgr-bullet-fill { height: 100%; border-radius: var(--radius-xs); }
.mgr-bullet-fill.good { background: var(--status-good); }
.mgr-bullet-fill.bad { background: #ff7a5a; }
.mgr-bullet-fill.muted { background: rgba(var(--tint-rgb), 0.14); }
.mgr-stat-empty .mgr-stat-val { color: var(--ash-dim); }
.mgr-bullet-avg { position: absolute; top: -2px; width: 2px; height: 11px; background: rgba(var(--tint-rgb), 0.6); border-radius: var(--radius-xs); }

@media (max-width: 1100px) {
  .boards { grid-template-columns: 1fr; }
  .kpi-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .kpi-row { grid-template-columns: 1fr; }
  .mgr-stats { grid-template-columns: 1fr; }
}

/* «Рассчитать» action + sparse-trend markers */
.head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
/* Кнопки ряда не сжимаются: «⏳ Собираем отчёт… 5%» + метка «таблица» шире подписи покоя, и сжатая
   flex-ом кнопка выталкивала метку за свой край под соседний переключатель (03.11.2026).
   Не помещается ряд — переносится, а не налезает. */
.head-actions > .recalc-btn, .head-actions > .seg { flex: 0 0 auto; }
/* Прозрачный вид как у «Сравнение периодов» (.compare-link): тёмная заливка + тонкая рамка,
   ember-контур появляется на hover (+ мягкое свечение). Ember-заливка больше не постоянная. */
.recalc-btn { border: 1px solid var(--hairline); background: var(--graphite-2); color: var(--bone); font-family: var(--font); font-size: var(--fs-sm); font-weight: 700; padding: 7px 14px; border-radius: var(--radius-pill); cursor: pointer; white-space: nowrap; text-align: center; font-variant-numeric: tabular-nums; transition: border-color 0.15s, box-shadow 0.15s, filter 0.15s; }
/* Здесь свечение на наведении существовало и раньше — правило приведено к общему
   токену. Добавлены два исключения:
   .busy/.running — у бегущей кнопки свой пульс контура с периодом 2.8 с, и
   вмешательство hover сбивало бы «одно дыхание» (в ветке reduced-motion
   анимация выключена, там hover перебил бы статичную тень напрямую);
   :disabled уже отсекал кнопки в часовом кулдауне — это условие сохранено. */
.recalc-btn:not(:disabled):not(.busy):not(.running):hover { border-color: var(--ember); box-shadow: var(--glow-hover); filter: brightness(1.05); }
/* Фиксируем ширину под САМЫЙ ДЛИННЫЙ (загрузочный) лейбл, чтобы кнопка не «пухла» на время
   сборки и не «усыхала» после. tabular-nums держит ширину процента ровной (5%→81%→100%). */
#recalc  { min-width: 170px; }
#rebuild { min-width: 206px; }
.recalc-btn.busy, .recalc-btn:disabled { background: rgba(var(--tint-rgb), 0.06); border-color: var(--hairline); color: var(--ash-dim); box-shadow: none; cursor: default; }

/* ---- Активная кнопка сборки «⏳ Собираем отчёт… N%» / «⏳ Обновляем…» ----
   Проблема: .busy гасил кнопку в еле заметный серый чип — сотрудник не видел, что
   отчёт обновляется. Теперь РАБОТАЮЩАЯ кнопка (.running перебивает .busy, стоит ниже
   по каскаду) непрерывно ПЕРЕЛИВАЕТСЯ тёплым свечением: тон плывёт ember → светлый янтарь
   → ember, а glow слегка расширяется. Свечение НЕ гаснет в ноль (высокий «пол»), поэтому
   не «прерывается». Один оранжевый тон и свечение-elevation — по DESIGN.md. */
.recalc-btn.running {
  color: var(--bone);
  cursor: progress;
  border: 1px solid var(--ember);                 /* та же толщина, что в покое — без +1px «роста» */
  background: rgba(34, 20, 13, 0.96);              /* тёплая тёмная заливка, ember-контур */
  /* alternate: раскадровка dim→bright проигрывается вперёд (рассвет) и назад (затухание)
     зеркально — нарастание и спад ОДИНАКОВЫ по времени и плавности (по 1.4с, цикл 2.8с). */
  animation: recalc-shimmer 1.4s ease-in-out infinite alternate;
}
.recalc-btn.running:hover { filter: none; }
@keyframes recalc-shimmer {
  from { border-color: #ff6a2e; box-shadow: 0 0 0 1px var(--ember), 0 0 16px 3px rgba(var(--ember-rgb), 0.45); }
  to   { border-color: #ffa067; box-shadow: 0 0 0 1px #ff7a3c,      0 0 30px 7px rgba(255, 130, 60, 0.62); }
}
/* Reduce-motion: без перелива — статичная заметная ember-рамка со свечением. */
@media (prefers-reduced-motion: reduce) {
  .recalc-btn.running { animation: none; border-color: var(--ember); box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 18px 3px var(--ember-glow); }
}
.cc-rev-dot { fill: var(--ember); }
.cc-conv-dot { fill: var(--series-conv); }
.cc-note { color: var(--ash-dim); font-size: var(--fs-xs); margin-left: auto; align-self: center; }

/* ---------------- Уведомления «товар поступил к поставщику» (out_of_stock) ---------------- */
.arrivals { position: relative; display: inline-flex; }
.arrivals-bell { display: inline-flex; align-items: center; gap: 7px; padding: 7px 12px; border-radius: var(--radius-block);
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline); color: var(--ash);
  cursor: pointer; font-size: var(--fs-sm); transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; }
.arrivals-bell:hover { background: rgba(var(--tint-rgb), 0.09); color: var(--bone); }
.arrivals-bell.has { color: var(--ember); border-color: rgba(var(--ember-rgb), 0.4); }
.arrivals-label { font-weight: 600; }
.arrivals-badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-block); background: var(--ember);
  color: var(--bone); font-size: var(--fs-2xs); font-weight: 700; display: inline-flex; align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums; }
.arrivals-pop { position: absolute; top: calc(100% + 8px); right: 0; width: 340px; max-width: 90vw;
  max-height: 440px; overflow-y: auto; padding: 12px; z-index: 60; border-radius: var(--radius-inner);
  background: rgba(20, 17, 14, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(var(--tint-rgb), 0.16);
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(var(--tint-rgb), 0.06);
  animation: cal-in 0.14s ease-out; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .arrivals-pop { background: rgba(29, 26, 23, 0.98); }
}
.arrivals-head { display: flex; justify-content: space-between; align-items: center; font-size: var(--fs-sm);
  color: var(--bone); font-weight: 700; margin-bottom: 10px; }
.arrivals-head span { color: var(--ember); }
.arrivals-empty { color: var(--ash-dim); font-size: var(--fs-sm); padding: 14px 4px; text-align: center; }
.arrivals-list { display: flex; flex-direction: column; gap: 8px; }
.arrival-item { padding: 9px 10px; border-radius: var(--radius-block); background: rgba(var(--tint-rgb), 0.04);
  border: 1px solid var(--hairline); }
.arrival-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.arrival-product { color: var(--bone); font-size: var(--fs-sm); font-weight: 600; }
.arrival-price { color: var(--ember); font-size: var(--fs-sm); font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.arrival-sub { color: var(--ash-dim); font-size: var(--fs-xs); margin-top: 3px; }

/* Оговорка о когортах на «Сравнении периодов»: конверсия делит победы, закрытые в окне, на
   лиды, созданные в окне. При скачке лидов она проседает механически — молчать об этом нельзя. */
.cmp-cohort-warn {
  margin: 10px 0 0; padding: 8px 12px; border-radius: var(--radius-ctl); cursor: help;
  border: 1px solid rgba(240, 161, 50, .35); background: rgba(240, 161, 50, .08);
  color: var(--warn, #f0a132); font-size: var(--fs-sm); line-height: 1.45;
}

/* ═══════════════ «Сотрудники»: оргструктура + редактор графика ═══════════════ */
.emp-wrap {
  padding: 20px 40px 60px; display: grid;
  grid-template-columns: minmax(240px, 320px) 1fr; gap: 22px; align-items: start;
}
/* — левая колонка: оргструктура (отделы → сотрудники) — */
.emp-structure {
  background: var(--graphite); border: 1px solid var(--hairline);
  border-radius: var(--radius-block); overflow: hidden auto;
  position: sticky; top: 88px; max-height: calc(100vh - 120px);
}
.emp-struct-head {
  display: flex; align-items: center; gap: 8px; padding: 12px 15px;
  font-weight: 700; color: var(--bone); font-size: var(--fs-md);
  border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; background: var(--graphite-2); z-index: 1;
}
.emp-struct-refresh {
  margin-left: auto; width: 26px; height: 26px; display: grid; place-items: center;
  border-radius: var(--radius-ctl); cursor: pointer; font-size: var(--fs-lg); line-height: 1; color: var(--ash);
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline);
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.emp-struct-refresh:hover { color: var(--bone); border-color: var(--ash); background: rgba(var(--tint-rgb), 0.1); }
.emp-struct-total {
  margin-left: 8px; font-size: var(--fs-2xs); color: var(--ash-dim);
  border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: 1px 8px;
  font-variant-numeric: tabular-nums;
}
.emp-struct-empty { padding: 16px 15px; color: var(--ash-dim); font-size: var(--fs-sm); }
.emp-dept { border-bottom: 1px solid var(--hairline); }
.emp-dept:last-child { border-bottom: none; }
.emp-dept-head {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: transparent; border: none; cursor: pointer; padding: 10px 15px;
  color: var(--ash-dim); font-family: var(--font); font-size: var(--fs-2xs);
  text-transform: uppercase; letter-spacing: 0.04em; transition: color 0.12s, background 0.12s;
}
.emp-dept-head:hover { color: var(--bone); background: rgba(var(--tint-rgb), 0.03); }
.emp-dept.open .emp-dept-head { color: var(--bone); }
.emp-dept-caret { width: 10px; font-size: var(--fs-micro); color: var(--ash-dim); }
.emp-dept.open .emp-dept-caret { color: var(--ember); }
.emp-dept-name { flex: 1; }
.emp-dept-count {
  font-variant-numeric: tabular-nums; opacity: 0.8; font-size: var(--fs-2xs);
  border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: 0 7px;
}
/* руководитель отдела в раскрытом списке — просто первым и жирным (без подписи) */
.emp-person.is-head .emp-person-name { color: var(--bone); font-weight: 700; }
.emp-person {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: transparent; border: none; border-left: 2px solid transparent;
  color: var(--bone); font-family: var(--font); font-size: var(--fs-md);
  padding: 7px 15px; cursor: pointer; transition: background 0.12s, border-color 0.12s;
}
.emp-person:hover { background: rgba(var(--tint-rgb), 0.05); }
.emp-person.active { background: rgba(var(--ember-rgb), 0.12); border-left-color: var(--ember); }
.emp-person-name { flex: 1; }
.emp-person-badge { color: var(--ember); font-size: var(--fs-xl); line-height: 0; }

/* — правая колонка: редактор — */
.emp-editor { padding: 20px 22px; border-radius: var(--radius-card); position: relative; z-index: 10; min-height: 360px; }
.emp-editor-empty { color: var(--ash-dim); font-size: var(--fs-md); padding: 48px 10px; text-align: center; }
.emp-editor-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.emp-who-name { display: block; font-size: var(--fs-xl); font-weight: 800; color: var(--bone); letter-spacing: -0.01em; }
.emp-who-dept { display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--ash-dim); }
.emp-month { position: relative; }
#e-monthTrigger { gap: 8px; }
.emp-caret { color: var(--ash-dim); font-size: var(--fs-2xs); }

/* месяц-грид редактора (панель управления вынесена НАД сеткой — контролы у верха) */
.emp-grid-wrap { border-top: 1px solid var(--hairline); padding-top: 18px; }
.emp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.e-day {
  min-height: 80px; display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 6px 8px; border-radius: var(--radius-block); cursor: pointer; position: relative;
  border: 1px solid var(--hairline); background: var(--graphite);
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
}
.e-day:not(.e-day--blank):hover { border-color: var(--hairline-strong); }
.e-day-num { font-size: var(--fs-sm); color: var(--ash); font-variant-numeric: tabular-nums; }
.e-day-tag {
  font-size: var(--fs-2xs); color: var(--bone); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Низ ячейки: место работы (для смены) и/или отработанные часы (прошлый день). Всегда прижат к низу
   (margin-top:auto), у дней без данных низ пуст — все ячейки одной высоты, сетка не «прыгает». */
.e-day-facts {
  margin-top: auto; align-self: stretch; display: flex; flex-direction: column; gap: 1px;
  padding-top: 3px; border-top: 1px solid var(--hairline); min-width: 0;
}
.e-day-place, .e-day-work {
  font-size: var(--fs-micro); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.e-day-place { color: var(--ash); }
.e-day-work { color: var(--ash-dim); }
.e-day--blank { background: transparent; border-color: transparent; cursor: default; }
/* Пустой день — намеренно «бесплотный»: прозрачный фон и слабый пунктир. Он должен читаться
   как ОТСУТСТВИЕ данных, а не как ещё один статус, поэтому контраст ниже всех заполненных. */
.e-day--empty { background: transparent; border-style: dashed; border-color: rgba(204, 204, 204, 0.1); }
.e-day--empty .e-day-num { color: rgba(138, 133, 127, 0.75); }
.e-day--work { background: rgba(var(--ember-rgb), 0.14); border-color: rgba(var(--ember-rgb), 0.32); }
.e-day--work .e-day-tag { color: #ffb596; }
/* Выходной — заполненный статус, и выглядеть должен как заполненный: фон/рамка на том же
   уровне, что у отпуска и больничного (было 3 % белого — на графите неотличимо от пустой
   ячейки). Тон холодный сланцевый: нейтрален к ember, поэтому смена остаётся главным
   акцентом сетки, но «выходной» больше не теряется. */
.e-day--off { background: rgba(125, 147, 173, 0.16); border-color: rgba(125, 147, 173, 0.4); }
.e-day--off .e-day-num { color: var(--ash); }
.e-day--off .e-day-tag { color: var(--sched-off); }
.e-day--vacation { background: rgba(59, 182, 166, 0.15); border-color: rgba(59, 182, 166, 0.35); }
.e-day--vacation .e-day-tag { color: var(--sched-vacation); }
.e-day--sick { background: rgba(224, 168, 62, 0.15); border-color: rgba(224, 168, 62, 0.35); }
.e-day--sick .e-day-tag { color: var(--sched-sick); }
.e-day.selected { border-color: var(--ember); box-shadow: 0 0 0 2px var(--ember), 0 0 14px 0 var(--ember-glow); }
/* drag-and-drop копирование дня */
/* Жест переноса дня — свой, на pointer-событиях (employees.js), поэтому цепляемся за класс,
   а не за атрибут draggable: нативный HTML5-перенос отключён (ломался на Windows). */
.e-day--movable { cursor: grab; }
.emp-dragging { user-select: none; -webkit-user-select: none; }
.emp-dragging .e-day--movable { cursor: grabbing; }
.e-day--dragging { opacity: 0.35; cursor: grabbing; }
.e-day--drop { border-color: var(--ember); box-shadow: 0 0 0 2px var(--ember), 0 0 16px 0 var(--ember-glow); }
.emp-drag-hint { margin-top: 10px; color: var(--ash-dim); font-size: var(--fs-xs); }

/* ─────────── панель управления днём — над сеткой, сразу под шапкой ─────────── */
/* Высота фиксирована под «рабочий» вид (заголовок+сегменты+время+место), чтобы сетка ниже НЕ
   прыгала при переключении статуса (у выходного/отпуска/больничного строк времени и места нет). */
.emp-control { min-height: 164px; margin-bottom: 14px; }
.emp-control-day {
  color: var(--bone); font-weight: 700; font-size: var(--fs-md); letter-spacing: -0.01em; margin-bottom: 14px;
}
.emp-control-day--hint { color: var(--ash-dim); font-weight: 600; }
.emp-state-seg { margin-bottom: 14px; }
.emp-state-seg .seg-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ember); }

/* Строки полей: подпись фикс-ширины → контролы выровнены по колонке; нота при нехватке места
   уходит на 2-ю строку (flex-wrap), а сами дропдауны не сжимаются (flex-shrink:0). */
.emp-time, .emp-place { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.emp-time.hidden, .emp-place.hidden { display: none; }
.emp-place { margin-top: 14px; }
.emp-time-cap { width: 104px; flex-shrink: 0; color: var(--ash); font-size: var(--fs-sm); }
.emp-time-dash { color: var(--ash-dim); }
.emp-time-note { color: var(--ash-dim); font-size: var(--fs-xs); margin-left: 2px; flex-shrink: 1; min-width: 0; }

/* до выбора дня — панель видна, но «серая» и неактивная (клик → тост «Выберите дату») */
.emp-control--disabled .emp-state-seg,
.emp-control--disabled .emp-time,
.emp-control--disabled .emp-place { opacity: 0.4; }
.emp-control--disabled .seg-btn,
.emp-control--disabled .emp-timesel-btn { cursor: not-allowed; }

/* ── Кастомные дропдауны (время/место): единый стиль, ФИКС ширина (не «прыгают»), не сжимаются ── */
.emp-timesel, .emp-placesel { position: relative; display: inline-block; }
.emp-timesel-btn {
  display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 11px;
  width: 84px; flex-shrink: 0; cursor: pointer; border-radius: var(--radius-ctl);
}
.emp-placesel-btn { width: 220px; }              /* фикс — размер не зависит от выбранной точки */
.emp-timesel-btn:hover { border-color: var(--ash); }
.emp-timesel-btn:focus-visible { outline: none; border-color: var(--ember); box-shadow: 0 0 0 2px var(--ember-smoke); }
.emp-timesel-val {
  flex: 1; min-width: 0; color: var(--bone); font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
  text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.emp-timesel-caret { flex-shrink: 0; color: var(--ash-dim); font-size: var(--fs-micro); }
/* попап — та же стеклянная рецептура, что у календаря (.cal-pop): единый визуальный язык.
   width:max-content (в пределах max-width) → длинные названия точек видны в списке целиком. */
.emp-timesel-pop {
  position: absolute; top: calc(100% + 5px); left: 0; z-index: 30;
  min-width: 100%; width: max-content; max-width: 300px;
  max-height: 224px; overflow-y: auto; padding: 5px; border-radius: var(--radius-card);
  background: rgba(20, 17, 14, 0.72);
  backdrop-filter: blur(14px) saturate(140%); -webkit-backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(var(--tint-rgb), 0.16);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(var(--tint-rgb), 0.06);
  animation: cal-in 0.12s ease-out;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .emp-timesel-pop { background: rgba(29, 26, 23, 0.98); }
}
.emp-timesel-opt {
  padding: 7px 11px; border-radius: var(--radius-ctl); cursor: pointer; font-size: var(--fs-sm); color: var(--bone);
  font-variant-numeric: tabular-nums; white-space: nowrap; transition: background 0.1s;
}
.emp-timesel-opt:hover { background: rgba(var(--tint-rgb), 0.09); }
.emp-timesel-opt.selected { background: var(--ember); color: var(--bone); box-shadow: 0 0 10px -2px var(--ember-glow); }
.emp-placesel-opt-none { color: var(--ash-dim); }   /* «— не выбрано» приглушённо */

/* легенда + сохранить + тост */
.emp-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.emp-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.emp-leg { display: inline-flex; align-items: center; gap: 6px; color: var(--ash-dim); font-size: var(--fs-xs); }
.emp-swatch { width: 12px; height: 12px; border-radius: var(--radius-xs); display: inline-block; }
.emp-sw--work { background: rgba(var(--ember-rgb), 0.55); }
.emp-sw--off { background: rgba(var(--tint-rgb), 0.14); }
.emp-sw--vacation { background: rgba(59, 182, 166, 0.6); }
.emp-sw--sick { background: rgba(224, 168, 62, 0.6); }
.emp-toast {
  position: absolute; right: 22px; bottom: 16px; padding: 9px 15px; border-radius: var(--radius-ctl);
  font-size: var(--fs-sm); font-weight: 600; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.4);
  animation: cal-in 0.14s ease-out;
}
.emp-toast--ok { background: rgba(var(--online-rgb), 0.16); color: var(--toast-ok); border: 1px solid rgba(var(--online-rgb), 0.4); }
.emp-toast--err { background: rgba(var(--ember-rgb), 0.16); color: #ffb596; border: 1px solid rgba(var(--ember-rgb), 0.4); }
.emp-toast--info { background: rgba(var(--tint-rgb), 0.08); color: var(--bone); border: 1px solid var(--hairline-strong); }

/* прошедший месяц — только просмотр: сетка серее и неинтерактивна, сверху баннер */
.emp-readonly-note {
  display: flex; align-items: center; gap: 8px; margin: 0 0 14px; padding: 9px 13px;
  border-radius: var(--radius-ctl); font-size: var(--fs-sm); color: var(--ash);
  background: rgba(var(--tint-rgb), 0.04); border: 1px solid var(--hairline);
}
.emp-editor--readonly .emp-grid { opacity: 0.5; pointer-events: none; filter: grayscale(0.4); }
.emp-editor--readonly .emp-control { min-height: 0; margin-bottom: 0; }

@media (max-width: 860px) {
  .emp-wrap { grid-template-columns: 1fr; padding: 16px 20px 48px; }
  .emp-structure { position: static; max-height: none; }
}

/* ═══════════════ Экран входа (/login) ═══════════════
   Отдельная лёгкая страница: незачем грузить дашборд тому, кто ещё не вошёл. */
.login-body { min-height: 100vh; display: flex; }
.login-wrap { flex: 1; display: flex; align-items: center; justify-content: center; padding: 24px; }
.login-card {
  width: min(440px, 100%); padding: 30px 28px 26px; border-radius: var(--radius-card);
  border: 1px solid var(--hairline); text-align: center;
}
.login-logo { width: 58px; height: 58px; display: block; margin: 0 auto 10px; }
.login-title { font-family: "Baloo 2", system-ui, sans-serif; color: var(--ember); font-size: var(--fs-4xl); margin: 0; }
.login-sub { color: var(--ash); font-size: var(--fs-sm); margin: 4px 0 20px; }

.login-people { display: flex; flex-direction: column; gap: 16px; text-align: left; }
.login-group-title {
  color: var(--ember); font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; margin-bottom: 7px;
}
.login-person {
  width: 100%; display: flex; align-items: baseline; gap: 9px; cursor: pointer;
  padding: 10px 13px; margin-bottom: 6px; border-radius: var(--radius-block); text-align: left;
  background: rgba(var(--tint-rgb), 0.03); border: 1px solid var(--hairline);
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.login-person:hover { background: rgba(var(--ember-rgb), 0.09); border-color: rgba(var(--ember-rgb), 0.42); transform: translateX(2px); }
.login-person:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.login-person-name { color: var(--bone); font-size: var(--fs-md); font-weight: 600; }
.login-person-dept { color: var(--ash-dim); font-size: var(--fs-xs); margin-left: auto; }
.login-person-nopin {
  color: var(--status-warn); font-size: var(--fs-2xs); border: 1px solid rgba(255, 183, 77, 0.4);
  border-radius: var(--radius-pill); padding: 1px 7px; white-space: nowrap;
}

.login-pin { display: flex; flex-direction: column; gap: 10px; text-align: left; }
.login-back {
  align-self: flex-start; background: none; border: none; cursor: pointer;
  color: var(--ash); font-size: var(--fs-xs); padding: 0 0 4px;
}
.login-back:hover { color: var(--ember); }
.login-who { display: flex; align-items: baseline; gap: 9px; margin-bottom: 4px; }
.login-who-name { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; }
.login-who-dept { color: var(--ash-dim); font-size: var(--fs-xs); }
.login-label { color: var(--ash); font-size: var(--fs-xs); }
.login-input {
  width: 100%; padding: 11px 13px; border-radius: var(--radius-block); letter-spacing: 0.25em;
  background: rgba(var(--tint-rgb), 0.04); border: 1px solid var(--hairline);
  color: var(--bone); font-size: var(--fs-xl); font-family: inherit;
}
.login-input:focus { outline: none; border-color: var(--ember); box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.18); }
.login-submit { width: 100%; justify-content: center; margin-top: 4px; }

.login-msg { margin-top: 14px; font-size: var(--fs-sm); border-radius: var(--radius-block); padding: 9px 12px; text-align: left; }
.login-msg--err { color: #ff9c7a; background: rgba(var(--ember-rgb), 0.1); border: 1px solid rgba(var(--ember-rgb), 0.32); }
.login-msg--info { color: var(--ash); background: rgba(var(--tint-rgb), 0.04); border: 1px solid var(--hairline); }
.login-empty { color: var(--ash-dim); font-size: var(--fs-sm); padding: 14px 0; }

/* ═══════════════ Права в интерфейсе ═══════════════
   Скрываем действия не по роли. Классы вешает auth_ui.js на <body>, поэтому правило работает и
   для кнопок, созданных позже (борды /reports перерисовываются через innerHTML).
   Это ТОЛЬКО UX: спрятанную кнопку можно «нажать» из DevTools — настоящая проверка на сервере. */
.perm-no-refresh_data [data-perm="refresh_data"],
.perm-no-edit_schedule [data-perm="edit_schedule"],
.perm-no-view_finance [data-perm="view_finance"] { display: none !important; }

/* Кто вошёл + выход — в выпадающем меню. */
.menu-user { border-top: 1px solid var(--hairline); margin-top: 6px; padding: 11px 14px 4px; }
.menu-user-name { color: var(--bone); font-size: var(--fs-md); font-weight: 700; }
.menu-user-meta { color: var(--ash-dim); font-size: var(--fs-xs); margin-top: 2px; }
.menu-logout {
  margin-top: 9px; width: 100%; padding: 7px 10px; border-radius: var(--radius-block); cursor: pointer;
  background: rgba(var(--ember-rgb), 0.1); border: 1px solid rgba(var(--ember-rgb), 0.34);
  color: #ff9c7a; font-size: var(--fs-sm); font-family: inherit;
}
.menu-logout:hover { background: rgba(var(--ember-rgb), 0.18); border-color: var(--ember); color: var(--bone); }

/* Доступ сотрудника в Капибару (PIN) — карточка в разделе «Сотрудники», видна только админу. */
.perm-no-manage_pins [data-perm="manage_pins"] { display: none !important; }
/* Административные кнопки принудительной выгрузки из Bitrix — скрыты всем, кроме админа. */
.perm-no-admin [data-perm="admin"] { display: none !important; }
.perm-no-view_hand_on_pulse [data-perm="view_hand_on_pulse"] { display: none !important; }
.emp-access {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin: 20px 0; padding: 10px 13px; border-radius: var(--radius-block);
  background: rgba(var(--tint-rgb), 0.025); border: 1px solid var(--hairline);
}
.emp-access-cap { color: var(--ash); font-size: var(--fs-xs); }
.emp-access-state { color: var(--ash-dim); font-size: var(--fs-xs); margin-right: auto; }
.emp-access-yes { color: var(--status-good); font-weight: 600; }
.emp-access-no { color: var(--status-warn); font-weight: 600; }
.emp-access-pin {
  width: 118px; padding: 6px 10px; border-radius: var(--radius-ctl); letter-spacing: 0.18em;
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline);
  color: var(--bone); font-size: var(--fs-sm); font-family: inherit;
}
.emp-access-pin:focus { outline: none; border-color: var(--ember); }
.emp-access-btn {
  padding: 6px 12px; border-radius: var(--radius-ctl); cursor: pointer; font-size: var(--fs-sm); font-family: inherit;
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline); color: var(--bone);
}
.emp-access-btn:hover { border-color: var(--ember); color: var(--ember); }
.emp-access-btn--danger:hover { border-color: #ff6b4a; color: #ff9c7a; }
.emp-access-flag {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  color: var(--ash); font-size: var(--fs-xs); user-select: none;
}
.emp-access-flag input { accent-color: var(--ember); cursor: pointer; }
.emp-access-flag:hover { color: var(--bone); }
.emp-access-device { color: var(--ash-dim); font-size: var(--fs-xs); }
.emp-access-device b { color: var(--bone); font-weight: 600; }

/* Классическая форма входа (логин + пароль). Список сотрудников больше не показываем. */
.login-form { display: flex; flex-direction: column; gap: 6px; text-align: left; }
.login-form .login-label { margin-top: 8px; }
.login-input--text { letter-spacing: normal; font-size: var(--fs-lg); }
.login-help { color: var(--ash-dim); font-size: var(--fs-xs); margin: 14px 0 0; }
.emp-access-login { width: 130px; letter-spacing: normal; }

/* Лимит устройств — граница тарифа, а не ошибка ввода: тёплая подача вместо красной. */
.login-msg--pro {
  color: var(--bone); background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.14), rgba(var(--tint-rgb), 0.03));
  border: 1px solid rgba(var(--ember-rgb), 0.45); line-height: 1.5;
}
.login-pro-badge {
  display: inline-block; margin-right: 6px; padding: 1px 7px; border-radius: var(--radius-pill);
  background: var(--ember); color: var(--bone); font-size: var(--fs-micro); font-weight: 800; letter-spacing: 0.06em;
  vertical-align: 1px;
}


.emp-pay {
  margin-top: 18px; padding: 16px 18px; border-radius: var(--radius-card);
  border: 1px solid var(--hairline);
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.06), rgba(var(--tint-rgb), 0.02));
}
.emp-pay-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.emp-pay-title { color: var(--bone); font-size: var(--fs-md); font-weight: 700; }
.emp-pay-note { color: var(--ash-dim); font-size: var(--fs-xs); }
.emp-pay-body { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.emp-pay-formula { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.emp-pay-cell { display: flex; flex-direction: column; gap: 5px; }
.emp-pay-cell i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.emp-pay-cell b { color: var(--bone); font-size: var(--fs-xl); font-weight: 700; font-variant-numeric: tabular-nums; }
.emp-pay-op { color: var(--ash-dim); font-size: var(--fs-lg); padding-bottom: 6px; }
.emp-pay-input {
  width: 108px; padding: 6px 10px; border-radius: var(--radius-block);
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline);
  color: var(--bone); font-size: var(--fs-lg); font-family: inherit; font-variant-numeric: tabular-nums;
}
.emp-pay-input:focus { outline: none; border-color: var(--ember); box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.16); }
.emp-pay-input:disabled { opacity: 0.65; cursor: default; }
.emp-pay-total { display: flex; flex-direction: column; gap: 3px; margin-left: auto; text-align: right; }
.emp-pay-total i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.emp-pay-total b { color: var(--ember); font-size: var(--fs-4xl); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.emp-pay-breakdown { color: var(--ash-dim); font-size: var(--fs-xs); }
@media (max-width: 720px) {
  .emp-pay-body { gap: 14px; }
  .emp-pay-total { margin-left: 0; text-align: left; }
}


.emp-top-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 18px; align-items: start; }
.emp-top-row .emp-control { margin-bottom: 0; }

.emp-summary {
  min-height: 164px; padding: 15px 17px; border-radius: var(--radius-card);
  border: 1px solid var(--hairline); background: rgba(var(--tint-rgb), 0.022);
  display: flex; flex-direction: column; gap: 12px;
}
.emp-sum-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.emp-sum-title { color: var(--bone); font-size: var(--fs-md); font-weight: 700; }
.emp-sum-period { color: var(--ash-dim); font-size: var(--fs-xs); }

.emp-sum-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 10px; }
.emp-sum-tile {
  display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border-radius: var(--radius-block);
  background: rgba(var(--tint-rgb), 0.03); border: 1px solid var(--hairline);
}
.emp-sum-tile i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.emp-sum-tile b { color: var(--bone); font-size: var(--fs-xl); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.15; }
.emp-sum-sub { color: var(--ash-dim); font-size: var(--fs-2xs); }

/* Заработок — акцентная плитка: занимает всю ширину строки и подсвечена ember. */
.emp-sum-tile--money {
  grid-column: 1 / -1;
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.11), rgba(var(--tint-rgb), 0.02));
  border-color: rgba(var(--ember-rgb), 0.34);
}
.emp-sum-tile--money b { color: var(--ember); font-size: var(--fs-3xl); font-weight: 800; }

@media (max-width: 1100px) {
  .emp-top-row { grid-template-columns: 1fr; }
  .emp-summary { min-height: 0; }
}

/* ═══════════ Карточка сотрудника (единый блок под календарём) ═══════════
   Иерархия: показатели → точки роста → зарплата в подвале. Один ember-акцент на весь блок —
   «Заработал»; всё остальное нейтральное, иначе рябит и выглядит дёшево. */
.emp-card {
  margin: 20px 0; padding: 20px 22px; border-radius: var(--radius-card);
  border: 1px solid var(--hairline); background: rgba(var(--tint-rgb), 0.022);
}
.emp-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.emp-card-title { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; }
.emp-card-period { color: var(--ash-dim); font-size: var(--fs-xs); }

.emp-card-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 22px; }
.emp-metric { display: flex; flex-direction: column; gap: 4px; }
.emp-metric i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.emp-metric b { color: var(--bone); font-size: var(--fs-3xl); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.emp-metric-sub { color: var(--ash-dim); font-size: var(--fs-2xs); }

.emp-card-section { margin-top: 18px; }
.emp-card-label { color: var(--ash); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 8px; }
.emp-card-by { color: var(--ash-dim); text-transform: none; letter-spacing: 0; margin-left: 8px; font-size: var(--fs-2xs); }
.emp-card-empty { color: var(--ash-dim); font-size: var(--fs-sm); }
.emp-growth-input {
  width: 100%; padding: 10px 12px; border-radius: var(--radius-block); resize: vertical; min-height: 68px;
  background: rgba(var(--tint-rgb), 0.04); border: 1px solid var(--hairline);
  color: var(--bone); font-size: var(--fs-sm); font-family: inherit; line-height: 1.5;
}
.emp-growth-input:focus { outline: none; border-color: var(--ember); box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.15); }
.emp-growth-text { color: var(--bone); font-size: var(--fs-sm); line-height: 1.55; white-space: pre-wrap; }

/* Подвал блока — зарплата. Отделён линией: другая зона доступа, и это должно читаться. */
.emp-card-pay { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--hairline); }
.emp-card-pay > .emp-card-label { margin-bottom: 14px; }
.emp-pay-inputs {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 14px 16px; margin-bottom: 20px;
}
.emp-pay-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.emp-pay-field i {
  color: var(--ash); font-size: var(--fs-2xs); font-style: normal; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.emp-pay-input {
  width: 100%; box-sizing: border-box; height: 38px; padding: 0 12px; border-radius: var(--radius-block);
  background: rgba(var(--tint-rgb), 0.05); border: 1px solid var(--hairline);
  color: var(--bone); font-size: var(--fs-lg); font-family: inherit; font-variant-numeric: tabular-nums;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.emp-pay-input:hover:not(:disabled) { border-color: var(--hairline-strong); }
.emp-pay-input:focus { outline: none; border-color: var(--ember); box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.16); }
.emp-pay-input:disabled { opacity: 0.6; cursor: default; }

.emp-pay-results { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; }
.emp-pay-result {
  display: flex; flex-direction: column; gap: 4px; padding: 16px 18px; border-radius: var(--radius-inner);
  background: rgba(var(--tint-rgb), 0.03); border: 1px solid var(--hairline);
}
.emp-pay-result i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.emp-pay-result b { color: var(--bone); font-size: var(--fs-2xl); font-weight: 700; font-variant-numeric: tabular-nums; }
.emp-pay-result--main {
  background: linear-gradient(135deg, rgba(var(--ember-rgb), 0.12), rgba(var(--tint-rgb), 0.02));
  border-color: rgba(var(--ember-rgb), 0.36);
}
.emp-pay-result--main b { color: var(--ember); font-size: var(--fs-4xl); font-weight: 800; }

/* ═══════════ Сворачиваемый редактор дня ═══════════
   Высоту НЕ считаем в JS: grid-template-rows 0fr→1fr анимирует её сам, поэтому содержимое
   может менять размер (место работы, время) без рывков и без пересчёта на каждый рендер. */
.emp-panel {
  border: 1px solid var(--hairline); border-radius: var(--radius-card); overflow: hidden;
  background: rgba(var(--tint-rgb), 0.022); margin: 20px 0;
  transition: border-color 0.25s ease, background 0.25s ease;
}
.emp-panel[data-open="true"] { border-color: rgba(var(--ember-rgb), 0.28); background: rgba(var(--ember-rgb), 0.04); }

.emp-panel-head {
  width: 100%; display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 13px 17px; background: none; border: none; text-align: left; font-family: inherit;
}
.emp-panel-head:hover .emp-panel-title { color: var(--ember); }
.emp-panel-head:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }
.emp-panel-title { color: var(--bone); font-size: var(--fs-md); font-weight: 700; transition: color 0.2s ease; }
.emp-panel-hint { color: var(--ash-dim); font-size: var(--fs-xs); margin-right: auto; }
.emp-panel[data-open="true"] .emp-panel-hint { color: var(--ember); }
.emp-panel-caret {
  color: var(--ash); font-size: var(--fs-xs); transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
.emp-panel[data-open="true"] .emp-panel-caret { transform: rotate(180deg); color: var(--ember); }

.emp-panel-body {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.34s cubic-bezier(0.4, 0, 0.2, 1);
}
.emp-panel[data-open="true"] .emp-panel-body { grid-template-rows: 1fr; }
.emp-panel-inner { overflow: hidden; }
/* Панель раскрыта и замерла (класс ставит JS после анимации): снимаем клип на обоих уровнях,
   иначе overflow:hidden обрезает выпадающие списки времени/места, выходящие за низ панели. */
.emp-panel--settled { overflow: visible; }
.emp-panel--settled .emp-panel-inner { overflow: visible; }
/* Содержимое чуть «выезжает» — раскрытие читается как движение, а не как рывок высоты. */
.emp-panel-inner > .emp-control {
  padding: 2px 17px 16px; min-height: 0; margin-bottom: 0;
  opacity: 0; transform: translateY(-6px);
  transition: opacity 0.26s ease 0.06s, transform 0.26s ease 0.06s;
}
.emp-panel[data-open="true"] .emp-panel-inner > .emp-control { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .emp-panel-body, .emp-panel-caret, .emp-panel-inner > .emp-control { transition: none; }
}
/* Пометка, что числа посчитаны по несохранённому черновику графика. */
.emp-card-draft { color: var(--ember); font-weight: 600; }

/* ═══════════ B2B: три воронки Кристины ═══════════
   Медиана стоит рядом со средним намеренно: в B2B среднее перекошено единичными крупными
   сделками, и показывать только его — вводить в заблуждение. */
.b2b-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; }
.b2b-tile {
  display: flex; flex-direction: column; gap: 4px; padding: 13px 15px; border-radius: var(--radius-inner);
  background: rgba(var(--tint-rgb), 0.03); border: 1px solid var(--hairline);
}
.b2b-tile i { color: var(--ash); font-size: var(--fs-2xs); font-style: normal; }
.b2b-tile b { color: var(--bone); font-size: var(--fs-2xl); font-weight: 700; font-variant-numeric: tabular-nums; }
.b2b-tile:first-child b { color: var(--ember); font-size: var(--fs-3xl); font-weight: 800; }
.b2b-sub { color: var(--ash-dim); font-size: var(--fs-2xs); }

.b2b-funnel { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.b2b-funnel:first-of-type { border-top: none; padding-top: 4px; margin-top: 8px; }
.b2b-funnel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.b2b-funnel-title { color: var(--ember); font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.b2b-funnel-sub { color: var(--ash-dim); font-size: var(--fs-xs); }
.b2b-row { margin-bottom: 9px; }
.b2b-row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
.b2b-row-head span { color: var(--ash); font-size: var(--fs-xs); }
.b2b-row-head b { color: var(--bone); font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.b2b-track { height: 8px; background: rgba(var(--tint-rgb), 0.05); border-radius: var(--radius-xs); overflow: hidden; }
.b2b-bar { height: 100%; border-radius: var(--radius-xs); background: linear-gradient(90deg, var(--ember), var(--series-revenue-deep)); transition: width 0.4s ease; }
.b2b-age { display: block; margin-top: 3px; color: var(--ash-dim); font-size: var(--fs-2xs); }
.b2b-age--bad { color: var(--status-warn); }
.b2b-bar--bad { background: linear-gradient(90deg, var(--status-warn), #ff8a3d); }
.b2b-warn { color: var(--status-warn); font-weight: 700; }
.b2b-dyn { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.b2b-dyn-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; color: var(--ash); font-size: var(--fs-xs); }
.b2b-dyn-legend { color: var(--ash-dim); font-size: var(--fs-2xs); }
.b2b-lg-rev, .b2b-lg-base { display: inline-block; width: 9px; height: 9px; border-radius: var(--radius-xs); margin: 0 4px 0 8px; }
.b2b-lg-rev { background: var(--ember); }
.b2b-lg-base { background: rgba(var(--ember-rgb), 0.42); }
.b2b-dyn-row { display: grid; grid-template-columns: 76px 1fr 78px 52px 74px 44px; align-items: center; gap: 10px; margin-bottom: 7px; }
.b2b-dyn-m { color: var(--ash); font-size: var(--fs-xs); }
.b2b-dyn-track { position: relative; height: 12px; background: rgba(var(--tint-rgb),0.05); border-radius: var(--radius-ctl); overflow: hidden; }
.b2b-dyn-bar { position: absolute; inset: 0 auto 0 0; background: var(--ember); border-radius: var(--radius-ctl); }
.b2b-dyn-base { position: absolute; inset: 0 auto 0 0; background: rgba(var(--tint-rgb),0.28); border-radius: var(--radius-ctl); }
.b2b-dyn-v, .b2b-dyn-wr { color: var(--bone); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; text-align: right; }
.b2b-dyn-wr { color: var(--ash-dim); }

/* Возрастные корзины: полоса от «свежих» к «старым». Цвет усиливается слева направо —
   чем правее сегмент, тем дольше сделка лежит без движения. */
.b2b-agbar { display: flex; gap: 3px; height: 22px; margin: 12px 0 5px; }
.b2b-ag { display: flex; align-items: center; justify-content: center; min-width: 26px;
  border-radius: var(--radius-xs); font-size: var(--fs-2xs); font-weight: 700; color: var(--on-accent);
  font-variant-numeric: tabular-nums; }
.b2b-ag-0 { background: #8fb996; }
.b2b-ag-1 { background: #c9c37e; }
.b2b-ag-2 { background: #e0a95f; }
.b2b-ag-3 { background: #ff8a3d; }
.b2b-ag-4 { background: var(--ember); color: var(--bone); }
.b2b-agnote { color: var(--ash-dim); font-size: var(--fs-2xs); margin-bottom: 14px; }
.b2b-funnels { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 22px; }
.b2b-dyn-hd { color: var(--ash-dim); font-size: var(--fs-2xs); padding-bottom: 6px;
  border-bottom: 1px solid var(--hairline); margin-bottom: 9px; }
.b2b-dyn-n { color: var(--ash); font-size: var(--fs-xs); text-align: right; font-variant-numeric: tabular-nums; }
/* Причины отказа — единственный блок, отвечающий «почему», поэтому он внизу воронки, как вывод. */
.b2b-lost { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--hairline); }
.b2b-lost > i { display: block; color: var(--ash-dim); font-size: var(--fs-2xs); font-style: normal;
  margin-bottom: 8px; }
.b2b-lost-row { display: grid; grid-template-columns: 1fr 70px 42px; align-items: center; gap: 8px;
  margin-bottom: 5px; color: var(--ash); font-size: var(--fs-xs); }
.b2b-lost-row b { color: var(--bone); text-align: right; font-variant-numeric: tabular-nums; }
.b2b-lost-track { height: 6px; background: rgba(var(--tint-rgb),0.05); border-radius: var(--radius-xs); overflow: hidden; }
.b2b-lost-track > span { display: block; height: 100%; background: rgba(var(--ember-rgb),0.55); border-radius: var(--radius-xs); }
/* Оговорка о качестве данных: намеренно заметная и НАД цифрами, а не сноской под ними. */
.b2b-caveat { margin: 10px 0 4px; padding: 9px 11px; border-radius: var(--radius-ctl); font-size: var(--fs-xs);
  line-height: 1.45; color: #ffcf9a; background: rgba(255,138,61,0.08);
  border-left: 2px solid #ff8a3d; }
/* Скелет загрузки B2B. Спокойная пульсация вместо спиннера: страница уже «дышит» ember-переливом
   на кнопке, второй активный акцент рядом соперничал бы с ним за внимание. */
.b2b-skel i, .b2b-skel b, .b2b-skel-line {
  display: block; border-radius: var(--radius-ctl);
  background: linear-gradient(90deg, rgba(var(--tint-rgb),0.04), rgba(var(--tint-rgb),0.09), rgba(var(--tint-rgb),0.04));
  background-size: 200% 100%;
  animation: b2b-skel 1.6s ease-in-out infinite;
}
.b2b-skel i { width: 62%; height: 9px; margin-bottom: 9px; }
.b2b-skel b { width: 44%; height: 17px; }
.b2b-skel-line { height: 13px; margin-bottom: 11px; }
.b2b-skel-line:nth-child(2n) { width: 84%; }
.b2b-skel-line:nth-child(3n) { width: 68%; }
@keyframes b2b-skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .b2b-skel i, .b2b-skel b, .b2b-skel-line { animation: none; background: rgba(var(--tint-rgb),0.07); }
}
/* Метка «оплата за смену» в ячейке дня. Некликабельная (pointer-events:none) — ячейка
   перетаскивается, и любой интерактивный контрол внутри конфликтовал бы с этим жестом. */
.e-day-paymark {
  position: absolute; top: 5px; right: 6px; pointer-events: none;
  width: 15px; height: 15px; border-radius: var(--radius-xs);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-micro); font-weight: 800; letter-spacing: 0;
  color: var(--on-accent); background: var(--ember);
  box-shadow: 0 0 8px -2px var(--ember-glow);
}
.emp-paymode { margin-top: 14px; }
.emp-pay-seg { flex-shrink: 0; }
/* Личный кабинет рядового сотрудника: оргструктуры нет, карточка занимает всю ширину. */
.emp-wrap--self { grid-template-columns: 1fr; }
.emp-wrap--self .emp-structure { display: none; }

/* ---- «Рука на пульсе»: пульс точек Драйва ---- */
/* Страница собрана из общих кирпичей (.cards/.card, .panel, .seg, .cal-pop, table).
   Здесь — только то, чего в системе нет: подпись под заголовком, ряд с сегментом и
   подсказкой, липкая первая колонка широкой месячной таблицы и пометка ручного ввода. */
.hp-sub { color: var(--ash-dim); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
/* Колонка выбранного в календаре дня — чтобы календарь на что-то влиял в табличном виде. */
.hp-day { background: rgba(var(--ember-rgb), 0.12); }
th.hp-day { color: var(--bone); }
.hp-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 14px; }
.hp-hint { color: var(--ash-dim); font-size: var(--fs-sm); }
/* Месячная таблица — 37 колонок: первая колонка липкая, иначе непонятно, чью строку смотришь. */
.hp-metric { position: sticky; left: 0; background: var(--graphite); color: var(--bone); }
/* Недельные и итоговые колонки: их считает формула, а не день — отделяем фоном. */
.hp-total { background: rgba(var(--tint-rgb), 0.04); font-weight: 600; }
/* Ссылка на готовый лист. Была браузерной синей и терялась на графите: это ИТОГ работы,
   до которого человек ждал минуту-три, — он обязан бросаться в глаза. Оформлена таблеткой
   семейства .recalc-btn, но с ember-заливкой: рядом с ней это не «ещё одна кнопка», а
   результат. Свечение — только на наведении, как заведено на активных кнопках. */
.sheet-link {
  display: inline-flex; align-items: center; gap: 6px; margin-left: 8px;
  padding: 6px 14px; border: 1px solid var(--ember-smoke); border-radius: var(--radius-pill);
  background: rgba(var(--ember-rgb), 0.10); color: var(--bone);
  font-family: var(--font); font-size: var(--fs-sm); font-weight: 700;
  text-decoration: none; white-space: nowrap;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.sheet-link:hover, .sheet-link:focus-visible {
  border-color: var(--ember); background: rgba(var(--ember-rgb), 0.18);
  box-shadow: 0 0 0 1px var(--ember-smoke), 0 0 16px 2px rgba(var(--ember-rgb), 0.35);
  outline: none;
}
/* Стрелка отъезжает по диагонали — движение спокойное, без подпрыгиваний. */
.sheet-link .sheet-link-arrow { transition: transform 0.15s; }
.sheet-link:hover .sheet-link-arrow { transform: translate(1px, -1px); }
@media (prefers-reduced-motion: reduce) {
  .sheet-link, .sheet-link .sheet-link-arrow { transition: none; }
  .sheet-link:hover .sheet-link-arrow { transform: none; }
}

/* День, которого срез не застал: гасим, чтобы «не считали» не читалось как «не было». */
td.hp-nodata, th.hp-nodata { color: var(--ink-dim); cursor: help; }
/* День самой сборки посчитан лишь до её времени — помечаем как неполный. */
th.hp-partial { border-bottom: 1px dashed var(--warn, #f0a132); cursor: help; }
.hp-notes { margin-top: 12px; color: var(--ash-dim); font-size: var(--fs-sm); line-height: 1.6; }
.hp-notes ul { margin: 0; padding-left: 18px; }
.hp-notes li { margin-bottom: 4px; }
/* Ручной ввод помечается ВСЕГДА: смешивать его с посчитанным нельзя (DATA_TRUTH.md). */
.hp-manual-badge { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--ash-dim); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-pill); padding: 1px 7px; margin-left: 6px; }
.hp-manual { display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap; }
.hp-field { display: flex; flex-direction: column; gap: 6px; font-size: var(--fs-xs); color: var(--ash); }
.hp-field-wide { flex: 1; min-width: 220px; }
.hp-field input {
  background: rgba(var(--tint-rgb), 0.05);
  border: 1px solid var(--hairline);
  color: var(--bone);
  border-radius: var(--radius-block);
  height: 38px;
  padding: 0 12px;
  font-size: var(--fs-lg);
  font-family: inherit;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.hp-field input:hover:not(:disabled) { border-color: var(--hairline-strong); }
.hp-field input:focus { outline: none; border-color: var(--ember);
  box-shadow: 0 0 0 3px rgba(var(--ember-rgb), 0.16); }
.seg-wrap { display: flex; flex-direction: column; gap: 6px; }
#hp-ratingSeg .seg-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ember); }

@media (max-width: 1024px) {
  .hp-manual { gap: 14px; }
}

/* ---- Кнопки выгрузок на «Отчётах» ---- */
/* Вид — общий `.recalc-btn` (фон graphite-2, тонкая рамка, ember только на hover): четыре
   залитых оранжевым кнопки в ряд оказались слишком броскими (заказчик, 2026-08-06).
   Здесь остаётся ТОЛЬКО раскладка: ровный ряд по ширине страницы, на телефоне — плитка 2×2.
   auto-fit + minmax даёт и то и другое без отдельного правила для планшета. */
.run-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 8px;
}
/* Ширина задаётся сеткой, поэтому снимаем nowrap и растягиваем кнопку на всю ячейку. */
.run-tile {
  width: 100%;
  white-space: normal;
  padding: 8px 12px;
  min-height: 38px;
}

@media (max-width: 600px) {
  .run-grid { grid-template-columns: repeat(2, 1fr); }
  .run-tile { min-height: 48px; font-size: var(--fs-xs); padding: 8px 8px; }
}

/* ---- Свечение на наведении и «меньше движения» ----
   Свечение остаётся (это подсказка о кликабельности, а не украшение), но
   появляется мгновенно. Переопределена ТОЛЬКО длительность: transition: none
   стёр бы весь список свойств, а вместе с ним переходы цвета и рамки, которые
   у этих кнопок были и до ember-glow. */
@media (prefers-reduced-motion: reduce) {
  .btn-cta,
  .tab,
  .seg-btn,
  .recalc-btn { transition-duration: 0.01ms; }
}

/* ---- Метка «что тронет кнопка»: таблицу или только локальный снапшот ----
   Причина появления: 08.08.2026 «Скачать месяц» нажали вместо выгрузки. Снапшот
   пересобрался, лист остался прежним, и понять это по виду кнопок было нельзя —
   различие жило только в атрибуте title, то есть требовало наведения мыши и было
   недоступно с тач-экрана. По доктрине проекта молчание о свежести данных
   приравнивается к вранью о ней; здесь то же правило применено к действию.

   Реализовано ПСЕВДОЭЛЕМЕНТОМ, а не вложенной разметкой: syncExtraRuns() и
   patchJobProgress() переписывают textContent кнопок («⏳ Собираем… 40%»,
   «⏳ Доступно через N мин»), и любой вложенный span был бы затёрт при первом же
   тике опроса. ::after этого не касается — метка держится и во время сборки. */
.recalc-btn[data-writes]::after {
  margin-left: 7px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  vertical-align: middle;
  white-space: nowrap;
}
/* Ember — потому что это действие с последствиями снаружи: перезапись общей таблицы. */
.recalc-btn[data-writes="sheet"]::after {
  content: "таблица";
  color: var(--ember);
  border: 1px solid var(--ember-smoke);
  background: rgba(var(--ember-rgb), 0.12);
}
/* Приглушённо — действие безопасное, ничего наружу не уходит. */
.recalc-btn[data-writes="local"]::after {
  content: "локально";
  color: var(--ash-dim);
  border: 1px solid var(--hairline);
  background: rgba(var(--tint-rgb), 0.04);
}
/* Погашенная кнопка не должна кричать меткой. */
.recalc-btn:disabled[data-writes]::after,
.recalc-btn.busy[data-writes]::after { opacity: 0.55; }

/* ---- Перетаскивание колонок таблиц (col_order.js) ----
   Переработано 10.08.2026 по замечанию «визуально захват столбца не понятен».
   Что было не так: (1) на нажатие не происходило НИЧЕГО — отклик появлялся только
   после порога 5px; (2) у захваченного заголовка стояли одновременно opacity:0.45 и
   ember-фон, а opacity умножается на фон — эффективная альфа выходила 0.045, то есть
   подсветки не было вовсе, колонка просто выцветала и читалась как «сломалась»;
   (3) реагировал только заголовок высотой ~30px, сама колонка — нет.

   Главный аффорданс перетаскивания — индикатор МЕСТА ВСТАВКИ, а не подсветка источника.
   Поэтому колонка-источник приглушена ровно настолько, чтобы читаться как «поднята», а
   ember отдан вертикальной линии — туда она встанет. */

/* Контейнер таблицы — система координат для оверлея. */
.table-wrap { position: relative; }

th.col-move {
  cursor: grab;
  /* Иначе при переносе выделяется текст соседних заголовков и жест выглядит сломанным. */
  user-select: none;
  -webkit-user-select: none;
  /* Отдаём горизонтальный жест странице: на тач-экране браузер иначе прокрутит таблицу. */
  touch-action: none;
  /* box-shadow в переходе базового селектора, а не в модификаторе: иначе подсветка
     зажигается плавно, а гаснет рывком. */
  transition: box-shadow 0.18s ease, background 0.18s ease;
}
/* Ненавязчивая подсказка «это можно тянуть» — только на наведении, постоянной иконки
   не заводим: в шапке из 16 колонок она превратилась бы в шум. */
th.col-move:hover { box-shadow: inset 0 -2px 0 0 var(--ember-smoke); }

/* Нажали, но ещё не потянули. Раньше этой фазы не существовало визуально вовсе. */
th.col-move.col-pressed {
  box-shadow: inset 0 0 0 1px var(--ember-smoke), 0 0 10px 1px rgba(var(--ember-rgb), 0.28);
  background: rgba(var(--ember-rgb), 0.14);
}
/* Тянем. Заголовок «поднят»: ember-кольцо и свечение. opacity НЕ используем — именно она
   съедала подсветку в прежней версии. */
th.col-move.col-dragging {
  box-shadow: inset 0 0 0 1px var(--ember), 0 0 16px 3px rgba(var(--ember-rgb), 0.40);
  background: rgba(var(--ember-rgb), 0.20);
  color: var(--bone);
}
th.col-move.col-drop { background: rgba(var(--ember-rgb), 0.10); }
/* Курсор «взято» на всём документе: жест продолжается и вне шапки. */
body.col-drag-active, body.col-drag-active * { cursor: grabbing !important; }

/* Оверлей: подсветка всей колонки и линия вставки. Взят вместо разметки ячеек, потому
   что таблицы содержат строки-разделители отделов с colspan — они рвут любую подсветку
   «по номеру ячейки», а оверлей проходит поверх них непрерывно. Ещё он не зависит от
   числа строк и едет вместе с горизонтальной прокруткой контейнера. */
.col-overlay {
  position: absolute; inset: 0;
  /* БЕЗ ЭТОГО ЖЕСТ ЛОМАЕТСЯ: оверлей перехватил бы указатель. */
  pointer-events: none;
  z-index: 2;
}
.col-overlay .col-band {
  position: absolute; top: 0; display: none;
  background: rgba(var(--ember-rgb), 0.10);
  border-radius: var(--radius-xs);
}
.col-overlay .col-line {
  position: absolute; top: 0; display: none;
  width: 3px; margin-left: -1px;
  background: var(--ember);
  border-radius: var(--radius-xs);
  box-shadow: 0 0 12px 2px rgba(var(--ember-rgb), 0.55);
}

@media (prefers-reduced-motion: reduce) {
  /* Переопределяем ТОЛЬКО длительность: transition:none стёр бы и переходы цвета. */
  th.col-move { transition-duration: 0.01ms; }
}

/* Только для экранного диктора: видимого места не занимает, но читается вслух.
   Нужен для объявлений о переносе колонок — визуальная линия вставки слепому
   пользователю недоступна, и без озвучивания жест для него молчит. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Фокус на заголовке — точка входа в клавиатурный перенос. Показываем только
   :focus-visible, чтобы клик мышью не оставлял рамку. */
th.col-move:focus { outline: none; }
th.col-move:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--ember), 0 0 12px 2px rgba(var(--ember-rgb), 0.35);
}

/* ---- Сквозная аналитика (/analytics): картотека → «открытая папка» с бордами ----
   Редизайн 26.08 (приёмка — глава маркетинга): вместо одной стеклянной плиты — плёнка-
   папка (тонировка БЕЗ blur: стеклят только борды внутри, иначе стекло-на-стекле) и
   отдельные .board.glass с воздухом, как на дашборде. Ярлык-таб остаётся стеклянным
   и «вырастает» из папки прежним швом. Wow-пакет в рамках спокойного языка: нумерация
   бордов, каскад первого появления, табло-числа героя, ember-нить борда денег,
   угловой свет всех бордов, дельты-капсулы, спарки с заливкой. */
.an-wrap { padding: 20px 40px 60px; }
.an-topbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 0; }
/* padding-top компенсирует overflow-x:auto на узких экранах: без него clip срезает
   верхнюю ember-кромку и свечение активного таба. */
.ftabs { display: flex; gap: 6px; overflow-x: auto; padding: 10px 2px 0; scrollbar-width: none; }
.ftabs::-webkit-scrollbar { display: none; }
.ftab {
  flex: none; display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px 9px; margin-bottom: -1px; position: relative; z-index: 2;
  border: 1px solid var(--hairline); border-bottom: none;
  border-radius: var(--radius-block) var(--radius-block) 0 0;
  background: var(--graphite); color: var(--ash);
  font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.01em;
  cursor: pointer; transform: translateY(2px);
  transition: color 0.18s ease, background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.ftab:hover { color: var(--bone); border-color: rgba(var(--ember-rgb), 0.55); box-shadow: var(--glow-hover-sm); }
.ftab:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--mark-ring), 0 0 0 3px var(--ember); }
.ftab.active {
  background: linear-gradient(180deg, rgba(29, 26, 23, 0.62), rgba(29, 26, 23, 0.60));
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  color: var(--bone); transform: none; cursor: default;
  box-shadow: inset 0 2px 0 var(--ember), 0 -8px 18px -10px rgba(var(--ember-rgb), 0.45);
}
.ftab-badge { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ember); border: 1px solid rgba(var(--ember-rgb), 0.4); border-radius: 999px; padding: 1px 7px; }
/* Папка: тонированная плёнка без blur — очерчивает поле вкладки, борды дышат внутри. */
.ftab-panel {
  border: 1px solid var(--hairline); border-top: none;
  border-radius: 0 0 var(--radius-card) var(--radius-card);
  background: rgba(var(--tint-rgb), 0.03); padding: 16px; position: relative; z-index: 1;
}

/* Борды внутри папки: нумерация «01 ·», угловой свет, каскад появления. */
.an-boards { counter-reset: an-board; }
.an-boards .board { position: relative; overflow: hidden; min-width: 0; }
.an-boards .board::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: radial-gradient(120% 60% at 18% 0%, rgba(255, 255, 255, 0.05), transparent 55%);
}
.an-boards .board-title::before {
  counter-increment: an-board;
  content: counter(an-board, decimal-leading-zero) " · ";
  color: var(--ember); font-variant-numeric: tabular-nums;
}
.an-boards .board-title .src-chip, .an-boards .board-title .stale-warn, .kpi-label .src-chip {
  font-size: 10px; letter-spacing: normal; text-transform: none; font-weight: 600;
  opacity: 0.85; white-space: nowrap;
}
/* Борд денег: ember-нить продолжает накал активного таба + тёплый очаг в углу. */
.an-board-money::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; z-index: 1;
  background:
    linear-gradient(90deg, var(--ember), transparent 55%) top / 100% 2px no-repeat,
    radial-gradient(90% 70% at 0% 0%, rgba(var(--ember-rgb), 0.06), transparent 60%);
}
.an-money-head { flex-wrap: wrap; row-gap: 8px; }
@keyframes an-board-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.an-anim .board { animation: an-board-in 0.32s ease-out backwards; animation-delay: calc(var(--i, 0) * 50ms); }

/* Сетки: строгая симметрия — колонки «Пульса» и героя совпадают по вертикальным осям. */
.an-quality-band, .an-hero { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.an-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.an-hero-card { padding: 16px 18px; }
.an-hero-card .kpi-val { font-size: clamp(26px, 2.2vw, 34px); }
/* Мастхед выручки: дисплейный кегль + «металлический» градиент по глифам.
   Свечение на буквы не вешать — просвечивает сквозь прозрачные глифы. */
.an-hero-card:first-child .kpi-val {
  font-size: clamp(32px, 2.8vw, 44px); letter-spacing: -0.03em;
  background: linear-gradient(180deg, var(--bone) 55%, var(--ash) 140%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .an-hero-card:first-child .kpi-val { background: none; -webkit-text-fill-color: currentColor; }
}
.an-hero-card .kpi-spark, .an-hero-card .spark { height: 40px; }
/* Дельты-капсулы: подложка из статусного цвета текста (color-mix), обе темы бесплатно. */
.an-boards .kpi-delta { padding: 2px 8px; border-radius: 999px; background: color-mix(in srgb, currentColor 12%, transparent); }
.an-loading .kpi-val, .an-loading td { opacity: 0.55; }

/* Тумблеры категорий: переключатели — glow на hover легален. Мультивыбор; точные суммы
   комбинаций дедуплицирует сервер (см. cross_analytics_combo). */
.an-cats { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.an-cats-label { color: var(--ash-dim); font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: 0.05em; font-weight: 700; margin-right: 3px; }
.an-cat {
  border: 1px solid var(--hairline-strong); border-radius: 999px; background: transparent;
  color: var(--ash); font-size: var(--fs-xs); font-weight: 700; padding: 5px 12px;
  cursor: pointer; transition: color 0.15s ease, border-color 0.15s ease, box-shadow 0.22s ease,
  background 0.15s ease;
}
.an-cat:hover { color: var(--bone); border-color: var(--ember); box-shadow: var(--glow-hover-sm); }
.an-cat:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--mark-ring), 0 0 0 3px var(--ember); }
.an-cat.on, .an-cat.on:hover {
  background: var(--ember); border-color: var(--ember); color: var(--bone);
  box-shadow: 0 0 12px -2px var(--ember-glow);
}
.an-filter-note { color: var(--ash-dim); font-size: var(--fs-sm); margin: 0 0 12px; }
.kpi.an-filtered { box-shadow: inset 2px 0 0 var(--ember); }
.an-share-track { height: 4px; border-radius: 2px; background: rgba(var(--tint-rgb), 0.08); min-width: 60px; }
.an-share-bar { height: 4px; border-radius: 2px; background: rgba(var(--series-leads-rgb), 0.75); }
.an-cut { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: bottom; }

/* Светлая тема: ярлык — по светлой рецептуре стекла, папка — светлая плёнка без blur;
   ember-кромка/нить в светлой теме — заливка бренда. */
:root[data-theme="ibrat-light"] .ftab {
  background: rgba(226, 233, 242, 0.55);
  -webkit-backdrop-filter: blur(28px); backdrop-filter: blur(28px);
  border-color: rgba(84, 112, 143, 0.42);
}
:root[data-theme="ibrat-light"] .ftab.active {
  background: var(--graphite);
  -webkit-backdrop-filter: blur(28px); backdrop-filter: blur(28px);
  box-shadow: inset 0 2px 0 var(--brand-fill), 0 -8px 18px -12px rgba(0, 130, 180, 0.35);
}
:root[data-theme="ibrat-light"] .ftab-panel,
:root[data-theme="ibrat-light"] .an-folder-head {
  background: rgba(228, 235, 245, 0.30); border-color: rgba(84, 112, 143, 0.42);
}
:root[data-theme="ibrat-light"] .an-cmp-btn.on {
  background: var(--brand-fill); border-color: var(--brand-fill); color: #fff;
}
:root[data-theme="ibrat-light"] .an-board-money::before {
  background:
    linear-gradient(90deg, var(--brand-fill), transparent 55%) top / 100% 2px no-repeat,
    radial-gradient(90% 70% at 0% 0%, rgba(0, 130, 180, 0.05), transparent 60%);
}
:root[data-theme="ibrat-light"] .kpi.an-filtered { box-shadow: inset 2px 0 0 var(--brand-fill); }
:root[data-theme="ibrat-light"] .an-cat.on, :root[data-theme="ibrat-light"] .an-cat.on:hover {
  background: var(--brand-fill); border-color: var(--brand-fill); color: #fff;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ftab.active { background: rgba(29, 26, 23, 0.97); }
  :root[data-theme="ibrat-light"] .ftab, :root[data-theme="ibrat-light"] .ftab.active { background: #dbe4ee; }
}
@media (prefers-reduced-motion: reduce) {
  .ftab, .an-cat { transition-duration: 0.01ms; }
  .an-anim .board { animation: none; }
}
@media (max-width: 1100px) {
  .an-quality-band, .an-hero { grid-template-columns: repeat(2, 1fr); }
  /* нечётная пятая карточка — на всю ширину: симметрия зеркальностью 2+2+1 */
  .an-quality-band .kpi:last-child, .an-hero .an-hero-card:last-child { grid-column: 1 / -1; }
  /* мастхед выручки в полколонки не влезает (дисплейный кегль режется) —
     на узких он занимает всю строку: иерархия 1+2+2 */
  .an-hero .an-hero-card:first-child { grid-column: 1 / -1; }
  .an-cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 1024px) {
  .an-wrap { padding: 16px 24px 48px; }
}
@media (max-width: 600px) {
  .an-wrap { padding: 12px 14px 40px; }
  .ftab-panel { padding: 8px; }
  .an-topbar { align-items: stretch; }
}

/* Борд 10 «Динамика по месяцам»: колонки-бары, одна метрика — одна ось. */
.an-trend-chart { display: flex; align-items: stretch; gap: 8px; height: 200px; margin-top: 12px; }
.an-tr-col { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; gap: 5px; }
.an-tr-val { font-size: 11px; color: var(--ash); font-variant-numeric: tabular-nums; white-space: nowrap; }
.an-tr-bar { width: 100%; max-width: 64px; border-radius: 6px 6px 2px 2px;
  background: linear-gradient(180deg, var(--ember), rgba(var(--ember-rgb), 0.35));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18); }
.an-tr-partial { opacity: 0.55; }              /* месяц не закончен — колонка «не в полную силу» */
.an-tr-pending { background: rgba(var(--tint-rgb), 0.12); box-shadow: none; }
.an-tr-lab { font-size: var(--fs-xs); color: var(--ash-dim); white-space: nowrap; }
:root[data-theme="ibrat-light"] .an-tr-bar {
  background: linear-gradient(180deg, var(--brand-fill), rgba(0, 130, 180, 0.35));
}
@media (max-width: 600px) {
  .an-trend-chart { height: 150px; gap: 4px; }
  .an-tr-val { display: none; }               /* на 390px значения — в title колонок */
}

/* Всплывающие пояснения метрик (.an-term → #an-tip): термин с пунктиром, попап-оверлей
   ПЛОТНЕЕ стекла-подложки (ложится поверх данных). Синглтон в body, position:fixed —
   игнорирует overflow таблиц и стек-контексты бордов. Native title бейджей не трогаем:
   у элемента либо title, либо .an-term, никогда оба. */
.an-term { text-decoration: underline dotted rgba(var(--tint-rgb), 0.45); text-underline-offset: 3px; cursor: help; }
.an-term:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--mark-ring), 0 0 0 3px var(--ember); border-radius: 3px; }
.an-tip {
  position: fixed; z-index: 70; max-width: 300px; padding: 10px 12px;
  background: rgba(20, 17, 14, 0.92);
  -webkit-backdrop-filter: blur(14px) saturate(140%); backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(var(--tint-rgb), 0.16); border-radius: var(--radius-inner);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  animation: cal-in 0.14s ease-out;
}
.an-tip-t { font-size: var(--fs-sm); font-weight: 700; color: var(--bone); margin-bottom: 4px; }
.an-tip-b { font-size: var(--fs-xs); color: var(--ash); line-height: 1.55; font-variant-numeric: tabular-nums; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .an-tip { background: rgba(20, 17, 14, 0.97); }
}
@media (prefers-reduced-motion: reduce) {
  .an-tip { animation: none; }
}

/* Селектор периодов «Сквозной аналитики»: второй ряд топбара + индикатор сравнения. */
/* «Шапка папки»: плёнка верха картотеки (НЕ стекло — блюрят только борды); все
   контролы времени одной строкой, ярлык-таб вырастает из неё прежним швом. Ритм 8/16. */
.an-folder-head {
  position: relative; display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap;
  border: 1px solid var(--hairline); border-bottom: none;
  border-radius: 0 var(--radius-card) 0 0;
  background: rgba(var(--tint-rgb), 0.03);
  padding: 12px 16px 10px;
}
.an-stepper { display: flex; align-items: center; gap: 8px; }
.an-period-label { min-width: 140px; text-align: center; }
.an-refresh-btn { margin-left: auto; }
.an-cmp-btn { display: inline-flex; align-items: center; gap: 6px; }
.an-cmp-btn.on { background: var(--ember); border-color: var(--ember); color: var(--bone); }
/* Единый профиль контролов шапки: одна высота — ряд не «дрожит» разнокалиберностью. */
.an-folder-head .btn-sm, .an-folder-head .cmp-datefield, .an-folder-head .an-period-label {
  min-height: 36px;
}
.an-folder-head .seg-btn { min-height: 30px; }
.an-rangefields { align-items: center; gap: 7px; }
/* display через :not(.hidden): голый display:flex перебивал .hidden (равная специфичность,
   мой селектор позже) — скрытые поля торчали за краем экрана (пойман стендом 27.08). */
.an-rangefields:not(.hidden) { display: flex; }
.an-range-dash { color: var(--ash-dim); }
.an-folder-head .cal-pop { top: calc(100% + 6px); left: 0; z-index: 70; }
/* Индикатор ручного сравнения — язык /compare: П1 синий, П2 ember, точки-капы. */
.an-cmpline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  flex-basis: 100%; font-size: var(--fs-sm); color: var(--ash); }
.an-cmpline .cmp-period-cap { font-weight: 700; }
.an-cmpline .an-cmp-x { border: 1px solid var(--hairline-strong); background: transparent;
  color: var(--ash); border-radius: 999px; width: 22px; height: 22px; cursor: pointer;
  line-height: 1; font-size: 13px; }
.an-cmpline .an-cmp-x:hover { color: var(--bone); border-color: var(--ember); }
@media (max-width: 600px) {
  .an-folder-head { padding: 10px 12px 8px; }
  .an-folder-head .seg { width: 100%; }
  .an-folder-head .seg .seg-btn { flex: 1; }
  .an-rangefields { width: 100%; }
  .an-rangefields .cmp-field { flex: 1; }
  .an-rangefields .cmp-datefield { width: 100%; }
}
/* Тач-эргономика (HIG ≥44pt): только на грубых указателях — десктоп не разбухает. */
@media (pointer: coarse) {
  .an-cat, .an-folder-head .seg-btn, .an-folder-head .btn-sm,
  .an-folder-head .cmp-datefield { min-height: 44px; }
  .an-cmpline .an-cmp-x { width: 34px; height: 34px; }
  .an-term { display: inline-block; padding: 6px 0; margin: -6px 0; }
}

/* Панель двух периодов сравнения: открытая занимает свою строку periodbar. */
#an-cmpfields:not(.hidden) { flex-basis: 100%; flex-wrap: wrap; }

/* Полировка 27.08: тихие бейджи в заголовках таблиц (сигнал без шума; полные — на
   карточках, где несут решение) + кроссфейд панелей вкладок. */
.an-boards .board-title .src-chip { opacity: 0.55; }
.ftab-panel:not(.hidden) { animation: cal-in 0.15s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .ftab-panel:not(.hidden) { animation: none; }
}

/* ═══ «Трафик → продажи» и «Менеджеры»: титулы, иерархия строк, окупаемость ═══════════
   Обе вкладки жили голым HTML — ни один их класс не имел правил, поэтому таблицы падали
   на браузерный дефолт, а титулы читались сплошным абзацем. Здесь они получают словарь
   соседних вкладок: поверхность .kpi, ember только меткой, глубина ореолом в тёмной теме
   и тенью в светлой, числа табличные.
   Секция стоит в конце файла НАМЕРЕННО: её светлотемные переопределения лежат тут же,
   рядом с базовыми правилами. Унеси я их в общий блок темы выше — они оказались бы
   раньше по каскаду и проиграли бы при равной специфичности. */

/* ── Титулы площадок: «медали» ──────────────────────────────────────────────────────
   Пять карточек = пять площадок. Карточка либо занята (есть покоритель), либо открыта
   («Стоит поднажать!»). Состояние читаем через :has() по вложенной метке, а не через
   класс-модификатор: разметка уже несёт признак — .an-title-pct против .an-title-hint, —
   и второй его источник пришлось бы синхронизировать вручную. Браузер без :has() покажет
   обе разновидности нейтральной карточкой: деградация тихая, ничего не ломается. */
/* Плита под медалями. Классы board glass ставятся в разметке: титулы — единственный
   блок вкладки, который иначе лежал бы прямо на плёнке .ftab-panel (3% тинта, без
   размытия), а сквозь неё в полную силу светит фотоподложка. Пиксельный замер на
   стенде: лента титула давала 2.8:1 в тёмной и 2.77:1 в светлой — текст стоял не на
   поверхности, а на фотографии. На соседних вкладках такого нет, потому что там ВСЁ
   живёт внутри бордов; здесь просто восстановлен тот же порядок. */
.an-titles {
  display: grid;
  /* auto-fit, а не жёсткие пять колонок как у .an-hero: список площадок приходит из CRM
     и завтра станет шестым. 190px — ширина, на которой «Никита Арефьев» ложится в две
     строки, а не в три. */
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;                 /* шаг .an-cards / .an-hero — вертикальные оси совпадают */
  margin-bottom: 16px;
}
.an-title-card {
  position: relative; overflow: hidden; min-width: 0;
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px 16px 13px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-inner);           /* «карточка внутри папки», не борд */
  /* --graphite-2, а не разреженная плёнка .kpi. Плёнка рассчитана на карточку ВНУТРИ
     непрозрачного контекста; здесь под ней стекло, а под стеклом фотоподложка в полную
     силу, и 11px лента титула садилась на 3.4–4.1:1 в обеих темах (замер пикселями).
     --graphite-2 — штатная поверхность «второго уровня» под мелкий текст, у неё уже
     есть выверенная пара рецептур: тёмная плита в одной теме, светлая матовая в другой.
     Побочный выигрыш: медаль стала физически ОТДЕЛЬНОЙ плашкой, а не подкрашенным
     участком борда, и «медальность» держится не свечением, а уровнем поверхности. */
  background: var(--graphite-2);
}
/* Лента титула. Кегль и трекинг взяты у .an-cats-label: это подпись над героем,
   а не заголовок. --ash-dim здесь 5.07:1 в тёмной и 4.65:1 в светлой. */
.an-title-plat {
  font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--ash-dim); overflow-wrap: anywhere;
}
/* Занятый титул — лента ember: тот же приём, что у нумерации бордов
   (.an-boards .board-title::before). Замер: 5.5:1 в тёмной, 4.75:1 в светлой. */
.an-title-card:has(.an-title-pct) .an-title-plat { color: var(--ember); }
/* Имя — герой карточки, поэтому block: процент уходит на свою строку и не выталкивает
   имя в лишний перенос. Кегль дисплейный, но с потолком — на 24px длинные имена рвутся
   в узкой колонке на три строки, и «медаль» превращается в столбик. */
.an-title-who b {
  display: block; overflow-wrap: anywhere;
  font-size: clamp(17px, 1.35vw, 21px); font-weight: 800; line-height: 1.15;
  letter-spacing: -0.01em; color: var(--bone);
}
/* Процент — акцент, а не второй герой: 17px против 21px у имени. Кегль выбран ещё и по
   контрасту: ember-текст в светлой теме даёт 4.75:1, то есть проходит норму 4.5 как
   ОБЫЧНЫЙ текст, и правило не зависит от послабления для крупного. */
.an-title-pct {
  display: inline-block; margin-top: 3px;
  font-size: var(--fs-xl); font-weight: 800; line-height: 1;
  color: var(--ember); font-variant-numeric: tabular-nums;
}
/* Открытый титул: приглушённо и БЕЗ тревожного цвета — это не сбой, а вакансия.
   Пунктир вместо заливки: место видно, но оно не требует реакции. */
/* Плиту НЕ снимаем: она несёт контраст, а не смысл. Первая редакция гасила фон, и
   11px лента открытого титула тут же уехала на 3.55:1 в светлой теме — «приглушённо»
   вышло за счёт читаемости. Приглушает пунктир и цвет текста, поверхность общая. */
.an-title-card:has(.an-title-hint) { border-style: dashed; }
.an-title-hint { color: var(--ash-dim); font-size: var(--fs-md); font-weight: 600; }
/* Свечение занятой карточки слабее hover-токена: --glow-hover рассчитан на ОТКЛИК
   контрола, а здесь состояние покоя — постоянный ореол той же силы превратил бы ряд
   титулов в гирлянду. Отрицательный spread держит свет у самой кромки. */
.an-title-card:has(.an-title-pct) {
  border-color: rgba(var(--ember-rgb), 0.32);
  box-shadow: 0 0 18px -8px var(--ember-glow);
}
/* Угловой свет — приём .an-boards .board::after, но тёплый: карточка читается
   подсвеченной изнутри, а не обведённой рамкой. */
.an-title-card:has(.an-title-pct)::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: radial-gradient(120% 85% at 12% -15%, rgba(var(--ember-rgb), 0.13), transparent 62%);
}
/* Дорожка конверсии. Один слой вместо пары .an-share-track + .an-share-bar: заливка
   задана жёсткой остановкой градиента на --pct, который renderManagers кладёт инлайном.
   margin-top:auto сажает дорожки всех карточек на одну линию — иначе имена разной длины
   развозят их по высоте. Шкала честная, от нуля до 100%: 37% и обязаны выглядеть чуть
   больше трети, подгонять её под максимум в ряду значило бы приукрасить данные. */
.an-title-card:has(.an-title-pct)::after {
  content: ""; margin-top: auto; height: 4px; border-radius: 2px;   /* габарит .an-share-bar */
  background: linear-gradient(90deg,
    var(--ember) 0 calc(var(--pct, 0) * 1%),
    rgba(var(--tint-rgb), 0.10) calc(var(--pct, 0) * 1%) 100%);
  animation: an-title-fill 0.55s ease-out both;
}
/* Заполнение слева направо, один раз. clip-path, а не width: ширина заставляла бы
   пересчитывать градиент каждый кадр, clip-path режет уже готовый слой. */
@keyframes an-title-fill {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* ── Таблицы обеих вкладок ──────────────────────────────────────────────────────────
   .tbl-wrap — второе имя того же жёлоба, что .table-wrap на соседних вкладках: два
   автора, одна роль. Дублируем правило, а не переименовываем класс — имя приходит из
   разметки, а её эта задача трогать не должна. */
.tbl-wrap { overflow-x: auto; position: relative; -webkit-overflow-scrolling: touch; }
/* Шапки числовых колонок стояли слева над правыми числами — колонка читалась сдвинутой.
   Правим в границах .an-traffic: у соседних таблиц свои привычки, и общий th.num
   переписал бы их все разом. */
.an-traffic th.num { text-align: right; }
/* Разряды выравниваем на всей таблице, а не только на td.num: числа встречаются и
   внутри <b> в строке отдела, а наследование font-variant-numeric сюда не дотягивалось. */
.an-traffic { font-variant-numeric: tabular-nums; }

/* Отдел. Готовая «прорезь» .dept-row сделана заливкой --obsidian и здесь не годится:
   в светлой теме --obsidian это ХОЛСТ, полоса стала бы светлее строк и band
   перевернулся бы. Тот же смысл даём воздухом и линией — это и есть иерархия отступом
   и весом, а не цветными заливками. */
.an-traffic .an-dept td {
  border-top: 1px solid var(--hairline-strong);
  padding-top: 16px; padding-bottom: 9px; background: none;
}
/* Первому отделу линия сверху не нужна: под ней шапка таблицы, и получилось бы
   двойное правило в один пиксель зазора. */
.an-traffic tbody > tr.an-dept:first-child td { border-top: none; padding-top: 9px; }
.an-traffic .an-dept td:first-child {
  color: var(--ember); font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.05em;
}
/* Итоги отдела — самые крупные числа таблицы, но цвет им даём основной, не ember:
   ember в этой системе метка принадлежности, а не синоним «важного». */
.an-traffic .an-dept td.num { color: var(--bone); }
/* Менеджер — итоговая строка человека. Имя основным цветом (глобальное td:first-child
   уже даёт --bone), числа плотнее площадочных на одну ступень веса. */
.an-traffic .an-mgr td { color: var(--ash); font-weight: 600; }
.an-traffic .an-mgr td:first-child { color: var(--bone); font-weight: 700; }
/* Площадка/источник — вложенный уровень. Отступ и засечка вместо заливки: вложенность
   обязана читаться и тогда, когда строку накрыл hover. */
/* --ink-soft, а не --ash-dim: последний на стекле борда давал 4.48:1 при норме 4.5 —
   промах крошечный, но это ровно та граница, ради которой в проекте и заведена шкала
   приглушённого текста. --ink-soft светлее на ступень и остаётся отчётливо тише --ash,
   так что вложенный уровень по-прежнему читается тише родительской строки. */
.an-traffic .an-src td { color: var(--ink-soft); font-size: var(--fs-sm); }
.an-traffic .an-src td:first-child {
  position: relative; padding-left: 30px; color: var(--ash); font-weight: 400;
}
.an-traffic .an-src td:first-child::before {
  content: ""; position: absolute; left: 13px; top: 50%; width: 9px; height: 1px;
  background: var(--hairline-strong);
}
/* На «Менеджерах» строка отдела — только подпись (colspan), подсвечивать её как данные
   незачем. На «Трафике» тот же класс несёт итоги, и там hover уместен — поэтому условие
   по colspan, а не по вкладке. */
.an-traffic .an-dept:has(td[colspan]):hover { background: none; }
/* «Нет данных» приходит без класса .no-data — доводим до того же вида. */
.an-traffic tbody > tr:only-child > td[colspan] { color: var(--ash-dim); font-style: italic; }

/* ── Подпись-пояснение ──────────────────────────────────────────────────────────────
   Текста много — методика когорты и определения двух разных конверсий. Это не строка,
   как .an-filter-note, а абзац, который читают. Даём поверхность .kpi, ember-нить слева
   (язык .kpi.an-filtered: «здесь оговорка к данным») и предел длины строки: на широком
   мониторе 200 знаков в строку глаз не удерживает. */
.an-note {
  margin: 0 0 14px; padding: 10px 14px; max-width: 92ch;
  border: 1px solid var(--hairline); border-radius: var(--radius-block);
  /* --graphite-2, а не 2.5% тинта: это штатная «полоса другого уровня» под мелкий
     текст (шапки таблиц, жёлоба), и обе её рецептуры уже выверены по контрасту.
     Разреженная плёнка пропускала подложку, и в светлой теме 14% площади подписи
     уходило под норму — замерено пикселями, а не выведено формулой. */
  background: var(--graphite-2);
  box-shadow: inset 2px 0 0 var(--ember);
  color: var(--ash); font-size: var(--fs-sm); line-height: 1.5;
}
.an-note b { color: var(--bone); font-weight: 700; }
/* Борд-обёртка таблицы: жёлоб скроллится внутри, поэтому боковые отступы отдаём ему —
   иначе левое поле уезжает вместе с содержимым и таблица «прилипает» к краю плиты. */
.board.glass > .tbl-wrap { margin: 0 -20px -18px; padding: 0 20px 18px; }

/* ── Окупаемость кабинетов ──────────────────────────────────────────────────────────
   Секция живёт ВНЕ сетки .an-boards — она приложение к вкладке, а не её борд. Поэтому
   поверхность ей дают классы board glass прямо в разметке (копия рецептуры стекла в CSS
   разъехалась бы с оригиналом при первой же правке темы), а здесь остаётся отбивка тем
   же шагом, что и зазор между бордами. */
.an-roi { margin-top: 16px; }
.an-roi .board-title { margin-bottom: 10px; }
/* Метка «расход есть, лидов в CRM нет». Рецептура .panel-note: цвет несёт КОНТУР, текст
   остаётся нейтральным. Красить сам текст в --status-warn нельзя — в светлой теме это
   #a8620a, то есть 4.04:1 на 11px, ниже нормы; --ash держит 11.5:1 и 5.1:1. Точка
   считается элементом интерфейса (порог 3:1) и проходит с запасом. */
.an-warn {
  display: inline-block; margin-left: 6px; padding: 1px 8px;
  border: 1px solid color-mix(in srgb, var(--status-warn) 50%, transparent);
  border-radius: var(--radius-pill);
  color: var(--ash); font-size: var(--fs-2xs); font-weight: 700;
  white-space: nowrap; vertical-align: 1px;
  /* Метка стоит поверх стекла борда, и 11px текст на нём упирался в 4.49:1 при норме
     4.5 — то есть ровно на границе. Подложка чипа снимает вопрос без правки цвета. */
  background: var(--graphite-2);
}
.an-warn::before {
  content: ""; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--status-warn); margin-right: 6px; vertical-align: 1px;
}

/* ── Светлая тема ───────────────────────────────────────────────────────────────────
   Глубина здесь — тень, а не ореол (решение 10.08.2026): --ember-glow в этой теме
   бледно-голубой кант, на светлом холсте его попросту нет. Берём --glow-hover, у
   которого в светлой теме как раз рецептура мягкой тени. */
:root[data-theme="ibrat-light"] .an-title-card:has(.an-title-pct) {
  border-color: rgba(var(--brand-fill-rgb), 0.55);
  box-shadow: var(--glow-hover);
}
/* Угловой свет и дорожка — фирменной ЗАЛИВКОЙ: --ember в светлой теме тёмная читаемая
   ступень для БУКВ, плашкой она выглядит грязно. Тот же развод ролей, что у .an-tr-bar. */
:root[data-theme="ibrat-light"] .an-title-card:has(.an-title-pct)::before {
  background: radial-gradient(120% 85% at 12% -15%, rgba(var(--brand-fill-rgb), 0.10), transparent 62%);
}
:root[data-theme="ibrat-light"] .an-title-card:has(.an-title-pct)::after {
  background: linear-gradient(90deg,
    var(--brand-fill) 0 calc(var(--pct, 0) * 1%),
    rgba(var(--tint-rgb), 0.10) calc(var(--pct, 0) * 1%) 100%);
}
:root[data-theme="ibrat-light"] .an-note { box-shadow: inset 2px 0 0 var(--brand-fill); }

@media (prefers-reduced-motion: reduce) {
  /* Селектор ОБЯЗАН повторять :has() из базового правила. Короткое .an-title-card::after
     весит (0,1,1) против (0,2,1) у объявления с анимацией и молча проигрывало бы —
     запрет движения не сработал бы вовсе, а на стенде это не видно без эмуляции. */
  .an-title-card:has(.an-title-pct)::after { animation: none; }
}
@media (max-width: 600px) {
  .an-title-card { padding: 12px 13px 11px; }
  .an-note { padding: 9px 11px; }
  /* Засечка вложенности на телефоне съедает и без того узкую первую колонку. */
  .an-traffic .an-src td:first-child { padding-left: 24px; }
  .an-traffic .an-src td:first-child::before { left: 10px; width: 7px; }
}

/* Дробь вместо процента на малой базе: «1 / 2» не должно читаться как достижение,
   поэтому оно приглушено и не спорит по весу с честными процентами соседних строк. */
.an-traffic .an-thin {
  color: var(--ink-soft);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Вкладки городов: «Владимир» и «Москва» ───────────────────────────────────────
   Переиспользуем существующие .kpi и .an-share-track; своего здесь только сетка на
   12 плиток, блок «Н/Д с причиной» и таблица источников. Цвета — из тех же токенов,
   что и вся страница: ember для акцента, ash-dim для пояснений. */
.an-city-head { margin: 0 0 14px; }
.an-city-head h3 { margin: 0 0 4px; font-size: var(--fs-lg); font-weight: 600; }
.an-city-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px;
}
/* Плитка без источника: приглушена и НЕСЁТ ПРИЧИНУ прямо в карточке, а не только
   в подсказке. «Н/Д» значит «не считали», и человек должен видеть, почему. */
.kpi.an-nd { opacity: 0.72; border-style: dashed; }
.kpi.an-nd .kpi-val { color: var(--ash-dim); }
.an-nd-why { margin-top: 6px; font-size: var(--fs-xs); line-height: 1.35; color: var(--ash-dim); }
.an-city-block { margin-top: 18px; }
.an-city-block h4 { margin: 0 0 8px; font-size: var(--fs-md); font-weight: 600; }
.an-city-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.an-city-table th {
  text-align: left; font-weight: 500; color: var(--ash-dim);
  padding: 4px 8px 6px; border-bottom: 1px solid rgba(var(--tint-rgb), 0.10);
}
.an-city-table td { padding: 6px 8px; border-bottom: 1px solid rgba(var(--tint-rgb), 0.06); }
.an-city-table td.num, .an-city-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.an-city-table tr:last-child td { border-bottom: none; }
/* Город рядом с доменом в борде «Точки»: домен — адрес, город — что он значит. */
.an-dom-city { color: var(--ash-dim); font-size: var(--fs-xs); margin-left: 6px; }

/* ---- «Качество сервиса» (реш. заказчика 31.10.2026, утверждённый макет) ----
   Пропущенные звонки и чаты без ответа — одним списком в карточках отделов (service_quality.js),
   ниже — «Обработано в регламенте» по менеджерам ОП. Цвета срочности — статусные токены
   (--status-good/-warn/-bad), поэтому три темы получают свои ступени без отдельных правил.
   ТВ-режим этих правил не видит: там прежняя вёрстка, а сотрудники скрыты. */
.live-missed #statusStamp { display: none; }
.live-missed #liveStamp { display: inline; }

/* Строка списка: колонка иконки + существующая сетка .live-row */
.sq-row { grid-template-columns: 18px minmax(0, 1fr) auto; column-gap: 10px; align-items: center; }
.sq-row .live-sub, .sq-row .sq-reg { grid-column: 2 / -1; }
.sq-ico { color: var(--ash-dim); display: flex; align-items: center; justify-content: center; }
.sq-ico svg { display: block; }
.sq-row.sev-danger .sq-ico { color: var(--status-bad); }
.sq-row.sev-warning .sq-ico { color: var(--status-warn); }
.sq-row .live-crm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Подпись срочности справа: зелёный / янтарь / красный */
.live-age.sq-ok   { color: var(--status-good); font-weight: 600; }
.live-age.sq-warn { color: var(--status-warn); font-weight: 700; }
.live-age.sq-over { color: var(--status-bad);  font-weight: 700; }
.sq-row.sev-danger  { border-left: 3px solid var(--status-bad);  background: rgba(255, 90, 90, 0.08); }
.sq-row.sev-warning { border-left: 3px solid var(--status-warn); background: rgba(255, 183, 77, 0.06); }
.sq-row:not(.sev-danger):not(.sev-warning) { border-left: 3px solid transparent; }
:root[data-theme="ibrat-light"] .sq-row.sev-danger  { background: linear-gradient(rgba(179, 38, 30, 0.07), rgba(179, 38, 30, 0.07)), rgba(255, 255, 255, 0.62); }
:root[data-theme="ibrat-light"] .sq-row.sev-warning { background: linear-gradient(rgba(168, 98, 10, 0.07), rgba(168, 98, 10, 0.07)), rgba(255, 255, 255, 0.62); }
:root[data-theme="new-year"] .sq-row.sev-danger  { background: rgba(255, 77, 109, 0.12); }
:root[data-theme="new-year"] .sq-row.sev-warning { background: rgba(255, 209, 102, 0.08); }

/* Полоса регламента 10 мин — дашбордная версия .tv-reg (тонкая, подпись справа) */
.sq-reg { display: block; height: 4px; margin-top: 3px; border-radius: var(--radius-pill);
          background: rgba(var(--tint-rgb), 0.10); overflow: hidden; }
.sq-reg i { display: block; height: 100%; border-radius: var(--radius-pill); transform-origin: 0 50%; }
.sq-reg.ok i   { background: var(--status-good); }
.sq-reg.warn i { background: var(--status-warn); }
.sq-reg.over i { background: var(--status-bad); }

/* Разбивка «📞N · 💬M» рядом с бейджем-итогом */
.sq-split { margin-left: auto; margin-right: 10px; display: inline-flex; gap: 10px; flex: none;
            font-size: var(--fs-xs); color: var(--ash-dim); font-variant-numeric: tabular-nums; }
.sq-split span { display: inline-flex; align-items: center; gap: 4px; }
.sq-split svg { display: block; }
.live-block-head .tv-btn + .sq-split { margin-left: 0; }

/* «Обработано в регламенте» — дневные карточки сотрудников */
.sq-emp-head { display: flex; align-items: baseline; gap: 12px; margin: 26px 0 14px; flex-wrap: wrap; position: relative; }
.sq-emp-title { margin: 0; color: var(--bone); font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.01em; }
.sq-emp-sub { color: var(--ash-dim); font-size: var(--fs-sm); }
.sq-info { width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--hairline-strong);
           color: var(--ash); font-size: 11px; font-weight: 700; display: inline-flex; align-items: center;
           justify-content: center; cursor: help; align-self: center; position: relative; }
.sq-tip { display: none; position: absolute; left: -8px; bottom: 30px; z-index: 5; width: 380px; padding: 12px 14px;
          background: var(--obsidian); border: 1px solid var(--hairline-strong); border-radius: var(--radius-inner);
          color: var(--bone); font-size: var(--fs-sm); font-weight: 400; line-height: 1.45; cursor: default;
          text-align: left; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35); }
.sq-info:hover .sq-tip, .sq-info:focus .sq-tip { display: block; }
.sq-tip::after { content: ''; position: absolute; left: 12px; bottom: -6px; width: 10px; height: 10px; background: var(--obsidian);
                 border-right: 1px solid var(--hairline-strong); border-bottom: 1px solid var(--hairline-strong); transform: rotate(45deg); }
.sq-tip b { color: var(--bone); }
.sq-tip .sq-tip-note { display: block; margin-top: 6px; color: var(--ash-dim); font-size: var(--fs-xs); }

.sq-emp-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; align-items: start; }
.sq-emp-note { grid-column: 1 / -1; color: var(--ink-muted); font-size: var(--fs-sm); padding: 4px 0; }
.sq-emp { overflow: visible; padding: 14px 16px; min-width: 0; }
.sq-emp.has-out { cursor: pointer; }
.sq-emp.has-out:hover { border-color: var(--hairline-strong); }
.sq-emp:focus-visible { outline: 2px solid var(--status-warn); outline-offset: 2px; }
/* :root + три класса — сильнее рамки .live-block у светлой и новогодней тем (там (0,3,0)):
   в макете у светлой темы янтарная рамка раскрытой карточки пропадала именно из-за этого. */
:root .live-block.sq-emp.open { border-color: var(--status-warn); }
:root[data-theme="ibrat-light"] .live-block.sq-emp.open {
  box-shadow: inset 0 0 0 1px var(--status-warn), 0 1px 2px rgba(16, 42, 67, 0.07), 0 8px 18px -6px rgba(16, 42, 67, 0.18);
}
:root[data-theme="new-year"] .live-block.sq-emp.open { box-shadow: inset 0 0 0 1px var(--status-warn), 0 0 60px rgba(79, 79, 128, 0.15); }
.sq-emp-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sq-emp-name { color: var(--bone); font-weight: 700; font-size: var(--fs-lg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sq-emp-caret { color: var(--ash-dim); font-size: var(--fs-xs); white-space: nowrap; }
.sq-emp-pct { font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -0.02em; line-height: 1;
              margin-top: 10px; font-variant-numeric: tabular-nums; color: var(--bone); }
.sq-emp-pct small { font-size: var(--fs-sm); font-weight: 600; color: var(--ash-dim); letter-spacing: 0; margin-left: 8px; }
.sq-emp-pct.sq-good { color: var(--status-good); }
.sq-emp-pct.sq-mid  { color: var(--status-warn); }
.sq-emp-pct.sq-bad  { color: var(--status-bad); }
.sq-emp-meter { height: 4px; border-radius: var(--radius-pill); background: rgba(var(--tint-rgb), 0.10); margin: 10px 0 9px; overflow: hidden; }
.sq-emp-meter i { display: block; height: 100%; border-radius: var(--radius-pill); }
.sq-emp-meter i.sq-good { background: var(--status-good); }
.sq-emp-meter i.sq-mid  { background: var(--status-warn); }
.sq-emp-meter i.sq-bad  { background: var(--status-bad); }
.sq-emp-line { color: var(--bone); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.sq-emp-line .sep { color: var(--ash-dim); margin: 0 6px; }
.sq-emp-speed { color: var(--ash-dim); font-size: var(--fs-xs); margin-top: 5px; font-variant-numeric: tabular-nums; }
.sq-emp.off { cursor: default; }
.sq-emp.off > * { opacity: 0.5; }
.sq-emp.off .sq-emp-pct { color: var(--ash); }

.sq-out { margin: 12px -16px -14px; border-top: 1px solid var(--hairline); }
.sq-out-title { padding: 9px 16px 4px; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--ash-dim); }
.sq-out-item { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 2px 9px; align-items: center;
               padding: 8px 16px; border-top: 1px solid var(--hairline); font-size: var(--fs-sm); color: var(--bone); }
.sq-out-item:first-of-type { border-top: none; }
.sq-out-item .sq-ico { color: var(--status-warn); }
.sq-out-item a { color: var(--bone); text-decoration: none; border-bottom: 1px solid var(--hairline-strong); }
.sq-out-item a:hover { color: var(--ember); border-color: var(--ember); }
.sq-out-item .d { color: var(--status-warn); font-weight: 600; }
.sq-out-item .s { grid-column: 2; color: var(--ink-soft); font-size: var(--fs-xs); }
.sq-out-more { padding: 8px 16px 10px; border-top: 1px dashed var(--hairline); font-size: var(--fs-xs); color: var(--ash); opacity: 0.7; }
:root[data-theme="ibrat-light"] .sq-out { background: rgba(255, 255, 255, 0.62); border-radius: 0 0 var(--radius-block) var(--radius-block); }
/* Переводы диалогов и «Спас лид» (реш. заказчика 03.11.2026): цепочка «Ева → Никита» — время
   переводов в title; «спас N» — отдельный счётчик, в процент не входит (зелёный, без свечения). */
.sq-chain { color: var(--bone); font-weight: 600; white-space: nowrap; cursor: help; }
.sq-row .live-sub .sq-chain { font-weight: 600; }
.sq-emp-line .sq-save { color: var(--status-good); font-weight: 700; }
.sq-out-title.sq-save-title { border-top: 1px solid var(--hairline); color: var(--status-good); }
.sq-out-title.sq-save-title:first-child { border-top: none; }
.sq-out-item.sq-save-item .sq-ico,
.sq-out-item.sq-save-item .d { color: var(--status-good); }

/* ТВ — прежний экран: сотрудников там нет */
html.tv-missed .live-missed .sq-emp-wrap { display: none !important; }

@media (max-width: 1500px) {
  .sq-emp-row { gap: 14px; }
  .sq-tip { width: 340px; }
}
@media (max-width: 1100px) {
  .sq-emp-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 768px) {
  .sq-emp-row { grid-template-columns: minmax(0, 1fr) !important; }
  .sq-tip { width: calc(100vw - 48px); max-width: 380px; }
  .sq-emp-head { margin-top: 20px; }
}
/* Светлая тема: карточка сотрудника несёт мелкий текст (строки звонков/скорости) — матовая
   подкладка той же плотности 0.62, что у .live-row/.status-person (правило темы). */
:root[data-theme="ibrat-light"] .live-block.sq-emp { background: rgba(255, 255, 255, 0.62); }

/* ---- «Риски дня» (реш. РОПа 03.11.2026, утверждённый макет — вариант А, scratchpad rop_mockup) ----
   В «Качестве сервиса», под «Обработано в регламенте»; сворачивается в одну строку (счётчики
   остаются на виду). Компоненты — существующие (.live-section/.live-block/.sq-row/.seg/.btn),
   новые правила — только с префиксом rk-. Срочность — статусными токенами (--status-*), поэтому
   три темы получают свои ступени без отдельных правил; адресно — только рамки чипов и плашки
   на фото светлой темы. ТВ-режим блок не показывает. Отрисовка — static/day_risks.js. */
.rk-section[hidden] { display: none; }
/* Внутри «Качества сервиса», под «Обработано в регламенте» (реш. заказчика 03.11.2026):
   заголовок — ступенью ниже секции, как у «Обработано в регламенте». */
.live-missed .rk-section { margin-top: 30px; }
.rk-section .live-title { font-size: var(--fs-xl); }
.rk-section .live-head { margin-bottom: 14px; }
.rk-section .live-title { position: relative; }
:root .live-section .pulse.rk-pulse { background: var(--status-bad); animation: rk-pulse 1.8s infinite; }
:root .live-section .pulse.rk-pulse.rk-calm-dot { background: var(--status-good); animation: none; box-shadow: none; }
:root .live-section .pulse.rk-pulse.rk-idle { background: var(--ash-dim); animation: none; box-shadow: none; }
@keyframes rk-pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 90, 90, 0.55); } 70% { box-shadow: 0 0 0 12px rgba(255, 90, 90, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 90, 90, 0); } }
@media (prefers-reduced-motion: reduce) { :root .live-section .pulse.rk-pulse { animation: none; } }
.rk-section .live-meta { flex-wrap: wrap; }
.rk-section .live-meta .seg { flex: none; }
.rk-section .live-stamp.is-stale { color: var(--status-warn); }
.rk-collapse { flex: none; }
.rk-collapse .car { margin-left: 6px; font-size: var(--fs-xs); opacity: 0.8; }
/* Подсказка у заголовка открывается ВНИЗ (как была, когда блок стоял первым на странице) */
.rk-info { font-size: 11px; letter-spacing: 0; }
.rk-info .sq-tip { bottom: auto; top: 30px; z-index: 30; }
.rk-info .sq-tip::after { bottom: auto; top: -6px; border: none; border-left: 1px solid var(--hairline-strong);
                          border-top: 1px solid var(--hairline-strong); }

/* Полоса счётчиков */
.rk-strip { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
.rk-chip { display: inline-flex; align-items: center; gap: 8px; padding: 6px 14px 6px 12px; font-family: var(--font);
           background: var(--graphite); border: 1px solid var(--hairline-strong); border-radius: var(--radius-pill);
           color: var(--ash); font-size: var(--fs-sm); white-space: nowrap; text-decoration: none; cursor: pointer;
           transition: box-shadow 0.22s ease, border-color 0.12s; }
.rk-chip:hover { box-shadow: var(--glow-hover-sm); }
.rk-chip b { color: var(--bone); font-size: var(--fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }
.rk-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ash-dim); flex: none; }
.rk-chip.bad  { border-color: rgba(255, 90, 90, 0.55); }
.rk-chip.bad .dot  { background: var(--status-bad); }
.rk-chip.bad b  { color: var(--status-bad); }
.rk-chip.warn { border-color: rgba(255, 183, 77, 0.5); }
.rk-chip.warn .dot { background: var(--status-warn); }
.rk-chip.warn b { color: var(--status-warn); }
.rk-chip.ok .dot { background: var(--status-good); }
.rk-chip.ok b { color: var(--status-good); }
.rk-chip.sum { cursor: default; }
.rk-chip.sum:hover { box-shadow: none; }
.rk-chip.sum b { font-size: var(--fs-md); }
:root[data-theme="ibrat-light"] .rk-chip { background: rgba(255, 255, 255, 0.86); color: #3c4a5c; }
:root[data-theme="ibrat-light"] .rk-section .live-stamp { background: rgba(255, 255, 255, 0.8); padding: 3px 10px; border-radius: var(--radius-pill); opacity: 1; }
:root[data-theme="ibrat-light"] .rk-section .seg { background: rgba(255, 255, 255, 0.86); }
:root[data-theme="ibrat-light"] .rk-section .rk-collapse { background: rgba(255, 255, 255, 0.86); }
:root[data-theme="ibrat-light"] .rk-chip.bad  { border-color: rgba(179, 38, 30, 0.45); }
:root[data-theme="ibrat-light"] .rk-chip.warn { border-color: rgba(168, 98, 10, 0.45); }
:root[data-theme="ibrat-light"] .rk-note { background: rgba(255, 255, 255, 0.8); padding: 3px 10px; border-radius: var(--radius-pill); }
:root[data-theme="new-year"] .rk-chip.bad  { border-color: rgba(255, 77, 109, 0.55); }
:root[data-theme="new-year"] .rk-chip.warn { border-color: rgba(255, 209, 102, 0.5); }

/* Свёрнуто: счётчики в строке заголовка, колонки скрыты */
.rk-section.rk-collapsed .live-head { margin-bottom: 0; }
.rk-section.rk-collapsed .live-head .rk-strip { margin: 0 auto 0 4px; }
.rk-section.rk-collapsed .rk-chip { padding: 4px 11px 4px 10px; font-size: var(--fs-xs); }
.rk-section.rk-collapsed .rk-chip b { font-size: var(--fs-md); }
.rk-section.rk-collapsed .rk-grid, .rk-section.rk-collapsed .rk-note { display: none; }
.rk-l-short { display: none; }
.rk-section.rk-collapsed .rk-l-full, .rk-section.rk-collapsed .live-total { display: none; }
.rk-section.rk-collapsed .rk-l-short { display: inline; }

/* Сетка групп */
.rk-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.22fr) minmax(0, 0.72fr); gap: 18px; align-items: start; }
.rk-grid .live-block-head { gap: 10px; }
.rk-grid .live-block-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rk-head-meta { margin-left: auto; color: var(--ash-dim); font-size: var(--fs-xs); white-space: nowrap; font-variant-numeric: tabular-nums; }
.live-count.rk-bad  { color: var(--status-bad);  border-color: var(--status-bad);  font-weight: 700; }
.live-count.rk-warn { color: var(--status-warn); border-color: var(--status-warn); font-weight: 700; }
.live-count.rk-ok   { color: var(--status-good); border-color: rgba(61, 220, 132, 0.5); }
.rk-head-meta + .live-count { margin-left: 0; }
.live-block-title + .live-count { margin-left: auto; }
.rk-row .live-crm a::after { content: "↗"; display: inline-block; margin-left: 5px; font-size: 0.8em; color: var(--ash-dim); }
.rk-row .live-crm a { border-bottom-color: var(--hairline-strong); }
.rk-stage { display: inline-block; padding: 0 7px; border: 1px solid var(--hairline-strong); border-radius: var(--radius-pill);
            font-size: var(--fs-xs); color: var(--ash); line-height: 18px; }
.rk-sum { color: var(--bone); font-weight: 600; font-variant-numeric: tabular-nums; }
.rk-nobody { color: var(--status-warn); font-weight: 600; }
.rk-section .live-more { opacity: 0.85; }
.rk-more { background: none; border: none; padding: 0; color: inherit; font: inherit; cursor: pointer;
           border-bottom: 1px solid var(--hairline-strong); }
.rk-more:hover { color: var(--bone); }
.rk-section .live-empty { display: flex; align-items: center; gap: 9px; color: var(--ash); }
.rk-section .live-empty svg { color: var(--status-good); flex: none; }
.rk-section .live-block.rk-flash { animation: rk-flash 1.2s ease; }
@keyframes rk-flash { 0%, 100% { box-shadow: none; } 30% { box-shadow: var(--glow-hover-sm); } }
.rk-wait { color: var(--ash); font-size: var(--fs-sm); padding: 6px 0; grid-column: 1 / -1; }
.rk-note { color: var(--ash-dim); font-size: var(--fs-xs); margin-top: 10px; display: inline-block; }
.rk-note:empty { display: none; }

/* Группа «Просрочено по регламенту» — счётчики вместо списка */
.rk-reg { padding: 14px 16px; }
.rk-reg-nums { display: flex; gap: 22px; align-items: flex-end; }
.rk-reg-num { display: flex; flex-direction: column; gap: 6px; }
.rk-reg-num .n { font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -0.02em; line-height: 1; font-variant-numeric: tabular-nums; color: var(--status-bad); }
.rk-reg-num .n.zero { color: var(--ash-dim); }
.rk-reg-num .l { display: inline-flex; align-items: center; gap: 5px; color: var(--ash); font-size: var(--fs-xs); }
.rk-reg-num .l svg { display: block; }
.rk-reg-worst { margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--hairline); color: var(--ink-soft); font-size: var(--fs-sm); line-height: 1.45; }
.rk-reg-worst b { color: var(--status-bad); }
.rk-reg-worst.rk-reg-ok { color: var(--status-good); }
.rk-reg-worst a { color: var(--bone); text-decoration: none; border-bottom: 1px solid var(--hairline-strong); }
.rk-reg .btn { margin-top: 14px; width: 100%; justify-content: center; }

/* Всё спокойно */
.rk-calm { grid-column: 1 / -1; display: flex; align-items: center; gap: 14px; padding: 16px; border: 1px solid rgba(61, 220, 132, 0.35);
           border-radius: var(--radius-inner); background: rgba(61, 220, 132, 0.05); }
:root[data-theme="ibrat-light"] .rk-calm { border-color: rgba(15, 112, 80, 0.35); background: rgba(255, 255, 255, 0.86); }
:root[data-theme="new-year"] .rk-calm { background: rgba(19, 19, 31, 0.86); }
.rk-calm-ico { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
               color: var(--status-good); border: 1px solid currentColor; flex: none; }
.rk-calm-t { color: var(--bone); font-weight: 700; font-size: var(--fs-lg); }
.rk-calm-s { color: var(--ash); font-size: var(--fs-sm); margin-top: 3px; }

html.tv-missed .rk-section { display: none !important; }

@media (max-width: 1500px) {
  .rk-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr) minmax(0, 0.7fr); gap: 14px; }
  /* свёрнутая строка на 1366 — без суммы и отметки времени, иначе переносится на вторую */
  .rk-section.rk-collapsed .rk-chip.sum, .rk-section.rk-collapsed #rkStamp { display: none; }
}
@media (max-width: 1100px) {
  .rk-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rk-grid #rkReg { grid-column: 1 / -1; }
}
@media (max-width: 768px) {
  .rk-grid { grid-template-columns: minmax(0, 1fr); }
  .rk-chip { white-space: normal; }
  .rk-info .sq-tip { left: auto; right: -8px; width: calc(100vw - 48px); max-width: 380px; }
  .rk-section.rk-collapsed .live-head .rk-strip { margin: 0; width: 100%; order: 3; }
}
