/* Компоненты и экраны — docs/DESIGN_CODE.md, разделы 3–8. Один файл читается
   по разделам (CLAUDE.md), как и сам дизайн-код. */

/* ── 0. Сброс и база ─────────────────────────────────────────────────── */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-family);
  font-size: var(--fs-body);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}
button {
  font-family: inherit;
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  color: inherit;
}
/* `hidden` прячет элемент правилом браузера `[hidden] { display: none }`, а
   любое авторское правило с `display` его перебивает — специфичность тут ни
   при чём, авторский стиль всегда сильнее браузерного. Поймались на этом
   28.08.2026: `.offline-banner { display: flex }` держал полосу «немає
   зв'язку» на экране всегда, хотя JS исправно снимал атрибут. `!important`
   тут не украшение, а смысл правила: оно обязано победить любой `display`,
   объявленный ниже по файлу. */
[hidden] { display: none !important; }

/* Все числа — tabular, минус «−», а не дефис (§4). */
.num { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}

/* ── 1. Каркас экрана ────────────────────────────────────────────────── */

/* Высота — только viewportStableHeight (js/telegram.js пишет --vh),
   100vh здесь нет нигде (§3). */
.screen {
  min-height: calc(var(--vh, 100vh) - 56px - env(safe-area-inset-bottom, 0px));
  max-width: 520px;
  margin: 0 auto;
  /* Нижний отступ считает не только панель, но и кнопку «сказати» над ней:
     она `position: fixed` (88px от низа плюс 46 своей высоты), и при отступе
     в 96px последняя строка экрана уезжала под неё — найдено осмотром
     01.09.2026 на «Гроші» и на карточке долга. */
  padding: 10px var(--space-screen) calc(144px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: var(--gap-card);
}

.screen-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 4px;
  font-size: var(--fs-screen);
  font-weight: var(--fw-screen);
  /* Заголовок экрана — одна строка с многоточием (§4.2). */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.screen-title .caption {
  font-size: var(--fs-caption);
  font-weight: 400;
  color: var(--muted);
  white-space: nowrap;
}
/* Имя экрана отжимает всё остальное вправо: с тремя детьми `space-between`
   растащил бы подпись и «+» по разным углам. */
.screen-title > span:first-child { margin-right: auto; }
/* Ручной ввод — тихая кнопка рядом с заголовком, не главное действие
   (docs/MINIAPP.md, «Общее»): акцент остаётся у «сказати». Площадь нажатия
   всё равно пальцевая — 44 px, как у остальных органов управления. */
.screen-add {
  flex: none;
  margin-left: 12px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: -12px;
  margin-bottom: -12px;
  font-size: 22px;
  font-weight: 400;
  line-height: 1;
  color: var(--muted);
}

/* Поля шторки ручного ввода. */
.add-input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-family);
  font-size: 14px;
  color: var(--text);
  background: transparent;
  border: none;
  padding: 0;
}
.add-input:focus { outline: none; }
.add-error {
  display: block;
  margin-top: 12px;
  font-size: var(--fs-secondary);
  color: var(--text-2);
  line-height: 1.45;
}

/* ── 2. Карточка ─────────────────────────────────────────────────────── */

.card {
  background: var(--surface);
  border-radius: var(--radius-card);
  padding: var(--pad-card) 16px;
  box-shadow: var(--card-shadow);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.card--tight { padding: 5px 16px; gap: 0; }

.section-label {
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 10px 0 2px;
}

/* Подпись — ступень caption (§4): 12/400, muted. До аудита 04.09.2026 правило
   было только у `.screen-title .caption`, а подписи стоят на всех экранах —
   и на «Гроші» «17 400 / 21 000 ₴» переносилось на две строки размером
   основного текста. */
.caption { font-size: var(--fs-caption); font-weight: 400; color: var(--muted); }

/* ── 3. Строка ленты / список ────────────────────────────────────────── */

.row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  border-bottom: 1px solid var(--divider);
}
.row:last-child { border-bottom: none; }
.row-time { width: 36px; flex: none; font-size: var(--fs-caption); color: var(--muted); }
.row-dot { width: 14px; flex: none; text-align: center; }
/* Точка категории — одна на ленту, категории «Грошей» и дорожку проектов.
   Была объявлена только внутри `.row-dot`, и вне ленты рисовался пустой span
   (аудит 04.09.2026). */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 99px; flex: none; }
.row-title {
  flex: 1;
  font-size: 14.5px;
  min-width: 0;
  /* Строка ленты — две строки, дальше многоточие (§4.2). */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.row-value { font-size: var(--fs-secondary); color: var(--text-2); flex: none; }

/* Строка задачи с чекбоксом («Далі чекають», список) */
.task-row { display: flex; align-items: center; gap: 12px; min-height: 46px; border-bottom: 1px solid var(--divider); }
.task-row:last-child { border-bottom: none; }
/* Срок в строке — тихо и справа: это ответ на «когда», а не оценка
   (docs/DESIGN_CODE.md §1.6). Не переносится и не сжимает название. */
.task-when { font-size: var(--fs-caption); color: var(--muted); white-space: nowrap; }
.checkbox { width: 22px; height: 22px; flex: none; border-radius: 999px; border: 2px solid var(--stroke); position: relative; }
/* Цель нажатия ≥44 px, включая чекбоксы (§3): кружок остаётся 22, зона — 44. */
.checkbox::before { content: ''; position: absolute; inset: -11px; }
.task-title { flex: 1; font-size: var(--fs-body); min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* ── 4. Чип, пилюля ──────────────────────────────────────────────────── */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--surface);
  border-radius: var(--radius-pill);
  padding: 7px 13px;
  font-size: 12.5px;
  color: var(--text-2);
  box-shadow: var(--card-shadow);
}
.chip-dot { width: 7px; height: 7px; border-radius: 99px; flex: none; }

/* ── 5. Таймер / «Зараз важливо» ─────────────────────────────────────── */

.timer-card { flex-direction: row; align-items: center; padding: 14px 16px; gap: 12px; }
.timer-dot { width: 10px; height: 10px; border-radius: 999px; flex: none; }
.timer-body { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.timer-label { font-size: var(--fs-secondary); color: var(--muted); }
.timer-value { font-size: var(--fs-number); font-weight: var(--fw-number); }
.timer-stop {
  background: var(--bg);
  border-radius: 12px;
  padding: 9px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  flex: none;
}

.important-card { gap: 4px; }
/* Две строки, дальше многоточие (docs/DESIGN_CODE.md §4.2). Названия
   приходят из речи и бывают длинными: без предела крупное имя в четыре строки
   съедало экран целиком и отодвигало остальные ступени за край. Шрифт при
   этом не сжимается — лучше обрезать, чем сделать нечитаемым. */
.important-title {
  font-size: var(--fs-title);
  font-weight: var(--fw-title);
  line-height: 1.15;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.important-when { font-size: var(--fs-secondary); color: var(--text-2); }
/* Ступени внутри блока отделяются подписью, а не цветом (§1.6): цвет
   состояния есть только у полосы бюджета трат. */
.important-card .section-label { padding-top: 8px; }
.important-card > .section-label:first-child { padding-top: 0; }
.important-more {
  font-size: var(--fs-secondary);
  color: var(--text-2);
  padding-top: 6px;
  cursor: pointer;
}

/* ── 6. Полоса итога ─────────────────────────────────────────────────── */

.summary-bar { display: flex; height: 12px; border-radius: 999px; overflow: hidden; }
.summary-legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: var(--fs-caption); color: var(--text-2); }

/* ── 7. Нижняя панель и «сказати» ────────────────────────────────────── */

.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  background: var(--surface);
  display: flex;
  align-items: center;
  padding: 10px 8px calc(20px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -1px 3px rgba(23, 28, 38, .04);
}
:root[data-theme="dark"] .tabbar { box-shadow: none; }
.tab {
  flex: 1;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  padding: 6px 4px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tab[aria-current="page"] {
  color: var(--accent);
}
.tab[aria-current="page"] > span {
  background: var(--accent-chip-bg);
  border-radius: var(--radius-pill);
  padding: 6px 14px;
  font-weight: 600;
}

.fab {
  position: fixed;
  right: 16px;
  bottom: calc(88px + env(safe-area-inset-bottom, 0px));
  z-index: 3;
  background: var(--accent);
  color: var(--fab-text);
  border-radius: var(--radius-pill);
  padding: 14px 24px;
  font-size: 15px;
  font-weight: 600;
  box-shadow: var(--fab-shadow);
  min-height: 44px;
}
/* На «Ще» ничего не наговаривают — акцента и кнопки там нет (§6.1). */
body[data-tab="more"] .fab { display: none; }

/* ── 8. Шторка карточки записи ───────────────────────────────────────── */

.sheet-scrim {
  position: fixed; inset: 0; z-index: 4;
  background: var(--scrim);
}
.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 5;
  max-width: 520px;
  margin: 0 auto;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  padding: 10px 20px calc(30px + env(safe-area-inset-bottom, 0px));
  box-shadow: var(--sheet-shadow);
  transform: translateY(0);
  transition: transform var(--motion-fast) var(--motion-ease);
}
.sheet[data-closing] { transform: translateY(100%); }
.sheet-handle { width: 36px; height: 4px; border-radius: 99px; background: var(--stroke); margin: 0 auto 14px; }
/* Карточка записи не обрезается вовсе (§4.2). */
.sheet-title { font-size: var(--fs-screen); font-weight: var(--fw-screen); line-height: 1.2; }
.sheet-meta { font-size: var(--fs-secondary); color: var(--muted); margin-top: 3px; }
.sheet-block { background: var(--bg); border-radius: var(--radius-inset); padding: 12px 14px; margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.sheet-field-row { display: flex; min-height: 38px; align-items: center; border-bottom: 1px solid var(--divider); }
.sheet-field-row:last-child { border-bottom: none; }
.sheet-field-label { width: 110px; flex: none; font-size: 13px; color: var(--muted); }
.sheet-field-value { font-size: 14px; flex: 1; min-width: 0; }
/* «Правити» у строки разбора — тихо и справа: строка отвечает на «что
   понял разбор», а не предлагает действие первым делом. */
.sheet-field-edit { font-size: 12.5px; color: var(--accent); font-weight: 600; padding-left: 10px; }
.sheet-actions { display: flex; gap: 8px; margin-top: 16px; }
.sheet-action { flex: 1; text-align: center; background: var(--bg); border-radius: var(--radius-button); padding: 12px 0; font-size: 13.5px; font-weight: 600; color: var(--text); min-height: 44px; }
/* «скасувати» — тише, не страшнее: тот же приём, что и в тоне продукта
   (CLAUDE.md, «Тон продукта»): никакого красного. */
.sheet-action--quiet { color: var(--muted); }

/* ── 9. Календарь ────────────────────────────────────────────────────── */

.segmented { background: var(--surface); border-radius: var(--radius-pill); padding: 4px; display: flex; gap: 2px; box-shadow: var(--card-shadow); }
.segmented button { border-radius: var(--radius-pill); padding: 5px 14px; font-size: 12.5px; color: var(--muted); min-height: 32px; }
.segmented button[aria-current="true"] { background: var(--accent-chip-bg); color: var(--accent); font-weight: 600; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-dow { font-size: 10.5px; color: var(--muted); text-align: center; }
.cal-cell {
  aspect-ratio: 1;
  border-radius: var(--radius-cell);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px;
  position: relative;
  /* Шрифт клетки не сжимается никогда (§4.2). */
}
/* Будущее — первая ступень заливки и число muted (§6.3, решение 02.09.2026).
   Обводка была у каждого будущего дня, и месяц состоял из рамок. */
.cal-cell--future { background: var(--cal-0); color: var(--muted); }
/* Пунктир остался на одном дне — завтрашнем: граница «дальше ничего ещё
   не было». */
.cal-cell--tomorrow { border: 1px dashed var(--stroke); background: transparent; }
.cal-nav { display: flex; align-items: center; justify-content: space-between; padding: 2px 2px 10px; }
.cal-nav-title { font-size: 15px; font-weight: 600; }
.cal-nav-arrow { width: 32px; height: 32px; border-radius: 999px; font-size: 17px; color: var(--text-2); background: transparent; }
.cal-today-link { font-size: 13px; color: var(--accent); font-weight: 600; }
.cal-cell--today { outline: 2px solid var(--accent); outline-offset: 2px; font-weight: 700; }
.cal-streak { position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 99px; }
.cal-legend { display: flex; align-items: center; justify-content: space-between; padding-top: 4px; border-top: 1px solid var(--divider); font-size: 11px; color: var(--muted); }
.cal-legend-swatches { display: flex; gap: 3px; }
.cal-legend-swatches span { width: 12px; height: 12px; border-radius: 4px; }

/* ── 10. Пустое состояние, скелетон, ошибка ─────────────────────────── */

.empty-state { padding: 40px 12px; text-align: center; color: var(--muted); font-size: var(--fs-body); display: flex; flex-direction: column; gap: 6px; }
.empty-state .hint { font-size: var(--fs-secondary); }

.skeleton { background: var(--surface); border-radius: var(--radius-card); box-shadow: var(--card-shadow); position: relative; overflow: hidden; }
.skeleton::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(140,148,158,.12), transparent);
  animation: shimmer 1.2s infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* Сервер выключен — данные тускнеют, баннер поверх, экран не пустеет
   (docs/MINIAPP.md, «Общее»). */
.offline-banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 6;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--text); color: var(--bg);
  text-align: center; font-size: 12.5px; padding: 6px 12px;
  padding-top: calc(6px + env(safe-area-inset-top, 0px));
}
.offline-retry {
  border: none; background: none; color: inherit; font-family: var(--font-family);
  font-size: inherit; text-decoration: underline; padding: 0;
}
.screen[data-stale] { opacity: .55; pointer-events: none; }

/* ── 11. Списки ──────────────────────────────────────────────────────── */

.list-row { display: flex; align-items: center; gap: 12px; min-height: 54px; border-bottom: 1px solid var(--divider); }
.list-row:last-child { border-bottom: none; }
.list-row-name { flex: 1; font-size: var(--fs-body); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-row-count { background: var(--bg); border-radius: var(--radius-pill); padding: 3px 10px; font-size: 12px; color: var(--text-2); }
.list-row-chevron { color: var(--stroke); }

.list-item-row { display: flex; align-items: center; gap: 12px; min-height: 48px; border-bottom: 1px solid var(--divider); }
.list-item-row:last-child { border-bottom: none; }
.list-item-title { flex: 1; font-size: var(--fs-body); min-width: 0; }
.list-item-qty { font-size: var(--fs-secondary); color: var(--muted); white-space: nowrap; }
/* Хрестик скасування — інше накреслення й відступ від кількості: поруч
   стояли два різних «×», і читалися вони одним (розбір 02.09.2026). */
.list-item-remove { font-size: 13px; color: var(--muted); padding: 4px 0 4px 12px; background: transparent; }
/* Линию над секцией рисует последняя открытая строка своим border-bottom —
   вторая сверху давала задвоенную (аудит 04.09.2026). */
.list-done-head { padding: 12px 2px 2px; margin-top: 6px; font-size: var(--fs-secondary); color: var(--muted); }

/* Виконаний пункт лишається в списку до кінця відкриття екрана, а не
   зникає — нейтральний сірий, без зеленого «успіху» (CLAUDE.md, «Тон
   продукта»: семантичні кольори до поведінки людини не застосовуються). */
.checkbox--checked { border-color: var(--muted); background: var(--muted); }
.list-item-title--done { color: var(--muted); text-decoration: line-through; }

/* ── 12. Настройки («Ще») ───────────────────────────────────────────── */

.settings-row { display: flex; align-items: center; gap: 12px; min-height: 52px; border-bottom: 1px solid var(--divider); }
.settings-row:last-child { border-bottom: none; }
.settings-label { flex: 1; font-size: var(--fs-body); }
.settings-value { font-size: var(--fs-secondary); color: var(--muted); }


/* ── Гроші (docs/MINIAPP.md, «6. Деньги»; design/Гроші.dc.html) ────────── */

.money-head { display: flex; flex-direction: column; gap: 6px; padding: 0 4px; }
.money-balance-row { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.money-balance { font-size: 40px; font-weight: 700; line-height: 1; letter-spacing: -0.01em; }
.money-line { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.money-line--head { cursor: pointer; }
.money-bar {
  position: relative; height: 8px; border-radius: var(--radius-pill);
  background: var(--bg); overflow: visible;
}
.money-bar-fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  border-radius: var(--radius-pill); background: var(--accent);
}
/* Риска — предел, заливка — факт (docs/MINIAPP.md, «Бюджеты трат»). */
.money-bar-mark {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: rgba(34, 37, 42, .5);
}
.money-row {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 0; border-bottom: 1px solid var(--divider);
}
.money-row:last-child { border-bottom: none; }
.money-row--child { padding-left: 18px; }
.money-row-title { flex: 1; font-size: 14.5px; }
.money-row-value { font-size: 14.5px; color: var(--text-2); white-space: nowrap; }
.money-row-value--lead { min-width: 74px; text-align: right; color: var(--text); }
.money-link { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.money-link .money-row-title { flex: none; }
.money-link .caption { flex: 1; }
.dot--hollow { background: none; border: 1.5px solid var(--muted); }
.budget { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; }
.budget + .budget { border-top: 1px solid var(--divider); }
.tabs { display: flex; gap: 8px; padding: 0 4px 4px; }
.tab-pill {
  border: none; border-radius: var(--radius-pill); padding: 7px 14px;
  font-family: var(--font-family); font-size: 13.5px;
  background: var(--surface); color: var(--text-2);
}
.tab-pill.is-active { background: var(--accent-chip-bg); color: var(--accent); font-weight: 600; }
.ghost-button {
  border: none; background: none; color: var(--accent);
  font-family: var(--font-family); font-size: 13.5px; padding: 6px 0; text-align: left;
}
.direction-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.direction-cell { display: flex; flex-direction: column; gap: 2px; }
.direction-value { font-size: 22px; font-weight: 700; }

/* Строка операции: точка, две строки текста, сумма справа (канва 8a). */
.money-row--feed { align-items: flex-start; }
.money-row-body { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.money-row-value--quiet { color: var(--muted); }
.money-note { padding: 8px 0 2px; }
.money-more {
  padding: 10px 0 4px; font-size: 13px; color: var(--accent);
}
.pill {
  font-size: 11.5px; color: var(--text-2); background: var(--bg);
  border-radius: var(--radius-pill); padding: 3px 8px; white-space: nowrap;
}
.ghost-link { font-size: 13px; color: var(--accent); }
.empty-icon { color: var(--muted); margin-bottom: 10px; }
.empty-action { display: flex; justify-content: center; }

/* Шторки денег: одно число крупно, чипы под ним, действие внизу (канва 8k, 8m). */
.sheet-amount { display: flex; align-items: baseline; gap: 8px; margin: 16px 0 10px; }
.sheet-input {
  flex: 1; min-width: 0; border: none; background: var(--bg);
  border-radius: var(--radius-inset); padding: 12px 14px;
  font-family: var(--font-family); font-size: 28px; font-weight: 700; color: var(--text);
}
.sheet-input:focus { outline: 2px solid var(--accent-chip-bg); }
.sheet-unit { font-size: 20px; color: var(--muted); }
.sheet-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.sheet-chips .chip { border: none; font-family: var(--font-family); }
.sheet-note { display: block; margin-top: 12px; line-height: 1.45; }
.sheet-list { margin-top: 14px; }
.sheet-primary {
  width: 100%; margin-top: 16px; border: none; border-radius: var(--radius-button);
  background: var(--accent); color: var(--fab-text); min-height: 46px;
  font-family: var(--font-family); font-size: 15px; font-weight: 600;
}
.sheet-danger { display: block; width: 100%; text-align: center; margin-top: 6px; }

/* ── 12. Дерево, проекты и рецепты (docs/DESIGN_CODE.md §7) ────────────── */

/* Кольцо прогресса — число внутри только у корня (§7). У вложенных узлов
   кольца нет вовсе, там дробь: в строке дерева кольцо оказывалось третьим
   кружком подряд после маркера раскрытия и чекбокса. */
.ring {
  width: 40px; height: 40px; flex: none; border-radius: 999px; position: relative;
  background: conic-gradient(var(--accent) var(--ring, 0deg), var(--bg) 0);
}
.ring-inner {
  position: absolute; inset: 3px; border-radius: 999px; background: var(--surface);
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 600; color: var(--text-2);
  letter-spacing: -0.01em;
}

.proj-row { display: flex; align-items: center; gap: 12px; min-height: 64px; border-bottom: 1px solid var(--divider); }
.proj-row:last-child { border-bottom: none; }
.proj-main { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.proj-name { font-size: var(--fs-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-sub { font-size: 12.5px; color: var(--muted); }
.proj-done-head { min-height: 52px; display: flex; align-items: center; color: var(--text-2); font-size: 14.5px; }

.proj-head { display: flex; align-items: center; gap: 10px; padding: 8px 4px 0; }
.proj-head-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Имя проекта в шапке — одна строка с многоточием (§4.2). */
.screen-title-text { font-size: var(--fs-screen); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-totals { display: flex; flex-wrap: wrap; gap: 4px 8px; padding: 0 4px; font-size: 13.5px; color: var(--text-2); }
.proj-controls { display: flex; align-items: center; justify-content: space-between; padding: 0 4px; }
.proj-expand { min-height: 48px; display: flex; align-items: center; color: var(--accent); font-weight: 600; font-size: 14.5px; }
.proj-foot { display: flex; gap: 8px; padding: 0 4px; }

/* Один компонент строки на все пять уровней: уровень меняет только отступ,
   но не строение строки (§7). На 360 px пятый уровень отдаёт под отступ
   72 px — остальное держит `min-width: 0` и многоточие. */
.node-row { display: flex; align-items: center; gap: 9px; min-height: 52px; border-bottom: 1px solid var(--divider); }
.node-row:last-child { border-bottom: none; }
.node-main { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.node-caret { width: 22px; flex: none; text-align: center; color: var(--muted); font-size: 13px; }
.node-title { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Закрытые дела остаются на месте, зачёркнутые и тусклые: видно, что работа
   идёт, а не только сколько осталось (docs/PROJECTS.md). */
.node-title--done { text-decoration: line-through; color: var(--muted); }
.node-meta { font-size: 12px; color: var(--text-2); }
/* Унаследованный срок — тускло, а не цветом (§6.5). Единственный способ
   отличить его на глаз, и он один на календарь, дерево и карточку. */
.node-meta--inherited { color: var(--muted); }
.node-progress { font-size: 12.5px; color: var(--text-2); flex: none; }
.node-menu { width: 28px; min-height: 44px; flex: none; color: var(--stroke); font-size: 16px; }

.tmpl-row { display: flex; align-items: center; gap: 10px; min-height: 52px; border-bottom: 1px solid var(--divider); }
.tmpl-row:last-child { border-bottom: none; }
.tmpl-main { flex: 1; min-width: 0; }
.tmpl-title { font-size: 14.5px; }
.tmpl-mark { border: 1px solid var(--stroke); border-radius: var(--radius-pill); padding: 1px 8px; font-size: 11px; color: var(--muted); white-space: nowrap; }
.tmpl-offset { font-size: 12px; color: var(--text-2); flex: none; }

/* Выключенный тумблер держится обводкой, а не тёмной заливкой: в тёмной теме
   заливка читалась бы как включённый. */
.toggle { width: 40px; height: 24px; flex: none; border-radius: 999px; background: var(--bg); border: 1px solid var(--stroke); position: relative; }
.toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 99px; background: var(--surface); border: 1px solid var(--stroke); }
.toggle--on { background: var(--accent); border-color: var(--accent); }
.toggle--on::after { left: auto; right: 2px; border-color: transparent; background: #fff; }

.note-box { border: 1px solid var(--stroke); border-radius: var(--radius-inset); padding: 12px 14px; font-size: 12.5px; color: var(--text-2); line-height: 1.5; }

/* ── 13. Календарь: неделя и дорожка проектов ──────────────────────────── */

.week-row { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--divider); }
.week-row:last-child { border-bottom: none; }
.week-row--today .week-day { color: var(--accent); font-weight: 600; }
.week-day { width: 52px; flex: none; font-size: 12.5px; color: var(--muted); padding-top: 4px; }
.week-items { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.week-item { display: flex; align-items: center; gap: 7px; min-height: 26px; min-width: 0; }
.week-dot { width: 8px; height: 8px; flex: none; border-radius: 99px; background: var(--cat-1); }
.week-main { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* Шрифт не сжимается никогда — лучше обрезать (§4.2). Обрезается при этом
   имя родителя, а не имя дела: `flex-shrink` у родителя больше, поэтому
   «Метель · обкладинка» на узком экране становится «Мет… · обкладинка», а
   не «Метель · обкл…». */
.week-name { display: flex; align-items: baseline; font-size: 13.5px; min-width: 0; }
.week-parent { flex: 0 999 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.week-sep { flex: none; white-space: pre; }
.week-own { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.week-item--done .week-name { text-decoration: line-through; color: var(--muted); }
/* Просроченное сказано словами и тем же серым: ни красного, ни бейджа (§1.6). */
.week-late { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.week-more { font-size: 12.5px; color: var(--muted); }

.track-row { display: flex; align-items: center; gap: 10px; min-height: 32px; }
.track-name { width: 118px; flex: none; display: flex; align-items: center; gap: 7px; min-width: 0; font-size: 13px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.track-rail { flex: 1; position: relative; height: 8px; border-radius: 999px; background: var(--bg); }
.track-bar { position: absolute; top: 0; bottom: 0; border-radius: 999px; }
/* Полоса в один день — точка, а не нитка в піксель (аудит 04.09.2026). */
.track-bar--point { top: 0; bottom: 0; width: 8px; margin-left: -4px; }
.track-today { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--text); opacity: .5; }
.track-range { width: 44px; flex: none; text-align: right; font-size: 12px; color: var(--muted); }
/* «План дня на Сьогодні» (docs/MINIAPP.md): фіксоване лягає заливкою
   (`.track-bar` з опацією), намір з часом — контуром. Своє і зсувне
   різняться формою, а не кольором (§1.6 — жодних семантичних кольорів). */
.track-bar--outline { background: transparent !important; border: 1.5px solid var(--text); box-sizing: border-box; opacity: .55; }

/* «Що бот про мене знає» (docs/MINIAPP.md, «9а») — строка факту без
   маркера, тихе «звідки» під нею і тиха кнопка «Зняти» праворуч. */
.knowledge-fact { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; min-height: 44px; padding: 8px 0; border-bottom: 1px solid var(--divider); }
.knowledge-fact:last-child { border-bottom: none; }
.knowledge-fact-text { font-size: var(--fs-body); color: var(--text); }
.knowledge-fact-source { font-size: 12px; color: var(--muted); margin-top: 2px; }
.knowledge-fact-revoke { flex: none; font-size: 12.5px; color: var(--muted); cursor: pointer; padding-top: 2px; }

/* Пульт режимів на «Сьогодні» (docs/MINIAPP.md «1. Сегодня»). Активний режим
   помічається фоном, а не кольором стану: колір стану в продукті є тільки в
   смузі бюджету витрат (docs/DESIGN_CODE.md §1.6). Режим міняє порядок і
   додає блоки — нічого з екрана він не прибирає. */
.mode-bar { display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 10px; }
.mode-chip { flex: none; padding: 6px 14px; border-radius: var(--radius-pill); background: var(--surface); border: 1px solid var(--stroke); color: var(--text-2); font-size: var(--fs-secondary); }
.mode-chip--on { background: var(--accent); border-color: var(--accent); color: var(--fab-text); }

/* Межа аптечки — перший блок екрана, а не дрібний шрифт унизу: унизу її не
   читають (docs/THINGS.md, «Аптечка»). */
.pharmacy-note { color: var(--text-2); }

/* Рядок запасів у два рядки: підпис «півтора кіло · холодильник · до завтра ·
   ти сказав» довша за ширину екрана, і в один ряд вона з'їдала назву речі
   цілком (стенд 375×812, 05.09.2026). Назва — головне на цьому рядку. */
.stock-row { align-items: flex-start; padding: 8px 0; }
.stock-row-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.stock-row-note { white-space: normal; line-height: 1.35; }

/* Кнопки регламенту тримаються праворуч і не тиснуть на назву: «+1» і
   «Зробив» поруч, назва речі — окремим рядком зліва. */
.stock-row-actions { display: flex; gap: 8px; flex: 0 0 auto; align-items: center; }

/* Слова власника не обрізаються трьома крапками: «день народження
   чотирнадцятого …» не відповідає на питання, заради якого картку відкрили
   (стенд 375×812, 05.09.2026). */
.fact-text { white-space: normal; overflow: visible; text-overflow: clip; }
