@import url('https://fonts.googleapis.com/css2?family=Jost:wght@500;700&family=Noto+Sans:wght@400;600&display=swap');
/* Material Symbols — единый набор иконок вместо текстовых символов ❮ ✕ ▲ ▼.
   Шрифт захостен локально (assets/fonts/), а не через @import с
   fonts.googleapis.com/fonts.gstatic.com: на изолированной от интернета
   удалённой машине (или за прокси, режущим fonts.gstatic.com) внешний
   @import не подгружался, и вместо иконок в интерфейсе показывался сырой
   текст лигатур ("chevron_left" и т.п.) — у иконочного шрифта, в отличие
   от текстовых, нет читаемого фолбэка при неудаче загрузки. */
@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/material-symbols-outlined.woff2') format('woff2');
}

:root {
  /* ── токены, уровень 1: примитивы ───────────────────────────────────────
     Сырые значения без смысла — сами по себе нигде не используются, только
     как источник для семантического слоя ниже. Не весь спектр, а только
     то, что реально нужно палитре продукта (полные рамки 100–900 были бы
     мёртвым весом для проекта такого размера). */
  --neutral-0:   #0b0d13;
  --neutral-50:  #12141c;
  --neutral-100: #181b24;
  --neutral-200: #20242f;
  --neutral-300: #262b3a;
  --neutral-600: #9ca3af;
  --neutral-900: #e5e7eb;

  --teal-500:   #38bdf8; /* акцент тёмной темы */
  --amber-500:  #f59e0b; /* акцент-2 тёмной темы, он же — уровень "warning" */
  --green-500:  #34d399; /* success, тёмная тема */
  --red-500:    #f87171; /* error, тёмная тема */

  /* ── токены, уровень 2: семантика ───────────────────────────────────────
     Названы по назначению, а не по значению — именно этот слой делает
     систему темизируемой: заменить тему = переопределить эти переменные
     (см. блок :root[data-theme="light"] ниже), ни один компонент трогать
     не нужно. */
  --bg: var(--neutral-0);
  --panel: var(--neutral-50);
  --panel-alt: var(--neutral-100);
  --panel-2: var(--neutral-200);
  --border: var(--neutral-300);
  --text: var(--neutral-900);
  --text-dim: var(--neutral-600);
  --accent: var(--teal-500);
  --accent-2: var(--amber-500);

  /* цвета обратной связи — общие для алертов, бейджей состояний и т.п.
     info сознательно = accent, warning = accent-2: заводить для них
     отдельный примитив было бы дублированием того же смысла двумя
     именами. success/error — единственные два действительно новых тона. */
  --color-info: var(--accent);
  --color-info-bg: #16324a;
  --color-success: var(--green-500);
  --color-success-bg: #123524;
  --color-warning: var(--accent-2);
  --color-warning-bg: #3a2a10;
  --color-error: var(--red-500);
  --color-error-bg: #3a1616;

  /* инверсный фон тултипа — контраст гарантирован в обеих темах именно
     тем, что он ВСЕГДА противоположен обычной поверхности темы, а не
     повторяет её (см. чеклист Tooltip: "inverse colour works best") */
  --tooltip-bg: #ffffff;
  --tooltip-fg: var(--neutral-50);

  /* ── токены, уровень 3: масштаб отступов ────────────────────────────────
     База-4 (см. чеклист Spacing/Grid) — делится ровно на большинство
     плотностей пикселей и не требует исключений. */
  --space-1: .25rem;  /* 4px  */
  --space-2: .5rem;   /* 8px  */
  --space-3: .75rem;  /* 12px */
  --space-4: 1rem;    /* 16px */
  --space-5: 1.5rem;  /* 24px */
  --space-6: 2rem;    /* 32px */
  --space-8: 3rem;    /* 48px */

  /* именованные по назначению, а не по числу — и отдельно от компонентных
     (внутренний паддинг) и layout-отступов (расстояние между блоками),
     ровно то разделение, которого чеклист просит явно */
  --space-component-sm: var(--space-2);  /* чип, кнопка, ячейка таблицы */
  --space-component-md: var(--space-3);  /* поле ввода, строка фильтра */
  --space-component-lg: var(--space-4);  /* паддинг карточки/KPI */
  --space-layout-sm: var(--space-3);     /* между связанными контролами */
  --space-layout-md: var(--space-4);     /* между карточками/секциями */
  --space-layout-lg: var(--space-6);     /* между крупными блоками страницы */

  /* именованные брейкпоинты (см. чеклист Spacing/Grid) — CSS не умеет
     var() внутри @media, поэтому это справочные значения для media-правил
     ниже по файлу, а не переменные; названы по поведению вьюпорта, а не
     по устройству, чтобы не устаревать вместе с формами телефонов:
       --bp-narrow: 480px   (телефон, портрет)
       --bp-mid:    768px   (телефон landscape / маленький планшет)
       --bp-wide:   1280px  (планшет / небольшой десктоп) */

  /* ── токены, уровень 3: типографическая шкала ───────────────────────────
     Модульная шкала, коэффициент 1.2, база 13px — самый частый размер
     текста в интерфейсе на момент введения шкалы (см. чеклист Typography:
     "модульная шкала даёт более гармоничную иерархию, чем произвольные
     размеры"). Определена в rem — корректно масштабируется на 200% zoom. */
  --text-xs:  .6875rem;  /* 11px — подписи, эйбрау, минимальный читаемый размер в системе */
  --text-sm:  .8125rem;  /* 13px — основной текст интерфейса: кнопки, таблицы, radio */
  --text-md:  1rem;      /* 16px */
  --text-lg:  1.1875rem; /* 19px */
  --text-xl:  1.375rem;  /* 22px */
  --text-2xl: 1.6875rem; /* 27px */

  /* именованы по роли — усложнять систему компонентными токенами поверх
     этого смысла нет причины: она названа один раз и используется как есть */
  --text-caption: var(--text-xs);     /* kpi-label, section-title, badge */
  --text-body: var(--text-sm);        /* умолчательный текст интерфейса */
  --text-heading-sm: var(--text-lg);  /* заголовок страницы */
  --text-heading-lg: var(--text-2xl); /* KPI-значение */

  --leading-tight: 1.15;  /* display-цифры (KPI) */
  --leading-snug: 1.3;    /* заголовки */
  --leading-normal: 1.5;  /* обычный текст */

  --tracking-normal: 0;
  --tracking-wide: .04em; /* uppercase-подписи */

  /* бренд ИСЭИ / predictor.su: заголовочный и текстовый шрифты */
  --font-heading: 'Jost', 'Segoe UI', Arial, sans-serif;
  --font-body: 'Noto Sans', 'Segoe UI', Arial, sans-serif;

  /* predictor-style.css красит ЛЮБОЙ <button> терракотовым (--predictor-
     color-button-bg-hover) при наведении — это цвет светлой темы бренда,
     он не зависит от data-theme и оставался розово-красным даже в тёмной
     теме. Переопределяем на акцентные цвета текущей темы (сам predictor-
     style.css грузится раньше этого файла, так что просто выигрываем по
     порядку, без !important). */
  --predictor-color-button-bg: var(--accent);
  --predictor-color-button-bg-hover: var(--accent-2);
}

/* Нативные Dash-компоненты (Dropdown, DatePickerRange) красят себя через
   собственные CSS-переменные --Dash-*, которые их JS-бандл прописывает в
   :root АСИНХРОННО при монтировании компонента — то есть уже ПОСЛЕ этого
   файла, и без !important эта прописка побеждала бы по порядку и оставляла
   лукапы (закрытый дропдаун, поле периода, попап календаря) белыми/фиоле-
   товыми независимо от выбранной темы. !important гарантирует, что наши
   значения побеждают всегда. */
:root {
  --Dash-Fill-Inverse-Strong: var(--panel-alt) !important;
  --Dash-Fill-Interactive-Strong: var(--accent) !important;
  --Dash-Text-Primary: var(--text) !important;
  --Dash-Text-Strong: var(--text) !important;
  --Dash-Text-Weak: var(--text-dim) !important;
  /* плейсхолдер закрытого дропдауна ("Все проблемы"/"Любая") и плейсхолдер
     поля периода красятся именно этой переменной — её дефолт, тёмно-синий
     rgba(0,21,89,.6), рассчитан на светлый фон и на тёмной теме сливался
     с фоном лукапа */
  --Dash-Text-Disabled: var(--text-dim) !important;
  --Dash-Stroke-Strong: var(--border) !important;
  --Dash-Stroke-Weak: var(--border) !important;
}

/* Светлая тема — палитра predictor.su (awb-color1..8 из фирменного CSS) */
:root[data-theme="light"] {
  --bg: #ffffff;
  --panel: #ffffff;
  --panel-alt: #fdfdfd;
  --panel-2: #e8eaeb;
  --border: #e8eaeb;
  --text: #111111;
  --text-dim: #748187;
  --accent: #57a7b3;
  --accent-2: #b36357;

  /* success/error — единственные два цвета обратной связи без готового
     эквивалента в брендовой палитре, поэтому у них отдельные значения на
     тему (info/warning по-прежнему = accent/accent-2 выше) */
  --color-success: #16a34a;
  --color-success-bg: #eafaf0;
  --color-error: #dc2626;
  --color-error-bg: #fbeae8;
  --color-info-bg: #eaf4f6;
  --color-warning-bg: #f7ece7;

  --tooltip-bg: #1f2430;
  --tooltip-fg: #ffffff;
}

* { box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  margin: 0;
}

/* ── иконки ──────────────────────────────────────────────────────────────
   font-variation-settings — одна строка держит толщину линии, скругление
   (FILL) и оптический размер одинаковыми у всех иконок приложения; менять
   стиль всего набора — это правка одной переменной оси, а не N SVG-файлов. */
.icon {
  font-family: 'Material Symbols Outlined';
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 20;
  font-style: normal;
  font-weight: normal;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  word-wrap: normal;
  display: inline-flex;
  vertical-align: middle;
  color: currentColor;
  -webkit-font-smoothing: antialiased;
}
.icon-xs { font-size: 14px; }
.icon-sm { font-size: 18px; }
.icon-md { font-size: 22px; }

.delta { display: inline-flex; align-items: center; gap: 2px; cursor: help; }

/* нативные чекбоксы/радио (в т.ч. внутри опций Dropdown) по умолчанию
   красятся браузером в фиолетовый — переводим на акцентный цвет бренда */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--accent);
}

/* фокус-рамка поиска в мульти-дропдауне у Dash по умолчанию фиолетовая —
   тоже на акцентный цвет бренда; !important, т.к. компонент красит себя
   инлайн-стилями */
.dash-dropdown-search,
.dash-dropdown-search:focus,
.dash-dropdown-search-container,
.dash-dropdown-search-container:focus-within,
.dash-dropdown-control:focus-within {
  border-color: var(--accent) !important;
  outline-color: var(--accent) !important;
  box-shadow: 0 0 0 1px var(--accent) !important;
}

/* сам контрол мульти-дропдауна — постоянная фиолетовая рамка, когда есть
   выбранное значение (не только на фокусе) */
button.dash-dropdown {
  border-color: var(--border) !important;
}
button.dash-dropdown:focus,
button.dash-dropdown:focus-within {
  border-color: var(--accent) !important;
  outline-color: var(--accent) !important;
}
/* predictor-style.css красит ЛЮБУЮ <button> терракотовым при наведении —
   это правило той же специфичности (element+:hover), что и здесь, и
   без явного hover-стиля лукап на ховере всё равно проваливался в
   терракотовый/акцентный фон вместо своего обычного. Оставляем фон как
   в состоянии покоя, подсвечиваем только рамку. */
button.dash-dropdown:hover {
  background-color: var(--Dash-Fill-Inverse-Strong) !important;
  border-color: var(--accent) !important;
}
.dash-dropdown-action-button:hover,
.dash-dropdown-clear:hover {
  background-color: transparent !important;
}

/* попап со списком опций мульти-дропдауна: фон/текст жёстко белые/тёмно-
   синие у Dash по умолчанию и не реагируют на смену темы */
.dash-dropdown-content {
  background-color: var(--panel) !important;
  color: var(--text) !important;
  border-color: var(--border) !important;
}
.dash-dropdown-search {
  background-color: var(--panel-alt) !important;
  color: var(--text) !important;
}
.dash-dropdown-search::placeholder {
  color: var(--text-dim) !important;
}
.dash-dropdown-action-button {
  color: var(--text-dim) !important;
}
.dash-dropdown-option {
  color: var(--text) !important;
  background-color: transparent !important;
}
.dash-dropdown-option:hover {
  background-color: var(--panel-alt) !important;
  color: var(--accent) !important;
}
/* крестик очистки выбора — фиолетовый, на терракотовом фоне открытого
   контрола читался как некрасивый красный */
.dash-dropdown-clear {
  color: var(--text-dim) !important;
}
.dash-dropdown-clear:hover {
  color: var(--text) !important;
}

/* календарь DatePickerRange: выбранная дата, подсветка диапазона и рамка
   самого поля-триггера — тоже фиолетовые по умолчанию */
.dash-datepicker-calendar-date-selected {
  background-color: var(--accent) !important;
}
.dash-datepicker-calendar-date-highlighted {
  color: var(--accent) !important;
}
.dash-datepicker-input-wrapper:focus-within {
  border-color: var(--accent) !important;
  outline-color: var(--accent) !important;
}

/* год в шапке календаря: числовой степпер подменяется на <select> скриптом
   assets/ru-datepicker.js — сам степпер (кнопки -/+) больше не нужен,
   инпут визуально спрятан скриптом. Оформляем select под общий стиль */
.dash-datepicker-controls .dash-input-stepper { display: none !important; }
.dash-datepicker-year-select {
  min-width: 78px;
  height: 32px;
  padding: 0 8px;
  background-color: var(--panel-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
}
.dash-datepicker-year-select:hover,
.dash-datepicker-year-select:focus {
  border-color: var(--accent);
  outline-color: var(--accent);
}

.app-shell { min-height: 100vh; }

.layout-row { display: flex; min-height: 100vh; }

/* ── сайдбар ─────────────────────────────────────────────────────────────── */

.sidebar {
  flex: 0 0 260px;
  width: 260px;
  background: var(--panel);
  border-right: 1px solid var(--border);
  padding: var(--space-4) var(--space-3);
  transition: width .15s ease, flex-basis .15s ease;
  overflow: hidden;
}
/* ширина подобрана так, чтобы влезали полные названия разделов ("Карта
   Уфы", "Динамика" и т.д.) без сокращения до 2 букв */
.layout-row.sidebar-collapsed .sidebar { flex-basis: 150px; width: 150px; padding: var(--space-4) var(--space-2); }

.sidebar-header { margin-bottom: var(--space-4); }
.sidebar-header-top { display: flex; justify-content: flex-end; margin-bottom: var(--space-2); }
.sidebar-logo { display: block; width: 100%; max-width: 168px; height: auto; margin: 0 auto var(--space-2); }
.sidebar-title {
  font-family: var(--font-heading);
  font-size: var(--text-md);
  font-weight: 700;
  line-height: var(--leading-snug);
  text-align: center;
}

.sidebar-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 50%;
  /* 32px — кратно базовой сетке в 8px (см. чеклист Spacing/Grid:
     "component heights designed to align to the base unit") */
  width: var(--space-6);
  height: var(--space-6);
  flex-shrink: 0;
  padding: 0;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .12);
  transition: background-color .18s ease, border-color .18s ease,
              color .18s ease, box-shadow .18s ease, transform .12s ease;
}
.sidebar-toggle-btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #ffffff;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
}
.sidebar-toggle-btn:active { transform: scale(.92); }
.sidebar-toggle-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.sidebar-toggle-icon {
  display: flex;
  line-height: 1;
  transition: transform .25s ease;
}
.sidebar-toggle-btn--collapsed .sidebar-toggle-icon { transform: rotate(180deg); }

.sidebar-nav { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-3); }
.nav-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  background: transparent;
  border: none;
  color: var(--text-dim);
  padding: var(--space-2) var(--space-2);
  border-radius: 8px;
  cursor: pointer;
  font-size: var(--text-body);
  text-align: left;
  white-space: nowrap;
}
.nav-btn:hover { background: var(--panel-alt); color: var(--text); }
.nav-btn--active { background: var(--panel-alt); color: var(--accent); font-weight: 600; }
.nav-btn:focus-visible,
.btn-page:focus-visible,
.region-chip-clear:focus-visible,
.alert-action:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.sidebar-divider { height: 1px; background: var(--border); margin: var(--space-3) 0; }

.sidebar-section { margin-bottom: var(--space-1); }
.sidebar-section-title {
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-dim);
  margin-bottom: var(--space-2);
}

.theme-radio { display: flex; flex-direction: column; gap: var(--space-2); }
.theme-radio label { color: var(--text); font-size: var(--text-sm); text-transform: none; letter-spacing: 0; }

/* при сворачивании прячем логотип/заголовок, фильтры и тему — названия
   разделов навигации остаются полными, без сокращения до 2 букв */
.layout-row.sidebar-collapsed .nav-label,
.layout-row.sidebar-collapsed .sidebar-section,
.layout-row.sidebar-collapsed .sidebar-divider {
  display: none;
}

/* ── основной контент ───────────────────────────────────────────────────── */

.main-content {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--space-5) var(--space-6) var(--space-8);
}

/* блок «Фильтры» в левом меню */
.sidebar-filter-item { width: 100%; margin-bottom: var(--space-3); }

/* > напрямую, а не просто "label" — иначе это правило заодно ловит
   <label> чекбоксов внутри выпадающего списка Dropdown (он монтируется
   тем же деревом внутри .sidebar-filter-item) и ставит их display:block,
   из-за чего чекбокс сваливается НАД текстом опции вместо "слева от него" */
.sidebar-filter-item > label {
  display: block;
  font-size: var(--text-caption);
  color: var(--text-dim);
  margin-bottom: var(--space-1);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}

/* поле периода в узком сайдбаре: у обёртки дропдауна justify-items: start,
   поэтому инпут сжимается до дефолтной браузерной ширины и не растягивается
   под грид-трек — год в дате (DD.MM.YYYY) обрезался и не помещался в поле.
   Растягиваем инпут на всю доступную ширину и даём под текст минимум места. */
.sidebar-filter-item .dash-datepicker-input-wrapper { width: 100%; }
.sidebar-filter-item .dash-datepicker-input {
  width: 100%;
  min-width: 92px;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2);
}

/* чекбокс опций мульти-дропдауна — гарантированно слева от текста,
   а не сверху */
.dash-options-list-option {
  display: flex !important;
  align-items: center;
  gap: var(--space-2);
}
.dash-options-list-option-wrapper { flex-shrink: 0; display: flex; align-items: center; }

.radio-inline label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-right: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}

.last-updated { font-size: var(--text-caption); color: var(--text-dim); }

.page-title {
  text-align: center;
  margin-bottom: var(--space-4);
}
.page-title-name {
  font-family: var(--font-heading);
  font-weight: 700;
  font-style: italic;
  font-size: var(--text-heading-sm);
  line-height: var(--leading-snug);
  color: var(--text);
}
.page-title-filters {
  font-size: var(--text-md);
  color: var(--text-dim);
}
.reset-filters-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: var(--space-3);
  vertical-align: middle;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 20px;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-caption);
  cursor: pointer;
}
.reset-filters-btn:hover { border-color: var(--accent); color: var(--accent); }
.reset-filters-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.groups-note {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-dim);
  font-size: var(--text-sm);
  margin-bottom: var(--space-3);
}

.tab-content { margin-top: var(--space-1); }

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.kpi-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: var(--space-component-lg);
}
.kpi-label {
  font-size: var(--text-caption);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.kpi-value {
  font-size: var(--text-heading-lg);
  line-height: var(--leading-tight);
  font-weight: 700;
  margin-top: var(--space-1);
  font-variant-numeric: tabular-nums;
}
.kpi-sub {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-sm);
  color: var(--accent-2);
  margin-top: var(--space-1);
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: var(--space-component-lg);
  margin-bottom: var(--space-4);
}
.card h3 { margin: var(--space-1) 0 var(--space-2); font-size: var(--text-md); }
.card h4 { margin: var(--space-1) 0 var(--space-2); font-size: var(--text-sm); color: var(--text-dim); text-transform: uppercase; }
.card-wide { width: 100%; }

.row-2col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}
/* планшет (768–1280px, см. чеклист адаптивности) — рейтинговые графики
   бок о бок уже не помещаются комфортно */
@media (max-width: 1280px) { .row-2col { grid-template-columns: 1fr; } }

.map-fullscreen {
  height: calc(100vh - 190px);
  min-height: 420px;
  width: 100%;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
}

.ts-controls {
  display: flex;
  gap: var(--space-6);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}

.region-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--panel-alt);
  border: 1px solid var(--accent);
  color: var(--text);
  border-radius: 20px;
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  margin-bottom: var(--space-4);
}
.region-chip-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  line-height: 1;
  padding: var(--space-1);
  border-radius: 50%;
}
.region-chip-clear:hover { background: var(--panel-2); color: var(--text); }

/* DataTable сам считает пиксельные ширины колонок в JS и игнорирует
   width/minWidth/maxWidth в процентах — принудительно фиксируем раскладку
   через CSS с !important, это уже гарантированно побеждает инлайн-стили
   компонента. "Текст поста" всегда ровно половина ширины таблицы. */
#posts-table-wrap table { table-layout: fixed !important; width: 100% !important; }
#posts-table-wrap [data-dash-column="text"] {
  width: 50% !important; min-width: 50% !important; max-width: 50% !important;
}
#posts-table-wrap [data-dash-column="group_name"] { width: 10% !important; min-width: 10% !important; max-width: 10% !important; }
#posts-table-wrap [data-dash-column="post_date"] { width: 7% !important; min-width: 7% !important; max-width: 7% !important; }
#posts-table-wrap [data-dash-column="problem_name"] { width: 9% !important; min-width: 9% !important; max-width: 9% !important; }
#posts-table-wrap [data-dash-column="problem_exists"] { width: 4% !important; min-width: 4% !important; max-width: 4% !important; }
#posts-table-wrap [data-dash-column="problem_confidence"] { width: 7% !important; min-width: 7% !important; max-width: 7% !important; }
#posts-table-wrap [data-dash-column="problem_reason"] { width: 13% !important; min-width: 13% !important; max-width: 13% !important; }

#groups-table-wrap table { table-layout: fixed !important; width: 100% !important; }
#groups-table-wrap [data-dash-column="name"] { width: 22% !important; min-width: 22% !important; max-width: 22% !important; }
#groups-table-wrap [data-dash-column="screen_name"] { width: 14% !important; min-width: 14% !important; max-width: 14% !important; }
#groups-table-wrap [data-dash-column="type"] { width: 8% !important; min-width: 8% !important; max-width: 8% !important; }
#groups-table-wrap [data-dash-column="count_members"] { width: 10% !important; min-width: 10% !important; max-width: 10% !important; }
#groups-table-wrap [data-dash-column="region"] { width: 14% !important; min-width: 14% !important; max-width: 14% !important; }
#groups-table-wrap [data-dash-column="ufa_region"] { width: 12% !important; min-width: 12% !important; max-width: 12% !important; }
#groups-table-wrap [data-dash-column="posts_count"] { width: 10% !important; min-width: 10% !important; max-width: 10% !important; }
#groups-table-wrap [data-dash-column="posts_with_problem"] { width: 10% !important; min-width: 10% !important; max-width: 10% !important; }

.posts-controls { margin-bottom: var(--space-3); }
.text-search {
  width: 100%;
  max-width: 420px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}

/* ── тултип (наведение/фокус) ─────────────────────────────────────────────
   Чистый CSS, без JS и без нового callback'а: раскрывается на hover/focus
   и закрывается сам на mouseleave/blur — по чеклисту явный dismiss нужен
   только для навязчивых/persistent тултипов, у ховер-варианта это
   избыточно. Фон — ВСЕГДА инверсия текущей темы (не копия поверхности под
   собой), это и даёт гарантированный контраст в обеих темах. */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 240px;
  background: var(--tooltip-bg);
  color: var(--tooltip-fg);
  font-size: var(--text-caption);
  /* сброс — источник тултипа часто сам uppercase (подпись фильтра,
     заголовок секции), но текст подсказки — обычное предложение */
  text-transform: none;
  font-weight: 400;
  letter-spacing: normal;
  line-height: var(--leading-normal);
  padding: var(--space-2) var(--space-3);
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .22);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .12s ease;
  z-index: 40;
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  opacity: 1;
  visibility: visible;
}
@media (prefers-reduced-motion: reduce) {
  [data-tooltip]::after { transition: none; }
}

.tooltip-icon {
  display: inline-flex;
  color: var(--text-dim);
  cursor: help;
  vertical-align: middle;
}
.tooltip-icon:hover,
.tooltip-icon:focus-visible { color: var(--accent); }

/* обёртка тултипа на disabled-кнопке: у самой кнопки atrribute disabled
   отключает pointer-events в большинстве браузеров, поэтому :hover на ней
   не срабатывает — ставим data-tooltip на обёртку, а не на сам <button> */
.tooltip-wrap { display: inline-flex; }

.pager {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-3);
}
.btn-page {
  background: var(--panel-alt);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  font-size: var(--text-sm);
}
.btn-page:hover { border-color: var(--accent); color: var(--accent); }
/* первая/последняя страница — кнопка недоступна, а не молча ничего не
   делает по клику ("достигнут лимит данных" должно быть видно, а не
   угадываться); tooltip-wrap рядом объясняет, почему именно недоступна */
.btn-page:disabled {
  opacity: .4;
  cursor: not-allowed;
}
.btn-page:disabled:hover { border-color: var(--border); color: var(--text); }
.page-info { font-size: var(--text-sm); color: var(--text-dim); }

/* ── алерт ─────────────────────────────────────────────────────────────────
   Единый компонент для ошибок и пустых состояний, с четырьмя семантическими
   вариантами (см. чеклист Alert) — раньше и «нет данных под фильтр», и
   «упала БД» рендерились одним нейтральным .empty-state и визуально не
   различались. Текст сообщения всегда --text (гарантированная читаемость),
   цвет варианта несёт только иконка/рамка/кнопка — не единственный сигнал. */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4);
  border-radius: 10px;
  border: 1px solid;
  background: var(--panel);
}
.alert-icon { flex-shrink: 0; margin-top: 1px; }
.alert-message {
  flex: 1 1 auto;
  font-size: var(--text-body);
  line-height: var(--leading-normal);
  color: var(--text);
  align-self: center;
}
.alert-action {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 6px;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-caption);
  cursor: pointer;
}
.alert-action:hover { opacity: .78; }
.alert-action:active { transform: scale(.97); }

.alert--info    { border-color: var(--color-info);    background: var(--color-info-bg); }
.alert--info    .alert-icon, .alert--info    .alert-action { color: var(--color-info); }
.alert--success { border-color: var(--color-success); background: var(--color-success-bg); }
.alert--success .alert-icon, .alert--success .alert-action { color: var(--color-success); }
.alert--warning { border-color: var(--color-warning); background: var(--color-warning-bg); }
.alert--warning .alert-icon, .alert--warning .alert-action { color: var(--color-warning); }
.alert--error   { border-color: var(--color-error);   background: var(--color-error-bg); }
.alert--error   .alert-icon, .alert--error   .alert-action { color: var(--color-error); }

/* мобильный, включая горизонтальную ориентацию (до 768px) — сайдбар
   переходит из колонки слева в блок над контентом */
@media (max-width: 768px) {
  .layout-row { flex-direction: column; }
  .sidebar { width: 100%; flex-basis: auto; border-right: none; border-bottom: 1px solid var(--border); }
  .main-content { padding: var(--space-4) var(--space-3) var(--space-6); }
}

/* смартфон в портретной ориентации (до 480px) — карточки KPI в один
   столбец, иначе минимальная ширина 200px не влезает по горизонтали;
   заодно ужимаем display-размеры шкалы (чеклист Typography: "responsive
   type behaviour") — на 320px экране 27px KPI-значение неоправданно крупное */
@media (max-width: 480px) {
  .kpi-row { grid-template-columns: 1fr; }
  :root { --text-heading-lg: 1.375rem; /* 22px вместо 27px */ }
  .page-title-name { font-size: var(--text-md); }
}
