/* Токены — 1:1 с Gentelella v4 (`src/scss/v4/_tokens.scss`).
   Значения сверены с npm-пакетом gentelella@4.0.1.
   Референс: https://preview.colorlib.com/theme/gentelella/ */
:root {
  /* Бренд: teal #1ABB9C — ключевой признак стиля Gentelella v4. */
  --primary: #1abb9c;
  /* Прозрачные производные акцента: заливки hover/selected и focus-ring. */
  --primary-lt: rgba(26,187,156,0.08);
  --primary-ring: rgba(26,187,156,0.18);
  /* Бренд-цвет для ТЕКСТА, заливок под белым текстом и индикаторов
     фокуса: яркий #1abb9c на белом даёт 2.43:1 — ниже AA (4.5 для
     текста) и ниже 3:1, которое WCAG 1.4.11 требует для фокуса.
     Тот же оттенок, но глубже — 5.25:1. --primary остаётся ярким
     для декора: бренд-марка, тинты, hover-границы. */
  --primary-strong: #0e7a68;
  --primary-strong-dk: #0b6355;

  /* Семантическая палитра референса (11 цветов + производные). */
  --blue: #066fd1;
  --azure: #4299e1;
  --green: #2fb344;
  --lime: #74b816;
  --yellow: #f59f00;
  --orange: #f76707;
  --red: #d63939;
  --pink: #d6336c;
  --purple: #ae3ec9;
  --indigo: #4263eb;
  --cyan: #17a2b8;

  --green-lt: rgba(47,179,68,0.08);
  --red-lt: rgba(214,57,57,0.08);
  --red-ring: rgba(214,57,57,0.20);
  --yellow-lt: rgba(245,159,0,0.12);
  --blue-lt: rgba(6,111,209,0.08);
  --azure-lt: rgba(66,153,225,0.08);
  --purple-lt: rgba(174,62,201,0.08);
  --slate-lt: rgba(148,163,184,0.08);

  /* Поверхности, текст, границы. */
  --body-bg: #f5f7fb;
  --bg-surface: #ffffff;
  --bg-surface-secondary: #f9fafb;
  --border-color: #e6e7eb;
  --border-color-light: #eff0f3;
  --border-translucent: rgba(4,32,69,0.08);
  --text: #1e2633;
  --text-secondary: #626d7d;
  --text-muted: #7e8896;
  --text-disabled: #c0c7cf;

  /* Sidebar — тёмный по умолчанию (отличие от прежней светлой панели:
     выбран владельцем как «полный Gentelella»). */
  --sidebar-bg: #1a2332;
  --sidebar-hover: rgba(255,255,255,0.04);
  --sidebar-active: rgba(26,187,156,0.10);
  --sidebar-text: #7b8fa3;
  --sidebar-text-hover: #c5d0dc;
  --sidebar-text-active: #ffffff;
  --sidebar-border: rgba(255,255,255,0.06);
  --sidebar-w: 252px;

  /* Геометрия: 4/6/8 как в референсе (было одно 10px). */
  --radius: 6px;
  --radius-sm: 4px;
  --radius-lg: 8px;

  /* Spacing scale — 4px база, как в референсе. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Тени «near-invisible» — в референсе тень почти не читается, объём даёт рамка. */
  --shadow: rgba(30,38,51,0.04) 0 2px 4px 0;
  --shadow-card: 0 0 0 1px var(--border-translucent), rgba(30,38,51,0.04) 0 2px 4px 0;
  --shadow-pop: 0 8px 24px rgba(15,23,42,0.12), 0 0 0 1px var(--border-translucent);
  --shadow-modal: 0 24px 48px rgba(15,23,42,0.18), 0 0 0 1px var(--border-translucent);

  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* Мягкие hover-заливки (тёмные/светлые поверхности без токена). */
  --hover: rgba(0,0,0,0.04);
  --hover-soft: rgba(0,0,0,0.02);

  /* ── Алиасы: исторические имена проекта. Все вьюхи и половина CSS
     ссылаются на них, поэтому они остаются рабочими и после перехода
     на канонические имена референса. ───────────────────────────────── */
  --bg: var(--body-bg);
  --surface: var(--bg-surface);
  --border: var(--border-color);
  --accent: var(--primary-strong);
  --accent-hover: var(--primary-strong-dk);
  --warning: var(--yellow);

  /* --muted / --success / --danger — семантические цвета проекта, поэтому для
     текста они намеренно темнее одноимённых «филловых» цветов референса:
     его --text-muted #7e8896 даёт 3.59:1 на белом, --green #2fb344 — 2.74:1,
     то есть ниже WCAG AA (4.5:1). --green/--red остаются в палитре как цвета
     заливок и полос. Замеры и альтернативы — DESIGN.md §2.9. */
  --muted: var(--text-secondary);   /* 5.0–5.3:1 на светлом */
  --success: #178030;               /* 5.1–5.5:1 */
  --danger: #b02c2c;                /* 5.9–6.5:1 */
}

/* Тёмная тема: значения заложены сейчас, переключателя пока нет —
   включается атрибутом <html data-theme="dark">. Алиасы выше разрешаются
   на этапе использования, поэтому перекрашиваются автоматически. */
[data-theme="dark"] {
  --body-bg: #0f1623;
  --bg-surface: #1a2332;
  --bg-surface-secondary: #141d2b;
  --border-color: rgba(255,255,255,0.08);
  --border-color-light: rgba(255,255,255,0.05);
  --border-translucent: rgba(255,255,255,0.08);
  --text: #e6ebf2;
  --text-secondary: #b3bccb;
  --text-muted: #8a93a3;
  --text-disabled: #5a6473;
  --primary-lt: rgba(26,187,156,0.14);
  --green-lt: rgba(47,179,68,0.16);
  --red-lt: rgba(214,57,57,0.16);
  --yellow-lt: rgba(245,159,0,0.16);
  --blue-lt: rgba(6,111,209,0.18);
  --azure-lt: rgba(66,153,225,0.16);
  --purple-lt: rgba(174,62,201,0.16);
  --hover: rgba(255,255,255,0.05);
  --hover-soft: rgba(255,255,255,0.03);
  --shadow: rgba(0,0,0,0.4) 0 2px 4px 0;
  --shadow-card: 0 0 0 1px var(--border-translucent), rgba(0,0,0,0.3) 0 2px 4px 0;
  /* На тёмном фоне затемнённые текстовые варианты нечитаемы (#178030 на
     #1a2332 — 2.9:1), поэтому возвращаем светлые цвета референса: они
     рассчитаны на тёмный сайдбар/поверхности. */
  --muted: var(--text-muted);
  --success: var(--green);
  --danger: var(--red);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  /* 1.4286 — межстрочный референса (14px × 1.4286 = 20px). */
  line-height: 1.4286;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Страница не должна скроллиться влево-вправо: горизонтальный скролл
     допустим только внутри таблицы (.table-wrap). */
  overflow-x: hidden;
}

/* Тонкий скроллбар как в референсе (6px, без рельса). */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.12); border-radius: 3px; }
/* На тёмном фоне чёрный ползунок не виден — инвертируем на белую полупрозрачность. */
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); }

/* Единый keyboard-focus. :focus-visible — чтобы клик мышью не рисовал рамку;
   у полей ввода свою рамку рисует box-shadow, поэтому ниже outline снят. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--primary-strong);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible,
.filters-bar select:focus-visible,
.filters-bar--inline input:focus-visible,
.filters-bar--inline select:focus-visible,
.category-select-search:focus-visible,
.color-hex:focus-visible,
.combobox-input:focus-visible { outline: none; }

/* Ссылки: teal и без подчёркивания, подчёркивание только на hover — как в
   референсе. Правила не было вообще, поэтому «голые» ссылки без класса
   (напр. import-rules.js:56) рендерились дефолтным синим браузера
   rgb(0,0,238), выбиваясь из палитры. Компонентные правила (.brand, .nav a,
   .card-link, a.btn, .cards-badge) объявлены ниже по файлу и при равной
   специфичности перебивают эти по порядку следования. */
a { color: var(--primary-strong); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Компонентные ссылки не подчёркиваются на hover: их собственные правила
   (.brand, .card-link) — один класс (0,1,0), а `a:hover` — (0,1,1), поэтому
   проигрывают по специфичности, а не по порядку. На карточке дашборда это
   подчёркивало бы весь текст карточки. .cards-badge:hover объявлен ниже и
   намеренно подчёркивается. */
.brand:hover,
.nav a:hover,
.card-link:hover,
a.btn:hover { text-decoration: none; }

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  /* Гарантируем, что .app занимает всю высоту вьюпорта, даже если контент
     короче — иначе .content не получит высоту для передачи детям. */
  min-height: 100vh;
  height: 100vh;
}

/* === Sidebar === */
/* Тёмная панель (#1a2332) — главный визуальный признак Gentelella v4.
   Flex-колонка: бренд зафиксирован, .nav скроллится сам (иначе на низких
   вьюпортах часть пунктов меню обрезалась бы). */
.sidebar {
  display: flex;
  flex-direction: column;
  background: var(--sidebar-bg);
  padding: var(--space-2) var(--space-2) 0;
  /* Плавное сворачивание при переключении состояния (.app.sidebar-hidden);
     overflow: hidden обрезает содержимое по ширине во время анимации. */
  overflow: hidden;
  transition: width 0.22s cubic-bezier(0.2, 0, 0, 1);
}
/* Скрытая боковая панель: колонка грида 0, сайдбар не виден,
   overflow скрыт, чтобы контент не вылезал при transition. */
.app.sidebar-hidden { grid-template-columns: 0 minmax(0, 1fr); }
.app.sidebar-hidden .sidebar {
  width: 0;
  padding-left: 0;
  padding-right: 0;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 56px;
  padding: 0 var(--space-3);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--sidebar-text-active);
  text-decoration: none;
  flex-shrink: 0;
  border-bottom: 1px solid var(--sidebar-border);
  margin-bottom: var(--space-2);
}
/* Марка бренда: сплошной teal-квадрат (был градиент синий→фиолетовый —
   градиент не встречается в референсе ни разу). */
.brand-dot {
  width: 28px; height: 28px;
  flex-shrink: 0;
  background: var(--primary);
  border-radius: var(--radius);
}
.nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding-bottom: var(--space-3);
}
.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  padding: 6px var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--sidebar-text);
  text-decoration: none;
  font-size: 13px;
  font-weight: 400;
  transition: background 0.12s, color 0.12s;
}
.nav a:hover {
  background: var(--sidebar-hover);
  color: var(--sidebar-text-hover);
}
.nav a.active {
  background: var(--sidebar-active);
  color: var(--sidebar-text-active);
  font-weight: 500;
}
.nav-icon {
  width: 18px;
  min-width: 18px;
  text-align: center;
  font-size: 15px;
  opacity: 0.5;
}
.nav a:hover .nav-icon,
.nav a.active .nav-icon { opacity: 0.85; }
.nav-section {
  padding: 16px var(--space-3) 4px;
  font-size: 10px;
  text-transform: uppercase;
  /* Цвет как у пунктов меню (--sidebar-text, 4.74:1 — проходит AA). Референс
     даёт здесь alpha 0.5 (2.26:1 — нечитаемо), 0.7 давала 3.06:1, то есть всё
     ещё ниже AA, а поднять без выравнивания с меню нельзя. Иерархия сохранена
     другими средствами: 10px против 14px, uppercase, letter-spacing и отбивка. */
  color: var(--sidebar-text);
  font-weight: 600;
  letter-spacing: 0.5px;
}

/* === Content === */
.content { display: flex; flex-direction: column; min-height: 0; }
/* Топбар — 56px, полупрозрачный с блюром (как в референсе). */
.topbar {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3);
  height: 56px;
  padding: 0 var(--space-5);
  background: rgba(255,255,255,0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-color);
  flex: 0 0 auto;
}
[data-theme="dark"] .topbar { background: rgba(20,29,43,0.85); }
.topbar h1 { font-size: 18px; margin: 0; font-weight: 600; letter-spacing: -0.1px; }
/* Мета прижата к правому краю — раньше space-between растаскивал три
   элемента и заголовок «висел» по центру. */
.topbar-meta { font-size: 13px; color: var(--muted); margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }

/* Кнопка-гамбургер в топбаре: переключает видимость боковой панели.
   Должна выглядеть как часть топбара (без рамки, как у бренда), но
   подсвечиваться при наведении. */
.sidebar-toggle,
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 16px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.sidebar-toggle:hover,
.theme-toggle:hover { background: var(--body-bg); color: var(--text); }
.sidebar-toggle:focus-visible,
.theme-toggle:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 1px; }
/* Когда сайдбар скрыт — иконка-стрелка показывает «развернуть»,
   когда виден — «свернуть». Это просто визуальный сигнал, не критично. */
.app.sidebar-hidden .sidebar-toggle .fa-bars::before { content: "\f0c9"; } /* bars (по умолчанию) */

/* .view должна быть флекс-колонкой с min-height: 0, чтобы высота
   корректно передавалась детям (в т. ч. .table-wrap). Без min-height: 0
   флекс-детям не разрешают сжиматься ниже их контента и overflow: auto
   в .table-wrap не сработает. */
.view {
  padding: var(--space-5);
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* Страховка на случай, когда содержимое выше вьюпорта: скроллится сама
     область контента, а НЕ body. Без этого body становился скроллером
     (у него overflow-x: hidden, из-за чего overflow-y вычисляется в auto),
     и сайдбар с position: static уезжал вверх вместе со страницей — на
     /import-rules форма + список правил дают 1912px при вьюпорте 900.
     Так же ведёт себя референс: там скроллится .main, а .sidebar и .topbar
     зафиксированы. На табличных страницах контент помещается, скроллбар
     не появляется — таблица по-прежнему скроллится внутри .table-wrap. */
  overflow-y: auto;
}

/* === Cards === */
/* Дашборд: ровно 5 показателей в строке, каждый блок — 5 карточек, итого 2 строки.
   Раньше стоял auto-fit minmax(200px, 1fr): шестая карточка второго блока
   не влезала в строку и оставалась одна на третьей. Фиксированные 5 колонок
   делают раскладку 5+5 независимой от ширины окна (см. брейкпоинты ниже). */
.cards {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  box-shadow: var(--shadow);
}
.card-label {
  font-size: 11.5px;
  color: var(--muted);
  text-transform: uppercase;
  font-weight: 500;
  letter-spacing: 0.3px;
  line-height: 1.3;
}
.card-value { font-size: 22px; font-weight: 600; letter-spacing: -0.5px; line-height: 1.2; margin-top: 6px; }
.card-sub { font-size: 11px; color: var(--muted); margin-top: 2px; }
/* Карточка-ссылка (дашборд): обёрнута в <a>, клик ведёт в раздел.
   Тонкий hover/focus, чтобы намекнуть на интерактивность, без перегруза. */
.card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.card-link:hover {
  box-shadow: var(--shadow-card);
  border-color: var(--primary);
}
.card-link:focus-visible {
  outline: 2px solid var(--primary-strong);
  outline-offset: 2px;
}
/* Кликабельная строка «Последние операции» — тот же hover-эффект, что у tr в таблице. */
.table .tx-row { cursor: pointer; }
.table .tx-row:hover td { background: var(--primary-lt); }
.table .tx-row:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: -2px; }
.card.accent .card-value { color: var(--accent); }
.card.success .card-value { color: var(--success); }
.card.danger .card-value { color: var(--danger); }

/* === Tables === */
.table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: auto;
  box-shadow: var(--shadow);
  /* Растягиваем таблицу на всю оставшуюся высоту .view. Скроллится
     только сама таблица; страница (включая сайдбар и топбар) неподвижна.
     min-height: 0 обязателен — без него флекс-детям не разрешают сжиматься
     ниже их контента, и overflow: auto не сработает. */
  flex: 1 1 auto;
  min-height: 0;
}
/* Контейнер превью импорта — флекс-колонка на всю оставшуюся высоту .view.
   Это обязательное условие работы «прилипающей» шапки (.table th,
   position: sticky): sticky считается от БЛИЖАЙШЕГО скролл-контейнера.
   Раньше ближайшим был .table-wrap, но с height: auto он не скроллился сам —
   скроллился .view, и шапка уезжала вместе с таблицей. */
.import-table {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  /* Не даём флексу сплющить таблицу на низком окне: ниже этого — скроллится
     уже .view (обычный случай: места достаточно, скроллится .table-wrap). */
  min-height: 240px;
}
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  /* Если контент шире контейнера — браузер сам покажет горизонтальный
     скроллбар внутри .table-wrap. Не даём раздувать grid/flex треки. */
  table-layout: auto;
}
.table th, .table td {
  padding: 8px 16px;
  text-align: left;
  border-bottom: 1px solid var(--border-color-light);
  vertical-align: middle;
}
.table th {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.3px;
  background: var(--bg-surface-secondary);
  border-bottom: 1px solid var(--border);
  /* Шапка прилипает к верху при прокрутке таблицы */
  position: sticky;
  top: 0;
  z-index: 1;
}
.table tr:last-child td { border-bottom: none; }
/* Текст ячеек оставлен основным (--text), а не --text-secondary как в
   референсе: finans — реестр операций, приглушение всех колонок заметно
   бьёт по читаемости. Остальные признаки (padding 8/16, светлая шапка,
   тонкие разделители, заливка строки) взяты из референса. */
.table td { color: var(--text); }
.table tr:hover td { background: var(--bg-surface-secondary); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Дата (ISO YYYY-MM-DD) переносилась по дефисам, когда колонку сжимали соседние.
   В реестре дата — короткая метка строки, держим её в одну линию. */
.table .date-cell { white-space: nowrap; }

/* Кнопки действий в строке таблицы (✎ / × / ⊘ и т. п.) — в одну линию,
   прижаты к правому краю ячейки. Раньше лежали в одной <td> напрямую и
   рендерились столбиком, что растягивало высоту строки. */
.row-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
}
.row-actions .btn-sm { line-height: 1; }

/* === P/L (portfolio) и любые отрицательные суммы ===
   profit-pos — зелёный для прибыли; переведён на палитру референса
   (--green) вместо отдельного #1a8754.
   profit-neg + amt-neg — оба красные, единый --danger для консистентности
   (был отдельный #c1352f у profit-neg, теперь оба на --danger). */
.profit-pos { color: var(--success); font-variant-numeric: tabular-nums; }
.profit-neg,
.amt-neg { color: var(--danger); font-variant-numeric: tabular-nums; }

/* === Buttons ===
   Высота 32 / radius 4 / кегль 12.5 — как .btn в референсе. Базовый .btn
   соответствует тамошнему .btn-outline: светлая рамка, почти невидимая тень. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 32px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  box-shadow: var(--shadow);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s, box-shadow 0.12s;
}
.btn:hover { background: var(--bg-surface-secondary); color: var(--text); }
.btn-primary {
  background: var(--accent);
  color: white;
  border-color: var(--accent-hover);
}
.btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: white;
}
/* Danger — красный outline, а не сплошная заливка: в таблицах реестра
   сплошные красные кнопки в каждой строке слишком агрессивны. */
.btn-danger {
  color: var(--danger);
  border-color: var(--red-ring);
  background: var(--red-lt);
}
.btn-danger:hover { background: rgba(214,57,57,0.16); color: var(--danger); }
.btn-sm { height: 28px; padding: 0 10px; font-size: 12px; }
/* Кнопки-ссылки (<a class="btn">): у ссылок по умолчанию подчёркивание,
   для кнопки это лишнее. Остальные ссылки проекта гасят его сами. */
a.btn { text-decoration: none; }

/* === Empty / Loading === */
.empty {
  text-align: center;
  padding: 48px 24px;
  color: var(--muted);
}
.empty-title { font-size: 16px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.loading { padding: 24px; text-align: center; color: var(--muted); }

/* === Toast ===
   Светлая карточка с цветной левой полосой (референс), а не сплошная
   тёмная/цветная плашка: сплошной цвет читался как алерт поверх контента. */
.toast {
  position: fixed;
  bottom: 16px;
  right: 16px;
  padding: 10px 14px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  font-size: 13px;
  font-weight: 500;
  max-width: 360px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.2, 0, 0, 1);
  z-index: 100;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.error { border-left: 3px solid var(--danger); padding-left: 11px; }
.toast.success { border-left: 3px solid var(--success); padding-left: 11px; }

/* === Section === */
.section-title {
  font-size: 12px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin: var(--space-5) 0 var(--space-3);
  letter-spacing: 0.4px;
}

/* === Form === */
.form-row { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
.form-row label { font-size: 13px; color: var(--muted); min-width: 100px; }
.form-row input, .form-row select {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
}
.form-row input:focus, .form-row select:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}

/* === Badge ===
   Радиус 4px вместо таблетки 999px — бейджи референса прямоугольные.
   Верхний регистр и кегль оставлены: наши бейджи несут статус, а не метку. */
.badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.badge-expense { background: var(--red-lt); color: var(--danger); }
.badge-income { background: var(--green-lt); color: var(--success); }
/* Перемещение — нейтральный бейдж: деньги не заработаны и не потрачены,
   поэтому зелёный/красный доход-расход здесь вводил бы в заблуждение. */
.badge-transfer { background: var(--slate-lt); color: var(--text-secondary); }
.badge-info   { background: var(--blue-lt); color: var(--blue); }
.badge-warn   { background: var(--yellow-lt); color: #b45309; }
.badge-ok     { background: var(--green-lt); color: var(--success); }
.badge-error  { background: var(--red-lt); color: var(--danger); }

/* === Page title (h2 на странице без вложения в .page-toolbar) === */
.page-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}

/* === Hint (мелкий подсказочный текст под полем формы) === */
.hint-warn {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
}

/* === Form grid для двухколоночных форм (правила маппинга) ===
   Было `repeat(auto-fit, minmax(200px, 1fr))`: на 1440px это давало ПЯТЬ колонок
   шириной ~211px, и форма расползалась в одну длинную неровную строку. Комментарий
   и назначение говорят про две колонки — фиксируем их явно.
   `minmax(0, 1fr)`, а не `1fr`: иначе колонку раздувает min-content селекта
   (см. §2.8 про тот же приём в .app). */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 640px) {
  .form-grid { grid-template-columns: minmax(0, 1fr); }
}
/* Поля сетки — обычные .form-field (вертикальный стек label + контрол).
   Раньше здесь стоял .filter, но он стилизован ТОЛЬКО как `.filters-bar .filter`,
   поэтому вне фильтр-бара контролы оставались нативными: border 1px #767676,
   radius 0, высота 19–21px вместо 36, шрифт 13.33px и ширина по содержимому
   (в одинаковых колонках получалось 49 / 108 / 144 / 153 / 191px). */
.form-grid > .form-field { margin-bottom: 0; }   /* расстояние задаёт gap сетки */
/* Когда .form-field сам является <label> (обёртка вокруг контрола), подпись —
   это <span>, а не вложенный <label>: даём ему тот же вид. */
.form-grid > .form-field > span {
  display: block;
  font-size: 12px;
  color: var(--text);
  font-weight: 500;
}
/* Иначе gap 4px складывался с margin-top подсказки и давал 8px. */
.form-grid .hint-warn { margin-top: 0; }

/* === Карточка формы правил маппинга === */
.rule-form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-top: 12px;
}
.rule-form h3 {
  margin: 0 0 12px 0;
  font-size: 14px;
  font-weight: 600;
}

/* === Описание/интро для страницы правил маппинга === */
.rules-intro {
  color: var(--muted);
  margin: 4px 0 16px 0;
  font-size: 13px;
  max-width: 720px;
}
.rules-intro code {
  background: var(--bg);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
}

/* === Секции импорта выписки === */
.import-intro {
  color: var(--muted);
  margin: 4px 0 16px 0;
  font-size: 13px;
  max-width: 720px;
}
/* Кнопка разворачивает длинное описание формата выписки (intro). По умолчанию
   свёрнуто — место над таблицей не съедается при повторных загрузках. */
.import-intro-row {
  margin: 4px 0 0 0;
}
.import-upload {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.import-filename {
  color: var(--muted);
  font-size: 13px;
}
/* === Табы выбора банка (Альфа / Точка) === */
.import-bank-tabs {
  display: flex;
  gap: 6px;
  margin-left: auto;
}
.bank-tab {
  height: 32px;
  display: inline-flex;
  align-items: center;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  padding: 0 14px;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.12s, color 0.12s, border-color 0.12s;
}
.bank-tab:hover {
  background: var(--bg-surface-secondary);
  color: var(--text);
}
.bank-tab.active {
  background: var(--primary-strong);
  color: #fff;
  border-color: var(--primary-strong-dk);
}
.bank-tab:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 2px; }
.bank-tab i {
  margin-right: 6px;
}
/* Подсказка «приглушённый текст» — для «—» в категории transfer-строк. */
.hint-muted { color: var(--muted); }
.import-summary {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 12px 0;
}
.import-actions {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 16px 0;
}
/* Подсказка в панели действий: в каких строках не хватает счёта/категории
   (импорт заблокирован). Красный — тот же --danger, что у .row-invalid. */
.import-actions-error {
  color: var(--danger);
  font-size: 13px;
}
/* Номера строк в подсказке «Заполните данные: …» — кликабельные: переход к
   строке в таблице (import.js#jumpToRow). Наследуют цвет родителя. */
.row-jump {
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
}
.row-jump:hover { opacity: 0.75; }
.row-jump:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 1px; }
/* «… ещё N» / «свернуть» в подсказке о незаполненных строках: при длинной
   выписке (Точка, 200+ строк) полный перечень номеров не помещается — прячем
   его за этой кнопкой. Жирнее row-jump, чтобы отличалась от номеров строк. */
.row-more {
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
  white-space: nowrap;
}
.row-more:hover { opacity: 0.75; }
.row-more:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 1px; }
/* Короткая подсветка строки, к которой перешли из подсказки. Фон + рамка:
   одно подсвечивает и валидные, и красные (.row-invalid) строки. */
.table.table-import tr.row-flash td {
  background: var(--primary-lt);
  box-shadow: inset 0 0 0 2px var(--primary-strong);
}
/* === Предложение применить правку к другим строкам (модалка импорта) ===
   Своя разметка внутри openModal: текст + кнопки-варианты на всю ширину.
   Раньше это была плашка внизу таблицы — при длинном списке она была за кадром. */
.modal-text {
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--text);
}
.modal-choice-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.modal-choice-list .btn {
  width: 100%;
  /* Подпись группы может быть длинной (текст операции целиком), поэтому
     разрешаем перенос и растягиваем кнопку по высоте: у .btn nowrap + height:32,
     и длинный текст вылезал за пределы кнопки. */
  height: auto;
  min-height: 32px;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 2px;
  padding: 7px 12px;
  white-space: normal;
  text-align: left;
  line-height: 1.3;
}
.modal-choice-main { white-space: nowrap; }
.modal-choice-hint {
  font-size: 11.5px;
  font-weight: 400;
  opacity: 0.85;
  overflow-wrap: anywhere;
}
.save-rule {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
}
.save-rule input { vertical-align: middle; margin-right: 4px; }

/* === Дубли в превью импорта (операция уже импортирована по externalRef) === */
.row-dup {
  opacity: 0.55;
  background: var(--yellow-lt);
}

/* === HOLD-операции (неподтверждённые резервы — сумма ещё не списана) === */
.row-hold {
  background: var(--yellow-lt);
}
.row-hold:hover {
  background: rgba(245,159,0,0.20);
}

/* === Частично распознанные операции (платежи ГИБДД/СБП/ЖКХ — нет MCC/PAN/merchant) === */
.row-minimal {
  background: var(--slate-lt);   /* серый, чуть прозрачнее чем row-dup */
}
.row-minimal:hover {
  background: rgba(148,163,184,0.16);
}

/* === Transfer-операции (переводы между своими счетами — Точка) ===
   Синеватый фон чтобы визуально отличать от обычных расходов: это не расход. */
.row-transfer {
  background: var(--azure-lt);
}
.row-transfer:hover {
  background: rgba(66,153,225,0.14);
}

/* === Строка превью с незаполненным обязательным полем (счёт/категория) ===
   Импорт таких строк заблокирован: кнопка «Импортировать выбранные» выключена,
   пока у всех отмеченных строк нет счёта (и категории для доход/расход). */
.row-invalid {
  background: var(--red-lt);
}
/* Маркер слева: на border-collapse:collapse box-shadow у <tr> не рисуется,
   поэтому красим первую ячейку. */
.row-invalid td:first-child {
  box-shadow: inset 3px 0 0 var(--danger);
}
/* Контекст transfer-строки: номера счетов плательщика/получателя по выписке
   (помогает понять, что выбрать в 2 select'ах). */
.transfer-context {
  font-size: 11px;
  margin-top: 4px;
  color: var(--muted);
  word-break: break-all;
}

/* === Импорт: более плотная таблица превью === */
.table.table-import td,
.table.table-import th {
  padding: 6px 8px;
  font-size: 12px;
  vertical-align: middle;
}
/* У прилипающей шапки border-collapse: collapse «теряет» нижнюю границу —
   дублируем её тенью, иначе шапка визуально сливается со строками. */
.table.table-import th {
  box-shadow: inset 0 -1px 0 var(--border);
}
.table.table-import select {
  font-size: 12px;
  height: 26px;
  padding: 0 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  max-width: 100%;
}
/* Инпут примечания к строке превью: та же плотность, что у select. Поле живёт
   в отдельной строке .row-comment-form, поэтому растягивается на всю ширину. */
.table.table-import .row-comment {
  width: 100%;
  min-width: 130px;
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
}
.table.table-import .row-comment:focus {
  outline: none;
  border-color: var(--primary-strong);
}
.table.table-import .row-comment:disabled { opacity: 0.85; }
/* Примечание к строке превью: иконка в колонке Merchant (как .raw-toggle),
   поле открывается отдельной строкой .row-comment-form под операцией. */
.table.table-import .comment-toggle {
  border: 0;
  background: none;
  padding: 0 4px 0 0;
  margin: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: inherit;
  vertical-align: middle;
}
.table.table-import .comment-toggle:hover,
.table.table-import .comment-toggle.active { color: var(--primary-strong); }
.table.table-import .comment-toggle.has-comment { color: var(--primary-strong); }
.table.table-import .comment-toggle:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 1px; }
/* Строка с полем примечания: во всю ширину таблицы, компактная, как .row-raw. */
.table.table-import tr.row-comment-form td {
  background: var(--bg-surface-secondary);
}
/* Кнопка inline-выбора в превью импорта (счёт/категория): внешне как select,
   но открывает всплывающий список с поиском (нативный select искать не умеет). */
.table.table-import .inline-pick {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  font-family: inherit;
  text-align: left;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.table.table-import .inline-pick:hover { border-color: var(--primary-strong); }
.table.table-import .inline-pick:disabled { cursor: default; opacity: 0.85; }
.table.table-import .inline-pick .inline-pick-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.table.table-import .inline-pick.is-empty { color: var(--muted); }
.table.table-import .inline-pick-caret { flex: 0 0 auto; color: var(--muted); font-size: 11px; }
/* Колонка Merchant / Описание: длинный текст (абонентки Тинькофф,
   штрафы ГИБДД) переносится, не обрезается. */
.table.table-import td.merchant-cell {
  max-width: 360px;
  word-break: break-word;
  white-space: normal;
  line-height: 1.3;
}
/* Для transfer-строк два счёта показываем ДРУГ НАД ДРУГОМ с подписями
   (Списание / Зачисление) — в ячейке таблицы так читается лучше, чем в строку. */
.table.table-import td.account-cell {
  white-space: nowrap;
}
.table.table-import td.account-cell select {
  display: inline-block;
  vertical-align: middle;
}
.table.table-import .transfer-accounts {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.table.table-import .transfer-account-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.table.table-import .transfer-account-label {
  flex: 0 0 auto;
  width: 72px;
  color: var(--muted);
  font-size: 11px;
}
.table.table-import .transfer-account-row select,
.table.table-import .transfer-account-row .inline-pick {
  flex: 1 1 auto;
  min-width: 0;
}
/* Сумма операций: расход красным, доход зелёным (для столбцов .num в таблицах). */
.num.num-expense { color: var(--danger); }
.num.num-income { color: var(--success); }

/* === Вид операции в превью импорта ===
   Отдельной колонки нет: тип показан иконкой у суммы (цвет наследуется от
   .num-expense/.num-income), редактор раскрывается кликом по иконке. */
.type-toggle {
  border: 0;
  background: none;
  padding: 0 0 0 4px;
  margin: 0;
  color: inherit;          /* красный для расхода, зелёный для дохода */
  cursor: pointer;
  font-size: inherit;      /* кнопки не наследуют шрифт ячейки по умолчанию */
  vertical-align: middle;
  opacity: 0.7;
}
.type-toggle:hover { opacity: 1; }
/* Дубли (уже в БД) не редактируются — иконка вида только для чтения. */
.type-toggle:disabled { cursor: default; opacity: 0.85; }
.table.table-import .row-type {
  display: block;
  margin: 4px 0 0 auto;    /* под суммой, по правому краю (.num → text-align:right) */
}
.table.table-import .row-type[hidden] { display: none; }

/* === Исходные данные строки выписки (кнопка у merchant) ===
   Отдельная <tr> под строкой: исходная CSV-строка или блок текста из PDF. */
.raw-toggle {
  border: 0;
  background: none;
  padding: 0 0 0 6px;
  margin: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: inherit;
  vertical-align: middle;
}
.raw-toggle:hover,
.raw-toggle.active { color: var(--primary-strong); }
.table.table-import tr.row-raw > td {
  background: var(--slate-lt);
  padding: 0;
}
.raw-source {
  margin: 0;
  padding: 8px 10px;
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
  max-height: 220px;
  overflow: auto;
}

/* === Исходные данные выписки в форме операции (.raw-source-block) ===
   Свёрнутый read-only блок: после импорта исходную строку выписки больше
   нигде не видно (в превью она была только до записи), а сверить разбор
   нужно — поэтому храним rawSource и показываем его здесь. Компактно, с
   ограничением высоты и скроллом, чтобы длинная CSV-строка не растягивала
   модалку. */
.raw-source-block {
  margin: 4px 0 12px;
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-surface-secondary);
}
.raw-source-block > summary {
  padding: 8px 10px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}
.raw-source-block > summary:hover { color: var(--text); }
.raw-source-block[open] > summary { border-bottom: 1px solid var(--border-color-light); }
.raw-source-text {
  margin: 0;
  padding: 8px 10px;
  max-width: 100%;
  max-height: 220px;
  overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}


/* === Toggle (сегментированный переключатель) === */
.toggle-group {
  display: flex;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
}
.toggle-segment {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.toggle-label {
  flex: 1;
  text-align: center;
  min-height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  border-right: 1px solid var(--border);
  transition: background 0.1s, color 0.1s;
  user-select: none;
}
.toggle-label:last-of-type { border-right: none; }
.toggle-segment:checked + .toggle-label {
  background: var(--accent);
  color: white;
}
.toggle-label:hover {
  background: var(--primary-lt);
}
.toggle-segment:checked + .toggle-label:hover {
  background: var(--accent-hover);
}
.toggle-segment:focus-visible + .toggle-label {
  outline: 2px solid var(--primary-strong);
  outline-offset: -2px;
}

/* === Category Select (кастомный dropdown с FA-иконками) === */
.category-select { position: relative; }
.category-select-trigger {
  width: 100%;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 12px;
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.category-select-trigger:hover { border-color: var(--primary); }
.category-select-trigger:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}
.category-select-trigger.is-empty { color: var(--muted); }
.category-select-display {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.category-select-display .fa { width: 16px; text-align: center; color: var(--muted); }
.category-select-caret { color: var(--muted); font-size: 12px; }
.category-select-dropdown {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  z-index: 50;
}
.category-select-dropdown.flip-up {
  top: auto;
  bottom: calc(100% + 2px);
}
/* .category-select .category-select-search — чтобы базовое `.form-field input`
   (класс+тип, специфичнее одного класса) не навязывало поиску полную рамку
   вместо одной нижней. */
.category-select .category-select-search {
  display: block;
  width: 100%;
  height: 36px;
  padding: 0 10px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
  outline: none;
  box-sizing: border-box;
}
.category-select-search:focus { border-bottom-color: var(--primary-strong); }
.category-select-search::placeholder { color: var(--muted); }
.category-select-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  cursor: pointer;
  font-size: 14px;
  color: var(--text);
  user-select: none;
}
.category-select-option:hover { background: var(--primary-lt); color: var(--accent); }
.category-select-option.is-selected {
  background: rgba(26,187,156,0.16);
  color: var(--accent);
  font-weight: 500;
}
.category-select-option .fa { width: 16px; text-align: center; color: var(--muted); }
.category-select-option:hover .fa,
.category-select-option.is-selected .fa { color: var(--accent); }

/* === Combobox === */
.combobox { position: relative; width: 100%; }
/* .form-field .combobox-input (а не просто .combobox-input): базовое правило
   `.form-field input { padding: 0 12px }` специфичнее классового и иначе
   съедало бы правый отступ под стрелку. */
.form-field .combobox-input {
  width: 100%;
  box-sizing: border-box;
  padding-right: 28px;
}
.combobox-dropdown {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  z-index: 50;
}
.combobox-option {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 14px;
  color: var(--text);
  user-select: none;
}
.combobox-option[hidden] { display: none; }
.combobox-option.active,
.combobox-option:hover {
  background: var(--primary-lt);
  color: var(--accent);
}
.combobox-empty {
  padding: 8px 12px;
  font-size: 13px;
  color: var(--muted);
  font-style: italic;
}
/* Стрелочка справа */
.form-field:has(.combobox-input) { position: relative; }
.form-field:has(.combobox-input)::after {
  content: '';
  position: absolute;
  right: 14px;
  top: calc(50% + 8px);
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--muted);
  pointer-events: none;
}

/* === Icon picker === */
.icon-picker { margin-top: 8px; }
.icon-picker-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.icon-picker-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  color: var(--muted);
  cursor: pointer;
  margin-bottom: -1px;
  transition: color 0.1s, border-color 0.1s;
}
.icon-picker-tab:hover { color: var(--text); }
.icon-picker-tab.active {
  color: var(--primary-strong);
  border-bottom-color: var(--primary-strong);
}
.icon-picker-pane { display: none; }
.icon-picker-pane.active { display: block; }
.icon-picker-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 4px;
  max-height: 180px;
  overflow-y: auto;
  padding: 4px;
  background: var(--bg-surface-secondary);
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.icon-picker-btn {
  aspect-ratio: 1;
  border: 1.5px solid transparent;
  background: var(--surface);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 14px;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.1s;
  padding: 0;
  line-height: 1;
}
.icon-picker-btn:hover {
  color: var(--primary-strong);
  border-color: var(--border);
  transform: scale(1.1);
}
.icon-picker-btn.selected {
  color: var(--primary-strong);
  border-color: var(--primary-strong);
  background: var(--primary-lt);
}
.icon-picker-emoji {
  font-size: 18px;
  line-height: 1;
  /* Цветные эмодзи — не наследуем color, чтобы не терять полноцветность */
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}

/* === Color picker === */
.color-picker { display: flex; flex-direction: column; gap: 10px; }
.color-palette { display: grid; grid-template-columns: repeat(6, 28px); gap: 8px; }
.color-swatch {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  border: 1.5px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: transform 0.1s, border-color 0.1s;
  box-shadow: var(--shadow);
}
.color-swatch:hover { transform: scale(1.12); }
.color-swatch.selected {
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 2px var(--primary-ring);
}
.color-custom { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.color-custom input[type="color"] {
  width: 36px;
  height: 28px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  background: var(--surface);
}
/* Селектор с .form-field — иначе базовое `.form-field input` перебивает
   это правило по специфичности (класс+тип против класса). */
.form-field .color-hex {
  width: 96px;
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 13px;
  background: var(--surface);
  color: var(--text);
}
.color-hex:focus { outline: none; border-color: var(--primary-strong); box-shadow: 0 0 0 3px var(--primary-lt); }
.form-field-color { align-items: stretch; }

/* === Modal === */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  animation: fadeIn 0.15s ease;
}
@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px;
  max-width: 480px;
  width: calc(100% - 32px);
  box-shadow: var(--shadow-modal);
  animation: slideUp 0.2s cubic-bezier(0.2, 0, 0, 1);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}
@keyframes slideUp { from { transform: translateY(8px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }
.modal-title { font-size: 15px; font-weight: 600; letter-spacing: -0.1px; margin: 0 0 16px; }
/* Широкая модалка: 520px вместо 480 — на две колонки полей (карты счёта). */
.modal-wide { max-width: 520px; }
.form-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.form-field label { font-size: 12px; color: var(--text); font-weight: 500; }
.form-field input, .form-field select, .form-field textarea {
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.form-field select { cursor: pointer; }
.form-field input:focus, .form-field select:focus, .form-field textarea:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}
/* textarea/checkbox не могут нести фиксированную height — снимаем её. */
.form-field textarea { height: auto; min-height: 90px; padding: 8px 12px; resize: vertical; line-height: 1.5; }
.form-field input[type="checkbox"] { width: 18px; height: 18px; padding: 0; }
.modal-form { display: flex; flex-direction: column; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }
.form-error {
  color: var(--danger);
  font-size: 12px;
  margin-bottom: 12px;
  padding: 8px 12px;
  background: var(--red-lt);
  border: 1px solid var(--red-ring);
  border-radius: var(--radius-sm);
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* === Page header === */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.page-header h2 { margin: 0; font-size: 16px; font-weight: 600; }

/* Page actions (только кнопка справа, без h2) */
.page-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-bottom: 16px;
}

/* === Filters bar (над таблицей) === */
.filters-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  margin-bottom: 12px;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.filters-bar .filter {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 140px;
}
.filters-bar .filter > span {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.3px;
}
.filters-bar select {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
}
.filters-bar select:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}
/* Инлайн-вариант: компактная строка фильтров прямо в тулбаре, в одном стиле
   с .page-summary (страница «Операции»). Без карточки — только поля. */
.filters-bar--inline {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-bottom: 0;
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}
.filters-bar--inline .filter {
  flex-direction: row;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.filters-bar--inline .filter > span {
  font-size: 13px;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  color: var(--muted);
}
.filters-bar--inline input,
.filters-bar--inline select {
  height: 32px;
  padding: 0 8px;
  font-size: 13px;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
}
.filters-bar--inline input[type="date"] { width: 138px; }
.filters-bar--inline input[type="text"] { width: 150px; }
.filters-bar--inline input:focus,
.filters-bar--inline select:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}

/* Контейнер .table-section оборачивает фильтры + таблицу, чтобы можно
   было перерисовать только эту часть при изменении фильтра. */
.table-section { display: contents; }

/* === Toolbar (итоги/фильтры/переключатель слева + actions справа) === */
.page-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
/* Внутри тулбара .page-actions не создаёт отдельную строку и не тянет отступ. */
.page-toolbar .page-actions {
  margin-bottom: 0;
  flex: 0 0 auto;
  margin-left: auto;
}
/* Тулбар страницы «Операции»: фильтры и кнопка «+ Добавить» — в одной строке,
   кнопка идёт сразу за фильтрами (внутри .filters-bar--inline), без прижатия
   к правому краю. */
.page-toolbar--filters { justify-content: flex-start; }
.page-toolbar--filters .filters-bar--inline { flex: 1 1 auto; }
/* Компактная строка итогов слева в тулбаре (напр. «Активных 4 · В месяц … »). */
.page-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  min-width: 0;
}
.page-summary-label { color: var(--muted); }
.page-summary-value { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.page-summary-sep { color: var(--muted); opacity: 0.6; }
/* Обёртка одного показателя («Итого 1 234,00 ₽»): label и value держим одним
   флекс-элементом, чтобы при переносе строки они не разъезжались по разным.
   Раньше класс был в разметке, но без стилей (DESIGN.md §5.1). */
.page-summary-item {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  min-width: 0;
}
.view-mode-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
}
.view-mode-toggle .view-mode-btn {
  border: none;
  border-radius: 0;
  background: transparent;
  min-height: 30px;
  padding: 6px 14px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.view-mode-toggle .view-mode-btn:hover { background: var(--hover); color: var(--text); }
.view-mode-toggle .view-mode-btn.active {
  background: var(--accent);
  color: white;
}
.view-mode-toggle .view-mode-btn.active:hover { background: var(--accent-hover); }
.view-mode-toggle .view-mode-btn + .view-mode-btn { border-left: 1px solid var(--border); }

/* === Import menu (dropdown на кнопке «Импорт из брокера») === */
.import-menu { position: relative; display: inline-block; }
.import-menu-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 280px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  padding: 4px;
  z-index: 50;
}
.import-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.1s;
}
.import-menu-item:hover { background: var(--primary-lt); }
/* «Загрузить по всем счетам» — первый пункт меню, отделён от списка счетов. */
.import-menu-item-all {
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  margin-bottom: 2px;
}
.import-menu-item-all .import-menu-item-title { color: var(--accent); font-weight: 600; }
.import-menu-item-title { font-size: 13px; font-weight: 500; color: var(--text); }
.import-menu-item-sub { font-size: 11px; color: var(--muted); margin-top: 2px; }
.import-menu-item-sub code { font-size: 11px; padding: 0 4px; background: var(--bg); border-radius: 3px; }
.import-menu-empty, .import-menu-error {
  padding: 12px;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}
.import-menu-error { color: var(--danger); }
/* Группа с вложенным меню (Т-Инвестиции: «загрузить новые» + «загрузить
   историю»). Контейнер — div вместо button, чтобы вложенные <button> не лежали
   внутри другого <button> (HTML-инвалид, у некоторых браузеров ломаются клики). */
.import-menu-item-group {
  cursor: default;
}
.import-menu-item-group:hover { background: transparent; }
/* Строка пункта: заголовок брокера слева, кнопка-переключатель «Загрузить ▾»
   справа (напротив названия). */
.import-menu-item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.import-menu-item-headtext { min-width: 0; }
.import-menu-item-head .import-menu-item-title { display: block; }
.import-menu-item-head .import-menu-item-sub { display: block; }
.import-submenu-toggle { white-space: nowrap; }
/* Раскрытый подсписок действий внутри пункта: лёгкая «врезка» на --bg,
   чтобы отличалась от фона самого дропдауна (--surface). */
.import-submenu {
  margin-top: 6px;
  padding: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.import-submenu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 7px 9px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.1s;
}
.import-submenu-item:hover { background: var(--primary-lt); }
.import-submenu-item-title { display: block; font-size: 13px; font-weight: 500; color: var(--text); }
.import-submenu-item-sub { display: block; font-size: 11px; color: var(--muted); margin-top: 2px; }

/* === Account cards (PAN-маски) === */
.cards-badge {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}
.cards-badge:hover { text-decoration: underline; }
.cards-list {
  margin-top: 6px;
  padding: 6px 10px;
  background: var(--bg-surface-secondary);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Авторский display у .cards-list перебивает UA-правило [hidden]{display:none},
   поэтому список карт нужно скрывать явно — иначе он виден всегда. */
.cards-list[hidden] { display: none; }
.cards-list-item .muted { color: var(--muted); }
/* Каретка у числа карт: ▸ свёрнуто, ▾ развёрнуто. */
.cards-badge-caret { display: inline-block; width: 10px; color: var(--muted); }

/* === Tree view (портфель деревом) === */
.tree-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: auto;
  box-shadow: var(--shadow);
  flex: 1 1 auto;
  min-height: 0;
  padding: 4px 0;
}
.tree-group-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 12px;
  cursor: pointer;
  user-select: none;
  background: var(--hover-soft);
  border-bottom: 1px solid var(--border);
  font-weight: 500;
  font-size: 13px;
  transition: background 0.1s;
}
.tree-group-header:hover { background: var(--primary-lt); }
.tree-group-header .tree-caret {
  font-size: 10px;
  color: var(--muted);
  width: 12px;
  flex-shrink: 0;
}
.tree-group-header .tree-group-label {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tree-group-header .tree-group-metrics {
  margin-left: auto;
  display: flex;
  gap: 12px;
  font-weight: 400;
  font-size: 12px;
  flex-shrink: 0;
}
.tree-group-header .tree-group-metric .muted { color: var(--muted); margin-right: 4px; }
.tree-group-children { padding-left: 20px; }
/* Позиция в дереве — вертикальная карточка: шапка (тикер + название),
   затем поля друг под другом. Так читается лучше, чем строка из 5 колонок. */
.tree-leaf {
  padding: 8px 12px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.tree-leaf:last-child { border-bottom: none; }
.tree-leaf-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  margin-bottom: 4px;
}
.tree-leaf-ticker { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 600; white-space: nowrap; }
.tree-leaf-name { color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.tree-leaf-fields { display: flex; flex-direction: column; gap: 2px; }
.tree-leaf-field { display: flex; align-items: baseline; gap: 8px; }
.tree-leaf-label { color: var(--muted); font-size: 12px; flex: 0 0 auto; }
.tree-leaf-qty,
.tree-leaf-value,
.tree-leaf-profit {
  margin-left: auto;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* === Settings page: компактная таблица категорий ===
   Раньше padding 8px12px, hex-код в колонке «Цвет», плюс здоровенная карточка
   «Категорий N/из M» сверху. Из-за этого помещалось 5 категорий. Теперь — до 12. */
.table-compact th, .table-compact td { padding: 5px 10px; font-size: 13px; }
.table-compact th { font-size: 10px; }
.cat-color-swatch {
  display: inline-block;
  width: 14px; height: 14px;
  border-radius: 3px;
  border: 1px solid var(--border);
  vertical-align: middle;
}
/* Тег-тип категории (Расход/Доход) вместо простого текста. */
.cat-type {
  display: inline-block;
  padding: 1px 7px;
  border-radius: var(--radius-sm);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.cat-type-expense { background: var(--red-lt); color: var(--danger); }
.cat-type-income  { background: var(--green-lt); color: var(--success); }
/* Заголовок секции с inline-действиями справа («Категории 16 · Экспорт · + Добавить»). */
.section-title-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.section-title-actions { display: inline-flex; gap: 8px; }
.muted-inline { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: 4px; }
/* Inline-empty для случая «список пуст» внутри секции настроек (без рамки/тени). */
.empty-inline {
  padding: 16px;
  background: var(--bg-surface-secondary);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-size: 13px;
  line-height: 1.6;
}
.empty-inline code { font-size: 12px; padding: 1px 4px; background: var(--surface); border-radius: var(--radius-sm); }

/* === Mini-dashboard (агрегаты по группам, над таблицей) ===
   Компактный вид: одна строка на группу (брокер/счёт), без «карточных» отступов. */
.dashboard-section { margin-bottom: 8px; }
.dashboard-section-title {
  font-size: 12px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.4px;
  margin-bottom: 4px;
}
/* Кликабельный заголовок секции дашборда: chevron + название,
   hover/aria/focus — как у дропдауна. */
.dashboard-section-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  margin-left: -6px;
  margin-bottom: 4px;
  user-select: none;
  transition: background 0.1s;
}
.dashboard-section-toggle:hover { background: var(--hover); color: var(--text); }
.dashboard-section-toggle:focus-visible { outline: 2px solid var(--primary-strong); outline-offset: 1px; }
.dashboard-section-toggle .fa { font-size: 10px; width: 10px; text-align: center; }
.dashboard-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 6px 10px;
}
/* Карточка группы — компактная строка: «Брокер  Позиций N  Стоимость …  Прибыль …». */
.dashboard-card {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
}
.dashboard-card-title {
  font-size: 13px;
  font-weight: 600;
  margin: 0;
  color: var(--text);
}
.dashboard-metric {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-size: 12px;
  margin: 0;
}
.dashboard-metric-label { color: var(--muted); }
.dashboard-metric-value { font-variant-numeric: tabular-nums; font-weight: 500; }

/* === Responsive === */
/* Дашборд: на узких экранах 5 колонок слишком мелкие — 3, затем 2 и 1. */
@media (max-width: 1280px) {
  .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
  /* minmax(0, 1fr), а не 1fr: `1fr` — это minmax(auto, 1fr), и грид-трек
     не может сжаться ниже min-content широкого ребёнка (таблица, дерево).
     Вместе с body { overflow-x: hidden } это отрезало правую часть контента
     без возможности доскроллить: на портфеле .app раздувался до 1520px при
     вьюпорте 768px. С minmax(0, 1fr) трек держит ширину, а скроллит уже
     .table-wrap / .tree-wrap внутри (у них overflow: auto). */
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar { display: none; }
  .topbar { padding: 0 16px; }
  .view { padding: 16px; }
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
}

/* === Классы, заменившие inline-стили в вьюхах ===
   Раньше эти свойства писались прямо в разметке (`style="..."`). Вынесены
   в CSS: цвета и радиусы должны идти через токены, а не дублироваться в JS
   (AGENTS.md §3/§4). Порядок объявлений сохранён 1:1, поведение не менялось. */

/* CTA внутри .empty («+ Добавить счёт», «Сбросить фильтры»).
   Раньше margin-top был 16px и 12px в двух местах — сведён к 16px. */
.empty-actions { margin-top: var(--space-4); }

/* Инпут inline-правки комментария в строке таблицы (transactions.js).
   Ячейка таблицы, не .form-field, поэтому стили свои и плотные. */
.comment-input {
  width: 100%;
  height: auto;
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 13px;
  background: var(--surface);
  color: var(--text);
}
.comment-input:focus {
  outline: none;
  border-color: var(--primary-strong);
  box-shadow: 0 0 0 3px var(--primary-lt);
}

/* Итоговая строка таблицы («Итого» в accounts.js и simple-list.js).
   background — токен --hover-soft вместо хардкода rgba(0,0,0,0.02). */
.table-total-row { font-weight: 600; background: var(--hover-soft); }

/* Отступ у ссылки «К импорту →» внутри .rules-intro (import-rules.js) —
   вместо inline margin-left. Правило на потомка, а не класс: ссылка там одна. */
.rules-intro a { margin-left: var(--space-2); }

/* === Модалка «Карты счёта» (accounts.js) ===
   Пересобрана на openModal({ body }): нужен динамический список карт и
   собственная форма добавления, чего декларативные поля не умеют. Раньше весь
   диалог собирался вручную, с ~10 инлайн-стилями. */
.cards-manager-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);              /* было 6px инлайном — ближайший шаг шкалы */
  margin-bottom: var(--space-4);
}
.cards-manager-label { font-size: 12px; color: var(--muted); }
.cards-manager-empty { font-size: 13px; color: var(--muted); margin-bottom: var(--space-3); }
/* Форма добавления карты: строка из двух полей и кнопки. */
.cards-add-form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: flex-end;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
/* Поля внутри неё тянутся, но не сжимаются ниже 160px, и без нижнего отступа —
   строка выравнивается по нижнему краю кнопки (было inline flex/min-width/margin). */
.cards-add-form .form-field { flex: 1 1 160px; margin: 0; }
.cards-note { font-size: 12px; color: var(--muted); margin-top: var(--space-3); line-height: 1.5; }

/* Приглушённый текст. До этого .muted был определён ТОЛЬКО в составных
   селекторах (.cards-list-item .muted, .tree-group-header .tree-group-metric .muted),
   хотя применяется и как самостоятельный класс — там он не давал ничего. */
.muted { color: var(--muted); }

/* Цветовой маркер счёта (10px круг в accounts.js). Цвет приходит из данных
   пользователя, поэтому ставится валидированным (api.js → cssColor), а не
   классом; класс держит геометрию. Раньше здесь был хардкод #999 в fallback. */
.acc-color-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: var(--space-2);
  vertical-align: middle;
}

/* Строка карты в модалке «Карты счёта» (accounts.js). Вынесена из inline —
   там был захардкожен border-radius: 6px в обход токена --radius. */
.card-manager-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* Маска карты: моно-шрифт из токена. Раньше inline-стек
   ui-monospace,Menlo,monospace дублировал --font-mono. */
.card-pan { font-family: var(--font-mono); font-size: 14px; }

/* === Всплывающий список категорий в превью импорта (inline, с поиском) ===
   Кладётся в document.body с position: fixed, чтобы не обрезался
   overflow: auto у .table-wrap; позицию считает JS от кнопки строки.
   Класс .category-select нужен, чтобы поле поиска получило стиль из блока
   .category-select выше (там же оформлены .category-select-option). */
.inline-pick-popover {
  position: fixed;
  /* Слой dropdown'ов (DESIGN.md §2.7): выше контента и sticky-шапки,
     ниже toast (100) и модалок (200). */
  z-index: 50;
  display: flex;
  flex-direction: column;
  max-height: 260px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}
.inline-pick-list {
  flex: 1 1 auto;
  overflow-y: auto;
  /* Прокрутка списка не должна «протекать» в таблицу (иначе вместе со
     списком уезжает и кнопка-якорь). */
  overscroll-behavior: contain;
}
.inline-pick-empty {
  padding: 10px 12px;
  font-size: 13px;
  color: var(--muted);
}

/* === Настройки: таблицы без фиксированной высоты ===
   На /settings несколько таблиц подряд (категории, архив, интеграции).
   На остальных страницах .table-wrap — flex-ребёнок .view с flex:1 1 auto,
   поэтому он растягивается на остаток высоты и скроллится ВНУТРИ себя.
   В настройках это не нужно: таблицы должны расти по содержимому, а
   прокручиваться — страница целиком (.view). Обёртка .settings-page не
   флекс-контейнер, так что flex у .table-wrap не действует; правила явные,
   чтобы поведение не сломалось, если обёртку когда-нибудь сделают flex. */
.settings-page .table-wrap {
  flex: 0 0 auto;
  min-height: auto;
}

/* === Импорт выписки: колонка с номером строки превью ===
   Номера строк нужны, чтобы соотносить таблицу с подсказкой
   «Заполните данные: строки N» и модалкой «применить к похожим» — там
   номера и раньше были (idx + 1), но в самой таблице их не было видно. */
.table.table-import .row-num {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* === Отчёты и графики (reports.js) ===
   Страница /reports: 4 карточки-итога, две диаграммы на чистом inline-SVG
   (группированные столбцы + donut на <circle>) и таблицы структуры.
   Диаграмм в проекте раньше не было, поэтому классы новые; цвета — только
   токены, динамические цвета категорий подставляются через cssColor(). */

/* 4 карточки в строке (доходы/расходы/сальдо/операций). В остальном это тот
   же .card; брейкпоинты повторяют поведение .cards из секции Responsive. */
.cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Кнопка «Сбросить» в фильтр-баре скрывается атрибутом hidden, но .btn задаёт
   свой display, который перебивает UA-правило [hidden] — возвращаем скрытие. */
.filters-bar .btn[hidden] { display: none; }

/* Контейнер двух диаграмм: 2 колонки, на узких — одна. */
.report-charts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.chart-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  box-shadow: var(--shadow);
  min-width: 0;
}
.chart-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.chart-title { font-size: 13px; font-weight: 600; color: var(--text); }

/* Горизонтальный скролл: при 12+ месяцах/категориях столбцы не сжимаются
   до нечитаемых, а прокручиваются внутри блока. */
.chart-wrap { overflow-x: auto; overflow-y: hidden; }
.chart-svg { display: block; max-width: none; }
.chart-svg .chart-axis-label { fill: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-svg .chart-grid-line { stroke: var(--border-color-light); stroke-width: 1; }
.chart-svg .chart-bar-income { fill: var(--success); }
.chart-svg .chart-bar-expense { fill: var(--danger); }

.chart-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 180px;
  color: var(--muted);
  font-size: 13px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

/* Donut: кольцо + легенда рядом. */
.chart-donut-body { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.chart-svg .chart-donut-track { stroke: var(--bg-surface-secondary); }
.chart-svg .chart-donut-value { fill: var(--text); font-size: 4.2px; font-weight: 600; }
.chart-svg .chart-donut-caption { fill: var(--muted); font-size: 2.6px; }

.chart-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 220px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
}
.chart-legend-item { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; }
.chart-legend-marker { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 2px; align-self: center; }
.chart-legend-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chart-legend-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
.chart-legend-share { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; min-width: 42px; text-align: right; }
/* Легенда столбчатой диаграммы (2 пункта) — в строку, под графиком. */
.chart-legend--inline { flex-direction: row; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-2); max-height: none; }

/* Доля категории в таблице структуры: полоска + процент. */
.share-bar { display: flex; align-items: center; gap: 8px; min-width: 120px; }
.share-bar-track { flex: 1 1 auto; height: 6px; border-radius: 999px; background: var(--bg-surface-secondary); overflow: hidden; }
.share-bar-fill { height: 100%; border-radius: 999px; background: var(--accent); }
.share-bar-pct { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 46px; text-align: right; }

/* У отчёта две таблицы под графиками. .table-wrap по умолчанию — flex-ребёнок
   .view с flex: 1 1 auto и скроллится внутри себя; здесь нужен обычный поток
   (скроллится вся страница), иначе обе таблицы делят остаток высоты и
   схлопываются. Тот же приём, что у .settings-page. */
.reports-page .table-wrap {
  flex: 0 0 auto;
  min-height: auto;
  margin-bottom: var(--space-5);
}

@media (max-width: 1280px) {
  .cards--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  .report-charts { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px) {
  .cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .cards--4 { grid-template-columns: minmax(0, 1fr); }
}

/* === Портфель: ретроспектива стоимости (ui/js/views/portfolio.js) === */
/* Линейный график (value/invested) — в отличие от столбцов/donut на /reports
   потомковые классы для линий, заливки и точек нужны именно здесь. */
.chart-svg .chart-line-value { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-svg .chart-line-invested { fill: none; stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 4 3; stroke-linejoin: round; }
.chart-svg .chart-area-value { fill: var(--accent); opacity: 0.08; }
.chart-svg .chart-dot-value { fill: var(--accent); }
/* Подпись о днях без котировок (fallback на среднюю цену покупки). */
.portfolio-note {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-left: 3px solid var(--warning);
  border-radius: var(--radius);
  background: var(--bg-surface-secondary);
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.4;
  cursor: help;
}
/* У .view-mode-toggle свой display:flex, поэтому атрибут [hidden] его не прячет. */
.portfolio-periods[hidden] { display: none; }
.portfolio-page { min-width: 0; }

/* === Живые подсказки и хит-зоны диаграмм (ui/js/ui/chartTooltip.js) ===
   Тултип — fixed в document.body (как .inline-pick-popover), чтобы его не
   обрезал overflow: auto у .chart-wrap. Слой 60: выше dropdown (50), ниже
   toast (100) и модалок (200) — см. DESIGN.md §2.7. */
.chart-tooltip {
  position: fixed;
  z-index: 60;
  max-width: 280px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop);
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.45;
  pointer-events: none; /* тултип не должен сам перехватывать курсор */
}
.chart-tooltip-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  margin-bottom: 4px;
}
.chart-tooltip-head[hidden] { display: none; }
.chart-tooltip-head.has-marker::before {
  content: '';
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--tip-color, transparent);
}
.chart-tooltip-row { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Хит-зоны: прозрачные, но ловят курсор — попадать в 13px-столбик неудобно. */
.chart-svg .chart-hit { fill: transparent; pointer-events: all; }
.chart-svg .chart-band { cursor: pointer; }
.chart-svg .chart-band:hover .chart-bar-income,
.chart-svg .chart-band:hover .chart-bar-expense { opacity: 0.8; }

/* Donut: сегмент и строка легенды подсвечиваются взаимно (data-seg). */
.chart-svg .chart-donut-seg { cursor: pointer; transition: stroke-width 0.1s; }
.chart-svg .chart-donut-seg.is-active { stroke-width: 8; }
.chart-legend-item[data-seg] { cursor: pointer; }
.chart-legend-item.is-active .chart-legend-name { font-weight: 600; color: var(--text); }

/* Линейный график: перекрестие и маркер ближайшей точки. */
.chart-svg .chart-crosshair { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.chart-svg .chart-dot-hover { fill: var(--surface); stroke: var(--accent); stroke-width: 2; pointer-events: none; }
.chart-svg .chart-dot-value.is-active { fill: var(--accent); }
/* На SVG-элементах [hidden] не прячет (UA-стиль рассчитан на HTML) — дублируем. */
.chart-svg [hidden] { display: none; }

/* === Экран входа (ui/js/views/login.js) ===
   Зачем: при включённой авторизации до входа нельзя показывать каркас
   приложения — сайдбар раскрывает разделы, а топбар содержит переключатели,
   ведущие на защищённые вьюхи. Класс .auth-screen ставит router.js. */
.app.auth-screen { grid-template-columns: minmax(0, 1fr); }
.app.auth-screen .sidebar,
.app.auth-screen .topbar { display: none; }

.login-page {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-4);
}
.login-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: 100%;
  max-width: 340px;
  padding: var(--space-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.login-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
}
.login-sub { margin: 0; font-size: 13px; color: var(--muted); }
.login-card .form-field { margin-bottom: 0; }
.login-card .form-error { margin: 0; }
.login-submit { width: 100%; justify-content: center; }

/* «Выйти» прижат к низу панели: .nav — flex-колонка, margin-top:auto
   сдвигает ссылку под список пунктов, а не в середину. */
.nav a.nav-logout {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--sidebar-border);
  border-radius: 0;
  color: var(--sidebar-text);
}

/* Кто вошёл — чип в шапке рядом с переключателем темы (многопользовательский
   режим). Наследует типографику .topbar-meta (13px, --muted); иконка чуть
   приглушена, чтобы имя читалось как метка, а не как кнопка. */
.topbar-user {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-surface-secondary);
  color: var(--text);
  max-width: 200px;
}
.topbar-user i { opacity: 0.6; font-size: 12px; }
.topbar-user span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
