/* Палитра — валидированные слоты 1–3 (blue/orange/aqua) для комиссий, налогов
   и доходов. Темные шаги подобраны под темную подложку, а не выведены
   автоматической инверсией. */
/* Светлая подложка — холодная, в тон синему акценту (13.09.2026, вариант «C»
   из сравнения на живой странице). Прежний теплый #f4f3f0 спорил с холодным
   синим и рядом с ним желтил, а карточки #fcfcfb отличались от фона на 1,08:1
   и держались одними рамками — страница читалась плоским серым листом. Теперь
   карточки чисто белые, глубину дает тень, рамка у них полупрозрачная.
   Приглушенный текст темнее: #82817c давал 3,8:1 при кегле 11 px. */
:root {
  color-scheme: light;
  --surface-0: #f0f3f7;
  --surface-1: #ffffff;
  --surface-2: #ffffff;
  --border:    #dee2e8;
  --grid:      #eaedf1;
  --text-primary:   #13181e;
  --text-secondary: #51575f;
  --text-muted:     #6e737a;
  --series-fee:    #2a78d6;
  --series-tax:    #eb6834;
  --series-income: #1baf7a;
  --series-rule:   #a8479b;
  /* Линия «LQDT ↔ GOLD» (13.09.2026). Фиолетовый, а не золотой: золотистый
     в темной теме при дальтонизме сливается с оранжевым «Вкладом» и зеленым
     «LQDT» (ΔE 4–5). Этот проверен скриптом палитры по всем парам пяти линий
     в обеих темах и новых провалов не добавляет. */
  --series-pair:   #4a3aa7;
  /* Линия «Лестница» — сохраненные облигации (13.09.2026). В светлой теме
     бордовый, в темной малиновый: один оттенок на обе темы не нашелся.
     Малиновый в светлой сливается с «Моментум+» (#a8479b, ΔE 5), а бордовый
     в темной — с «Вкладом» и «LQDT». Подобраны перебором скриптом палитры из
     навыка dataviz по всем парам шести линий: в светлой худшая пара при
     дальтонизме ΔE 16, в темной 8,3 (с «LQDT»), и прежние провалы темной
     темы новыми не дополнены. */
  --series-ladder: #892934;
  --good:     #0ca30c;
  --critical: #d03b3b;
  --warn-bg:  #fdf6e6;
  /* Тень у кнопок и вкладок — одна строка; у карточек своя, мягкая и
     глубже: одинаковая тень на кнопке выглядела бы тяжелой. */
  --shadow: 0 1px 2px rgba(16,24,40,.05);
  --shadow-card: 0 1px 2px rgba(16,24,40,.04), 0 6px 20px -6px rgba(16,24,40,.08);
  --card-border: rgba(16,24,40,.07);
  /* Подсветка строки при наведении. Раньше это был --surface-2, белый чуть
     белее карточки; на белой карточке он пропал бы совсем. */
  --hover: #f5f7fa;
  /* Свечение под шапкой и стеклянная шапка — только в светлой теме. */
  --page-glow: radial-gradient(1100px 420px at 50% -140px, rgba(42,120,214,.13), transparent 70%);
  --topbar-bg: rgba(255,255,255,.72);
  --topbar-border: rgba(16,24,40,.07);
  /* Стрелка списка цветом --text-muted. Картинка, а не currentColor: у
     <select> нет псевдоэлементов, а в data: URI переменную не подставить. */
  --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236e737a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
/* Тема только системная: ручной выбор светлой или темной убран вместе с
   кнопкой (13.09.2026), и блоков под атрибут data-theme больше нет. */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --surface-0: #121211;
    --surface-1: #1a1a19;
    --surface-2: #232322;
    --border:    #34342f;
    --grid:      #2b2b28;
    --text-primary:   #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted:     #918f85;
    --series-fee:    #3987e5;
    --series-tax:    #d95926;
    --series-income: #199e70;
    --series-rule:   #d183c4;
    --series-pair:   #794cc5;
    --series-ladder: #bb3285;
    --good:     #0ca30c;
    --critical: #d03b3b;
    --warn-bg:  #2a2418;
    --shadow: none;
    --shadow-card: none;
    --card-border: #34342f;
    --hover: #232322;
    --page-glow: none;
    --topbar-bg: #1a1a19;
    --topbar-border: #34342f;
    --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23918f85' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; }
body {
  background: var(--page-glow) no-repeat, var(--surface-0);
  color: var(--text-primary);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1, h2 { margin: 0; font-weight: 600; }
h1 { font-size: 17px; letter-spacing: -.01em; }
h2 { font-size: 13px; color: var(--text-secondary); }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92em; }

/* --- шапка --- */
/* Три колонки, а не space-between: справа контролы периода живут только в
   «Аналитике», и при их исчезновении гибкая раскладка увозила переключатель
   разделов вбок. Центральная колонка держится на месте независимо от боков. */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px;
  padding: 12px 24px;
  /* Полупрозрачная с размытием: прокрученное содержимое проступает под
     шапкой, а не обрезается ее краем. В темной теме подложка сплошная. */
  background: var(--topbar-bg);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--topbar-border);
}
.topbar__title { display: flex; align-items: baseline; gap: 12px; min-width: 0; }
.topbar__title h1 { white-space: nowrap; }
/* Знак продукта перед названием (14.09.2026, выбран из пяти вариантов): тот же
   рисунок, что у иконки вкладки и ярлыка, в цветах кнопки вкладки своей темы.
   Цвета — переменными, а не атрибутами, как в favicon.svg: встроенный в
   страницу знак следует теме сам. Рамка не масштабируется вместе с рисунком,
   иначе на 26 px она истончалась бы до 0,8 px и была бы бледнее рамок кнопок.
   Отрицательный отступ сводит общий зазор заголовка к 9 px: знак и название —
   одно слово, а не два соседних элемента. По базовой линии svg не выравнивается
   (его «базовая линия» — нижний край), поэтому центр. */
.brand { flex: none; align-self: center; width: 26px; height: 26px; margin-right: -3px; }
.brand__plate { fill: var(--surface-2); stroke: var(--border); vector-effect: non-scaling-stroke; }
.brand__bars { fill: none; stroke: var(--text-secondary); stroke-width: 3; stroke-linecap: round; }
.topbar__account { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Время обновления стоит в строке заголовка. Под кнопкой «Обновить» оно
   делало правую группу выше остальных, поэтому висело абсолютом, а место под
   него держал увеличенный нижний отступ шапки — двадцать восемь пикселей
   пустоты во всю ширину экрана. Не сжимается: при нехватке места многоточие
   получает название счета, а не время. */
.topbar__updated {
  flex: none; white-space: nowrap;
  font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.badge--demo { flex: none; color: var(--series-tax); border-color: var(--series-tax); }
.tabs { justify-self: center; }
.topbar__actions { justify-self: end; }
/* Панель периода живет в разделе, а не в шапке: в шапке она есть только на
   «Аналитике», и ее появление двигало переключатель разделов. */
.period-bar {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 16px;
}
/* Готовые периоды — список под кнопкой «Период». <details>, а не самодельный
   попап: открытие с клавиатуры и состояние open достаются даром, скрипт только
   закрывает меню щелчком мимо и клавишей Esc. */
.period-menu { position: relative; flex: none; }
.period-menu > summary {
  display: flex; align-items: center; gap: 6px; list-style: none; user-select: none;
}
.period-menu > summary::-webkit-details-marker { display: none; }
.period-menu[open] > summary { border-color: var(--text-muted); }
.period-menu__list {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 30;
  display: flex; flex-direction: column; min-width: 180px; padding: 4px;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.14);
}
.period-menu__list button {
  display: flex; justify-content: space-between; gap: 16px;
  font: inherit; font-size: 13px; text-align: left; padding: 7px 10px; cursor: pointer;
  color: var(--text-primary); background: transparent; border: none; border-radius: 6px;
}
.period-menu__list button:hover,
.period-menu__list button:focus-visible { background: var(--hover); outline: none; }
/* Отметка у выбранного: поля рядом показывают границы, но не то, каким
   готовым периодом они получены. */
.period-menu__list button[aria-current="true"]::after { content: '✓'; color: var(--series-fee); }
/* Телефон: даты и «Период» в одну строку. Поля дат делят остаток ширины и
   сжимаются сами, а не переносят кнопку на следующую строку. */
@media (max-width: 720px) {
  .period-bar { gap: 8px; }
  .period-bar .field { flex: 1 1 0; min-width: 0; }
  .period-bar .field input { flex: 1 1 auto; min-width: 0; width: 100%; }
}
.topbar__account { color: var(--text-muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.topbar__actions { display: flex; align-items: center; gap: 8px; }
/* Кнопка и расписание — одна группа: интервал относится к обновлению. */
.refresh { display: flex; align-items: center; }
.refresh__row { display: flex; align-items: center; gap: 6px; }
.refresh__every {
  /* Высота задана явно: у select своя высота строки, и подгонка отступами
     оставляла его на пару пикселей ниже соседних кнопок. */
  font: inherit; font-size: 13px; height: 34px; cursor: pointer;
  box-sizing: border-box; line-height: 1;
  color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: 6px;
  /* Своя стрелка вместо системной: та прижималась к правому краю, и где она
     стоит, решает браузер. Отступ справа — 12 px до стрелки плюс ее ширина. */
  appearance: none; -webkit-appearance: none;
  padding: 0 32px 0 10px;
  background: var(--surface-2) var(--select-arrow) no-repeat right 12px center / 10px 6px;
}
.refresh__every:hover { color: var(--text-primary); border-color: var(--text-muted); }
.field { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.field input {
  font: inherit; padding: 5px 8px; color: var(--text-primary);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
}
.select {
  font: inherit; font-size: 12px; padding: 4px 8px; cursor: pointer;
  color: var(--text-primary); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 6px;
}
.select:hover { border-color: var(--text-muted); }
/* WebKit (Safari на iPhone) обрезает текст сжатого списка только на экране, а
   в ширину страницы засчитывает полный: «надежнейший по мнению рынка» в поле
   на 107 px раздвигал раздел облигаций до 490 px при экране 430. Chrome так не
   делает, поэтому в его эмуляции телефона этого не видно. */
select { overflow: hidden; text-overflow: ellipsis; }
.btn {
  font: inherit; font-size: 13px; padding: 6px 12px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-primary);
}
.btn:hover { border-color: var(--text-muted); }
.btn--primary { background: var(--series-fee); border-color: var(--series-fee); color: #fff; }
.btn--primary:hover { filter: brightness(1.08); }
.btn--primary:disabled { opacity: .55; cursor: default; filter: none; }
.btn:disabled { cursor: default; }
/* Кнопка-значок в шапке: колокольчик уведомлений рядом с «Обновить». */
.btn--icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; flex: none; color: var(--text-secondary);
}
.btn--icon:hover { color: var(--text-primary); }
.btn__icon {
  display: block; width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
/* Кнопка меню шапки и подписи внутри меню нужны только телефону: на компьютере
   список, «Обновить» и колокольчик стоят в строке и объясняют себя сами.
   Правило стоит после .btn--icon, иначе его display перебил бы скрытие. */
.topbar__menu, .refresh__caption, .refresh__account, .topbar__actions .btn__text { display: none; }
.refresh__field { display: contents; }

/* --- индикатор синхронизации --- */
/* Шкала загрузки вместо журнала строк (13.09.2026, просьба пользователя):
   «Котировки каталога 60/153: 8 свечей» ни на какой вопрос не отвечало, а
   «сколько осталось» из него не читалось. Процент считает сервер.
   Подложка — полосой во всю ширину окна, а сама шкала — шириной тела сайта:
   боковые поля повторяют main (1180 px и поля по 24), и процент слева и конец
   линии справа стоят ровно по краям карточек. */
.syncbar {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px max(24px, calc((100% - 1180px) / 2 + 24px));
  background: var(--surface-2);
  border-bottom: 1px solid var(--border); font-size: 12px; color: var(--text-secondary);
}
/* В разделах шкала стоит между карточками и выглядит как они: полосой во всю
   ширину окна она остается только под шапкой. */
main .syncbar {
  margin-bottom: 16px; padding: 12px 16px;
  border: 1px solid var(--card-border); border-radius: 12px; box-shadow: var(--shadow-card);
}
.syncbar__title { color: var(--text-primary); font-weight: 500; }
.progress { display: flex; align-items: center; gap: 10px; }
.progress__track {
  flex: 1; height: 6px; border-radius: 3px; overflow: hidden; background: var(--border);
}
.progress__fill {
  width: 0; height: 100%; border-radius: inherit; background: var(--series-fee);
  transition: width .4s ease-out;
}
.progress--failed .progress__fill { background: var(--critical); }
/* Слева — неподвижное начало шкалы «0 %», справа — сколько загружено.
   Ширина правой подписи — под «100 %»: иначе конец линии сдвигался бы с
   каждой цифрой. */
.progress__min { flex: none; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.progress__value {
  flex: none; min-width: 5ch; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--text-secondary);
}
@media (prefers-reduced-motion: reduce) { .progress__fill { transition: none; } }

main { max-width: 1180px; margin: 0 auto; padding: 20px 24px 56px; }
section { margin-bottom: 16px; }

/* --- герой и плитки --- */
/* Колонки сеток — minmax(0, …), а не голый 1fr: у того нижняя граница равна
   ширине содержимого. График, нарисованный в скрытом разделе, берет запасную
   ширину 520 px; в одноколоночной сетке телефона он раздвигал общую колонку,
   сосед при перерисовке мерил уже ее и рисовался теми же 520, и дальше они
   держали друг друга — страница ездила вбок до перезагрузки. */
.hero-row { display: grid; grid-template-columns: minmax(240px, 1fr) minmax(0, 2fr); gap: 16px; }
/* Рамка полупрозрачная: карточку отделяет тень. Цветные рамки карточек
   решения (.stg-verdict, .bnd-ladder, .gp-verdict--*) объявлены ниже и
   перебивают эту порядком в файле. */
.hero, .tile, .card {
  background: var(--surface-1); border: 1px solid var(--card-border);
  border-radius: 12px; box-shadow: var(--shadow-card);
}
.hero { padding: 20px; display: flex; flex-direction: column; justify-content: center; }
.hero__label { font-size: 12px; color: var(--text-secondary); }
.hero__value {
  font-size: 48px; font-weight: 600; line-height: 1.1; margin: 6px 0 4px;
  letter-spacing: -.02em;
}
.hero__note { font-size: 11px; color: var(--text-muted); }
.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.tiles--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tile { padding: 14px 16px; }
/* Подпись — обычный текст, а не flex-строка: в flex цветная точка и «?» не
   сжимаются, а слово переносится только целиком, и в плитке шириной 127 px
   «Дивиденды» вылезало за край, на 320 px — вместе со страницей. Точка и
   кнопка идут потоком и переносятся вместе с текстом. */
.tile__label { font-size: 12px; color: var(--text-secondary); }
.tile__label .dot { margin-right: 7px; vertical-align: middle; }
.tile__value { font-size: 22px; font-weight: 600; margin-top: 6px; letter-spacing: -.01em; }
.tile__note { font-size: 11px; color: var(--text-muted); margin-top: 3px; }
/* Заработок стоит рядом с суммой, но не спорит с ней за внимание: меньше
   кеглем и не жирнее. Неразрывность — чтобы «(+30,35 ₽ · +0,03 %)» не рвалось
   пополам на узкой плитке: перенос уместен перед скобкой, а не внутри нее. */
.tile__delta { font-size: 14px; font-weight: 500; white-space: nowrap; }
.dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.dot--fee { background: var(--series-fee); }
.dot--tax { background: var(--series-tax); }
.dot--income { background: var(--series-income); }
.dot--rule { background: var(--series-rule); }
.dot--pair { background: var(--series-pair); }
.dot--ladder { background: var(--series-ladder); }
.dot--muted { background: var(--text-muted); }
/* Классы вместо inline style: строгий CSP на сервере запрещает style-атрибуты. */
.is-critical { color: var(--critical); }
.hit-area { cursor: crosshair; }
.pos { color: var(--good); }
.neg { color: var(--critical); }
/* Пополнение и вывод различаются только знаком суммы, поэтому цвет берет всю
   строку: у моноширинной колонки типа свой цвет, и он перебивается здесь. */
tr.row--pos td { color: var(--good); }
tr.row--neg td { color: var(--critical); }

/* --- карточки и графики --- */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.card { padding: 16px; }
.card--warn { background: var(--warn-bg); }
/* Перенос нужен узким экранам: в заголовке «Операции» рядом с ним стоит
   выбор категории, и вдвоем они не влезают в ширину телефона. */
.card__head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px; margin-bottom: 12px;
}
.card__note { font-size: 12px; color: var(--text-secondary); margin: 0 0 12px; }
.card__note--warn {
  color: var(--text-primary); background: var(--warn-bg);
  border-radius: 6px; padding: 8px 10px; margin-top: 10px;
}
/* Строка «все линии до налога» под графиками. Видна всегда, а не спрятана в
   пояснение: без нее сравнение «Портфеля» с остальными читалось бы неверно. */
.chart-basis { margin: 10px 0 0; }
.chart { width: 100%; overflow-x: auto; }
.chart svg { display: block; }
/* Последние значения рядов под графиком (узкий экран): у концов линий они
   забирали треть ширины карточки. */
.chart__ends {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 8px 0 12px;
  font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.chart__ends span { display: inline-flex; align-items: center; gap: 6px; }
.chart__ends b { font-weight: 500; color: var(--text-primary); }
.legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--text-secondary); }
.legend span { display: flex; align-items: center; gap: 6px; }
/* Легенда-переключатель: галочка занимает место, поэтому отступ до кружка
   меньше, чем между самими пунктами — иначе строка расползается. */
.legend__item { display: flex; align-items: center; gap: 5px; cursor: pointer; user-select: none; }
.legend__item input { margin: 0; accent-color: var(--series-fee); cursor: pointer; }
.legend__item:has(input:not(:checked)) { color: var(--text-muted); }
.legend__item:has(input:not(:checked)) .dot { opacity: .35; }
.table-view { margin-top: 12px; font-size: 12px; }
.table-view summary { cursor: pointer; color: var(--text-secondary); }
.table-view[open] summary { margin-bottom: 8px; }

/* --- таблицы --- */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--grid); }
th { font-weight: 500; font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--hover); }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; color: var(--text-secondary); }
/* Вторая строка в ячейке: доля под суммой операции. Цвет приглушен, чтобы
   процент не читался как вторая сумма. */
.cell-note { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.empty { color: var(--text-muted); font-size: 13px; padding: 16px 0; }

/* Телефон: операция — две строки вместо пяти колонок. Колонки не помещались
   в ширину экрана: сумма уезжала за край, дата рвалась на четыре строки, а
   таблица распирала карточку и вместе с ней страницу. Сверху — что и сколько,
   снизу — когда и каким типом; заголовки колонок при такой раскладке не нужны,
   каждое значение узнается по виду. */
@media (max-width: 720px) {
  #tableOperations table, #tableOperations tbody { display: block; }
  #tableOperations thead { display: none; }
  #tableOperations tbody tr {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "ticker cat sum" "date type sum";
    column-gap: 10px; row-gap: 2px; padding: 9px 0;
    border-bottom: 1px solid var(--grid);
  }
  #tableOperations tbody tr:last-child { border-bottom: none; }
  #tableOperations td { padding: 0; border: none; }
  #tableOperations .op-ticker { grid-area: ticker; font-weight: 500; }
  #tableOperations .op-cat { grid-area: cat; }
  #tableOperations .op-sum { grid-area: sum; }
  #tableOperations .op-date {
    grid-area: date; font-size: 11.5px; white-space: nowrap; font-variant-numeric: tabular-nums;
  }
  #tableOperations .op-type { grid-area: type; overflow-wrap: anywhere; }
  /* :where обнуляет вес селектора: у пополнений и выводов цвет берет вся
     строка (tr.row--pos td), и приглушенная дата не должна его перебивать. */
  :where(#tableOperations) .op-date { color: var(--text-secondary); }
}

.filters { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  font: inherit; font-size: 12px; padding: 3px 10px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-secondary);
}
.chip[aria-pressed="true"] { background: var(--text-primary); color: var(--surface-1); border-color: var(--text-primary); }
.pager { display: flex; align-items: center; gap: 12px; margin-top: 12px; font-size: 12px; color: var(--text-secondary); }

/* --- экран настройки --- */
.setup {
  background: var(--surface-1); border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: var(--shadow-card); padding: 24px;
}
.setup h2 { font-size: 15px; color: var(--text-primary); margin-bottom: 10px; }
.setup ol { margin: 0; padding-left: 20px; }
.setup li { margin-bottom: 14px; color: var(--text-secondary); }
.setup pre {
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 6px;
  padding: 10px 12px; overflow-x: auto; font-size: 12px; color: var(--text-primary); margin: 8px 0 0;
}
.setup .ok { color: var(--good); font-weight: 500; }
.setup .todo { color: var(--critical); font-weight: 500; }
.setup__accounts { margin-top: 10px; }
.account {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 10px 12px; margin-top: 8px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px; font-size: 13px;
}
.account .mono { margin-left: 8px; }
.account__status { margin-left: 8px; color: var(--text-muted); font-size: 12px; }

/* Пояснительный текст во всю ширину, без потолка в символах: пользователь
   трижды просил растянуть такие блоки по разделам (12–13.09.2026), и
   точечные исключения по разделам заменены общим правилом. */
.footnote { font-size: 12px; color: var(--text-muted); margin: 24px 0 0; }

/* --- сноска «как считается» --- */
.why {
  appearance: none; -webkit-appearance: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 6px; padding: 0;
  flex: none; vertical-align: middle;
  font: 600 10px/1 inherit; font-family: inherit;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid var(--border); border-radius: 50%;
  cursor: help;
}
.why:hover, .why:focus-visible {
  color: var(--surface-1); background: var(--text-secondary);
  border-color: var(--text-secondary); outline: none;
}
.why:focus-visible { box-shadow: 0 0 0 2px var(--surface-1), 0 0 0 4px var(--series-fee); }
h2 .why { margin-left: 7px; }

/* --- подсказка ---
   Выше модального окна (60): значки в карточке выпуска тоже объясняются
   подсказкой, и под затемнением ее не было бы видно. Кликов она не ловит. */
.tooltip {
  position: fixed; z-index: 70; pointer-events: none;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px;
  box-shadow: 0 4px 16px rgba(0,0,0,.14);
  padding: 8px 10px; font-size: 12px; color: var(--text-primary);
  max-width: 260px;
}
.tooltip__title { color: var(--text-secondary); margin-bottom: 5px; }
.tooltip__row { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.tooltip__row + .tooltip__row { margin-top: 3px; }
.tooltip__val { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 500; }
.tooltip--wide { max-width: 340px; padding: 12px 14px; }
.tip-title { font-weight: 600; margin-bottom: 6px; }
.tip-body { margin: 0 0 8px; color: var(--text-secondary); line-height: 1.45; }
.tip-formula {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 5px;
  padding: 6px 8px; margin-bottom: 8px; color: var(--text-primary);
}
.tip-notes { margin: 0; padding-left: 16px; color: var(--text-muted); line-height: 1.45; }
.tip-notes li + li { margin-top: 4px; }
.tip-notes:last-child { margin-bottom: 0; }

/* --- страница входа --- */
.login-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; }
.login {
  width: min(360px, calc(100vw - 32px));
  background: var(--surface-1); border: 1px solid var(--card-border);
  border-radius: 12px; box-shadow: var(--shadow-card); padding: 28px;
}
.login h1 { font-size: 18px; margin-bottom: 6px; }
.login__note { font-size: 12.5px; color: var(--text-secondary); line-height: 1.5; margin: 0 0 18px; }
.login__form { display: flex; flex-direction: column; gap: 12px; }
.login__field { display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.login__field input {
  font: inherit; font-size: 14px; padding: 9px 10px; color: var(--text-primary);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
}
.login__field input:focus-visible { outline: none; border-color: var(--series-fee); }
.login .btn { padding: 9px 12px; font-size: 14px; }
.login__error {
  margin: 14px 0 0; font-size: 12.5px; color: var(--critical);
  background: var(--warn-bg); border-radius: 6px; padding: 8px 10px;
}

.login__forgot { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.login__forgot .login__form { margin-top: 0; }
.login__note--tight { margin: 0; }
.login__link {
  font: inherit; font-size: 12.5px; color: var(--series-fee); background: none; border: 0;
  padding: 0; cursor: pointer; text-align: left;
}
.login__link:hover { text-decoration: underline; }
.login__link:disabled { opacity: .5; cursor: default; }

/* --- переключатель разделов --- */
/* В одну строку это сегментный переключатель: дорожка и сегменты в ней. Текущий
/* Каждая вкладка — отдельная кнопка с рамкой и иконкой, одинаково на телефоне
   и на компьютере (13.09.2026). Сегментный переключатель — надписи в общей
   дорожке — не читался как набор кнопок: кнопкой выглядела только текущая.
   Текущий раздел отмечен акцентом.
   Жирность у текущей не меняется: в широкой шапке вкладки стоят по центру, и
   кнопка, ставшая шире, сдвигала бы соседей. */
.tabs { display: flex; gap: 6px; }
.tab {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: 13px; height: 34px; padding: 0 12px; border-radius: 8px;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  background: var(--surface-2); border: 1px solid var(--border); box-shadow: var(--shadow);
  color: var(--text-primary);
  -webkit-tap-highlight-color: transparent;
  transition: background-color .12s, border-color .12s, color .12s;
}
.tab__icon {
  display: block; width: 15px; height: 15px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  color: var(--text-secondary);
}
/* Наведение — только там, где оно есть: на iPhone :hover залипает после
   касания, и вкладка оставалась бы подсвеченной, уже не будучи текущей. */
@media (hover: hover) {
  .tab:hover { border-color: var(--text-muted); }
}
.tab:active { background: var(--surface-0); }
.tab:focus-visible { outline: 2px solid var(--series-fee); outline-offset: 2px; }
.tab[aria-pressed="true"] {
  background: color-mix(in srgb, var(--series-fee) 14%, var(--surface-2));
  border-color: color-mix(in srgb, var(--series-fee) 60%, var(--border));
  color: var(--text-primary);
}
.tab[aria-pressed="true"]:active { background: color-mix(in srgb, var(--series-fee) 24%, var(--surface-2)); }
.tab[aria-pressed="true"] .tab__icon { color: var(--series-fee); }
.topbar__period { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* --- заголовок раздела --- */
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.section-head__title { font-size: 20px; color: var(--text-primary); letter-spacing: -.01em; }
.section-head__note { font-size: 12px; color: var(--text-muted); margin: 4px 0 0; }
.section-head__note a { color: var(--text-secondary); text-decoration: none; border-bottom: 1px solid var(--border); }
.section-head__note a:hover { color: var(--text-primary); border-bottom-color: var(--text-muted); }

.card--intro { background: var(--surface-2); }
.card--intro h2 { margin-bottom: 8px; }
.card--intro .card__note { margin-bottom: 8px; }
.card--intro .card__note:last-child { margin-bottom: 0; }

/* Свернутая карточка-пояснение. Текст читается один раз, а места занимал
   экран над таблицей, ради которой раздел и открывают. <details> вместо
   <section>, поэтому отступ снизу приходится задавать самой карточке. */
/* Пояснение под графиком свернуто (13.09.2026, просьба пользователя): на
   телефоне это десяток строк, и следующая карточка уезжала за экран. Обертка
   прячется целиком, когда пояснения нет (`noteFold` в app.js), — пустая
   строка «Показать пояснение» читалась бы как потерянный текст. */
.note-fold > summary {
  display: inline-flex; align-items: center; gap: 6px; list-style: none;
  cursor: pointer; user-select: none; font-size: 12px; color: var(--text-secondary);
}
.note-fold > summary::-webkit-details-marker { display: none; }
.note-fold > summary::before { content: '▸'; font-size: 11px; color: var(--text-muted); }
.note-fold[open] > summary::before { content: '▾'; }
.note-fold > summary:hover { color: var(--text-primary); }
.note-fold[open] .note-fold__more,
.note-fold:not([open]) .note-fold__less { display: none; }
.note-fold .card__note { margin: 8px 0 0; }

.card--fold { margin-bottom: 16px; }
.card--fold > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 8px;
}
.card--fold > summary::-webkit-details-marker { display: none; }
.card--fold > summary::before { content: '▸'; font-size: 11px; color: var(--text-muted); }
.card--fold[open] > summary::before { content: '▾'; }
.card--fold > summary:hover::before { color: var(--text-secondary); }
.card--fold > summary h2 { margin: 0; }
.card--fold__body { margin-top: 10px; }

.table-scroll { overflow-x: auto; }
.badge {
  flex: none; font-size: 11px; padding: 3px 9px; border-radius: 999px;
  color: var(--text-secondary); background: var(--surface-0); border: 1px solid var(--border);
}

.passport {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px;
  margin: 0 0 16px; padding: 12px 14px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
}
.passport dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.passport dd { margin: 3px 0 0; font-size: 12.5px; color: var(--text-primary); }

/* --- общее для таблиц с параметрами (раздел облигаций) --- */
.check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.check input { accent-color: var(--series-fee); }
.asset-breakdown {
  margin: 12px 0 0; padding: 10px 12px; font-size: 12.5px; line-height: 1.5;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
}
.asset-divs-total { font-weight: 400; color: var(--text-muted); font-size: 12px; }
.th-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.th-sort:hover { color: var(--text-secondary); }
.th-sort--on { color: var(--text-primary); }

/* --- карточка актива --- */
.asset-link {
  font: inherit; padding: 0; border: none; background: none; cursor: pointer;
  color: var(--text-primary); text-align: left;
  border-bottom: 1px solid var(--border);
}
.asset-link:hover { border-bottom-color: var(--text-muted); }
.asset-link:focus-visible { outline: 2px solid var(--series-fee); outline-offset: 2px; }

.modal { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .45); }
.modal__card {
  position: relative; z-index: 1;
  width: min(760px, calc(100vw - 32px)); max-height: calc(100vh - 64px); overflow-y: auto;
  background: var(--surface-1); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: 0 12px 40px rgba(0, 0, 0, .3); padding: 24px;
}
.modal__close {
  position: absolute; top: 12px; right: 14px;
  font: inherit; font-size: 20px; line-height: 1; padding: 4px 8px;
  background: none; border: none; border-radius: 6px; cursor: pointer; color: var(--text-muted);
}
.modal__close:hover { color: var(--text-primary); background: var(--surface-0); }
.modal__card--narrow { width: min(600px, calc(100vw - 32px)); }

/* --- окно «Уведомления» --------------------------------------------------
   Свой префикс ntf; .check, .btn и .card__note--warn — общие. */
.ntf__title { font-size: 18px; color: var(--text-primary); margin: 0 0 8px; padding-right: 32px; }
.ntf__text { font-size: 13px; color: var(--text-secondary); margin: 0 0 10px; line-height: 1.5; }
.ntf__muted { font-size: 12px; color: var(--text-muted); margin: 6px 0 0; line-height: 1.45; }
.ntf__block { margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--border); }
.ntf__block h3 { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.ntf__event { align-items: flex-start; font-size: 13px; line-height: 1.45; margin-bottom: 8px; }
.ntf__event input { margin-top: 3px; flex: none; }
.ntf__event b { color: var(--text-primary); font-weight: 600; }
.ntf__row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ntf__input {
  flex: 1 1 220px; min-width: 0; font: inherit; font-size: 13px; padding: 6px 10px;
  color: var(--text-primary); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 6px;
}
.ntf__input:focus-visible { outline: none; border-color: var(--series-fee); }
.ntf__steps { margin: 0 0 10px; padding-left: 20px; font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
.ntf__steps li { margin-bottom: 4px; }
.ntf__devices { margin: 4px 0 0; padding-left: 18px; font-size: 12.5px; color: var(--text-secondary); }
.ntf__test { margin-top: 18px; }
.ntf__note { font-size: 12.5px; color: var(--good); }
.ntf__note--bad { color: var(--critical); }
.ntf__log { list-style: none; margin: 0; padding: 0; }
.ntf__log li { border-bottom: 1px solid var(--grid); }
.ntf__log summary {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; align-items: baseline;
  padding: 7px 0; cursor: pointer; list-style: none; font-size: 12.5px;
}
.ntf__log summary::-webkit-details-marker { display: none; }
.ntf__log details[open] { padding-bottom: 8px; }
.ntf__when { color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ntf__what { color: var(--text-primary); }
.ntf__state { font-size: 11px; white-space: nowrap; color: var(--text-muted); }
.ntf__state--sent { color: var(--good); }
.ntf__state--failed { color: var(--critical); }

.asset-head { margin-bottom: 16px; padding-right: 32px; }
.asset-head h2 { font-size: 18px; color: var(--text-primary); }
.asset-sub { margin: 6px 0 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.asset-metrics { grid-template-columns: repeat(3, 1fr); }
.asset-section { margin-top: 20px; }
.asset-section h3 { margin: 0 0 8px; font-size: 13px; color: var(--text-secondary); font-weight: 600; }
.asset-divs { font-size: 12.5px; max-width: 320px; }
.asset-foot { margin-top: 18px; max-width: 70ch; }

@media (max-width: 900px) {
  .hero-row, .grid-2 { grid-template-columns: minmax(0, 1fr); }
  /* Плитки в столбик занимали на телефоне пять экранов прокрутки, а числа в
     них короткие. Поэтому расходы, налоги и выплаты идут строкой по трое, а
     «Заведено нетто» и «Чистый денежный результат» — парой; во всю ширину
     остается только стоимость портфеля: у нее рядом заработок и дата снимка. */
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles:not(.tiles--three) > .tile:first-child { grid-column: 1 / -1; }
  .tiles--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .passport, .asset-metrics { grid-template-columns: repeat(2, 1fr); }
  .modal__card { padding: 18px; }
  main { padding: 16px; }
  .syncbar { padding: 10px 16px; }
  /* Узкий экран: одна колонка, каждый блок в своей строке. Центрировать нечего,
     поэтому и смещаться нечему. */
  .topbar { grid-template-columns: 1fr; padding: 12px 16px; }
  /* Шапка в одну колонку: строка заголовка занимает всю ширину, и время
     обновления встает к правому краю. В широкой шапке так нельзя — там
     заголовок занимает левую треть, и подпись у ее края читалась бы как
     часть вкладок, стоящих по центру. */
  .topbar__updated { margin-left: auto; }
  .topbar__actions { justify-self: start; }
  .topbar__actions { flex-wrap: wrap; }
}

/* Средняя ширина: вкладки уходят второй строкой на всю ширину. Колонка
   заголовка с min-width: 0 уступает место молча: при нехватке ширины номер
   счета сжимается в ноль, а вкладки наезжают на название. Замер 13.09.2026:
   заголовок 313 px, вкладки-кнопки 571, действия 193 (с колокольчиком
   уведомлений — 232, все еще уже заголовка), отступы и зазоры 80.
   Боковые колонки равны, считать по более широкой: 80 + 571 + 2 × 313 = 1277
   впритык, порог взят с запасом на длинное название счета и подпись времени.
   С пятой вкладкой (13.09 — 05.10.2026, «Тренажер») порог поднимали до 1440.
   Знак продукта перед названием (14.09.2026) добавил колонке заголовка 35 px
   с каждой стороны: при подписи «обновлено сегодня в 00:55» номер счета перестает
   сжиматься с 1486 px (Chrome и WebKit одинаково), с «12.09 в 16:34» — с 1462.
   Порог поднят до 1500.
   Добавишь кнопку в шапку — перемерь. */
@media (max-width: 1499px) {
  .topbar .tabs { justify-self: stretch; }
  .tab { flex: 1 1 auto; }
}
@media (min-width: 901px) and (max-width: 1499px) {
  .topbar { grid-template-columns: minmax(0, 1fr) auto; }
  .topbar__title { grid-column: 1; grid-row: 1; }
  .topbar__actions { grid-column: 2; grid-row: 1; }
  .topbar .tabs { grid-column: 1 / -1; grid-row: 2; }
}

/* Телефон: плитки стоят по трое и парами, поэтому отступы и кегль меньше —
   на строку из трех каждой достается 127 px. */
@media (max-width: 720px) {
  .tiles, .tiles--three { gap: 8px; }
  .tile { padding: 10px 12px; }
  .tile__label { gap: 5px; font-size: 11.5px; }
  .tiles--three .tile__value { font-size: 18px; }
}
/* Экраны уже 400 px: в трети ширины семизначная сумма не помещалась, а
   разряды разделены неразрывным пробелом и перенести ее нельзя. */
@media (max-width: 400px) {
  .tiles--three .tile__value { font-size: 16px; }
}

/* Телефон: каждая строка шапки заполняет ширину целиком. Кнопки разной ширины
   выстраивались лесенкой с рваным правым краем, а свободного места на узком
   экране столько, что оно читается как сбитая верстка. Ширины делятся между
   кнопками строки, а не задаются каждой отдельно: кнопка обновления прячется
   при APP_ALLOW_SYNC=0, и любая жестко расписанная сетка при этом рассыпалась
   бы. */
@media (max-width: 720px) {
  .topbar { padding: 12px 16px; gap: 10px; }
  .topbar .tabs, .topbar__actions { justify-self: stretch; }

  /* Пять вкладок — в две строки, две и три (сетка на шесть долей): по две в
     строке их было бы три ряда. Длинное название переносится, а не
     обрезается: «Лестница обли…» не читается. Порядок на телефоне свой:
     сверху парой «Аналитика» и «Тренажер», ниже тройкой «LQDT ↔ GOLD»,
     «Моментум+», «Лестница облигаций». Переставляет `order`, а не разметка:
     на компьютере порядок прежний. «Тренажер» — ссылка на /trainer/, у нее
     data-link вместо data-view. Новую вкладку вписывать сюда. */
  .tabs { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .tab { grid-column: span 2; }
  .tab[data-view="analytics"] { order: 1; grid-column: span 3; }
  .tab[data-link="trainer"] { order: 2; grid-column: span 3; }
  .tab[data-view="goldpair"] { order: 3; }
  .tab[data-view="screener"] { order: 4; }
  .tab[data-view="bonds"] { order: 5; }
  .tab { height: auto; min-height: 40px; padding: 6px 10px; white-space: normal; line-height: 1.2; }
  .tab__icon { width: 16px; height: 16px; }

  /* Действия шапки — в меню под кнопкой «три полоски» справа от времени
     обновления (14.09.2026, просьба пользователя): строка из списка, «Обновить»
     и колокольчика занимала высоту липкой шапки на каждом экране. В меню стоят
     те же элементы, что в строке на компьютере, а не копии: обработчик и
     состояние («Обновляю…», скрытие в демо) у них одни.
     Якорь панели — блок нулевого размера в ячейке строки заголовка, прижатый к
     ее низу и правому краю: панель встает под кнопкой меню, какой бы высоты ни
     вышла строка. Открывает и закрывает класс topbar--menu (app.js). */
  .topbar__title { grid-column: 1; grid-row: 1; }
  .topbar .tabs { grid-column: 1; grid-row: 2; }
  /* Номер счета — в меню, на его месте время обновления (14.09.2026, просьба
     пользователя): к правому краю прижимается уже кнопка меню. Длинное
     название счета сжимается многоточием, а не выталкивает кнопку за край. */
  .topbar__account { display: none; }
  .topbar__title h1 { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .topbar__updated { margin-left: 0; }
  /* Правый край кнопки — без отрицательного отступа: кнопка меню, вкладки и
     «Период» стоят по одной вертикали в 16 px от края экрана. Вертикальные
     отступы отрицательные, чтобы кнопка не делала строку заголовка выше. */
  .topbar__menu { display: inline-flex; align-self: center; margin: -4px 0 -4px auto; }
  /* Колонка задана явно — здесь, у заголовка и у вкладок. Блоку со строкой, но
     без колонки, сетка ищет свободную ячейку в этой строке и заводит неявную
     вторую колонку: у якоря она нулевой ширины, но с зазором 10 px, и на эти
     10 px укорачивались вкладки; а задай колонку одному якорю — в новую
     колонку уезжал заголовок, и вкладки сжимались вдвое. */
  .topbar__actions {
    grid-column: 1; grid-row: 1; justify-self: end; align-self: end;
    position: relative; width: 0; height: 0;
  }
  .refresh {
    position: absolute; top: 8px; right: 0; z-index: 30;
    width: min(280px, calc(100vw - 32px)); padding: 8px;
    flex-direction: column; align-items: stretch;
    background: var(--surface-1); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  }
  .topbar:not(.topbar--menu) .refresh { display: none; }
  .refresh__row { flex-direction: column; align-items: stretch; gap: 8px; }
  /* Порядок как в просьбе: уведомления, обновление, частота обновления; номер
     счета — справкой над ними, отделенный чертой: это не действие. */
  .refresh__account {
    order: 0; display: flex; flex-direction: column; gap: 2px;
    padding: 2px 4px 10px; border-bottom: 1px solid var(--border);
  }
  .refresh__account:has(#menuAccount:empty) { display: none; }
  .refresh__account-id { font-size: 14px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
  .refresh__row > #notifyBtn { order: 1; }
  .refresh__row > #syncBtn { order: 2; }
  .refresh__field { order: 3; display: flex; flex-direction: column; gap: 4px; }
  .refresh__field:has(select[hidden]) { display: none; }
  .refresh__caption { display: block; font-size: 11px; color: var(--text-muted); }
  .refresh__row .btn { height: 38px; padding: 0 12px; }
  .refresh__every { width: 100%; height: 38px; }
  .refresh__row .btn--icon { width: auto; justify-content: flex-start; gap: 8px; color: var(--text-primary); }
  .topbar__actions .btn__text { display: inline; }
}
/* Уже 360 px в трети строки не помещается «Моментум+» одним словом: вкладки
   по две в том же порядке, последняя по порядку — «Лестница облигаций» — во
   всю ширину. */
@media (max-width: 359px) {
  .tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tab, .tab[data-view], .tab[data-link] { grid-column: auto; }
  .tab[data-view="bonds"] { grid-column: 1 / -1; }
}

/* --- «Лестница облигаций» --------------------------------------------------
   Устроен как «Моментум+» и «LQDT ↔ GOLD»: карточка результата с главной
   строкой и сеткой фактов, под ней пул выпусков таблицей, в конце свернутое
   правило. Свой префикс bnd; .check, .th-sort, .field и .select — общие. */
#viewBonds .section-head > div { flex: 1 1 100%; }
/* Плитки итога у «LQDT ↔ GOLD»: три в ряд внутри карточки. Отдельный класс,
   потому что .tiles живет внутри своей сетки раздела. */
.tiles-3 {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px;
}
/* Плитки внутри карточки — вдавленные, а не парящие: тень карточки на них
   выглядела бы вторым этажом. */
.tiles-3 .tile {
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px; box-shadow: none;
}

.bnd-ladder { border-color: color-mix(in srgb, var(--series-income) 45%, var(--border)); }
.bnd-asof { font-size: 11.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.bnd-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.bnd-reload { font-size: 12px; padding: 4px 10px; }
/* Статус сохраненной лестницы. Сохраненная помечена полосой цветом линии
   «Лестница» — той же, что на графиках «Аналитики»: цвет связывает раскладку
   на экране с линией там. */
.bnd-saved { margin: 0 0 14px; font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }
.bnd-saved--on, .bnd-saved--diff { padding-left: 10px; box-shadow: inset 3px 0 0 var(--series-ladder); }
.bnd-saved--diff { box-shadow: inset 3px 0 0 var(--border); }
.bnd-link {
  font: inherit; padding: 0; border: none; background: none; cursor: pointer;
  color: var(--series-fee); white-space: nowrap;
}
.bnd-link:focus-visible { outline: 2px solid var(--series-fee); outline-offset: 2px; }
@media (hover: hover) { .bnd-link:hover { text-decoration: underline; } }
/* Параметры стоят внутри карточки, а не панелью над ней: панель читалась как
   чужой блок между карточками, и ни у одного соседнего раздела такой нет.
   Смена любого параметра пересчитывает сразу, кнопки «Пересчитать» нет. */
.bnd-params {
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
  margin: 0 0 12px; font-size: 12px;
}
.bnd-params__label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); flex: none;
}
.bnd-params__note { font-size: 11.5px; color: var(--text-muted); }
.bnd-params input[type="number"] { width: 110px; }
.bnd-params--pool { padding-top: 10px; border-top: 1px solid var(--grid); }
/* Главная строка одна и крупная, как в соседних разделах: что получилось
   при этих параметрах. */
.bnd-ladder__action {
  margin: 6px 0 12px; font-size: 20px; line-height: 1.3; font-weight: 600;
  letter-spacing: -.01em; color: var(--text-primary);
}
.bnd-why { margin: 0 0 14px; font-size: 13.5px; line-height: 1.5; color: var(--text-primary); }
.bnd-next {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px;
  margin: 0 0 14px; padding: 12px 14px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
}
.bnd-next dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.bnd-next dd { margin: 3px 0 0; font-size: 13px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.bnd-next dd b { font-size: 15px; }
.bnd-next dd span { display: block; font-size: 11.5px; color: var(--text-secondary); margin-top: 2px; }
/* Пока сервер считает, прежнее содержимое приглушается, а не стирается:
   мигание пустой карточкой на каждую галочку читалось бы как сбой. */
.is-busy { opacity: .55; transition: opacity .15s; }

.bnd-table { font-size: 12.5px; }
.bnd-table th, .bnd-table td { padding: 7px 8px; }
.bnd-table td { color: var(--text-secondary); }
.bnd-table .num { font-variant-numeric: tabular-nums; }
.bnd-table .bnd-col--ticker { white-space: nowrap; }
/* Длинные названия выпусков не растаскивают таблицу: имя сжимается,
   числовые колонки остаются читаемыми. */
.bnd-table .bnd-col--name { max-width: 230px; }
.bnd-table th .why { vertical-align: baseline; margin-left: 4px; }
.bnd-table th.num .why { margin-left: 5px; }
.bnd-muted { color: var(--text-muted); font-weight: 400; }
.bnd-skipped { margin-bottom: 12px; }
.bnd-warn {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--warn-bg); border-radius: 6px; padding: 8px 10px;
  color: var(--text-primary); margin-bottom: 16px;
}
.bnd-footnote { margin: 12px 0 0; }
.bnd-subhead { margin: 20px 0 8px; font-size: 13px; color: var(--text-secondary); font-weight: 600; }

.bnd-steps td { vertical-align: middle; }
.bnd-step__window { white-space: nowrap; color: var(--text-secondary); }
.bnd-step__pick { min-width: 260px; }
.bnd-step__pick select { max-width: 320px; }
.bnd-step--empty td { color: var(--text-muted); }

/* Второе число под первым: срок под датой погашения, доходность к оферте под
   доходностью, цена лота под ценой. Так таблица укладывается в общую ширину
   раздела, и своя широкая раскладка ей не нужна. */
.bnd-sub { display: block; font-size: 11px; color: var(--text-muted); margin-top: 2px; font-weight: 400; }

/* Значки — кнопки: нажатие показывает, что значит свойство (словарь
   BND_TERMS в bonds.js). На iPhone атрибут title не виден, а наведения нет. */
.bnd-badge {
  appearance: none; -webkit-appearance: none; cursor: help;
  display: inline-block; margin-left: 5px; padding: 1px 5px; border-radius: 4px;
  font: inherit; font-size: 10px; line-height: 1.4; background: var(--surface-0);
  border: 1px solid var(--border); color: var(--text-muted); vertical-align: middle;
}
.bnd-badge:focus-visible { outline: 2px solid var(--series-fee); outline-offset: 1px; }
@media (hover: hover) {
  .bnd-badge:hover { color: var(--text-secondary); border-color: var(--text-muted); }
}
.badge--term { appearance: none; -webkit-appearance: none; font-family: inherit; cursor: help; }
.bnd-check { display: inline-flex; align-items: center; }
.bnd-terms { margin: 0 0 6px; display: grid; gap: 12px; }
.bnd-terms dt { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.bnd-terms dd { margin: 3px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--text-secondary); }
.bnd-terms dd p { margin: 0 0 4px; }
.bnd-terms dd p:last-child { margin-bottom: 0; }
.bnd-badge--call { border-color: var(--series-tax); color: var(--series-tax); }
.bnd-badge--warn { border-color: var(--critical); color: var(--critical); }
.bnd-stale { margin-left: 5px; color: var(--text-muted); font-size: 11px; }

/* Полоса выплат по годам: ширина ставится скриптом, инлайн-стилей в разметке
   быть не должно — на сервере отдается CSP default-src 'self'. */
.bnd-payments { font-size: 12.5px; max-width: 420px; }
.bnd-payments td { padding: 4px 8px 4px 0; }
.bnd-bar { width: 55%; }
.bnd-bar i {
  display: block; height: 8px; border-radius: 3px; background: var(--series-income);
  min-width: 2px;
}
.bnd-payments tfoot td { border-top: 1px solid var(--grid); font-weight: 600; }

.bnd-schedule { max-width: 420px; }
.bnd-ev--mty td, .bnd-ev--call td { font-weight: 600; }
.bnd-ev--call td { color: var(--series-tax); }
.bnd-steps-list { margin: 0 0 10px; padding-left: 20px; }
.bnd-steps-list li { margin-bottom: 6px; }

/* Спред в десятки пунктов — не выгодная покупка, а ожидание дефолта. Цвет
   тот же, что у критических значений в остальном интерфейсе. */
.bnd-spread--wide { color: var(--critical); }
/* Уровень риска — шкала брокера из трех значений, а не кредитный рейтинг.
   Цветом выделен только высокий: остальные два — норма, и подсветка каждой
   строки превратила бы таблицу в светофор. */
.bnd-risk { font-size: 12px; }
.bnd-risk--high { color: var(--critical); }
.bnd-risk--unknown { color: var(--text-muted); }

@media (max-width: 900px) {
  .tiles-3 { grid-template-columns: 1fr; }
  .bnd-next { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Телефон: поля параметров делят строку пополам, а не выстраиваются
   лесенкой; таблицы прокручиваются внутри карточки. */
@media (max-width: 720px) {
  .bnd-ladder__action { font-size: 17px; }
  .bnd-next { gap: 10px; }
  .bnd-table th, .bnd-table td { padding: 6px 5px; }
  .bnd-table .bnd-col--name { max-width: 160px; }
  .bnd-params .field { flex: 1 1 45%; min-width: 0; }
  /* Подпись не сжимается: поле с width: 100% отнимало у нее место, и «На
     ступень брать» рвалось на три строки. Длинные подписи и списки с длинными
     вариантами занимают строку целиком, иначе в половине ширины от «надежнейший
     по мнению рынка» оставалось «надежнейшиі», а от «без потолка» — «без пото».
     Парой остаются только «Горизонт» и «Ступеней»; правило выбора уходит в
     конец, чтобы они встали рядом. */
  .bnd-params .field > span { flex: none; }
  .bnd-params .bnd-field--wide { flex-basis: 100%; }
  .bnd-params .bnd-field--end { order: 1; }
  .bnd-params .field select, .bnd-params .field input { flex: 1 1 auto; min-width: 0; width: 100%; }
  .bnd-params .bnd-check { flex: 1 1 45%; }
  .bnd-params__note { flex: 1 1 100%; }
  .bnd-step__pick { min-width: 200px; }
}

/* --- «Моментум+»: решение правила ------------------------------------------
   Свой префикс stg; .th-sort и .check выше — общие с разделом облигаций. */
#viewScreener .section-head > div { flex: 1 1 100%; }
.stg-verdict { border-color: color-mix(in srgb, var(--series-rule) 45%, var(--border)); }
.stg-asof { font-size: 11.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* Главная строка одна и крупная: ответ на «что делать» не должен спорить
   с соседними абзацами за внимание. */
.stg-verdict__action {
  margin: 6px 0 12px; font-size: 20px; line-height: 1.3; font-weight: 600;
  letter-spacing: -.01em; color: var(--text-primary);
}
.stg-verdict__fund { margin: 0 0 12px; font-size: 13px; color: var(--text-secondary); }
.stg-picks { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.stg-picks li { display: flex; align-items: baseline; gap: 8px; font-size: 13px;
  padding: 7px 10px; border: 1px solid var(--grid); border-radius: 8px;
  box-shadow: inset 3px 0 0 var(--series-rule); }
.stg-picks li span:first-of-type { color: var(--text-secondary); flex: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stg-why { margin: 0 0 14px; font-size: 13.5px; line-height: 1.5; color: var(--text-primary); }
/* Пометка «не рекомендация» относится к строке решения — стоит вплотную к ней. */
.stg-why + .stg-disclaimer { margin-top: -8px; }
.stg-next {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
  margin: 0 0 14px; padding: 12px 14px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
}
.stg-next dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.stg-next dd { margin: 3px 0 0; font-size: 13px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.stg-next dd b { font-size: 15px; }
.stg-next dd span { display: block; font-size: 11.5px; color: var(--text-secondary); }
.stg-dot--defence { background: var(--text-muted); }
.stg-now { padding: 8px 10px; background: var(--surface-0); border: 1px solid var(--border); border-radius: 6px; }
.stg-table { font-size: 12.5px; }
.stg-table th, .stg-table td { padding: 7px 8px; }
.stg-table td { color: var(--text-secondary); }
.stg-table .stg-ticker { white-space: nowrap; }
.stg-table .stg-name { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stg-table .stg-rank { color: var(--text-muted); width: 2.5em; }
.stg-table th .why { vertical-align: baseline; margin-left: 4px; }
/* Состав по правилу: подсветка слева, а не заливка — заливка читается как
   выделение мышью. Первая восьмерка в защите помечена бледнее: ее не купили. */
.stg-row--pick td:first-child { box-shadow: inset 3px 0 0 var(--series-rule); }
.stg-row--eight td:first-child { box-shadow: inset 3px 0 0 var(--border); }
.stg-pick { font-size: 10.5px; padding: 1px 5px; border-radius: 4px; white-space: nowrap;
  color: var(--series-rule); background: color-mix(in srgb, var(--series-rule) 14%, transparent); }
.stg-pick--ghost { color: var(--text-muted); background: var(--surface-0); border: 1px solid var(--border); }
.stg-history .stg-date { white-space: nowrap; font-variant-numeric: tabular-nums; }
.stg-def { color: var(--text-muted); }
.stg-footnote { margin: 12px 0 0; }
.stg-steps { margin: 0 0 10px; padding-left: 20px; }
.stg-steps li { margin-bottom: 5px; }
@media (max-width: 720px) {
  .stg-verdict__action { font-size: 17px; }
  .stg-picks { grid-template-columns: 1fr; }
  .stg-next { grid-template-columns: 1fr; gap: 8px; }
  /* Под таблицу на телефоне остается 364 px. Оборот прячется — он самая
     служебная колонка, лишь объясняет, почему бумага во вселенной; пометка
     уходит под тикер, а не рядом с ним, название ужимается, отступы тоже. */
  .stg-col--turnover { display: none; }
  .stg-table th, .stg-table td { padding: 6px 5px; }
  .stg-table .stg-name { max-width: 118px; }
  .stg-table .stg-pick { display: block; width: max-content; margin-top: 2px; }
  .stg-history th { white-space: normal; }
  .stg-history .stg-tickers { font-size: 11.5px; }
}

/* --- «LQDT ↔ GOLD»: решение правила по паре фондов -------------------------
   Свой префикс gp; разметка карточки решения повторяет «Моментум+», но
   рамка и метки окрашены по активу: золото — оранжевый ряд, LQDT — синий. */
#viewGoldpair .section-head > div { flex: 1 1 100%; }
.gp-verdict--gold { border-color: color-mix(in srgb, var(--series-tax) 45%, var(--border)); }
.gp-verdict--cash { border-color: color-mix(in srgb, var(--series-fee) 45%, var(--border)); }
.gp-asof { font-size: 11.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* Переключатель «сейчас у меня»: приложение не знает позицию на чужом счете,
   ее отмечает человек. Кнопки маленькие — это не главное на карточке. */
.gp-position { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 10px; }
.gp-position__label { font-size: 12px; color: var(--text-secondary); }
.gp-position__note { font-size: 11px; color: var(--text-muted); }
.gp-seg { display: inline-flex; gap: 2px; padding: 2px; background: var(--surface-0);
  border: 1px solid var(--border); border-radius: 7px; }
.gp-seg__btn { height: 26px; padding: 0 10px; border: 1px solid transparent; border-radius: 5px;
  background: transparent; color: var(--text-secondary); font: inherit; font-size: 12.5px; cursor: pointer; }
.gp-seg__btn:hover { color: var(--text-primary); }
.gp-seg__btn[aria-pressed="true"] { background: var(--surface-2); border-color: var(--border);
  color: var(--text-primary); font-weight: 500; box-shadow: var(--shadow); }
/* Главная строка одна и крупная — ответ на «что делать». */
.gp-verdict__action {
  margin: 6px 0 12px; font-size: 20px; line-height: 1.3; font-weight: 600;
  letter-spacing: -.01em; color: var(--text-primary);
}
.gp-verdict__action--switch { padding-left: 12px; box-shadow: inset 3px 0 0 var(--series-tax); }
.gp-verdict--cash .gp-verdict__action--switch { box-shadow: inset 3px 0 0 var(--series-fee); }
.gp-why { margin: 0 0 14px; font-size: 13.5px; line-height: 1.5; color: var(--text-primary); }
.gp-why + .gp-disclaimer { margin-top: -8px; }
.gp-next {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px;
  margin: 0 0 14px; padding: 12px 14px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
}
.gp-next dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.gp-next dd { margin: 3px 0 0; font-size: 13px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.gp-next dd b { font-size: 15px; }
.gp-next dd span { display: block; font-size: 11.5px; color: var(--text-secondary); margin-top: 2px; }
/* «Сейчас»: две цены и предварительный взгляд в одной сетке; третья ячейка
   шире — там предложение, а не число. */
.gp-live { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2fr); }
.gp-live__preview dd span { font-size: 12.5px; color: var(--text-primary); line-height: 1.45; }
.gp-live__note { margin: 0 0 14px; }
.gp-tiles { margin-bottom: 14px; }
.gp-table { font-size: 12.5px; }
.gp-table th, .gp-table td { padding: 7px 8px; }
.gp-table td { color: var(--text-secondary); }
.gp-table .num { font-variant-numeric: tabular-nums; }
.gp-table .gp-date { white-space: nowrap; font-variant-numeric: tabular-nums; }
.gp-partial { font-size: 10.5px; color: var(--text-muted); white-space: nowrap; }
/* Год, где правило обогнало LQDT, помечен полоской слева, а не заливкой. */
.gp-row--beat td:first-child { box-shadow: inset 3px 0 0 var(--series-rule); }
.gp-pos { font-size: 10.5px; padding: 1px 6px; border-radius: 4px; white-space: nowrap; font-weight: 500; }
.gp-pos--gold { color: var(--series-tax); background: color-mix(in srgb, var(--series-tax) 14%, transparent); }
.gp-pos--cash { color: var(--series-fee); background: color-mix(in srgb, var(--series-fee) 14%, transparent); }
.gp-open { color: var(--text-muted); font-style: italic; }
.gp-steps { margin: 0 0 10px; padding-left: 20px; }
.gp-steps li { margin-bottom: 6px; }
@media (max-width: 720px) {
  .gp-verdict__action { font-size: 17px; }
  .gp-next { grid-template-columns: 1fr 1fr; gap: 10px; }
  .gp-live { grid-template-columns: 1fr 1fr; }
  .gp-live__preview { grid-column: 1 / -1; }
  .gp-table th, .gp-table td { padding: 6px 5px; }
  .gp-segments th { white-space: normal; }
}
