/* Пульт «Табло обменника» — слой поверх Bootstrap 5.3 (data-bs-theme следует
   за data-theme, оба ставит theme.js). Источник решений по облику —
   design-tz-veltora.md, утверждено 24.08.2026.

   Доктрина цвета: цвет означает «нужен человек», всё, что идёт своим ходом, —
   серое. Статусов три (alarm / warn / ok) плюс бренд; каждый статус несёт три
   сигнала — место, слово, форму (треугольник, круг, галочка).

   Две темы — один мир в двух материалах: подсвеченное табло на тёмном поле и
   печатное на тёплой бумаге. Структура, сетка и размеры общие; под
   :root[data-theme="light"] переопределяются только значения токенов.

   Все значения контраста посчитаны в ТЗ (раздел 3); свои оттенки не
   подбирать. Уточнение по --rule-strong: 3.09 / 3.17 он даёт на --ground —
   поэтому обводки полей и одиночные линии лежат на поле, а между строками с
   заливкой стоит декоративная --rule. */
:root {
  /* поле */
  --rail: #141714;
  --ground: #191d19;
  --row: #1e231f;
  --row-alt: #1b201c;
  --hover: #262c27;
  --rule: #2d342e;
  --rule-strong: #5f6c62;
  /* текст и цифры */
  --ink: #eef2ee;
  --ink-2: #b3bfb6;
  --ink-3: #8b998e;
  --figure: #f2e9d0;
  /* статусы — ровно три; плашки: текст / подложка */
  --alarm: #ff5a4d;
  --warn: #ffc247;
  --ok: #43c98a;
  --alarm-ink: #ff5a4d;
  --alarm-wash: #2a1d1b;
  --warn-ink: #ffc247;
  --warn-wash: #2a2110;
  --ok-ink: #43c98a;
  --ok-wash: #14261e;
  /* бренд: заливка и текст */
  --brand: #2fd79a;
  --brand-deep: #10a374;
  --brand-ink: #097552;
  --on-brand: #0d120e;
  --brand-text: var(--brand);
  --danger: #b3241a;
  --on-danger: #ffffff;
  --qr-plate: #ffffff;
  --scrim: rgb(10 12 10 / .66);
  --shadow: 0 16px 40px rgb(0 0 0 / .5);
  /* шрифт: одна гарнитура; моноширинный — только машинным строкам */
  --sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, monospace;
  /* лестница: семь ролей, ни одной половинной, 12px — нижний предел */
  --fs-board: 40px;
  --fs-amount: 22px;
  --fs-title: 17px;
  --fs-body: 15px;
  --fs-meta: 13px;
  --fs-label: 12px;
  --fs-mono: 13px;
  --lh-text: 1.5;
  --lh-tight: 1.15;
  --lh-vn: 1.65;
  --track: .06em;
  /* ритм и скругления */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;
  --r-control: 6px;
  --r-box: 10px;
  --r-pill: 999px;
  /* Bootstrap берёт поле, текст и обводку отсюда */
  --bs-body-font-family: var(--sans);
  --bs-body-font-size: var(--fs-body);
  --bs-body-line-height: var(--lh-text);
  --bs-body-bg: var(--ground);
  --bs-body-color: var(--ink);
  --bs-border-color: var(--rule-strong);
  --bs-danger-rgb: 255, 90, 77;
  color-scheme: dark;
}
:root[data-theme="light"] {
  --rail: #e8e5dc;
  --ground: #f2f0ea;
  --row: #ffffff;
  --row-alt: #f8f6f1;
  --hover: #ebe8e0;
  --rule: #ddd9cf;
  --rule-strong: #8e8676;
  --ink: #171a17;
  --ink-2: #525a51;
  --ink-3: #616860;
  --figure: #2a2118;
  --alarm: #c62a1d;
  --warn: #7f5400;
  --ok: #0f7a4f;
  --alarm-ink: #b3241a;
  --alarm-wash: #fbe7e5;
  --warn-ink: #7f5400;
  --warn-wash: #fbf0d8;
  --ok-ink: #0a7c57;
  --ok-wash: #e4f4ec;
  --brand-text: var(--brand-ink);
  --scrim: rgb(42 33 24 / .45);
  --shadow: 0 16px 40px rgb(42 33 24 / .18);
  --bs-danger-rgb: 179, 36, 26;
  color-scheme: light;
}

/* Атрибут hidden обязан побеждать display, заданный классом: правило вида
   «.bal-hold { display: flex }» перекрывает hidden молча (поймано стендом
   виджета баланса). На reboot с CDN не полагаемся. */
[hidden] { display: none !important; }

html { scrollbar-width: thin; scrollbar-color: var(--rule-strong) transparent; }
body {
  background: var(--ground); color: var(--ink); margin: 0;
  font: 400 var(--fs-body)/var(--lh-text) var(--sans);
  font-variant-numeric: tabular-nums; caret-color: var(--brand-text);
}
::selection { background: var(--brand); color: var(--on-brand); }
b, strong { font-weight: 600; }
.small, small { font-size: var(--fs-meta); }
/* обводка фокуса зависит от темы: бирюза на бумаге даёт 1.86 — в светлой это --brand-ink */
:focus-visible { outline: 2px solid var(--brand-text); outline-offset: 2px; }
.btn:focus-visible, .form-control:focus-visible, .form-select:focus-visible, .form-check-input:focus-visible {
  outline: 2px solid var(--brand-text); outline-offset: 2px; box-shadow: none;
}

/* ── формы трёх сигналов: треугольник — тревога, круг — ждёт, галочка — готово,
   кольцо — идёт своим ходом. Рисуются из currentColor, различимы в сером. ── */
.sign-tri, .chip.bad::before, .dot.red, .first-alarm.alarm .mark, .verdict.bad::before, .cap-word.full::before, .cap .word.full::before {
  clip-path: polygon(50% 0, 100% 100%, 0 100%); border-radius: 0;
}
.sign-check, .chip.ok::before, .dot.green, .verdict::before {
  clip-path: polygon(14% 52%, 0 68%, 38% 100%, 100% 22%, 86% 8%, 38% 72%); border-radius: 0;
}
.chip.idle::before, .chip.info::before, .chip.calm::before, .chip.brand::before {
  background: transparent; box-shadow: inset 0 0 0 2px currentColor;
}
/* ── колонка статуса — канал опознания, не тревоги (ТЗ, раздел 4, правка 27.08):
   у каждого исхода заявки свой силуэт, ни одного общего. Цветов не добавляет —
   различает формой и весом; тон (заливка плашки) остаётся каналом тревоги. ── */
.chip.status-awaiting_payment::before { background: transparent; box-shadow: inset 0 0 0 2px currentColor; clip-path: none; border-radius: 50%; } /* кольцо — ждёт оплату */
.chip.status-paid::before { background: radial-gradient(circle, currentColor 2.5px, transparent 3px); box-shadow: inset 0 0 0 2px currentColor; clip-path: none; border-radius: 50%; } /* точка в кольце — оплачена, выплаты ещё нет */
.chip.status-payout_pending::before { background: currentColor; box-shadow: none; clip-path: none; border-radius: 50%; } /* круг — выплата в очереди */
.chip.status-paid_out::before { background: currentColor; box-shadow: none; border-radius: 0; clip-path: polygon(14% 52%, 0 68%, 38% 100%, 100% 22%, 86% 8%, 38% 72%); } /* галочка — закрыта */
.chip.status-expired::before { background: currentColor; box-shadow: none; border-radius: 0; clip-path: polygon(15% 3%, 3% 15%, 38% 50%, 3% 85%, 15% 97%, 50% 62%, 85% 97%, 97% 85%, 62% 50%, 97% 15%, 85% 3%, 50% 38%); } /* крест — истекла */
.chip.status-refunded::before { background: currentColor; box-shadow: none; border-radius: 0; clip-path: polygon(0 50%, 42% 8%, 42% 34%, 100% 34%, 100% 66%, 42% 66%, 42% 92%); } /* стрелка назад — возвращена */
/* оба треугольника зовут человека, но к разным действиям, и красный против жёлтого —
   ровно та пара, которую путает цветовая слепота; в сером на светлой теме они сливались.
   Сплошной — где двигаются деньги, контурный — где нужно решение. Контур нарисован одним
   полигоном: внешний обход по часовой, внутренний против, шов по левому ребру и оси. */
.chip.status-refund_pending::before { background: currentColor; box-shadow: none; border-radius: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); } /* сплошной треугольник — ждёт возврата */
.chip.status-manual_review::before { background: currentColor; box-shadow: none; border-radius: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%, 50% 0, 50% 32%, 23% 86%, 77% 86%, 50% 32%); } /* контурный треугольник — ручной разбор */

/* ── каркас: рейл + поле ───────────────────────────────────────────────── */
.shell { display: flex; min-height: 100vh; }
.side {
  width: 204px; flex: none; background: var(--rail); border-right: 1px solid var(--rule);
  display: flex; flex-direction: column; padding: var(--s4) var(--s3) var(--s3);
}
.wordmark { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s2) var(--s5); }
/* знак «Поток» — SVG дословно из design/veltora-identity.html */
.wordmark svg { display: block; color: var(--brand-text); flex: none; }
.wordmark b { font-size: var(--fs-title); font-weight: 700; letter-spacing: -.01em; line-height: var(--lh-tight); }
.wordmark span { color: var(--ink-2); font-size: var(--fs-meta); }
.nav-side { display: flex; flex-direction: column; gap: 2px; }
.nav-side a {
  display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  min-height: 36px; border-radius: var(--r-control); color: var(--ink-2);
  text-decoration: none; font-size: var(--fs-body); font-weight: 500;
}
.nav-side a:hover { background: var(--ground); color: var(--ink); }
.nav-side a.active { background: var(--brand); color: var(--on-brand); font-weight: 600; }
.nav-side .count {
  margin-left: auto; min-width: 22px; line-height: 20px; text-align: center;
  font-size: var(--fs-label); font-weight: 600; padding: 0 var(--s2);
  border-radius: var(--r-pill); background: var(--ground); color: var(--ink-2);
}
.nav-side a.active .count { background: var(--on-brand); color: var(--brand); }
.nav-side .count.hot, .nav-side a.active .count.hot { background: var(--alarm-wash); color: var(--alarm-ink); }
.side .foot {
  margin-top: auto; border-top: 1px solid var(--rule); padding: var(--s3) var(--s2) 0;
  display: flex; flex-direction: column; gap: var(--s2); align-items: flex-start;
}
.side .op { font-size: var(--fs-meta); color: var(--ink-2); }
.side .op b { color: var(--ink); }
.side .foot .btn { width: 100%; text-align: left; }

.content { flex: 1; min-width: 0; padding: var(--s4) var(--s5) 64px; }

/* ── табло: курс и остатки накладными цифрами, справа ёмкость счетов ───── */
.board {
  display: flex; flex-wrap: wrap; gap: var(--s4) var(--s6); align-items: flex-start;
  padding: var(--s3) 0 var(--s4); margin: 0 0 var(--s4);
  border-bottom: 1px solid var(--rule-strong);
}
.board > .cell, .bal > .cell { flex: 0 1 auto; min-width: 0; }
#board-capacity { flex: 1 1 200px; }
.board .k, .recon .label {
  font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--track);
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s1);
}
.figure, .recon .value, .bal-big .sum {
  font-size: var(--fs-board); font-weight: 700; line-height: var(--lh-tight);
  letter-spacing: -.02em; color: var(--figure); white-space: nowrap;
}
.figure u, .bal-big .sum u {
  text-decoration: none; font-size: var(--fs-meta); font-weight: 600;
  color: var(--ink-2); letter-spacing: 0; margin-left: var(--s1);
}
.board .under { font-size: var(--fs-meta); color: var(--ink-2); margin-top: var(--s1); }
.board .under.alarm { color: var(--alarm-ink); font-weight: 600; }
/* виджет баланса: разметка одна на странице, тик меняет только числа; блок
   раскрывается в две ячейки табло — «свободно» и «в кошельке» */
.bal { display: contents; }
.bal-hold {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3);
  font-size: var(--fs-meta); color: var(--ink-2); margin-top: var(--s1); max-width: 220px;
}
.bal-hold b { color: var(--ink); font-weight: 600; }
.bal .meter { margin-top: var(--s2); max-width: 220px; }
.bal-stop { font-size: var(--fs-meta); color: var(--alarm-ink); font-weight: 600; margin-top: var(--s1); }
/* выдача встала — это остановка, не «мало денег»; молчащий экран хуже тревожного */
.bal.stop .k, .bal.stop .figure, .bal.stop .figure u { color: var(--alarm-ink); }
.bal-age { font-size: var(--fs-meta); color: var(--warn-ink); font-weight: 600; margin-top: var(--s1); }
.bal-chain { margin-top: var(--s1); font-size: var(--fs-meta); color: var(--ink-2); }
.bal-chain > div { display: flex; justify-content: space-between; gap: var(--s3); line-height: 1.6; }
.bal-chain b { color: var(--ink); font-weight: 600; }
.bal-chain b.apart { color: var(--warn-ink); }
.bal-chain b.bad { color: var(--alarm-ink); }
.bal-accept { margin-top: var(--s2); }
/* ёмкость — четырьмя словами, не процентом; цвет только у исчерпанного */
.cap-list { display: grid; grid-template-columns: max-content 1fr; gap: 2px var(--s3); align-items: baseline; }
.cap { display: contents; }
.cap .name { font-weight: 600; }
.cap .word, .cap-word { color: var(--ink-2); display: inline-flex; align-items: center; gap: var(--s2); white-space: nowrap; }
.cap .word.load, .cap-word.load, .cap .word.busy, .cap-word.busy { color: var(--ink); }
.cap .word.load, .cap-word.load { font-weight: 600; }
.cap .word.off, .cap-word.off { color: var(--ink-3); }
.cap .word.full, .cap-word.full { color: var(--alarm-ink); font-weight: 600; }
.cap .word.full::before, .cap-word.full::before { content: ""; width: 10px; height: 9px; background: currentColor; flex: none; }

/* ── полоса первой тревоги: самое раннее неразрешённое, гаснет по «Прочитано» ── */
.first-alarm {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s3) var(--s4); margin: 0 0 var(--s4); border-radius: var(--r-box);
  background: var(--alarm-wash); color: var(--alarm-ink); font-size: var(--fs-body);
}
.first-alarm.warn { background: var(--warn-wash); color: var(--warn-ink); }
.first-alarm .mark { width: 14px; height: 13px; background: currentColor; flex: none; border-radius: 50%; }
.first-alarm b { font-weight: 700; }
.first-alarm .more { color: inherit; opacity: .85; }
.first-alarm .actions { margin-left: auto; display: flex; gap: var(--s2); }
.first-alarm .btn-quiet { --bs-btn-color: inherit; --bs-btn-hover-color: inherit; }

.pagehead { display: flex; align-items: baseline; gap: var(--s3); margin: 0 0 var(--s3); flex-wrap: wrap; }
.pagehead h1 { font-size: var(--fs-title); font-weight: 600; margin: 0; line-height: var(--lh-tight); }

/* ── секции и таблицы: без карточек, строки одной высоты ───────────────── */
.panel-card { margin: 0 0 var(--s5); }
.panel-card .scroll { overflow-x: auto; }
.card-head {
  display: flex; align-items: baseline; gap: var(--s3); padding: var(--s4) 0 var(--s2);
  border-bottom: 1px solid var(--rule-strong);
}
.card-head h2 { font-size: var(--fs-title); font-weight: 600; margin: 0; line-height: var(--lh-tight); }
.card-head .count, .count {
  font-size: var(--fs-label); font-weight: 600; line-height: 20px; padding: 0 var(--s2);
  border-radius: var(--r-pill); background: var(--row-alt); color: var(--ink-2);
}
.card-head .count.hot { background: var(--alarm-wash); color: var(--alarm-ink); }
.card-head .sub-note { margin-left: auto; color: var(--ink-3); font-size: var(--fs-meta); }
.panel-card .table, .table {
  width: 100%; margin: 0; --bs-table-bg: transparent; --bs-table-color: var(--ink);
  --bs-table-border-color: var(--rule); --bs-table-accent-bg: transparent; color: var(--ink);
}
.table thead th {
  font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--track); text-transform: uppercase;
  color: var(--ink-3); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap; background: transparent; vertical-align: bottom; text-align: left;
}
/* Одиннадцать столбцов устройств не влезали в 1440 на 35 px, и держала их не
   ширина данных, а nowrap у шапки: одиннадцать заголовков просят 831 px
   минимума. Этой таблице заголовки разрешено переносить — 1188 в 1188
   (замерено 30.08). Остальным nowrap остаётся: там он ничего не держит, но
   переносить заголовок ради нечего значит поднять шапку на два этажа. */
.table.head-wrap thead th { white-space: normal; }
.table tbody td {
  padding: var(--s2) var(--s3); height: 44px; border-bottom: 1px solid var(--rule);
  vertical-align: middle; color: var(--ink); background: var(--row);
}
.table tbody tr:nth-child(even) td { background: var(--row-alt); }
.table tbody tr:hover td { background: var(--hover); }
th.num, td.num { text-align: right; }
td.num { font-variant-numeric: tabular-nums; }
/* сумма — опознавательный знак заявки: крупно, табличными цифрами, по разряду */
.money, .lead-money {
  white-space: nowrap; font-size: var(--fs-amount); font-weight: 600; letter-spacing: -.01em;
  line-height: var(--lh-tight); color: var(--figure); font-variant-numeric: tabular-nums;
}
/* приход и расход различаются знаком, а не цветом: движение денег — нормальный ход */
.money.in, .in, .money.out, .out { color: var(--figure); }
.mono { font-family: var(--mono); font-size: var(--fs-mono); }
/* anywhere, а не break-all: русские слова не рвутся посередине в узких колонках */
.sub { font-size: var(--fs-meta); color: var(--ink-2); overflow-wrap: anywhere; margin-top: 2px; font-weight: 400; }
.sub.inline { display: inline; margin: 0; }
td.dimcell { font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2); word-break: break-all; }
.dimtext { color: var(--ink-3); }
/* строка-исключение: тот же фон, что у плашки «отказ»; ждёт человека — фон «ждём» */
.table tbody tr.flag-red td, .table tbody tr.flag-red:hover td { background: var(--alarm-wash); }
.table tbody tr.flag-amber td, .table tbody tr.flag-amber:hover td { background: var(--warn-wash); }
/* завершённое тускнеет, но читается: суммы остаются в силе */
tr.dim td { color: var(--ink-3); }
tr.dim td.money, tr.dim .money { color: var(--ink-2); }
/* успех показывается и гаснет: четыре секунды зелёного, дальше строка серая */
.table tbody tr.fresh td { animation: row-success 4.4s linear forwards; }
tr.fresh .chip { animation: chip-success 4.4s linear forwards; }
/* заливка успеха лежит поверх фона строки внутренней тенью: после затухания
   чередование строк остаётся на месте */
@keyframes row-success { 0%, 90% { box-shadow: inset 0 0 0 999px var(--ok-wash); } 100% { box-shadow: inset 0 0 0 999px transparent; } }
@keyframes chip-success { 0%, 90% { background: var(--ok-wash); color: var(--ok-ink); } 100% { background: transparent; } }
.good { color: var(--ink); }
.overdue { color: var(--alarm-ink); font-weight: 600; }
/* предупреждение, а не отказ: канал жив, риск назревает */
.warnword { color: var(--warn-ink); font-weight: 600; }
.nowrap { white-space: nowrap; }
.packages { font-size: var(--fs-mono); }
/* вьетнамский банковский текст: интервал под составные диакритики, без обрезки */
.bankcell, .acc-name, .raw-text, .vn { line-height: var(--lh-vn); }
/* имя держателя — не машинная строка: в ячейке банка оно набирается Inter;
   строки реквизитов одной высоты — банк и счёт не переносятся, метка держит
   ширину под примечание */
.bankcell { white-space: nowrap; }
.bankcell .sub { font-family: var(--sans); font-size: var(--fs-meta); white-space: normal; }
.acc-label { min-width: 180px; }
/* каретка и метка — соседи в строке, а не два этажа: строчной раскладкой
   метка уходила под каретку и добавляла строке лишние 24 px. Флексить сам
   <td> нельзя — он перестаёт быть табличной ячейкой, и фон с линейкой столбца
   съезжают со строкой (замерено: полоса ячейки 493–537 против строки
   493–569); отсюда своя обёртка на строку имени */
.acc-title { display: flex; align-items: flex-start; }
/* строка реквизита и полоса разбора — две строки таблицы на один счёт, поэтому
   чередование красится классом, а не по номеру узла */
.table tbody tr.acc-row td, .table tbody tr.acc-detail td { background: var(--row); }
.table tbody tr.acc-row.alt td, .table tbody tr.acc-detail.alt td { background: var(--row-alt); }
.table tbody tr.acc-row:hover td, .table tbody tr.acc-detail:hover td { background: var(--hover); }
.table tbody tr.acc-row { cursor: pointer; }
.table tbody tr.acc-detail td { height: auto; }
.disclose {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  width: 24px; height: 24px; margin-right: var(--s1); padding: 0;
  background: none; border: 0; color: var(--ink-3); cursor: pointer;
}
.disclose:hover { color: var(--ink); }
.disclose::before {
  content: ""; width: 6px; height: 6px; border: solid currentColor; border-width: 0 1.5px 1.5px 0;
  transform: rotate(-45deg); margin-left: -2px; transition: transform .15s;
}
.disclose[aria-expanded="true"]::before { transform: rotate(45deg); margin: -3px 0 0 0; }
/* примечание и предупреждение о глухом телефоне не решают высоту строки:
   одна строка с многоточием, полный текст — в подсказке наведения. Зажим
   построчный, а не nowrap: nowrap заставил бы колонку требовать всю длину
   текста и таблица перестала бы помещаться на 1440 (замерено: 1218 > 1178) */
.acc-label .sub, .acc-row td.device .sub {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1;
  white-space: normal; overflow: hidden;
}
/* место держится под каждой необязательной подстрокой, а не под одной:
   примечание у метки, слово ёмкости под статусом, жалоба телефона. Иначе
   строки счетов прыгают по высоте — и между собой, и внутри ячейки, когда
   телефон оглох на живом экране (ТЗ, критерий 26) */
.acc-label .sub, .acc-row td.device .sub, .acc-row .cap-word { min-height: 20px; }
/* слово ёмкости в строке счёта — своя строка, а не хвост тумблера: пустое
   оно инлайном встало бы рядом с тумблером и места бы не заняло */
.acc-row .cap-word { display: flex; }
/* числа разбора: под строкой, а не в строке — иначе таблица не помещается */
.acc-more { display: flex; flex-wrap: wrap; gap: var(--s5); padding: var(--s2) 0 var(--s3); }
.acc-more .cell { min-width: 150px; }
.acc-more .k {
  font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--track);
  text-transform: uppercase; color: var(--ink-3); margin-bottom: var(--s1);
}
.acc-more .v { font-variant-numeric: tabular-nums; }
select[data-device-for] { min-width: 148px; }
.addr { font-size: var(--fs-mono); word-break: break-all; }
.ttl { font-variant-numeric: tabular-nums; }

/* ── статус: место, слово, форма ───────────────────────────────────────── */
/* слово обычным регистром, 13px, без разрядки: капслок с трекингом остаётся
   заголовкам колонок; значение, которое сканируют глазом, так набирается быстрее */
.chip {
  display: inline-flex; align-items: center; gap: var(--s2); white-space: nowrap;
  font-size: var(--fs-meta); font-weight: 600;
  line-height: 22px; padding: 0 var(--s2); border-radius: var(--r-pill); color: var(--ink);
}
.chip::before { content: ""; flex: none; width: 14px; height: 14px; border-radius: 50%; background: currentColor; }
.chip.bad  { background: var(--alarm-wash); color: var(--alarm-ink); }
.chip.warn { background: var(--warn-wash); color: var(--warn-ink); }
/* готово — серое: успех сообщается вспышкой, а не копится. Живое — чернилами,
   завершённое — третичными: «моё сейчас» и «уже история» читаются раньше исхода */
.chip.ok, .chip.info, .chip.calm, .chip.brand { color: var(--ink); }
.chip.idle, .chip.status-paid_out, .chip.status-expired, .chip.status-refunded, tr.dim .chip { color: var(--ink-3); }
/* гипотеза, а не наблюдение: восстановленная сумма не выглядит как разобранная */
.guess { color: var(--ink-2); font-style: italic; }
td.num .guess + .sub { letter-spacing: normal; }
.dot { display: inline-block; width: 10px; height: 10px; margin-right: var(--s2); vertical-align: -1px; background: currentColor; border-radius: 50%; }
.dot.red { color: var(--alarm-ink); width: 11px; }
.dot.amber { color: var(--warn-ink); }
.dot.green { color: var(--ink-2); width: 12px; }
.alert-title { font-weight: 600; }
.alert-kind { font-family: var(--mono); font-size: var(--fs-label); color: var(--ink-3); margin-left: var(--s2); }
.kv { font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2); }
.kv b { color: var(--ink); font-weight: 600; }
.raw { margin-top: var(--s1); }
/* раскрывашка с нарисованным шевроном вместо браузерного треугольника */
.raw summary {
  font-size: var(--fs-meta); color: var(--ink-3); cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: var(--s2);
}
.raw summary::-webkit-details-marker { display: none; }
.raw summary::before {
  content: ""; width: 7px; height: 7px; flex: none; margin-top: -3px;
  border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.raw[open] summary::before { transform: rotate(225deg); margin-top: 3px; }
.raw summary:hover { color: var(--ink); }
.raw-text {
  font-size: var(--fs-meta); color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere;
  margin-top: var(--s1); padding: var(--s2) var(--s3); background: var(--ground);
  border-radius: var(--r-control); max-width: 480px;
}

/* ── кнопки: главная (одна на экран), вторичная, тихая; опасная — вариант главной ── */
.btn {
  --bs-btn-font-family: var(--sans); --bs-btn-font-size: var(--fs-body); --bs-btn-font-weight: 600;
  --bs-btn-line-height: 1.3; --bs-btn-padding-x: var(--s4); --bs-btn-padding-y: var(--s2);
  --bs-btn-border-radius: var(--r-control); min-height: 36px;
}
.btn-sm { --bs-btn-font-size: var(--fs-meta); --bs-btn-padding-x: var(--s3); --bs-btn-padding-y: var(--s1); min-height: 32px; }
/* кромка кнопки — --brand-text: в тёмной теме сливается с заливкой, на бумаге
   даёт печатную кромку 4.57, чтобы яркая заливка не растворялась в поле */
.btn-primary, .btn-go-primary {
  --bs-btn-color: var(--on-brand); --bs-btn-bg: var(--brand); --bs-btn-border-color: var(--brand-text);
  --bs-btn-hover-color: var(--on-brand); --bs-btn-hover-bg: var(--brand-deep); --bs-btn-hover-border-color: var(--brand-text);
  --bs-btn-active-color: var(--on-brand); --bs-btn-active-bg: var(--brand-deep); --bs-btn-active-border-color: var(--brand-deep);
  --bs-btn-disabled-color: var(--on-brand); --bs-btn-disabled-bg: var(--brand); --bs-btn-disabled-border-color: var(--brand);
}
.btn-outline-primary, .btn-outline-secondary, .btn-outline-success {
  --bs-btn-color: var(--ink); --bs-btn-bg: transparent; --bs-btn-border-color: var(--rule-strong);
  --bs-btn-hover-color: var(--ink); --bs-btn-hover-bg: var(--hover); --bs-btn-hover-border-color: var(--ink-2);
  --bs-btn-active-color: var(--ink); --bs-btn-active-bg: var(--hover); --bs-btn-active-border-color: var(--ink-2);
  --bs-btn-disabled-color: var(--ink-3); --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: var(--rule);
}
/* кнопка в строке или в полосе тревоги лежит не на поле: там rule-strong даёт
   2.59–3.03, обводка — ink-3. То же для полей ввода внутри таблиц */
.table .btn-outline-primary, .table .btn-outline-secondary, .table .btn-outline-success,
.first-alarm .btn-outline-primary, .first-alarm .btn-outline-secondary, .first-alarm .btn-outline-success { --bs-btn-border-color: var(--ink-3); }
.table .form-select, .table .form-control { border-color: var(--ink-3); }
.btn-quiet {
  --bs-btn-color: var(--ink-2); --bs-btn-bg: transparent; --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--ink); --bs-btn-hover-bg: var(--hover); --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--ink); --bs-btn-active-bg: var(--hover); --bs-btn-active-border-color: transparent;
  --bs-btn-disabled-color: var(--ink-3); --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: transparent;
}
.btn-outline-danger, .btn-go-danger {
  --bs-btn-color: var(--on-danger); --bs-btn-bg: var(--danger); --bs-btn-border-color: var(--danger);
  --bs-btn-hover-color: var(--on-danger); --bs-btn-hover-bg: var(--danger); --bs-btn-hover-border-color: var(--ink);
  --bs-btn-active-color: var(--on-danger); --bs-btn-active-bg: var(--danger); --bs-btn-active-border-color: var(--ink);
  --bs-btn-disabled-color: var(--on-danger); --bs-btn-disabled-bg: var(--danger); --bs-btn-disabled-border-color: var(--danger);
}
/* запертая на время запроса кнопка: деньги не должны уходить дважды */
.btn:disabled, .btn.disabled { opacity: .55; cursor: progress; }
.form-control, .form-select {
  font-family: var(--sans); font-size: var(--fs-body); line-height: var(--lh-text);
  border-radius: var(--r-control); background: var(--ground); border-color: var(--rule-strong);
  color: var(--ink); min-height: 36px; padding: var(--s1) var(--s3);
}
.form-control-sm, .form-select-sm { font-size: var(--fs-meta); min-height: 32px; }
.form-control::placeholder { color: var(--ink-3); }
.form-control:focus, .form-select:focus {
  background: var(--ground); color: var(--ink); border-color: var(--brand-text);
  box-shadow: 0 0 0 1px var(--brand-text);
}
.form-check-input { border-color: var(--ink-3); background-color: var(--ground); }
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.form-check-input:checked[type="checkbox"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%230d120e' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}
.form-check-input:focus { border-color: var(--brand-text); box-shadow: 0 0 0 1px var(--brand-text); }
.alert { border-radius: var(--r-box); font-size: var(--fs-body); padding: var(--s3) var(--s4); }
.alert-danger { --bs-alert-color: var(--alarm-ink); --bs-alert-bg: var(--alarm-wash); --bs-alert-border-color: var(--alarm-wash); }
.alert-info { --bs-alert-color: var(--ink); --bs-alert-bg: var(--row); --bs-alert-border-color: var(--rule); }
.toolbar { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; margin-bottom: var(--s3); }
.toolbar .grow { flex: 1; min-width: 220px; }
/* ширины полей — классом, не встроенным стилем: встроенный побеждает медиазапрос */
.q-input { width: 240px; }
.q-status { width: auto; }
.rate-num { width: 130px; }
.actions { display: flex; gap: var(--s2); white-space: nowrap; }

/* ── тумблер online/offline: нейтральный, слово рядом ──────────────────── */
.toggle {
  display: inline-flex; align-items: center; gap: var(--s2); cursor: pointer; min-height: 32px;
  background: none; border: 0; padding: 0; font: inherit; color: var(--ink-2);
}
.toggle .switch {
  width: 34px; height: 20px; border-radius: var(--r-pill); flex: none; position: relative;
  background: transparent; border: 1px solid var(--ink-3); transition: background .15s;
}
.toggle .switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--ink-2); transition: left .15s, background .15s;
}
.toggle.on .switch { background: var(--ink-2); border-color: var(--ink-2); }
.toggle.on .switch::after { left: 17px; background: var(--ground); }
.toggle .state { font-size: var(--fs-meta); color: var(--ink-2); white-space: nowrap; }
.toggle.on .state { color: var(--ink); font-weight: 600; }
.toggle.frozen .state { color: var(--alarm-ink); }
@media (prefers-reduced-motion: reduce) {
  .toggle .switch, .toggle .switch::after, .disclose::before { transition: none; }
}

/* ── меню действий «⋮» ─────────────────────────────────────────────────── */
.rowmenu { position: relative; display: inline-block; }
.kebab {
  width: 32px; height: 32px; border-radius: var(--r-control); border: 1px solid transparent;
  background: transparent; color: var(--ink-2); font-size: var(--fs-body); cursor: pointer; line-height: 1;
}
.kebab:hover, .kebab[aria-expanded="true"] { color: var(--ink); background: var(--hover); }
.menu {
  position: fixed; z-index: 20; min-width: 190px;
  background: var(--ground); border: 1px solid var(--rule-strong); border-radius: var(--r-box);
  box-shadow: var(--shadow); padding: var(--s1); text-align: left;
}
.menu button {
  display: block; width: 100%; text-align: left; min-height: 36px; padding: var(--s2) var(--s3);
  font: 400 var(--fs-body)/1.3 var(--sans); color: var(--ink);
  background: none; border: 0; border-radius: var(--r-control); cursor: pointer;
}
.menu button:hover { background: var(--hover); color: var(--ink); }
.menu button.danger { color: var(--alarm-ink); }
.menu button.danger:hover { background: var(--alarm-wash); color: var(--alarm-ink); }

/* ── специфика экранов ─────────────────────────────────────────────────── */
.recon {
  display: grid; grid-template-columns: repeat(3, minmax(190px, 1fr)); gap: var(--s5);
  padding: var(--s3) 0 var(--s4); margin-bottom: var(--s4); border-bottom: 1px solid var(--rule-strong);
}
.recon .value { margin-top: var(--s1); }
.verdict { display: inline-flex; align-items: center; gap: var(--s2); font-weight: 600; color: var(--ink); }
.verdict::before { content: ""; width: 12px; height: 10px; background: var(--ink-2); flex: none; }
.verdict.bad { color: var(--alarm-ink); }
.verdict.bad::before { width: 11px; height: 10px; background: currentColor; }
/* QR: подложка белая в обеих темах — сканеру нужен контраст, у темы здесь нет голоса */
.code-row { display: inline-flex; gap: var(--s3); align-items: flex-start; margin: 0 var(--s4) var(--s1) 0; }
.code-qr { width: 92px; height: 92px; background: var(--qr-plate); padding: 5px; border-radius: var(--r-control); display: block; cursor: zoom-in; }
.qr-big { background: var(--qr-plate); padding: var(--s4); border-radius: var(--r-box); margin: 0 auto var(--s3); width: min(280px, 70vw); }
.qr-big img { width: 100%; height: auto; display: block; }
.qr-big-code { text-align: center; }
.code-badge {
  font-family: var(--mono); font-size: var(--fs-title); letter-spacing: .12em;
  background: var(--ground); color: var(--ink); border: 1px solid var(--rule-strong);
  border-radius: var(--r-control); padding: var(--s1) var(--s3);
}
/* Секрет — не код привязки: во всю ширину, без разрядки, с переносом в любом
   месте — ключ показывается один раз, и увидеть его надо целиком. */
.secret-badge {
  display: block; width: 100%; box-sizing: border-box;
  font-family: var(--mono); font-size: var(--fs-mono); line-height: 1.5;
  word-break: break-all; user-select: all;
  background: var(--ground); color: var(--ink); border: 1px solid var(--rule-strong);
  border-radius: var(--r-control); padding: var(--s2) var(--s3);
}
.secret-row { display: flex; gap: var(--s2); align-items: flex-start; }
.secret-row .btn { flex: none; }
.note-under { color: var(--ink-3); font-size: var(--fs-meta); margin: var(--s2) 0 0; max-width: 80ch; }

/* ── модальные окна взамен браузерных prompt/confirm/alert ─────────────── */
.modal-layer {
  position: fixed; inset: 0; z-index: 40; background: var(--scrim);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 10vh var(--s4) var(--s4); overflow-y: auto;
}
.dlg {
  width: 480px; max-width: 100%; background: var(--ground);
  border: 1px solid var(--rule-strong); border-radius: var(--r-box); box-shadow: var(--shadow);
}
.dlg-head { padding: var(--s4) var(--s5) var(--s3); border-bottom: 1px solid var(--rule); font-weight: 600; font-size: var(--fs-title); line-height: var(--lh-tight); }
.dlg-body { padding: var(--s4) var(--s5) var(--s1); }
.dlg-foot { padding: var(--s3) var(--s5) var(--s4); display: flex; gap: var(--s2); justify-content: flex-end; }
.field { margin-bottom: var(--s3); }
.field > label { display: block; font-size: var(--fs-meta); color: var(--ink-2); margin-bottom: var(--s1); font-weight: 600; }
.field .hint { font-size: var(--fs-meta); color: var(--ink-3); margin-top: var(--s1); }
.field.invalid .form-control, .field.invalid .form-select { border-color: var(--alarm); }
.field.invalid > label { color: var(--alarm-ink); }
.dlg .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.dlg .preview-box {
  background: var(--row); border: 1px solid var(--rule); border-radius: var(--r-control);
  padding: var(--s2) var(--s3); font-size: var(--fs-meta); margin-bottom: var(--s3);
}
.dlg-error { margin: var(--s1) var(--s5) 0; font-size: var(--fs-meta); padding: var(--s2) var(--s3); }
.dlg-note { color: var(--ink-2); font-size: var(--fs-body); margin: 0 0 var(--s3); }

/* ── выгрузка CSV в тулбаре заявок ─────────────────────────────────────── */
.csv-bar { display: inline-flex; gap: var(--s2); align-items: center; margin-left: auto; }
.csv-bar input[type="date"] { width: auto; }

/* ── курс: строка фактического над историей ────────────────────────────── */
.rate-live { padding: var(--s3) 0; font-size: var(--fs-body); border-bottom: 1px solid var(--rule); margin-bottom: var(--s3); }
.rate-live.bad { color: var(--alarm-ink); font-weight: 600; }

/* ── статистика на главной: три окна, без плиток ───────────────────────── */
/* Экран заявок открывают ради очереди: табло → тревога → очередь (ТЗ §7),
   а три окна статистики идут под списком на любой ширине. Ничего не
   спрятано: цифры те же, порядок другой. */
#screen { display: flex; flex-direction: column; }
#screen .stats, #screen .stats-note { order: 5; }
.stats {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5);
  padding: var(--s3) 0; margin-bottom: var(--s2); border-bottom: 1px solid var(--rule);
}
.stats .cell h3 {
  font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--track);
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s2);
}
/* .row совпадает по имени с бутстраповским грид-рядом — возвращаем строке вид пары */
.stats .row { display: flex; justify-content: space-between; gap: var(--s3); font-size: var(--fs-meta); padding: 2px 0; margin: 0; }
.stats .row > * { width: auto; max-width: none; padding: 0; flex: none; }
.stats .row span { color: var(--ink-2); }
.stats .row b { font-weight: 600; }
.stats-note { margin: 0 0 var(--s3); }
@media (max-width: 900px) { .stats, .card-grid { grid-template-columns: 1fr; } }

/* ── карточка заявки и пустые состояния словами ────────────────────────── */
.empty-note { color: var(--ink-3); padding: var(--s3) 0; font-size: var(--fs-body); }
.backlink { margin: 0 0 var(--s3); font-size: var(--fs-meta); }
/* ссылки — навигация, ей положен бренд; в светлой теме это --brand-ink. Все ссылки
   в строках (#screen tbody a), не только data-nav: иначе хеш в «Ушли» уходит в
   бутстраповскую синюю — четвёртый оттенок в палитре из трёх */
.backlink a, #screen a[data-nav], #screen tbody a, .card-body a, .first-alarm a[data-nav] { color: var(--brand-text); text-decoration: none; }
#screen a[data-nav]:hover, #screen tbody a:hover, .card-body a:hover { color: var(--brand-text); text-decoration: underline; text-underline-offset: 3px; }
.first-alarm a[data-nav] { color: var(--ink); }
/* на строке-исключении ссылка — чернилами: сигнал — цвет строки, а не ссылки
   (brand-ink на подложках в светлой теме: 4.80 / 5.05) */
#screen tbody tr.flag-red a, #screen tbody tr.flag-amber a { color: var(--ink); }
/* реквизит — отдельная сущность: свой вес, чтобы глаз выхватывал «через какой счёт» */
.table tbody td.acc-name, .acc-name { color: var(--ink); font-weight: 600; }
.table tbody td.aside { color: var(--ink-3); white-space: nowrap; }
.card-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); }
.card-body { padding: var(--s3) 0 var(--s4); font-size: var(--fs-body); }
.card-body .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin-bottom: var(--s3); }
.card-body .sub { margin-top: var(--s2); }
.card-head .filter { margin-left: auto; }

/* ── крупный виджет вкладки «Баланс» ───────────────────────────────────── */
.bal-big { padding: var(--s4) 0; }
.bal-big .about { color: var(--ink-2); font-size: var(--fs-body); margin: 0 0 var(--s3); }
.bal-big .sum.stop { color: var(--alarm-ink); }
.bal-big .under { color: var(--ink-2); font-size: var(--fs-meta); margin-top: var(--s1); }
.bal-big .under.stop { color: var(--alarm-ink); font-weight: 600; }
.bal-big .meter { margin: var(--s4) 0 var(--s3); max-width: 420px; }
.bal-three { display: flex; gap: var(--s6); flex-wrap: wrap; }
.bal-three .k { color: var(--ink-3); font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--track); text-transform: uppercase; }
.bal-three .v { font-size: var(--fs-amount); font-weight: 600; margin-top: var(--s1); color: var(--figure); letter-spacing: -.01em; }
.bal-three .v.hold, .bal-three .v.all, .bal-three .v.keep { color: var(--ink-2); }
/* одна геометрия полос на весь проект: 4px, пилюля; занятость резерва — серым */
.meter { height: 4px; border-radius: var(--r-pill); background: var(--rule); overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--ink-2); border-radius: var(--r-pill); }
/* автовыплата в шапке экрана выплат: тело в одну строку */
.autopay .card-body { display: flow-root; font-size: var(--fs-meta); }

/* ── вход ──────────────────────────────────────────────────────────────── */
.login-wrap { max-width: 22rem; margin: 14vh auto 0; padding: 0 var(--s4); }
.login-card .wordmark { padding: 0 0 var(--s5); }
.login-card .form-control { margin-bottom: var(--s2); }
.login-card .btn { width: 100%; margin-top: var(--s1); }

@media (max-width: 900px) {
  .shell { flex-direction: column; }
  .side { width: auto; flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--s1); border-right: 0; border-bottom: 1px solid var(--rule); }
  .side .wordmark { padding: 0; }
  .nav-side { flex-direction: row; flex-wrap: wrap; }
  .side .foot { margin: 0 0 0 auto; border: 0; padding: 0; flex-direction: row; align-items: center; gap: var(--s2); }
  .side .foot .btn { width: auto; }
  .side .op { margin: 0; }
  .recon { grid-template-columns: 1fr; }
}

/* Полоса «панель обновилась»: поверх всего и на всю ширину, внизу — вверху
   табло и кнопки, которыми в этот момент пользуются. */
.static-stale {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; gap: var(--s3); align-items: center; justify-content: center;
  padding: var(--s3) var(--s4); background: var(--warn-wash); color: var(--warn-ink);
  font-weight: 600; border-top: 1px solid var(--warn);
}

/* ── телефон: таблица строками не читается ─────────────────────────────
   Ниже 700 px строка становится карточкой: подпись колонки слева (data-label
   расставляет labelCells() в operator.js), значение справа. Порог 700, а не
   900: на планшете в альбоме таблица ещё читается.
   Второе правило блока — палец: ничего касаемого мельче 44 px, поля ввода не
   мельче 16 px — Safari на iOS иначе зумит страницу при фокусе, и форма
   уезжает за край. 16 здесь — требование платформы, а не восьмая ступень
   лестницы. */
@media (max-width: 700px) {
  .content { padding: var(--s3) var(--s3) 64px; }

  /* Вкладки — одной прокручиваемой строкой и всегда на виду. */
  .side { position: sticky; top: 0; z-index: 30; padding: var(--s2) var(--s3); gap: var(--s2); }
  .nav-side {
    order: 3; width: 100%; flex-wrap: nowrap; overflow-x: auto;
    gap: var(--s1); padding-bottom: 2px; scrollbar-width: none;
  }
  .nav-side::-webkit-scrollbar { display: none; }
  .nav-side a { white-space: nowrap; min-height: 44px; padding: var(--s2) var(--s3); }

  /* Табло на телефоне — ячейки друг под другом: две цифры по 40px в ряд
     отрывают единицу от числа и рвут строку курса посреди формулы. */
  .board { gap: var(--s2); }
  .board > .cell, .bal > .cell, #board-capacity { flex-basis: 100%; }
  /* ёмкость — по два счёта в ряд, строки кошелька плотнее: полоса тревоги
     обязана попасть на первый экран телефона */
  .cap-list { grid-template-columns: max-content 1fr max-content 1fr; }
  .bal-chain > div { line-height: 1.4; }
  .first-alarm .actions { margin-left: 0; width: 100%; }
  .first-alarm .actions .btn { flex: 1; }

  /* Строка → карточка. Шапка прячется целиком, а не по th. */
  .panel-card .scroll { overflow-x: visible; }
  .table, .table tbody, .table tbody tr, .table tbody td { display: block; width: auto; }
  .table thead { display: none; }
  .table tbody tr {
    border: 1px solid var(--rule); border-radius: var(--r-box);
    margin: var(--s2) 0; padding: var(--s1) 0; background: var(--row);
  }
  .table tbody tr:nth-child(even) td { background: transparent; }
  /* Наведение на телефоне залипает после тапа — подсветки строки нет. */
  .table tbody tr:hover td { background: transparent; }
  .table tbody td {
    display: flex; gap: var(--s3); align-items: baseline; justify-content: space-between;
    padding: var(--s2) var(--s3); height: auto; min-height: 44px; border-bottom: 0; background: transparent;
  }
  .table tbody td::before {
    content: attr(data-label); flex: none; max-width: 42%; text-align: left;
    font-size: var(--fs-label); letter-spacing: var(--track); text-transform: uppercase;
    color: var(--ink-3); font-family: var(--sans); font-weight: 600;
  }
  .table tbody td .cell-body { flex: 1; min-width: 0; text-align: right; }
  /* Безымянная ячейка — кнопки: занимают всю ширину карточки. */
  .table tbody td.no-label { padding-top: 2px; }
  .table tbody td.no-label::before { display: none; }
  /* Ссылка на заявку — главный переход экрана: 44 по высоте, ширина по тексту. */
  .table tbody td a[data-nav], .backlink a, .card-body a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  /* Цветная строка-исключение — вся карточка. */
  .table tbody tr.flag-red, .table tbody tr.flag-red td { background: var(--alarm-wash); }
  .table tbody tr.flag-amber, .table tbody tr.flag-amber td { background: var(--warn-wash); }
  .table tbody tr.fresh td { animation: none; }
  .table tbody tr.fresh { animation: row-success 4.4s linear forwards; }

  .money, td.dimcell, .addr { white-space: normal; overflow-wrap: anywhere; }

  /* Меню действий: список во всю ширину под карточкой — в «⋮» пальцем не попасть. */
  .rowmenu { display: block; width: 100%; }
  .kebab { width: 100%; height: 44px; font-size: var(--fs-body); color: var(--ink); border-color: var(--rule-strong); }
  .kebab::after { content: " Действия"; }
  .menu { position: static; width: 100%; min-width: 0; margin-top: var(--s2); box-shadow: none; padding: var(--s2); }
  .menu button { min-height: 44px; }

  /* Галочка выбора — тоже касание: родные 15 px мимо пальца, порог тот же,
     что у всего касаемого, — 44. */
  .form-check-input { width: 44px; height: 44px; margin: 0; }

  /* Всё остальное, чего касаются пальцем. */
  .btn, .toggle, .form-control, .form-select, .kebab, .disclose { min-height: 44px; }
  .disclose { min-width: 44px; }
  /* Строка стала карточкой — ровнять по высоте нечего, и пустое место под
     необязательной подстрокой на телефоне только съедает экран. Обёртка метки
     возвращается в блок: в карточке значение прижато вправо, и каретка рядом
     с меткой развернула бы пару влево. */
  .acc-label .sub, .acc-row td.device .sub, .acc-row .cap-word { min-height: 0; }
  .acc-title { display: block; }
  .form-control, .form-select { font-size: 16px; }
  .toolbar { gap: var(--s2); }
  .toolbar .btn, .toolbar .grow { width: 100%; }
  .csv-bar { margin-left: 0; width: 100%; flex-wrap: wrap; }
  .csv-bar input[type="date"], .csv-bar .btn { flex: 1 1 42%; }
  .toolbar .q-input, .toolbar .q-status, .rate-num { width: 100%; }

  /* Модальное окно: во всю ширину и от верха — клавиатура занимает полэкрана. */
  .modal-layer { padding: 4vh var(--s2) var(--s2); }
  .dlg { width: 100%; }
  .dlg .row2, .card-body .row2 { grid-template-columns: 1fr; }
  .dlg-foot .btn { flex: 1; }
  .raw-text { max-width: none; }
}
