/* ==========================================================================
   КОМПОНЕНТЫ: кнопки, панели, показатели, таблицы, полосы, вкладки, формы,
   модальные окна, панель детали строки, подсказка, диаграмма, пустые
   состояния, полоса сходимости.
   Разметка соответствует design/mockup.html 2.1.
   ========================================================================== */

/* ---------- Кнопки ---------- */
.btn{height:32px;padding:0 12px;border-radius:var(--r-2);border:1px solid var(--line-2);
     background:transparent;color:var(--ink);font-size:var(--fs-2);font-weight:var(--fw-med);
     cursor:pointer;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.btn:hover{background:var(--layer-2)}
.btn-main{background:var(--accent);border-color:transparent;color:var(--ink-inv)}
.btn-main:hover{background:var(--accent-2)}
.btn-quiet{border-color:transparent;color:var(--ink-2);font-weight:var(--fw)}
.btn-quiet:hover{color:var(--ink);background:var(--layer-2)}
.btn-neg{color:var(--neg)}
.btn-lg{height:40px;padding:0 18px}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn[disabled]:hover{background:transparent}

/* ---------- Панели ---------- */
/* 🚩 Д-21 живого прогона. Широкая таблица прокручивается ВНУТРИ своей панели,
   а не распирает страницу. До правки таблица на 770 px в контейнере 472 px
   уводила вбок весь экран — вместе с меню и шапкой с периодом, — и начиналось
   это уже на 1024 px, то есть на обычном ноутбуке и в окне в половину экрана.
   `min-width:0` обязателен: панель лежит в flex-колонке, и без него она не
   даёт себя сжать, сколько бы `overflow` ей ни назначили.
   ⚠️ Всплывающие подсказки этим не обрезаются — они `position:fixed`. */
.panel{background:var(--panel);border-radius:var(--r-3);padding:var(--sp-5);
       box-shadow:0 0 0 1px var(--line);overflow-x:auto;min-width:0}
.panel.tight{padding:var(--sp-4) var(--sp-5)}
.panel + .panel{margin-top:var(--sp-4)}
.panel-h{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4);
         margin-bottom:var(--sp-4);flex-wrap:wrap}
.panel-h h2,.panel-h h3{font-size:var(--fs-2);font-weight:var(--fw-med)}
.panel-h .meta{font-size:var(--fs-1);color:var(--ink-2);display:flex;align-items:center;
               gap:var(--sp-2);flex-wrap:wrap}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4)}
/* 🚩 Д-21: колонка сетки по умолчанию не уже своего содержимого (min-width
   auto), и широкая таблица в одной из колонок растягивала всю сетку, а с ней
   страницу. Ширину задаёт сетка, содержимое прокручивается внутри панели. */
.grid2 > *{min-width:0}
@media (max-width:1000px){.grid2{grid-template-columns:1fr}}

/* ---------- Показатели ----------
   Ряд ключевых показателей. Группа = один период, и он подписан ОДИН раз над
   группой: так снимается вопрос «это за месяц или за всё время» без мелких
   подписей под каждой цифрой (Р-60).
   Показатели лежат на панели и получают весь верх экрана — это главное, ради
   чего руководитель открывает дашборд; диаграмма ниже — контекст (Р-82.1). */
.kpi{display:flex;gap:var(--sp-6);flex-wrap:wrap;align-items:stretch;
     background:var(--panel);border-radius:var(--r-3);box-shadow:0 0 0 1px var(--line);
     padding:var(--sp-5) var(--sp-6);margin-bottom:var(--sp-4)}
.kpi-g{display:flex;flex-direction:column;justify-content:flex-start}
.kpi-g + .kpi-g{padding-left:var(--sp-6);border-left:1px solid var(--line)}
.kpi-lbl{font-size:var(--fs-1);color:var(--ink-3);margin-bottom:var(--sp-4)}
.kpi .stats{margin-bottom:0;gap:var(--sp-6);row-gap:var(--sp-5)}
.kpi .stat{min-width:118px}
.kpi .stat .lbl{color:var(--ink-2)}
@media (max-width:1100px){.kpi-g + .kpi-g{padding-left:0;border-left:0}}
.stats{display:flex;gap:var(--sp-7);flex-wrap:wrap;margin-bottom:var(--sp-5)}
.stat .lbl{font-size:var(--fs-1);color:var(--ink-2)}
.stat .val{font-size:var(--fs-3);font-weight:var(--fw-med);letter-spacing:-.02em;
           font-variant-numeric:tabular-nums;margin-top:4px}
.stat .val.hero{font-size:var(--fs-4);margin-top:2px}
.stat .delta{font-size:var(--fs-1);color:var(--ink-2);font-variant-numeric:tabular-nums;margin-top:2px}

/* ---------- Таблица ---------- */
table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
th{font-size:var(--fs-1);font-weight:var(--fw-med);color:var(--ink-2);text-align:left;
   padding:0 var(--sp-3) var(--sp-2);border-bottom:1px solid var(--line);white-space:nowrap}
td{padding:0 var(--sp-3);height:var(--row-h);border-bottom:1px solid var(--line);
   font-size:var(--fs-2);vertical-align:middle}
.r{text-align:right}
tbody tr:hover{background:var(--layer-2)}
tbody tr.clickable{cursor:pointer}
tfoot td{font-weight:var(--fw-med);border-bottom:0;border-top:1px solid var(--line-2)}
tfoot tr:hover{background:transparent}
/* Секция внутри таблицы и её собственный итог. Нужны там, где строки разной
   природы нельзя складывать в один итог: «нам должны» / «мы должны»
   (Р-90.5, REQ-179). Общего tfoot у такой таблицы нет. */
tbody tr.grp td{height:auto;padding:var(--sp-5) var(--sp-3) var(--sp-2);
                font-size:var(--fs-1);color:var(--ink-2);font-weight:var(--fw-med)}
tbody tr.grp:first-child td{padding-top:var(--sp-2)}
tbody tr.grp:hover{background:transparent}
tbody tr.sub td{font-weight:var(--fw-med);border-bottom:0;border-top:1px solid var(--line-2)}
tbody tr.sub:hover{background:transparent}
/* Колонка отметки оплаты (📌 Р-120, макет 2.29). Узкая и первая: галочка
   отвечает за строку целиком, поэтому стоит там, где строка начинается.
   Ширина задана явно — иначе колонка из одного значка растягивается наравне
   с текстовыми. */
th.mk,td.mk{width:34px;text-align:center;padding-left:var(--sp-3);padding-right:0}
td.name{font-weight:var(--fw)}
.flag{display:inline-block;width:3px;height:20px;border-radius:2px;background:var(--neg);
      vertical-align:-4px;margin-right:8px}
.flag.off{background:transparent}
.rowact{opacity:0;border:0;background:transparent;color:var(--ink-2);cursor:pointer;
        padding:2px 6px;border-radius:var(--r-1);font-size:var(--fs-2)}
tr:hover .rowact,.rowact:focus-visible{opacity:1}
.link{color:var(--accent)}
.exp{border:0;background:transparent;color:var(--ink-2);cursor:pointer;padding:0 4px;font-size:15px}
.expand{background:var(--layer-2);border-radius:var(--r-2)}
.expand td{border-bottom:0;height:auto;padding:var(--sp-4) var(--sp-5)}

/* Строка, исключённая из показателей (коммуналка-транзит, пени, начисление без
   оплаты). Показывается приглушённо, но не прячется: деньги прошли, и бухгалтер
   обязан их видеть. Доходом при этом не считается. */
tr.excluded td{color:var(--ink-3)}
tr.excluded td.keep{color:var(--ink)}

/* Быстрые действия в строке реестра: появляются при наведении и по фокусу. */
.rowq{display:inline-flex;gap:var(--sp-1);opacity:0;transition:opacity var(--dur) var(--ease)}
tr:hover .rowq,.rowq:focus-within{opacity:1}
.rowq button{height:26px;padding:0 8px;border-radius:var(--r-2);border:1px solid var(--line-2);
             background:var(--panel);color:var(--ink-2);font:var(--fw) var(--fs-1)/1 var(--font);
             cursor:pointer;white-space:nowrap}
.rowq button:hover{background:var(--layer-2);color:var(--ink)}
.rowq button[disabled]{opacity:.45;cursor:not-allowed}
.rowq button[disabled]:hover{background:var(--panel);color:var(--ink-2)}
.rowq button.btn-neg{color:var(--neg)}
/* В справочниках действия строки видны сразу: строк мало, они редкие,
   и «удалить нельзя» нужно увидеть до того, как потянешься мышью. */
[data-screen="settings"] .rowq{opacity:1}

/* ---------- Состояние записи справочника ---------- */
.state{font-size:var(--fs-1);color:var(--ink-2)}
.state.off{color:var(--ink-3)}
tr.dim td:not(.keep){color:var(--ink-3)}
[data-pane="usr"] td{height:auto;padding-top:9px;padding-bottom:9px}
[data-pane="usr"] td .faint{font-size:var(--fs-1)}

/* ---------- Постранично ---------- */
.pager{display:flex;align-items:center;gap:var(--sp-2);margin-top:var(--sp-4);
       font-size:var(--fs-1);color:var(--ink-2)}
.pager .pgs{display:flex;gap:2px;margin-left:auto}
.pager .pgs button{min-width:28px;height:28px;padding:0 6px;border:1px solid transparent;
       background:transparent;color:var(--ink-2);border-radius:var(--r-1);cursor:pointer;
       font-size:var(--fs-1);font-variant-numeric:tabular-nums}
.pager .pgs button:hover{background:var(--layer-2);color:var(--ink)}
.pager .pgs button[aria-current="true"]{background:var(--layer-2);color:var(--ink);
       font-weight:var(--fw-med);box-shadow:0 0 0 1px var(--line)}
.pager .pgs button[disabled]{opacity:.4;cursor:not-allowed}

/* Сортируемый заголовок: только дата и сумма. Конструктора фильтров в карточках
   нет — произвольные срезы живут в «Отчётах» (Р-63, Р-82.3). */
th.sort{cursor:pointer;user-select:none}
th.sort:hover{color:var(--ink)}
th.sort .ar{color:var(--ink-3)}
th.sort[aria-sort] .ar{color:var(--ink)}

/* ---------- Матрица отчёта «Прибыли и убытки» (макет 2.17, REQ-370) --------
   Единственная широкая таблица системы: строк немного, а колонок столько,
   сколько месяцев в окне. Отсюда три вещи, которых нет больше нигде:
   1. горизонтальная прокрутка живёт ВНУТРИ панели, а не у страницы — иначе
      соседние блоки уезжают вбок вместе с таблицей;
   2. первая колонка закреплена: уехав к декабрю, человек обязан видеть, что
      за строку он читает, — без этого матрица нечитаема уже на пятой колонке;
   3. колонка «Итого» отделена ФОНОМ, а не жирностью: жирность в таблице уже
      занята итоговыми СТРОКАМИ, и два разных смысла одним средством
      различать нельзя. */
.xscroll{overflow-x:auto;margin:0 calc(-1 * var(--sp-5));padding:0 var(--sp-5)}
.matrix{overflow-x:auto;margin:0 calc(-1 * var(--sp-5));padding:0 var(--sp-5)}
.matrix table{width:auto;min-width:100%}
.matrix td{white-space:nowrap;height:36px;padding-left:var(--sp-2);padding-right:var(--sp-2)}
.matrix th{padding-left:var(--sp-2);padding-right:var(--sp-2)}
.matrix th.lbl,.matrix td.lbl{position:sticky;left:0;z-index:1;background:var(--panel);
      text-align:left;white-space:nowrap;min-width:210px}
.matrix tbody tr:hover td.lbl{background:var(--layer-2)}
/* 🔧 2.31 (находка 7 UX-аудита). КОЛОНКА «ИТОГО» ЗАКРЕПЛЕНА СПРАВА — тем же
   приёмом, каким слева закреплена колонка названий строк. Тринадцать колонок
   на экран не помещаются: видно по «июн 26», дальше нужна прокрутка. То есть
   две колонки, ради которых отчёт и открывают, — последний месяц и годовой
   итог, — не были видны при открытии НИКОГДА.
   Левая граница отделяет итог от месяцев: фон у него был и раньше, но у
   закреплённой колонки фон работает как «она поверх», а не как «она другая». */
.matrix th.tc,.matrix td.tc{background:var(--layer-2);position:sticky;right:0;z-index:1;
      border-left:1px solid var(--line-2)}
.matrix tbody tr:hover td.tc{background:var(--layer-2)}
/* Ноль в матрице — не новость: приглушается, чтобы глаз цеплялся за числа,
   которые есть. Красным по-прежнему только убыток (Р-98, палитра). */
.matrix td.z{color:var(--ink-3)}
tr.tot td{font-weight:var(--fw-med);border-top:1px solid var(--line-2)}
/* Справочные строки — та же таблица, но в прибыль они не входят. Отделяет их
   не цвет и не размер, а приглушённая подпись строки: цвет здесь занят. */
tr.ref td.lbl{color:var(--ink-2)}
/* «12 месяцев» в две строки ломало высоту всей полосы фильтров. */
#pnlDepth button{white-space:nowrap}
/* Действующая ставка договора показывается текстом, а не полем ввода
   (📌 Р-105): значение читается как значение, а не как пустая форма. */
.field .value{margin:0;padding:7px 0;font-size:var(--fs-2)}

/* Пометка при значении (макет 2.15) и причина прочерка (2.16). Оба — про
   число, у которого другой знаменатель или которого нет вовсе. Ни один не
   красный: красным в системе отмечаются убыток и долг, а другой знаменатель
   не плохая новость. Токены только имеющиеся (Р-60). */
.mark{display:inline-block;font-size:var(--fs-1);color:var(--ink-2);
      border:1px solid var(--line-2);border-radius:var(--r-1);
      padding:0 5px;margin-left:6px;white-space:nowrap;vertical-align:1px;
      text-decoration:none}
.why{display:block;font-size:var(--fs-1);color:var(--ink-3);
     white-space:normal;line-height:1.3;margin-top:1px}

/* ---------- Полоски ---------- */
.meter{display:inline-flex;align-items:center;gap:8px}
.meter .track{width:40px;height:6px;border-radius:var(--r-1);background:var(--track);overflow:hidden}
.meter .fill{height:100%;background:var(--seq-3);border-radius:var(--r-1)}
.meter .pct{font-variant-numeric:tabular-nums;min-width:44px;text-align:right}
.meter.wide .track{width:120px;height:8px}

/* ---------- Список полос (структура расходов) ----------
   Все категории показываются полностью: ограничение «не более пяти» снято
   заказчиком. Идентичность несёт подпись слева, а не цвет — поэтому тон один. */
.bars{display:grid;grid-template-columns:1fr 3fr auto auto;gap:6px var(--sp-4);align-items:center}
.bars .bar{height:8px;border-radius:var(--r-1);background:var(--seq-3)}
.bars .amt,.bars .shr{font-variant-numeric:tabular-nums;text-align:right}
.bars .shr{color:var(--ink-2);min-width:52px}
.cmpbar{display:inline-block;height:8px;border-radius:4px;background:var(--d-profit)}
.cmpbar.loss{background:var(--d-loss)}

/* ---------- Вкладки ---------- */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:var(--sp-5);
      flex-wrap:wrap}
.tabs button{border:0;background:transparent;padding:10px 16px;cursor:pointer;
             color:var(--ink-2);font-size:var(--fs-2);border-bottom:2px solid transparent;
             margin-bottom:-1px;border-radius:var(--r-2) var(--r-2) 0 0}
.tabs button:hover{color:var(--ink);background:var(--layer-2)}
.tabs button[aria-selected="true"]{color:var(--ink);font-weight:var(--fw-med);border-bottom-color:var(--accent)}
.tabs .cnt{color:var(--ink-3);font-weight:var(--fw);margin-left:6px}
.tabpane{display:none}
.tabpane.on{display:block}

/* ---------- Формы ---------- */
.field{display:flex;flex-direction:column;gap:var(--sp-1);margin-bottom:var(--sp-4)}
.field > label{font-size:var(--fs-1);color:var(--ink-2)}
.field .opt{color:var(--ink-3)}
/* 📌 Р-99 / REQ-355: постоянная подпись под полем — не подсказка по наведению.
   Видна с клавиатуры и с планшета, печатается вместе с формой. */
.field .hint{font-size:var(--fs-1);color:var(--ink-2);line-height:1.4;margin:0}
input[type=text],input[type=number],input[type=date],input[type=password],select,textarea{
  height:32px;padding:0 10px;border:1px solid var(--line-2);border-radius:var(--r-2);
  background:var(--panel);color:var(--ink);font:var(--fw) var(--fs-2)/1 var(--font);width:100%}
input:hover,select:hover{border-color:var(--ink-3)}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4)}
.row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--sp-4)}
@media (max-width:640px){.row2,.row3{grid-template-columns:1fr}}
.filters{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap;margin-bottom:var(--sp-3)}
.filters input[type=text]{width:280px}
.filters select{width:auto;min-width:120px}
/* 🔧 2.31 (находка 8): подпись у переключателя внутри полосы фильтров.
   Она называет то, чем управляет соседний орган, — без неё второй
   переключатель времени читается как второй период. */
.filters .fld-lbl{font-size:var(--fs-1);color:var(--ink-2);margin-left:var(--sp-2)}
.chk{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-2);color:var(--ink-2);cursor:pointer}
.chk input{width:auto;height:auto}
.found{margin-left:auto;font-size:var(--fs-1);color:var(--ink-2)}

/* ---------- Журнал изменений (REQ-165.1, 📌 Р-100) ----------
   Пометка «задним числом» намеренно НЕ красная. Правка прошлого — законная
   операция (Р-96), а не ошибка; красным в системе отмечается убыток и долг.
   Взято из макета 2.7 без изменений. */
.retro{display:inline-block;font-size:var(--fs-1);color:var(--ink-2);
       background:var(--layer-2);border-radius:var(--r-1);padding:1px 7px;
       margin-left:6px;white-space:nowrap}
[data-pane="log"] td{height:auto;padding-top:9px;padding-bottom:9px}
[data-pane="log"] td .faint{font-size:var(--fs-1);margin-top:2px}
.seg .cnt{color:var(--ink-3);font-weight:var(--fw);margin-left:6px}
.pay{width:100px}
.err{color:var(--neg);font-size:var(--fs-1);margin-top:var(--sp-1)}

/* Выбор уровня расхода. Уровня два (Р-64, Р-65: здание удалено), поэтому каждая
   карточка занимает половину ширины формы: промахнуться невозможно.
   Выбранность несёт не только цвет — ещё метка ● и рамка 2 px (Р-40). */
.levels{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3)}
@media (max-width:640px){.levels{grid-template-columns:1fr}}
.level{border:1px solid var(--line-2);border-radius:var(--r-2);padding:var(--sp-4);
       background:transparent;text-align:left;cursor:pointer;min-height:84px;
       color:var(--ink);font:inherit;display:grid;grid-template-columns:auto 1fr;
       column-gap:var(--sp-3);align-items:start}
.level:hover{background:var(--layer-2)}
.level::before{content:"○";font-size:16px;line-height:1.3;color:var(--ink-3);grid-row:1/3}
.level[aria-pressed="true"]::before{content:"●";color:var(--accent)}
.level b{grid-column:2;font-weight:var(--fw-med);font-size:var(--fs-3);letter-spacing:-.02em}
.level span{grid-column:2;display:block;font-size:var(--fs-1);color:var(--ink-2);margin-top:4px}
.level[aria-pressed="true"]{border-color:var(--accent);border-width:2px;padding:15px;
       background:var(--accent-bg)}

/* ---------- Счётчик последствий (📌 Р-95 · REQ-163 · макет 2.12) ----------
   Плашка под вопросом «изменение или исправление». Красного здесь нет
   намеренно, как и у пометки «задним числом» выше: правка прошлого — законная
   операция, а красным в системе отмечается убыток и долг. Вес плашке даёт
   заголовок и подложка, а не цвет. Взято из макета 2.12 без изменений. */
.impact{background:var(--layer-2);border-radius:var(--r-2);
        padding:var(--sp-4);margin-top:var(--sp-4)}
.impact > h3{font-size:var(--fs-3);letter-spacing:-.02em;font-weight:var(--fw-med);
             margin-bottom:var(--sp-3)}
.impact table{margin-bottom:var(--sp-3)}
.impact .sum{max-width:none;margin-bottom:var(--sp-3)}
.impact .note:first-of-type{border-top:1px solid var(--line);padding-top:var(--sp-3)}

/* ---------- Вход и смена пароля (📌 Р-103, макет 2.13) ----------
   Экран входа живёт ВНЕ оболочки: до входа нет ни меню, ни периода, ни имени
   пользователя, поэтому вся `.app` просто не показывается. Карточка — та же
   `.panel` с тенью модального окна, поля — те же `.field`. Ширина 360 px:
   три коротких поля и кнопка, шире делать не от чего.
   Новых токенов не заведено (Р-60): --neg и --neg-bg те же, что у убытка. */
.auth{display:none;flex-direction:column;align-items:center;justify-content:center;
      gap:var(--sp-4);min-height:88vh;padding:var(--sp-6) var(--sp-4)}
html[data-auth] .auth{display:flex}
html[data-auth] .app{display:none}
.auth-card{background:var(--panel);border-radius:var(--r-3);box-shadow:var(--shadow);
           width:100%;max-width:360px;padding:var(--sp-6)}
.auth-card .brand{font-size:var(--fs-1);color:var(--ink-2);padding:0;margin-bottom:var(--sp-5)}
.auth-card h1{margin-bottom:var(--sp-2)}
.auth-card .lead{color:var(--ink-2);font-size:var(--fs-1);line-height:1.4;
                 margin-bottom:var(--sp-5)}
.auth-card .field:last-of-type{margin-bottom:var(--sp-5)}
.btn.wide{width:100%;height:36px;justify-content:center}
/* Ошибка входа. Место постоянное — НАД полями, сразу под заголовком: ошибка,
   показанная под кнопкой, уезжает за нижний край на ноутбуке.
   ⚠️ Текст берётся из `message` ответа и у поля не подписывается (§2.1):
   разные подписи «логина нет» / «пароль неверен» превратили бы форму входа
   в способ узнать, кто работает в компании. */
.errbox{background:var(--neg-bg);color:var(--neg);border-radius:var(--r-2);
        padding:10px 12px;font-size:var(--fs-2);line-height:1.4;margin-bottom:var(--sp-4)}

/* ---------- Первый запуск (📌 Р-129, макет 2.36) ----------
   Единственный новый кирпич версии — граница внутри карточки, между
   организацией и учётной записью. Довод не оформительский: «Название
   организации» и «Имя» стоят подряд и оба спрашивают имя, а название
   организации после сохранения правится ТОЛЬКО девопсом в базе — экранного
   способа исправить опечатку нет и по Р-129 не заводится. Без границы две
   строки читаются как пара «организация — контактное лицо», и своё ФИО
   попадает в необратимое поле. Новых токенов ноль (Р-60).
   ⛔ Это НЕ стили снятого Р-98 мастера загрузки (`.first`, `.steps`, `.step`):
   те сняты и не возвращаются, здесь заводится одна строка-разделитель. */
.authgroup{font-size:var(--fs-1);color:var(--ink-2);
           margin:var(--sp-5) 0 var(--sp-3);padding-top:var(--sp-4);
           border-top:1px solid var(--line)}
/* Место под сообщение об отказе держится постоянно и здесь — правило одно на
   систему (U-32). Но под заголовком стоит ещё и пояснение, и два отступа
   подряд давали над первым полем провал, который на самом первом экране
   системы читается как «что-то не загрузилось». Отступ отдан сообщению, у
   пояснения снят: суммарная высота карточки та же. */
.auth-card[data-setup] .lead{margin-bottom:0}

/* ---------- Модальное окно ---------- */
.scrim{position:fixed;inset:0;background:var(--scrim);display:none;z-index:40;
       align-items:flex-start;justify-content:center;padding:6vh var(--sp-4);overflow:auto}
.scrim.on{display:flex}
.modal{background:var(--overlay);border-radius:var(--r-3);box-shadow:var(--shadow);
       width:100%;max-width:560px;max-height:88vh;overflow:auto}
.modal.wide{max-width:880px}
.modal-h{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
         padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line)}
.modal-b{padding:var(--sp-5)}
.modal-f{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:var(--sp-4) var(--sp-5);
         border-top:1px solid var(--line)}
.x{border:0;background:transparent;color:var(--ink-2);cursor:pointer;font-size:16px;
   width:28px;height:28px;border-radius:var(--r-2)}
.x:hover{background:var(--layer-2)}

/* ---------- Панель детали строки ---------- */
.drawer{position:fixed;top:0;right:0;height:100vh;width:420px;max-width:92vw;z-index:45;
        background:var(--overlay);box-shadow:var(--shadow);transform:translateX(100%);
        transition:transform var(--dur) var(--ease);overflow:auto;visibility:hidden}
.drawer.on{transform:none;visibility:visible}
.drawer-h{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-3);
          padding:var(--sp-5) var(--sp-5) var(--sp-4);border-bottom:1px solid var(--line)}
.drawer-b{padding:var(--sp-5)}
.dl{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-2) var(--sp-5);font-size:var(--fs-2)}
.dl dt{color:var(--ink-2);white-space:nowrap}
.dl dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}

/* ---------- Подсказка ---------- */
.tip{position:fixed;z-index:60;pointer-events:none;opacity:0;transition:opacity 100ms;
     background:var(--overlay);border-radius:var(--r-2);box-shadow:var(--shadow);
     padding:8px 10px;font-size:var(--fs-1);max-width:280px}
.tip.on{opacity:1}
.tip .t-m{color:var(--ink-2);margin-bottom:4px}
.tip .t-r{display:flex;align-items:center;gap:8px;justify-content:space-between}
.tip .t-k{display:flex;align-items:center;gap:6px;color:var(--ink-2)}
.tip .t-s{width:2px;height:10px;border-radius:1px;display:inline-block}
.tip .t-v{font-size:var(--fs-2);font-weight:var(--fw-med);font-variant-numeric:tabular-nums}
[data-tip]{cursor:help;text-decoration:underline dotted var(--ink-3);text-underline-offset:3px}

/* ---------- Диаграмма ---------- */
.chart{width:100%;height:auto;display:block}
.chart .g{stroke:var(--line);stroke-width:1}
.chart .ax{fill:var(--ink-3);font-size:11px;font-family:var(--font)}
.chart .b-inc{fill:var(--d-income)}
.chart .b-exp{fill:var(--d-expense)}
.chart .ln{fill:none;stroke:var(--d-profit);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.chart .dt{fill:var(--d-profit);stroke:var(--panel);stroke-width:2}
.chart .hit{fill:transparent}
.chart .hit:hover,.chart .hit:focus-visible{fill:var(--layer-2);fill-opacity:.8;outline:none}
.legend{display:flex;gap:var(--sp-4);font-size:var(--fs-1);color:var(--ink-2)}
.legend i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:6px;vertical-align:0}

/* ---------- Пустые состояния ---------- */
.empty{text-align:center;padding:var(--sp-7) var(--sp-5);max-width:520px;margin:0 auto}
.empty h3{font-size:var(--fs-3);margin-bottom:var(--sp-2)}
.empty p{color:var(--ink-2);margin-bottom:var(--sp-5)}
.acts{display:flex;gap:var(--sp-2);justify-content:center;flex-wrap:wrap}

/* 📌 Р-98: стилей экрана «Первый запуск» (.first, .steps, .step) здесь больше
   нет — экран снят, пустая система встречает пустым состоянием дашборда.
   Мёртвая разметка тянет за собой соблазн её вернуть, поэтому убрана. */

/* ---------- Прочее ---------- */
.note{font-size:var(--fs-1);color:var(--ink-2);margin-top:var(--sp-3)}
/* Модификатор .note, а не новый компонент (макет 2.29). Нужен ровно одному
   месту — предупреждению о дате отметки (REQ-352.2). Красным его красить
   нельзя: случай законный и частый (платёж за июль пришёл 5 августа), а
   красный в этой палитре означает убыток и долг. Серой строкой .note тоже
   нельзя: это единственная ошибка системы, которую не ловит ни один
   инвариант, — деньги сходятся в обоих месяцах, и человек не узнает, что
   доход уехал. Отсюда планка цветом акцента на существующих токенах. */
.note.warn{background:var(--layer-2);border-left:3px solid var(--accent);
           border-radius:var(--r-2);padding:10px 12px;color:var(--ink)}
.dz{border:1px dashed var(--line-2);border-radius:var(--r-3);padding:var(--sp-7);
    text-align:center;color:var(--ink-2)}
.tmpl{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-2) var(--sp-4);font-size:var(--fs-2)}
/* 🔧 2.31 (REQ-380.1): отметка загруженного шаблона — ОТДЕЛЬНОЙ СТРОКОЙ под
   именем файла. В строку с именем она не помещается: три колонки на экран, а
   фраза длиннее самого имени. */
.tmpl .done{display:block;font-size:var(--fs-1);color:var(--ink-2);margin-top:2px}
@media (max-width:800px){.tmpl{grid-template-columns:1fr}}
.chain{display:grid;grid-template-columns:auto 1fr auto;gap:6px var(--sp-3);font-size:var(--fs-2);
       font-variant-numeric:tabular-nums;margin-top:var(--sp-4)}
.chain .n{color:var(--ink-3)}
.chain .v{text-align:right}
.sum{display:grid;grid-template-columns:1fr auto;gap:6px var(--sp-4);font-variant-numeric:tabular-nums}
.sum .tot{border-top:1px solid var(--line-2);padding-top:6px;margin-top:2px;font-weight:var(--fw-med)}

/* Полоса сходимости расчёта (§1.9 контракта, REQ-209). Ответ остаётся 200, но
   числам верить нельзя — и это должно быть видно поверх экрана, а не в консоли. */
.integrity{background:var(--neg-bg);color:var(--ink);border-radius:var(--r-2);
           padding:var(--sp-3) var(--sp-4);margin-bottom:var(--sp-4);
           box-shadow:0 0 0 1px var(--neg);font-size:var(--fs-2)}
.integrity b{color:var(--neg)}
.integrity ul{margin:var(--sp-2) 0 0;padding-left:var(--sp-5);font-size:var(--fs-1);color:var(--ink-2)}
.integrity ul b{color:var(--ink)}
/* Тот же блок, когда сообщать не о чем плохом: отчёт о сохранении без отказов
   (Р-90.2). Нейтральный, а не зелёный — цветом в системе обозначается только
   убыток (Р-60), и «всё хорошо» не заслуживает собственного цвета. */
.integrity.good{background:var(--layer-2);box-shadow:0 0 0 1px var(--line-2)}
.integrity.good b{color:var(--ink)}

/* Полоса «показано по вашим объектам» (§1.5): менеджер обязан понимать, что
   итог — это его часть портфеля, а не компания. */
.scopenote{font-size:var(--fs-1);color:var(--ink-2);margin-top:var(--sp-3)}

/* Демонстрационный режим: подключён не сервер, а примеры ответов из контракта.
   Полоса исчезает вместе с переключением config.DATA_SOURCE на 'live'. */
.mockbar{background:var(--accent-bg);color:var(--ink);font-size:var(--fs-1);
         padding:8px var(--sp-3);border-radius:var(--r-2);margin-bottom:var(--sp-3)}

/* ---------- Всплывающие сообщения ---------- */
.toasts{position:fixed;right:var(--sp-5);bottom:var(--sp-5);z-index:70;
        display:flex;flex-direction:column;gap:var(--sp-2);max-width:420px}
.toast{background:var(--overlay);border-radius:var(--r-2);box-shadow:var(--shadow);
       padding:var(--sp-3) var(--sp-4);font-size:var(--fs-2)}
.toast.bad{box-shadow:var(--shadow),0 0 0 1px var(--neg);}
.toast.bad b{color:var(--neg)}
.toast .req{font-size:var(--fs-1);color:var(--ink-3);margin-top:4px}

/* ---------- Загрузка ---------- */
.loading{padding:var(--sp-7);text-align:center;color:var(--ink-3);font-size:var(--fs-1)}
