/* Оформление окна к Сириусу (спека 026).
 *
 * Это ОКНО, а не отчёт. Отчёт читают один раз и внимательно; окно висит рядом с
 * терминалом весь день и в него заглядывают на секунду. Отсюда всё остальное:
 * плотность выше, чем в принятых страницах (14px против 16px, строки в 1.45),
 * навигация всегда на виду слева, а не заголовками в потоке, и ни одной
 * анимации, кроме той, что сообщает «идёт работа». Движение в боковом зрении —
 * налог, который платится каждым взглядом на экран.
 *
 * ── Про два словаря имён ─────────────────────────────────────────────────
 *
 * Оформление, клиент и разметку писали параллельно, и за время работы на диске
 * побывали ДВА поколения клиента с разными именами одних и тех же вещей:
 *
 *   поколение I  (живое сейчас): .nav-item/.ico, .row>.title/.date/.aux/.days,
 *                .counts/.count, .grid/.tight, .feed-row, .err, .md, .kv,
 *                .scroll, .composer, .panel.collapsed, body.stale, .nav-item.on;
 *   поколение II (было час назад): .navlink/.key, .burn-row/.cell-*, .cards,
 *                .table-wrap, .feed-item, .panel-error, .chat-body, .chat-form,
 *                .shell/.content, html.is-offline, .navlink.active.
 *
 * Оформлены ОБА. Это не запас на всякий случай: имя, которое здесь не оформлено,
 * становится невидимой Никите строкой — без ошибки в консоли, без единого следа.
 * Пока разметка не устоялась, два словаря в CSS дешевле, чем один пропавший
 * раздел. Значения у синонимов одни и те же, чтобы окно выглядело одинаково,
 * какое бы поколение ни оказалось на диске.
 *
 * ── Палитра ──────────────────────────────────────────────────────────────
 *
 * Та же, что в docs/architecture.html, имя в имя (--bg --card --ink --muted
 * --line --accent --opus --sonnet --haiku --fable --mono). Причина не в
 * экономии: agents.html и architecture.html встраиваются iframe'ом в это же
 * окно, и если оболочка заведёт свои цвета, встроенный документ будет спорить с
 * рамкой. Своих добавлено четыре (--hot --warn --ok --chip) плюс их фоновые
 * оттенки и --line2 — тонкая линия внутри таблиц, где полная --line даёт
 * частокол.
 *
 * Ничего внешнего: ни импортов, ни ссылок на чужие хосты, ни одного шрифта из
 * сети — в файле нет ни одного адреса вообще, и это проверяется грепом. Шрифт
 * из сети — это и канал наружу (правило локальности), и пустой экран, пока он
 * не приехал. Системный стек уже принят Никитой в architecture.html.
 */

/* ═══════════════════════ Палитра и темы ═══════════════════════ */

/* ═══════════════════════ Палитра ═══════════════════════
 *
 * Тема «алхимическая печать» — по вкусовой базе Никиты (13.08.2026).
 * Стальной алхимик: Братство — единственный образ с отметкой `love`, а Гарри
 * Поттер и Средиземье, названные им отдельно, сходятся с ним в одну эстетику,
 * а не спорят: сдержанность, историчность, дисциплина линии. Ни неона, ни
 * пастели — ни того, ни другого его база не подтверждает ничем.
 *
 * СВЕТЛОЙ ТЕМЫ НЕТ ВОВСЕ — решение Никиты: «только не светлая, чуть
 * затемнённая». Поэтому обе ветки тёмные, и переключатель выбирает не
 * «светло/темно», а ТЕПЛО или ХОЛОД:
 *
 *   по умолчанию — тёплая полутьма: кабинет при свече, графит с коричневым
 *   [data-theme="dark"] — холодный графит-индиго: сама печать, ночь и металл
 *
 * Что здесь несущее, а что украшение. Несущее — контраст текста к фону (в обеих
 * ветках выше 11:1) и то, что КРАСНЫЙ появляется только на просрочке. Золото
 * держит акценты и тонкие линейки-разделители, но числа им не красятся: цвет,
 * которым выделено всё, не выделяет ничего.
 */
:root {
  color-scheme: dark;

  /* Тёплая полутьма. Фон не чёрный: «чуть затемнённая» — это графит с
     коричневым подтоном, на котором пергаментный текст читается как тушь на
     бумаге при свече, а не как подсветка в темноте. */
  --bg: #1a1815; --card: #232019; --ink: #ece5d8; --muted: #a09585;
  --line: #38322a; --line2: #2c2721; --chip: #2a251e;
  --accent: #c9a227;

  --hot: #d9705c; --hot-bg: #2e1c18;
  --warn: #c9a961; --warn-bg: #2c2418;
  --ok: #7fb98c;  --ok-bg: #1c2a1f;

  --opus: #a08ae0; --sonnet: #7aaede; --haiku: #7cc4a0; --fable: #e08a80;

  --mono: "SF Mono", ui-monospace, Menlo, Consolas, monospace;
  --ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --nav-w: 212px;
  --radius: 11px;
}

/* Холодная ветка — та самая печать: индиго вместо коричневого, золото то же.
   Оба выбора ручные и оба тёмные, поэтому медиазапрос по системной теме здесь
   не нужен вовсе: выбирать не из чего, кроме тепла и холода. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #14161f; --card: #1b1f2b; --ink: #e6e8ef; --muted: #8f95a8;
  --line: #2c3242; --line2: #232836; --chip: #212636;
  --accent: #c9a227;

  --hot: #d9614f; --hot-bg: #2b1a1c;
  --warn: #c9a961; --warn-bg: #2a2519;
  --ok: #6fbf90;  --ok-bg: #17281f;
}

/* Прежний выбор «светлая» мог остаться в localStorage с прошлых версий. Он
   больше ничего не означает и намеренно ведёт в тёплую ветку, а не в белизну:
   иначе окно однажды откроется светлым у человека, который этого не хочет. */
:root[data-theme="light"] { color-scheme: dark; }

/* ═══════════════════════ Основа ═══════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body, h1, h2, h3, h4, h5, h6, p, ul, ol, dl, dd, figure { margin: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.45 var(--ui);
  -webkit-font-smoothing: antialiased;
  /* Скроллит содержимое, а не страница: у окна должна быть неподвижная рама —
     навигация и футер со штампом не уезжают вверх, когда список длинный. */
  overflow: hidden;
  height: 100dvh;
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
}

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

.mono, code, kbd, samp { font-family: var(--mono); }
code {
  font-size: .9em;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  padding: 1px 5px; border-radius: 4px;
}
kbd {
  font: 11px var(--mono); background: var(--chip); color: var(--muted);
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 0 4px;
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }

/* Полосы прокрутки — тонкие и в цвете темы: жирная системная полоса в узком
   окне съедает колонку данных. */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--muted); }

[hidden] { display: none !important; }

/* ═══════════════════════ Раскладка ═══════════════════════
 *
 * Позиции заданы ЯВНО (grid-column/grid-row у каждой области), а не порядком
 * детей. Причина не в педантизме: разметку писал другой исполнитель, и за время
 * работы она сменилась дважды. Раскладка, которая держится на «первый ребёнок —
 * навигация», ломается от перестановки строки; раскладка на явных координатах —
 * нет, и неизвестный ей узел просто ляжет в поток, а не сложит колонку.
 *
 * Поддержаны обе разметки, которые побывали на диске:
 *
 *   I)  body → [#offline] + nav.nav + main.view + section.view + footer.foot
 *       — навигация и экраны лежат прямо в body (живая сейчас);
 *   II) body → [#offline] + .shell(aside.nav + main.content) + footer.foot
 *       — колонку делит .shell, футер лежит СНАРУЖИ оболочки.
 *
 * Сетка body одна и та же: «баннер · тело · футер» по высоте, «навигация ·
 * содержимое» по ширине. В варианте II тело занимает .shell на всю ширину и
 * делит колонку у себя внутри. Ненужные правила просто ни к чему не прилипают.
 *
 * Страница не скроллится целиком никогда: рама неподвижна, прокрутка живёт
 * внутри .view / .content / .chat-log — иначе футер со штампом свежести уезжал
 * бы за край ровно тогда, когда он нужнее всего.
 */

.banner-offline { grid-column: 1 / -1; grid-row: 1; }
.foot           { grid-column: 1 / -1; grid-row: 3; }

/* Вариант I: навигация и экраны — прямые дети body. */
body > .nav  { grid-column: 1; grid-row: 2; }
body > .view { grid-column: 2; grid-row: 2; }

/* Вариант II: оболочка на всю ширину, колонка — внутри неё. */
.shell {
  grid-column: 1 / -1; grid-row: 2;
  min-height: 0;                       /* иначе дети не смогут скроллиться */
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  overflow: hidden;
}
.content {
  min-width: 0; min-height: 0;
  overflow: hidden;                    /* скроллит не он, а его видимый ребёнок */
  display: flex; flex-direction: column;
  background: var(--bg);
}

/* Виден ровно один экран, остальные помечены hidden. Видимый занимает всю
   высоту: панели скроллятся сами, чат прижимает поле ввода к низу. */
.view, .chat, .docs { flex: 1 1 auto; min-height: 0; min-width: 0; }
.view { overflow: auto; padding: 14px 16px 24px; }
.docs, .doc-view { overflow: hidden; display: flex; flex-direction: column; padding: 10px 12px 12px; }
/* Чат — единственный экран, который не скроллится сам: скроллится его лента. */
.chat-view { overflow: hidden; padding: 0; }
.chat-view > .chat { height: 100%; }

/* ═══════════════════════ Навигация ═══════════════════════ */

.nav {
  background: var(--card);
  border-right: 1px solid var(--line);
  padding: 12px 9px 10px;
  overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px;
}

.brand {
  padding: 0 8px 9px; margin-bottom: 6px;
  border-bottom: 1px solid var(--line2);
  display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  font-size: 15px; font-weight: 650; letter-spacing: -.01em;
}
.brand .sub, .brand-sub { font: 10.5px var(--mono); color: var(--muted); font-weight: 400; letter-spacing: 0; }
.brand-name { font-size: 15px; font-weight: 650; letter-spacing: -.01em; }

/* Заголовок группы разделов. Мелко и в разрядку: это указатель, а не пункт. */
.nav-group {
  font-size: 10px; text-transform: uppercase; letter-spacing: .12em;
  color: var(--muted); font-weight: 600; padding: 11px 8px 3px;
}
.nav-spacer { flex: 1 1 auto; min-height: 8px; }
.navlist { display: flex; flex-direction: column; gap: 1px; }

.nav-item, .navlink {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 9px; border-radius: 8px;
  color: var(--ink); font-size: 13.5px; line-height: 1.3;
  border: 1px solid transparent;
  cursor: pointer;
}
.nav-item:hover, .navlink:hover { background: var(--chip); text-decoration: none; }

/* Активный пункт. Клиент поколения I ставит .on и aria-current, поколения II —
   .active; оформлены все три, потому что цена ошибки здесь — «раздел открыт, а
   в навигации не видно, какой».
   Заливкой, а не рамкой: «поярче переключение, а то путаюсь» (Никита, 12.08).
   Тонкая рамка отличала выбранное от невыбранного ровно настолько, чтобы не
   отличать; ровно тот же приём, что у state-btn внутри тикета. */
.nav-item.on, .nav-item.active, .nav-item[aria-current],
.navlink.on, .navlink.active, .navlink[aria-current] {
  background: var(--accent); border-color: var(--accent);
  color: var(--bg); font-weight: 700;
}
.nav-item.on .ico, .nav-item[aria-current] .ico,
.navlink.on .key, .navlink.active .key, .navlink[aria-current] .key { color: var(--bg); }
/* Счётчик у активного пункта: обычная плашка на акцентном фоне пропадала. */
.navlink.on .badge, .navlink.active .badge, .navlink[aria-current] .badge {
  background: color-mix(in srgb, var(--bg) 22%, transparent);
  color: var(--bg);
  border-color: color-mix(in srgb, var(--bg) 45%, transparent);
}

/* Горячая клавиша пункта. Клавиатурой ходят чаще, чем мышью, — цифра видна
   всегда, а не всплывает по Alt. */
.ico, .key {
  flex: none; width: 15px; text-align: center;
  font: 600 11px var(--mono); color: var(--muted);
}
.navtext { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Счётчик у пункта: сколько горит — видно, не открывая раздел. Пустой счётчик
   исчезает целиком: пустой кружок читается как «ноль чего-то важного». */
.badge {
  margin-left: auto; flex: none;
  font: 600 10.5px var(--mono); font-variant-numeric: tabular-nums;
  padding: 1px 6px; border-radius: 10px;
  background: var(--chip); color: var(--muted); border: 1px solid var(--line);
}
.badge:empty { display: none; }
.badge.hot, .badge-hot {
  background: var(--hot-bg); color: var(--hot);
  border-color: color-mix(in srgb, var(--hot) 40%, transparent);
}
.badge-warn {
  background: var(--warn-bg); color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 40%, transparent);
}

.nav-foot {
  margin-top: auto; padding-top: 10px;
  border-top: 1px solid var(--line2);
  display: flex; flex-wrap: wrap; gap: 5px;
}

/* ═══════════════════════ Футер ═══════════════════════ */

.foot {
  border-top: 1px solid var(--line);
  background: var(--card);
  padding: 5px 14px;
  font: 11.5px var(--mono);
  color: var(--muted);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.foot code { background: transparent; padding: 0; color: var(--accent); }
.foot a { color: var(--muted); }
/* В одной разметке поля футера разделяет .foot-item, в другой — точки .sep. */
.foot-item { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.foot-item + .foot-item { margin-left: 8px; }
.sep { opacity: .4; }
/* Подсказка по клавишам — справа: это справка, а не состояние. */
.foot .hint { margin-left: auto; opacity: .75; font-size: 11px; }

/* Точка связи. Цвет ей присваивает клиент (dot on / dot off); без него она
   серая и ничего не утверждает — а зелёная утверждала бы «связь есть». */
.dot { display: inline-block; flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.dot.on { background: var(--ok); }
.dot.off { background: var(--hot); }

/* ═══════════════════════ Панель ═══════════════════════
 *
 * `.panel` — и раздел целиком, и сворачиваемая секция, и карточка внутри сетки:
 * клиент строит из неё всё. Поэтому рамка тонкая, а различает уровни вложение,
 * а не отдельные имена.
 */

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 13px 12px;
  margin-bottom: 12px;
}
.panel:last-child { margin-bottom: 0; }
/* Панель внутри панели — это карточка, а не рамка в рамке. */
.panel .panel { margin-bottom: 0; background: color-mix(in srgb, var(--chip) 35%, transparent); }

.panel-head {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  padding-bottom: 8px; margin-bottom: 10px;
  border-bottom: 1px solid var(--line2);
  cursor: default;
}
.panel-title { font-size: 15.5px; font-weight: 650; letter-spacing: -.01em; }
.panel-body { min-width: 0; }
/* Шапка со стрелкой кликабельна целиком — курсор об этом говорит. */
.panel-head:has(.caret) { cursor: pointer; }
.caret {
  color: var(--muted); font-size: 11px; width: 12px; flex: none;
  transition: transform .15s ease;
}
.panel.collapsed > .panel-head { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.panel.collapsed > .panel-head .caret { transform: rotate(-90deg); }

/* Метаданные шапки: источник и штамп прижаты вправо, кнопка — последней. */
.panel-head > .src { margin-left: auto; }
.panel-meta { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; flex: 1 1 auto; min-width: 0; }
.panel-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }

/* Верхняя кромка панели-раздела — её единственная примета в боковом зрении: по
   цвету видно, где ты, не читая заголовок. Цвета взяты из общего с
   architecture.html набора, своих не заведено. */
.panel-burn, .panel-money, .panel-capital, .panel-debts,
.panel-travel, .panel-health, .panel-roadmap, .panel-feed {
  border-top: 2px solid var(--panel-accent, var(--line));
}
.panel-burn    { --panel-accent: var(--hot); }
.panel-money   { --panel-accent: var(--accent); }
.panel-capital { --panel-accent: var(--haiku); }
.panel-debts   { --panel-accent: var(--muted); }
.panel-travel  { --panel-accent: var(--sonnet); }
.panel-health  { --panel-accent: var(--fable); }
.panel-roadmap { --panel-accent: var(--opus); }
.panel-feed    { --panel-accent: var(--line); }
.panel-roadmap .panel-body { max-width: 96ch; }

/* Свёртка второго поколения: своя рамка вместо .panel.collapsed. */
.fold { border: 1px solid var(--line2); border-radius: 9px; margin: 10px 0; overflow: hidden; }
.fold-head {
  display: flex; align-items: baseline; gap: 7px;
  width: 100%; text-align: left; padding: 6px 10px;
  background: color-mix(in srgb, var(--chip) 55%, transparent);
  border: none; border-bottom: 1px solid var(--line2);
  color: var(--ink); font: 600 12px var(--ui);
  letter-spacing: .04em; text-transform: uppercase; cursor: pointer;
}
.fold-head:hover { background: var(--chip); }
.fold-mark { flex: none; color: var(--muted); font-size: 10px; }
.fold-title { flex: 1 1 auto; min-width: 0; }
.fold-body { min-width: 0; }
.fold > .fold-body { padding: 8px 10px 10px; }
.folded > .fold-head { border-bottom: none; }

/* Плитка вместо полос.
 *
 * Свёрнутая секция несла одну строку текста и занимала всю ширину окна — на
 * 1440 px это восемь полос подряд, между которыми глаз идёт вниз, хотя вопрос
 * («где деньги», «из чего ликвид») решается взглядом вширь. В плитке они стоят
 * по нескольку в ряд и читаются одним движением.
 *
 * Раскрытая занимает ряд целиком намеренно: внутри таблица со счетами, и в
 * колонке 260 px она рассыпалась бы на переносы. То есть ширину получает то,
 * что открыто, а не всё подряд. */
.fold-grid {
  display: grid; gap: 9px; align-items: start; margin: 10px 0;
  grid-template-columns: repeat(auto-fill, minmax(min(258px, 100%), 1fr));
}
.fold-grid > .fold { margin: 0; }
.fold-grid > .fold:not(.folded) { grid-column: 1 / -1; }
.fold-grid > .fold.folded > .fold-head {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; row-gap: 6px; padding: 8px 10px;
}
/* Третий ребёнок заголовка — чипсы с суммой; в узкой карточке они уходят на
 * вторую строку под название, а не жмут его до многоточия. */
.fold-grid > .fold.folded > .fold-head > :nth-child(3) { grid-column: 2; }
.fold-grid > .fold.folded .fold-title { overflow: hidden; text-overflow: ellipsis; }

/* `.pairs` — для сеток, где внутри не таблица, а список строк: там раскрытая
 * секция не требует всей ширины и встаёт в половину. Так «Хочу» читается в две
 * колонки вместо девяти полос, а на узком экране правило снимается — две
 * колонки по 130 px были бы хуже одной. Плотная укладка убирает дыры, которые
 * иначе оставляют элементы разной ширины. */
.fold-grid.pairs { grid-auto-flow: row dense; }
.fold-grid.pairs > .fold:not(.folded) { grid-column: 1 / -1; }
@media (min-width: 1000px) {
  .fold-grid.pairs > .fold:not(.folded) { grid-column: span 2; }
}

/* ═══════════════════════ Ярусы сроков ═══════════════════════
 *
 * Ярус 1 — «видно с той стороны комнаты»: красная планка слева, крупные строки.
 * Ярус 3 — долг системы: он ОБЯЗАН быть виден (иначе честности нет) и обязан не
 * соревноваться с горящим за внимание — если кричит всё, не кричит ничто.
 * Отсюда приглушение целиком, а не мелкий шрифт: размер читается как «мелочь»,
 * приглушение — как «не сейчас».
 */

.tier { margin-bottom: 12px; }
.panel.tier1 { border-left: 3px solid var(--hot); }
.tier1 > .panel-head { border-bottom-color: color-mix(in srgb, var(--hot) 30%, transparent); }
.tier1 > .panel-head .panel-title { color: var(--hot); }
.tier1 .row {
  border-left: 3px solid var(--hot);
  background: color-mix(in srgb, var(--hot-bg) 55%, transparent);
  border-bottom: none; margin-bottom: 3px; padding: 7px 9px;
}
.tier1 .row:hover { background: var(--hot-bg); }
.tier1 .row .title { font-size: 14.5px; font-weight: 600; line-height: 1.32; }
.tier1 .row .days { font-size: 13.5px; font-weight: 650; }

.tier2 .row .title { font-size: 13.5px; }

.tier3 { opacity: .72; }
.tier3:hover { opacity: 1; transition: opacity .2s ease; }
.tier3 > .panel-head .panel-title { color: var(--muted); }
.tier3 .row { padding: 3px 6px; font-size: 12.5px; }
.tier3 .row .title { color: var(--muted); }
.tier3 .row .title b, .tier3 .row .title strong { color: var(--ink); font-weight: 600; }

/* Панель «Долг системы» целиком — по той же причине, что и ярус 3. */
.panel-debts .rows { opacity: .8; }
.panel-debts .rows:hover { opacity: 1; }

/* ═══════════════════════ Заголовки, пустота, ошибки ═══════════════════════ */

.section-title, .sub-h {
  font-size: 11px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--muted); font-weight: 600;
  margin: 16px 0 7px;
}
.panel-body > .section-title:first-child, .panel-body > .sub-h:first-child { margin-top: 2px; }

/* Пусто — это ответ, а не сбой; поэтому спокойно и словами. */
.empty {
  color: var(--muted); font-size: 13px; font-style: italic;
  padding: 12px; text-align: center;
  border: 1px dashed var(--line); border-radius: 8px;
}
.loading { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; padding: 18px 4px; }

/* Панель не бросает исключений — она их показывает. Ошибка занимает место
   данных, чтобы пустая панель не читалась как «ничего нет». */
.err, .panel-error {
  background: var(--hot-bg);
  border: 1px solid color-mix(in srgb, var(--hot) 35%, transparent);
  border-left-width: 3px; border-radius: 8px;
  padding: 8px 11px; margin: 8px 0;
  color: var(--hot); font-size: 13px;
}
.err b, .panel-error b { font-weight: 650; }

.note, .hint { color: var(--muted); font-size: 12px; margin-top: 7px; max-width: 96ch; }
.note.i { font-style: italic; }
.note.warn { color: var(--warn); }

/* «Панель пришла в форме, которой я не знаю» — сырьё под кат. «Данных нет» и
   «я не понял данные» это разные утверждения, и путать их нельзя. */
.raw { margin-top: 10px; font-size: 12.5px; }
.raw > summary { cursor: pointer; font: 11.5px var(--mono); padding: 3px 0; list-style: none; }
.raw > summary::-webkit-details-marker { display: none; }
.raw > summary::before { content: "▸ "; }
.raw[open] > summary::before { content: "▾ "; }

/* ═══════════════════════ Числа, источники, штампы ═══════════════════════ */

/* Цифры всегда моноширинные и табличные: столбец чисел, где «1» уже «8»,
   читается как разный порядок величины. */
.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
}
td.num, th.num, .num.r { text-align: right; }
.num.big { font-size: 20px; font-weight: 650; letter-spacing: -.02em; line-height: 1.15; }
.num.neg { color: var(--hot); }
.num.pos { color: var(--ok); }

/* Валюта — словом рядом с числом. Разные валюты не складываются нигде, поэтому
   подпись стоит у каждой суммы, а не в шапке столбца. */
.cur { font: 11.5px var(--mono); color: var(--muted); margin-left: 3px; }
/* known = 0 значит «сумма неизвестна», а не ноль. Ноль здесь был бы не
   округлением, а выдумкой, поэтому у неизвестного свой вид — словом. */
.unknown { font-style: italic; font-size: 12.5px; color: var(--muted); }

/* «Сколько дней» — крайний правый столбец: выровнен по правому краю и с запасом
   ширины под минус, иначе строка с «−12» толкает всю строку. */
.days {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--muted); font-size: 12px;
  min-width: 4ch; text-align: right;
}
.days.overdue { color: var(--hot); font-weight: 650; }
.days.soon { color: var(--warn); font-weight: 600; }

/* Подпись источника — правило «у каждого числа видно происхождение». Мелкая и
   моноширинная: это имя вьюхи, а не фраза, и читается как код. Незаметна, пока
   её не ищут. */
.src {
  display: inline-block; max-width: 52ch;
  font: 10.5px var(--mono); color: var(--muted);
  background: var(--chip); border: 1px solid var(--line);
  padding: 1px 6px; border-radius: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  vertical-align: baseline;
}

/* Штамп несёт время целиком — вместе со словом «посчитано», которое кладёт
   клиент. Подписи от оформления здесь нет намеренно: пока она была
   (`::before { content: "данные на " }`), в окне читалось «данные на посчитано
   00:37» — два автора подписали одно и то же с разных сторон. Слова о данных
   пишет тот, кто знает, что это за данные. */
.stamp { font: 10.5px var(--mono); color: var(--muted); white-space: nowrap; }
.stamp.bare::before { content: none; }
.stamp.bare { color: inherit; opacity: .9; }

/* ═══════════════════════ Плашки, счётчики, распределения ═══════════════════════ */

.chip {
  display: inline-flex; align-items: baseline; gap: 4px;
  font: 11.5px var(--mono);
  background: var(--chip); color: var(--muted);
  border: 1px solid var(--line); border-radius: 20px;
  padding: 1px 8px; white-space: nowrap;
  max-width: 48ch; overflow: hidden; text-overflow: ellipsis;
}
.chip .n, .chip-n { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.chips { display: flex; flex-wrap: wrap; gap: 5px; align-items: baseline; }

.chip.hot  { background: var(--hot-bg);  color: var(--hot);  border-color: color-mix(in srgb, var(--hot) 38%, transparent); }
.chip.warn { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 38%, transparent); }
.chip.ok   { background: var(--ok-bg);   color: var(--ok);   border-color: color-mix(in srgb, var(--ok) 38%, transparent); }
.chip.hot .n, .chip.hot .chip-n   { color: var(--hot); }
.chip.warn .n, .chip.warn .chip-n { color: var(--warn); }
.chip.ok .n, .chip.ok .chip-n     { color: var(--ok); }
/* Приглушённая плашка — фон, а не сообщение: её читают, когда спрашивают. */
.chip.mut, .chip.src-chip, .chip.scope, .chip.domain { background: transparent; opacity: .82; }
.chip.src-chip, .chip.scope { border-style: dashed; font-size: 10.5px; }
.chip.agent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); font-weight: 600; }
.chip.opus   { color: var(--opus);   border-color: color-mix(in srgb, var(--opus) 40%, transparent); }
.chip.sonnet { color: var(--sonnet); border-color: color-mix(in srgb, var(--sonnet) 40%, transparent); }
.chip.haiku  { color: var(--haiku);  border-color: color-mix(in srgb, var(--haiku) 40%, transparent); }
.chip.fable  { color: var(--fable);  border-color: color-mix(in srgb, var(--fable) 40%, transparent); }

/* Приоритеты роадмапа: P0 обязан выделяться из ряда, P2–P3 — не обязаны. */
.chip.prio-P0, .p0 { background: var(--hot-bg); color: var(--hot); border-color: color-mix(in srgb, var(--hot) 40%, transparent); }
.chip.prio-P0 .n { color: var(--hot); }
.chip.prio-P1, .p1 { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.chip.prio-P1 .n { color: var(--warn); }
.chip.prio-P2, .chip.prio-P3, .p2, .p3 { opacity: .75; }
.chip.prio { letter-spacing: .04em; }

/* Ряд крупных счётчиков — «горит / впереди / долг системы». Число крупно,
   подпись мелко: с расстояния читается число, вблизи — что это. Ровно тот
   случай, ради которого окно вообще открыто. */
.counts, .chips-lead { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 11px; align-items: stretch; }
.count {
  flex: 1 1 120px; min-width: 100px;
  background: var(--chip); border: 1px solid var(--line); border-radius: 9px;
  padding: 7px 11px;
}
.count .n {
  display: block;
  font: 650 23px/1.05 var(--mono); font-variant-numeric: tabular-nums;
  letter-spacing: -.02em; color: var(--ink);
}
.count .k { display: block; font-size: 11px; color: var(--muted); margin-top: 3px; }
.count.hot  { background: var(--hot-bg);  border-color: color-mix(in srgb, var(--hot) 32%, transparent); }
.count.hot .n  { color: var(--hot); font-size: 27px; }
.count.warn { background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.count.warn .n { color: var(--warn); }
.count.ok   { background: var(--ok-bg);   border-color: color-mix(in srgb, var(--ok) 32%, transparent); }
.count.ok .n   { color: var(--ok); }
.count.mut  { opacity: .78; }
/* Второе поколение делало тот же ряд плашками, а не карточками. */
.chips-lead .chip { font-size: 12.5px; padding: 4px 12px; }
.chips-lead .chip-n { font-size: 16px; letter-spacing: -.02em; }
.chips-lead .chip.tier1 { background: var(--hot-bg); color: var(--hot); border-color: color-mix(in srgb, var(--hot) 45%, transparent); font-weight: 600; }
.chips-lead .chip.tier1 .chip-n { color: var(--hot); font-size: 19px; }
.chips-lead .chip.tier3 { opacity: .7; }
.chips-src { margin-bottom: 10px; opacity: .82; }

/* Пары «ключ — число»: по источникам, по видам ёмкостей, по состояниям. */
.kv { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 14px; font-size: 12.5px; }
.kv .k { color: var(--muted); overflow-wrap: anywhere; }
.kv .v { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; }

/* ═══════════════════════ Состояния ═══════════════════════
 *
 * Состояние приходит из вьюхи словом (state ∈ open|overdue|due_soon|…) и словом
 * же показывается — раскрашена только степень срочности. Значков нет: значок
 * надо помнить, слово — нет. Ширина фиксирована по самому длинному состоянию: в
 * столбце из сорока строк плашки разной ширины дают рваный край, и глаз читает
 * его как структуру, которой нет.
 */

.state {
  display: inline-block;
  font: 600 10px var(--mono); letter-spacing: .04em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 5px; white-space: nowrap;
  background: var(--chip); color: var(--muted); border: 1px solid var(--line);
  min-width: 11ch; text-align: center;
}

/* Просрочено, ни разу, не закрыто — это долг, и он красный. */
.state-overdue, .state-never, .state-unresolved {
  background: var(--hot-bg); color: var(--hot);
  border-color: color-mix(in srgb, var(--hot) 40%, transparent);
}
/* Срок подходит. */
.state-due_soon {
  background: var(--warn-bg); color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 40%, transparent);
}
/* Открыто и действует — нейтральное: это не тревога, это работа. */
.state-open, .state-active { background: var(--chip); color: var(--ink); border-color: var(--line); }
/* Сомнение, а не тревога: пунктир — «числу верить с оглядкой». */
.state-stale, .state-unverified, .state-unchecked,
.state-unconfirmed, .state-imprecise, .state-inherited {
  background: transparent; color: var(--muted); border-style: dashed;
}
/* Снято с повестки: обязанность есть, тревоги нет. */
.state-disabled, .state-no_date, .state-accepted,
.state-dropped, .state-cancelled {
  background: transparent; color: var(--muted); opacity: .78; border-color: var(--line2);
}
/* Закрыто. */
.state-done, .state-paid, .state-ok, .state-achieved, .state-closed {
  background: var(--ok-bg); color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 38%, transparent);
}

/* ═══════════════════════ Таблицы ═══════════════════════ */

/* Обёртка скроллит таблицу вбок, а шапка липнет к её верху: таблица остатков
   длиннее экрана, а столбец чисел без шапки — просто числа. */
.scroll, .table-wrap, .md-table-wrap {
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  max-height: min(70vh, 660px);
  border: 1px solid var(--line2); border-radius: 8px;
  margin-bottom: 4px;
}
.md-table-wrap { max-height: none; margin: .6em 0; }

table { border-collapse: collapse; width: 100%; font-size: 13px; }
th, td { text-align: left; padding: 5px 9px; border-bottom: 1px solid var(--line2); vertical-align: top; }
th {
  background: var(--chip); color: var(--muted);
  font: 600 10.5px var(--ui); text-transform: uppercase; letter-spacing: .06em;
  white-space: nowrap;
  position: sticky; top: 0; z-index: 2;
  box-shadow: inset 0 -1px 0 var(--line);
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: color-mix(in srgb, var(--chip) 55%, transparent); }
td.t { font-family: var(--mono); font-size: 12.5px; white-space: nowrap; }
td.w { color: var(--muted); font-size: 12.5px; }
td.tot, tr.tot td { font-weight: 700; border-top: 2px solid var(--line); }
tr.mut td { opacity: .7; }

/* `.grid` на ТАБЛИЦЕ — это класс таблицы (второе поколение), на диве — сетка
   карточек (первое). Одно имя, две роли: различаем тегом, иначе таблица с
   display:grid рассыпается в столбик. */
table.grid td { overflow-wrap: anywhere; }
div.grid { display: grid; gap: 11px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
/* 300px — не вкус, а замер: уже этого таблица остатков уезжает под прокрутку,
   и одна колонка целиком лучше двух обрубленных. */
div.grid.tight { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 9px; }

/* Столбцы с деньгами — по правому краю и по разряду. Номера колонок совпадают с
   заголовками, которые собирает клиент; менять их вместе с ним. */
.money-grid td:nth-child(3), .money-grid th:nth-child(3) { text-align: right; }
.month-grid td:nth-child(n+2), .month-grid th:nth-child(n+2) { text-align: right; }
.capacity-grid td:nth-child(2) { color: var(--muted); font-size: 12.5px; }

/* ═══════════════════════ Строки ═══════════════════════ */

.rows { display: flex; flex-direction: column; }

.row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 5px 7px; border-radius: 6px;
  border-bottom: 1px solid var(--line2);
  min-width: 0;
}
.row:last-child { border-bottom: none; }
.row:hover { background: color-mix(in srgb, var(--chip) 60%, transparent); }

/* Заголовок переносится, а не обрезается многоточием: спрятанный хвост строки
   про то, что горит, — ровно та ложь, ради устранения которой окно и делалось. */
.row .title { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.row .date { font: 12px var(--mono); color: var(--muted); white-space: nowrap; min-width: 9ch; }
.row .aux { color: var(--muted); font-size: 12.5px; }
.row .right, .right { margin-left: auto; }

/* Ячейки второго поколения — те же роли под другими именами. */
.cell-title { min-width: 0; overflow-wrap: anywhere; }
.cell-date { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.cell-days { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--muted); white-space: nowrap; }
.cell-when, .cell-last { font-size: 12.5px; white-space: nowrap; }
.cell-detail { font-size: 12.5px; min-width: 0; overflow-wrap: anywhere; }
.cell-tags { display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; min-width: 0; }
.row-note { font-size: 11.5px; line-height: 1.35; }

.burn-row { display: grid; grid-template-columns: 10ch 13ch minmax(0, 1fr) auto; gap: 3px 12px; align-items: baseline; }
.health-row { display: grid; grid-template-columns: minmax(0, 1fr) 19ch 21ch auto; gap: 2px 12px; align-items: baseline; }
.health-row .row-note { grid-column: 1 / -1; }
.debt-row { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: 2px 12px; align-items: baseline; padding: 3px 7px; font-size: 12.5px; }
/* Источник и «в стол» — одна ячейка: на узком окне строка схлопывается в
   колонку, и две отдельные ячейки дали бы каждой из 58 строк лишний этаж. */
.debt-aux { display: flex; gap: 8px; align-items: baseline; justify-self: end; min-width: 0; }
.debt-row .src { max-width: 40ch; }
.burn-row.state-overdue .cell-days, .burn-row.state-never .cell-days { color: var(--hot); font-weight: 650; }
.burn-row.state-due_soon .cell-days { color: var(--warn); font-weight: 600; }
.health-row.state-never, .health-row.state-overdue { background: color-mix(in srgb, var(--hot-bg) 45%, transparent); }
.health-row.state-never .cell-when, .health-row.state-overdue .cell-when { color: var(--hot); font-weight: 600; }

/* Карточки второго поколения: «что горит» плиткой и своды по валютам. */
.burn-cards, .cards { display: grid; gap: 9px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.burn-card, .card {
  border: 1px solid var(--line); border-left: 3px solid var(--line); border-radius: 9px;
  padding: 9px 11px; background: var(--card);
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.burn-card { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; }
.burn-when { display: flex; flex-direction: column; gap: 1px; min-width: 9ch; }
.burn-date { font-size: 14px; font-weight: 600; }
.burn-days { font: 600 12px var(--mono); font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.burn-what { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.burn-title { font-size: 14.5px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.burn-sub { display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
.burn-card.state-overdue, .burn-card.state-never {
  border-left-color: var(--hot); background: color-mix(in srgb, var(--hot-bg) 55%, transparent);
}
.burn-card.state-overdue .burn-days, .burn-card.state-never .burn-days { color: var(--hot); font-size: 13px; }
.burn-card.state-due_soon { border-left-color: var(--warn); background: color-mix(in srgb, var(--warn-bg) 50%, transparent); }
.burn-card.state-due_soon .burn-days { color: var(--warn); }

.card-title { font-size: 13.5px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.card-num { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 19px; font-weight: 650; line-height: 1.15; letter-spacing: -.02em; overflow-wrap: anywhere; }
.card-sub { font-size: 12px; color: var(--muted); }
/* «Счета без суммы в итог не вошли» — не примечание, а поправка к числу. */
.card-warn { font-size: 12px; color: var(--warn); }
.money-card .card-num { font-size: 21px; }
.goal-card.state-achieved, .liab-card.state-closed, .liab-card.state-paid { border-left-color: var(--ok); }
.goal-card.state-overdue, .liab-card.state-overdue { border-left-color: var(--hot); }
.goal-card.state-due_soon, .liab-card.state-due_soon { border-left-color: var(--warn); }
.liab-card .card-num { font-size: 17px; }

/* ═══════════════════════ Полоса «дни против порога» ═══════════════════════ */

/* Ширину задаёт клиент инлайном; цвет — классом, а не порогом в CSS: порог живёт
   в данных, а не в оформлении. */
.bar {
  display: flex; height: 9px; margin: 5px 0;
  background: var(--chip); border: 1px solid var(--line);
  border-radius: 5px; overflow: hidden;
}
.bar > i, .bar-fill { display: block; height: 100%; background: var(--ok); }
.bar.warn > i, .bar-fill.level-warn { background: var(--warn); }
.bar.hot > i, .bar-fill.level-hot { background: var(--hot); }
.bar-fill.level-ok { background: var(--ok); }
/* Заштрихованный хвост — дни без посадочных: граница может оказаться ближе, чем
   показывает сплошная часть, и это обязано быть видно глазом, а не только в
   подписи. Клиент дублирует штриховку инлайном — пусть переживёт любое
   оформление. */
.bar-unc, .bar > i.bar-unc {
  height: 100%;
  background: repeating-linear-gradient(135deg, currentColor 0 2px, transparent 2px 5px);
  opacity: .55;
}

.travel-row {
  display: flex; flex-direction: column; gap: 5px;
  padding: 9px 11px; margin-bottom: 8px;
  border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: 9px; background: var(--card);
}
.travel-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.travel-name { font-size: 14px; font-weight: 650; }
.travel-num { margin-left: auto; font-size: 13px; color: var(--muted); }
.travel-sub { font-size: 12.5px; }
.travel-row.level-ok { border-left-color: var(--ok); }
.travel-row.level-warn { border-left-color: var(--warn); }
.travel-row.level-hot { border-left-color: var(--hot); background: color-mix(in srgb, var(--hot-bg) 45%, transparent); }
.travel-row.level-hot .travel-num { color: var(--hot); font-weight: 650; }

/* ── Материалы гайда (тикет #14) ─────────────────────────────
   Списки заметок/мест/гайдбуков внутри свёртки «Гайд». Стили короткие —
   карточка с заголовком, датой, кратким описанием, тегами и путём к файлу. */
.guide-list, .guide-reports {
  list-style: none; margin: 6px 0 14px 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.guide-note {
  padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--card);
}
.guide-note-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.guide-note-title { font-size: 13.5px; font-weight: 650; }
.guide-note-date { font-size: 11.5px; margin-left: auto; }
.guide-note-sum { margin-top: 4px; font-size: 12.5px; line-height: 1.45; }
.guide-note-foot {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-top: 5px;
}
.guide-note-path { font-size: 11px; margin-left: auto; }
.guide-report { padding: 5px 4px; font-size: 13px; }
.guide-report-link { font-weight: 600; }

/* ═══════════════════════ Лента системы ═══════════════════════ */

.feed-row {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto;
  gap: 3px 12px; align-items: baseline;
  padding: 5px 6px; border-bottom: 1px solid var(--line2); font-size: 12.5px;
}
.feed-row:last-child { border-bottom: none; }
.feed-row:hover { background: color-mix(in srgb, var(--chip) 55%, transparent); }
.feed-row .ts { font: 11.5px var(--mono); color: var(--muted); white-space: nowrap; }
.feed-row .who { font: 600 11.5px var(--mono); color: var(--accent); white-space: nowrap; }
/* Причина записи — то, ради чего лента существует: видно не только «кто писал»,
   но и «зачем». Поэтому она полноразмерная, а не подпись. */
.feed-row .why { color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.feed-row .meta { font: 11.5px var(--mono); color: var(--muted); white-space: nowrap; }
.verdict { font-weight: 600; }
.verdict.ok { color: var(--ok); }
.verdict.no { color: var(--hot); }

.feed { display: flex; flex-direction: column; }
.feed-item { padding: 6px 7px; border-bottom: 1px solid var(--line2); min-width: 0; }
.feed-item:last-child { border-bottom: none; }
.feed-head { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; font-size: 12px; }
.feed-time { font: 11.5px var(--mono); color: var(--muted); min-width: 9ch; }
.feed-reason { margin-top: 3px; font-size: 12.5px; overflow-wrap: anywhere; cursor: pointer; }
.feed-target { margin-top: 3px; font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }

/* ═══════════════════════ Markdown: ответ чата и роадмап ═══════════════════════ */

/* Ширина ограничена — строка длиной в окно теряется при переходе на следующую. */
.md, .chat-body, .roadmap { font-size: 13.5px; line-height: 1.55; max-width: 92ch; }
.md > * + *, .chat-body > * + *, .roadmap > * + * { margin-top: .6em; }
.md h1, .md h2, .roadmap h1, .roadmap h2, .chat-body h2 {
  font-size: 15px; font-weight: 650; margin-top: 1.1em;
  padding-bottom: 5px; border-bottom: 1px solid var(--line2);
}
.md h3, .md h4, .roadmap h3, .roadmap h4, .chat-body h3, .chat-body h4 {
  font-size: 13.5px; font-weight: 650; margin-top: .9em; color: var(--accent);
}
.md h5, .md h6, .chat-body h5, .chat-body h6 { font-size: 13px; font-weight: 650; margin-top: .8em; }
.md ul, .md ol, .roadmap ul, .roadmap ol, .chat-body ul, .chat-body ol, .md-list { padding-left: 1.35em; }
.md li + li, .roadmap li + li, .chat-body li + li { margin-top: .22em; }
.md li::marker, .roadmap li::marker, .chat-body li::marker { color: var(--muted); }
.md b, .md strong, .chat-body strong { font-weight: 650; }
.md del, .chat-body del { color: var(--muted); }
.md blockquote, .chat-body blockquote { border-left: 3px solid var(--line); padding-left: 10px; color: var(--muted); }
.md table, .chat-body table { font-size: 12.5px; }
.md th, .chat-body th, .md-table-wrap th { position: static; }
.md hr, .chat-body hr { border: none; border-top: 1px solid var(--line); margin: 1em 0; }

/* Блоки кода: и в ответе чата, и в «сырых данных панели». */
.md pre, .chat-body pre, pre.code, pre.mono {
  background: var(--chip); border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 11px; overflow-x: auto; max-height: 60vh;
  font: 12px/1.45 var(--mono);
  margin: .5em 0;
}
.md pre code, .chat-body pre code, pre.code code, pre.mono code {
  background: none; padding: 0; font-size: inherit;
}

/* Путь на диске из [[FILE: …]]: клик кладёт его в буфер. Пунктир снизу —
   единственный знак того, что это не просто текст. */
.file-ref {
  cursor: pointer;
  border-bottom: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
}
.file-ref.copied { background: var(--ok-bg); color: var(--ok); border-bottom-color: transparent; }

/* Чекбоксы роадмапа приходят disabled по устройству: фронт не пишет ни во что,
   отметку ставит Сириус по просьбе из чата. Курсор «нельзя» на них не ставим —
   он читался бы как поломка; вместо этого рядом живёт кнопка «→ в чат». */
li.task { list-style: none; margin-left: -1.25em; display: flex; gap: 7px; align-items: baseline; flex-wrap: wrap; }
li.task input[type="checkbox"] { margin: 0; flex: none; opacity: .85; }
li.task > span { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
li.task.done > span, li.task.done { color: var(--muted); }
.to-chat {
  opacity: 0; flex: none;
  font: 11px var(--ui); color: var(--accent);
  background: none; border: 1px solid var(--line); border-radius: 6px;
  padding: 0 6px; cursor: pointer; white-space: nowrap;
}
li.task:hover .to-chat, .to-chat:focus-visible { opacity: 1; }

/* ═══════════════════════ Встроенные документы ═══════════════════════ */

/* agents.html и architecture.html показываются как есть — рамка окна не должна
   выдавать их за свою страницу, поэтому только высота и тонкая граница.
   Рукописной копии схемы здесь нет и быть не может (правило одной правды). */
.doc-wrap { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.doc-head { padding-bottom: 7px; margin-bottom: 0; border-bottom: 1px solid var(--line2); }
.doc-frame {
  flex: 1 1 auto; width: 100%; min-height: 320px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card);
}

/* ═══════════════════════ Чат ═══════════════════════ */

/* Единственный экран во всю высоту: поток скроллится сам, поле ввода прижато к
   низу и не уезжает вместе с ответом. */
.chat { display: flex; flex-direction: column; overflow: hidden; }
.chat-head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 16px; margin-bottom: 0;
  border-bottom: 1px solid var(--line); background: var(--card);
  font-size: 12.5px; color: var(--muted);
}
.chat-head .title { font-size: 14px; font-weight: 650; color: var(--ink); }
.chat-head .right { margin-left: auto; display: flex; gap: 6px; align-items: center; }

/* Индикатор живого микрофона — виден всегда, пока сеанс открыт (спека 056
   §2): красная точка, а не оформление, — тот же смысл, что у ОС-индикатора
   записи, продублированный внутри окна. */
.voice-indicator {
  font-size: 11.5px; font-weight: 600; color: var(--hot);
  animation: work-pulse 1.4s ease-in-out infinite;
}

.chat-log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 14px 16px 20px;
  display: flex; flex-direction: column; gap: 9px;
}

.chat-msg { border-radius: 12px; padding: 8px 12px; max-width: min(80ch, 92%); overflow-wrap: anywhere; }
/* Реплики Никиты справа и с подложкой, ответ — слева и без рамки: разговор
   должен читаться как разговор, а ответ — как текст, из которого копируют. */
.chat-msg.user { align-self: flex-end; background: var(--chip); border: 1px solid var(--line); }
.chat-msg.claude { align-self: flex-start; background: transparent; border: none; padding-left: 0; max-width: min(86ch, 100%); }
.chat-msg.pending { color: var(--muted); }
.chat-msg .who {
  display: block; font: 600 10.5px var(--mono); letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 3px;
}
.chat-msg.claude .who { color: var(--accent); }
.chat-msg .cost, .chat-meta { display: block; margin-top: 5px; font: 10.5px var(--mono); color: var(--muted); }
.chat-msg.error, .chat-msg-error, .chat-error {
  background: var(--hot-bg); color: var(--hot);
  border: 1px solid color-mix(in srgb, var(--hot) 35%, transparent);
  border-radius: 8px; padding: 6px 10px;
  align-self: flex-start; max-width: min(80ch, 92%); font-size: 12.5px;
}
.chat-msg.error .who { color: var(--hot); }
.chat-msg .md p { margin: 0; }
.chat-msg .md > p + p { margin-top: .45em; }

/* Строка инструмента («financier: запрос к базе»). Работа агентов должна быть
   видна — но это подстрочник к ответу, а не сам ответ, поэтому мелко и
   приглушённо. Маркер рисуется здесь, имя агента красит клиент тегом <b>. */
.tool-line, .chat-system {
  align-self: flex-start; max-width: 100%;
  font: 11.5px var(--mono); color: var(--muted);
  padding: 1px 0 1px 14px; position: relative; overflow-wrap: anywhere;
}
.tool-line::before { content: "▸"; position: absolute; left: 2px; opacity: .6; }
.tool-line b { color: var(--accent); font-weight: 600; }
.tool-dot { color: var(--accent); opacity: .7; }
.chat-system { font-style: italic; }
.chat-system::before { content: none; }

/* Поле ввода. Два имени — .composer и .chat-form — одно поведение. */
.composer, .chat-form {
  flex: 0 0 auto;
  border-top: 1px solid var(--line); background: var(--card);
  padding: 9px 16px;
  display: flex; gap: 9px; align-items: flex-end;
}
.composer textarea, .chat-input {
  flex: 1 1 auto; resize: none;
  min-height: 40px; max-height: 40vh;
  font: 14px/1.4 var(--ui); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 10px;
}
.composer textarea:focus, .chat-input:focus { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.composer .side { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.composer-hint {
  flex: 0 0 auto; background: var(--card);
  padding: 0 16px 9px; font-size: 11px; color: var(--muted);
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
}

/* ═══════════════════════ Обрыв связи ═══════════════════════
 *
 * Самый вероятный способ показать ложь — открытое окно при мёртвом сервере.
 * Поэтому обрыв не подписывается мелочью внизу, а гасит весь экран: приглушение
 * и обесцвечивание читаются раньше, чем текст баннера. Цифры при этом остаются
 * читаемыми — их не прячут, их помечают.
 *
 * Класс ставит КЛИЕНТ, и оба варианта учтены: поколение I вешает `stale` на
 * body, поколение II — `is-offline` на <html>. Баннер под приглушение не
 * попадает намеренно: гаснуть должно то, чему больше нельзя верить, а сообщение
 * об этом обязано остаться в полную силу.
 */

.banner-offline {
  position: relative; z-index: 50;
  display: flex; align-items: center; gap: 12px; justify-content: center;
  padding: 7px 14px;
  background: var(--hot-bg); color: var(--hot);
  border-bottom: 1px solid color-mix(in srgb, var(--hot) 45%, transparent);
  font-size: 12.5px; font-weight: 600;
}
.banner-offline .btn { border-color: currentColor; color: inherit; background: transparent; }
.banner-offline .btn:hover { background: color-mix(in srgb, var(--hot) 15%, transparent); }

body.stale > .nav, body.stale > .view, body.stale > .foot, body.stale > .shell,
html.is-offline .nav, html.is-offline .view, html.is-offline .foot, html.is-offline .shell {
  opacity: .55;
  filter: saturate(.2);
  transition: opacity .2s ease, filter .2s ease;
}
/* Штампы при обрыве не имеют права выглядеть свежими. */
body.stale .stamp, html.is-offline .stamp, .stamp-stale {
  color: var(--hot);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--hot) 65%, transparent);
}
.banner-offline .stamp { text-decoration: none; color: inherit; }

/* ═══════════════════════ Кнопки и поля ═══════════════════════ */

.btn {
  font: 13px var(--ui); color: var(--ink);
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 4px 11px; cursor: pointer; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
}
.btn:hover { background: var(--chip); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: default; transform: none; }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--chip); color: var(--ink); }
.btn.accent, .btn.primary {
  border-color: var(--accent); color: var(--accent); font-weight: 600;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.btn.accent:hover, .btn.primary:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.btn.danger { border-color: color-mix(in srgb, var(--hot) 45%, transparent); color: var(--hot); }

/* Сводка недели — спека 042: одна кнопка на внешний артефакт, без своей витрины. */
.brief-box { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 4px 2px; }
.brief-open { font-size: 14px; padding: 9px 16px; }
.btn.sm, .btn.tiny { font-size: 11.5px; padding: 2px 8px; border-radius: 6px; }
.btn-row { display: flex; gap: 7px; align-items: baseline; flex-wrap: wrap; }

/* Пульт — спека 055: задача с видимым исполнителем, три кнопки максимум. */
.pult-box { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.pult-input {
  width: 100%; max-width: 78ch; display: block;
  font: 13px/1.45 var(--ui); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 9px; resize: vertical;
}
.pult-input:focus { outline: none; border-color: var(--accent); }
.pult-buttons { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pult-quota { font-size: 12px; }
.pult-err { margin: 0; }
.pult-row { align-items: baseline; }
.pult-row.state-warn { background: color-mix(in srgb, var(--warn-bg) 40%, transparent); }
.cell-time { font: 12px var(--mono); color: var(--muted); white-space: nowrap; min-width: 5ch; }
.cell-out { font-size: 12.5px; min-width: 0; overflow-wrap: anywhere; }

input[type="text"], input[type="search"], textarea, select {
  font: 14px var(--ui); color: var(--ink);
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 6px 9px;
}
input[type="checkbox"] { accent-color: var(--accent); }

/* Крутилка: единственная анимация в окне, и та несёт смысл — «процесс идёт».
   При prefers-reduced-motion она замедляется, а не останавливается: замершая
   крутилка читается как «зависло», то есть врёт о состоянии. */
.spinner {
  display: inline-block; width: 12px; height: 12px; vertical-align: -2px;
  border: 2px solid var(--line); border-top-color: var(--accent);
  border-right-color: transparent;
  border-radius: 50%; animation: sirius-spin .7s linear infinite;
}
@keyframes sirius-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2.4s; }
  * { transition-duration: .01ms !important; }
}

/* ═══════════════════════ Мелочи ═══════════════════════ */

.mut, .muted { color: var(--muted); }
.hot { color: var(--hot); }
.warn-c { color: var(--warn); }
.ok-c { color: var(--ok); }
.nowrap { white-space: nowrap; }

/* Длинный текст под кат в две строки; клик снимает класс — это делает клиент,
   здесь только вид. */
.clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }

/* ═══════════════════════ Узкое окно ═══════════════════════ */

/* Полсотни сантиметров рядом с терминалом. Колонка навигации превращается в
   ленту сверху — прятать её в бургер нельзя, это лишний клик на каждое
   переключение, ради которого окно и открыто. */
@media (max-width: 920px) {
  body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto minmax(0, 1fr) auto; }
  .banner-offline { grid-column: 1; grid-row: 1; }
  body > .nav  { grid-column: 1; grid-row: 2; }
  body > .view { grid-column: 1; grid-row: 3; }
  .shell { grid-column: 1; grid-row: 2 / 4; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .foot { grid-column: 1; grid-row: 4; }
  .nav {
    flex-direction: row; align-items: center; gap: 4px;
    border-right: none; border-bottom: 1px solid var(--line);
    padding: 7px 10px;
    overflow-x: auto; overflow-y: hidden;
  }
  .brand { border-bottom: none; margin-bottom: 0; padding: 0 10px 0 2px; flex: none; }
  .brand .sub, .brand-sub, .nav-group, .nav-spacer { display: none; }
  .navlist { flex-direction: row; gap: 3px; }
  .nav-item, .navlink { white-space: nowrap; padding: 5px 9px; flex: none; }
  .nav-foot { margin-top: 0; padding-top: 0; border-top: none; flex-wrap: nowrap; }
  .view { padding: 12px; }
}

@media (max-width: 760px) {
  .burn-row, .health-row, .debt-row, .feed-row { grid-template-columns: minmax(0, 1fr); }
  .debt-aux { justify-self: start; }
  .cards, .burn-cards, div.grid, div.grid.tight { grid-template-columns: minmax(0, 1fr); }
  .foot .hint { display: none; }
}

/* ═══════════════════════ Подтверждение необратимого ═══════════════════════ */

/* Карточка стоит в ленте чата, а не всплывает поверх: вопрос обязан быть там
   же, где течёт ответ. Всплывающее окно ищут глазами по экрану, а здесь оно
   приходит по ходу разговора — как реплика, которой оно и является.
   Цвет тревожный, но не красный: это не ошибка, это остановка перед дверью. */
.confirm-card {
  border: 1px solid color-mix(in srgb, var(--warn, var(--accent)) 55%, var(--line));
  background: color-mix(in srgb, var(--warn, var(--accent)) 9%, var(--card));
  border-radius: 12px;
  padding: 12px 14px;
  margin: 8px 0 8px 0;
  max-width: 760px;
}
.confirm-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 13.5px; margin-bottom: 6px;
}
.confirm-mark { font-size: 15px; }
.confirm-tool {
  font: 11px var(--mono); color: var(--muted);
  border: 1px solid var(--line); border-radius: 20px; padding: 1px 8px;
}
.confirm-reason { font-size: 13px; color: var(--ink); margin: 0 0 8px; }
.confirm-detail {
  font: 11.5px/1.45 var(--mono); color: var(--muted);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border-radius: 8px; padding: 8px 10px; margin: 0 0 10px;
  white-space: pre-wrap; word-break: break-word; max-height: 180px; overflow: auto;
}
.confirm-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.confirm-status { font-size: 12px; color: var(--muted); }
/* Отвеченная карточка гаснет, но не исчезает: что именно разрешили сегодня —
   часть разговора, а не служебный шум. */
.confirm-yes, .confirm-no { opacity: .72; }
.confirm-no { border-style: dashed; }

/* ═══════════════════════ Лента работы ═══════════════════════ */

/* Что Сириус делает прямо сейчас. Свёрнутая группа вместо двух десятков
   сообщений вперемешку с ответом: «сейчас» должно быть в одном месте, иначе
   в простыне не видно ни работы, ни результата. */
.work {
  border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--ink) 3%, var(--card));
  margin: 6px 0; max-width: 760px; overflow: hidden;
}
.work-head {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: 0; cursor: pointer; text-align: left;
  padding: 7px 11px; color: var(--muted); font: 12.5px var(--ui);
}
.work-head:hover { background: var(--chip); color: var(--ink); }
.work-mark { font-size: 10px; transition: transform .15s ease; display: inline-block; }
.work.open .work-mark { transform: rotate(90deg); }
.work-title { font-variant-numeric: tabular-nums; }
.work-list { display: none; border-top: 1px solid var(--line2); }
.work.open .work-list { display: block; }

.work-row { border-bottom: 1px solid var(--line2); }
.work-row:last-child { border-bottom: 0; }
.work-row-head {
  display: grid; grid-template-columns: 16px auto minmax(0, 1fr); gap: 8px;
  align-items: baseline; width: 100%;
  background: none; border: 0; cursor: pointer; text-align: left;
  padding: 6px 11px; color: var(--ink); font: 12.5px var(--ui);
}
.work-row-head:hover { background: var(--chip); }
.work-state { font-size: 11px; text-align: center; }
.work-row.running .work-state { color: var(--warn); animation: work-pulse 1.1s ease-in-out infinite; }
.work-row.ok  .work-state { color: var(--ok); }
.work-row.bad .work-state { color: var(--hot); }
@keyframes work-pulse { 50% { opacity: .25; } }
.work-tool { font: 600 11.5px var(--mono); color: var(--accent); white-space: nowrap; }
.work-detail {
  font: 11.5px var(--mono); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Вывод терминала. Показывается по завершении команды — построчного stdout
   работающего процесса CLI не отдаёт, и делать вид, что отдаёт, нельзя. */
.work-out { display: none; }
.work-row.open .work-out {
  display: block;
  font: 11.5px/1.5 var(--mono); color: var(--muted);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  margin: 0; padding: 8px 11px 10px 35px;
  white-space: pre-wrap; word-break: break-word;
  max-height: 320px; overflow: auto;
}
.work-row.bad .work-out { color: var(--hot); }

/* ═══════════════════ Правка по осмотру 12.08: плотность и ритм ═══════════════════
 *
 * Никита посмотрел готовое окно и сказал: «большинство окон неинформативно,
 * убери то, чего нет». Правки ниже — про то же самое со стороны оформления:
 * данные были, но их было не видно за пустыми колонками и рваными строками.
 */

/* Даты и короткие числовые ячейки не переносятся. «10.08.202 / 6» в колонке
   «сверено» — не экономия места, а нечитаемая дата: год уехал на вторую
   строку и перестал быть годом. */
.grid td .num, .grid td.num { white-space: nowrap; }
.capacity-grid td:nth-child(2),
.capacity-grid td:last-child,
.money-grid td:last-child { white-space: nowrap; }

/* Подпись выброшенной колонки: «состояние: открыто» вместо тридцати шести
   одинаковых ячеек. Читается как заголовок таблицы, а не как её содержимое. */
.chips-same { margin: 0 0 6px; }
.chips-same .chip {
  background: transparent; border-style: dashed; color: var(--muted);
  font-size: 11px;
}

/* Сноска про поля, пустые во всех строках. Мелкая и серая: это факт о данных,
   а не предупреждение — видеть надо, спотыкаться не надо. */
.note-dropped { font-size: 11.5px; opacity: .75; margin-top: 6px; }

/* Второй уровень заголовка внутри раздела: «С условиями договора» под
   «Ёмкости». Раньше все подзаголовки были одного веса, и структура раздела
   читалась только по вертикальным промежуткам. */
.sub-h-min {
  font-size: 11px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--muted); font-weight: 600;
  margin: 14px 0 6px;
}

/* Ритм разделов. Панель — это несколько смысловых блоков подряд, и глазу
   нужен воздух между ними, иначе таблица сливается со следующим заголовком. */
.sub-h { margin-top: 22px; }
.sub-h:first-child { margin-top: 0; }
.table-wrap + .sub-h, .rows + .sub-h, .cards + .sub-h { margin-top: 26px; }

/* Строки списков (здоровье, лента): выравнивание по колонкам, а не по потоку.
   Прежде ячейки ехали по ширине текста, и одинаковые по смыслу вещи стояли
   на разной высоте в соседних строках — глаз не мог их сравнить. */
.health-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 190px auto;
  gap: 10px; align-items: baseline;
  padding: 7px 10px;
}
.health-row .cell-when { text-align: right; white-space: nowrap; }
.health-row .cell-tags { justify-content: flex-end; }
@media (max-width: 900px) {
  .health-row { grid-template-columns: 1fr; gap: 3px; }
  .health-row .cell-when, .health-row .cell-tags { text-align: left; justify-content: flex-start; }
}

/* Ссылка на клинреку — подсказкой, а не полстрокой пути, обрезанного на
   середине. Обрезанный путь не читается и занимает место как читаемый. */
.src-chip { cursor: help; border-style: dotted; }

/* Плашки строки здоровья не переносятся: «клинрека», уехавшая на вторую
   строку, растягивает строку вдвое ради одного слова, и список перестаёт
   читаться единым столбцом. */
.health-row .cell-tags { flex-wrap: nowrap; white-space: nowrap; }
@media (max-width: 1100px) {
  .health-row { grid-template-columns: minmax(0, 1fr) auto; }
  .health-row .cell-tags { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Числовая колонка целиком: заголовок и все ячейки. Выравнивание по правому
   краю — не про красоту: разряды встают друг под друга, и порядок величины
   виден без чтения цифр. */
.grid th.col-num, .grid td.col-num {
  text-align: right; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Строка долга: название · состояние · источник. Колонки, а не поток —
   тридцать четыре строки подряд обязаны читаться столбцами. */
.debt-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 150px auto;
  gap: 10px; align-items: baseline; padding: 5px 10px;
}
.debt-row .cell-detail { justify-self: start; }
.debt-row .src { font-size: 10.5px; opacity: .7; white-space: nowrap; }
@media (max-width: 900px) { .debt-row { grid-template-columns: 1fr; gap: 2px; } }

/* Счётчик повторов: один долг, записанный в базе четырежды. Число вместо
   четырёх одинаковых строк — то же знание, вчетверо меньше места. */
.chip.dup {
  margin-left: 6px; font-size: 10px; padding: 0 5px;
  background: var(--chip); color: var(--muted); border-color: var(--line);
}

/* Строка невыполненного пункта роадмапа: метка · суть · где записан. */
.rm-row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 10px; align-items: baseline; padding: 6px 10px;
}
.rm-row .cell-when { white-space: nowrap; font-size: 11.5px; }
.rm-row .prio { justify-self: start; }
.rm-row.prio-P1 { border-left: 2px solid var(--hot); }
.rm-row.prio-P2 { border-left: 2px solid var(--warn); }
.rm-row.prio-P3 { border-left: 2px solid var(--line); }
@media (max-width: 900px) {
  .rm-row { grid-template-columns: 34px minmax(0, 1fr); }
  .rm-row .cell-when { grid-column: 2; }
}

/* Полосы резидентства. Цвет отмечает ПЕРЕСЕЧЕНИЕ порога, а не оценку: что
   значит пересечение — хорошо или плохо, — зависит от нормы, а направления
   порога в данных нет. Зелёный и красный здесь врали бы уверенностью. */
.bar-fill.level-under { background: var(--accent); opacity: .55; }
.bar-fill.level-near  { background: var(--warn); }
.bar-fill.level-over  { background: var(--hot); }
.travel-row.level-over { border-left-color: var(--hot); }
.travel-row.level-near { border-left-color: var(--warn); }
.travel-row.level-under { border-left-color: var(--line); }
.travel-sub .over { color: var(--hot); font-weight: 600; }
/* Штриховка неподтверждённых лежит ВНУТРИ набранного, поверх заливки. */
.bar-unc { position: absolute; left: 0; top: 0; bottom: 0; }
.bar { position: relative; }

/* Диапазон повторяющегося долга: «с 15.09.2025 по 15.06.2026». */
.burn-range { font: 10.5px var(--mono); margin-top: 2px; }

/* Подпись перед разбивкой: чья это разбивка. Без неё строка чипов стояла
   вплотную под счётчиками горящего и читалась как их расшифровка. */
.chips-cap { font-size: 10.5px; color: var(--muted); margin-right: 2px; }

/* Строка яруса без даты: две колонки схлопываются, заголовку достаётся место. */
.burn-row { align-items: baseline; }

/* ═══════════════════ Крупное число и структура ═══════════════════
 *
 * Просьба Никиты: «общая сумма, при нажатии разбивается и показывает, где что
 * хранится». Отсюда форма: сверху ответ одной строкой, под кликом — состав.
 *
 * Оформление держится того же вкуса, что в принятых им страницах
 * (architecture.html, отчёт по рукаву 2.3): тёплая приглушённая палитра, тонкие
 * линии вместо рамок, моноширинные цифры, мелкая подпись-основание под числом.
 * Ничего яркого: окно висит открытым весь день, и то, что кричит, к вечеру
 * начинают не замечать.
 */
.big {
  border: 1px solid var(--line);
  border-radius: 14px;
  background:
    radial-gradient(120% 140% at 0% 0%,
      color-mix(in srgb, var(--accent) 7%, transparent) 0%, transparent 60%),
    var(--card);
  margin: 0 0 16px;
  overflow: hidden;
}
.big-head {
  display: block; width: 100%; text-align: left; position: relative;
  background: none; border: 0; cursor: pointer;
  padding: 16px 44px 15px 18px; color: var(--ink);
}
.big-head:hover { background: color-mix(in srgb, var(--ink) 3%, transparent); }

/* Число — единственное, что здесь имеет право быть крупным. Моноширинное и с
   табличными цифрами: разряды встают столбиком, а взгляд ловит порядок
   величины раньше, чем прочитает цифры. */
.big-num {
  font: 600 34px/1.05 var(--mono);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
/* Три валюты рядом, одна и та же величина в трёх пересчётах — не главная и
   две мелких сноски, а три равных числа. Шрифт мельче одиночного `.big-num`
   ровно настолько, чтобы рубль, доллар и тенге поместились в один ряд. */
.big-num-multi { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 40px; }
.big-num-part {
  font: 600 26px/1.15 var(--mono);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.big-cap { margin-top: 5px; font-size: 12.5px; color: var(--muted); }
/* Основание числа. Мельче подписи и в одну степень серее: читать обязательно,
   но не при каждом взгляде. */
.big-note {
  margin-top: 7px; font-size: 11px; line-height: 1.45;
  color: var(--muted); opacity: .8; max-width: 70ch;
}
.big-mark {
  position: absolute; right: 16px; top: 20px;
  font-size: 11px; color: var(--muted);
  transition: transform .16s ease;
}
.big.open .big-mark { color: var(--accent); }
.big-body { display: none; padding: 0 18px 16px; }
.big.open .big-body { display: block; }

/* Полоса состава: доли одним взглядом. Оттенки одного тёплого ряда, а не
   радуга — это структура одного и того же, а не разные сущности. */
.share {
  display: flex; height: 10px; border-radius: 6px; overflow: hidden;
  margin: 4px 0 14px; background: var(--chip);
}
.share-part { display: block; position: relative; min-width: 2px; transition: filter .15s ease; }
.share-part:hover { filter: brightness(1.25); }
.share-0 { background: color-mix(in srgb, var(--accent) 88%, var(--ink)); }
.share-1 { background: color-mix(in srgb, var(--accent) 62%, transparent); }
.share-2 { background: color-mix(in srgb, var(--ok) 55%, transparent); }
.share-3 { background: color-mix(in srgb, var(--sonnet) 50%, transparent); }
.share-4 { background: color-mix(in srgb, var(--warn) 55%, transparent); }
.share-5 { background: color-mix(in srgb, var(--muted) 45%, transparent); }
.share-label { position: absolute; left: -9999px; }

/* ═══════════════════ Общая отделка ═══════════════════ */

/* Шапка панели: имя крупнее, источник и штамп — служебной строкой. Раньше всё
   стояло в один вес, и заголовок терялся среди технических подписей. */
.panel-title { font-size: 17px; letter-spacing: -.01em; font-weight: 650; }
.panel-head .src {
  font-size: 10.5px; letter-spacing: .02em;
  background: var(--chip); border: 1px solid var(--line);
  padding: 1px 7px; border-radius: 20px;
}

/* Волосяные линии вместо рамок: таблица на тридцать строк с полноценной
   границей у каждой ячейки превращается в частокол. */
.grid td { border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.grid tbody tr:hover td { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.grid th {
  font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
  border-bottom: 1px solid var(--line);
}

/* Карточки и свёртки — мягкая тень вместо жирной рамки. Глубина в один пиксель
   читается как слой, а не как коробка. */
.card, .fold, .work, .confirm-card {
  box-shadow: 0 1px 2px color-mix(in srgb, var(--ink) 5%, transparent);
}

/* Наведение и фокус: заметно, но без прыжков. Движение в боковом зрении — это
   налог, который платится каждым взглядом на экран. */
.fold-head, .navlink, .btn { transition: background .14s ease, color .14s ease; }

/* Свёртка «оформляется» — сделка в процессе: не своё и не чужое. Пунктир
   вместо сплошной рамки читается как «ещё не закреплено». */
.fold.pending { border-style: dashed; border-color: color-mix(in srgb, var(--warn) 50%, var(--line)); }

/* Мелкая служебная таблица внутри раскрытия крупного числа. */
.src-grid { font-size: 12.5px; }
.src-grid td, .src-grid th { padding: 4px 9px; }

/* ═══════════════════ Стол: тикеты и нити (спека 028) ═══════════════════
 *
 * Единственное место, где окно пишет. Форма — переписка, а не форма ввода:
 * это и есть разговор, просто с адресом и состоянием.
 */
.ticket-body { font-size: 13px; margin: 0 0 8px; color: var(--ink); white-space: pre-wrap; }
.thread { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.msg {
  border-left: 2px solid var(--line); padding: 6px 0 6px 10px;
  font-size: 13px; max-width: 78ch;
}
.msg-nikita { border-left-color: var(--accent); }
.msg-sirius { border-left-color: color-mix(in srgb, var(--sonnet) 60%, var(--line)); }
.msg-head { font-size: 11.5px; margin-bottom: 3px; }
.msg-body { white-space: pre-wrap; }
/* Место, где ответ ещё пишется. Пунктир и пульс — чтобы отличалось от
   написанного с одного взгляда, без чтения. */
.msg.pending { border-left-style: dashed; border-left-color: var(--warn); }
.msg.pending .msg-head b { animation: work-pulse 1.4s ease-in-out infinite; }
/* Очередь работ: тема · ярлыки · агент · запуск. Агент моноширинным — это
   имя из системы, а не слово из предложения. */
.work-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; gap: 2px 12px; align-items: baseline; }
.work-row.hot-row .cell-title { font-weight: 600; }
.work-agent { font: 11.5px var(--mono); color: var(--accent); white-space: nowrap; }
@media (max-width: 900px) { .work-row { grid-template-columns: minmax(0, 1fr); } }

/* Чем Сириус занят сейчас (спека 031). Стоит первым в разделе и потому обязан
   читаться с одного взгляда, не требуя чтения: точка слева говорит «работает
   или нет» цветом, а строка — чем именно. Пульс только у работающей точки:
   движение в боковом зрении — налог, и платить его за «свободен» незачем. */
.now-box { display: flex; align-items: baseline; gap: 10px; margin: 0 0 10px;
           padding: 9px 12px; background: var(--chip); border-radius: var(--radius);
           border: 1px solid var(--line2); }
.now-label { font: 11px var(--mono); color: var(--muted); text-transform: uppercase;
             letter-spacing: .04em; flex: none; }
.now-line { min-width: 0; display: flex; align-items: baseline; gap: 6px;
            flex-wrap: wrap; }
.now-stack { min-width: 0; display: grid; gap: 3px; }
/* Наблюдаемые признаки — мельче и глуше сказанного: это не заявление, а то,
   чем заявление проверяется. Разный вес шрифта здесь несёт смысл, а не вкус. */
.now-facts { display: flex; gap: 12px; flex-wrap: wrap; font-size: 11.5px;
             color: var(--muted); }
.now-facts .ok-mark { color: var(--ok); }
.now-facts .warn-mark { color: var(--warn); }
.now-dot { flex: none; font-size: 10px; line-height: 1; }
.now-dot.busy { color: var(--ok); animation: work-pulse 1.4s ease-in-out infinite; }
.now-dot.idle { color: var(--muted); }

/* Пачка ответов: сколько набрано и что с отправленным. */
.batch-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             margin: 0 0 12px; padding: 9px 12px; border-radius: var(--radius);
             background: var(--warn-bg); border: 1px solid var(--line2); }
.batch-wait { font-size: 13px; color: var(--muted); }
.batch-wait.broke { color: var(--hot); font-weight: 600; }

/* Знак банка (тикет #12). Своя монограмма, не логотип: окно не ходит наружу, а
   класть копию чужого товарного знака в репозиторий незачем. Цвет — для
   различения боковым зрением, размер маленький: это метка строки, а не герой. */
.bank-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none; border-radius: 6px;
  background: var(--mark, var(--chip)); color: #fff;
  font: 600 9.5px/1 var(--ui); letter-spacing: .02em;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .12);
}
/* Неопознанный банк глухой, но ВИДИМЫЙ: пустое место среди знаков читалось бы
   как поломка, а не как «метка не задана». */
.bank-mark.unknown { background: transparent; color: var(--muted);
                     box-shadow: inset 0 0 0 1px var(--line); }
.with-mark { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }

/* ═══════════════════════ Календарь бизнеса ═══════════════════════
 *
 * Просьба Никиты 13.08: «в виде календаря, таблицей по месяцам — какие месяцы
 * закрыты, что ожидается, что уже уплачено; отмечай цветом».
 *
 * Цвет здесь несёт СМЫСЛ, а не настроение, поэтому он один и тот же в полосе и
 * в карточках: зелёное — закрыто фактом оплаты, красное — просрочено, жёлтое —
 * срок ещё не вышел, серое — обязательств нет. Четвёртое состояние отдельным
 * тоном намеренно: «нечего платить» и «не оплачено» обязаны отличаться с
 * одного взгляда, иначе спокойный месяц читается как тревожный.
 *
 * Цвет продублирован СЛОВОМ в каждой ячейке. Витрина, где состояние читается
 * только по оттенку, слепа для тех, кто различает цвета иначе, и врёт на
 * чёрно-белой печати. */
.cal-ok   { border-color: color-mix(in srgb, var(--ok) 42%, var(--line));
            background: color-mix(in srgb, var(--ok) 7%, var(--card)); }
.cal-warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line));
            background: color-mix(in srgb, var(--warn) 8%, var(--card)); }
.cal-hot  { border-color: color-mix(in srgb, var(--hot) 50%, var(--line));
            background: color-mix(in srgb, var(--hot) 9%, var(--card)); }
.cal-mut  { opacity: .58; }

/* ═══════════════════════ Календарь года по дням ═══════════════════════
 *
 * Двенадцать месяцев сеткой, в каждом — настоящие числа с понедельника.
 * Пометка стоит на ЧИСЛЕ, потому что вопрос к календарю такой: что меня ждёт
 * этого числа. День с несколькими делами несёт несколько точек, а не «главный»
 * цвет: решать за человека, что из четырёх дел важнее, витрина не вправе. */
/* Ровно ЧЕТЫРЕ месяца в ряд — то есть три ряда на год, как просил Никита
 * 13.08. Не `auto-fill`: тот подбирает число колонок под ширину и на широком
 * экране ставил их пять-шесть, ломая привычное «квартал в строке». Здесь сетка
 * задана явно и ужимается ступенями, а не плавно.
 *
 * Размеры подняты по прямой причине: «у меня не очень зрение». Числа стали
 * 14 px вместо 10,5, точки-пометки крупнее, названия месяцев больше. Клетка
 * держит минимум 34 px — это ещё и палец на телефоне, а не только глаз. */
.year-grid { display: grid; gap: 14px; margin: 12px 0;
             grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1180px) { .year-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .year-grid { grid-template-columns: minmax(0, 1fr); } }
.month-box { border: 1px solid var(--line); border-radius: var(--radius);
             padding: 11px 12px 12px; background: var(--card); }
.month-now { box-shadow: inset 0 0 0 2px var(--accent); }
.month-head { display: flex; align-items: baseline; justify-content: space-between;
              gap: 8px; margin-bottom: 8px; }
.month-head b { font-size: 15.5px; text-transform: capitalize; }
.month-state { font-size: 11px; color: var(--muted); letter-spacing: .03em; }
.month-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dow { font-size: 10.5px; color: var(--muted); text-align: center; padding-bottom: 4px;
       letter-spacing: .04em; }
.day { position: relative; aspect-ratio: 1; min-height: 34px; border: none;
       background: transparent; color: var(--ink); font: inherit; font-size: 14px;
       border-radius: 7px; display: flex; flex-direction: column; align-items: center;
       justify-content: center; gap: 2px; cursor: default; padding: 0; }
.day.empty { visibility: hidden; }
.day.has { cursor: pointer; }
.day.has:hover { background: var(--chip); }
.day-n { line-height: 1; font-variant-numeric: tabular-nums; }
/* Сегодня видно даже когда на нём ничего нет: «где я» — первый вопрос. */
.day.today { box-shadow: inset 0 0 0 2px var(--accent); font-weight: 700; }
.day.is-open { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.dots { display: flex; gap: 3px; height: 6px; align-items: center; }
.dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; }
.dot-overdue { background: var(--hot); }
.dot-due     { background: var(--warn); }
.dot-paid    { background: var(--ok); }
.dot-in      { background: var(--sonnet); }
.dot-want    { background: var(--muted); }
.note .dot { margin: 0 2px; }
/* Раскрытый день — под сеткой, а не в ней: подробности дня не должны рвать
 * сетку месяцев, по которой ведут взглядом. */
.day-detail { margin-top: 12px; padding: 10px 12px; border-radius: var(--radius);
              border: 1px solid var(--line); background: var(--card); }
.day-detail-head { margin-bottom: 6px; font-size: 12.5px; }
.diary-what .muted { font-weight: 400; }

/* Ежедневник: плитка месяца снаружи, подробности внутри. Лицо плитки — две
 * строки (месяц и состояние словом) плюс чипсы с суммами; всё остальное
 * появляется по клику, потому что вопрос «что с августом» и вопрос «что именно
 * в августе» задают в разные моменты. */
.diary-face { display: grid; gap: 2px; min-width: 0; }
.diary-face b { font-size: 13px; text-transform: capitalize; letter-spacing: 0; }
.diary-state { font-size: 10px; color: var(--muted); letter-spacing: .03em;
               text-transform: none; }
.diary-chips { margin-top: 2px; }
.diary-chips .chip { font-size: 10px; }
.fold-grid.diary > .fold.folded > .fold-head { text-transform: none; padding: 9px 10px; }
.diary-country { margin: 12px 0 5px; font-size: 11px; letter-spacing: .05em;
                 text-transform: uppercase; color: var(--muted); }
.diary-country:first-child { margin-top: 2px; }
/* «Что необходимо» — единственная часть месяца, говорящая не о прошлом.
 * Поэтому она отбита рамкой: её читают, когда на остальное уже посмотрели. */
.diary-todo { margin-top: 12px; padding: 9px 11px; border-radius: 9px;
              border: 1px solid color-mix(in srgb, var(--warn) 40%, var(--line));
              background: color-mix(in srgb, var(--warn) 7%, transparent); }
.diary-todo b { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.diary-todo ul { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 3px; }
.diary-todo li { font-size: 12px; }

/* Расход списком: строка «что — сколько», под ней «кому / срок / чем закрыт»,
 * и третьей — разбор платежа словами того, кто платил. Третья строка и есть
 * содержание: «17 233,62 ₽» одинаково выглядит и когда за ним счёт №1554, и
 * когда расчётная доля остатка. */
.diary-out { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 8px; }
.diary-line { display: grid; gap: 2px; padding-bottom: 7px;
              border-bottom: 1px solid var(--line2); }
.diary-line:last-child { border-bottom: none; padding-bottom: 0; }
.diary-line-head { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto;
                   gap: 7px; align-items: baseline; }
.diary-dot { width: 7px; height: 7px; border-radius: 50%; align-self: center; }
.diary-dot.ok   { background: var(--ok); }
.diary-dot.warn { background: var(--warn); }
.diary-dot.hot  { background: var(--hot); }
.diary-what { font-size: 12.5px; display: flex; align-items: baseline; gap: 6px;
              flex-wrap: wrap; min-width: 0; }
.diary-amount { font-size: 12.5px; font-weight: 600;
                font-variant-numeric: tabular-nums; }
.diary-line.is-paid .diary-what { opacity: .78; }
.diary-line-meta { display: flex; flex-wrap: wrap; gap: 10px; padding-left: 15px;
                   font-size: 11px; color: var(--muted); }
.diary-note { padding-left: 15px; margin-top: 3px; font-size: 11px;
              line-height: 1.45; color: var(--muted); }
.diary-note .chip { margin-right: 4px; }
/* Текущий месяц — единственное место, где рамка толще: взгляд должен находить
 * «сейчас» без чтения подписей. */
.cal-now  { box-shadow: inset 0 0 0 1px var(--accent); }
.cal-now .cal-badge { color: var(--accent); }

/* Карточки имущества: числа крупно, происхождение рядом, фото если есть.
 *
 * `auto-fill`, а НЕ `auto-fit`. Разница в одном слове и в том, как выглядит
 * окно: `auto-fit` схлопывает пустые дорожки и растягивает уцелевшие карточки
 * на всю ширину — два объекта превращались в две полосы по пол-экрана. При
 * `auto-fill` пустые дорожки остаются, и карточка держит свои ~250 px, сколько
 * бы объектов ни было. Третий и четвёртый встанут в тот же ряд, а не удвоят
 * высоту страницы. */
.asset-cards { display: grid; gap: 10px;
               grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); }
.asset-card {
  display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 11px;
  padding: 10px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card);
}
.asset-photo { width: 72px; height: 72px; border-radius: 9px; object-fit: cover;
               background: var(--chip); }
.asset-photo.none { display: flex; flex-direction: column; align-items: center;
                    justify-content: center; gap: 2px; color: var(--muted);
                    font-size: 22px; border: 1px dashed var(--line); }
.asset-photo.none small { font-size: 9.5px; letter-spacing: .02em; }
.asset-body { min-width: 0; display: grid; gap: 5px; align-content: start; }
.asset-name { font-weight: 600; font-size: 13.5px; line-height: 1.3; }
.asset-sum { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
             font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.asset-rub { font-size: 12px; font-weight: 400; color: var(--muted); }
/* Доля владения. Обведена рамкой, а не приглушена в текст: это условие
   стоящего рядом числа, и потерять его глазами дороже, чем прочитать лишний
   раз. `cursor: help` обещает подсказку — в ней цена объекта целиком. */
.asset-dolya { font-size: 11px; font-weight: 600; color: var(--muted);
               border: 1px solid var(--line); border-radius: 5px;
               padding: 0 5px; cursor: help; }
.asset-share { display: flex; align-items: center; gap: 7px; font-size: 11px;
               color: var(--muted); }
.asset-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
              font-size: 11px; color: var(--muted); }
@media (max-width: 560px) { .asset-card { grid-template-columns: 60px minmax(0, 1fr); }
                            .asset-photo { width: 60px; height: 60px; } }

/* Перенос строки витрины в стол. Приглушена до наведения: это действие
   доступное, но не то, ради которого открывают «что горит». */
.btn.to-desk { opacity: .35; transition: opacity .12s ease; }
.row:hover .btn.to-desk, .burn-card:hover .btn.to-desk,
.btn.to-desk:focus-visible, .btn.to-desk.ok { opacity: 1; }
.btn.to-desk.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, var(--line)); }

.chip.busy {
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 45%, var(--line));
  animation: work-pulse 1.4s ease-in-out infinite;
}

.thread-input {
  width: 100%; max-width: 78ch; display: block; margin-bottom: 6px;
  font: 13px/1.45 var(--ui); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 9px; resize: vertical;
}
.thread-input:focus { outline: none; border-color: var(--accent); }
.thread-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Ожидающий ответа тикет подсвечен: ради него стол и заведён. */
.fold.ticket-waiting { border-color: color-mix(in srgb, var(--hot) 45%, var(--line)); }
.fold.ticket-done .fold-title, .fold.ticket-dropped .fold-title { opacity: .6; }
.thread-states { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }

/* ── стол: чей ход, новое, переключение ─────────────────────────────── */

/* Мяч на ком. Два цвета и никаких оттенков: вопрос у читающего один —
   делать мне что-то или нет. */
.chip.ball-you {
  background: var(--hot-bg); color: var(--hot); font-weight: 650;
  border-color: color-mix(in srgb, var(--hot) 45%, transparent);
}
.chip.ball-me {
  background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.chip.ok {
  color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent);
}

/* Пришло новое, пока тебя не было. Цифра та же, новость другая. */
.badge-new {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent); border-color: var(--accent);
  animation: work-pulse 1.8s ease-in-out infinite;
}

/* Переключение состояния: выбранное — ЗАЛИВКОЙ. Рамка отличала выбранное от
   невыбранного ровно настолько, чтобы не отличать («я путаюсь», 12.08). */
.states-cap { font-size: 11.5px; align-self: center; margin-right: 2px; }
.state-btn { opacity: .6; }
.state-btn:hover { opacity: 1; }
.state-btn.on {
  opacity: 1; font-weight: 700; cursor: default;
  background: var(--accent); color: var(--bg); border-color: var(--accent);
}
.state-btn.on:hover { background: var(--accent); }

/* Поле «что решить» у кнопки «в стол»: появляется по наведению на строку —
   сорок пустых полей в списке кричали бы громче самих строк. */
.to-desk-wrap { display: inline-flex; gap: 6px; align-items: baseline; }
.to-desk-why {
  width: 0; padding: 0; border-width: 0; opacity: 0; font-size: 11.5px;
  transition: width .12s ease, opacity .12s ease;
}
.row:hover .to-desk-why, .burn-card:hover .to-desk-why, .to-desk-why:focus {
  width: 22ch; padding: 2px 7px; border-width: 1px; opacity: 1;
}

/* Выбор рода записи — по той же логике, что и поле выше: в покое его нет.
   Три кнопки, видимые всегда, превратили бы каждую строку долга в панель
   управления; всплывают они вместе с полем «что решить», то есть ровно
   тогда, когда рука уже на строке. */
.kind-pick { display: inline-flex; gap: 4px; }
.to-desk-wrap .kind-pick {
  width: 0; overflow: hidden; opacity: 0;
  transition: width .12s ease, opacity .12s ease;
}
.row:hover .to-desk-wrap .kind-pick, .burn-card:hover .to-desk-wrap .kind-pick,
.to-desk-wrap:focus-within .kind-pick { width: auto; opacity: 1; }
.kind-pick .btn.on {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* В форме «Завести тикет» ряд стоит отдельной строкой: там места хватает,
   а прятать род в форме, где всё видно, — прятать ради единообразия. */
.kind-row { align-items: baseline; gap: 8px; margin: 2px 0 6px; }

/* ── стол: причёска реплик и формы ─────────────────────────────────────
   Отличать автора одним взглядом. Раньше различал только цвет левой
   рамки в 2px — авторы читались после текста, а не до, и нить с двух
   метров выглядела как один голос. Подложка в 5–6% цвета уже даёт
   границу боковым зрением, но не забивает сам текст. */
.msg { padding: 7px 0 7px 12px; border-left-width: 3px; border-radius: 0 8px 8px 0; }
.msg-nikita { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.msg-sirius { background: color-mix(in srgb, var(--sonnet) 5%, transparent); }
.msg-head b { font-weight: 650; }
.msg-nikita > .msg-head b { color: var(--accent); }
.msg-sirius > .msg-head b { color: color-mix(in srgb, var(--sonnet) 80%, var(--ink)); }

/* Форма ответа: отбить от последней реплики пунктирной линией, а не
   пустотой. Линия говорит «здесь начинается моё», пустота — «здесь
   ничего». */
.thread > .thread-input { margin-top: 12px; }
.thread-form { margin-top: 8px; padding-top: 10px; border-top: 1px dashed var(--line2); }

/* Шапка свёрнутого тикета, ждущего ответа. К красной рамке добавлена
   тёплая подложка — список тикетов должен показывать «где мяч у меня»
   раньше, чем читается заголовок. */
.fold.ticket-waiting > .fold-head {
  background: color-mix(in srgb, var(--hot-bg) 55%, transparent);
}
.fold.ticket-waiting > .fold-head:hover {
  background: color-mix(in srgb, var(--hot-bg) 85%, transparent);
}

/* Компактная нить тикета. Правка 12.08 (тикет #3, третья): «сделай окно
   тикета меньше, чтоб видно было несколько». Нить с двумя-тремя длинными
   репликами сама по себе занимает экран; несколько раскрытых уводили карточки
   за нижний край, и приходилось «туда-сюда бегать». Ответ — ограничить высоту
   раскрытой нити и пустить скролл ВНУТРИ, а не по всей странице: список
   тикетов остаётся на виду, а нить читается там же, где раскрыта.

   Меньше отступов у шапки — та же цель: за один взгляд помещается больше
   заголовков, а не «две карточки на экран». Заливка активной вкладки и
   красная рамка ждущих ответа при этом не меняются: они и есть тот способ,
   которым Никита видит, куда смотреть. */
.fold.ticket-fold > .fold-head { padding: 4px 10px; font-size: 11px; }
.fold.ticket-fold > .fold-body {
  max-height: min(58vh, 460px);
  overflow-y: auto;
  padding: 6px 10px 8px;
  /* Собственный скроллбар: тонкий, чтобы не крал ширину у самих реплик. */
  scrollbar-width: thin;
  scrollbar-gutter: stable;
}
/* Кнопка платного разбора. Обычно приглушена — умолчание «ждёт живую сессию»
 * правильное, и подталкивать к трате незачем. Голос она подаёт только когда
 * терминала нет: тогда ожидание бессрочно, и это надо видеть. */
.thread-headless { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
                   margin-top: 7px; font-size: 11px; }
.headless-btn { opacity: .62; }
.headless-btn:hover:not(:disabled) { opacity: 1; }
.headless-btn:disabled { opacity: .35; cursor: default; }
.headless-btn.urge {
  opacity: 1; color: var(--warn); font-weight: 600;
  border-color: color-mix(in srgb, var(--warn) 45%, transparent);
  background: var(--warn-bg);
}

.fold.ticket-fold { margin: 6px 0; }
/* Пока нить свёрнута, тень внутреннего скролла не нужна — она делает шапку
   визуально «оторванной» от карточки. */
.fold.ticket-fold.folded > .fold-head { padding-top: 5px; padding-bottom: 5px; }

/* Строка с заголовком раздела и кнопками «свернуть/раскрыть всё». Кнопки —
   рядом с заголовком, а не отдельной строкой: массовое сворачивание — это
   действие ПО списку, и живёт над списком, а не в стороне от него. */
.sub-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-top: 14px; flex-wrap: wrap;
}
.sub-row > .sub-h { margin: 0; }
.sub-actions { display: inline-flex; gap: 6px; flex-wrap: wrap; }

/* ── хочу ────────────────────────────────────────────────────────────── */

.wish-card { display: flex; flex-direction: column; gap: 5px; }
.wish-head { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
.wish-title { font-weight: 600; overflow-wrap: anywhere; }
.wish-what { font-size: 13px; color: var(--ink); margin: 0; }
/* «Хочу» отличается от «идея» заливкой карточки, а не только ярлыком: список
   читают глазами по диагонали, и решённое должно выделяться без чтения. */
.wish-card.status-хочу { border-left: 2px solid var(--accent); padding-left: 10px; }

/* Строка про разбор в подвале: видна из любого раздела. Пульсирует, только
   когда идёт работа, — иначе движение в углу экрана становится фоном. */
.foot-item.warn { color: var(--warn); }
#react-note.warn::before {
  content: '●'; font-size: 8px; margin-right: 2px;
  animation: work-pulse 1.2s ease-in-out infinite;
}

/* ── Движение тикета (спека 035) ───────────────────────────────────────
   Три ряда в карточке: следующий шаг, срок, связи. Ряды, а не сетка:
   поля разной длины, и колоночная раскладка растягивала бы дату на
   полэкрана рядом с длинным шагом. */
.ticket-move {
  display: flex; flex-direction: column; gap: 6px;
  margin: 8px 0 10px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--card-2, transparent);
}
.move-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.move-row .inp {
  flex: 1 1 220px; min-width: 0;
  padding: 4px 8px; font: inherit; font-size: 13px;
  color: var(--ink); background: var(--bg);
  border: 1px solid var(--line); border-radius: 6px;
}
.move-row .inp.narrow { flex: 0 0 auto; min-width: 132px; }
.link-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 4px 2px 7px; border: 1px solid var(--line);
  border-radius: 999px; font-size: 12.5px;
}
.link-chip code { font-size: 12px; }
.link-chip .btn.tiny { padding: 0 5px; line-height: 1.4; }

/* ── задачи на оценку (вкладка «Задачи») ──────────────────────────────────
   Строка задачи шире обычной: суть должна читаться без раскрытия. Список,
   в котором надо кликать, чтобы понять, о чём пункт, оценивают не глядя. */
.tasks-bar { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; }
.tasks-bar .muted { font-size: 12.5px; }

.tasks-rows { margin-bottom: 18px; }
.task-row { display: flex; align-items: flex-start; gap: 16px; padding: 12px 10px; }
.task-main { flex: 1 1 auto; min-width: 0; }
.task-main .note { margin-top: 5px; max-width: 82ch; }
.task-verdict { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px;
                align-items: flex-end; }

/* Решённое приглушено, но НЕ спрятано: исчезновение строки после нажатия
   читалось бы как «задача удалена», а не как «решение принято». */
.task-decided { opacity: .62; }

.verdicts { display: flex; gap: 6px; }
.vbox { display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
        padding: 4px 9px; border: 1px solid var(--line); border-radius: 999px;
        font-size: 12px; white-space: nowrap; background: transparent; }
.vbox:hover { background: color-mix(in srgb, var(--chip) 70%, transparent); }
/* Квадратик рисуется сам, без `<input type=checkbox>` внутри `<label>`.
   Измерено нажатием 15.08.2026: один клик мышью по такой паре порождал ТРИ
   события — метка пересылает нажатие полю, оно возвращается и пересылается
   снова, — отметка ставилась и тут же снималась. Собранный DOM при этом был
   правильным: ломалось поведение, и увидеть это можно было только нажав. */
.vmark { width: 13px; height: 13px; flex: 0 0 auto; border-radius: 3px;
         border: 1.5px solid var(--line); background: transparent;
         display: inline-block; position: relative; }
.vbox[aria-checked="true"] .vmark { border-color: currentColor;
                                    background: currentColor; }
.vbox[aria-checked="true"] .vmark::after {
  content: '✓'; position: absolute; inset: -3px 0 0 0; color: var(--bg);
  font-size: 11px; line-height: 13px; text-align: center; font-weight: 700; }
.vbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vbox-ok   { background: var(--ok-bg);   color: var(--ok);
             border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.vbox-warn { background: var(--warn-bg); color: var(--warn);
             border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.vbox-hot  { background: var(--hot-bg);  color: var(--hot);
             border-color: color-mix(in srgb, var(--hot) 45%, transparent); }

@media (max-width: 760px) {
  .task-row { flex-direction: column; gap: 10px; }
  .task-verdict { align-items: flex-start; }
}

/* ── поездки: шкала года и карточки ───────────────────────────────────────
   Шкала — просьба Никиты 19.08.2026: «прямая график дней 365, закрашенный по
   странам где я находился, но не занимать основное место, сверху просто шкала
   потолще с закрашенными периодами».

   Отсюда все размеры. Полоса высотой 22px — это «потолще», но всё ещё строка,
   а не блок: год целиком занимает столько же места, сколько один заголовок.
   Клетки не имеют зазоров, иначе 365 щелей съедают цвет и период перестаёт
   читаться как период. Цвета стран взяты из палитры моделей (--opus, --sonnet
   и т.д.) намеренно: они уже подобраны различимыми между собой в обеих темах,
   и заводить второй набор различимых цветов значило бы подбирать заново. */
.ystrip-box { margin: 4px 0 18px; }
.ystrip-head { font-size: 13px; margin-bottom: 6px; }
.ystrip {
  display: flex; width: 100%; height: 34px;
  border: 1px solid var(--line); border-radius: 6px; overflow: hidden;
  background: var(--card);
}
.ycell { flex: 1 1 0; min-width: 0; height: 100%; display: block; }

/* Цвет клетки — опорный цвет флага страны, по одному на страну.

   Сначала здесь были сами флаги полосами (просьба Никиты 19.08.2026 «раскрась
   под цвет флага»), и на живой полосе это выглядело плохо: год в России — это триколор
   шириной в экран, где белая полоса выжигает глаз и тянет внимание сильнее,
   чем сама страна. Флаг хорош значком, а не заливкой длиной в 341 день.

   Поэтому от флага остался его опорный цвет — тот, по которому страну узнают
   (российский синий, казахстанский небесно-голубой, грузинский красный), а сам
   флажок стоит эмодзи в легенде, где ему и место. Лёгкий вертикальный отлив
   внутри клетки нужен, чтобы полоса читалась как трек, а не как плоская
   заливка; на цвет он не влияет. */
.ycell.c-RU { --flag: #2f62b0; }
.ycell.c-KZ { --flag: #16a8c8; }
.ycell.c-GE { --flag: #cf3030; }
.ycell.c-TH { --flag: #7b5ec7; }
.ycell.c-UZ { --flag: #2aa35c; }
.ycell[class*="c-"] {
  background-image: linear-gradient(to bottom,
    color-mix(in srgb, var(--flag, var(--muted)) 88%, #fff) 0%,
    var(--flag, var(--muted)) 45%,
    color-mix(in srgb, var(--flag, var(--muted)) 86%, #000) 100%);
}
.ycell.c-none { background: color-mix(in srgb, var(--muted) 22%, transparent); }
/* Планируемое — штриховкой поверх того же цвета. Именно поверх цвета, а не
   вместо: страна должна остаться узнаваемой, отличаться обязано только то,
   факт это или намерение. */
/* Планируемое — та же заливка флагом, но под диагональной сеткой. Именно
   ПОД: страна должна остаться узнаваемой, отличаться обязано только то, факт
   это или намерение. Свойство `background-image` здесь дополняет градиент
   флага, а не заменяет его, поэтому оно списком из двух слоёв. */
.ycell.is-planned { position: relative; }
.ycell.is-planned::after {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(45deg,
    rgba(20,17,15,.55) 0 3px, rgba(255,255,255,.16) 3px 6px);
}
.ycell.is-today { box-shadow: inset 0 0 0 2px var(--accent); }
.ystrip-months {
  display: grid; grid-template-columns: repeat(12, 1fr);
  font-size: 10.5px; color: var(--muted); margin-top: 3px; letter-spacing: .02em;
}
.ystrip-months span { text-align: center; }
.ystrip-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 8px; font-size: 12.5px; }
.ylg { display: inline-flex; align-items: center; gap: 5px; }
.ylg .ycell { width: 14px; height: 14px; flex: 0 0 14px; border-radius: 3px;
               border: 1px solid var(--line); }

/* Плотнее, чем обычная карточка окна (просьба Никиты 19.08.2026 — «по
   поездкам сделай карточки поменьше»). Поездок на экране всегда несколько, и
   вопрос к ним быстрый: что впереди, куплено ли, где документ. Подробности
   живут в файлах, ссылки на которые тут же, поэтому карточке незачем быть
   размером с документ. */
.trip-grid {
  display: grid; gap: 9px; margin: 6px 0 16px;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
}
.trip-card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 9px; padding: 9px 11px 10px; font-size: 12.5px;
}
/* Слева цветная кромка по состоянию: впереди — золото (это то, к чему готовятся),
   сейчас — зелень, позади и идея приглушены. Взгляд находит нужную карточку до
   того, как прочитает слово. */
.trip-card.state-ahead { border-left: 3px solid var(--accent); }
.trip-card.state-now   { border-left: 3px solid var(--ok); }
.trip-card.state-past  { border-left: 3px solid var(--line); opacity: .82; }
.trip-card.state-idea  { border-left: 3px dashed var(--muted); }
.trip-head { display: flex; align-items: center; gap: 6px; }
.trip-flag { font-size: 15px; }
.trip-name { font-size: 13.5px; }
.trip-state { margin-left: auto; }
.trip-meta { display: flex; flex-wrap: wrap; gap: 3px 9px; font-size: 12px; margin: 4px 0 6px; }
.trip-line { font-size: 12px; margin: 5px 0; }
.trip-doc { margin: 4px 0 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.trip-note { font-size: 11.5px; color: var(--muted); line-height: 1.4; margin-top: 2px; }
.trip-file {
  display: block; margin: 3px 0; padding: 5px 7px; border-radius: 6px;
  background: var(--chip); border: 1px solid var(--line); color: var(--ink);
  text-decoration: none; font-size: 12px;
}
.trip-file:hover { border-color: var(--accent); }
.trip-mats { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.chip.mat { font-size: 10.5px; padding: 1px 5px; }
a.chip.mat { text-decoration: none; }
a.chip.mat:hover { border-color: var(--accent); color: var(--ink); }
.trip-file.pdf { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }

/* Роды событий ежедневника. Событие Календаря — тем же золотом, что и акцент
   окна: это единственный род, который приходит не из баз системы, и взгляд
   должен отличать его от денег без чтения подписи. */
.dot-event { background: var(--accent); }
.dot-task  { background: var(--warn); opacity: .75; }
.diary-dot.event { background: var(--accent); }
.diary-line.is-event .diary-what { font-weight: 600; }
.ev-time { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 500; }
.ev-cal {
  font-size: 11px; padding: 0 5px; border-radius: 4px;
  background: var(--chip); border: 1px solid var(--line); color: var(--muted);
}

/* ── ежедневник: сегодня и неделя ─────────────────────────────────────────
   Восемь дней в ряд, каждый — узкая колонка. Свободный день показан словом
   «свободно», а не пустотой: пустая клетка читается как «данные не доехали»,
   и именно в ежедневнике эта разница стоит дороже всего. */
.diary-ahead { margin: 6px 0 20px; }
.ahead-grid {
  display: grid; gap: 7px;
  grid-template-columns: repeat(auto-fit, minmax(126px, 1fr));
}
.ahead-day {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 9px; padding: 7px 8px 8px; min-height: 92px;
}
.ahead-day.is-today { border-color: var(--accent); background: var(--warn-bg); }
.ahead-day.is-free { opacity: .62; }
.ahead-head { display: flex; justify-content: space-between; align-items: baseline;
              font-size: 12px; margin-bottom: 5px; gap: 6px; }
.ahead-free { font-size: 11.5px; color: var(--muted); font-style: italic; }
.ahead-list { list-style: none; margin: 0; padding: 0; font-size: 11.5px; }
.ahead-item { display: flex; gap: 4px; align-items: baseline; margin: 3px 0; line-height: 1.35; }
.ahead-item .dot { flex: 0 0 auto; margin-top: 4px; }
.ahead-more { font-size: 11px; margin-top: 3px; }
.ahead-overdue {
  border: 1px solid color-mix(in srgb, var(--hot) 45%, var(--line));
  background: var(--hot-bg); border-radius: 9px; padding: 8px 11px; margin-bottom: 9px;
}
.ahead-overdue .diary-out { margin-top: 5px; }
/* День, который ещё не наступил. Не серый «нет данных», а прозрачный: там
   нечего знать, а не что-то потеряно. Разница видна рядом с настоящими
   пробелами прошлого, которые остаются серыми. */
.ycell.c-ahead { background: color-mix(in srgb, var(--line) 45%, transparent); }

/* Итог на сегодня — одна строка над шкалой. Заменила собой снесённый блок
   резидентства (решение Никиты 19.08.2026): вердикты, пороги и полосы ушли,
   счёт прожитых дней остался. Строка, а не карточка: это подпись к шкале,
   а не самостоятельный раздел. */
.today-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  font-size: 13px; margin: 2px 0 10px;
}
.today-when { font-weight: 600; }
.today-country { display: inline-flex; align-items: center; gap: 5px; }
.today-country .ycell { width: 12px; height: 12px; flex: 0 0 12px; border-radius: 3px;
                        border: 1px solid var(--line); }
.today-country .num { font-size: 15px; }
/* Прошлые поездки — плотнее и приглушённее: их читают выборочно, а не подряд. */
.trip-grid.past { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
.trip-grid.past .trip-card { opacity: .75; }
.trip-grid.past .trip-card:hover { opacity: 1; }

/* Кнопки закрытого вопроса (миграция 102). Стоят над полем свободного ответа,
   а не вместо него: вопрос, не позволяющий ответить иначе, вынуждает выбрать
   неверное из трёх, когда верное — четвёртое. */
.q-options { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
             margin: 10px 0 4px; }
.q-opt { font: inherit; padding: 7px 14px; border-radius: 8px; cursor: pointer;
         border: 1px solid var(--line, #d8d8d8); background: transparent;
         color: inherit; }
.q-opt:hover:not([disabled]) { border-color: currentColor; }
.q-opt.picked { background: var(--fg, #222); color: var(--bg, #fff);
                border-color: transparent; }
.q-opt[disabled] { opacity: .55; cursor: default; }
