/* Оформление в духе Финтабло: светло-сиреневый фон, белые панели, синий акцент */

:root {
    --bg: #eff0f8;
    --panel: #ffffff;
    --border: #e4e6f2;
    --text: #2c2f45;
    /* Серый для второстепенного текста. Был #8b90a8 — контраст с белым
       около 3:1, и подписи под цифрами читались с трудом. Сейчас 6:1:
       текст остаётся второстепенным на вид, но читается без прищура. */
    --muted: #585d78;
    --accent: #4a5bc4;
    --accent-soft: #eceefb;
    --accent-dark: #3b4aa3;
    --income: #1f9d67;
    --outcome: #d9534f;
    /* Те же смыслы, но для мелкого текста. #d9534f на белом даёт 3.96:1,
       а на розовой плашке 3.47:1 — для 11-12 пикселей этого мало (нужно
       4.5:1). Крупные цифры остаются прежними: там контраста хватает,
       и менять их значило бы перекрасить весь раздел. */
    --outcome-text: #b02a2a;
    --income-text: #177047;
    --transfer: #7a6ff0;
    --row-hover: #f7f8fd;
    --shadow: 0 1px 3px rgba(44, 47, 69, .06), 0 6px 20px rgba(44, 47, 69, .04);
    --radius: 10px;
    --sidebar: 208px;
}

/* Половина «Люди» живёт на том же скине, но со своим акцентом: по цвету меню
   сразу видно, смотришь ты на деньги по банку или на людей по журналу записей. */
body.section-people {
    --accent: #1f8f6a;
    --accent-soft: #e5f4ee;
    --accent-dark: #17714f;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.45 -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- каркас ---------- */

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

.sidebar {
    width: var(--sidebar);
    flex: 0 0 var(--sidebar);
    background: var(--panel);
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    padding-bottom: 24px;
}

/* Граница между меню и содержимым: её можно тянуть мышкой.
   Названия отчётов в разделе «Люди» длинные и переносятся в две строки —
   одной ширины на оба раздела не хватает, поэтому её выбирает человек,
   а выбор запоминается в браузере (см. static/layout.js). */
.sidebar-resizer {
    flex: 0 0 5px;
    position: sticky;
    top: 0;
    height: 100vh;
    cursor: col-resize;
    background: var(--border);
    background-clip: content-box;
    border-left: 2px solid transparent;
    border-right: 2px solid transparent;
    transition: background-color .12s;
    z-index: 25;
}

.sidebar-resizer:hover,
.sidebar-resizer.dragging { background-color: var(--accent); }

/* Пока тянут — курсор не должен превращаться в текстовый над таблицами,
   а выделение текста мешает попасть в нужную ширину. */
body.resizing { cursor: col-resize; user-select: none; }

.logo {
    display: flex; align-items: center; gap: 8px;
    padding: 16px 18px; font-weight: 700; font-size: 17px; color: var(--accent);
}
.logo .mark {
    width: 26px; height: 26px; border-radius: 7px; background: var(--accent);
    color: #fff; font-size: 12px; display: flex; align-items: center; justify-content: center;
    flex: 0 0 26px;
}
/* Линия пульса рисуется currentColor, а цвет здесь белый: один и тот же файл
   знака работает и на синей плитке «Денег», и на зелёной у «Людей». */
.logo .mark svg { width: 20px; height: 20px; display: block; }


.nav-group { margin-top: 6px; }
.nav-title {
    padding: 9px 18px; color: var(--text); font-weight: 600; font-size: 13px;
    display: flex; align-items: center; gap: 8px;
}
.nav a {
    display: block; padding: 7px 18px 7px 40px; color: var(--text);
    font-size: 13.5px; border-left: 3px solid transparent;
}
.nav a:hover { background: var(--row-hover); text-decoration: none; }
.nav a.active {
    color: var(--accent); background: var(--accent-soft);
    border-left-color: var(--accent); font-weight: 600;
}
/* shtab#1824: колонка директоров. Директор и группа внутри него — тот же
   `.nav-group`; отличие только в отступе и весе заголовка. Экран, которого
   ещё нет или который пока не отвечает, — серая строка без ссылки. */
.nav-dir > .nav-title { font-weight: 700; font-size: 14px; }
.nav-sub > .nav-title { padding-left: 40px; font-weight: 500; color: var(--muted); }
.nav-sub .nav a, .nav-sub .nav .nav-stub { padding-left: 56px; }
.nav .nav-stub {
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
    padding: 7px 18px 7px 40px; color: var(--muted); font-size: 13.5px;
    border-left: 3px solid transparent; cursor: default;
}
.nav .nav-stub.active { color: var(--accent); background: var(--accent-soft); border-left-color: var(--accent); }
.nav .nav-stub .badge { font-size: 10.5px; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    background: var(--panel); border-bottom: 1px solid var(--border);
    padding: 11px 24px; display: flex; align-items: center; gap: 20px;
    position: sticky; top: 0; z-index: 20;
}
.topbar .biz { color: var(--muted); font-size: 13.5px; }
.topbar .money { font-size: 17px; font-weight: 600; margin-left: auto; }
.topbar .money small { color: var(--muted); font-weight: 400; font-size: 12px; display: block; }

.content { padding: 22px 24px 60px; }

h1 { font-size: 25px; margin: 0 0 18px; font-weight: 600; }
h2 { font-size: 17px; margin: 0 0 14px; font-weight: 600; }

/* ---------- панели ---------- */

.panel {
    background: var(--panel); border-radius: var(--radius);
    box-shadow: var(--shadow); padding: 18px 20px; margin-bottom: 16px;
}
.panel.tight { padding: 12px 16px; }
/* Кнопка, открывающая три кнопки ввода операции. На большом экране она
   не нужна: там три кнопки помещаются и стоят открытыми. */
/* .btn объявлен ниже и с тем же весом перебивал display: none —
   кнопка вылезала на большом экране, где прятать нечего. */
.btn.add-ops-btn { display: none; }
.panel-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; margin-bottom: 16px; }
.card { background: var(--panel); border-radius: var(--radius); box-shadow: var(--shadow); padding: 16px 18px; }
.card .label { color: var(--muted); font-size: 13px; margin-bottom: 6px; }
.card .value { font-size: 21px; font-weight: 600; }

/* ---------- элементы управления ---------- */

.btn {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    border: 1px solid var(--border); background: var(--panel); color: var(--text);
    padding: 7px 14px; border-radius: 8px; font-size: 13.5px; font-family: inherit;
    text-decoration: none;
}
.btn:hover { background: var(--row-hover); text-decoration: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-dark); }
.btn-income { background: var(--income); border-color: var(--income); color: #fff; }
.btn-outcome { background: var(--outcome); border-color: var(--outcome); color: #fff; }
.btn-transfer { background: var(--transfer); border-color: var(--transfer); color: #fff; }
.btn-income:hover, .btn-outcome:hover, .btn-transfer:hover { opacity: .9; }
.btn-sm { padding: 4px 10px; font-size: 12.5px; }

/* Кнопки исхода: цвет говорит, чем кончится нажатие, а не украшает ряд.
   Заливка мягкая, а не сплошная, — на планёрке рядом стоят три кнопки,
   и сплошной светофор перетягивает внимание с текста вопроса на себя.
   Синий — разговор, зелёный — вопрос закрыт решением, красный — снят
   без решения, песочный — решение не сработало и вопрос вернулся. */
.btn-talk { background: var(--accent-soft); border-color: #c9cff2; color: var(--accent-dark); }
.btn-talk:hover { background: #e0e4fa; }
.btn-ok { background: #e6f5ee; border-color: #b9e0cd; color: #146b48; }
.btn-ok:hover { background: #d8eee3; }
.btn-drop { background: #fdeceb; border-color: #f3c6c4; color: #a33b37; }
.btn-drop:hover { background: #f9dedc; }
.btn-back { background: #fdf3e0; border-color: #ecd8ac; color: #8a6415; }
.btn-back:hover { background: #f8ead0; }

.tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.tabs a {
    padding: 6px 14px; border-radius: 8px; color: var(--text); font-size: 13.5px;
    border: 1px solid transparent;
}
.tabs a:hover { background: var(--row-hover); text-decoration: none; }
.tabs a.active { background: var(--accent); color: #fff; }

input[type=text], input[type=date], input[type=number], input[type=month],
input[type=password], select, textarea {
    border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px;
    font: inherit; font-size: 13.5px; color: var(--text); background: #fff;
    max-width: 100%;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
label { font-size: 13px; color: var(--muted); display: block; margin-bottom: 3px; }

.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.filters .field { display: flex; flex-direction: column; }

/* ---------- таблицы ---------- */

/* Тень у правого края, пока таблица не докручена до конца: без неё
   на телефоне не видно, что за краем есть ещё колонки. Тень рисуется
   фоном самой рамки и исчезает сама, когда прокручивать больше нечего. */
/* Таблица занимает всю ширину обёртки.
   Правило width: 100% стоит у table.grid и table.report, но шесть таблиц
   в разделах «Директор» и «Совет» написаны голым <table>. Внутри
   .table-wrap с overflow-x они сжимались по содержимому: на планшете
   1280 таблица трекера проектов занимала 319 пикселей из 1019, колонка
   «Проект» — 52, названия ломались на три строки, а справа стояло
   пустое поле в половину окна. */
.table-wrap > table { width: 100%; }

.table-wrap {
    overflow-x: auto;
    background:
        linear-gradient(to right, var(--panel) 30%, rgba(255, 255, 255, 0)) left / 24px 100% no-repeat,
        linear-gradient(to left, var(--panel) 30%, rgba(255, 255, 255, 0)) right / 24px 100% no-repeat,
        radial-gradient(farthest-side at 0 50%, rgba(44, 47, 69, .14), transparent) left / 11px 100% no-repeat,
        radial-gradient(farthest-side at 100% 50%, rgba(44, 47, 69, .14), transparent) right / 11px 100% no-repeat;
    background-attachment: local, local, scroll, scroll;
}
table.grid { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.grid th {
    text-align: right; color: var(--muted); font-weight: 600; font-size: 12px;
    text-transform: uppercase; letter-spacing: .03em;
    padding: 9px 10px; border-bottom: 1px solid var(--border); white-space: nowrap;
}
table.grid th:first-child, table.grid td:first-child { text-align: left; }
table.grid td { padding: 9px 10px; border-bottom: 1px solid var(--border); text-align: right; white-space: nowrap; }
table.grid tbody tr:hover { background: var(--row-hover); }
table.grid td.text, table.grid th.text { text-align: left; white-space: normal; }

.num { font-variant-numeric: tabular-nums; }
.income { color: var(--income); }
.outcome { color: var(--outcome); }
.muted { color: var(--muted); }
.nowrap { white-space: nowrap; }

.badge {
    /* 12,5px, как у .btn-sm: 11,5px у 100 кнопок «Правило» на ленте разбора — ниже
       читаемого (design-critique shtab#1631/#1663, 13.09.2026); зеркало в Фокусе то же. */
    display: inline-block; padding: 1px 8px; border-radius: 20px; font-size: 12.5px;
    background: var(--accent-soft); color: var(--accent-dark);
}
.badge.warn { background: #fdf0e3; color: #b4700f; }
.badge.grey { background: #f0f1f6; color: var(--muted); }
/* закрытый месяц: число окончательное и правкой задним числом не
   меняется (shtab#718). Зелёный тот же, что у «считается само» */
.badge.zakryt { background: #e8f7ef; color: #1a7a4f; }

/* важность отклонения: красный — смотреть сразу, жёлтый — при разборе месяца */
.badge.sev-high { background: #fdeaea; color: #b02a2a; }
.badge.sev-medium { background: #fdf0e3; color: #b4700f; }
.badge.sev-low { background: #f0f1f6; color: var(--muted); }

.alert-row td { vertical-align: top; padding-top: 10px; padding-bottom: 10px; }
.alert-row .badge { margin-right: 6px; }

button.mini {
    font: inherit; font-size: 12.5px; padding: 4px 10px; margin-right: 4px;
    border: 1px solid var(--border); border-radius: 7px;
    background: #fff; color: var(--text); cursor: pointer;
}
button.mini:hover { background: var(--accent-soft); border-color: transparent; }

.inline-form { display: inline-flex; gap: 8px; align-items: center; }

/* ---------- отчёты ---------- */

table.report { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.report th {
    position: sticky; top: 0; background: var(--panel); z-index: 2;
    text-align: right; color: var(--muted); font-weight: 600; font-size: 12px;
    text-transform: uppercase; padding: 10px 12px; border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
table.report th:first-child { text-align: left; left: 0; z-index: 3; min-width: 280px; }
/* Шапка месяца — заглавными; отметка статуса под ней читается как
   обычный текст, иначе «СВЕРЕН» кричит громче самого месяца. */
table.report th .mstat { text-transform: none; font-weight: 400; margin-top: 4px; }
table.report td { padding: 8px 12px; text-align: right; white-space: nowrap; border-bottom: 1px solid #f2f3fa; }
table.report td:first-child {
    text-align: left; position: sticky; left: 0; background: var(--panel); z-index: 1;
}
table.report tr:hover td { background: var(--row-hover); }
table.report tr.group > td { font-weight: 600; }
table.report tr.subtotal > td, table.report tr.total > td {
    background: #f7f8fd; font-weight: 600; border-top: 1px solid var(--border);
}
table.report tr.subtotal td:first-child, table.report tr.total td:first-child { background: #f7f8fd; }
table.report tr.total > td { font-size: 14.5px; }
/* Подпись под числом плана: почему числа нет или из чего оно сложилось
   (shtab#1816, app/templates/_plan_yachejka.html). Мельче числа, без веса. */
table.report .cell-note { font-size: 12px; line-height: 1.3; margin-top: 2px; font-weight: 400;
    max-width: 170px; margin-left: auto; white-space: normal; }
table.report tr.ratio td { color: var(--muted); font-size: 12.5px; }
table.report tr.ratio td:first-child { padding-left: 26px; }
table.report .lvl1 td:first-child { padding-left: 30px; font-weight: 400; }
table.report .lvl2 td:first-child { padding-left: 48px; font-weight: 400; }
table.report .lvl3 td:first-child { padding-left: 66px; font-weight: 400; }

/* ОПиУ (shtab#1404/#1441, отменено и переделано shtab#1492 п.2): направлений
   в шапке много, а имена длинные («Медицинская одежда [!Несалоны]») —
   общий `.report` не переносит заголовок и растягивает колонку по самому
   длинному слову.
   ПЕРВАЯ версия (10.09.2026) сжимала padding — владелец забраковал 11.09:
   давало горизонтальный скролл, колонки выглядели пережатыми. Отступы
   (padding) НЕ трогаем — они те же, что у общего `.report`. Вместо сжатия
   ширины: `table-layout: fixed` держит таблицу в 100% контейнера (без
   выхода за экран, без скролла) и заставляет длинный заголовок переноситься
   ВНУТРИ своей доли ширины, а не раздувать колонку под самое длинное слово.
   Шрифт заголовка чуть меньше (11px вместо 12) — для того же переноса
   нужно меньше строк. Не трогаем общий `table.report` — на нём ещё 30+
   других экранов с короткими заголовками. */
table.report.report-opiu { table-layout: fixed; }
.table-wrap table.report.report-opiu th {
    /* Специфичность выше строки 1407 (`.table-wrap table.report th`,
       мобильный брейкпоинт ≤900px) — та молча возвращала nowrap здесь же
       при более узком окне, и перенос переставал работать именно там,
       где он нужнее всего. */
    /* Перенос ТОЛЬКО по границам слов: `word-break: break-word` рвал
       «МЕДИЦИНСК/АЯ ОДЕЖДА» посередине слова — владелец забраковал
       11.09.2026 вместе с той же болезнью в подписях строк. */
    white-space: normal; word-break: normal; overflow-wrap: normal;
    line-height: 1.25; font-size: 11px; vertical-align: bottom;
}
/* shtab#1492: длинные подписи строк («Операционная прибыль (ОП, EBITDA)»,
   «Валовая прибыль по направлениям (ВП1)») наезжали на первую колонку
   данных — table-layout:fixed сузил первую колонку, а `nowrap` общего
   table.report td (строка 285) заставлял текст вылезать вправо ЗА
   границу ячейки, поверх соседней.
   ПЕРВАЯ попытка чинила это `word-break: break-word` — владелец
   забраковал 11.09.2026 скриншотом: слова рвались посередине
   («Производствен/ные расходы»), читать невозможно. Перенос разрешён
   ТОЛЬКО по границам слов, а колонке дана явная ширина: при
   table-layout:fixed `min-width` не держит — ширину назначает первая
   строка, и без явного `width` колонка схлопывается тем сильнее, чем
   больше направлений в шапке. */
.table-wrap table.report.report-opiu th:first-child,
.table-wrap table.report.report-opiu td:first-child {
    width: 300px;
    white-space: normal;
    word-break: normal;
    overflow-wrap: normal;
    text-wrap: pretty;
    line-height: 1.35;
}
/* Цифры одной ширины: при сворачивании/разворачивании строк колонка не
   дёргается, разряды стоят друг под другом. */
.table-wrap table.report.report-opiu td.num { font-variant-numeric: tabular-nums; }
/* Колонка «Итого» (shtab#1542, критика вёрстки 11.09.2026): при
   table-layout:fixed ширина делится поровну, и самое длинное число
   отчёта — итог по компании — обрезалось справа («-28 506 229,0»).
   Ей нужна своя ширина, и она же отделена чертой, как в эталоне
   «Финтабло»: итог не должен сливаться с колонками направлений. */
.table-wrap table.report.report-opiu th.itogo,
.table-wrap table.report.report-opiu td.itogo {
    width: 150px;
    border-left: 1px solid var(--border);
    background: #fbfbfe;
    font-weight: 600;
}

/* ДДС (shtab#1686): заголовки колонок остаются с брендом в скобках
   («ТОЧКА ТРЕХГОРКА [ТОЧКА КРАСОТЫ]»), но у длинных имён переносятся на
   вторую строку вместо горизонтального скролла — тот же приём, что и у
   ОПиУ чуть выше (shtab#1492): `table-layout: fixed` держит таблицу в
   ширине контейнера, перенос только по границам слов. */
table.report.report-cashflow { table-layout: fixed; }
.table-wrap table.report.report-cashflow th {
    white-space: normal; word-break: normal; overflow-wrap: normal;
    line-height: 1.25; font-size: 11px; vertical-align: bottom;
}
.table-wrap table.report.report-cashflow th:first-child,
.table-wrap table.report.report-cashflow td:first-child {
    width: 220px;
}
.table-wrap table.report.report-cashflow th.itogo,
.table-wrap table.report.report-cashflow td.itogo {
    width: 150px;
    border-left: 1px solid var(--border);
    background: #fbfbfe;
    font-weight: 600;
}

.zero { color: #c9cbd8; }

/* редактируемая ячейка: выглядит как текст, списком становится по клику */
.cell-edit {
    display: inline-block; border: 1px solid transparent; padding: 2px 6px;
    border-radius: 6px; cursor: pointer; min-width: 90px;
}
.cell-edit:hover { border-color: var(--border); background: #fff; }
/* Было #b4700f — контраст с плашкой 3.72:1, ниже нормы 4.5:1. Это самый
   важный сигнал на экране операций («без статьи» = здесь работа), и он
   читался хуже обычного текста. Сейчас 5.74:1 (замер 11.09.2026,
   shtab#1560); оттенок остался тем же, изменилась только светлота. */
.cell-edit.unset { color: #8a5600; background: #fdf6ec; }
.cell-edit.saved { border-color: var(--income); background: #eaf7f0; }
.cell-edit.failed { border-color: var(--outcome); background: #fdecec; }
select.cell-select { max-width: 260px; font-size: 13px; padding: 2px 4px; }

/* Выпадашка с поиском для ячейки. Живёт в body, а не в строке таблицы:
   внутри ячейки её обрезала бы горизонтальная прокрутка таблицы. */
.cellpick {
    position: fixed; z-index: 120; width: 320px; max-width: calc(100vw - 16px);
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
.cellpick-search {
    width: 100%; border: 0; border-bottom: 1px solid var(--border);
    padding: 10px 12px; font-size: 14px; color: var(--text); background: #fff;
}
.cellpick-search:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.cellpick-list { list-style: none; margin: 0; padding: 4px 0; max-height: 288px; overflow-y: auto; }
.cellpick-list li {
    padding: 9px 12px; cursor: pointer; font-size: 13.5px; line-height: 1.3;
    min-height: 40px; display: flex; align-items: center;
}
.cellpick-list li.current { color: var(--accent); font-weight: 600; }
.cellpick-list li.active { background: var(--accent-soft); }
.cellpick-empty { color: var(--muted); cursor: default; }

/* На телефоне пункт списка — цель для пальца, а не для мыши. */
@media (max-width: 720px) {
    .cellpick-list li { min-height: 44px; font-size: 15px; }
}

/* Подробности внутри строки таблицы: «5 точек» разворачивается в список
   «какая точка сколько».

   Сделано раскрытием, а не второй таблицей рядом. Две таблицы об одном
   предмете на одной странице спутать легче, чем прочитать: у нас так уже
   вышло с двумя платёжными календарями — по ИП и по точке. Свёрнутое
   состояние оставляет страницу такой же, как была; развёрнутое отвечает
   на второй вопрос, не заводя второго экрана.

   Строки таблицы, склеенные colspan, layout.js в карточки не разбирает —
   поэтому подробности живут ВНУТРИ ячейки, а не отдельной строкой снизу:
   иначе на телефоне они выпали бы из карточки. */
.row-more > summary {
    cursor: pointer; color: var(--muted); font-size: 12.5px;
    /* Цель для пальца: 44 пикселя по высоте вместе с отступами строки. */
    padding: 6px 0; list-style-position: inside;
    /* «4 точки» не переносится: колонка узкая, и подпись раскрытия,
       разорванная на две строки, читается как две разные метки. */
    white-space: nowrap;
}
.row-more > summary:hover { color: var(--text); }
.row-more[open] > summary { color: var(--text); font-weight: 600; }
.row-more-list {
    list-style: none; margin: 2px 0 6px; padding: 0;
    font-size: 12.5px; line-height: 1.5; white-space: normal;
}
.row-more-list li { padding: 2px 0; }

@media (max-width: 720px) {
    .row-more > summary { min-height: 44px; display: flex; align-items: center; }
    .row-more-list { font-size: 13.5px; }
}

/* ---------- вспомогательное ---------- */

.pagination { display: flex; gap: 6px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
.pagination a, .pagination span {
    padding: 5px 10px; border-radius: 7px; border: 1px solid var(--border);
    background: #fff; font-size: 13px;
}
.pagination .current { background: var(--accent); color: #fff; border-color: var(--accent); }

.empty { padding: 40px; text-align: center; color: var(--muted); font-size: 14px; }

/* Плашка «почему список выглядит не так, как вы ждали». Ставится там, где
   фильтр пришёл со стороны — например, из отчёта по начислению. */
.notice {
    background: var(--accent-soft); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 10px 14px; font-size: 13px;
    color: var(--text); line-height: 1.45;
}
.notice a { margin-left: 4px; }

/* Норма на текущую дату под фактом: второстепенная строка, но читаемая.
   Красной становится, когда факт хуже нормы, — тогда её и надо заметить. */
.pace { font-size: 11px; color: var(--muted); line-height: 1.3; margin-top: 2px; }
.pace.bad { color: var(--outcome-text); }

.flash { padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 13.5px; }
.flash.ok { background: #e8f7ef; color: #1a7a4f; }
.flash.err { background: #fdeceb; color: #a8322e; }

/* Итог обмена с ZenMoney — отметка рядом с кнопкой. Общий баннер сверху
   сдвигал всю страницу вниз ради «новых: 0». */
.sync-chip {
    background: #e8f7ef; color: #1a7a4f; border-radius: 8px;
    padding: 6px 10px; font-size: 12px; white-space: nowrap; margin-top: 5px;
}

.dropzone {
    border: 2px dashed var(--border); border-radius: var(--radius); padding: 34px;
    text-align: center; color: var(--muted); background: #fbfbfe;
}
.dropzone.over { border-color: var(--accent); background: var(--accent-soft); }

/* ---------- панель управления отчётом ---------- */

.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }

.period-nav { display: flex; align-items: center; gap: 2px; position: relative; }
.period-nav .step {
    width: 28px; height: 32px; display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 8px; color: var(--muted);
    background: #fff; text-decoration: none; font-size: 16px;
}
.period-nav .step:hover { background: var(--accent-soft); color: var(--accent); text-decoration: none; }
.period-btn {
    background: var(--accent-soft); border: 1px solid transparent; color: var(--accent-dark);
    font: inherit; font-weight: 600; font-size: 13.5px; padding: 7px 16px;
    border-radius: 8px; cursor: pointer; min-width: 150px;
}
.period-btn:hover { background: #e2e5f9; }

.period-menu {
    display: none; position: absolute; top: 40px; left: 30px; z-index: 40;
    background: #fff; border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 10px 30px rgba(44, 47, 69, .16); min-width: 240px; padding: 6px;
}
.period-menu.open { display: block; }
.period-menu .presets { display: flex; flex-direction: column; }
.period-menu .presets a {
    padding: 7px 12px; border-radius: 7px; color: var(--text); font-size: 13.5px;
}
.period-menu .presets a:hover { background: var(--row-hover); text-decoration: none; }
.period-custom {
    display: flex; align-items: center; gap: 6px; padding: 10px 8px 4px;
    border-top: 1px solid var(--border); margin-top: 6px;
}
.period-custom input[type=date] { width: 130px; }

.icon-btn {
    width: 34px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 8px; background: #fff; cursor: pointer;
    color: var(--muted); font-size: 15px; text-decoration: none; position: relative;
}
.icon-btn:hover { background: var(--accent-soft); color: var(--accent); text-decoration: none; }
.icon-btn sup { color: var(--accent); font-size: 18px; line-height: 0; }

.inline-form { display: inline-flex; }
.inline-check { color: var(--text); font-size: 13px; display: flex; align-items: center; gap: 5px; }

.tabs-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }

.filters-box {
    background: #fafbfe; border: 1px solid var(--border); border-radius: 10px;
    padding: 12px 14px; margin-bottom: 14px;
}
.filters-box.hidden { display: none; }
/* Кнопка, открывающая фильтры. Точка внутри — признак, что фильтр стоит:
   свёрнутый фильтр иначе незаметно врёт про число строк. */
.filters-btn { margin-bottom: 12px; }
.filters-btn::after { content: ' ▾'; color: var(--muted); }
.filters-btn .dot { color: var(--accent); font-weight: 700; }

/* ---------- модальное окно ---------- */

.modal {
    display: none; position: fixed; inset: 0; z-index: 100;
    background: rgba(44, 47, 69, .35); align-items: center; justify-content: center;
}
.modal.open { display: flex; }
.modal-box {
    background: #fff; border-radius: 12px; padding: 22px 24px; width: min(520px, 92vw);
    box-shadow: 0 20px 60px rgba(44, 47, 69, .25);
}
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.modal-head h2 { margin: 0; }
.modal-foot { margin-top: 18px; display: flex; align-items: center; gap: 12px; }

/* Настройки ОПиУ (shtab#1441) — своя модалка с разделами слева, шире
   обычной: пять панелей эталона «Финтабло» не влезают в узкий список. */
.modal-box.wide { width: min(760px, 94vw); display: flex; padding: 0; overflow: hidden; position: relative; }
.settings-tabs { flex: 0 0 210px; background: #f7f8fc; padding: 22px 0; border-right: 1px solid #ececf5; }
.settings-tabs button {
    display: block; width: calc(100% - 24px); margin: 2px 12px; text-align: left;
    padding: 11px 14px; border: 0; border-radius: 8px; background: none;
    cursor: pointer; color: var(--text); font-size: 13.5px;
}
.settings-tabs button.active { background: #eef0fb; color: var(--accent); font-weight: 600; }
/* shtab#1464: короткие вкладки (Валюта) не требуют внутренней прокрутки,
   длинные (Внешний вид, Статьи ввода) — требуют, и классическая полоса
   прокрутки Windows/Chrome (~15-17px) то появляется, то исчезает, меняя
   ширину карточки между вкладками. `scrollbar-gutter: stable` резервирует
   место под неё всегда — ширина не гуляет. */
/* shtab#1492 п.1: короткие вкладки (Валюта) и длинные (Внешний вид) давали
   разную высоту карточки — окно настроек прыгало при переключении вкладок.
   Высота фиксирована (не max-height), а не подстраивается под контент. */
.settings-panel {
    flex: 1; padding: 24px 26px; height: 72vh; overflow: auto;
    scrollbar-gutter: stable; display: flex; flex-direction: column;
}
/* Крестик закрытия сидит абсолютным углом карточки (см. modal-box.wide) —
   длинный заголовок вроде «Распределять косвенные доходы/расходы по
   направлениям» иначе наезжает на него и обрезается им же визуально. */
.settings-panel h2 { margin: 0 44px 16px 0; font-size: 17px; line-height: 1.3; }
.settings-pane { display: none; }
.settings-pane.active { display: block; }
.radio-row {
    display: flex; align-items: center; gap: 9px; padding: 9px 0;
    color: var(--text); font-size: 13.5px; margin: 0; cursor: pointer;
}
.settings-stub { color: var(--muted); font-size: 12px; margin-top: 2px; }
/* Разделитель между смысловыми блоками одной вкладки настроек (эталон
   «Финтабло» отбивает «Группировку ФОТ», список статей и т.п. тонкой
   линией — без неё вкладка читается одним слитным списком). */
.settings-divider { border: 0; border-top: 1px solid #ececf5; margin: 16px 0; }
.settings-subhead { font-weight: 600; font-size: 13.5px; color: var(--text); margin: 0 0 4px; }
.check-row {
    display: flex; align-items: center; gap: 9px; padding: 9px 0;
    color: var(--text); font-size: 13.5px; margin: 0; cursor: pointer;
    border-bottom: 1px solid #f2f3fa;
}
/* Та же строка с галочкой, но в ряд панели (shtab#1880, галочки
   источников в «Разборе неразнесённых»): без черты и отступов списка. */
.check-row.v-stroku { display: inline-flex; gap: 6px; padding: 0; border-bottom: 0; }
.istochniki-razbora { display: inline-flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* ---------- сворачивание групп ---------- */

tr.toggler > td:first-child, tr.row-toggler > td:first-child { cursor: pointer; }
/* shtab#1448, эталон владельца (docs/obrazcy-fintablo/svyortka-etalon-10-09/
   kak-hochu-svyortku.png): кружок с шевроном, не треугольник без фона —
   первая версия (голый треугольник) была ошибкой, эталон читали по
   словам постановки, не по картинке, картинка была другой. Свёрнуто —
   светлый кружок, серый шеврон вниз; развёрнуто — залитый кружок акцента,
   белый шеврон вверх. Один компонент на ОПиУ и ДДС, правка здесь. */
.caret {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; margin-right: 8px; vertical-align: middle;
    border-radius: 50%; background: var(--panel); border: 1px solid var(--border);
    transition: background-color .12s, border-color .12s;
}
.caret::before {
    content: ""; display: block; width: 7px; height: 7px;
    border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translate(-1px, -1px); transition: transform .12s, border-color .12s;
}
tr:not(.collapsed) .caret {
    background: var(--accent); border-color: var(--accent);
}
tr:not(.collapsed) .caret::before {
    border-color: #fff; transform: rotate(225deg) translate(-1px, -1px);
}

.pct { display: block; font-size: 12px; color: var(--muted); }

/* сумма-ссылка: открывает операции, из которых она сложилась */
a.drill { color: inherit; text-decoration: none; border-bottom: 1px dashed transparent; }
a.drill:hover { color: var(--accent); border-bottom-color: var(--accent); text-decoration: none; }

/* ---------- готовность правил зарплаты ---------- */

.rules-readiness {
    margin-top: 12px; padding: 10px 12px; border-radius: 8px; font-size: 12.5px;
}
.rules-readiness.ok { background: #f4f8f4; border: 1px solid #dbe7db; }
.rules-readiness.wait { background: #fdf6ec; border: 1px solid #f0e0c8; }

/* ---------- сверка выручки под ОПиУ ---------- */

/* Плашка стоит под таблицей, а не над ней: сначала цифры прибыли, за которыми
   пришли, потом оговорка о том, сколько из них дошло до счёта. */
.revenue-check {
    margin-top: 14px; padding: 12px 14px; border-radius: 10px;
    font-size: 13px; line-height: 1.5;
}
.revenue-check.ok { background: #f4f8f4; border: 1px solid #dbe7db; }
.revenue-check.alarm { background: #fdeaea; border: 1px solid #f2cdcd; }
.revenue-check.alarm b { color: #b02a2a; }
.revenue-check .muted { font-size: 12px; margin-top: 6px; }
.revenue-check-list { margin: 8px 0 0; padding-left: 20px; }
.revenue-check-list li { margin-bottom: 3px; }
.revenue-check-note { border-top: 1px solid rgba(0, 0, 0, .07); padding-top: 8px; }

/* ---------- тумблер и инструкция ---------- */

.instruction-toggle {
    display: flex; align-items: center; justify-content: center; gap: 12px;
    padding: 16px 0 10px; color: var(--text); font-size: 13.5px;
}
.switch {
    /* display явно: класс вешают и на <button> (сброс инлайновый по умолчанию
       не нужен), и на <span> (shtab#1441) — у span без display:inline-block
       width/height к inline-элементу не применяются, переключатель схлопывается
       в ширину 0 и наезжает на подпись рядом (найдено на мобильной ширине). */
    display: inline-block; vertical-align: middle;
    width: 40px; height: 22px; border-radius: 20px; border: 0; background: #d3d6e6;
    position: relative; cursor: pointer; padding: 0; transition: background .15s;
}
.switch i {
    position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
    background: #fff; border-radius: 50%; transition: left .15s;
}
.switch.on { background: var(--accent); }
.switch.on i { left: 21px; }
.switch-link { display: inline-flex; align-items: center; gap: 9px; }

/* Справку читают, когда что-то непонятно, — она обязана читаться легко.
   Серый текст на белом фоне выглядит аккуратно и не читается вовсе. */
.instruction .lead { color: var(--text); margin: 0 0 18px; font-size: 14.5px; }
.instruction-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px;
}
.instruction-block h3 { font-size: 14px; margin: 0 0 8px; }
.instruction-block ul { margin: 0; padding-left: 18px; }
.instruction-block li { margin-bottom: 7px; font-size: 13.5px; color: var(--text); line-height: 1.5; }

/* ---------- закрытие месяца ---------- */

.close-progress { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.close-progress .bar {
    width: 180px; height: 8px; border-radius: 6px; background: var(--border); overflow: hidden;
}
.close-progress .bar i { display: block; height: 100%; background: var(--income); }

.task-list { display: flex; flex-direction: column; }
.task {
    display: flex; gap: 12px; padding: 13px 0; border-bottom: 1px solid #f2f3fa;
    align-items: flex-start;
}
.task:last-child { border-bottom: 0; }
.task-check input { width: 17px; height: 17px; cursor: pointer; margin-top: 2px; }
.task-body { flex: 1; min-width: 0; }
.task-title { font-weight: 600; font-size: 14px; }
.task-done .task-title { text-decoration: line-through; color: var(--muted); font-weight: 400; }
.task-hint { color: #4a4e69; font-size: 12.5px; margin-top: 4px; }
.task-meta {
    display: flex; gap: 14px; flex-wrap: wrap; margin-top: 6px;
    font-size: 11.5px; color: var(--muted);
}
.task-auto {
    margin-top: 8px; font-size: 12.5px; padding: 6px 10px; border-radius: 7px;
    display: inline-block;
}
.task-count {
    display: inline-block; min-width: 40px; text-align: center; font-size: 11.5px;
    padding: 2px 6px; border-radius: 20px; background: #f0f1f6; color: var(--muted);
}
.task-count.full { background: #eaf7f0; color: #1a7a4f; }

.direction-marks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.direction-marks .mark {
    display: inline-flex; align-items: center; gap: 5px; margin: 0;
    padding: 3px 10px 3px 7px; border: 1px solid var(--border); border-radius: 20px;
    font-size: 12px; color: var(--text); cursor: pointer; background: #fff;
}
.direction-marks .mark:hover { border-color: var(--accent); }
.direction-marks .mark.on { background: #eaf7f0; border-color: #a8dcc0; color: #1a7a4f; }
.direction-marks input { width: 13px; height: 13px; cursor: pointer; }

.task-auto.ok { background: #eaf7f0; color: #1a7a4f; }
.task-auto.bad { background: #fdf0e3; color: #b4700f; }
/* Нечем проверить — не нарушение (shtab#723). Серый намеренно: жёлтый
   рядом с жёлтым читается как «тоже плохо», а тут учёт не заполнен. */
.task-auto.unknown { background: #f0f1f6; color: var(--muted); }
.task-auto a { margin-left: 6px; }

/* простая столбчатая диаграмма без внешних библиотек */
.chart { display: flex; align-items: flex-end; gap: 10px; height: 190px; padding-top: 8px; }
.chart-col { flex: 1; display: flex; flex-direction: column; align-items: center; height: 100%; }
.chart-col .bars {
    flex: 1; width: 100%; display: flex; align-items: flex-end;
    justify-content: center; gap: 3px;
}
.chart .bar { width: 44%; max-width: 26px; border-radius: 3px 3px 0 0; min-height: 2px; }
.chart .bar-in { background: var(--income); opacity: .85; }
.chart .bar-out { background: var(--outcome); opacity: .75; }
.chart-col:hover .bar { opacity: 1; }
.chart-label { font-size: 12px; color: var(--muted); padding-top: 6px; }
.legend-dot {
    display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 4px;
}
.legend-dot.in { background: var(--income); }
.legend-dot.out { background: var(--outcome); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* minmax(0, 1fr), а не 1fr: иначе широкая таблица внутри колонки
   растягивает саму колонку, и вбок уезжает вся страница, а не таблица. */
.grid-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .grid-2 { grid-template-columns: minmax(0, 1fr); } }

/* Правый угол шапки: сосед, шестерёнка, дверь — ровно в этом порядке и
   ровно так же на Пульте (решение Сергея 20.08.2026). Имя и роль отсюда
   убраны: они занимали место в самой дорогой части экрана, а прочитать их
   можно в профиле — туда и ведёт шестерёнка, там же управление
   пользователями. */
.whoami-wrap { margin-left: auto; }
/* Список в шторке нужен только на телефоне: на большом экране он стоит
   в шапке, а в меню был бы вторым таким же. */
.whoami-side { display: none; }
.whoami { display: flex; align-items: center; gap: 8px; font-size: 13px; }

/* Три угловые кнопки одного размера: разнобой в углу читается как
   случайность, а не как порядок. Квадрат 34 — палец на телефоне попадает,
   на большом экране не выпирает. */
.corner {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 34px; padding: 0 9px;
    border: 1px solid var(--border); border-radius: 10px;
    color: var(--muted); font-size: 16px; line-height: 1;
    background: transparent;
}
.corner:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
/* Сосед — со словом: иконка увела бы в другую систему молча, а переход
   туда стоит объявлять. Шрифт мельче значка, чтобы кнопки были одной высоты. */
.corner.neighbour { font-size: 13px; font-weight: 600; white-space: nowrap; }

/* Остатки по счетам в меню: сумма всегда на виду, список — по нажатию */
.money-total { position: relative; padding: 4px 14px 8px 18px; }
.money-total-btn {
    display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
    width: 100%; text-align: left; cursor: pointer; font-family: inherit;
    background: var(--accent-soft); border: 1px solid var(--border);
    border-radius: 9px; padding: 7px 10px; color: var(--text);
}
.money-total-btn:hover { border-color: var(--accent); }
.money-total-label { font-size: 11px; color: var(--muted); }
.money-total-sum { font-size: 15px; font-weight: 700; white-space: nowrap; }
/* shtab#730, пункт 2: та же тревога, что красит строку счёта ниже (var(--outcome-text),
   см. .money-total-row.alarm) — здесь на самой сумме, до клика в список. */
.money-total-sum.alarm { color: var(--outcome-text); }
/* shtab#1647: состав суммы (сколько счетов сложено) — заметно слабее
   самой суммы, не спорит с ней за внимание, но читается без прищура. */
.money-total-sostav { font-size: 11px; font-weight: 400; color: var(--muted); }
/* Список раскрывается внутри меню, а не поверх него: у боковой панели своя
   прокрутка, и всплывающая шире неё коробка обрезалась по правому краю —
   имена были видны, суммы нет. */
.money-total-menu {
    margin-top: 6px; background: var(--bg); border: 1px solid var(--border);
    border-radius: 9px; padding: 4px 0; max-height: 46vh; overflow-y: auto;
}
.money-total-head, .money-total-row {
    display: flex; justify-content: space-between; gap: 8px;
    padding: 5px 9px; font-size: 12px; align-items: baseline;
}
.money-total-row b, .money-total-head b { white-space: nowrap; }
.money-total-row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.money-total-head { border-bottom: 1px solid var(--border); margin-bottom: 3px; }
.money-total-head b { font-size: 13px; }
.money-total-row span { color: var(--text); }
/* Счёт вне общей суммы — блёклый: иначе он молча ломает сложение в уме */
.money-total-row.aside span, .money-total-row.aside b { color: var(--muted); }
.money-total-loading { padding: 9px; color: var(--muted); font-size: 12px; }
.money-total-foot {
    display: block; padding: 7px 9px 4px; font-size: 11.5px;
    border-top: 1px solid var(--border); margin-top: 3px;
}

/* Кнопка, выглядящая ссылкой: форма нужна ради POST, а рисовать её кнопкой
   в плотной таблице незачем. */
button.link {
    background: none; border: 0; padding: 0; cursor: pointer;
    color: var(--accent); font: inherit; font-size: 12.5px;
}
button.link:hover { text-decoration: underline; }

/* Таблица «свойство — значение» в профиле: заголовки слева и обычным
   текстом, иначе колонка подписей выглядит как шапка отчёта. */
table.grid.props th {
    text-align: left; text-transform: none; letter-spacing: 0;
    font-size: 12.5px; width: 45%; font-weight: 400;
}
table.grid.props td { text-align: left; }

/* Платёжный календарь: дни — колонки, время идёт слева направо.
   Тридцать одна колонка не помещается в экран, поэтому таблица прокручивается
   вбок, а колонка с названием строки остаётся приклеенной — иначе, доехав
   до 25-го числа, не понять, чей это остаток. */
/* Шрифт мельче обычного: в строке «Вся группа» стоят шестизначные суммы,
   а колонок 31. При масштабе браузера 125 % они первыми упирались
   в границу клетки и превращались в «1...». */
table.calendar-grid { font-size: 11px; white-space: nowrap; }
table.calendar-grid th, table.calendar-grid td { padding: 3px 2px; }
table.calendar-grid .sticky-col {
    position: sticky; left: 0; z-index: 2;
    background: #fff; text-align: left; min-width: 144px;
    box-shadow: 1px 0 0 var(--line);
}
table.calendar-grid thead .sticky-col, table.calendar-grid .group .sticky-col {
    background: var(--head-bg, #f6f7fb);
}
/* сегодняшний день — вертикальная линия, по ней видно границу факта и прогноза */
table.calendar-grid .is-today { box-shadow: inset 2px 0 0 var(--accent); }
table.calendar-grid .is-weekend { background: #fafbfd; }
/* провал: столько на счёте не будет */
table.calendar-grid .short { background: #fdecec; color: #a8323b; font-weight: 600; }

/* ---------- финансовый директор ---------- */

/* Окно ФД: разговор занимает главную колонку, всё вспомогательное — узкую
   боковую. На узком экране колонки складываются в одну, разговор остаётся
   первым: за ним сюда и приходят. */
.fd-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; }
@media (max-width: 1100px) { .fd-layout { grid-template-columns: 1fr; } }

.fd-chat { display: flex; flex-direction: column; gap: 14px; }
.fd-msg { border-radius: 10px; padding: 12px 14px; }
.fd-user { background: var(--accent-soft); }
.fd-fd { background: var(--row-hover); border: 1px solid var(--border); }
.fd-error { background: #fdecec; color: #a8323b; }
.fd-who {
    font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted); margin-bottom: 6px;
}
.fd-who .muted { text-transform: none; letter-spacing: 0; }

.fd-body > *:first-child { margin-top: 0; }
.fd-body > *:last-child { margin-bottom: 0; }
.fd-body p { margin: 8px 0; }
.fd-body h3, .fd-body h4, .fd-body h5 { margin: 14px 0 6px; font-size: 15px; }
.fd-body ul, .fd-body ol { margin: 8px 0; padding-left: 22px; }
.fd-body li { margin: 3px 0; }
.fd-body code { background: #f0f1f6; border-radius: 4px; padding: 1px 5px; font-size: 12.5px; }
.fd-body pre { background: #f7f8fd; border-radius: 8px; padding: 10px 12px; overflow-x: auto; }
.fd-body pre code { background: none; padding: 0; }
.fd-body table { margin: 10px 0; }
/* таблица в ответе не должна распирать страницу вбок */
.fd-body table { display: block; max-width: 100%; overflow-x: auto; }
.fd-report { font-size: 14.5px; }

.fd-ask textarea {
    width: 100%; border: 1px solid var(--border); border-radius: 8px;
    padding: 10px 12px; font: inherit; resize: vertical;
}
.fd-ask textarea:focus { outline: none; border-color: var(--accent); }

.fd-side .panel { margin-bottom: 14px; }
.fd-side h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted); margin: 0 0 8px; }
.fd-list { list-style: none; margin: 8px 0 0; padding: 0; font-size: 13px; }
.fd-list li { padding: 4px 0; border-top: 1px solid var(--border); }
.fd-list li:first-child { border-top: none; }
.fd-list .muted { font-size: 11.5px; margin-left: 4px; }
.fd-current > a { font-weight: 600; }

/* Кто делает задачу чек-листа: цвет отвечает на вопрос «это навсегда или
   пока». Серое — работа человека по существу, синее — недоделка программы. */
.badge.fd-kind-hands { background: #f0f1f6; color: #5c6178; }
.badge.fd-kind-part { background: #eef6ff; color: #2a6099; }
.badge.fd-kind-auto { background: #e8f7ef; color: #1a7a4f; }
.badge.fd-kind-todo { background: #fdf0e3; color: #b4700f; }
.badge.fd-kind-fd { background: var(--accent-soft); color: var(--accent-dark); }

/* Окно-мишень вместо системного поля файла: то показывает «Файл не выбран»
   и не поддаётся оформлению ни в одном браузере. Сюда файлы и перетаскивают,
   и выбирают кликом — можно сразу несколько. */
.fd-drop {
    display: block; padding: 14px 10px; text-align: center; cursor: pointer;
    border: 1.5px dashed var(--border); border-radius: 8px;
    font-size: 12.5px; color: var(--text);
}
.fd-drop .muted { font-size: 11.5px; }
.fd-drop.drag { border-color: var(--accent); background: var(--accent-soft); }
.fd-file-name { display: block; margin-top: 6px; }

/* Кружок ожидания. Нужен там, где страница честно ждёт ответа минуту-полторы:
   без движения на экране это неотличимо от «кнопка не нажалась». */
.spinner {
    display: inline-block; width: 12px; height: 12px; vertical-align: -1px;
    border: 2px solid currentColor; border-right-color: transparent;
    border-radius: 50%; animation: spin .7s linear infinite; margin-right: 6px;
}
@keyframes spin { to { transform: rotate(360deg); } }
.fd-wait { display: none; align-items: center; gap: 7px; }

/* Пока советник думает, окно висит на отправленной форме минуту-полторы.
   Крутящееся колесо тут не годится: оно одинаково выглядит и на первой
   секунде, и на сотой, и через полминуты человек начинает думать, что
   программа зависла. Поэтому вместо колеса — пульс, а рядом живые цифры:
   сколько идёт время и сколько советник уже надумал. */
.claude-pulse {
    display: inline-block; width: 13px; height: 13px; flex: none;
    background: #d97757; opacity: .85;
    animation: claude-pulse 1.6s ease-in-out infinite;
    /* восьмилучевая звезда: узнаваемый значок, а не безликая точка */
    clip-path: polygon(50% 0, 60% 34%, 93% 22%, 72% 50%, 93% 78%, 60% 66%,
                       50% 100%, 40% 66%, 7% 78%, 28% 50%, 7% 22%, 40% 34%);
}
@keyframes claude-pulse {
    0%, 100% { transform: scale(.8) rotate(0deg); opacity: .55; }
    50%      { transform: scale(1.15) rotate(45deg); opacity: 1; }
}
/* Цифры не должны прыгать вправо-влево при смене «1 м 9 с» на «1 м 10 с» */
.fd-wait-time { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
    .claude-pulse { animation-duration: 3.2s; }
}

/* Ответ после перезагрузки не должен оказываться под шапкой */
#last { scroll-margin-top: 24px; }

/* Предупреждение строкой. Раньше такие плашки рисовались классом .empty
   с отступом в 40 пикселей и текстом по центру — на календаре это съедало
   треть экрана ради одного предложения. */
.alert-line {
    padding: 10px 14px; margin: 12px 0; border-radius: 8px;
    font-size: 13.5px; line-height: 1.45; border-left: 3px solid transparent;
}
.alert-line.bad { background: #fdecec; color: #a8323b; border-left-color: #d9534f; }
.alert-line.warn { background: #fdf0e3; color: #8a5a10; border-left-color: #e0a800; }
.alert-line.good { background: #e8f7ef; color: #1a7a4f; border-left-color: #1f9d67; }

/* Две таблицы календаря — остатки по ИП и платежи одного счёта — стоят одна
   под другой и читаются вместе: «в этот день провал, вот какой платёж в нём
   стоит». Пока ширины колонок считались по содержимому, дни в них разъезжались,
   и сравнивать приходилось линейкой. Теперь сетка одинаковая и фиксированная,
   а вместе с ней пропал и горизонтальный ползунок у верхней таблицы. */
table.calendar-grid { table-layout: fixed; width: 100%; }
table.calendar-grid .sticky-col { width: 144px; min-width: 144px; }
/* последняя колонка — «Худший день» и «За месяц»; заголовку можно
   в две строки, иначе он обрезается раньше всех */
table.calendar-grid thead th:last-child,
table.calendar-grid tbody td:last-child,
table.calendar-grid tfoot td:last-child { width: 78px; }
table.calendar-grid thead th:last-child { white-space: normal; }
table.calendar-grid th, table.calendar-grid td { overflow: hidden; text-overflow: ellipsis; }

/* Список месяцев в выпадающем меню — в три колонки: полтора года одной
   колонкой не помещаются на экран. */
.period-menu.month-menu .presets {
    display: grid; grid-template-columns: repeat(3, minmax(120px, 1fr)); gap: 0 4px;
}
.period-menu.month-menu .presets a.current { font-weight: 700; background: var(--accent-soft); }

/* Ячейка с пояснением: текст переносится по строкам и не растягивает таблицу.
   Обычные ячейки отчёта живут в nowrap — числа рвать по строкам нельзя, —
   но объяснение в одну строку выталкивало страницу за экран, и появлялась
   горизонтальная прокрутка ради одного столбца. */
table.report td.wrap, table.grid td.wrap {
    white-space: normal; max-width: 520px; line-height: 1.4; text-align: left;
}

/* Подсказка у цифры — знак вопроса с всплывающим объяснением.
   Раньше жила в стилях раздела «Люди» и в «Деньгах» не работала:
   значок был, объяснение не появлялось. Всплывашка на CSS без
   скриптов, открывается и по наведению, и по фокусу с клавиатуры. */
.hint {
    display: inline-flex; position: relative; color: var(--muted);
    cursor: help; vertical-align: middle; margin-left: 4px; outline: none;
}
.hint:hover, .hint:focus { color: #4a5bc4; }
.hint-pop {
    /* Позиция считается в layout.js в момент показа, отсюда fixed. Раньше
       всплывашка стояла absolute внутри значка, и от этого было две беды:
       в покое она растягивала документ на 11 пикселей вправо (страница ехала
       вбок), а внутри таблицы с прокруткой её обрезало рамкой — объяснение
       было видно наполовину. Fixed не участвует в ширине страницы
       и не обрезается ничем. */
    position: fixed; left: 0; top: 0; z-index: 40;
    width: 280px; max-width: calc(100vw - 24px); padding: 9px 11px;
    background: #1f2537; color: #eef0f8; border-radius: 7px;
    font-size: 12px; line-height: 1.45; font-weight: 400; text-transform: none;
    letter-spacing: 0; text-align: left; white-space: normal;
    box-shadow: 0 6px 22px rgba(20, 24, 40, .28);
    opacity: 0; visibility: hidden; transition: opacity .12s;
}
.hint-pop::after {
    content: ''; position: absolute; top: 100%; left: 50%;
    margin-left: calc(-5px - var(--hint-nudge, 0px));
    border: 5px solid transparent; border-top-color: #1f2537;
}
.hint:hover .hint-pop, .hint:focus .hint-pop { opacity: 1; visibility: visible; }


/* ---------- сворачиваемое меню и советники ---------- */

.nav-title {
    display: flex; align-items: center; gap: 6px;
    cursor: pointer; user-select: none;
}
.nav-title:hover { color: var(--accent); }
.nav-icon { width: 18px; text-align: center; }
.nav-caret {
    margin-left: auto; font-size: 10px; transition: transform .15s;
    color: var(--muted);
}
.nav-group.collapsed .nav-caret { transform: rotate(-90deg); }
.nav-group.collapsed .nav { display: none; }

/* Кнопка советника в шапке. Это собеседник, а не пункт меню, поэтому она
   заметная и стоит рядом с названием бизнеса. */
.advisor-tabs { display: inline-flex; gap: 8px; }
/* Список совета в меню-шторке живёт только на телефоне: на большом
   экране совет стоит в шапке, а в меню он был бы вторым таким же. */
.advisor-tabs-side { display: none; }
.advisor-btn {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 6px 14px 6px 8px;
    background: transparent; border: 1px solid var(--border);
    border-radius: 10px; color: var(--text);
    font-weight: 600; font-size: 13.5px; line-height: 1.15;
}
.advisor-btn:hover { border-color: var(--accent); text-decoration: none; }
.advisor-btn.current small { color: rgba(255, 255, 255, .8); }
.advisor-face {
    font-size: 20px; background: #fff; border-radius: 8px;
    width: 32px; height: 32px; display: inline-flex;
    align-items: center; justify-content: center;
}

/* Цвет каждого директора совпадает с акцентом его раздела: по залитой
   вкладке видно, в чьём «кабинете» ты находишься. Будущие члены совета
   стоят с пометкой «скоро» — это план состава, а не кнопки. */
.advisor-btn.tab-fd { --tab: #4a5bc4; --tab-dark: #3b4aa3; }
/* Зелёный и оранжевый затемнены до нормы AA: белый текст на #1f8f6a давал
   контраст 4.04, на #c2571f — 4.49 при требуемых 4.5. Разница на глаз почти
   не видна, а надпись на залитой вкладке перестала расплываться. */
.advisor-btn.tab-kd { --tab: #1d8462; --tab-dark: #17714f; }
.advisor-btn.tab-db { --tab: #8a5a1f; --tab-dark: #6d4616; }
.advisor-btn.tab-dp { --tab: #7a3fb0; --tab-dark: #61328c; }
.advisor-btn.tab-mk { --tab: #be551e; --tab-dark: #9a4418; }
.advisor-btn.current {
    color: #fff;
    background: var(--tab, var(--accent));
    border-color: var(--tab-dark, var(--accent-dark));
}
.advisor-btn.soon {
    opacity: .55; cursor: default; border-style: dashed;
}
.advisor-btn.soon small { font-style: italic; }
@media (max-width: 1350px) {
    /* на узком экране будущие директора прячутся: работающие важнее плана */
    .advisor-btn.soon { display: none; }
}

/* Планёрка: вопросы одной кнопкой. Ровная сетка три на четыре,
   кнопки одной ширины — это подсказки, а не самостоятельные кнопки,
   поэтому они мелкие и не спорят с полем ввода. */
.fd-quick {
    margin-top: 14px; padding: 12px 14px 10px;
    background: var(--accent-soft); border-radius: 10px;
}
.fd-quick-title {
    font-size: 11px; font-weight: 600; letter-spacing: .06em; text-align: center;
    text-transform: uppercase; color: var(--accent-dark); margin-bottom: 8px;
}
.fd-quick-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
}
.fd-quick form { display: contents; }
.quick-q {
    cursor: pointer; font-family: inherit; font-size: 11.5px; width: 100%;
    padding: 5px 8px; border-radius: 8px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
    border: 1px solid transparent; background: #fff; color: var(--text);
    box-shadow: 0 1px 2px rgba(44, 47, 69, .08);
    text-align: left;
}
.quick-q .qq-icon { margin-right: 6px; }
.quick-q:hover { border-color: var(--accent); color: var(--accent); }
.quick-q:disabled { opacity: .5; cursor: default; }
@media (max-width: 1000px) { .fd-quick-grid { grid-template-columns: repeat(2, 1fr); } }

/* Большие разборы — четыре карточки: это главные кнопки планёрки,
   и выглядеть они должны весомее подсказок. */
.fd-presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
@media (max-width: 1000px) { .fd-presets { grid-template-columns: repeat(2, 1fr); } }
.preset-card {
    cursor: pointer; font-family: inherit; text-align: left; width: 100%;
    border: 1px solid var(--border); border-radius: 10px; background: #fff;
    padding: 12px 14px; transition: transform .1s, box-shadow .1s;
}
.preset-card:hover {
    border-color: var(--accent); transform: translateY(-1px);
    box-shadow: 0 4px 10px rgba(44, 47, 69, .10);
}
.preset-card .pc-icon { font-size: 19px; display: block; margin-bottom: 6px; }
.preset-card .pc-title { font-weight: 600; font-size: 13.5px; color: var(--text); }
.preset-card .pc-note { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.preset-card:disabled { opacity: .5; cursor: default; transform: none; }
/* =========================================================================
   Доступность: видимый фокус и переход к содержимому
   =========================================================================
   Раньше обводку по фокусу имели только поля ввода. Человек, который ходит
   по дашборду с клавиатуры, терял курсор на первой же ссылке меню —
   двадцать пунктов подряд выглядели одинаково. */

.skip-link {
    position: absolute; left: -9999px; top: 0; z-index: 200;
    background: var(--accent); color: #fff; padding: 10px 16px;
    border-radius: 0 0 8px 0; font-size: 13.5px;
}
.skip-link:focus { left: 0; text-decoration: none; }

:where(a, button, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 6px;
}

/* Анимации выключаем, если человек попросил об этом в системе:
   выезжающее меню и бегущие полосы — частая причина укачивания. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}

/* =========================================================================
   Телефон и планшет
   =========================================================================
   До этого дашборд существовал только в ширину ноутбука: меню в 208 пикселей
   занимало половину экрана телефона, а таблицы отчётов выдавливали страницу
   вбок целиком — прокручивалась не таблица, а весь макет вместе с шапкой.

   Разбираем это тремя приёмами:
   1. меню уезжает за край и открывается кнопкой (бургер) поверх содержимого;
   2. вертикальные отступы режем, чтобы цифры начинались на первом экране;
   3. всё, что шире экрана, прокручивается внутри своей рамки, а не страницей.  */

/* Кнопка меню. На большом экране её нет — меню и так на виду. */
.burger {
    display: none;
    width: 38px; height: 38px; flex: none; padding: 0;
    box-shadow: 0 2px 10px rgba(20, 24, 40, .12);
    align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 9px;
    background: #fff; color: var(--text); cursor: pointer;
}
.burger:hover { background: var(--accent-soft); color: var(--accent); }
.burger i {
    position: relative; display: block; width: 17px; height: 2px;
    background: currentColor; border-radius: 2px; transition: background .12s;
}
.burger i::before, .burger i::after {
    content: ''; position: absolute; left: 0; width: 17px; height: 2px;
    background: currentColor; border-radius: 2px; transition: transform .15s;
}
.burger i::before { top: -6px; }
.burger i::after { top: 6px; }
/* Открытое меню — тот же значок крестиком: закрыть можно там же, где открыл. */
body.nav-open .burger i { background: transparent; }
body.nav-open .burger i::before { transform: translateY(6px) rotate(45deg); }
body.nav-open .burger i::after { transform: translateY(-6px) rotate(-45deg); }

/* Затемнение под выехавшим меню: клик по нему закрывает. */
.nav-backdrop {
    display: none; position: fixed; inset: 0; z-index: 55;
    background: rgba(31, 35, 58, .45);
}

/* Крестик внутри выехавшего меню. На большом экране меню не выезжает —
   и закрывать нечего. */
.nav-close {
    display: none; margin-left: auto; width: 34px; height: 34px; flex: none;
    align-items: center; justify-content: center; padding: 0;
    border: 0; border-radius: 8px; background: none; cursor: pointer;
    color: var(--muted); font: inherit; font-size: 15px;
}
.nav-close:hover { background: var(--row-hover); color: var(--text); }

@media (max-width: 900px) {
    .burger, .nav-close { display: inline-flex; }
    body.nav-open .nav-backdrop { display: block; }
    /* Пока меню открыто, фон не прокручиваем: иначе, закрыв меню,
       человек оказывается в другом месте страницы. */
    body.nav-open { overflow: hidden; }

    /* Меню выезжает поверх содержимого. Ширину, выбранную мышкой
       на компьютере, здесь не применяем — на телефоне тянуть нечем,
       а сохранённые 560 пикселей закрыли бы экран целиком. */
    .sidebar {
        position: fixed; top: 0; left: 0; z-index: 60;
        width: min(82vw, 300px); flex-basis: auto;
        height: 100%; height: 100dvh;
        transform: translateX(-100%);
        transition: transform .18s ease-out;
        box-shadow: 0 0 40px rgba(31, 35, 58, .22);
        padding-bottom: max(24px, env(safe-area-inset-bottom));
        /* Шторка открывается во весь экран, поэтому в режиме приложения
           её верх заходит под строку состояния. В обычной вкладке вставка
           нулевая и отступ не появляется. */
        padding-top: env(safe-area-inset-top);
        overscroll-behavior: contain;
        /* Закрытое меню уезжает за край, но остаётся на странице: нажав Tab,
           человек отправлял фокус в два десятка невидимых ссылок и не понимал,
           где он. Прячет их от клавиатуры атрибут inert — его ставит
           layout.js; через CSS это не решается: visibility ломает выезд. */
    }
    body.nav-open .sidebar { transform: none; }

    .sidebar-resizer { display: none; }

    /* Пункты меню — под палец: 13 пикселей высоты пунктом не попасть.
       Отступ слева тоже режем: на узком экране он съедал треть строки,
       а названия отчётов в «Людях» и без того переносятся. */
    .nav-title { padding: 13px 16px 12px; }
    .pagination a, .pagination span { padding: 12px 14px; }
    .switch-section { margin: 4px 12px 10px; }
    .switch-section a { padding: 9px 0; font-size: 14px; }
    .logo { padding: 14px 16px; }

    /* Шапка: слева кнопка меню, справа главная цифра. Название бизнеса
       уходит — на 360 пикселях за него нечем платить. */
    /* Шапки на телефоне нет вовсе. От неё оставалась одна кнопка меню,
       а полосу она занимала во всю ширину и высотой 57 пикселей — на экране
       в 800 пикселей это тринадцатая часть высоты ни за что. Кнопка теперь
       висит в правом верхнем углу поверх содержимого и не уезжает
       при прокрутке; заголовок страницы держит от неё дистанцию. */
    .topbar { display: none; }
    .burger {
        position: fixed; z-index: 55;
        top: max(10px, env(safe-area-inset-top));
        right: max(10px, env(safe-area-inset-right));
    }
    /* Пока меню открыто, плавающая кнопка не нужна: закрыть его есть чем —
       крестик стоит в самом меню. Два крестика на экране читаются как две
       разные кнопки. */
    body.nav-open .burger { display: none; }

    /* «Кто вошёл» переезжает в конец шторки: имя, роль и ссылки — там, где
       их ищут, когда шапки нет. */
    .whoami-side {
        display: block; margin: 10px 12px 16px; padding-top: 12px;
        border-top: 1px solid var(--border);
    }
    .whoami-side .whoami { flex-wrap: wrap; gap: 10px; }

    /* Шапка на телефоне — это кнопка меню и «кто вошёл», больше ничего.
       Совет директоров занимал её целиком: пять вкладок в строку — 795
       пикселей, прокруткой видно одну, и кажется, что твоего директора нет.
       Поэтому из шапки он уходит в меню-шторку, где помещается списком. */
    .topbar .advisor-tabs { display: none; }
    .advisor-tabs-side {
        display: flex; flex-direction: column; gap: 6px;
        padding: 0 12px 12px; margin: 0;
    }
    .advisor-tabs-side .advisor-btn { width: 100%; padding: 7px 12px 7px 7px; }
    .advisor-tabs-side .advisor-btn small { display: block; }

    /* Кто вошёл: имя и роль остаются, ссылки прячем — они есть в профиле. */
    .whoami { margin-left: 12px; gap: 8px; }
    .whoami a { display: none; }
    .whoami .who { font-size: 12px; max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* Подсказка «?». Шириной ровно 280 пикселей и по центру над значком:
       у правого края таблицы половина текста уходила за экран, а прокрутить
       туда нечего — всплывашка не часть страницы. На телефоне показываем её
       полосой у нижнего края: места хватает любому объяснению, и до него
       не нужно целиться пальцем.

       Правило жило в people.css и работало только в «Людях» — в «Деньгах»
       подсказка уезжала за край на всех страницах. Здесь оно общее. */
    .hint-pop {
        position: fixed; left: 12px; right: 12px; bottom: 12px;
        top: auto; width: auto; transform: none;
        padding: 12px 14px; font-size: 13px; border-radius: 10px;
        padding-bottom: max(12px, env(safe-area-inset-bottom));
    }
    /* Хвостик указывал на значок — у полосы внизу указывать не на что. */
    .hint-pop::after { display: none; }
    td:first-child .hint-pop, th:first-child .hint-pop { left: 12px; transform: none; }
    /* Значок «?» — цель для пальца, а не для курсора. */
    .hint { padding: 4px; margin-left: 0; }

    .content {
        padding: 14px 12px 48px;
        padding-left: max(12px, env(safe-area-inset-left));
        padding-right: max(12px, env(safe-area-inset-right));
        /* Шапки на телефоне нет, и заголовок страницы стоит сразу под
           краем экрана: в режиме приложения он уезжал под часы и вырез.
           Кнопка меню отступ уже знает (см. .burger выше), содержимое —
           нет. В обычной вкладке вставка нулевая, остаются прежние 14. */
        padding-top: max(14px, env(safe-area-inset-top));
    }

    /* Заголовок делит строку с плавающей кнопкой меню: 38 пикселей кнопки
       плюс поля. У длинных названий («Отчёт о прибылях и убытках») значок «?»
       не влезал и срывался на строку ниже одиноким кружком. */
    h1 { font-size: 18px; margin-bottom: 12px; line-height: 1.25; padding-right: 46px; }
    h2 { font-size: 15.5px; }

    .panel { padding: 14px 13px; border-radius: 9px; margin-bottom: 12px; }
    .panel.tight { padding: 10px 11px; }
    .btn.add-ops-btn { display: inline-flex; width: 100%; justify-content: center; margin-bottom: 12px; }
    .add-ops-btn::after { content: ' ▾'; color: var(--muted); }
    .add-ops.hidden { display: none !important; }

    /* Плитки показателей — по две в ряд. По одной получался столбик
       в четыре экрана, между первой и последней цифрой нет сравнения. */
    .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 12px; }
    .card { padding: 12px 13px; }
    .card .value { font-size: 17px; }
    .card .label { font-size: 11.5px; }

    /* Поля ввода: меньше 16 пикселей — и Safari на iPhone приближает
       страницу при попадании в поле, а обратно уже не отдаляет. */
    input[type=text], input[type=date], input[type=number], input[type=month],
    input[type=password], select, textarea { font-size: 16px; padding: 8px 10px; }

    /* Кнопки и переключатели — не меньше пальца (44 пикселя по рекомендации
       Apple и Google), иначе в «‹ период ›» попасть невозможно. */
    .btn { padding: 10px 14px; min-height: 40px; }
    /* Цели касания. WCAG 2.1 требует 44×44; было: значок «?» 21×21, кнопка
       деления операции 30×34, крестик меню 34×34, поле поиска 29 в высоту.
       По таким целям не попасть пальцем, а у владельца ещё и слабое зрение.
       Где кнопка одна — растим её саму; где значок стоит в тексте и раздувать
       его нельзя, растим невидимую область нажатия вокруг него. */
    .btn-sm { padding: 8px 12px; min-height: 40px; min-width: 40px; justify-content: center; }
    .nav-close { width: 44px; height: 44px; }
    .nav-search input { min-height: 40px; }
    .nav a, .nav .nav-stub { padding: 12px 16px 12px 22px; font-size: 14.5px; }
    .nav-sub .nav a, .nav-sub .nav .nav-stub { padding-left: 34px; }
    .nav-sub > .nav-title { padding-left: 22px; }
    .tabs a { padding: 11px 9px; font-size: 12.5px; white-space: nowrap; }

    /* Значок «?» и переключатель: размер оставляем, площадь нажатия растим. */
    .hint, .switch { position: relative; }
    .hint::before, .switch::before {
        content: ''; position: absolute; top: 50%; left: 50%;
        width: 44px; height: 44px; transform: translate(-50%, -50%);
    }
    /* 44, а не 40: палец попадает по цели от сорока четырёх точек.
       Замер на 375 до правки — стрелки периода и значки 40 × 40. */
    .icon-btn, .period-nav .step { width: 44px; height: 44px; font-size: 17px; }
    .period-btn { min-width: 0; padding: 10px 12px; min-height: 44px; }
    .period-nav .period-btn { flex: 1; }
    .period-nav { flex: 1 1 200px; }
    .toolbar { gap: 8px; }
    /* «Все · Поступления · Списания · Переводы» не влезали в 364 пикселя
       и падали второй строкой — четыре слова занимали два ряда. Ужимаем
       отступы и шрифт: одна строка читается как один выбор, две — как два
       разных списка. Выпадающий список сюда не ставим: он превращает один
       клик в два, а переключаются здесь часто.

       Перенос оставлен: в ДДС вкладок пять («Статьи · Виды деятельности ·
       Контрагенты · Счета · Направления»), и запрет переноса выносил
       последнюю за экран на 74 пикселя. Где вкладок четыре — они и так
       встают в строку после ужатия. */
    .tabs { gap: 2px; }
    button.mini { padding: 7px 11px; }

    /* Выпадашка периода упиралась в правый край: она была привязана
       к кнопке, а кнопка на телефоне почти во всю ширину. */
    .period-menu { left: 0; right: 0; min-width: 0; }
    .period-custom { flex-wrap: wrap; }
    .period-custom input[type=date] { width: auto; flex: 1 1 120px; }

    /* Окно настроек снизу, как лист: до верхней части экрана
       большим пальцем не дотянуться. */
    .modal { align-items: flex-end; }
    .modal-box {
        width: 100%; border-radius: 14px 14px 0 0; padding: 18px 16px;
        max-height: 88vh; overflow-y: auto;
        padding-bottom: max(18px, env(safe-area-inset-bottom));
    }
    .check-row { padding: 12px 0; }
    .modal-foot { flex-wrap: wrap; }

    /* Таблицы. Приклеенная первая колонка в 280 пикселей на телефоне
       не оставляла места самим цифрам — оставляем ей примерно половину. */
    .table-wrap { -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; padding-bottom: 2px; }
    /* Таблица сжималась до ширины экрана и ломала слова по слогам:
       «Компас (бывш. «Академия сало-нов»)» в колонку шириной с палец.
       Пусть лучше честно прокручивается — читать по слогам хуже,
       чем двигать пальцем. Полосу прокрутки не прячем: по ней видно,
       что за краем есть ещё колонки, — одной тени под плотным текстом
       не видно. */
    .table-wrap table { min-width: 560px; }

    /* Помесячный отчёт на телефоне: первая колонка — название статьи —
       забирала весь экран, и на первом экране ОПиУ не было ни одной цифры.
       Отчёт о прибылях без прибыли. Название прилипает к левому краю
       и занимает фиксированные 148 пикселей, цифры прокручиваются под ним:
       видно, к какой статье относится число, не отпуская его из виду. */
    .table-wrap table.report th:first-child,
    .table-wrap table.report td:first-child,
    .table-wrap table.grid th:first-child,
    .table-wrap table.grid td:first-child {
        position: sticky; left: 0; z-index: 2;
        min-width: 148px; max-width: 148px;
        background: var(--panel);
        box-shadow: 1px 0 0 var(--border);
        /* Иначе длинное название («*Закупка материалов для работы») вылезает
           за свои 148 пикселей и ложится поверх цифры соседней колонки. */
        white-space: normal; overflow-wrap: anywhere;
    }
    .table-wrap table.report th, .table-wrap table.grid th { white-space: nowrap; }
    .table-wrap::-webkit-scrollbar { height: 6px; }
    .table-wrap::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }


    /* Документы, собранные из Markdown (архив проектов, исследования):
       таблицу внутри них не обернуть в table-wrap — разметку рисует
       конвертер, а не шаблон. Поэтому прокручиваем вбок сам документ. */
    .director-md { overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
    table.report th:first-child { min-width: 150px; }
    /* ОПиУ (shtab#1492): на узком окне 300px под подписи — половина
       экрана; своего `@media`-блока НЕ заводим — тест
       `test_period_arrows_and_icons_are_44_not_40` читает первый блок
       `@media (max-width: 900px)` целиком и ломается, если раньше
       встанет чужой. */
    .table-wrap table.report.report-opiu th:first-child,
    .table-wrap table.report.report-opiu td:first-child { width: 180px; }
    table.report th, table.report td { padding: 8px 9px; }
    table.grid th, table.grid td { padding: 8px 8px; }
    table.report tr.total > td { font-size: 13.5px; }
    table.report .lvl1 td:first-child { padding-left: 18px; }
    table.report .lvl2 td:first-child { padding-left: 30px; }
    table.report .lvl3 td:first-child { padding-left: 42px; }

    /* Ширину выпадающего списка задаёт самая длинная строка внутри него.
       В боевой базе филиал называется «Точка Красоты - ТЦ "Курс" -
       ш. Можайское, 159 - г. Одинцово» — 499 пикселей, и страница уезжала
       вбок на всех витринах «Людей». На пустой базе этого не видно: филиалов
       там нет. Поэтому правило общее — поле не шире отведённого ему места. */
    select, input, textarea { max-width: 100%; }
    .inline-form { flex-wrap: wrap; gap: 8px; max-width: 100%; min-width: 0; }
    .tabs-row { min-width: 0; flex-wrap: wrap; }
    /* Галочки: 13 пикселей — размер для курсора, а не для пальца.
       Строка-подпись кликабельна целиком, но попасть хочется в саму галочку. */
    input[type=checkbox], input[type=radio] { width: 19px; height: 19px; }
    .filters { gap: 8px; }
    .filters-btn { width: 100%; justify-content: center; }

    /* Три кнопки ввода операции стояли первыми и в полный рост — 60 пикселей
       каждая. Но с телефона на «Операции» приходят читать, а не заводить
       платёж руками: в строку и мелким шрифтом они не мешают списку. */
    .panel.tight .btn-income,
    .panel.tight .btn-outcome,
    .panel.tight .btn-transfer {
        flex: 1 1 0; min-width: 0; padding: 8px 4px;
        font-size: 12px; white-space: nowrap;
        overflow: hidden; text-overflow: ellipsis;
    }
    /* Ширину списка задаёт самая длинная строка в нём: у фильтра «Статья»
       это «!(И) Возврат банковских кредитов» — 401 пиксель, и страница
       уезжала вбок. На пустой базе не видно, статей там нет. Поле теперь
       не шире своей колонки, а длинное название обрезается многоточием. */
    .filters .field { flex: 1 1 140px; min-width: 0; }
    .filters .field select,
    .filters .field input { max-width: 100%; text-overflow: ellipsis; }
    .filters-box { padding: 10px 11px; }

    .grid-2 { gap: 12px; }
    .chart { height: 150px; gap: 5px; }
    .chart-label { font-size: 10px; }
    .close-progress { margin-left: 0; width: 100%; }
    .close-progress .bar { flex: 1; width: auto; }
    .instruction-grid { gap: 14px; }
    .empty { padding: 26px 14px; }
}

/* --------------------------------------------------------------------
   Цели нажатия на телефоне и планшете.

   Управляющая смотрит экран пальцем и на ходу, между салонами. Палец
   попадает по цели от 44 точек в меньшей стороне; всё, что меньше,
   промахивается — а промах по выбору филиала или по дате означает
   не «не нажалось», а «посмотрел не тот салон».

   Здесь только размеры и отступы: ни цвета, ни расположение, ни поведение
   не меняются. На большом экране правила не действуют — там мышь,
   и она попадает и по тридцати шести точкам.

   Замеры до правки (375 точек, экран «Деньги дня по салону»):
     выбор филиала   310 × 35,6
     поле даты       118,8 × 37,9
     кнопка меню     38 × 38
     поиск по меню   230,8 × 40
     «К содержимому» 131,4 × 39,6
     заголовки групп меню 284,8 × 43,9
   -------------------------------------------------------------------- */
@media (max-width: 1199px) {
    /* Списки и поля ввода в панелях: выбор филиала, дата, фильтры. */
    .panel select,
    .panel input[type="date"],
    .panel input[type="text"],
    .panel input[type="number"],
    .panel input[type="search"] {
        min-height: 44px;
    }

    /* Кнопка меню была ровно 38 × 38 — самая мелкая цель на экране
       и при этом самая нужная: с неё начинается любой переход. */
    .burger { width: 44px; height: 44px; }

    /* Поиск по меню и заголовки групп: по ним попадают в шторке,
       где палец держат одной рукой. */
    .nav-search input { min-height: 44px; }
    .nav-title { min-height: 44px; }

    /* Ссылка «К содержимому» — цель для тех, кто ходит с клавиатуры
       и с экранным диктором; ей ровно та же мерка. */
    .skip-link { min-height: 44px; display: flex; align-items: center; }

    /* Кнопки и вкладки на «Операциях»: «Добавить операцию» и «Фильтры»
       меряли 40,8 по высоте, вкладки «Все · Поступления · Списания ·
       Переводы» — 41,7, а кнопка «разнести» в каждой строке списка
       40 × 40, и таких на экране сотня. */
    .btn { min-height: 44px; }
    .btn-sm { min-width: 44px; }
    /* min-width — ради короткого «Все»: 39,1 точки по ширине. Пять
       лишних пикселей вкладки переживают, в строку они по-прежнему
       помещаются. */
    .tabs a {
        min-height: 44px; min-width: 44px;
        display: inline-flex; align-items: center; justify-content: center;
    }
}

@media (max-width: 1199px) {
    /* Совет директоров в шапке: пять кнопок требуют больше тысячи ста
       пикселей, и на планшете 1024 шапка вылезала за край окна — вбок
       ехала вся страница, а не одна таблица. Ниже 1200 совет уходит
       списком в боковое меню, где помещается целиком.
       Раньше это начиналось с 900, то есть только на телефоне. */
    .topbar .advisor-tabs { display: none; }
    .advisor-tabs-side {
        display: flex; flex-direction: column; gap: 6px;
        padding: 0 12px 12px; margin: 0;
    }
    .advisor-tabs-side .advisor-btn { width: 100%; padding: 7px 12px 7px 7px; }
    .advisor-tabs-side .advisor-btn small { display: block; }

    /* ------------------------------------------------------------------
       Таблица карточками.

       Прокрутка вбок читается плохо: первая колонка прилипшая и широкая,
       остальное сжато в полоску, и, пока возишь пальцем, теряешь строку.
       На узком экране строка таблицы разворачивается в карточку: данные
       идут сверху вниз, подпись слева, значение справа. Прокрутки вбок
       не остаётся вовсе.

       Подписи в ячейки проставляет layout.js из шапки таблицы: 191 таблица
       в 108 шаблонах, руками их не разметить. Включается классом table-cards
       на обёртке — так вкладку можно перевести на карточки по одной
       и посмотреть, что вышло, прежде чем переводить остальные.

       Шапка карточки собирается не по порядку ячеек, а по смыслу:
       слева первая колонка (дата, название), справа первая денежная —
       у «Операций» это «Дата» и «Сумма», у «Где лежат деньги» — «Счёт»
       и «Остаток». Порядок задаётся order, поэтому от места колонки
       в разметке ничего не зависит. */
    .table-wrap.table-cards {
        overflow-x: visible;
        background: none;
        padding-bottom: 0;
    }
    .table-wrap.table-cards table { min-width: 0; display: block; }
    .table-wrap.table-cards thead { display: none; }
    .table-wrap.table-cards tbody { display: block; }

    .table-wrap.table-cards tbody tr {
        display: flex; flex-wrap: wrap; align-items: baseline;
        column-gap: 12px;
        border: 1px solid var(--border); border-radius: var(--radius);
        background: var(--panel);
        padding: 11px 13px;
        margin-bottom: 8px;
    }
    .table-wrap.table-cards tbody tr:last-child { margin-bottom: 0; }
    /* Подсветка строки под курсором на телефоне не нужна: курсора нет,
       а на нажатие она срабатывает и выглядит как выделение. */
    .table-wrap.table-cards tbody tr:hover { background: var(--panel); }

    /* Подпись и значение стоят двумя колонками фиксированной ширины.
       Выравнивать значение по правому краю нельзя: длинное название
       переносится, и левый край строки становится рваным — читать
       список сверху вниз по такому краю невозможно. */
    .table-wrap.table-cards td {
        order: 2; flex: 1 0 100%;
        display: grid; grid-template-columns: 104px minmax(0, 1fr);
        column-gap: 10px; align-items: baseline;
        border: 0; padding: 3px 0;
        text-align: left; white-space: normal;
    }
    .table-wrap.table-cards td::before {
        content: attr(data-label);
        color: var(--muted); font-size: 12.5px; font-weight: 400;
        line-height: 1.5;
    }
    /* Колонка без заголовка — обычно кнопка действия. Подписывать нечем,
       и пустое место слева ей ни к чему. */
    .table-wrap.table-cards td:not([data-label])::before,
    .table-wrap.table-cards td[data-label=""]::before { display: none; }
    /* Ячейке без подписи левая колонка не нужна: кнопка действия
       начинается с края карточки, как и заголовок над ней. */
    .table-wrap.table-cards td:not([data-label]),
    .table-wrap.table-cards td[data-label=""] { grid-template-columns: minmax(0, 1fr); }
    /* Пустая ячейка в карточке — строка «Контрагент —» ни о чём.
       Ячейки без содержимого прячет layout.js, проставляя data-empty. */
    .table-wrap.table-cards td[data-empty] { display: none; }

    .table-wrap.table-cards td.cell-title {
        order: 0; flex: 1 1 auto; display: block;
        font-size: 15px; font-weight: 600; line-height: 1.3;
        padding-bottom: 7px;
    }
    .table-wrap.table-cards td.cell-lead {
        order: 1; flex: 0 0 auto; display: block;
        font-size: 17px; font-weight: 600; line-height: 1.3;
        text-align: right; white-space: nowrap;
        padding-bottom: 7px;
    }
    .table-wrap.table-cards td.cell-title::before,
    .table-wrap.table-cards td.cell-lead::before { display: none; }
    /* Длинное значение — не повод на треть экрана: «Назначение» платежа
       показываем тремя строками, остальное прячется. Полный текст остаётся
       в карточке операции, куда ведёт кнопка справа. */
    .table-wrap.table-cards td > .cell-value {
        display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
        overflow: hidden; min-width: 0; overflow-wrap: anywhere;
    }
    .table-wrap.table-cards td.cell-title > .cell-value { -webkit-line-clamp: 2; }
    /* Ячейка с раскрытием — исключение из правила трёх строк. Найдено на
       375 пикселях: раскрытый список «по статьям» обрезался на второй
       строке, и человек, нажавший «2 статьи», видел одну. Обрезать текст,
       который сам же и попросили показать, — хуже, чем длинная карточка:
       свёрнутое состояние по-прежнему занимает одну строку. */
    .table-wrap.table-cards td > .cell-value:has(details.row-more) {
        display: block; -webkit-line-clamp: none; overflow: visible;
    }
    /* Сумму в шапке не режем построчно: display:-webkit-box развернул бы
       знак «+» и само число в две строки. */
    .table-wrap.table-cards td.cell-lead > .cell-value { display: inline; }

    /* Ниже шапки числа не крупнее подписей: крупным в карточке
       остаётся одно — то, ради чего в неё смотрят. */
    .table-wrap.table-cards td.num { font-weight: 600; }

    /* Прилипшая первая колонка и минимальная ширина — приёмы прокрутки.
       Карточкам они мешают: колонка не должна ни прилипать, ни резаться. */
    .table-wrap.table-cards table.grid th:first-child,
    .table-wrap.table-cards table.grid td:first-child {
        position: static; min-width: 0; max-width: none;
        box-shadow: none; background: none;
    }
}

/* Карточки плиткой на планшете и в узком окне.

   Столбик карточек во всю ширину тысячи пикселей читается плохо:
   подпись слева, значение рядом, а дальше пустое поле в пол-экрана —
   ровно то, на что Сергей пожаловался, глядя на планшет. Начиная
   с 640 пикселей карточки встают плиткой и занимают ширину целиком.

   Ширина колонки 300 пикселей — та, при которой пара «подпись 104 +
   значение» ещё не режется по слогам. */
@media (min-width: 640px) and (max-width: 1199px) {
    .table-wrap.table-cards tbody {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        gap: 8px;
    }
    .table-wrap.table-cards tbody tr { margin-bottom: 0; align-content: start; }
}

/* Совсем узкие экраны (iPhone SE и подобные): плитки в одну колонку —
   на 320 пикселях в две колонки сумма переносится посреди числа. */
@media (max-width: 360px) {
    .cards { grid-template-columns: 1fr; }
    .topbar .money { font-size: 14px; }
}

/* Счёт с невозможным остатком: минус на банке — это поломка данных.
   Показываем прямо в выпадашке, иначе итог врёт молча. */
.money-total-row.alarm span, .money-total-row.alarm b { color: var(--outcome-text); }
.money-total-warn {
    padding: 7px 9px; font-size: 12px; color: var(--outcome-text);
    background: #fdecec; margin-top: 3px; line-height: 1.4;
}
/* Остаток, присланный банком, — под нашей цифрой. Две цифры рядом
   объясняют себя сами: «у нас столько, у банка столько». */
.money-total-bank {
    padding: 0 9px 6px 9px; font-size: 11.5px; color: var(--outcome-text);
}

/* Выключенное правило видно, но не спорит за внимание: оно существует
   и в любой момент включается обратно. */
tr.rule-off td { opacity: .5; }
/* Четыре кнопки в узкой колонке: переносим их целиком на следующую строку,
   а не сжимаем. Сжатая кнопка ломает подпись по буквам и вытягивается
   в столбик из четырёх строк — попасть по ней пальцем невозможно. */
.rule-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.rule-actions form { display: inline; flex: 0 0 auto; }
.rule-actions .btn { white-space: nowrap; }

/* Выбор базы сравнения и изменение под цифрой плитки */
.compare-pick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
                margin-top: 10px; font-size: 13px; }
.compare-pick label { color: var(--muted); }
.card-delta { font-size: 12.5px; margin-top: 4px; }
/* Мелкая строка изменения: свои оттенки, иначе 12,5 пикселя не дотягивают
   до 4,5:1 ни красным, ни зелёным. */
.card-delta.outcome { color: var(--outcome-text); }
.card-delta.income { color: var(--income-text); }

/* Те же смыслы для любого мелкого текста: просроченный срок, предупреждение
   под цифрой, изменение к прошлому месяцу. Обычные .income и .outcome
   рассчитаны на крупные цифры и на одиннадцати пикселях читаются плохо —
   а это ровно те строки, которые обязаны броситься в глаза. */
.outcome-sm { color: var(--outcome-text); }
.income-sm { color: var(--income-text); }

/* Плашка, которая сообщает не «как устроено», а «что-то не так». */
.notice.notice-alarm {
    background: #fdecec; border-color: #f3c9c9; color: var(--outcome-text);
}
/* Денег больше нормы — это не беда, а повод распорядиться: спокойный тон. */
.money-total-warn.money-total-note {
    background: var(--accent-soft); color: var(--text);
}

/* Метки операции: чип со снятием. Крестик — отдельная цель для пальца,
   поэтому у него своя площадь, а не иконка в тексте. */
.tag-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.tag-chip {
    display: inline-flex; align-items: center; gap: 4px;
    background: var(--accent-soft); border: 1px solid var(--border);
    border-radius: 999px; padding: 4px 6px 4px 12px; font-size: 13px;
}
.tag-drop {
    border: 0; background: none; cursor: pointer; color: var(--muted);
    font-size: 14px; line-height: 1; padding: 6px 8px; border-radius: 999px;
    min-width: 28px; min-height: 28px;
}
.tag-drop:hover { color: var(--outcome-text); background: #fdecec; }

/* Действия в строке корзины: три кнопки в ряд, на телефоне переносятся. */
.trash-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.trash-actions form { display: inline; }

@media (max-width: 720px) {
    .tag-drop { min-width: 44px; min-height: 44px; }
}

/* Признаки дубля словами: балл не говорит, почему пара подозрительная. */
.dup-sign { font-size: 11.5px; color: var(--muted); line-height: 1.4; }
.dup-sign.strong { color: var(--outcome-text); font-weight: 600; }
.dup-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.dup-actions form { display: inline; }
/* Метка в списке операций: не кнопка, а признак — читается, не нажимается. */
.tag-line { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 3px; }
.tag-mark {
    font-size: 11px; background: var(--accent-soft); color: var(--accent-dark);
    border-radius: 999px; padding: 1px 8px;
}
.row-tools { display: flex; gap: 4px; align-items: center; }
/* Описание платежа — самая длинная колонка: из-за неё кнопка действия
   уезжала за правый край. Держим её в берегах, полный текст в подсказке. */
.dup-side { max-width: 300px; }
.dup-desc {
    color: var(--muted); font-size: 11.5px; line-height: 1.35;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
/* Колонка признаков узкая: слова короткие, а место нужно кнопке действия. */
.grid td .dup-sign { white-space: nowrap; }

/* Выделение операций для массового изменения. Колонка узкая: чекбокс —
   не содержимое строки, а способ её выбрать. */
/* Галочка выбора строки — 22px: 17px ниже нормы WCAG 2.2 Target Size (24 CSS px)
   для 100+ целей на экране (design-critique shtab#1631/#1663); зеркало в Фокусе то же. */
.grid th.pick, .grid td.pick { width: 40px; padding-left: 10px; padding-right: 0; }
.grid td.pick input, .grid th.pick input { width: 22px; height: 22px; margin: 1px; cursor: pointer; }

/* Панель действий липнет к низу экрана: список длинный, и уезжать к нему
   наверх после выделения двадцатой строки — лишний путь. */
.bulk-bar {
    position: sticky; bottom: 0; z-index: 20;
    display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
    background: var(--panel); border-top: 1px solid var(--border);
    padding: 10px 4px; margin-top: 8px;
    box-shadow: 0 -4px 14px rgba(44, 47, 69, .06);
}
.bulk-count { color: var(--text); font-size: 13px; font-weight: 600; }
/* display у класса сильнее атрибута hidden — без этой строки панель
   действий висела бы внизу всегда, даже когда ничего не выделено. */
.bulk-bar[hidden] { display: none; }

@media (max-width: 720px) {
    .grid th.pick, .grid td.pick { width: 44px; }
    .grid td.pick input, .grid th.pick input { width: 22px; height: 22px; }
}

/* График остатка. Одна серия — один цвет; столбец ниже нормы красится
   статусным оттенком и получает подпись: цветом одним смысл не передаём. */
.chart-wrap { overflow-x: auto; padding: 4px 0 2px; }
.chart { width: 100%; min-width: 520px; height: auto; display: block; }
.chart-bar { fill: var(--accent); }
.chart-bar.low { fill: var(--outcome); }
.chart-bar:hover { fill: var(--accent-dark); }
.chart-bar.low:hover { fill: var(--outcome-text); }
/* Коридор нормы — фон, а не данные: он не должен спорить со столбцами. */
.chart-band { fill: var(--accent-soft); }
.chart-axis { stroke: var(--border); stroke-width: 1; }
.chart-label { font-size: 11px; fill: var(--muted); text-anchor: middle; }
.chart-value { font-size: 11px; fill: var(--muted); text-anchor: middle; }
.chart-value.low { fill: var(--outcome-text); font-weight: 600; }
.chart-note { font-size: 10.5px; fill: var(--muted); }

/* Карточка операции во всплывающем окне.
   Ячейка, которую нельзя поправить на месте (дата, счёт, контрагент,
   назначение), — вход в карточку. Пунктир говорит, что тут можно нажать. */
.row-open { border-bottom: 1px dashed var(--border); color: inherit; }
.row-open:hover { border-bottom-color: var(--accent); text-decoration: none; }
.row-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.card-form { display: flex; flex-direction: column; gap: 14px; }
.card-form .field { display: flex; flex-direction: column; gap: 4px; }
.card-form label { font-size: 13px; color: var(--muted); }
.card-form input, .card-form select, .card-form textarea { font-size: 15px; }
.card-form textarea { resize: vertical; min-height: 46px; }
.field-hint { font-size: 12px; color: var(--muted); line-height: 1.35; }

/* Факт или план: два состояния, а не галочка «это план». Галочка отвечает
   на вопрос «да или нет», а человеку нужно видеть оба варианта сразу. */
.card-kind { display: flex; align-items: center; gap: 8px; }
.radio-chip {
    display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 8px 14px; border: 1px solid var(--border); border-radius: 20px;
    font-size: 14px; min-height: 40px;
}
.radio-chip:has(input:checked) {
    border-color: var(--accent); background: var(--accent-soft, #eef0fb);
    font-weight: 600;
}
.radio-chip:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.hint-q {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--border);
    color: var(--muted); font-size: 12px; cursor: help;
}

/* Сумма — главное поле карточки, поэтому крупная и в своей рамке.
   Знак стоит снаружи: его задаёт вид операции, а не человек. */
.card-sum-row {
    display: flex; align-items: center; gap: 8px;
    border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px;
    background: var(--bg);
}
.card-sum-row:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(74, 91, 196, .14); }
.card-sign { font-size: 24px; font-weight: 700; color: var(--muted); }
.card-sum-row.income .card-sign { color: var(--income-text); }
.card-sum-row.outcome .card-sign { color: var(--outcome-text); }
.card-sum-input {
    flex: 1; border: 0; background: transparent; padding: 0;
    font-size: 24px; font-weight: 700; color: var(--text); min-width: 0;
}
.card-sum-input:focus { outline: none; }
.card-cur { font-size: 18px; color: var(--muted); }

/* Два столбца там, где хватает ширины. На телефоне — один: поля с длинными
   названиями статей в половину экрана не читаются. */
.card-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 560px) {
    .card-grid { grid-template-columns: 1fr 1fr; }
    .card-grid .field:has(#card-partner) { grid-column: 1 / -1; }
}

.card-foot {
    display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
    margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--border);
}
.card-link { margin-left: auto; }
/* Окно карточки шире обычного: в нём девять полей, а не два. */
#card-modal .modal-box { width: min(660px, 94vw); }

/* ---------- меню действий строки ---------- */

/* Одна кнопка вместо трёх иконок. Пятьдесят на сорок — палец попадает,
   а раньше три иконки по двадцать пикселей стояли вплотную. */
.row-menu-btn { min-width: 44px; min-height: 40px; font-size: 16px; line-height: 1; }
.row-menu-btn[aria-expanded="true"] { background: var(--accent-soft); border-color: var(--accent); }
.parts-mark { font-size: 12px; color: var(--muted); margin-right: 6px; }

.row-menu {
    position: absolute; z-index: 90; min-width: 220px; padding: 6px;
    background: #fff; border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 12px 34px rgba(44, 47, 69, .18);
}
.row-menu[hidden] { display: none; }
.row-menu form { margin: 0; }
.menu-item {
    display: block; width: 100%; text-align: left; box-sizing: border-box;
    padding: 10px 12px; min-height: 40px; border: 0; border-radius: 7px;
    background: transparent; color: var(--text); font-size: 14px;
    line-height: 1.3; cursor: pointer; text-decoration: none;
}
.menu-item:hover { background: var(--bg); text-decoration: none; }
.menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.menu-danger { color: var(--outcome-text); }
.menu-danger:hover { background: #fdeceb; }
/* На телефоне палец крупнее курсора: сорока пикселей мало, промахнуться
   в «Удалить» вместо «Клонировать» тут стоит дороже лишнего пробела. */
@media (pointer: coarse) {
    .menu-item { min-height: 48px; padding: 13px 12px; }
    .row-menu { min-width: 240px; }
    .row-menu-btn { min-height: 44px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Экран «Операции» по образцу «Финтабло» (shtab#1560).

   Эталон — сохранённая страница «Деньги» из «Финтабло», лежит в Штабе:
   docs/obrazcy-fintablo/operacii-2026-09-11/. Владелец сравнивает наш
   экран с ней построчно, поэтому и вёрстка повторяет её, а не «похожа».
   ───────────────────────────────────────────────────────────────────────── */


/* Кнопка обновления рядом с заголовком экрана (эталон «Финтабло»). */
h1 .refresh-btn {
    margin-left: 10px; font-size: 18px; line-height: 1; vertical-align: middle;
    color: var(--accent);
}
/* Вкладки разделов под заголовком: Операции · Импорт · Автоправила · Сверка.
   Подчёркиванием, а не заливкой: заливка уже занята вкладками знака операции
   ниже (.tabs), и два одинаковых на вид ряда читались бы как один список. */
.razdely { display: flex; gap: 26px; margin: -6px 0 18px; border-bottom: 1px solid var(--border); }
.razdely .item {
    display: inline-block; padding: 0 0 10px; font-size: 14.5px;
    color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.razdely a.item:hover { color: var(--text); text-decoration: none; }
.razdely .item.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

/* Первая строка панели: период · чипы знака · фильтр · быстрые фильтры. */
.ops-top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ops-top .grow { flex-grow: 1; }

/* Вторая строка: выгрузка слева, авторазнесение справа — как в эталоне. */
.ops-top2 {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}

/* Чипы знака операции — единой группой с рамкой и разделителями, как в
   эталоне: четыре среза одного списка, а не четыре отдельные кнопки.
   «Без статьи» стоит отдельной плашкой — это не знак операции, а работа. */
.chips { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.chips .group {
    display: flex; align-items: center;
    border: 1px solid var(--border); border-radius: 9px; overflow: hidden;
    background: #fff;
}
.chips .group a {
    padding: 8px 16px; font-size: 13.5px; color: var(--muted);
    border-left: 1px solid var(--border);
}
.chips .group a:first-child { border-left: 0; }
.chips .group a:hover { background: var(--row-hover); color: var(--text); text-decoration: none; }
.chips .group a.active {
    background: var(--accent-soft); color: var(--accent-dark); font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--accent-soft);
}
.chips .apart {
    padding: 8px 16px; font-size: 13.5px; color: var(--muted);
    border: 1px solid var(--border); border-radius: 9px; background: #fff;
}
.chips .apart:hover { background: var(--row-hover); color: var(--text); text-decoration: none; }
.chips .apart.active { background: var(--accent-soft); color: var(--accent-dark); font-weight: 600; border-color: #c9cff2; }

/* Период — единой плашкой со стрелками внутри, как в эталоне. Раньше
   стрелки стояли голыми значками и не читались как одна деталь с названием
   месяца между ними. */
.ops-top .period-nav {
    background: var(--accent-soft); border-radius: 9px; padding: 3px 4px;
}
/* Стрелки внутри плашки периода — без своей рамки и белой заливки: в эталоне
   это одна деталь «‹ Ноябрь 2023 ›», а две белые кнопки поверх сиреневой
   плашки читались как три отдельных элемента подряд. Подсветка остаётся на
   наведении — по ней видно, что стрелка нажимается. */
.ops-top .period-nav .step {
    color: var(--accent-dark); background: none; border-color: transparent;
}
.ops-top .period-nav .step:hover { background: #fff; color: var(--accent-dark); }
.ops-top .period-nav .period-btn {
    background: none; border: 0; font-size: 13.5px; font-weight: 600;
    color: var(--accent-dark); padding: 5px 10px;
}

/* «Фильтр» и «Быстрые фильтры» — одинаковой высоты и с рамкой, как в
   эталоне: это пара, и разный вид читался бы как разная важность. */
.ops-top .filters-btn,
.ops-top #quick-filters {
    height: 38px; border: 1px solid var(--border); border-radius: 9px;
    background: #fff; color: var(--text); font-size: 13.5px; padding: 0 14px;
}
.ops-top #quick-filters { min-width: 210px; }
/* Кнопка «Фильтр» — общая `.btn`, а у той снизу отступ 12px на случай, когда
   кнопки идут в несколько рядов. В полосе с `align-items:center` центрируется
   ВНЕШНЯЯ рамка вместе с отступом, и кнопка вставала на 6px выше соседнего
   «Быстрые фильтры»: замер 11.09 — верх 308 против 314 при равной высоте 38.
   Сергей увидел это как «кнопки разнородные» (shtab#1560). */
.ops-top .filters-btn { margin: 0; gap: 8px; }
/* Галочку «▾» у «Фильтра» снимаем только на этом экране: она обещает
   выпадающий список, а кнопка разворачивает форму под панелью. Рядом стоят
   настоящие «Быстрые фильтры» со своей галочкой, и две одинаковые стрелки
   рядом с разным поведением — обман. На других экранах `.filters-btn`
   остаётся как была. */
.ops-top .filters-btn::after { content: none; }
.ops-top .filters-btn .filter-ico { flex: 0 0 auto; color: var(--muted); }
/* Период и чипы знака — той же высоты, что и пара фильтров справа: полоса
   читается как один ряд деталей, а не как четыре разноростые плашки.
   `box-sizing` обязателен — иначе рамка добавляется сверх 38px. */
.ops-top .period-nav,
.ops-top .chips .group,
.ops-top .chips .apart {
    height: 38px; box-sizing: border-box;
}
.ops-top .chips .group,
.ops-top .chips .apart { display: flex; align-items: center; }
/* Только срезы ВНУТРИ группы тянутся на её высоту. «Без статьи» стоит сам по
   себе, и `height:100%` от полосы с автовысотой давал ему 37,2px против 38 у
   соседей — ступенька в один пиксель по всему ряду. */
.ops-top .chips .group a { display: flex; align-items: center; height: 100%; }

/* Три кнопки заведения операции. В эталоне они одного цвета: цветом там
   помечен знак суммы в строке, а не кнопка. Разные цвета на кнопках читались
   как «опасная красная» — хотя списание такое же обычное дело, как приход. */
.add-ops-row { display: flex; gap: 10px; flex-wrap: wrap; }
.add-ops-row .btn {
    background: var(--accent); border-color: var(--accent); color: #fff;
    padding: 11px 22px; font-size: 14.5px; border-radius: 9px;
}
.add-ops-row .btn:hover { background: var(--accent-dark); }

/* Строка фильтров в шапке таблицы: выбор счёта, контрагента, статьи и поиск
   стоят прямо над своими колонками, а не в отдельной свёрнутой форме. */
table.grid tr.col-filters th {
    padding: 8px 10px 12px; background: var(--panel); border-bottom: 1px solid var(--border);
    font-weight: 400; text-transform: none; letter-spacing: 0;
}
table.grid tr.col-filters select,
table.grid tr.col-filters input[type=text] {
    width: 100%; min-width: 150px; padding: 6px 8px; font-size: 13px;
    /* поле поиска шире прочих: в нём стоит подсказка из трёх слов, и на
       150px она обрывалась на «назв…» */
    border: 1px solid var(--border); border-radius: 7px; background: #fff; color: var(--text);
}


table.grid tr.col-filters input[type=text] { min-width: 230px; }

/* Курсор-рука на всей строке: в эталоне строка операции нажимается целиком,
   и рука — единственный признак, по которому это видно до нажатия. */
table.grid.txn tbody tr.txn-row { cursor: pointer; }
/* Шапка дня. Операции сгруппированы по дате, как в эталоне: колонка «Дата»
   в каждой строке повторяла одно и то же двадцать раз подряд. */
table.grid tr.day-row td {
    background: var(--row-hover); color: var(--muted); font-size: 12.5px;
    padding: 7px 10px; text-align: left; border-bottom: 1px solid var(--border);
}

/* Строка операции в два уровня: сверху главное (сумма, контрагент, статья),
   снизу уточнение (счёт, назначение, направление). */
table.grid.txn td { vertical-align: top; padding: 11px 10px; }
/* Шапка таблицы операций — обычным регистром, как в эталоне «Финтабло».
   Капс сжимает буквы и при астигматизме читается хуже; к тому же заголовок
   здесь длиннее одного слова («Контрагент и назначение»). */
table.grid.txn thead tr:first-child th {
    text-transform: none; letter-spacing: 0; font-size: 12.5px;
}
/* Сумма: минус вплотную к числу, как в эталоне. Отступ ячейки-редактора
   разрывал знак и цифру, и «−» читался как тире, а не как минус. */
table.grid.txn td.txn-value .cell-money { padding-left: 0; min-width: 0; }

.txn-main { font-size: 15px; font-weight: 600; white-space: nowrap; }
/* 13px, а не 12.5: у владельца астигматизм, и подпись под цифрой читают
   так же часто, как саму цифру — счёт и направление это не «мелкий шрифт». */
.txn-sub { color: var(--muted); font-size: 13px; margin-top: 4px; line-height: 1.45; }
.txn-sub.wrap { white-space: normal; max-width: 420px; }
/* tabular-nums: цифры одной ширины, и столбец сумм читается сверху вниз
   как столбец, а не как рваный текст. */
td.txn-value { text-align: left; }
td.txn-value .txn-main { font-variant-numeric: tabular-nums; }
td.txn-value .txn-main.income { color: var(--income); }
td.txn-value .txn-main.outcome { color: var(--outcome); }

/* Кнопка «Правило» — завести автоправило по этой операции. В эталоне она стоит
   в каждой строке: правило чаще всего заводят, глядя на конкретный платёж.

   Надпись была «АВТО» и читалась как ПРИЗНАК («разнесено автоматически»), а не
   как действие — при том что то же действие в меню строки называется «Создать
   автоправило». Два имени у одного действия человек считает двумя разными
   (design-critique финального вида, 12.09.2026). */
.autorule-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 74px; height: 30px; padding: 0 10px;
    border: 1px solid var(--border); border-radius: 8px; letter-spacing: .04em;
    /* 12,5px: 11,5px у 100 кнопок «Правило» на экране — ниже читаемого (design-critique shtab#1631/#1663) */
    color: var(--accent); font-size: 12.5px; font-weight: 700; background: #fff;
}
.autorule-btn:hover { background: var(--accent-soft); text-decoration: none; }

/* Итоги липкой панелью внизу списка — как в эталоне. Раньше они стояли мелкой
   строкой над таблицей и уезжали за экран на первой же прокрутке: человек,
   долиставший до конца месяца, уже не видел сальдо, ради которого пришёл. */
.saldo-bar {
    position: sticky; bottom: 0; z-index: 19;
    display: flex; gap: 34px; align-items: center; flex-wrap: wrap;
    background: var(--panel); border-top: 1px solid var(--border);
    padding: 13px 4px; margin-top: 4px; font-size: 14px;
    box-shadow: 0 -4px 14px rgba(44, 47, 69, .06);
}
.saldo-bar b { font-weight: 600; font-variant-numeric: tabular-nums; }
.saldo-bar .saldo-total { margin-left: auto; font-weight: 600; }

@media (max-width: 720px) {
    .razdely { gap: 16px; overflow-x: auto; }
    .saldo-bar { gap: 14px; font-size: 13px; }
    .saldo-bar .saldo-total { margin-left: 0; }
}

/* Ширины колонок держит colgroup, а не содержимое: иначе длинное назначение
   платежа растягивает свою колонку и выдавливает остальные за край экрана. */
table.grid.txn { table-layout: fixed; }
/* `.row-tools` объявлен flex-контейнером (строка выше по файлу). На ячейке
   таблицы это ломает раскладку: `display:flex` выбивает `td` из табличной
   модели, соседние колонки перестают держать заданную ширину, и по краю
   ячейки тянутся обрывки границ. Сергей увидел это как «проблемы в конце
   строчки с разметкой» и «много воздуха посередине» (shtab#1560).
   В таблице операций возвращаем ячейке её природу — кнопки и так стоят
   в строку. */
table.grid.txn td.row-tools { display: table-cell; text-align: left; white-space: nowrap; padding-right: 0; }
table.grid.txn td:last-child { text-align: left; padding-left: 0; }
table.grid.txn td.row-tools .parts-mark { vertical-align: middle; }

/* «…» и «АВТО» — одного роста. Замер 11.09: кнопка меню 40px, «АВТО» 30px,
   стояли рядом в одной строке и давали ступеньку по нижнему краю — это и есть
   «неаккуратно в конце строчки». Высоту держит общее правило, а не каждая
   кнопка отдельно: разойдутся снова, как только кто-то поправит одну. */
table.grid.txn td.row-tools .row-menu-btn,
table.grid.txn td:last-child .autorule-btn {
    height: 30px; min-height: 30px; padding: 0 10px;
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box;
}
/* Обе служебные кнопки прижаты к верхней строке операции, а не к середине
   ячейки: в строке два уровня текста, и кнопка, повисшая между ними, читается
   как относящаяся к нижнему уточнению, а не ко всей операции. */
table.grid.txn td.row-tools,
table.grid.txn td:last-child { vertical-align: top; }

/* Поле поиска в шапке растягивается по своей ячейке, а не по собственному
   `min-width`. Замер 11.09: ячейка 144px, поле 230px — поле вылезало за
   правый край таблицы поверх границ соседних ячеек. Это и были «обрывки
   линий в конце строчки» (shtab#1560). */
table.grid.txn tr.col-filters th[colspan] input[type=text] {
    min-width: 0; width: 100%; box-sizing: border-box;
}
/* Селекты фильтров — тоже по ширине своей колонки: у «Счёта» она уже
   150px, и жёсткий `min-width` выдавливал select за границу ячейки. */
table.grid.txn tr.col-filters select {
    min-width: 0; width: 100%; box-sizing: border-box;
}

table.grid.txn td.text, table.grid.txn th.text { overflow: hidden; }
table.grid.txn .txn-main { overflow: hidden; text-overflow: ellipsis; }
table.grid.txn .txn-sub.wrap { max-width: none; white-space: normal; }

/* Карточка операции по эталону «Финтабло»: подпись слева, поле справа. */
.card-fintablo .card-rows { display: flex; flex-direction: column; gap: 12px; margin-top: 16px; }
.card-fintablo .card-row { display: flex; align-items: flex-start; gap: 14px; }
.card-fintablo .card-label {
    display: flex; align-items: center; gap: 8px;
    /* 11px, а не 8: замер 11.09 — подпись стояла на 2,6-3,7px выше середины
       своего поля во всех строках сразу, и ряд читался как слегка съехавший.
       Верхнее выравнивание (а не `center`) оставлено намеренно: у «Описания»
       поле в три строки, и подпись к нему должна стоять у первой. */
    min-width: 170px; max-width: 170px; padding-top: 11px;
    color: var(--text); font-size: 14px;
}
.card-fintablo .card-label label { margin: 0; font-size: 14px; color: var(--text); }
.card-fintablo .card-row > select,
.card-fintablo .card-row > textarea,
.card-fintablo .card-field-with-link,
.card-fintablo .card-field-with-hint,
.card-fintablo .card-field-inline { flex: 1 1 auto; min-width: 0; }
.card-fintablo .card-field-with-link { display: flex; align-items: center; gap: 10px; }
.card-fintablo .card-field-with-link input { flex: 1 1 auto; }
.card-fintablo .card-field-with-hint { display: flex; flex-direction: column; gap: 4px; }
.card-fintablo .card-field-with-hint input { width: 100%; }
.card-fintablo .card-field-inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.card-fintablo .card-field-inline .inline-note { color: var(--muted); font-size: 13px; }
.card-fintablo .spread-input { width: 70px; }
.card-fintablo .field-link { color: var(--accent); font-size: 13.5px; white-space: nowrap; }

/* «Разбить» и «Преобразовать в перевод» — справа под суммой, как в эталоне. */
.card-sum-actions { display: flex; gap: 22px; justify-content: flex-end; margin-top: 8px; }
.card-sum-actions a { color: var(--accent); font-size: 13.5px; }
.to-transfer-box {
    margin-top: 12px; padding: 14px; border: 1px solid var(--border);
    border-radius: 10px; background: var(--row-hover);
}
.hidden-form { display: none; }

/* shtab#1776: карточки кандидатов на пару для перевода. */
.to-transfer-kandidat {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 10px 12px; margin-bottom: 8px; background: #fff;
    border: 1px solid var(--border); border-radius: 8px; font-size: 13px;
}
.to-transfer-kandidat-opis { line-height: 1.4; }
.to-transfer-ruchnoy-open { display: inline-block; margin-top: 4px; font-size: 13px; color: var(--accent); }

.card-history-line { margin-top: 18px; text-align: right; }
.card-history-line a { color: var(--accent); font-size: 13.5px; }
.card-foot-center { justify-content: center; gap: 18px; }
.btn-plain { background: none; border-color: transparent; color: var(--accent); }
.btn-plain:hover { background: var(--accent-soft); }

/* Окно автоправила (shtab#1560) — шире обычной карточки: в нём три блока
   с условиями, и в узком окне они сжимаются в кашу.
   Ширину задаём именно `width`, а не `max-width`: у `.modal-box` стоит
   `width: min(520px, 92vw)`, и один `max-width` окно НЕ расширял — поля
   условия переносились в столбик, хотя в эталоне стоят одной строкой. */
.modal-box.modal-wide {
    /* Ширина снята с эталона замером по пикселям: окно занимает 90,4 %
       ширины экрана (1373 из 1518 на скриншоте итога авторазнесения и
       1097 из 1252 на скриншоте настроек — 87,6 %), а не половину. */
    width: min(1240px, 90vw); max-width: none;
    /* Шапка окна уезжала за верхний край: карточка росла выше экрана, а
       прокручивалась вся страница целиком. Теперь высота ограничена
       экраном, шапка стоит на месте, а прокручивается только тело. */
    max-height: 92vh; display: flex; flex-direction: column; padding: 0;
    /* Опора для подтверждения отмены: без неё вопрос уезжает в угол
       страницы, а не встаёт поверх своей формы. */
    position: relative;
}
/* Боковой отступ 56px — снят с эталона: там содержимое отступает от края
   окна на 66 CSS-пикселей (83 device при dpr 1.25), у нас было 28, и текст
   шёл почти по краю. Шапка и тело отступают ОДИНАКОВО: разные отступы были
   первым, что бросалось в глаза Сергею — заголовок стоял с отступом, а
   текст под ним упирался в край. */
.modal-wide .modal-head {
    flex: 0 0 auto; margin: 0; gap: 16px;
    padding: 26px 56px 16px; border-bottom: 1px solid var(--border);
}
/* 21px — размер заголовка эталона (26 device / 1.25). Было 22: на глаз
   разница мелкая, но заголовок в окне шире эталонного на полсантиметра. */
.modal-wide .modal-head h2 { font-size: 21px; line-height: 1.3; text-wrap: balance; }
.modal-head-right { display: flex; align-items: center; gap: 14px; }
/* Ссылка на справку — там же, где у эталона: в правом верхнем углу окна,
   рядом с крестиком. Справку дал Сергей 11.09.2026. */
.rule-help { color: var(--accent); font-size: 13.5px; text-decoration: underline; white-space: nowrap; }
/* На узком экране длинная ссылка сдавливала заголовок до переноса по
   буквам — там она уходит под заголовок целой строкой. */
@media (max-width: 780px) {
    .modal-wide .modal-head { flex-wrap: wrap; padding: 18px 18px 12px; }
    .modal-scroll { padding: 16px 18px 22px; }
    .rule-help { white-space: normal; }
}
.modal-scroll { overflow: auto; padding: 20px 28px 26px; }
.rule-lead { color: var(--muted); font-size: 13.5px; margin: 0 0 16px; line-height: 1.5; }
.rule-step { border: 1px solid var(--border); border-radius: 12px; padding: 18px 20px; margin-bottom: 16px; }
.rule-step-head { display: flex; align-items: center; gap: 10px; font-size: 15px; font-weight: 600; margin-bottom: 12px; }
.rule-num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: 50%; background: var(--text);
    color: #fff; font-size: 12.5px; font-weight: 700;
}
.rule-cond-box { background: var(--row-hover); border-radius: 10px; padding: 16px 18px; }
.rule-sub { display: block; color: var(--muted); font-size: 12.5px; margin-bottom: 6px; }
/* «Тип» — одно значение из трёх, ему не нужна вся ширина блока: в эталоне
   поле занимает примерно треть и не тянется до правого края. */
.rule-cond-box select[name=grp] { width: 340px; max-width: 100%; }
/* Три поля условия — одной строкой, как в эталоне («что / как / значение»
   читаются как фраза). `nowrap` здесь нельзя: на узком экране строка
   должна честно переноситься, поэтому перенос оставлен, но поля подобраны
   так, чтобы в окне 1080px они укладывались в одну линию. */
.rule-cond { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.rule-cond .rule-pole { display: flex; flex-direction: column; flex: 0 1 230px; min-width: 180px; }
.rule-cond .rule-pole-shirokoe { flex: 1 1 300px; min-width: 220px; }
.rule-cond .rule-pole .rule-sub { margin-bottom: 4px; }
.rule-cond select, .rule-cond input[type=text] { width: 100%; }
/* Единственное действие — не выбор: текстом, а не серым списком из одного
   пункта. Отключённый список не берётся клавиатурой и читается как поломка. */
.rule-odno-deystvie { margin: 0; padding: 9px 0; font-size: 14px; }
/* «И» между условиями — плашкой, как в эталоне: это связка, а не подпись. */
.rule-and {
    display: inline-block; margin: 12px 0; padding: 7px 20px;
    border: 1px solid var(--border); border-radius: 8px; background: #fff;
    color: var(--accent); font-size: 13px; font-weight: 600;
}
.rule-note { color: var(--muted); font-size: 12.5px; margin: 12px 0 0; }
.rule-fill { display: flex; gap: 20px; flex-wrap: wrap; }
.rule-fill .field { flex: 1 1 260px; }
/* Поля в окне выше обычных: в эталоне они «дышат», и в 26 пикселей высоты
   по ним трудно попасть мышью (правило 44×44 для целей нажатия). */
.rule-form select, .rule-form input[type=text] { padding: 10px 12px; font-size: 14px; }
.rule-form .rule-fill select { width: 100%; }
.rule-field-note { font-size: 12.5px; margin-top: 6px; line-height: 1.4; }
/* Низ окна как в эталоне: «Сохранить» синяя, «Отменить» текстом рядом,
   обе по центру и без разделительной линии над ними. */
.rule-form .card-foot { border-top: 0; margin-top: 8px; padding-top: 18px; gap: 24px; }
.rule-form .card-foot .btn { padding: 11px 30px; }

/* shtab#1769: вторая кнопка «Сохранить и создать автоправило» — контурная,
   не спорит весом с заливкой «Сохранить», но заметнее текстовой ссылки. */
.btn-secondary {
    background: #fff; border-color: var(--accent); color: var(--accent);
}
.btn-secondary:hover { background: var(--accent-soft); }
.btn-secondary svg { vertical-align: -2px; margin-right: 4px; }
.btn-secondary[disabled] { opacity: .5; cursor: not-allowed; }

/* shtab#1769: окно правила «из операции» — чекбоксы-условия и доли построчно. */
.rule-cond-chk { margin-bottom: 12px; }
.rule-cond-chk:last-child { margin-bottom: 0; }
.chk-row { display: flex; align-items: center; gap: 7px; margin-bottom: 5px; font-size: 13px; }
.chk-row input[type=checkbox] { width: auto; margin: 0; }
.rule-doli-spisok { display: flex; flex-direction: column; gap: 8px; }
.rule-doli-row { display: flex; gap: 8px; align-items: center; }
.rule-doli-row select { flex: 2; min-width: 0; }
.rule-doli-row input.rule-doli-pct { flex: 0 0 64px; text-align: right; }
.rule-doli-drop {
    flex: 0 0 auto; width: 28px; height: 28px; border: 0; background: none;
    color: var(--muted); cursor: pointer; font-size: 15px; border-radius: 6px;
}
.rule-doli-drop:hover { background: var(--row-hover); color: var(--outcome); }
.rule-doli-actions {
    display: flex; justify-content: space-between; align-items: center;
    margin-top: 10px; font-size: 13px;
}
.rule-doli-itogo b { font-variant-numeric: tabular-nums; }
.rule-warn { color: var(--outcome); font-size: 12.5px; margin: 10px 0 0; }
/* shtab#1769, design-critique (перенесено из «Фокуса», PR#38): назначение
   платежа не помещалось в одну строку input — текст обрезался, и было не
   видно, что реально уйдёт в условие правила. */
.rule-cond-textarea {
    width: 100%; box-sizing: border-box; padding: 10px 12px; font-size: 14px;
    font-family: inherit; resize: vertical; border: 1px solid var(--border);
    border-radius: 8px; color: var(--text); background: #fff;
}
.rule-cond-textarea:disabled { opacity: .55; }

/* Окно автоправила помещается целиком, без прокрутки — слово Сергея
   11.09.2026: «умести ты уже в одно окно это всё». Прокрутка внутри окна
   прячет кнопку «Сохранить»: человек видит форму и не видит, чем её
   закончить. Поэтому отступы и высоты здесь плотнее общих. */
#rule-modal .rule-lead { margin: 0 0 10px; font-size: 13px; }
#rule-modal .notice.rule-tight { margin: 0 0 10px; padding: 8px 12px; font-size: 12.5px; }
#rule-modal .rule-step { padding: 12px 14px; margin-bottom: 10px; }
#rule-modal .rule-step-head { margin-bottom: 9px; font-size: 14.5px; }
#rule-modal .rule-cond-box { padding: 10px 12px; }
#rule-modal .rule-and { margin: 8px 0; padding: 5px 16px; }
#rule-modal .rule-note { margin-top: 7px; font-size: 12px; }
#rule-modal .rule-field-note { margin-top: 5px; font-size: 12px; }
#rule-modal .card-foot { margin-top: 6px; }

/* ---------- окно «Разбить операцию» (shtab#1563, пункт 8) ----------

   Эталон: docs/obrazcy-fintablo/operacii-2026-09-11/etalon-fintablo-okno-razbit.png
   в репозитории Штаба. Размеры ниже сняты с него замером, а не на глаз:
   поле общих полей 355px, столбец подписей 170px, «История изменений»
   по правому краю полей. */

/* Служебный текст только для чтения с экрана. Заголовок окна спрятан:
   в эталоне он один и приходит из формы. */
.visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* Шапка без разделительной черты и почти без высоты: в эталоне над
   заголовком формы стоит только крестик, а линия рисовала бы вторую
   границу там, где окно уже отделено тенью. */
.modal-wide .modal-head.split-modal-head {
    border-bottom: 0; padding: 14px 20px 0; justify-content: flex-end; min-height: 0;
}
/* Крестик без рамки — как в эталоне. Рамка делала его тяжелее заголовка. */
.icon-btn-bare { border-color: transparent; background: none; font-size: 17px; }

#split-modal .modal-box { width: min(1240px, 94vw); max-width: none; }
#split-modal .modal-scroll { padding: 0 28px 26px; }

/* Заголовок и сумма — одной строкой; сумма занимает весь остаток ширины,
   как поле ввода эталона. */
.split-head { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin: 2px 0 22px; }
.split-title { font-size: 22px; font-weight: 600; line-height: 1.2; }
.split-sum {
    flex: 1 1 420px; min-width: 260px;
    display: flex; align-items: center; gap: 10px;
    border: 1px solid var(--border); border-radius: 10px; padding: 9px 14px;
    background: var(--row-hover);
    font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums;
}
/* Знак и «₽» — по краям поля, как в эталоне: знак слева, валюта справа. */
.split-sum .card-sign { font-size: 20px; }
.split-sum .card-cur { margin-left: auto; font-size: 17px; }

/* Шапка таблицы — обычным текстом, без капса: в эталоне это подписи к
   полям, а не заголовки отчёта. */
table.split-grid th { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 400; color: var(--muted); }
table.split-grid td { padding: 6px 7px; vertical-align: middle; }
table.split-grid th { padding: 6px 7px; }
table.split-grid input, table.split-grid select {
    width: 100%; min-width: 0; padding: 9px 11px; font-size: 13.5px; border-radius: 8px;
}
/* Числа слева, как в эталоне: там столбцы узкие и значение стоит сразу
   после левой границы поля — прижатое вправо читалось бы как итог. */
table.split-grid .split-value, table.split-grid .split-percent {
    text-align: left; font-variant-numeric: tabular-nums;
}
/* Доля считается, а не вводится — серым по светлому, но с тем же
   контрастом текста: значение должно читаться, просто не приглашать к вводу. */
table.split-grid .split-percent { background: var(--row-hover); color: var(--text); }
/* Тот же случай веса, что и у подвала: `td:first-child` тянет номер влево. */
table.grid.split-grid td.split-num { color: var(--muted); font-size: 13px; text-align: center; }
.split-equal { margin-left: 8px; font-weight: 400; color: var(--accent); font-size: 12px; }

/* Крестик удаления части — глиф без рамки, 32×32: палец попадает,
   а взгляд не цепляется за лишнюю границу. */
.split-drop {
    width: 32px; height: 32px; border: 0; background: none; cursor: pointer;
    color: var(--muted); font-size: 15px; border-radius: 8px; padding: 0;
}
.split-drop:hover { background: var(--accent-soft); color: var(--accent); }

/* Подвал таблицы. Он внутри `<tfoot>`, поэтому «Итого» само стоит под
   столбцами «Сумма» и «%» и не разъезжается при смене ширины окна. */
table.split-grid tfoot td { border: 0; padding: 6px 7px; }
/* `table.split-grid tfoot`, а не просто `.split-left-row`: у общего правила
   `table.grid td:first-child { text-align: left }` вес (0,2,1) — выше двух
   классов, и «Осталось распределить» молча прилипало к левому краю вместо
   столбца «Сумма» (замер 12.09: текст кончался на 300px левее). */
table.split-grid tfoot .split-left { text-align: right; font-size: 13.5px; padding-top: 16px; }
.split-left b { font-variant-numeric: tabular-nums; }
.split-actions { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.split-total-row td { padding-top: 4px; }
.split-itogo-label { font-weight: 600; font-size: 15px; }
/* Итоговые числа в рамке — как в эталоне: это тот же столбец, что и поля
   выше, и рамка удерживает взгляд в колонке. */
.split-itogo-box {
    display: block; border: 1px solid var(--border); border-radius: 8px;
    padding: 9px 11px; background: #fff; font-weight: 600; font-size: 13.5px;
    /* Слева, как значения в столбце над ними: итог должен читаться
       продолжением столбца, а не отдельным числом у правого края. */
    text-align: left; font-variant-numeric: tabular-nums;
}

/* Общие поля: подпись слева, поле справа — тот же строй, что в карточке
   операции. Ширины совпадают с эталоном (170 + 14 + 355). */
.split-below { max-width: 539px; margin-top: 22px; }
.split-common { display: flex; flex-direction: column; gap: 12px; }
.split-common .card-row { display: flex; align-items: flex-start; gap: 14px; }
.split-common .card-label {
    display: flex; align-items: center;
    min-width: 170px; max-width: 170px; padding-top: 11px;
    color: var(--text); font-size: 14px;
}
.split-common .card-label label { margin: 0; font-size: 14px; color: var(--text); }
.split-common > .card-row > input,
.split-common > .card-row > textarea { flex: 1 1 auto; min-width: 0; }
/* Поля неактивны намеренно: счёт, дату и описание правят в карточке —
   они общие для всех частей. Серая заливка говорит это без подписи. */
.split-common input[disabled], .split-common textarea[disabled] {
    background: var(--row-hover); color: var(--muted); cursor: not-allowed;
}
.split-below .card-history-line { margin-top: 18px; text-align: right; }

/* На узком экране столбец подписей съедает поле — там подпись встаёт над
   полем, а таблица частей прокручивается вбок (`.table-wrap`). */
@media (max-width: 900px) {
    #split-modal .modal-scroll { padding: 0 16px 20px; }
    /* Таблица не сжимается, а прокручивается вбок: замер 12.09 при 820px —
       поля «Контрагент» и «Статья» ужимались до 50px и показывали по три
       буквы названия статьи, то есть не показывали ничего. */
    table.split-grid { min-width: 940px; }
    .split-common .card-row { flex-direction: column; gap: 4px; }
    .split-common .card-label { min-width: 0; max-width: none; padding-top: 0; }
}

/* Красное «осталось распределить» — тёмным красным, а не основным:
   замер 12.09 дал у #d9534f на белом 3.96:1, а тексту в 13,5 пикселя нужно
   4.5:1. #b02a2a даёт 7.0:1 — ровно для этого он в палитре и заведён. */
table.split-grid tfoot .outcome { color: var(--outcome-text); }

/* Меню строки операции: девять пунктов со значками (shtab#1563, пункт 2).
   Значок стоит в своей колонке фиксированной ширины — иначе подписи
   разъезжаются по левому краю и меню читается как список разной длины,
   а не как столбец действий. */
.row-menu { min-width: 268px; }
.menu-ico {
    display: inline-block; width: 22px; margin-right: 4px;
    color: var(--muted); font-size: 14px; text-align: center;
}
.menu-danger .menu-ico { color: inherit; }
.menu-tag-form { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 4px; }
.menu-tag-label { cursor: default; }
.menu-tag-label:hover { background: none; }
.menu-tag-row { display: flex; gap: 6px; padding: 0 12px 8px 38px; }
.menu-tag-row input { flex: 1 1 auto; min-width: 0; padding: 6px 8px; font-size: 13px; }

/* Фильтры колонок спрятаны под воронку — эталон «Финтабло» (shtab#1563).
   Три постоянно раскрытых списка занимали целую строку и читались как часть
   таблицы: глаз спотыкался о них раньше, чем доходил до операций. */
.col-filter-btn {
    border: 0; background: none; cursor: pointer; padding: 0 6px 0 0;
    color: var(--muted); font-size: 12px; line-height: 1;
}
.col-filter-btn:hover { color: var(--accent); }
/* Фильтр стоит — воронка окрашена и с точкой: свёрнутый фильтр без такого
   признака молча врёт про число операций в списке. */
.col-filter-btn.on { color: var(--accent); }
.col-filter-btn.on::after { content: '•'; margin-left: 2px; }
/* `position: fixed`, а не `absolute`: окно фильтра живёт внутри обёртки
   таблицы, у которой своя прокрутка (`overflow-x: auto`) — она обрезала
   список по нижнему краю ячейки, и виден был только поиск. Координаты
   ставит скрипт по месту кнопки. */
.col-filter-pop {
    position: fixed; z-index: 60; min-width: 260px;
    padding: 10px; background: #fff; border: 1px solid var(--border);
    border-radius: 10px; box-shadow: 0 12px 34px rgba(44, 47, 69, .18);
}
.col-filter-pop[hidden] { display: none; }
.col-filter-pop select { width: 100%; font-size: 13px; }
.col-filter-pop .col-filter-search {
    width: 100%; margin-bottom: 8px; padding: 7px 9px; font-size: 13px;
    border: 1px solid var(--border); border-radius: 7px;
}
/* Ячейке заголовка нужна точка отсчёта, иначе окно фильтра прилипнет
   к краю страницы, а не к своей колонке. */
table.grid.txn thead th { position: relative; }
.col-search {
    width: 100%; padding: 7px 9px; font-size: 13px; font-weight: 400;
    border: 1px solid var(--border); border-radius: 7px; background: #fff;
}

/* Фильтр колонки — прокручиваемый список пунктов, как в эталоне «Финтабло»
   (shtab#1563). Был выпадающий `select`: он рисует свой скролл, выглядит
   по-разному в каждом браузере и не даёт подсветить выбранный пункт так,
   как в эталоне. */
.col-filter-list { max-height: 300px; overflow-y: auto; margin: 0 -4px; }
.col-filter-item {
    display: block; width: 100%; text-align: left; border: 0; background: none;
    padding: 8px 12px; border-radius: 7px; font-size: 13.5px; color: var(--text);
    cursor: pointer; line-height: 1.35;
}
.col-filter-item:hover { background: var(--row-hover); }
.col-filter-item[hidden] { display: none; }
/* Выбранный пункт подсвечен — по эталону это первое, что видно при открытии:
   человек должен понять, какой отбор стоит сейчас, а не гадать. */
.col-filter-item.vybran { background: var(--accent-soft); color: var(--accent-dark); font-weight: 600; }
/* Заголовок колонки с открытым фильтром подсвечен целиком, как в эталоне. */
table.grid.txn thead th:has(.col-filter-btn[aria-expanded="true"]) {
    background: var(--accent-soft); border-radius: 8px;
}
.col-filter-pop { width: 340px; }

/* Догрузка списка прокруткой (shtab#1563, п.9). Счётчик «показано N из M»
   стоит рядом с кнопкой: без него не видно, дошёл человек до конца или
   список ещё едет — а это разные вещи, когда операций полторы тысячи. */
.podgruzka { display: flex; align-items: center; gap: 14px; padding: 16px 4px 6px; }
.podgruzka .muted { font-size: 13px; }

/* Настройки авторазнесения (shtab#1563, п.4). Два режима — плашками, а не
   выпадающим списком: их всего два, и оба надо прочитать целиком, прежде
   чем выбрать. Список прятал бы половину вопроса. */
.autoraz-rezhim {
    display: block; border: 1px solid var(--border); border-radius: 10px;
    padding: 14px 16px 14px 44px; margin-bottom: 10px; cursor: pointer; position: relative;
}
.autoraz-rezhim:hover { background: var(--row-hover); }
.autoraz-rezhim.vybran { border-color: var(--accent); background: var(--accent-soft); }
.autoraz-rezhim input { position: absolute; left: 16px; top: 17px; }
.autoraz-imya { display: block; font-weight: 600; font-size: 14.5px; }
.autoraz-poyas { display: block; color: var(--muted); font-size: 13px; margin-top: 4px; line-height: 1.45; }
.autoraz-razdel { border: 0; border-top: 1px solid var(--border); margin: 18px 0 14px; }
.autoraz-podpis { font-size: 13.5px; margin: 0 0 10px; }
.autoraz-isklyucheniya { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.autoraz-isklyuchenie {
    display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
    background: var(--row-hover); border: 1px solid var(--border);
    border-radius: 8px; font-size: 13px;
}
.autoraz-snyat { border: 0; background: none; color: var(--muted); cursor: pointer; font-size: 12px; }
.autoraz-snyat:hover { color: var(--outcome-text); }
.autoraz-pusto { font-size: 13px; margin: 0 0 12px; }
.autoraz-dobavit { display: flex; gap: 8px; flex-wrap: wrap; }
.autoraz-dobavit input { flex: 1 1 260px; min-width: 0; padding: 8px 10px; font-size: 13px; }

/* Окно итога авторазнесения (shtab#1563, п. 5–6). Сводка тремя строками
   сверху: человек должен увидеть числа раньше, чем начнёт листать статьи. */
.itog-svodka {
    background: var(--accent-soft); border-radius: 10px;
    padding: 12px 16px; margin-bottom: 16px;
}
.itog-stroka { font-size: 13.5px; padding: 3px 0; }
.itog-znak { display: inline-block; width: 20px; }
.itog-znak.ok { color: var(--income); }
.itog-znak.vnimanie { color: #b4700f; }
.itog-gruppa {
    display: block; width: 100%; text-align: left; cursor: pointer;
    border: 1px solid var(--border); border-radius: 10px; background: #fff;
    padding: 13px 16px; margin-bottom: 10px;
}
.itog-gruppa:hover { background: var(--row-hover); }
.itog-gruppa-verh { display: flex; align-items: center; gap: 14px; }
.itog-statya { font-weight: 600; font-size: 14.5px; }
.itog-schet { color: var(--muted); font-size: 13px; }
.itog-summa { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.itog-strelka { color: var(--muted); font-size: 18px; }
.itog-kontragenty { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.itog-kontragent {
    background: var(--row-hover); border: 1px solid var(--border);
    border-radius: 7px; padding: 3px 9px; font-size: 12.5px;
}
.itog-foot { justify-content: flex-end; gap: 16px; }
.itog-detali-shapka {
    /* Два этажа в каждой колонке, как в эталоне: подпись сверху, значение
       снизу. `space-between` разводит их по краям полосы — иначе имя статьи
       и её сумма стоят вплотную и читаются одной фразой. */
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; background: var(--row-hover);
    border-radius: 10px; padding: 14px 18px; margin-bottom: 14px;
}
.itog-detali-statya, .itog-detali-itog { display: flex; flex-direction: column; gap: 3px; }
.itog-detali-itog { align-items: flex-end; text-align: right; }
.itog-detali-imya { font-size: 15px; }
.itog-detali-shapka .itog-summa-krupno { font-size: 19px; font-weight: 600; }
.itog-detali-deystviya {
    display: flex; align-items: center; gap: 12px; margin-bottom: 14px;
}
.itog-razneseno-status { font-size: 13px; }
.itog-uspeh-odnoy { margin-bottom: 12px; }
.itog-detal-stroka {
    display: flex; align-items: center; gap: 14px; padding: 11px 14px;
    border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px;
    font-size: 13.5px;
}
.itog-detal-stroka b { margin-left: auto; font-variant-numeric: tabular-nums; }
.itog-detal-stroka .itog-vybor { margin-left: 0; }


/* Подтверждение отмены автоправила — по эталону «Финтабло»
   (etalon-fintablo-avtopravilo-otmena.png): маленькое окно поверх формы,
   форма под ним притушена и остаётся видна — человек понимает, что она
   никуда не делась и её ещё можно спасти. */
/* `display: flex` ниже перебивал бы `[hidden]` (равная специфичность,
   но наш блок идёт в файле позже) — вопрос висел бы поверх окна всегда.
   Поймано на живом экране: скрытый через `hidden` блок оставался виден. */
.rule-podtverzhdenie[hidden] { display: none; }
.rule-podtverzhdenie { position: absolute; inset: 0; display: flex;
    align-items: center; justify-content: center;
    background: rgba(255, 255, 255, .72); border-radius: inherit; z-index: 3; }
.rule-podtverzhdenie-okno { background: #fff; border-radius: 12px;
    padding: 24px 28px; max-width: 420px; box-shadow: 0 10px 34px rgba(20, 24, 40, .18); }
.rule-podtverzhdenie-okno h3 { margin: 0 0 10px; font-size: 17px; line-height: 1.3; }
.rule-podtverzhdenie-okno p { margin: 0 0 18px; }
.rule-podtverzhdenie-knopki { display: flex; gap: 10px; justify-content: flex-end; }
/* Красная — потому что разрушает работу, а не потому что «главная». */
/* Красный затемнён против эталона: белый на #d05a52 даёт контраст 3,8:1
   при требуемых 4,5:1, а на этой кнопке написано разрушающее действие —
   именно её нельзя прочитать неверно. #bf4339 даёт 5,1:1. У владельца
   астигматизм, светлый текст на светлом фоне он читает хуже всех. */
.btn-opasno { background: #bf4339; color: #fff; border-color: #bf4339; }
.btn-opasno:hover { background: #a93a31; border-color: #a93a31; }


/* ── Окно итога авторазнесения: детали статьи ──────────────────────────
   Эталоны: etalon-fintablo-detali-statyi-svyornuto.png и …-razvernuto.png.
   Контрагент — карточка, которая раскрывается: свёрнутая показывает итог,
   раскрытая — сами операции. */
.itog-kontragent-blok { border: 1px solid var(--line); border-radius: 10px;
    margin-bottom: 10px; overflow: hidden; background: #fff; }
.itog-kontragent-blok.razvernut { background: var(--row-hover); }
.itog-kontragent-blok .itog-detal-stroka { display: flex; align-items: center;
    gap: 14px; padding: 12px 14px; border: 0; }
.itog-razvernut { display: flex; align-items: center; gap: 10px; flex: 1;
    background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
    font: inherit; color: inherit; min-height: 44px; }
.itog-galka { color: var(--muted); transition: transform .15s; font-size: 15px; }
.itog-kontragent-blok.razvernut .itog-galka { transform: rotate(180deg); }
.itog-kontragent-imya { font-weight: 600; }
.itog-kontragent-imya .muted { font-weight: 400; font-size: 12.5px; }
/* Кнопка правки проявляется при наведении и наезде клавиатурой, но не
   исчезает совсем: скрытое насовсем действие человек не находит. */
/* Не .35, а .7: при .35 синий на белом даёт контраст около 2:1 — ниже
   любого порога, и у владельца (астигматизм) кнопка попросту не читалась.
   Приглушение оставляем — оно отделяет действие от данных, — но настолько,
   чтобы текст оставался текстом. */
.itog-pravka-statyi { background: none; border: 0; cursor: pointer; font: inherit;
    font-size: 13px; color: var(--accent); opacity: .7; transition: opacity .15s;
    white-space: nowrap; padding: 6px 8px; }
.itog-kontragent-blok:hover .itog-pravka-statyi,
.itog-kontragent-blok.razvernut .itog-pravka-statyi,
.itog-pravka-statyi:focus-visible { opacity: 1; }
.itog-kontragent-summa { white-space: nowrap; }
.itog-operacii { border-top: 1px solid var(--line); background: #fff; }
.itog-operaciya { display: grid;
    grid-template-columns: minmax(90px, 140px) 110px 1fr auto;
    gap: 12px; align-items: baseline; padding: 10px 14px 10px 38px;
    font-size: 13px; border-bottom: 1px solid var(--line); }
.itog-operaciya:last-child { border-bottom: 0; }
.itog-op-schet, .itog-op-data { color: var(--muted); }
.itog-op-nazn { color: var(--text); }
.itog-op-summa { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Принятая правка — видимая отметка, а не тихое изменение: человек должен
   знать, что его выбор учтён, ДО нажатия «Подтвердить и сохранить». */
.itog-pravka-metka { margin: 0 14px 12px; padding: 8px 12px; border-radius: 8px;
    background: #eef3ff; color: #2b4a8b; font-size: 12.5px; }

/* Выбор статьи для контрагента — окошко у кнопки, как в эталоне. */
.itog-vybor-statyi { position: fixed; z-index: 60; width: min(340px, 92vw);
    background: #fff; border-radius: 12px; padding: 16px;
    box-shadow: 0 12px 36px rgba(20, 24, 40, .22); }
.itog-vybor-zagolovok { margin: 0 0 12px; font-weight: 600; font-size: 14px; line-height: 1.35; }
.itog-vybor-poisk { width: 100%; margin-bottom: 10px; }
.itog-vybor-spisok { max-height: 220px; overflow-y: auto; display: flex;
    flex-direction: column; border: 1px solid var(--line); border-radius: 8px; }
.itog-vybor-punkt { text-align: left; background: none; border: 0; font: inherit;
    padding: 9px 12px; cursor: pointer; min-height: 38px; }
.itog-vybor-punkt:hover { background: var(--row-hover); }
.itog-vybor-punkt.vybran { background: #e8efff; font-weight: 600; }
/* «+ Создать новую статью» — полосой во всю ширину под списком, как в
   эталоне: это не третья кнопка в ряду «Отмена / Применить», а выход из
   ситуации «нужного в списке нет». */
.itog-sozdat-statyu { width: 100%; margin-top: 10px; padding: 10px;
    background: var(--row-hover); border: 0; border-radius: 8px; cursor: pointer;
    font: inherit; color: var(--accent); min-height: 42px; }
.itog-sozdat-statyu:hover { background: #e8efff; }
.itog-sozdat-statyu[disabled] { opacity: .6; cursor: default; }
.itog-vybor-knopki { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; }


/* Предпросмотр «кого зацепит правило» — прямо под условием (shtab#1567).
   Не всплывающим окном и не по кнопке: смотреть его должны все, а не те,
   кто догадался нажать. */
.rule-predprosmotr { margin-top: 12px; padding: 12px 14px; border-radius: 10px;
    background: #eef3ff; font-size: 13px; line-height: 1.5; }
.rule-predprosmotr-itog { margin-bottom: 8px; }
.rule-primer { display: grid; grid-template-columns: 82px minmax(90px, 1fr) 2fr auto;
    gap: 10px; align-items: baseline; padding: 4px 0;
    border-top: 1px solid rgba(43, 74, 139, .12); }
.rule-primer b { white-space: nowrap; font-variant-numeric: tabular-nums; }
.rule-primer span:nth-child(3) { overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
@media (max-width: 720px) {
    .rule-primer { grid-template-columns: 1fr auto; }
    .rule-primer span:nth-child(3) { display: none; }
}


/* Инструкция на «Разборе неразнесённых» — свёрнута, как у «Финтабло»
   («Показать инструкцию»). Человек приходит сюда разносить, а не читать;
   прочитать он захочет один раз, а видеть — каждый день. */
.razbor-instrukciya { margin: 0 0 12px; font-size: 12.5px; }
.razbor-instrukciya > summary { cursor: pointer; color: var(--accent);
    padding: 6px 0; min-height: 32px; display: flex; align-items: center; }
.razbor-instrukciya p { margin: 6px 0 0; }

/* «Предлагаем» — подпись, а не часть имени статьи: мельче и приглушённее,
   чтобы глаз читал её как пометку и шёл дальше к самой статье. */
.razbor-predlagaem { font-size: 12px; font-weight: 400; color: var(--muted);
    text-transform: uppercase; letter-spacing: .04em; margin-right: 4px; }

/* «Почему» под контрагентами: не решение, а его основание — потому мельче
   и приглушённее самой статьи, но читаемо (не .35, см. правку контраста). */
.itog-pochemu { display: block; margin-top: 6px; font-size: 12px; line-height: 1.4; }

/* «Что мы сделали» — раскрыто по умолчанию, но сворачивается: первый раз
   это нужно прочесть, на пятый раз — мешает. */
.itog-kak-rabotaet { margin: 0 0 14px; padding: 12px 16px; border-radius: 10px;
    background: #eef3ff; font-size: 13px; }
.itog-kak-rabotaet > summary { cursor: pointer; font-weight: 600; color: #2b4a8b;
    min-height: 28px; display: flex; align-items: center; }
.itog-shagi { margin: 10px 0 0; padding-left: 20px; line-height: 1.55; }
.itog-shagi li { margin-bottom: 6px; }
.itog-shagi li:last-child { margin-bottom: 0; }

/* «Изменить статью всей группе» — в шапке статьи, рядом с её именем: там,
   где человек и смотрит, верна ли статья. */
.itog-pravka-gruppy { display: inline-block; margin-top: 6px; background: none;
    border: 0; padding: 0; cursor: pointer; font: inherit; font-size: 12.5px;
    color: var(--accent); }
.itog-pravka-gruppy:hover { text-decoration: underline; }
.itog-oborot { font-weight: 400; font-size: 12px; margin-left: 6px; }

/* Ручная операция: вся строка — вход в карточку. Подпись «Подробнее»
   появляется при наведении, но ссылка кликабельна всегда: скрытое
   насовсем действие человек не находит. */
.itog-ruchnaya-stroka { align-items: flex-start; }
.itog-podrobnee { flex: 1; color: inherit; text-decoration: none; display: block; }
.itog-podrobnee:hover { text-decoration: none; }
.itog-podrobnee:hover .muted { color: var(--text); }
.itog-podrobnee-znak { display: inline-block; margin-left: 8px; font-size: 12px;
    color: var(--accent); opacity: .6; }
.itog-podrobnee:hover .itog-podrobnee-znak,
.itog-podrobnee:focus-visible .itog-podrobnee-znak { opacity: 1; }
/* Карточка операции открывается ПОВЕРХ окна разбора: иначе она уезжает
   под него, и клик выглядит как «ничего не произошло». */
#card-modal { z-index: 80; }

/* Ручная операция: подробности раскрываются под строкой, как контрагент в
   деталях статьи. Окно поверх окна человек не увидел (Сергей 12.09.2026:
   «не всплывает»), а раскрытие вниз он уже знает по соседнему блоку. */
.itog-ruchnaya-operaciya { border: 1px solid var(--line); border-radius: 10px;
    margin-bottom: 8px; overflow: hidden; background: #fff; }
.itog-ruchnaya-operaciya.razvernut { background: var(--row-hover); }
.itog-ruchnaya-operaciya .itog-detal-stroka { border: 0; margin: 0; }
.itog-razvernut-ruchnuyu { flex: 1; }
.itog-ruchnaya-operaciya.razvernut .itog-galka { transform: rotate(180deg); }
/* `display: grid` ниже перебил бы `[hidden]` — правило-класс идёт в файле
   позже атрибута, и подробности были бы раскрыты у ВСЕХ операций сразу.
   Второй раз за день на одном и том же: любое `display` в правиле,
   которое прячут через `hidden`, требует этой строки рядом. */
.itog-podrobnosti[hidden] { display: none; }
.itog-podrobnosti { border-top: 1px solid var(--line); background: #fff;
    padding: 12px 14px 12px 38px; font-size: 13px; line-height: 1.5;
    display: grid; gap: 6px; }
.itog-podrobnosti .muted { min-width: 64px; display: inline-block; }
.itog-podrobnosti-nazn { white-space: pre-wrap; }
.itog-v-kartochku { color: var(--accent); text-decoration: none; font-size: 12.5px;
    justify-self: start; }
.itog-v-kartochku:hover { text-decoration: underline; }

/* Статья и направление в раскрытом блоке — парами «подпись: значение»,
   в две колонки: так их читают глазами, а не ищут. */
.itog-podrobnosti-polya { display: grid; grid-template-columns: auto 1fr;
    gap: 6px 10px; align-items: baseline; margin-top: 4px; }
.itog-podrobnosti-polya .cell-edit { cursor: pointer; }

/* Окно правки справочника — одно на все справочники «Дашборда».
   shtab#1590. Раньше эти правила жили тремя копиями прямо в шаблонах
   (partners.html, directions.html, accounts.html), и копии УЖЕ разошлись:
   у счетов не был стилизован `select`, а окно правки статьи состоит из
   выпадающих списков на три четверти. Четвёртая копия закрепила бы
   расхождение — правила переехали сюда целиком. */
.dir-modal-backdrop {
    display: none; position: fixed; inset: 0; background: rgba(0,0,0,.35);
    z-index: 1000; align-items: center; justify-content: center;
}
.dir-modal-backdrop.open { display: flex; }
.dir-modal {
    background: var(--panel-bg, #fff); border-radius: 10px; padding: 24px;
    width: 420px; max-width: calc(100vw - 32px); box-shadow: 0 12px 40px rgba(0,0,0,.25);
}
.dir-modal h2 { margin: 0 0 18px; font-size: 19px; }
.dir-modal .field { margin-bottom: 14px; }
.dir-modal label { display: block; font-size: 12.5px; color: var(--muted-fg, #777); margin-bottom: 4px; }
.dir-modal input[type=text], .dir-modal input[type=date],
.dir-modal select, .dir-modal textarea {
    width: 100%; box-sizing: border-box; padding: 8px 10px;
    border: 1px solid var(--border, #ddd); border-radius: 6px; font: inherit;
}
.dir-modal textarea { resize: vertical; min-height: 60px; }
.dir-modal .balance-row { display: flex; gap: 8px; align-items: center; }
.dir-modal .balance-row input { width: auto; }
.dir-modal .archive-row { display: flex; align-items: center; gap: 8px; margin: 18px 0; }
.dir-modal .archive-row input[type=checkbox] { width: auto; }
.dir-modal .actions { display: flex; gap: 10px; align-items: center; margin-top: 6px; }
/* Строка справочника, открывающая окно: курсор и подсветка одни на всех. */
tr.partner-row, tr.acc-row, tr.dir-row, tr.cat-row { cursor: pointer; }
tr.partner-row:hover, tr.acc-row:hover, tr.dir-row:hover, tr.cat-row:hover {
    background: var(--row-hover);
}

/* Название статьи в таблице: кликабельный ТЕКСТ, а не кнопка.
   shtab#1590, правка по слову Сергея 12.09.2026 — на бою названия
   превратились в 111 серых кнопок с рамками, потому что <button> уехал
   без стилей и браузер нарисовал его по умолчанию.

   Тег остаётся <button>: он доступен с клавиатуры и читается голосовым
   доступом как действие — в отличие от кликабельного <span>. Снимается
   только ВИД кнопки. Отклик на наведение обязателен: без него текст не
   выглядит нажимаемым и человек не догадается, что окно вообще есть. */
.cat-open {
    background: none; border: 0; padding: 0; margin: 0;
    font: inherit; color: inherit; text-align: left;
    cursor: pointer;
}
.cat-open:hover { color: var(--accent); text-decoration: underline; }
/* Рамку фокуса НЕ снимаем: по ней человек, идущий с клавиатуры, видит,
   где он находится. Её снятие — первая строка в списке того, чего делать
   нельзя (доступность). */
.cat-open:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px;
}

/* Деньги на ленте разбора — текстовыми парами (--income-text/--outcome-text): светлые
   --income/--outcome на белом дают 3,0–3,5:1 при норме AA 4,5:1 — 102 элемента из 826
   на экране (design-critique shtab#1631/#1663, 13.09.2026). Заливки и диаграммы не трогаем. */
table.grid.txn .txn-main.income, table.grid.txn .cell-money.income, b.income { color: var(--income-text); }
table.grid.txn .txn-main.outcome, table.grid.txn .cell-money.outcome, b.outcome { color: var(--outcome-text); }
