/* app-record.css — общие компоненты «список записей».
   Заведён 16.08.2026 по п. 2 заданий 02-documents.md и 03-accounting.md.

   Причина: одна и та же болезнь лечилась постранично уже трижды. Строка
   таблицы разрасталась до 300 px, состояние говорилось пятью способами,
   действия стояли столбиком ссылок. Сначала это чинили в
   `documents_queue.css`, потом то же самое понадобилось в `accounting.css`,
   дальше будут объекты и контрагенты. Поэтому определения переехали сюда,
   в файл, который `base.html` подключает всем страницам.

   Что здесь лежит:

     .rec-tiles / .rec-tile   — плитки показателей (одна геометрия на весь
                                продукт; `.today-tile` — второе имя того же
                                компонента, чтобы не переписывать главную)
     .rec-table               — плотная таблица записей: строка = строка
     .rec-line / .rec-sub     — главная строка ячейки и подпись под ней
     .rec-state               — состояние ОДНИМ каналом: точка + слово
     .rec-chain               — цепочка связей четырьмя метками, а не
                                четырьмя ссылками в столбик
     .rec-menu                — «…» на строке (`.docs-more-menu` — второе имя)
     .status-compact          — переехало из `documents_queue.css`

   Правило, ради которого всё это существует (канон проекта): **у строки
   один цветовой канал состояния** — полоса слева. Всё остальное внутри
   строки нейтрального цвета. */

/* ─────────────────── плитки показателей ─────────────────── */

/* Группа плиток с явной подписью периода. Пять плиток в ряд, где три
   считают месяц, а две — всю историю, читаются как одна шкала и врут
   глазу; подпись группы называет период вслух. */
.rec-tile-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.rec-tile-group__title {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: var(--line-height-tight);
  color: var(--text-secondary);
}

.rec-tile-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--space-4);
  align-items: start;
}

.rec-tiles,
.today-tiles {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.today-tiles--3,
.today-tiles--4 {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* ── реестр старения долга ──────────────────────────────────────────── */
/* Нужен и на главной, и в «Финансах» (решение Tim 17.08.2026), поэтому
   объявлен здесь и сразу под двумя именами — как .rec-tile / .today-tile.
   Строка читается слева направо: срок → доля полосой → сумма → сколько
   ожиданий. Полоса нужна, чтобы перекос было видно, не сравнивая цифры. */
.rec-aging,
.today-aging {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  background: var(--surface-primary);
  overflow: clip;
}

.rec-aging__row,
.today-aging__row {
  display: grid;
  /* 09.09.2026: добавлена колонка доли. Полоса сравнивает корзины между
     собой, а процент — доля от всей просрочки; без него полоса отвечает на
     один вопрос, а число рядом на другой. */
  grid-template-columns: minmax(120px, auto) minmax(80px, 1fr) minmax(120px, auto) 44px 44px;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-4);
  min-height: 44px;
  color: inherit;
  text-decoration: none;
  border-top: 1px solid var(--border-color);
}

.rec-aging__row:first-child,
.today-aging__row:first-child {
  border-top: 0;
}

.rec-aging__row:hover,
.today-aging__row:hover {
  background: var(--surface-secondary);
}

/* Пустая корзина не должна выглядеть как проблема: гасим её целиком,
   но не убираем — отсутствие долга в интервале это тоже сведение. */
.rec-aging__row.is-empty,
.today-aging__row.is-empty {
  color: var(--text-secondary);
}

.rec-aging__label,
.today-aging__label {
  font-size: var(--font-size-sm);
}

.rec-aging__bar,
.today-aging__bar {
  display: block;
  height: 6px;
  border-radius: 999px;
  background: var(--surface-tertiary);
  overflow: clip;
}

.rec-aging__fill,
.today-aging__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent-interactive);
}

/* Долг старше 90 дней — не сегодняшняя работа, и цветом он не кричит:
   отдельный оттенок, а не тревожный красный. Красным на этом экране
   помечено то, что требует действия сейчас. */
.rec-aging__row.is-stale .rec-aging__fill,
.today-aging__row.is-stale .today-aging__fill {
  background: var(--text-secondary);
}

/* Непустая корзина видна даже при одном проценте: «мало» не должно
   выглядеть как «ничего». 09.09.2026 */
.rec-aging__row:not(.is-empty) .rec-aging__fill,
.today-aging__row:not(.is-empty) .today-aging__fill {
  min-width: 6px;
}

.rec-aging__amount,
.today-aging__amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--font-size-sm);
}

.rec-aging__count,
.today-aging__count {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
}

/* Доля корзины во всей просрочке. Полоса показывает соотношение корзин
   между собой, а это число — сколько от общего долга. 09.09.2026 */
.rec-aging__share,
.today-aging__share {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: var(--font-size-xs);
}

/* Подпись справа от заголовка раздела: итог, чтобы разложение не
   заставляло складывать четыре числа в уме. */
.today-section__aside {
  margin-left: var(--space-2);
  font-weight: 500;
  color: var(--text-secondary);
}

/* Оговорка под «Долгом по срокам»: пока выписки не заведены, это не долг
   арендаторов, а все начисления с прошедшим сроком. Без неё самое крупное
   число на экране читается неправильно. 08.09.2026, отчёт 189. */
.today-aging__caveat {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-xs);
  line-height: 1.4;
  color: var(--text-secondary);
  border-left: 3px solid var(--warning-border, #e0a800);
  padding-left: var(--space-2);
}

.today-section__link {
  margin-left: auto;
  font-size: var(--font-size-xs);
  font-weight: 600;
  color: var(--link-color);
  text-decoration: none;
}

.today-section__link:hover {
  text-decoration: underline;
}


@media (max-width: 640px) {
  .rec-aging__row,
  .today-aging__row {
    grid-template-columns: 1fr auto;
    row-gap: 4px;
  }

  .rec-aging__bar,
  .today-aging__bar {
    grid-column: 1 / -1;
    order: 3;
  }

  .rec-aging__count,
  .today-aging__count {
    display: none;
  }

  /* На узком экране доля важнее счётчика: она объясняет длину полосы. */
  .rec-aging__share,
  .today-aging__share {
    order: 2;
  }
}

.rec-tile,
.today-tile {
  display: block;
  padding: var(--card-padding-sm, 16px);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-lg);
  background: var(--card-bg);
  color: var(--text-primary);
  text-decoration: none;
  transition: background-color 0.16s ease;
}

a.rec-tile:hover,
a.today-tile:hover,
button.rec-tile:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.rec-tile__label,
.today-tile__label {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  line-height: var(--line-height-tight);
}

.rec-tile__value,
.today-tile__value {
  margin-top: var(--space-2);
  font-size: var(--font-size-2xl);
  font-weight: 700;
  line-height: var(--line-height-tight);
  letter-spacing: -0.01em;
  color: var(--text-primary);
  /* Сумма не должна рваться переносом посреди разрядов.
   *
   * Здесь стояло `overflow-wrap: anywhere`, которое делает ровно
   * обратное — разрешает разрыв в любом месте. На телефоне «518 458 ₽»
   * разрывалось, и знак рубля уезжал на вторую строку. Разряды и знак
   * валюты Intl и так соединяет неразрывным пробелом; нам остаётся не
   * ломать это правилом переноса. Чтобы длинная сумма при этом не
   * вылезала за плитку, на узком экране уменьшается кегль — ниже.
   * 18.08.2026 */
  overflow-wrap: normal;
}

.rec-tile__note,
.today-tile__note {
  margin-top: var(--space-1);
  font-size: var(--font-size-xs);
  color: var(--text-muted);
  line-height: var(--line-height-tight);
}

.rec-tile--danger .rec-tile__value,
.today-tile--danger .today-tile__value {
  color: var(--status-error-text, var(--danger-500));
}

/* ─────────────────── строка записи ─────────────────── */

/* Целевая высота строки — 56–72 px. Достигается тремя вещами сразу:
   паддинг 8/12, вертикальное выравнивание по середине и запрет на
   вторую строку текста в ячейке (`.rec-line`). Ни одна из трёх не
   работает без остальных: с `vertical-align: top` строка растёт от
   самой высокой ячейки, а без `.rec-line` растёт от самого длинного
   названия объекта. */
.rec-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.rec-table th,
.rec-table td {
  padding: 8px 12px;
  vertical-align: middle;
  border-bottom: 1px solid var(--border-color);
  font-size: var(--font-size-sm);
}

.rec-table thead th {
  /* Было --surface-secondary: 1,05 к карточке, шапка сливалась с телом
     таблицы. Токен --table-header-bg существовал с 12.08 и не был
     подключён нигде — подключён. 23.08.2026 */
  background: var(--table-header-bg, var(--surface-secondary));
  color: var(--text-secondary);
  font-size: var(--font-size-xs);
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  letter-spacing: 0.02em;
}

.rec-table thead th[data-sort] {
  cursor: pointer;
  user-select: none;
}

.rec-table tbody tr {
  /* Полоса состояния слева — единственный цветной канал строки.
     Прозрачная по умолчанию, чтобы текст не ездил на 3 px, когда
     состояние меняется. */
  border-left: 3px solid transparent;
}

.rec-table tbody tr:hover {
  background: var(--surface-hover);
}

/* Специфичность, а не флаг: базовое правило выше — `.rec-table tbody tr`
   (0,1,2), и одиночный класс его не перебивал. Селектор с тем же
   контекстом даёт (0,2,2) и выигрывает честно. 17.08.2026 */
.rec-table tbody tr.rec-row--warning {
  border-left-color: var(--warning-500);
}

.rec-table tbody tr.rec-row--danger {
  border-left-color: var(--danger-500);
}

.rec-row--muted td {
  opacity: 0.55;
}

.rec-line {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
  line-height: var(--line-height-tight);
}

.rec-sub {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 2px;
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  line-height: var(--line-height-tight);
}

.rec-amount {
  display: block;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-primary);
}

/* ─────────────────── состояние одним каналом ─────────────────── */

.rec-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
}

.rec-state__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}

.rec-state--ok .rec-state__dot {
  background: var(--success-500, #22c55e);
}

.rec-state--warning .rec-state__dot {
  background: var(--warning-500, #f59e0b);
}

.rec-state--danger .rec-state__dot {
  background: var(--danger-500, #ef4444);
}

.rec-state__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
}

/* ─────────────────── цепочка связей ─────────────────── */

/* Было: четыре ссылки-чипа со стрелками между ними — в узкой колонке
   они переносились и добавляли строке до 90 px. Стало: четыре метки по
   одной букве. Что связано — заполнено, чего нет — обведено пунктиром.
   Расшифровка в подсказке к ячейке. */
.rec-chain {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: help;
}

.rec-chain__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-sm);
  border: 1px dashed var(--border-color-strong, var(--border-color));
  background: transparent;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
}

/* Заливка `--surface-tertiary` в тёмной теме почти совпадает с фоном
   карточки (#1f2a36 против #1e293b) — замер 16.08.2026: связанная и
   несвязанная метки выглядели одинаково. Различаем по обводке: сплошная
   и яркая против пунктирной и приглушённой. */
.rec-chain__link.is-on {
  border-style: solid;
  border-color: currentColor;
  background: transparent;
  color: var(--text-primary);
}

/* Прозрачность у «пустой» метки не ставим: `--text-muted` даёт 5,7:1 к
   фону карточки, а 60 % прозрачности роняли контраст до ~2,9:1 — ниже
   порога 4,5:1. Разница читается обводкой: сплошная против пунктирной. */

a.rec-chain__link.is-on:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

/* ─────────────────── меню «…» ─────────────────── */

.rec-menu,
.docs-more-menu {
  position: relative;
}

.rec-menu__trigger,
.docs-more-menu__trigger {
  list-style: none;
  cursor: pointer;
}

/* Треугольник-маркер `<summary>` рисуют по-разному: в WebKit это
   ::-webkit-details-marker, в остальных — ::marker. Гасим оба. */
.rec-menu__trigger::-webkit-details-marker,
.rec-menu__trigger::marker,
.docs-more-menu__trigger::-webkit-details-marker,
.docs-more-menu__trigger::marker {
  display: none;
  content: "";
}

.rec-menu__list,
.docs-more-menu__list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  padding: var(--space-1);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  background: var(--card-bg);
  box-shadow: var(--shadow-lg);
}

.rec-menu__item,
.docs-more-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--font-size-sm);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.rec-menu__item:hover,
.docs-more-menu__item:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.rec-menu__item i,
.docs-more-menu__item i {
  width: 16px;
  color: var(--text-secondary);
}

.rec-menu__item--danger,
.rec-menu__item--danger i {
  color: var(--status-error-text, var(--danger-500));
}

/* ─────────────────── подпись состояния под названием ─────────────────── */

/* Переехало из `documents_queue.css`: тем же компонентом теперь
   пользуется и «Финансы». Постраничные поправки остались на месте. */
.status-compact {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.status-compact .status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.status-compact-note {
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  line-height: var(--line-height-tight);
}

/* ─────────────────── строка фильтров ─────────────────── */

/* Одна строка вместо трёх мест. Геометрия та же, что на `/documents/`:
   поиск тянется, остальные поля фиксированной доли, кнопки справа. */
.rec-filters {
  display: grid;
  grid-template-columns: minmax(200px, 1.7fr) repeat(4, minmax(120px, 1fr)) auto;
  gap: var(--space-2);
  align-items: center;
}

@media (max-width: 1180px) {
  .rec-filters {
    grid-template-columns: minmax(180px, 1.6fr) repeat(2, minmax(120px, 1fr)) auto;
  }
}

/* На телефоне поля идут по два в ряд: в один столбец семь контролов
   давали 428 px только на фильтры (замер 16.08 при 390 px). Поиск
   занимает всю ширину — он длиннее остальных. */
@media (max-width: 760px) {
  .rec-filters {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .rec-filters > *:first-child {
    grid-column: 1 / -1;
  }
}

/* Плитки показателей на узком экране — тоже по две: пять плиток в
   столбик занимали 628 px, то есть полтора экрана до первой строки. */
@media (max-width: 520px) {
  .rec-tiles,
  .today-tiles,
  .today-tiles--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Две колонки на 390 px — это 140 px под плитку, и 24 px кегля сумма
     уже не помещается. Уменьшаем кегль по ширине окна, а не рвём число. */
  .rec-tile__value,
  .today-tile__value {
    font-size: clamp(15px, 4.4vw, var(--font-size-2xl));
  }
}

.rec-filters > * {
  min-width: 0;
}

.rec-filters .filter-control {
  width: 100%;
  /* Было 36 px — ступень «между» двумя, ничего не выражавшая. Панель
     фильтров над списком — обычная, не вспомогательная. 17.08.2026 */
  height: var(--control-h);
  padding: 0 var(--space-3);
  font-size: var(--font-size-sm);
}

.rec-filters__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* Чипы быстрых фильтров: одна переносящаяся полоса, а не панель с
   заголовком и рамкой (панель занимала 250 px и повторяла то, что уже
   стоит в выпадающих списках). */
.rec-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Строка-пояснение рядом с чипами: то, что чипом быть перестало.
   09.09.2026 — «У всех 30 нет: счёта · есть у всех: документ, договор,
   платёж». Занимает одну строку и не притворяется кнопкой. */
.rec-chips__note {
  flex-basis: 100%;
  margin-top: 2px;
  font-size: 0.8125rem;
  line-height: 1.35;
}

.rec-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--card-border);
  border-radius: var(--radius-base);
  background: var(--card-bg);
  color: var(--text-secondary);
  font-size: var(--font-size-xs);
  line-height: 1.4;
  cursor: pointer;
}

.rec-chip strong {
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.rec-chip:hover {
  background: var(--surface-hover);
}

.rec-chip.is-active {
  border-color: var(--accent-interactive, var(--primary-color));
  color: var(--text-primary);
}

/* `--accent-interactive` — цвет ЗАЛИВКИ кнопки (#9333ea): как текст на
   тёмной карточке он даёт 2,7:1. Для текста в проекте есть парный
   `--accent-text` (#c084fc в тёмной теме). Замер 17.08.2026. */
.rec-chip.is-active strong {
  color: var(--accent-text, var(--accent-interactive));
}

/* `.hidden` объявлен в unified-bundle.css, то есть РАНЬШЕ этого файла, и
   при равной специфичности проигрывает `.rec-chips`/`.rec-menu`. Скрипт
   гасит полосу чипов именно классом `hidden` — возвращаем ему силу. */
.rec-chips.hidden,
.rec-tiles.hidden,
.rec-menu.hidden {
  display: none;
}

/* ─────────────────── заголовок группы внутри таблицы ───────────────────

   Две таблицы сводятся в одну, группы разделяются строкой-заголовком, а
   не второй карточкой. Заведено на `/documents/` 16.08.2026 («В работе»
   и «В реестре»), в тот же день понадобилось «Финансам» («Ожидания» и
   «Проводки») — определения переехали сюда. `.docs-group-*` — второе имя
   того же компонента. */

/* 17.08.2026: «Объекты» выводят заголовок группы через <td colspan>, а не
   <th> — в теле таблицы <th> ломает разметку колонок. Компонент общий,
   поэтому оба варианта здесь. */
.rec-group-head th,
.rec-group-head td,
.docs-group-head th,
.docs-group-head td {
  padding: var(--space-4) var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--border-color);
  background: var(--surface-secondary);
  text-align: left;
  font-weight: 400;
  /* Прописные у шапки таблицы сняты ещё 13.08: для кириллицы они
     читаются хуже строчных. Здесь тем более — это подпись, не ярлык. */
  text-transform: none;
  letter-spacing: 0;
}

.rec-group-title,
.docs-group-title {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--text-primary);
}

.rec-group-count,
.docs-group-count {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-tertiary);
  color: var(--text-secondary);
  font-size: var(--font-size-xs);
  font-weight: 700;
}

.rec-group-count:empty,
.docs-group-count:empty {
  display: none;
}

.rec-group-note,
.docs-group-note {
  margin-left: var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: 400;
  color: var(--text-muted);
}

.rec-group-help,
.docs-group-help {
  width: 22px;
  height: 22px;
  min-width: 22px;
  min-height: 22px;
  margin-left: var(--space-2);
  padding: 0;
  border: 1px solid var(--border-color);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 10px;
  cursor: pointer;
  vertical-align: middle;
}

.rec-group-help:hover,
.docs-group-help:hover {
  border-color: var(--border-color-strong);
  color: var(--text-primary);
}

/* Правый край строки-заголовка группы: там живут её собственные
   переключатели (у «Финансов» — состояние ожидания и «обновить»). */
.rec-group-head th {
  position: relative;
}

.rec-group-tools {
  float: right;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

/* Период в подписи плитки — отдельным словом после точки-разделителя.
   Ставить его в название нельзя: «Ожидания открытые за все периоды»
   переносится на две строки и плитки становятся разной высоты. */
.rec-tile__period {
  color: var(--text-muted);
}

.rec-tile__note > .rec-tile__period::before {
  content: " · ";
}

/* ───────── панель раздела, 16.08.2026 ─────────

   Одна строка: поиск тянется, остальное фиксировано, редкое — под «…».
   Заменяет `.action-row`, в которой у «Истории платежей» стояло 13
   кнопок и 5 полей подряд. */

.portal-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  /* Не переносим: поле поиска сжимается, кнопки — нет. С переносом
     «…» уезжала на вторую строку и панель раздела занимала 120 px. */
  flex-wrap: nowrap;
  min-width: 0;
}

@media (max-width: 760px) {
  .portal-toolbar {
    flex-wrap: wrap;
    width: 100%;
  }
}

.portal-toolbar__search {
  flex: 1 1 220px;
  min-width: 0;
  max-width: 340px;
}

.portal-toolbar .filter-control {
  /* Плотная ступень: панель кабинета вспомогательная. */
  height: var(--control-h-sm);
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
}

.portal-toolbar__select {
  flex: 0 1 180px;
  min-width: 0;
}

.portal-toolbar__period {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
}

.portal-toolbar__period .filter-control {
  width: 140px;
}

/* Поля внутри меню «…»: подпись слева, элемент справа. */
.rec-menu__field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.rec-menu__field .filter-control {
  flex: 0 0 auto;
  width: 190px;
  /* Было 30 px. Внутри меню — плотная ступень. */
  height: var(--control-h-sm);
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
}

.rec-menu__group {
  padding: var(--space-2) var(--space-2) 4px;
  font-size: var(--font-size-xs);
  font-weight: 700;
  color: var(--text-muted);
}

.rec-menu__group:not(:first-child) {
  margin-top: 4px;
  border-top: 1px solid var(--border-color);
}

/* Кнопка загрузки прячет системное поле выбора файла: раньше оно стояло
   в строке само по себе — чужой шрифт и надпись «Файл не выбран». */
.portal-upload {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  cursor: pointer;
}

.portal-upload__input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

/* Фокус с клавиатуры попадает на скрытое поле (`opacity: 0`), и кольцо
   рисуется на невидимом элементе: замер 17.08.2026 дал 1,41 — кольца не
   видно. Показываем его на самой кнопке. `overflow: hidden` выше обрезал
   бы обводку, поэтому на время фокуса возвращаем видимое переполнение. */
.portal-upload:focus-within {
  overflow: visible;
  outline: 3px solid var(--focus-ring-color);
  outline-offset: 2px;
}

/* ───────── полоса «смотрю от лица», 16.08.2026 ─────────
   Была полноразмерная секция с заголовком, подзаголовком и подписью
   поля — три пересказа одного и того же на 210 px над содержимым
   кабинета, и это при том, что арендатор её вообще не видит: секция
   только для администратора. */

.portal-impersonate {
  margin-bottom: var(--space-4);
}

.portal-impersonate.is-hidden {
  display: none;
}

.portal-impersonate__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-3);
  border: 1px dashed var(--border-color-strong, var(--border-color));
  border-radius: var(--radius-md);
  background: var(--surface-secondary);
}

.portal-impersonate__row.is-hidden {
  display: none;
}

.portal-impersonate__label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  white-space: nowrap;
}

.portal-impersonate__select {
  flex: 1 1 260px;
  min-width: 0;
  height: 32px;
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
}

.portal-impersonate__search {
  flex: 0 1 200px;
  min-width: 0;
  height: 32px;
  padding: 0 var(--space-2);
  font-size: var(--font-size-sm);
}

/* Контакты поддержки в кабинетах. 17.08.2026 */
.support-contacts {
  display: grid;
  gap: var(--space-2);
}

.support-line {
  display: grid;
  grid-template-columns: minmax(140px, 200px) minmax(0, 1fr);
  gap: var(--space-3);
  align-items: baseline;
}

.support-line__key {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.support-line__value {
  color: var(--text-primary);
}

@media (max-width: 600px) {
  .support-line {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }
}

/* ── отсеянный долг по заменённым договорам ─────────────────────────── */
/* Решение Tim 17.08.2026. Прятать молча нельзя: если статус договора
   где-то проставлен ошибочно, отсев спрячет настоящий долг. Строка
   свёрнута, но на виду, и раскрывается в разбивку по тем же срокам. */

.rec-aging__hidden {
  border-top: 1px solid var(--border-color);
}

.rec-aging__hidden-head,
.rec-aging__hidden > summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-4);
  min-height: 44px;
  cursor: pointer;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  list-style: none;
}

.rec-aging__hidden > summary::-webkit-details-marker {
  display: none;
}

/* Треугольник рисуем сами: у details он выглядит по-разному в разных
   браузерах, а тут это часть строки таблицы. */
.rec-aging__hidden > summary::before {
  content: "▸";
  display: inline-block;
  width: 12px;
  transition: transform 0.15s ease;
}

.rec-aging__hidden[open] > summary::before {
  transform: rotate(90deg);
}

.rec-aging__hidden > summary:hover {
  background: var(--surface-secondary);
  color: var(--text-primary);
}

.rec-aging__hidden-amount {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.rec-aging__hidden-body {
  padding: 0 var(--space-4) var(--space-3) calc(var(--space-4) + 12px + var(--space-3));
  background: var(--surface-secondary);
}

.rec-aging__hidden-note {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
}

.rec-aging__hidden-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(100px, auto) 44px;
  gap: var(--space-3);
  padding: 4px 0;
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
}

.rec-aging__hidden-row > :nth-child(2),
.rec-aging__hidden-row > :nth-child(3) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ── списки на узком экране: таблица → карточки ─────────────────────── */
/*
  Заведено 17.08.2026.

  Замер на 390 px: «Контрагенты», «Объекты», «Документы» и «Приборы»
  выводили десктопную таблицу как есть — из 161 нажимаемой цели 137
  меньше 24 px (ссылки строк 19 px, флажки 18×18). Пальцем не попасть.

  Подписи ячейкам проставляет `responsive-table.js` из шапки таблицы,
  поэтому рендереры страниц не меняются, а новые списки получают
  мобильный вид сами собой. Таблице, которой это не подходит, ставят
  класс `no-mobile-cards`.
*/
/* Списки на узком экране: строка таблицы → карточка «подпись → значение».
   ------------------------------------------------------------------
   Класс `has-mobile-cards` ставит `js/responsive-table.js` тем таблицам,
   которые об этом попросили атрибутом `data-mobile-cards`. По умолчанию
   слой не применяется ни к чему: в продукте уже есть постраничные
   мобильные вёрстки, и поверх них он ломается (разбор — в шапке
   помощника). 17.08.2026 */
/* Порог «список → карточки» — 860 px.
   ---------------------------------------------------------------------
   Замер 17.08.2026: одно и то же решение принималось на ПЯТИ разных
   ширинах — «Контрагенты» 860, «Объекты» 767, «Документы» 767,
   «Финансы» 768, общий слой 720. Причём 767 и 768 стоят рядом: между
   ними полпикселя, на котором не срабатывает ни то, ни другое.

   На практике это значило, что при сужении окна списки превращались в
   карточки по очереди, а не вместе.

   860 выбрано не на глаз: таблицам этих страниц нужно 900–1101 px
   (замер ширины содержимого), ниже они всё равно уезжают вбок. Значит
   переключаться надо раньше, чем начнётся теснота, а не когда станет
   совсем узко.

   Медиа-запрос не умеет читать переменные, поэтому число повторяется в
   файлах страниц — но всегда с ссылкой на эту запись. */
@media (max-width: 860px) {
  table.has-mobile-cards,
  table.has-mobile-cards tbody,
  table.has-mobile-cards tr,
  table.has-mobile-cards td {
    display: block;
    width: auto;
  }

  /* Сброс десктопных ширин.
     ----------------------------------------------------------------
     Одного `width: auto` мало. В `unified-bundle.css` на узком экране
     стоит `.table { min-width: 640px }` — правило родом из времён, когда
     единственным ответом на телефон была горизонтальная прокрутка. Плюс
     колонки просят своё: `.meters-table .col-object { min-width: 170px }`
     и подобные.

     Замер 17.08.2026: карточки на «Приборах» получились шириной 640 px
     внутри экрана в 390 — значения обрезались по правому краю
     («18013448», «30.11.201…»).

     `!important` здесь по делу, и это проверено дважды. 17.08.2026 я
     попробовал снять флаги, решив, что после уборки страничных файлов
     надобность отпала, — и замер на «Приборах» в 390 px показал возврат
     дефекта: `td.col-object` получал `min-width: 170px`, `td.col-actions`
     сжимался с 283 до 48 px. Колоночные правила задаются через
     `colgroup`/`col` и по специфичности слою не уступают. Флаг остаётся:
     слой обязан пересилить ширины, назначенные страницей под свои
     колонки, а перечислять их поимённо — это ровно то размножение
     правил, от которого слой и заводился. */
  table.has-mobile-cards {
    min-width: 0 !important;
  }

  table.has-mobile-cards td {
    min-width: 0 !important;
    max-width: none !important;
    width: auto !important;
  }

  /* Шапка не нужна: подписи переехали в сами ячейки. */
  table.has-mobile-cards thead {
    display: none;
  }

  table.has-mobile-cards tr {
    margin-bottom: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--surface-primary);
  }

  /* Заголовок группы («Срок истёк 22») остаётся полосой, а не карточкой:
     он и так одна ячейка во всю ширину. */
  table.has-mobile-cards tr.rec-group-head,
  table.has-mobile-cards tr.docs-group-head {
    margin-bottom: 0;
    padding: 0;
    border: 0;
    background: transparent;
  }

  table.has-mobile-cards td {
    display: grid;
    grid-template-columns: minmax(90px, 38%) 1fr;
    gap: var(--space-3);
    align-items: baseline;
    padding: 6px 0;
    border: 0;
    /* Строка карточки — цель для пальца, не только для глаза. */
    min-height: 32px;
  }

  table.has-mobile-cards td::before {
    content: attr(data-label);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    /* Подпись переносится, даже если ячейка запрещает перенос.
       Страницы ставят `white-space: nowrap` на колонки дат и номеров
       осознанно — «30.11.202 2» читается как другое число. Но подпись
       это ограничение наследовала: замер 17.08.2026 на «Приборах» —
       «Следующая поверка» не уместилась в свой столбец и наехала на
       дату. Запрет переноса нужен значению, не подписи. */
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* Ячейка без подписи (флажок, меню «…») занимает всю ширину и стоит
     первой строкой карточки — как ручка, за которую её берут. */
  table.has-mobile-cards td:not([data-label]) {
    grid-template-columns: 1fr;
  }

  table.has-mobile-cards td:not([data-label])::before {
    content: none;
  }

  /* Обрезанное значение раскрывается по нажатию.
     ----------------------------------------------------------------
     Решение Tim 18.08.2026: «Раскрывай». На телефоне подсказка `title`
     не всплывает, и из «Максимов Владими…» нельзя узнать целое имя.
     Ячейки, чьё содержимое не помещается, помечает
     `js/responsive-table.js`; здесь только вид. */
  table.has-mobile-cards td[data-truncated] {
    cursor: pointer;
  }

  /* Ссылку раскрывать нажатием нельзя — нажатие по ней ведёт по ссылке.
     Поэтому название, которое и есть ссылка (объект, документ), в
     карточке просто переносится: это главное поле строки, и обрезать
     его без возможности раскрыть — хуже, чем отдать ему вторую строку.
     18.08.2026 */
  table.has-mobile-cards td > a.rec-line,
  table.has-mobile-cards td > a.rec-line:only-child {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* Знак того, что есть что раскрыть: значение подчёркнуто пунктиром —
     тем же приёмом, что подсказки в остальном интерфейсе. Отдельной
     кнопки нет: она заняла бы строку в карточке из четырёх. */
  table.has-mobile-cards td[data-truncated] > .rec-line,
  table.has-mobile-cards td[data-truncated] > .rec-state .rec-state__text {
    text-decoration: underline dotted var(--border-color);
    text-underline-offset: 3px;
  }

  table.has-mobile-cards td[data-expanded] {
    align-items: start;
  }

  table.has-mobile-cards td[data-expanded],
  table.has-mobile-cards td[data-expanded] .rec-line,
  table.has-mobile-cards td[data-expanded] .rec-state,
  table.has-mobile-cards td[data-expanded] .rec-state__text {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  table.has-mobile-cards td[data-expanded] > .rec-line,
  table.has-mobile-cards td[data-expanded] > .rec-state .rec-state__text {
    text-decoration: none;
  }

  table.has-mobile-cards td[data-truncated]:focus-visible {
    outline: 2px solid var(--accent-interactive, var(--primary-color));
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }

  /* Колонка, скрытая на десктопе (свёрнутый «Менеджер»), в карточке
     тоже не нужна: пустая строка «Менеджер —» не сообщает ничего. */
  table.has-mobile-cards td[data-mobile-hidden],
  table.has-mobile-cards td[hidden] {
    display: none;
  }

  /* Цели под палец. 24 px — нижняя граница по WCAG 2.5.8, 44 — размер,
     при котором не приходится целиться. */
  table.has-mobile-cards a,
  table.has-mobile-cards button,
  table.has-mobile-cards summary,
  table.has-mobile-cards [role="button"] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  table.has-mobile-cards input[type="checkbox"],
  table.has-mobile-cards input[type="radio"] {
    width: 22px;
    height: 22px;
    /* Сам флажок оставляем узнаваемым, а зону нажатия расширяем полем. */
    margin: 11px;
  }

  /* Ссылка-подложка строки («открыть карточку по клику в любом месте»)
     на телефоне растягивается на всю карточку, а не на ячейку. */
  table.has-mobile-cards td .property-row-open,
  table.has-mobile-cards td .contractor-row-link {
    min-height: 44px;
  }

  /* Горизонтальная прокрутка контейнера теперь ни к чему: ширины нет. */
  .table-container:has(table.has-mobile-cards),
  .table-wrapper:has(table.has-mobile-cards) {
    overflow-x: visible;
  }
}

/* Цели под палец в списках — общее правило, не привязанное к карточному
   слою.
   ------------------------------------------------------------------
   Замер 17.08.2026 на ширине 390 px, уже ПОСЛЕ того как у страниц
   появилась своя мобильная вёрстка:

     «Контрагенты»  136 целей из 136 меньше 24 px
     «Объекты»       42 из 84
     «Документы»    114 из 146

   Разбор «Контрагентов»: 68 флажков 18×18 и 68 ссылок строки высотой
   19 px. Вёрстка карточек тут ни при чём — карточки как раз есть; мелкие
   именно нажимаемые места. Поэтому правило живёт отдельно от
   `.has-mobile-cards` и работает на любой таблице.

   Нижняя граница WCAG 2.5.8 (AA) — 24×24. Её и берём за минимум для
   ссылок: тянуть текстовую строку до 44 px значит раздуть карточку на
   четверть без пользы.

   `min-height` намеренно без смены `display`: у строчной ссылки внутри
   текста он не действует и ничего не ломает, а у блочной (`.contractor-row-link`
   и подобных, которые и есть вся строка) поднимает высоту до нормы. */
@media (max-width: 860px) {
  table td a,
  table td button,
  table td summary,
  table td [role="button"] {
    min-height: 24px;
    /* Квадратная кнопка-значок («?» у заголовка группы) была 22×22:
       высоту поднимает правило выше, ширину — это. У строчной ссылки
       `min-width` не действует, длинный текст не растягивает. */
    min-width: 24px;
  }

  /* Флажок остаётся 18×18 на вид — размер задан вёрсткой страницы, и
     менять его значит спорить с её сеткой. Расширяем не сам флажок, а
     зону нажатия: прозрачная накладка вокруг доводит цель до 44 px.
     Видимое не меняется, попадать становится нечем не промахнуться. */
  table td input[type="checkbox"],
  table td input[type="radio"] {
    position: relative;
  }

  table td input[type="checkbox"]::after,
  table td input[type="radio"]::after {
    content: "";
    position: absolute;
    /* 18 + 13×2 = 44 */
    inset: -13px;
  }
}

/* Каркас карточки списка — одно определение на все списки.
   ---------------------------------------------------------------------
   Замер 17.08.2026 на 390 px. Одна и та же вещь — строка списка,
   ставшая карточкой, — была нарисована ЧЕТЫРЕ раза, и каждый раз своими
   числами:

     «Контрагенты»  радиус 20, отступ 14, тень 0 16px 34px
     «Объекты»      радиус 16, отступ 12, тень 0 10px 24px
     «Документы»    радиус 12 (токен), отступ 8, тени нет
     общий слой     радиус 16 (токен), отступ 12, тени нет

   Из четырёх радиусов два (20 и 12) вне шкалы для этого размера, тени
   расходятся втрое, отступы — вдвое. Ни одно из различий ничего не
   выражает: это один и тот же объект, просто нарисованный разными
   руками в разное время.

   Здесь он один. Странице остаётся только своё:
   `--list-card-gutter` — место слева под флажок, если он вынесен, и
   `--list-card-gutter-end` — место справа под меню строки.

   Список селекторов вместо класса — чтобы не трогать разметку четырёх
   страниц. Новый список подключается общим слоем (`data-mobile-cards`)
   и попадает сюда сам. */
@media (max-width: 860px) {
  .contractors-page #contractors-table tbody tr[data-contractor-row],
  .properties-page #properties-table tbody tr[data-property-row],
  .documents-queue-table tbody tr,
  table.has-mobile-cards tbody tr {
    position: relative;
    margin-bottom: var(--space-3);
    padding: var(--space-3);
    padding-left: var(--list-card-gutter, var(--space-3));
    padding-right: var(--list-card-gutter-end, var(--space-3));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--surface-primary);
    box-shadow: var(--shadow-md);
  }

  /* Заголовок группы карточкой не становится — он и так полоса. */
  .documents-queue-table tbody tr.docs-group-head,
  table.has-mobile-cards tbody tr.rec-group-head,
  table.has-mobile-cards tbody tr.docs-group-head {
    margin-bottom: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }

  /* И его единственная ячейка — тоже полоса во всю ширину, иначе она
     остаётся шириной первого столбца и режет заголовок («В р…»).
     19.08.2026 */
  table.has-mobile-cards tbody tr.rec-group-head > *,
  table.has-mobile-cards tbody tr.docs-group-head > * {
    display: block;
    width: 100%;
    overflow: visible;
    white-space: normal;
  }
}

/* Расшифровка меток связей в заголовке столбца.
   Была под «?» — её видел только тот, кто уже догадался навести мышь.
   Решение Tim 18.08.2026: подписать. */
.accounting-chain-legend {
  margin-top: 2px;
  font-size: var(--font-size-xs);
  font-weight: 400;
  line-height: 1.25;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
  /* Переносится внутри столбца: в одну строку расшифровка вылезала на
     соседний столбец и обрезалась по краю таблицы. */
  white-space: normal;
  max-width: 220px;
}

/* Строка «показать ещё» под группой таблицы. */
.accounting-more-cell {
  padding: 10px 12px;
  text-align: center;
  background: var(--surface-secondary);
}
