/* ============================================================
   Marketplace-Assist — Base CSS
   Общая библиотека стилей. Подключать ПОСЛЕ theme.css.
   <link rel="stylesheet" href="/assets/theme.css">
   <link rel="stylesheet" href="/assets/base.css">
   ============================================================ */

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* --- Root (html) --- */
/* scrollbar-gutter: stable — резервирует 15px под скроллбар глобально.
 * Устраняет CLS-дёрганье раскладки (~15px) при появлении/исчезновении
 * вертикального скроллбара: правый отступ всегда одинаков на всех страницах.
 * Применяется ко ВСЕМ страницам включая /analytics/ (эталон). ADR: T-gutter. */
html { scrollbar-gutter: stable; }

/* ============================================================
   Единый скроллбар портала — WebKit + Firefox
   Применяется глобально: страницы, модалки, поповеры, AG Grid.
   Токены: --scrollbar-thumb / --scrollbar-thumb-hover / --scrollbar-track
   определены в theme.css (оба блока: dark + light).
   ТОЛЬКО стиль — механика overflow/scroll не меняется.
   ============================================================ */

/* --- Глобальный WebKit: убрать кнопки-стрелки --- */
::-webkit-scrollbar-button { display: none; }

/* --- Угол пересечения вертикального и горизонтального скроллбара --- */
::-webkit-scrollbar-corner { background: transparent; }

/* --- Размер: 10px × 10px (умеренно, не громоздко) --- */
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

/* --- Дорожка (трек): прозрачная, без лишнего фона --- */
::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
}

/* --- Ползунок: скруглённый, тонтированный токен темы ---
   border-radius: 8px — канон рестайла 2026-06-08 (было 999px; визуально
   идентично при высоте 10px, но фиксируем точное значение канона). */
::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 8px;
  /* Прозрачная рамка создаёт визуальный «gap» между бегунком и краем трека
   * без изменения реального размера области прокрутки */
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:active {
  background: var(--scrollbar-thumb-hover);
  border: 2px solid transparent;
  background-clip: padding-box;
}

/* --- Firefox: тонкий скроллбар на ВСЕХ скролл-контейнерах (канон 2026-06-08) ---
   Применяем к * (раньше только html), чтобы модалки/поповеры/панели тоже
   получали тонкий тонированный скроллбар в Firefox, а не системный серый. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) transparent;
}

/* ============================================================
   AG Grid — скроллбар внутри вьюпортов грида
   Глобальное правило уже применяется к этим элементам,
   но явный scoped-блок гарантирует перебивку дефолтного
   стиля AG Grid в случае если его CSS загружается позже.
   ============================================================ */
.ag-body-viewport::-webkit-scrollbar,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar,
.ag-center-cols-viewport::-webkit-scrollbar,
.ag-virtual-list-viewport::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.ag-body-viewport::-webkit-scrollbar-track,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-track,
.ag-center-cols-viewport::-webkit-scrollbar-track,
.ag-virtual-list-viewport::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
}
.ag-body-viewport::-webkit-scrollbar-thumb,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb,
.ag-center-cols-viewport::-webkit-scrollbar-thumb,
.ag-virtual-list-viewport::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 8px;          /* канон рестайла 2026-06-08 */
  border: 2px solid transparent;
  background-clip: padding-box;
}
.ag-body-viewport::-webkit-scrollbar-thumb:hover,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb:hover,
.ag-center-cols-viewport::-webkit-scrollbar-thumb:hover,
.ag-virtual-list-viewport::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
  border: 2px solid transparent;
  background-clip: padding-box;
}
.ag-body-viewport::-webkit-scrollbar-button,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button,
.ag-center-cols-viewport::-webkit-scrollbar-button,
.ag-virtual-list-viewport::-webkit-scrollbar-button { display: none; }
.ag-body-viewport::-webkit-scrollbar-corner,
.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-corner,
.ag-center-cols-viewport::-webkit-scrollbar-corner,
.ag-virtual-list-viewport::-webkit-scrollbar-corner { background: transparent; }

/* --- Body --- */
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ============================================================
   Резерв под левый сайдбар — СТАТИЧНО, до выполнения JS (анти-FOUC).
   Раньше отступ под сайдбар приходил ТОЛЬКО из рантайм-стиля
   app-sidebar.js (инъекция `body{padding-left:…!important}`): первый
   кадр body красился во всю ширину → контент «прыгал» вправо, когда
   инъекция приземлялась. Теперь резерв задан здесь, в base.css (грузится
   в <head> до paint), поэтому первый же кадр уже со сдвигом — дёрганья нет.

   Значения ОБЯЗАНЫ совпадать с константами app-sidebar.js:
     SIDEBAR_EXPANDED  = 240px  (развёрнут — дефолт)
     SIDEBAR_COLLAPSED = 60px   (body.sidebar-collapsed)
     MOBILE_BREAKPOINT = 1024px (≤1023px → сайдбар off-canvas, резерв 0)
   При изменении констант в app-sidebar.js — синхронизировать здесь.

   Класс `body.sidebar-collapsed` app-sidebar.js выставляет СИНХРОННО в
   самом верху IIFE (до построения DOM), читая localStorage — поэтому
   свёрнутый пользователь сразу получает 60px-резерв без вспышки 240→60.

   transition 0.2s ease-out — тот же тайминг, что у ширины сайдбара
   (#app-sidebar transition: width 0.2s ease-out): свёртка/развёртка
   контента и панели идут синхронно.

   Страницы БЕЗ сайдбара (/login/, /setup/, /employee/) сайдбар не
   рисуют (ранний return в app-sidebar.js), но и резерв им не мешает —
   их вёрстка центрируется/полноэкранна; если потребуется — отдельный
   override на body этих страниц. ============================================================ */
body {
  padding-left: 240px;
  transition: padding-left 0.2s ease-out;
}
body.sidebar-collapsed { padding-left: 60px; }

/* Opt-out для страниц БЕЗ сайдбара, которые всё же подключают base.css
   (полноэкранные/центрированные: юр-доки privacy/oferta/consent, онбординг
   setup/sync-progress, sandbox-спайки). Без этого они получали бы пустой
   240px-отступ слева от статического резерва выше.
   Два пути выставления класса `no-sidebar`:
     • Страницы С app-sidebar.js, где скрипт делает ранний return и НЕ рисует
       сайдбар (/employee, /login, /setup*) — app-sidebar.js ставит класс
       СИНХРОННО вверху IIFE (до paint, без вспышки).
     • Страницы БЕЗ app-sidebar.js (JS не выполнится) — статический
       `class="no-sidebar"` прямо на <body> (единственный надёжный способ).
   !important — чтобы перебить базовый `body{padding-left:240px}` выше при
   любом порядке/специфичности. Мобильный @media ниже и так даёт 0. */
body.no-sidebar { padding-left: 0 !important; }

/* Мобильный режим: сайдбар уезжает за левый край (off-canvas),
   контент занимает всю ширину — резерв снимаем в обоих состояниях. */
@media (max-width: 1023px) {
  body,
  body.sidebar-collapsed { padding-left: 0; }
}

/* --- Typography --- */
/* №33 (2026-06-08): единый размер h1 = 20px. `.h1` (была 22px) сведена к
   `.page-header h1` (20px, ниже) — один размер заголовков разделов на всех
   страницах. Исключение — overview-hero (~40px, маркетинговый герой в page-CSS,
   намеренно НЕ трогаем). См. ARCHITECTURE §дизайн-система. */
.h1 { font-size: 20px; font-weight: 700; line-height: 1.3; }
.h2 { font-size: 16px; font-weight: 700; line-height: 1.4; }
.h3 { font-size: 14px; font-weight: 600; line-height: 1.4; }
.body-text { font-size: 13px; line-height: 1.5; }
.small-text { font-size: 12px; line-height: 1.4; }
.label-text {
  font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--text2);
}

/* --- Layout --- */
.container {
  max-width: 1400px;
  margin: 0 auto;
  padding: var(--space-6);
}

/* --- Page Header --- */
.page-header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: var(--space-4) var(--space-6);
  position: sticky;
  top: 0;
  z-index: 10;
}
.page-header-top {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}
/* №33: канон размера h1 = 20px (см. `.h1` выше). */
.page-header h1 { font-size: 20px; font-weight: 700; }
.page-header .section-desc {
  font-size: 13px;
  color: var(--text2);
  margin-top: var(--space-1);
  max-width: 600px;
  line-height: 1.5;
}

/* Индикатор обновления данных */
.sync-status {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 12px;
  color: var(--text2);
}
.sync-status-time { white-space: nowrap; }
.sync-status-next {
  white-space: nowrap;
  opacity: 0.7;
}
.sync-status-next::before { content: '· '; }
.sync-btn {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text2);
  cursor: pointer;
  transition: all 0.15s;
  flex-shrink: 0;
}
.sync-btn:hover { border-color: var(--accent); color: var(--accent); }
.sync-btn.syncing { animation: spin 1s linear infinite; }
.sync-btn.syncing:hover { cursor: wait; }
.sync-status.error .sync-status-time { color: var(--error); }
.sync-status.stale .sync-status-time { color: var(--warning); }

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* --- Grid --- */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
.grid-auto {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
}

@media (max-width: 768px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* --- Card --- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  transition: border-color 0.2s;
}
.card:hover { border-color: color-mix(in srgb, var(--border) 50%, var(--accent) 50%); }
.card-clickable { cursor: pointer; text-decoration: none; color: var(--text); display: block; }
.card-clickable:hover { transform: translateY(-1px); box-shadow: var(--shadow); }

/* --- KPI Card --- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}
.kpi-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  transition: border-color 0.2s;
}
.kpi-card:hover { border-color: var(--accent); }
.kpi-label {
  font-size: 12px;
  color: var(--text2);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
  margin-bottom: var(--space-2);
}
.kpi-value {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.2;
}
.kpi-hint {
  font-size: 12px;
  color: var(--text2);
  margin-top: var(--space-1);
}
.kpi-trend {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  font-weight: 600;
  margin-top: var(--space-1);
}
.kpi-trend.up { color: var(--green); }
.kpi-trend.down { color: var(--red); }
.kpi-trend.neutral { color: var(--text2); }

/* ============================================================
   .kc-card — КАНОН KPI-карточки (рестайл 2026-06-08)
   Источник истины: src/design-system .dsv-kpi-card (одобренный вариант).
   Компакт (2 строки), нажимная, фикс-ширина 200px (карточка и её скелетон
   ОДНОГО размера независимо от длины значения), hover-рамка + расходящаяся
   снизу с двух сторон акцент-линия (НЕ «3px левый border» — AI-tell).
   НОВЫЙ класс — НЕ конфликтует со старым виджетом .kpi-card (KPICard).
   Wave 2: страницы переходят на .kc-card. Только токены theme.css.
   ============================================================ */
.kc-card {
  position: relative;
  width: 200px;                 /* фикс-ширина → карточка == скелетон */
  min-height: 74px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}
/* Значение во 2-й строке не ломает фикс-ширину */
.kc-card-value {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.kc-card-label {
  font-size: 12px;
  color: var(--text2);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kc-card:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
}
/* Акцент-линия снизу: расходится из центра к краям при hover */
.kc-card::after {
  content: '';
  position: absolute;
  left: 50%; right: 50%; bottom: 0;
  height: 2px;
  background: var(--accent);
  transition: left 0.18s ease, right 0.18s ease;
}
.kc-card:hover::after { left: 0; right: 0; }
.kc-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Скелетон = тот же размер карточки, без hover-эффектов и линии */
.kc-card--loading { cursor: default; }
.kc-card--loading::after { display: none; }
.kc-card--loading:hover {
  border-color: var(--border);
  box-shadow: none;
}
/* Активное состояние (фильтр применён через карточку) */
.kc-card--active {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.kc-card--active::after { left: 0; right: 0; }

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface2);
  color: var(--text);
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
  text-decoration: none;
  line-height: 1.4;
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn:active { transform: scale(0.98); }

.btn-primary {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}
.btn-primary:hover { opacity: 0.9; color: white; }

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text2);
}
.btn-ghost:hover { color: var(--accent); background: var(--accent-light); }

.btn-warning {
  border-color: var(--warning);
  color: var(--warning);
  background: var(--warning-bg);
}
.btn-warning:hover { border-color: var(--warning); opacity: 0.9; }

.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-lg { padding: 10px 20px; font-size: 14px; }

/* Группа кнопок-переключателей */
.btn-group {
  display: flex;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.btn-group .btn-toggle {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  background: transparent;
  color: var(--text2);
  border: none;
  cursor: pointer;
  transition: all 0.15s;
}
.btn-group .btn-toggle.active { background: var(--accent); color: white; }
.btn-group .btn-toggle:hover:not(.active) { color: var(--text); background: var(--accent-light); }

/* --- Inputs --- */
.input, .select {
  padding: 8px 12px;
  font-size: 13px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s, box-shadow 0.15s;
  line-height: 1.4;
}
.input:focus, .select:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-light);
}
.input::placeholder { color: var(--text2); }
.input-sm { padding: 4px 8px; font-size: 12px; }

/* ============================================================
   Инпуты — КАНОН рестайла 2026-06-08
   :focus-visible (WCAG 2.1 AA) + :disabled-стандарт + textarea + явный
   выпадающий select с видимым chevron. decision id='inputs',
   вариант 'inputs-focus'. Только токены theme.css.
   ============================================================ */
/* Клавиатурный фокус-ринг (Tab) — кольцо акцента поверх рамки */
.input:focus-visible,
.select:focus-visible,
textarea.input:focus-visible {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Заблокированные поля — единый вид (раньше opacity задавалась inline) */
.input:disabled,
.select:disabled,
textarea.input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* Textarea — наследует .input, добавляет вертикальный ресайз */
textarea.input {
  resize: vertical;
  min-height: 64px;
  line-height: 1.5;
}
/* --- Явный выпадающий список: нативный <select> + видимый chevron ---
   Стандарт: оборачиваем select в .select-wrap, chevron — псевдоэлемент.
   Кастомные div-dropdown — только при неизбежности (мультивыбор/поиск). */
.select-wrap {
  position: relative;
  display: inline-block;
}
.select-wrap > .select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 100%;
  padding-right: 34px;          /* место под chevron */
}
.select-wrap::after {
  content: '';
  position: absolute;
  right: 12px;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 1.5px solid var(--text2);
  border-bottom: 1.5px solid var(--text2);
  transform: rotate(45deg);
  pointer-events: none;         /* клик проходит на select */
}

/* Inline edit cell (таблицы) */
.input-cell {
  width: 100%;
  padding: 4px 6px;
  text-align: right;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
}
.input-cell:focus { border-color: var(--accent); outline: none; }

/* --- Tables: КАНОН-таблица bespoke-страниц (.data-table) ---
   ЕДИНЫЙ ИСТОЧНИК визуального оформления для не-движковых (bespoke) таблиц
   портала: payroll, my-expenses «Команда», settings, dashboard «Топ категорий»,
   import-preview. Размеры из канон-токенов (эталон AG-Grid /analytics/):
   шапка 32px / строка 34px / шрифт тела --table-font-size. Раньше каждая
   страница дублировала свои padding/font → разнобой (rows 40px, разные шрифты).
   Правка размера = ОДНА строка в theme.css → следуют все.
   Sticky ТОЛЬКО на th (leaf), НИКОГДА на thead (failure-taxonomy Cat 1.2 —
   sticky на thead не работает; раньше было `.data-table thead{sticky}`). */
.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}
.data-table th {
  box-sizing: border-box;
  height: var(--table-header-h);
  font-size: 11px;
  font-weight: 600;
  color: var(--text2);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 4px 16px;
  text-align: left;
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 5;
}
.data-table th.num, .data-table th[align="right"] { text-align: right; }
.data-table td {
  padding: 8px 16px;                  /* строка ≈ --table-row-h (34px) */
  font-size: var(--table-font-size);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}
.data-table td.num, .data-table td[align="right"] { text-align: right; font-variant-numeric: tabular-nums; }
.data-table tbody tr:hover { background: var(--accent-light); }
.data-table tbody tr:last-child td { border-bottom: none; }

/* Компактный вариант канон-таблицы (строка 26px / шрифт 12px) */
.data-table.compact th { height: var(--table-row-h-compact); padding: 3px 12px; }
.data-table.compact td { padding: 3px 12px; font-size: var(--table-font-size-compact); }

/* --- Tabs --- */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--border);
  margin-bottom: var(--space-6);
}
.tab {
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--text2);
  background: none;
  border: none;
  cursor: pointer;
  position: relative;
  transition: color 0.15s;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--accent); }
.tab.active::after {
  content: '';
  position: absolute;
  bottom: -2px; left: 0; right: 0;
  height: 2px;
  background: var(--accent);
  border-radius: 1px 1px 0 0;
}
.tab-content { display: none; }
.tab-content.active { display: block; }

/* --- Period Chips --- */
.period-chips {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.chip {
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text2);
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip.active {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}

/* --- Компактный чип .chip--sm (КАНОН рестайла 2026-06-08) ---
   Слияние дубля .ps-chip (PeriodSelector). Меньше класс — один источник.
   Применять как `.chip.chip--sm` или одиночно `.chip--sm`. */
.chip--sm {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text2);
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.chip--sm:hover,
.chip--sm.active {
  background: var(--accent-light);
  border-color: var(--accent);
  color: var(--accent);
}

/* --- .ps-chip — АЛИАС на канон .chip (backwards-compat) ---
   PeriodSelector исторически использует .ps-chip; алиас гарантирует единый
   вид даже если page-specific .ps-chip убрать (Wave 2). Page-CSS (analytics,
   sandbox) при наличии перебивает этот алиас по каскаду — поведение сохранено.
   НЕ удалять до миграции всех потребителей на .chip / .chip--sm. */
.ps-chip {
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  background: var(--surface2);
  color: var(--text2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}
.ps-chip:hover  { border-color: var(--accent); color: var(--accent); }
.ps-chip.active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* --- Badges --- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  border-radius: var(--radius-pill);
  line-height: 1.4;
}
.badge-accent { background: var(--accent-light); color: var(--accent); }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-error { background: var(--error-bg); color: var(--error); }
.badge-soon {
  background: var(--surface2);
  color: var(--text2);
  font-size: 10px;
}

/* ============================================================
   Статус-бейджи (.sb-status-*) — КАНОН (рестайл 2026-06-08)
   Подписи С Заглавной по-русски (Готово / Бета / Новое / В разработке).
   Перенесены из inline-стилей app-sidebar.js → единый CSS-источник.
   Потребители: сайдбар (бейджи разделов), любые статус-метки.
   Только токены из theme.css.
   ============================================================ */
.sb-status-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  line-height: 1.4;
}
.sb-status-ready  { background: var(--success-bg); color: var(--success); }  /* Готово */
.sb-status-beta   { background: var(--warning-bg); color: var(--warning); }  /* Бета */
.sb-status-new    { background: var(--accent-light); color: var(--accent); } /* Новое */
.sb-status-dev    { background: var(--surface2);   color: var(--text2);   }  /* В разработке */

/* --- Alerts --- */
.alert {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 13px;
  line-height: 1.4;
}
.alert-warn { border-color: var(--warning-border); background: var(--warning-bg); }
.alert-error { border-color: rgba(239,68,68,0.3); background: var(--error-bg); }
.alert-info { border-color: rgba(110,128,247,0.3); background: var(--accent-light); }
.alert-icon { font-size: 16px; flex-shrink: 0; line-height: 1; }
.alert-text { flex: 1; }
.alert-action {
  font-size: 12px;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
  font-weight: 600;
}
.alert-action:hover { text-decoration: underline; }

/* --- Skeleton Loading (КАНОН рестайла 2026-06-08) ---
   Единственный источник @keyframes ma-shimmer на портал. kpi-card.css больше
   НЕ объявляет свою анимацию (kc-shimmer удалён → алиас на ma-shimmer).
   Градиент: surface2 → border → surface2 (mid-стоп заметнее на обеих темах). */
.skeleton {
  background: linear-gradient(90deg, var(--surface2) 25%, var(--border) 50%, var(--surface2) 75%);
  background-size: 200% 100%;
  animation: ma-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
@keyframes ma-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
/* Алиас старого имени анимации — на случай прямых ссылок animation:skeleton-pulse
   в page-CSS (обратная совместимость, не удалять без grace-period). */
@keyframes skeleton-pulse {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-text { height: 14px; width: 80%; margin-bottom: 8px; }
.skeleton-text.short { width: 40%; }
.skeleton--circle { border-radius: 50%; }
.skeleton-card {
  height: 100px;
  border-radius: var(--radius-md);
}
.skeleton-row {
  height: 44px;
  margin-bottom: 2px;
}
.skeleton-chart {
  height: 300px;
  border-radius: var(--radius-md);
}

/* --- Top/Ranking tables --- */
.top-table-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.top-table-title {
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 700;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.top-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 16px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.top-row:last-child { border-bottom: none; }
.top-rank { font-weight: 700; color: var(--text2); min-width: 20px; }
.top-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.top-value { font-weight: 600; white-space: nowrap; }

/* --- Dropzone --- */
.dropzone {
  background: var(--surface);
  border: 2px dashed var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-8) var(--space-6);
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  position: relative;
}
.dropzone:hover { border-color: var(--accent); background: var(--accent-light); }
.dropzone.dragover { border-color: var(--accent); background: var(--accent-light); transform: scale(1.005); }
.dropzone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; z-index: 1; }

/* --- Utility classes --- */
.text-accent { color: var(--accent); }
.text-green { color: var(--green); }
.text-red { color: var(--red); }
.text-yellow { color: var(--yellow); }
.text-muted { color: var(--text2); }
.text-center { text-align: center; }
.text-right { text-align: right; }
.font-bold { font-weight: 700; }
.font-semibold { font-weight: 600; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hidden { display: none !important; }
.spacer { flex: 1; }
.flex-row { display: flex; align-items: center; }
.flex-col { display: flex; flex-direction: column; }
.gap-1 { gap: var(--space-1); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-8 { margin-bottom: var(--space-8); }

/* --- Empty state (legacy .empty-state — алиас, см. .ma-empty канон ниже) --- */
.empty-state {
  text-align: center;
  padding: 40px 20px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
}
.empty-state-icon { font-size: 48px; margin-bottom: var(--space-3); }
.empty-state-text {
  font-size: 14px;
  color: var(--text2);
  line-height: 1.6;
  margin-bottom: var(--space-4);
}

/* ============================================================
   .ma-empty — КАНОН пустого состояния (рестайл 2026-06-08)
   БЕЗ эмодзи-значка, единые пропорции/заливка, кнопки = портальные .btn/.btn-sm.
   ПРИМЕЧАНИЕ: расширенная версия с CTA-кнопками живёт в empty-state.css
   (компонент MA_EmptyState). Этот блок — базовый канон для inline-разметки
   `.ma-empty` без подключения компонента. Эмодзи-значок канон НЕ предусматривает:
   .ma-empty-icon принудительно скрыт здесь (Wave 2: компонент/вызовы перестают
   передавать icon). Кнопки внутри .ma-empty-actions используют .btn/.btn-sm.
   ============================================================ */
.ma-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-5);
  color: var(--text2);
}
.ma-empty-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin: 0;
}
.ma-empty-text {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text2);
  max-width: 420px;
  margin: 0;
}
.ma-empty-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  justify-content: center;
  margin-top: var(--space-2);
}

/* --- Banner (информационная полоска) --- */
.banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  margin-bottom: var(--space-4);
}
.banner-warn {
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  color: var(--warning);
}
.banner-error {
  background: var(--error-bg);
  border: 1px solid rgba(239,68,68,0.3);
  color: var(--error);
}
.banner-info {
  background: var(--accent-light);
  border: 1px solid rgba(110,128,247,0.3);
  color: var(--accent);
}
.banner a { color: inherit; font-weight: 600; }

/* --- Section --- */
.section { margin-bottom: var(--space-8); }
.section-title {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* --- Responsive --- */
@media (max-width: 768px) {
  .container { padding: var(--space-4); }
  .page-header { padding: var(--space-3) var(--space-4); }
  .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-3); }
  .kpi-value { font-size: 22px; }
}

/* ============================================================
   Column Groups — стили для двухуровневых таблиц с группами
   Используется: table-engine.js (window.TableEngine)
   Эталон: src/sandbox/table-lab/index.html
   ============================================================ */

/* --- Общие стили таблицы --- */
.te-table {
  width: max-content;
  /* min-width:100% УБРАН (Александр 2026-05-20): когда sum_declared < container,
   * min-width:100% форсил таблицу до container width, и browser распределял
   * extra space пропорционально по всем колонкам → «двигается в обе стороны»
   * при resize. Bundles (sum~1517<1629) ловил баг, Orders (sum~2596>1629) нет.
   * Source of truth — declared widths (set _lockTableLayout/initResize). */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
}

/* Sticky ТОЛЬКО на th, НИКОГДА на thead.
   Высота шапки = канон-токен --table-header-h (32px, эталон AG-Grid /analytics/);
   box-sizing:border-box → height точная, padding внутри. Шрифт метки шапки (11px)
   намеренно меньше тела таблицы и НЕ канон-токен (заголовки компактнее значений). */
.te-table thead th {
  position: sticky;
  top: 0;
  z-index: 18;
  box-sizing: border-box;
  height: var(--table-header-h);
  background: var(--surface);
  padding: 4px 4px 4px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  text-align: left;
  border-bottom: 2px solid var(--border);
  cursor: default;
  white-space: nowrap;
  user-select: none;
}
.te-table thead th:hover { background: var(--surface2); }

/* Тело таблицы — канон-плотность (эталон AG-Grid /analytics/): шрифт =
   --table-font-size, высота строки ≈ --table-row-h (34px) через вертикальный
   padding 8px (8+8+18 ≈ 34). ЕДИНЫЙ ИСТОЧНИК для ВСЕХ TableEngine-страниц
   (price-alerts / system-health / admin / assembly-sort): раньше нормального
   td-правила в base.css не было → страницы без table-layout.css рендерили
   td браузер-дефолтом. Числовые — правый край (.num ниже). */
.te-table td {
  padding: 8px 10px;
  font-size: var(--table-font-size);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Внутренний контейнер th: название + кнопки --- */
.th-inner { display: flex; align-items: center; gap: 0; width: 100%; position: relative; }
.th-label { flex: 1; overflow: hidden; text-overflow: ellipsis; text-align: center; min-width: 0; }

/* --- Sort / Filter кнопки --- */
.th-sort {
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text2); flex-shrink: 0;
  border-radius: 2px; transition: all .15s;
}
.th-sort:hover { background: var(--accent-light); color: var(--accent); }
.sort-active .th-sort { color: var(--accent); }
.th-sort svg { display: block; }

.th-filter {
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text2); flex-shrink: 0;
  border-radius: 2px; transition: all .15s;
}
.th-filter:hover { opacity: 1 !important; background: var(--accent-light); color: var(--accent); }
.th-filter.active { opacity: 1 !important; color: #fff; background: var(--accent); }
.th-filter svg { display: block; }

/* --- Вертикальный стек: sort ↕ сверху, filter ▽ снизу --- */
/* Абсолютный: не сдвигает label, label центрируется по полной ширине ячейки */
.th-controls-stack {
  display: flex; flex-direction: column; gap: 0;
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  background: var(--surface2); border-radius: 3px; padding: 1px;
  z-index: 1;
}
.th-controls-stack .th-sort {
  width: 16px; height: 13px; margin: 0; padding: 0; border-radius: 2px 2px 0 0;
}
.th-controls-stack .th-filter {
  width: 16px; height: 13px; margin: 0; padding: 0;
  border-radius: 0 0 2px 2px; opacity: 0.4;
  border-top: 1px solid var(--border);
}
.th-controls-stack .th-sort svg { width: 10px; height: 11px; }
.th-controls-stack .th-filter svg { width: 9px; height: 9px; }

/* --- Стрелка expand/collapse группы (▸/◂) --- */
.th-group-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px;
  cursor: pointer; color: var(--accent);
  font-size: 12px; border-radius: 3px;
  flex-shrink: 0; transition: background .15s; margin-left: 4px;
}
.th-group-toggle:hover { background: var(--accent-light); }

/* --- Агрегат-колонка (свёрнутая группа) --- */
.th-aggregate {
  background: var(--surface) !important;
  white-space: normal !important;
  min-width: 85px;
}
.th-aggregate .th-label {
  white-space: normal; line-height: 1.3;
  word-break: break-word; text-align: center;
}

/* --- Раскрытая группа: заголовок Row 1 --- */
.th-group-expanded {
  background: var(--surface) !important;
  text-align: center;
  border-bottom: none !important;
  padding: 4px 8px !important;
}

/* --- Двухуровневый thead: компактные rowspan-колонки --- */
.te-table thead tr.thead-row1 th[rowspan="2"] {
  padding-top: 4px;
  padding-bottom: 4px;
}
[data-theme="dark"] .th-group-expanded { background: var(--surface) !important; }

/* --- Hint-tooltip на группах колонок --- */
.te-hint {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin-left: 4px;
  font-size: 11px; cursor: help; opacity: 0.5;
  position: relative; flex-shrink: 0;
  border-radius: 50%;
}
.te-hint:hover { opacity: 1; background: var(--accent-light); }
.te-hint-popup {
  display: none; position: absolute; bottom: calc(100% + 6px); left: 50%;
  transform: translateX(-50%); z-index: 200;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 12px;
  font-size: 12px; font-weight: 400; color: var(--text2);
  white-space: normal; text-align: left; line-height: 1.5;
  min-width: 200px; max-width: 320px;
  box-shadow: 0 4px 12px rgba(0,0,0,.12);
  pointer-events: none;
}
.te-hint:hover .te-hint-popup { display: block; }

/* --- Дочерние колонки Row 2 --- */
.th-group-child {
  border-top: 2px solid var(--accent) !important;
  font-size: 10px !important;
  padding: 4px 6px !important;
}

/* --- Двухуровневый thead: sticky с учётом высоты Row 1 --- */
.te-table thead tr.thead-row1 th { top: 0; z-index: 18; background: var(--surface); }
.te-table thead tr.thead-row2 th { top: var(--te-row1-h, 30px); z-index: 18; background: var(--surface); }

/* --- Рамки группы: боковые границы на td/th --- */
td.group-first { border-left: 1px solid rgba(110,128,247,0.2); }
td.group-last  { border-right: 1px solid rgba(110,128,247,0.2); }
th.group-first { border-left: 1px solid rgba(110,128,247,0.2) !important; }
th.group-last  { border-right: 1px solid rgba(110,128,247,0.2) !important; }

/* --- Drag-and-drop индикаторы --- */
.col-dragging { opacity: 0.4; }
.col-drop-left  { box-shadow: inset 3px 0 0 var(--accent) !important; }
.col-drop-right { box-shadow: inset -3px 0 0 var(--accent) !important; }

/* --- Column resize handle --- */
.col-resize-handle {
  position: absolute; right: 0; top: 0; bottom: 0;
  width: 8px; cursor: col-resize;
  background: transparent; z-index: 5;
}
/* Hover оставляем 8px (не сжимать!) — UX-принцип affordance: подсветка
 * не должна уменьшать кликабельную область. UI Architect 2026-05-20 P5. */
.col-resize-handle:hover { background: var(--accent); }

/* --- Per-column filter popup --- */
.col-filter-popup {
  position: fixed; min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 12px;
  z-index: 200; box-shadow: 0 8px 24px rgba(0,0,0,0.18);
}
.col-filter-popup label {
  display: block; font-size: 11px; color: var(--text2); margin-bottom: 2px;
}
.col-filter-popup input {
  width: 100%; padding: 6px 8px; font-size: 12px; font-family: inherit;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--text); margin-bottom: 6px;
  box-sizing: border-box; outline: none;
}
.col-filter-popup input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}
.col-filter-popup input[type="number"] { -moz-appearance: textfield; }
.col-filter-popup input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; }
.col-filter-popup .filter-row { display: flex; gap: 6px; }
.col-filter-popup .filter-row input { flex: 1; min-width: 0; }
.col-filter-popup button {
  width: 100%; padding: 5px 8px; font-size: 11px; font-family: inherit;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface2); color: var(--text); cursor: pointer; margin-top: 2px;
}
.col-filter-popup button:hover { border-color: var(--accent); color: var(--accent); }

/* --- Компактный режим для column groups --- */
.compact .th-aggregate { min-width: 70px; }
.compact .th-group-child { font-size: 9px !important; padding: 4px 6px !important; }
.compact .th-group-expanded { padding: 4px 8px !important; }

/* --- Pin/freeze колонок --- */
.te-table td.pinned { position: sticky; left: 0; z-index: 5; background: var(--bg); }
.te-table th.pinned { z-index: 19 !important; background: var(--surface) !important; }
.pinned-shadow { box-shadow: 4px 0 8px rgba(0,0,0,0.1); clip-path: inset(0 -10px 0 0); }
.te-table tr:hover td.pinned { background: var(--accent-light); }

/* --- Row hover (мягкий синий фон) --- */
.te-table tr:hover td { background: rgba(110,128,247,0.03); }

/* --- Zebra-полоски --- */
.zebra .te-table tbody tr:nth-child(even) td { background: var(--surface2); }
.zebra .te-table tbody tr:nth-child(even):hover td { background: rgba(110,128,247,0.06); }
.zebra .te-table tbody tr:nth-child(even) td.pinned { background: var(--surface2); }

/* --- Цвета ячеек: прибыль/убыток/нейтраль --- */
.cell-positive { color: var(--green, #22c55e); font-weight: 700; }
.cell-negative { color: var(--red, #ef4444); font-weight: 700; }
.cell-warning { color: #ca8a04; font-weight: 600; }
.cell-muted { color: var(--text2, #888); }

/* --- Heatmap ячейки (фон по марже) --- */
.heatmap-cell { position: relative; }
.heatmap-bg { position: absolute; inset: 0; z-index: 0; }
.heatmap-cell span { position: relative; z-index: 1; }
.heatmap-cell .cell-positive,
.heatmap-cell .cell-negative,
.heatmap-cell .cell-warning { text-shadow: 0 0 2px var(--bg); }

/* --- Trend arrows --- */
.trend-up { color: var(--green, #22c55e); font-weight: 700; font-size: 16px; }
.trend-down { color: var(--red, #ef4444); font-weight: 700; font-size: 16px; }
.trend-flat { color: var(--text2, #888); font-size: 14px; }
.trend-cell { position: relative; }
.trend-cell .trend-bg { position: absolute; inset: 0; z-index: 0; }
.trend-cell span { position: relative; z-index: 1; }

/* --- Категории-аккордеон --- */
.cat-row td { background: var(--surface2); padding: 0; border-bottom: 1px solid var(--border); cursor: pointer; }
.cat-row-inner { display: flex; align-items: center; gap: 10px; padding: 10px 14px; font-weight: 600; font-size: 13px; }
.cat-arrow { transition: transform .2s; font-size: 12px; color: var(--text2); }
.cat-row.collapsed .cat-arrow { transform: rotate(-90deg); }
.cat-stats { display: flex; gap: 10px; margin-left: auto; font-size: 12px; font-weight: 400; color: var(--text2); }

/* --- Вертикальные разделители между th (укороченные линии) --- */
.te-table thead th { border-right: none; position: relative; }
.te-table thead th::after { content: ''; position: absolute; right: 0; top: 25%; bottom: 25%; width: 1px; background: var(--border); }
.te-table thead th:last-child::after { display: none; }

/* --- Числовые колонки --- */
.te-table thead th.num { text-align: right; }
.te-table td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* --- Compact mode для te-table — канон-плотность (строка ≈ 26px) --- */
.compact .te-table td { padding: 4px 8px; font-size: var(--table-font-size-compact); }
.compact .te-table thead th { box-sizing: border-box; height: var(--table-row-h-compact); padding: 4px 8px; font-size: 10px; }
.compact .cat-row-inner { padding: 6px 12px; }
.compact td[data-col="img"], .compact th[data-col="img"] { display: none; }

/* --- Минимальные ширины --- */
.te-table td, .te-table th { min-width: 75px; }
.te-table th[data-col="img"], .te-table td[data-col="img"] { min-width: 52px; max-width: 52px; }

/* --- Name cell (обрезка длинных названий) --- */
.name-cell { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }

/* --- Wrap names (многострочные) --- */
.wrap-names .name-cell { white-space: normal !important; word-break: break-word; max-width: 220px; min-width: 100px; display: inline-block !important; overflow: visible !important; text-overflow: clip !important; }
.wrap-names td[data-col="name"] { vertical-align: top; }
.compact.wrap-names .name-cell { max-width: 180px; }

/* --- Цветовая маркировка: Экономика vs Аналитика --- */
th.col-pricing { border-left: 2px solid var(--green, #22c55e) !important; }
td.col-pricing { border-left: 2px solid rgba(34,197,94,0.2) !important; }
th.col-analytics { border-left: 2px solid var(--accent, #6e80f7) !important; }
td.col-analytics { border-left: 2px solid rgba(110,128,247,0.2) !important; }

/* --- Scroll arrows --- */
.scroll-arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 15; width: 28px; height: 48px; border: none; border-radius: var(--radius-md); background: rgba(0,0,0,0.25); color: #fff; font-size: 14px; cursor: pointer; opacity: 0; transition: opacity .2s; pointer-events: none; }
.scroll-arrow.visible { opacity: 0.6; pointer-events: auto; }
.scroll-arrow:hover { opacity: 1; }
.scroll-arrow-left { left: 4px; }
.scroll-arrow-right { right: 4px; }

/* --- Scroll minimap --- */
.scroll-minimap { height: 6px; background: var(--surface2); border-top: 1px solid var(--border); position: relative; cursor: pointer; flex-shrink: 0; display: none; transition: height .15s; }
.scroll-minimap:hover { height: 10px; }
.scroll-minimap.visible { display: block; }
.minimap-thumb { position: absolute; top: 0; height: 100%; background: var(--accent); border-radius: 3px; opacity: 0.5; min-width: 20px; cursor: grab; }
.minimap-thumb:hover { opacity: 0.8; }

/* --- Image preview (TableEngine) --- */
#te-img-preview {
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  display: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  box-shadow: 0 2px 5px rgba(50,50,93,.1), 0 1px 3px rgba(0,0,0,.07);
}
#te-img-preview img {
  width: 200px;
  height: 200px;
  object-fit: contain;
  border-radius: 6px;
  display: block;
}
#te-img-preview.visible { display: block; }

/* Заглушка для пустых изображений */
.te-img-placeholder {
  width: 44px; height: 44px;
  background: var(--surface2);
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text2); font-size: 18px;
}

/* ============================================================
   .ma-skeleton — CLS-резерв (№31): скелетон-плейсхолдер под контент,
   который дорендеривается асинхронно (грид / тулбар / summary-bar).
   Цель — занять место ЗАРАНЕЕ, чтобы блоки не «выталкивали» друг друга
   при загрузке (analytics CLS ~0.244 у границы «плохо»).

   Это ПЕРЕИСПОЛЬЗУЕМАЯ часть (Infrastructure Lead). Применение per-page
   (min-height контейнера + расстановка плейсхолдеров на время загрузки) —
   зона Frontend Engineer (wave 2).

   ТОЛЬКО токены: фон/мерцание через color-mix над --surface/--surface2.
   prefers-reduced-motion → мерцание выключается (статичная заливка).
   ============================================================ */
.ma-skeleton {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-sm);
  /* базовая нейтральная заливка (видна и без анимации, и в reduced-motion) */
  background: var(--surface2);
}

/* Бегущий блик — псевдоэлемент, чтобы не трогать фон контейнера.
   Цвета блика — токенами: подмешиваем --surface к прозрачному (светлее фона
   в light, темнее — наследуется автоматически через токен темы). */
.ma-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--surface) 0%, transparent) 0%,
    color-mix(in srgb, var(--surface) 60%, transparent) 50%,
    color-mix(in srgb, var(--surface) 0%, transparent) 100%
  );
  animation: ma-skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes ma-skeleton-shimmer {
  100% { transform: translateX(100%); }
}

/* — Варианты-заготовки под типовые блоки портала — */

/* Блок грида: высокий прямоугольник под таблицу (задаёт min-height резерва).
   Конкретную высоту страница задаёт inline/в своём CSS (зависит от строк). */
.ma-skeleton--grid {
  width: 100%;
  min-height: 240px;
  height: 100%;
}

/* Строка тулбара: горизонтальная полоса под ряд кнопок управления. */
.ma-skeleton--toolbar {
  width: 100%;
  height: 40px;
  margin-bottom: var(--space-3);
}

/* Summary-bar: полоса под строку итогов (обычно над/под таблицей). */
.ma-skeleton--summary {
  width: 100%;
  height: 44px;
}

/* Текстовая строка (универсальный плейсхолдер под подпись/значение). */
.ma-skeleton--line {
  width: 100%;
  height: 14px;
  border-radius: var(--radius-sm);
}

/* Узкая строка (метка/число) — модификатор ширины. */
.ma-skeleton--sm { width: 40%; }

/* Reduced-motion: статичная заливка без бегущего блика (a11y / батарея). */
@media (prefers-reduced-motion: reduce) {
  .ma-skeleton::after {
    animation: none;
    /* лёгкий статичный блик по центру, чтобы блок читался как «загрузка» */
    transform: none;
    background: color-mix(in srgb, var(--surface) 30%, transparent);
  }
}
