/* Экраны рабочего места.
 *
 * Плотно, как в таблицах, но читаемо: администратор сидит здесь смену
 * целиком, и «нарядно» тут проигрывает «не устают глаза» (владелец,
 * 20.08.2026).
 *
 * ТРИ ПРАВИЛА ЦВЕТА.
 *
 * 1. Поверхности у всех трёх направлений ОДИНАКОВЫЕ — тёплый серый.
 *    Заливать экран фирменным цветом нельзя: красный IARTPRO во весь
 *    экран утомляет за час.
 * 2. Направление различает АКЦЕНТ: активный пункт меню, полоса под
 *    шапкой, значок филиала, главная кнопка, рамка фокуса. Этого хватает,
 *    чтобы не перепутать окна IARTPRO, AVRORA и ARTA.
 * 3. Ни чистого белого фона, ни чистого чёрного текста. Контраст
 *    достаточный для чтения и недостаточный для рези в глазах.
 *
 * Тема — `data-theme` на <html>: `light`, `dark` или отсутствует
 * (тогда решает система). Ставит её `/static/theme.js` ДО отрисовки,
 * иначе на каждой загрузке мигает светлым.
 *
 * Никаких внешних шрифтов и CDN: страница обязана открываться на сервере
 * без выхода наружу (docs/БЕЗОПАСНОСТЬ.md). */

/* ─────────────── Палитра: поверхности ─────────────── */

:root {
  --bg:        #f4f3f0;
  --surface:   #ffffff;
  --surface-2: #faf9f6;
  --line:      #dedbd4;
  --line-soft: #ece9e3;
  --ink:       #23211e;
  --muted:     #6e6a63;
  --shadow:    0 1px 2px rgba(35, 33, 30, .06), 0 4px 14px rgba(35, 33, 30, .05);

  --ok:      #1d6b3f;  --ok-bg:   #eef6f0;
  --warn:    #8a5a00;  --warn-bg: #fdf4e0;
  --bad:     #9b2226;  --bad-bg:  #fbeceb;

  /* IARTPRO по умолчанию: инстанс подставляет свой набор ниже. */
  --accent:      #c8202e;
  --accent-ink:  #ffffff;
  --accent-soft: #fbeced;
  --accent-line: #eab6ba;
}

:root[data-theme='dark'] {
  --bg:        #15161a;
  --surface:   #1d1f24;
  --surface-2: #23262c;
  --line:      #343841;
  --line-soft: #2a2e35;
  --ink:       #e7e4de;
  --muted:     #9a968e;
  --shadow:    0 1px 2px rgba(0, 0, 0, .4), 0 4px 16px rgba(0, 0, 0, .3);

  --ok:      #6cc48d;  --ok-bg:   #16281e;
  --warn:    #e0b155;  --warn-bg: #2c2415;
  --bad:     #f08d90;  --bad-bg:  #2e1a1b;

  --accent:      #f0656f;
  --accent-ink:  #1a1113;
  --accent-soft: #352023;
  --accent-line: #5c3438;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg:        #15161a;
    --surface:   #1d1f24;
    --surface-2: #23262c;
    --line:      #343841;
    --line-soft: #2a2e35;
    --ink:       #e7e4de;
    --muted:     #9a968e;
    --shadow:    0 1px 2px rgba(0, 0, 0, .4), 0 4px 16px rgba(0, 0, 0, .3);

    --ok:      #6cc48d;  --ok-bg:   #16281e;
    --warn:    #e0b155;  --warn-bg: #2c2415;
    --bad:     #f08d90;  --bad-bg:  #2e1a1b;

    --accent:      #f0656f;
    --accent-ink:  #1a1113;
    --accent-soft: #352023;
    --accent-line: #5c3438;
  }
}

/* ─────────────── Палитра: направление ───────────────
   Художественная школа — красный товарного знака; школа моделей —
   ГОЛУБОЙ фирменного знака (владелец, 30.08.2026: «цвета Авроры
   голубоватый»; тон снят с голубых силуэтов присланного знака,
   точного кода владелец не называл — правится этими четырьмя
   строками); фотостудия — глубокий бирюзовый. Различимы и на глаз, и
   людьми с дальтонизмом: разный тон И разная светлота.

   У Авроры чернила на акценте ТЁМНЫЕ, а не белые: фирменный голубой
   светлый, белый текст на нём нечитаем, а пара «голубой + почти
   чёрный» — это и есть стилистика знака. */

:root[data-brand='avrora'] {
  --accent: #6cbede; --accent-ink: #10222b; --accent-soft: #eaf6fc; --accent-line: #b9e2f4;
}
:root[data-brand='arta'] {
  --accent: #0f6e72; --accent-ink: #ffffff; --accent-soft: #e8f4f4; --accent-line: #a8d2d3;
}
:root[data-theme='dark'][data-brand='avrora'] {
  --accent: #8ed3ef; --accent-ink: #0d1d26; --accent-soft: #16303c; --accent-line: #2c5468;
}
:root[data-theme='dark'][data-brand='arta'] {
  --accent: #5fc3c7; --accent-ink: #0d1e1f; --accent-soft: #122c2e; --accent-line: #2c4d4f;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light'])[data-brand='avrora'] {
    --accent: #8ed3ef; --accent-ink: #0d1d26; --accent-soft: #16303c; --accent-line: #2c5468;
  }
  :root:not([data-theme='light'])[data-brand='arta'] {
    --accent: #5fc3c7; --accent-ink: #0d1e1f; --accent-soft: #122c2e; --accent-line: #2c4d4f;
  }
}

/* ─────────────── Шрифт направления: AVRORA ───────────────
   DIN Next CYR — фирменный шрифт школы моделей; файлы прислал владелец
   30.08.2026, лицензия на его стороне. Объявления глобальны, но браузер
   запрашивает файл шрифта только когда тот ПРИМЕНЁН: художка и
   фотостудия эти три файла не тянут. Элементы форм наследуют через
   font: inherit. */
@font-face {
  font-family: 'DIN Next CYR';
  src: url('/static/fonts/DINNextCYR-Light.otf') format('opentype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'DIN Next CYR';
  src: url('/static/fonts/DINNextCYR-Regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'DIN Next CYR';
  src: url('/static/fonts/DINNextCYR-Medium.otf') format('opentype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
:root[data-brand='avrora'] body {
  font-family: 'DIN Next CYR', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
}

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

* { box-sizing: border-box; }

html { color-scheme: light; }
:root[data-theme='dark'] { color-scheme: dark; }
@media (prefers-color-scheme: dark) { :root:not([data-theme='light']) { color-scheme: dark; } }

body {
  margin: 0;
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

/* Ширина одинаковая у шапки и у содержимого — иначе они «разъезжаются»
   на широком мониторе и экран читается как две разные страницы.
   Потолка ширины нет: «при развороте на весь экран не должно оставаться
   пустых полей по бокам» (владелец, 22.08.2026) — экран работает как
   боевая таблица, во всю ширину монитора. */
.wrap {
  width: 100%;
  margin: 0 auto;
  padding: 0 20px;
}
/* Отступ шапка → содержимое небольшой: экран работает как боевая
   таблица, и воздух тут — потерянные строки (владелец, 25.08.2026). */
main { padding: 10px 0 40px; }
main > .wrap { padding-top: 0; }

a { color: var(--accent); }
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ─────────────── Шапка: она есть на КАЖДОМ экране ─────────────── */

.top {
  position: sticky; top: 0; z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 var(--line-soft);
}
.top::before {
  content: ''; display: block; height: 3px; background: var(--accent);
}
/* Шапка ОДНОЙ строкой: логотип · меню · пользователь (владелец,
   25.08.2026 — меню не уезжает вниз, пока помещается). Меню тянется
   (flex:1) и при нехватке места переносит СВОИ кнопки внутри себя,
   не выталкивая блок пользователя вниз — гарантия 24.08.2026 живёт
   здесь; телефонная раскладка — в медиа-правиле ниже. */
.top .wrap { padding-top: 6px; padding-bottom: 6px; }
.top-row { display: flex; align-items: center; gap: 14px; min-height: 36px; }

.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: inherit; }
.brand img { height: 22px; width: auto; display: block; }

/* Знак AVRORA — не символ, а ГОРИЗОНТАЛЬНАЯ БЛОКИРОВКА: фигура, строка
   «МОДЕЛЬНОЕ АГЕНТСТВО» и «AVRORA MODEL» в рамке. На 22 px, снятых со
   знака художки (компактный символ), его мелкая строка на обычном
   экране без удвоенных точек превращается в грязь. 26 px помещаются в
   шапку без её роста (`.top-row` min-height 36 px) и возвращают строку.
   Проверено рендером в браузере на 22/28/32/40 px, а не на глаз. */
:root[data-brand='avrora'] .top .brand img { height: 26px; }
.brand .name { font-weight: 700; letter-spacing: .04em; font-size: 14px; }

/* СЛОВЕСНЫЙ знак — направление, у которого файла знака ещё нет
   (`apps/web/src/layout.ts`, BRANDS). Подставлять сюда знак другого
   направления нельзя: логотип IARTPRO зарегистрирован как товарный
   знак. Начертание нейтральное — оно НЕ выдаёт себя за знак. */
.brand-word {
  font-weight: 700; letter-spacing: .06em; font-size: 15px;
  text-transform: uppercase; color: var(--accent); white-space: nowrap;
}

/* Знаки IARTPRO (#1E1E1D) и AVRORA (#2B2B2B) — из векторных оригиналов,
   начертание тёмное, и на тёмной теме оно исчезает. Отображение
   инвертируется фильтром: геометрия и файл знака не меняются
   (начертание — товарный знак).

   Правило перечисляет направления ПОИМЁННО, а не красит всё подряд:
   инверсия верна только для ОДНОЦВЕТНОГО тёмного знака. Цветному она
   подменила бы фирменный цвет — красный стал бы голубым. У ARTA знака
   пока нет; когда появится, решение принимается по его цвету, а не
   переносится сюда по привычке. */
:root[data-theme='dark'][data-brand='iartpro'] .top .brand img,
:root[data-theme='dark'][data-brand='avrora'] .top .brand img { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light'])[data-brand='iartpro'] .top .brand img,
  :root:not([data-theme='light'])[data-brand='avrora'] .top .brand img { filter: invert(1); }
}

.nav { display: flex; gap: 2px; flex-wrap: wrap; flex: 1 1 auto; min-width: 0; }
.nav a {
  text-decoration: none; color: var(--ink); padding: 6px 8px;
  border-radius: 6px; font-size: 13.5px; white-space: nowrap;
}
.nav a:hover { background: var(--surface-2); }
.nav a[aria-current='page'] {
  background: var(--accent-soft); color: var(--accent); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--accent-line);
}

.who { margin-left: auto; display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 13.5px; }
.badge {
  background: var(--accent); color: var(--accent-ink); border-radius: 4px;
  padding: 2px 8px; font-size: 12px; font-weight: 600; letter-spacing: .02em;
}
.inline { display: inline; }
button.link {
  background: none; border: none; color: var(--accent); cursor: pointer;
  text-decoration: underline; font: inherit; padding: 0;
}
button.theme, button.iconbtn, a.iconbtn {
  background: var(--surface-2); border: 1px solid var(--line); color: var(--ink);
  border-radius: 6px; padding: 4px 10px; font: inherit; font-size: 13px; cursor: pointer;
}
a.iconbtn { display: inline-flex; align-items: center; text-decoration: none; }
button.theme:hover, button.iconbtn:hover, a.iconbtn:hover { border-color: var(--accent-line); }
.iconbtn svg { width: 20px; height: 20px; display: inline-block; vertical-align: middle; }

/* ─────────────── Заголовки ─────────────── */

h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -.01em; }
h2 { font-size: 17px; margin: 22px 0 9px; }
h3 { font-size: 15px; margin: 0 0 6px; }
.sub { color: var(--muted); margin: 0 0 18px; }

/* ─────────────── Сетка и карточки ─────────────── */

.cols { display: grid; grid-template-columns: minmax(430px, 5fr) minmax(380px, 6fr); gap: 18px; align-items: start; }
@media (max-width: 1000px) { .cols { grid-template-columns: 1fr; } }

.card {
  position: relative;
  background: var(--surface); border: 1px solid var(--line); border-radius: 9px;
  padding: 15px 17px; margin-bottom: 14px;
}
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }

/* Кликабельная карточка: ссылка растянута на всю карточку, чтобы
   попадать не в подпись, а в плитку целиком (владелец, 20.08.2026). */
.card.link { transition: border-color .12s, box-shadow .12s, transform .12s; }
.card.link:hover { border-color: var(--accent-line); box-shadow: var(--shadow); }
.card.link:has(a:focus-visible) { border-color: var(--accent); }
.card.link a.stretch { text-decoration: none; color: inherit; }
.card.link a.stretch::after { content: ''; position: absolute; inset: 0; border-radius: 9px; }

/* Плитки показателей: тоже кликабельны, ведут в свой раздел. */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin-bottom: 16px; }
.tile {
  position: relative; background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; padding: 12px 14px;
}
.tile .label { color: var(--muted); font-size: 12.5px; margin-bottom: 3px; }
.tile .value { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.tile .note { color: var(--muted); font-size: 12px; margin-top: 2px; }
.tile a.stretch { text-decoration: none; color: inherit; }
.tile a.stretch::after { content: ''; position: absolute; inset: 0; border-radius: 9px; }
.tile:hover { border-color: var(--accent-line); box-shadow: var(--shadow); }
.tile.bad .value { color: var(--bad); }
.tile.ok .value { color: var(--ok); }

/* Раскрывающийся блок — для «Движения денег» и прочего, что нужно
   изредка. Закрыт по умолчанию, состояние помнит браузер. */
details.fold {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; margin-bottom: 14px;
}
/* Сводная строка педагога («ФИО · занятий · часы · расчёт N ₽» плюс
   пометки) на телефоне переносится, а не тащит страницу вправо
   (владелец, 25.08.2026). */
details.fold > summary {
  cursor: pointer; padding: 12px 16px; font-weight: 600; list-style: none;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; row-gap: 4px;
}
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::before {
  content: '▸'; color: var(--accent); transition: transform .12s;
  display: inline-block; width: 18px; height: 18px; line-height: 16px;
  text-align: center; font-size: 12px; border: 1px solid var(--line);
  border-radius: 50%; background: var(--surface-2); flex-shrink: 0;
}
details.fold > summary:hover::before { border-color: var(--accent-line); }
details.fold[open] > summary::before { transform: rotate(90deg); }
details.fold > summary .count { color: var(--muted); font-weight: 400; font-size: 13px; }
details.fold .foldbody { padding: 0 16px 14px; }

/* ─────────────── Формы ─────────────── */

.field { display: grid; grid-template-columns: 26px 1fr; gap: 8px; margin-bottom: 10px; align-items: start; }
.field .no { color: var(--muted); font-size: 12px; padding-top: 8px; text-align: right; }
.field label { display: block; font-size: 12.5px; color: var(--muted); margin-bottom: 3px; }
.field .hint { font-size: 12px; color: var(--muted); margin-top: 3px; }
/* Подпись-подсказка и вне поля формы: экраны ставят <p class="hint"> на
   верхнем уровне, и без этого правила она шла основным кеглем. */
p.hint { font-size: 12.5px; color: var(--muted); }
input, select, textarea {
  width: 100%; padding: 8px 9px; font: inherit; color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
}
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .8; }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 9px; }
@media (max-width: 560px) { .row2, .row3 { grid-template-columns: 1fr; } }
.check { display: flex; gap: 7px; align-items: baseline; }
.check input { width: auto; }

button.primary, a.button-like.primary {
  display: inline-block; text-decoration: none;
  background: var(--accent); color: var(--accent-ink); border: 1px solid var(--accent);
  padding: 9px 17px; border-radius: 7px; font: inherit; font-weight: 600; cursor: pointer;
}
button.primary:hover { filter: brightness(1.06); }
button.primary[disabled] { opacity: .45; cursor: not-allowed; filter: none; }
button.ghost, a.ghost {
  display: inline-block; background: var(--surface); border: 1px solid var(--line);
  color: var(--ink); padding: 9px 17px; border-radius: 7px; font: inherit;
  cursor: pointer; text-decoration: none;
}
button.ghost:hover, a.ghost:hover { border-color: var(--accent-line); }

/* Панель фильтра — над таблицей, в одну строку, без «применить». */
.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 12px; }
.filters .f { display: flex; flex-direction: column; gap: 3px; }
.filters label { font-size: 12.5px; color: var(--muted); }
.filters input, .filters select { width: auto; min-width: 150px; }

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

/* Широкая таблица прокручивается ВНУТРИ себя: страница не должна ездить
   вбок, иначе шапка уезжает вместе с ней. */
.scroll { overflow-x: auto; margin: 0 -17px; padding: 0 17px; }

table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
th, td { border-bottom: 1px solid var(--line-soft); padding: 6px 8px; text-align: left; vertical-align: top; }
th {
  font-size: 12px; color: var(--muted); font-weight: 600; white-space: nowrap;
  position: sticky; top: 0; background: var(--surface); border-bottom: 1px solid var(--line);
}
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
tbody tr:hover { background: var(--surface-2); }
tbody tr.clickable { cursor: pointer; }
tfoot td { font-weight: 700; border-top: 2px solid var(--line); border-bottom: none; background: var(--surface-2); }
td a { text-decoration: none; }
td a:hover { text-decoration: underline; }

/* Колонка «Остаток» читается как столбик — по нему ищут расхождение. */
td.running { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Разделитель дня внутри периода. */
tr.dayhead td {
  background: var(--surface-2); color: var(--muted);
  font-size: 12px; font-weight: 600; padding: 4px 8px;
  border-bottom: 1px solid var(--line);
}

/* ─────────────── Сообщения ─────────────── */

.refusal, .warning, .okbox { border-radius: 7px; padding: 11px 15px; margin-bottom: 12px; }
.refusal { background: var(--bad-bg); border: 1px solid var(--bad); color: var(--bad); }
.warning { background: var(--warn-bg); border: 1px solid var(--warn); color: var(--warn); }
.okbox { background: var(--ok-bg); border: 1px solid var(--ok); color: var(--ok); }
.refusal ul, .warning ul, .okbox ul { margin: 5px 0 0 18px; padding: 0; }
.refusal li, .warning li, .okbox li { margin: 3px 0; }
.refusal h3, .warning h3, .okbox h3 { color: inherit; }

.totals { display: flex; gap: 24px; flex-wrap: wrap; margin: 10px 0 0; }
.totals div { font-size: 13px; color: var(--muted); }
.totals strong { display: block; font-size: 19px; color: var(--ink); font-variant-numeric: tabular-nums; }
.snapshot { color: var(--muted); font-size: 12px; }
.muted { color: var(--muted); }
.login { max-width: 420px; margin: 60px auto; }
.stale { opacity: .45; transition: opacity .12s; }

/* Предпросмотр бумаги внутри экрана: лист в рамке, со своим фоном —
   бумага белая всегда, даже в тёмной теме. */
.paper {
  background: #fff; color: #000; border: 1px solid var(--line);
  border-radius: 7px; padding: 14px 16px; overflow-x: auto;
}
.paper table th { background: #f2f2ef; color: #333; position: static; }
.paper table th, .paper table td { border: 1px solid #999; }

/* ─────────────── Дашборд сезона ───────────────
   Цвет ячейки отвечает СТАТУСУ месяца (боевое правило 21.08.2026):
   зелёный — оплачен, голубой — переплата, жёлтый — частично, красный —
   просрочен. Палитра своя на обе темы: токены --ok/--warn/--bad заняты
   сообщениями, а тут цвет несёт смысл колонки. */
.dashboard td.mcol, .dashboard th.mcol { min-width: 72px; font-size: 12.5px; }
.dashboard td.sticky, .dashboard th.sticky {
  position: sticky; left: 0; background: var(--surface); z-index: 5;
  border-right: 1px solid var(--line);
}
.dashboard tbody tr:hover td.sticky { background: var(--surface-2); }
/* Цвета статусов месяца — и в ячейках таблиц, и в легенде дашборда:
   легенда без цвета цветов не объясняет (владелец, 24.08.2026). */
td.pay-full, .legend .pay-full { background: var(--ok-bg); color: var(--ok); }
td.pay-over, .legend .pay-over { background: #e3f2fb; color: #14557b; }
td.pay-part, .legend .pay-part { background: var(--warn-bg); color: var(--warn); }
td.pay-due, .legend .pay-due { background: var(--bad-bg); color: var(--bad); }
td.pay-wait { }
td.pay-none, .legend .pay-none { background: var(--surface-2); }
:root[data-theme='dark'] td.pay-over,
:root[data-theme='dark'] .legend .pay-over { background: #10222e; color: #7db8d8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) td.pay-over,
  :root:not([data-theme='light']) .legend .pay-over { background: #10222e; color: #7db8d8; }
}

.legend { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; font-size: 12px; align-items: center; }
.legend span { padding: 2px 9px; border-radius: 5px; border: 1px solid var(--line-soft); }
.legend .legend-label { padding: 0; border: none; }

/* Телефоны дашборда: по номеру на строку, звонок касанием (tel:). */
.dashboard td.phones { white-space: nowrap; }
/* Почта не раздаёт колонку: длинный адрес переносится в две строки. */
.dashboard td.email { max-width: 16ch; overflow-wrap: anywhere; }

/* Мини-шапки групп дашборда — «подсвеченные по цветам, с названием
   группы, как в старой таблице» (владелец, 22.08.2026). Палитра
   детерминированная по порядку секции: цвет различает соседние группы,
   а не кодирует смысл. Тёмной теме — приглушённые аналоги. */
.dashboard tr.group-head td {
  font-weight: 650; font-size: 13.5px; padding: 8px 12px;
  border-top: 2px solid var(--line); white-space: nowrap;
}
.dashboard .g0 td { background: #fce8d5; }
.dashboard .g1 td { background: #d9ead3; }
.dashboard .g2 td { background: #d0e0e3; }
.dashboard .g3 td { background: #fff2cc; }
.dashboard .g4 td { background: #ead1dc; }
.dashboard .g5 td { background: #d9d2e9; }
.dashboard .g6 td { background: #e6efd9; }
.dashboard .g7 td { background: #f4cccc; }
:root[data-theme='dark'] .dashboard .g0 td { background: #33261a; }
:root[data-theme='dark'] .dashboard .g1 td { background: #1f2d1a; }
:root[data-theme='dark'] .dashboard .g2 td { background: #1a282c; }
:root[data-theme='dark'] .dashboard .g3 td { background: #322b14; }
:root[data-theme='dark'] .dashboard .g4 td { background: #2e1e27; }
:root[data-theme='dark'] .dashboard .g5 td { background: #262038; }
:root[data-theme='dark'] .dashboard .g6 td { background: #232d1a; }
:root[data-theme='dark'] .dashboard .g7 td { background: #331e1e; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .dashboard .g0 td { background: #33261a; }
  :root:not([data-theme='light']) .dashboard .g1 td { background: #1f2d1a; }
  :root:not([data-theme='light']) .dashboard .g2 td { background: #1a282c; }
  :root:not([data-theme='light']) .dashboard .g3 td { background: #322b14; }
  :root:not([data-theme='light']) .dashboard .g4 td { background: #2e1e27; }
  :root:not([data-theme='light']) .dashboard .g5 td { background: #262038; }
  :root:not([data-theme='light']) .dashboard .g6 td { background: #232d1a; }
  :root:not([data-theme='light']) .dashboard .g7 td { background: #331e1e; }
}
/* Строка ученика: боевые колонки узкие и без переносов там, где перенос
   ломает чтение (телефон, номер договора, дата рождения). */
.dashboard td.center { text-align: center; }
.dashboard td.nowrap { white-space: nowrap; }
.dashboard td.comment { min-width: 220px; font-size: 12.5px; }
/* Расшифровка платежа в ячейке месяца переносится по строкам, чтобы
   столбец не распирало (владелец, 22.08.2026: «слишком широкий,
   неоправданно»). Перенос — только МЕЖДУ частями: сумма, дата и номер
   бланка обёрнуты .nw и не рвутся посередине; потолок ширины держит
   обёртка .pw, столбец складывается по содержимому. */
.dashboard td.pcell { white-space: normal; text-align: left; }
.dashboard td.pcell .pw { max-width: 178px; }
/* Сумма к оплате в неоплаченном месяце — как в боевой книге
   (владелец, 25.08.2026): видно, СКОЛЬКО принять, а не только цвет. */
.dashboard td.pcell .due-sum { font-weight: 600; font-size: 11.5px; }

/* Поимённые проблемы табеля ЗП (занятие без педагога) — видны сразу. */
.warn-list { margin: 6px 0 10px; padding-left: 0; list-style: none; }
.warn-list li { margin: 2px 0; }

/* Журнал посещений на карточке договора: строка дат, под ней номера
   занятий (владелец, 25.08.2026). Колонки узкие, прокрутка вбок. */
.att-log { border-collapse: collapse; }
.att-log th { text-align: left; padding: 3px 8px 3px 0; white-space: nowrap; }
.att-log td { border: 1px solid var(--line-soft); padding: 3px 6px; text-align: center; white-space: nowrap; font-size: 12.5px; }
.att-log td.att-present { background: rgba(47, 158, 111, .14); }
.att-log td.att-absent { background: rgba(217, 79, 79, .12); }
:root[data-theme='dark'] .att-log td.att-present { background: rgba(47, 158, 111, .22); }
:root[data-theme='dark'] .att-log td.att-absent { background: rgba(217, 79, 79, .18); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .att-log td.att-present { background: rgba(47, 158, 111, .22); }
  :root:not([data-theme='light']) .att-log td.att-absent { background: rgba(217, 79, 79, .18); }
}
.dashboard .nw { white-space: nowrap; }

/* Кнопки-вкладки: филиалы касс и дашборда, месяцы кассы. Крупнее обычных
   ссылок — по ним попадают пальцем (владелец, 22.08.2026: «кнопками
   побольше и повиднее»). */
.tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.tabs .tab {
  display: inline-block; padding: 9px 18px; border: 1px solid var(--line);
  border-radius: 8px; text-decoration: none; color: var(--ink);
  background: var(--surface); font-weight: 600;
}
.tabs .tab:hover { border-color: var(--accent-line); }
.tabs .tab.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* График оплат в карточке договора: все столбцы, кроме первого («Месяц»)
   и последнего («Расчёт»), — по центру (владелец, 22.08.2026). Центр
   перебивает и .num: селектор специфичнее. */
.schedule-grid th:not(:first-child):not(:last-child),
.schedule-grid td:not(:first-child):not(:last-child) { text-align: center; }

/* ─────────────── Сетка недели и журнал занятия (окно 2з) ───────────────
   Журнал рассчитан на телефон педагога (§6.9, владелец 22.08.2026):
   крупные кнопки-мишени, один столбец на узком экране. */
.schedule-week { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.schedule-day h3 { margin: 0 0 8px; }
.lesson-card {
  display: block; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); padding: 10px 12px; margin-bottom: 8px;
  color: var(--ink); text-decoration: none;
}
.lesson-card:hover { border-color: var(--accent-line); }
.lesson-card.is-cancelled { opacity: .65; }
.lesson-card.is-cancelled .lesson-head { text-decoration: line-through; }
.lesson-card .cancelled { color: var(--bad); font-size: 12.5px; margin: 4px 0; text-decoration: none; }
.roster { margin: 6px 0 0; padding-left: 22px; font-size: 13px; }
.roster li { margin: 1px 0; }
.payicon { font-size: 12px; }
/* Боевые отметки строки ученика (окно 2и): сумма долга видимой строкой
   («❌ + сумма»), курс·режим и комментарий — мелкими подстроками. */
.debt-inline { color: var(--bad); font-size: 12px; font-weight: 600; white-space: nowrap; }
.stu-sub { font-size: 11.5px; line-height: 1.35; }
/* «Не будет» (0041): ученик зачёркнут, но остаётся в табе — наполняемость
   видна; краткая причина — подстрокой предупреждающим цветом. */
.notice-sub { color: var(--warn); font-weight: 600; }
/* Черновик договора в составе (0036): ожидаемый ученик — блеклой строкой,
   чтобы отличался от заключённых договоров (владелец, 26.08.2026). */
.draft-row { opacity: .62; font-style: italic; }
.lesson-sub { margin: 14px 0 4px; font-size: 14px; }
.checkline { display: flex; align-items: center; gap: 7px; padding-top: 24px; }
.btnrow { display: flex; gap: 8px; align-items: end; }
.makeup-decide { margin-top: 8px; }
.teacher-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Перенос разрешён: форма из пяти полей (смена мастер-класса) на узком
   экране обязана складываться, а не вылезать за карточку (владелец,
   25.08.2026 — «Моя зарплата» педагога живёт на телефоне). */
.inline-form { display: inline-flex; gap: 6px; row-gap: 8px; align-items: center; flex-wrap: wrap; }
/* Подпись и её поле — неделимая пара: переносится вся, а не текст от поля. */
.inline-form label { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.inline-form input { max-width: 190px; }
.inline-fold summary { cursor: pointer; font-size: 13px; }
.warn-inline { color: var(--warn); }
.mini-badge {
  display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 9px;
  background: var(--warn-bg); color: var(--warn); vertical-align: 1px;
}
.week-nav .tab { font-weight: 400; }

.lesson-list { list-style: none; margin: 0; padding: 0; }
.lesson-list .stu {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap;
}
.lesson-list .stu-fio { font-size: 15px; }
.mark-form { display: flex; gap: 8px; }
.mark-btn {
  min-width: 92px; min-height: 44px; font-size: 15px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); cursor: pointer;
}
.mark-btn:disabled { opacity: .5; cursor: default; }
.mark-btn.active.mark-present { background: var(--ok-bg); color: var(--ok); border-color: var(--ok); }
.mark-btn.active.mark-absent { background: var(--bad-bg); color: var(--bad); border-color: var(--bad); }

/* Телефон: логотип и пользователь остаются вместе первой строкой
   (гарантия 24.08.2026), меню уходит второй — прокручиваемой; журнал —
   столбцом. */
@media (max-width: 700px) {
  .top-row { flex-wrap: wrap; }
  .nav { order: 3; flex-basis: 100%; overflow-x: auto; white-space: nowrap; max-width: 100%; flex-wrap: nowrap; }
  .schedule-week { grid-template-columns: 1fr; }
  .lesson-list .stu { flex-direction: column; align-items: stretch; }
  .mark-form .mark-btn { flex: 1; }
  /* Плотная таблица шире телефона — это НОРМА (боевая книга), поэтому
     она прокручивается внутри себя, а не тащит за собой всю страницу:
     уехавшая вправо страница прячет кнопки и читается как поломка
     (владелец, 25.08.2026). Правило общее для всех карточек: заворачивать
     каждую таблицу руками — тридцать мест, где однажды забудут. Таблицы,
     уже лежащие в .scroll, оставлены как есть — иначе прокрутка вложится
     в прокрутку. */
  .card table { display: block; overflow-x: auto; max-width: 100%; }
  .card .scroll table { display: table; }
  /* Формы в один столбец: подпись над полем, поле во всю ширину, кнопка
     крупная под пальцем — как формы посещаемости (ТЗ-ЭКРАНЫ §3.6). */
  .inline-form { display: flex; }
  .inline-form label { display: flex; flex-direction: column; align-items: stretch; gap: 4px; flex: 1 1 100%; }
  .inline-form input, .inline-form select { max-width: none; width: 100%; box-sizing: border-box; }
  .inline-form button { flex: 1 1 100%; min-height: 44px; }
}

/* ── Цвета групп в сетке ──
   Каждая группа — своим цветом, как в боевом листе (владелец,
   23.08.2026: «чтобы отличались»). Класс g-h0…g-h9 считается на сервере
   от имени группы (groupHueClass), поэтому одна группа всегда одного
   цвета. Цвет несёт полоска слева: заливка целиком спорила бы со
   значками оплаты, а полоску видно и на телефоне. */
/* Семьи цветов — правило боевого листа (владелец, 23.08.2026):
   взрослые — сине-голубые, дети — тёплые, летняя — розовая. */
.lesson-card.g-blue0 { border-left: 5px solid #3f83d9; }
.lesson-card.g-blue1 { border-left: 5px solid #2b9d9d; }
.lesson-card.g-blue2 { border-left: 5px solid #5a6fd9; }
.lesson-card.g-warm0 { border-left: 5px solid #6fa832; } /* салатовый */
.lesson-card.g-warm1 { border-left: 5px solid #d9884f; } /* рыжий */
.lesson-card.g-warm2 { border-left: 5px solid #d94f4f; } /* красный */
.lesson-card.g-warm3 { border-left: 5px solid #c9a227; } /* жёлтый */
.lesson-card.g-summer { border-left: 5px solid #d05f9b; } /* розовый */

/* ── Таблица учеников на карточке сетки ──
   Колонки боевого листа (владелец, 23.08.2026: «чтобы легче читался
   список»); отметка красит строку — «кто был» видно с карточки. */
/* Скролла ВНУТРИ карточки нет: ползунок съедает место на экране
   (владелец, 23.08.2026) — таблица обязана вмещаться. table-layout:
   fixed держит колонки на любой ширине (фотоаппарат не уезжает),
   длинный текст переносится внутри своей колонки. */
.cell-roster-wrap { margin-top: 6px; }
.cell-roster { width: 100%; border-collapse: collapse; font-size: 12.5px; table-layout: fixed; }
.cell-roster td { padding: 3px 6px 3px 0; border-top: 1px solid var(--line-soft); vertical-align: top; overflow-wrap: break-word; }
.cell-roster tr:first-child td { border-top: 0; }
/* Колонки-значки и номер — не шире содержимого (владелец, 23–24.08.2026:
   место отдаётся ФИО, комментарию и режиму, меньше переносов строк).
   Значки стоят ПО ЦЕНТРУ, ровно под своими значками шапки. Ширина 💰
   держит сумму долга («9 200,00 ₽» под значком) — её видит и педагог:
   он принимает оплату на занятии (владелец, 24.08.2026).
   ВАЖНО: при table-layout: fixed ширины берутся из ПЕРВОЙ строки —
   правила обязаны покрывать th шапки, на td одних они не работают. */
.cell-roster th.num, .cell-roster td.num { width: 14px; padding-right: 3px; }
.cell-roster th.stu-course, .cell-roster td.stu-course { width: 17%; }
.cell-roster th.stu-mode, .cell-roster td.stu-mode { width: 20%; }
.cell-roster th.stu-pay, .cell-roster td.stu-pay { width: 4.6em; text-align: center; padding-right: 2px; }
.cell-roster th.stu-cam, .cell-roster td.stu-cam { width: 18px; text-align: center; padding-right: 0; }
/* ФИО переносится по словам — фамилия не рвётся посередине. */
.cell-roster td.stu-fio { overflow-wrap: normal; }
.cell-roster td.stu-pay .debt-inline { display: block; font-size: 10.5px; }
.cell-roster .stu-mode, .cell-roster .stu-course { color: var(--muted); }
.stu-row.att-present { background: rgba(47, 158, 111, .14); }
.stu-row.att-absent { background: rgba(217, 79, 79, .12); }
:root[data-theme='dark'] .stu-row.att-present { background: rgba(47, 158, 111, .22); }
:root[data-theme='dark'] .stu-row.att-absent { background: rgba(217, 79, 79, .18); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .stu-row.att-present { background: rgba(47, 158, 111, .22); }
  :root:not([data-theme='light']) .stu-row.att-absent { background: rgba(217, 79, 79, .18); }
}

/* Согласия на фото нет — тот же фотоаппарат, но перечёркнут. */
.no-photo { position: relative; opacity: .55; }
.no-photo::after {
  content: ''; position: absolute; left: -1px; right: -1px; top: 50%;
  border-top: 2px solid var(--bad); transform: rotate(-20deg);
}

/* ── Вопрос-подтверждение своим окном, не браузерным ── */
dialog.confirm-dialog {
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  color: var(--ink); padding: 18px 20px; max-width: 420px; box-shadow: var(--shadow);
}
dialog.confirm-dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog.confirm-dialog p { margin: 0 0 14px; }
dialog.confirm-dialog .btnrow { display: flex; gap: 8px; justify-content: flex-end; }

/* ── Переключатель темы: контурные иконки ──
   Какую иконку показать, знает только браузер (localStorage) — app.js
   ставит data-mode, CSS выбирает; до отработки скрипта видна «система». */
.theme svg { width: 20px; height: 20px; display: none; vertical-align: middle; }
.theme .ic-system { display: inline-block; }
.theme[data-mode='light'] .ic-system, .theme[data-mode='dark'] .ic-system { display: none; }
.theme[data-mode='light'] .ic-light { display: inline-block; }
.theme[data-mode='dark'] .ic-dark { display: inline-block; }


/* Шапка раздела — одной строкой: заголовок, сезоны, филиалы, навигация.
   Сетка и «Ученики» (владелец, 23.08.2026: меньше места по высоте). */
/* Небольшой зазор снизу: кнопки филиалов не липнут к таблице
   (владелец, 25.08.2026). */
.schedule-top { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
.schedule-top h1 { margin: 0; }
.schedule-top .tabs { margin: 0; }
.schedule-top .sub { margin: 0; }
/* Легенда цветов — в той же строке, что кнопки филиалов (владелец,
   25.08.2026: «поднять к филиалам»). */
.schedule-top .legend { margin: 0; }

/* Заголовок таблицы учеников на карточке. */
.cell-roster th { text-align: left; font-weight: 500; color: var(--muted);
  font-size: 11px; padding: 0 6px 2px 0; border-bottom: 1px solid var(--line-soft); }

/* Выбор «кто за стойкой» — крупные кнопки в одно нажатие, а не кружочки
   с отдельной кнопкой «Продолжить» (владелец, 25.08.2026). */
.choice-row { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0; }
.choice-row .inline-form { margin: 0; }
button.big-choice {
  min-height: 48px; min-width: 180px; padding: 10px 18px; font-size: 15px;
  border-radius: 9px; cursor: pointer;
}
.desk-who { text-decoration: none; border-bottom: 1px dashed var(--accent-line); }

/* Плитки «Настроек» под шестерёнкой (владелец, 27.08.2026). Раздел
   растёт по одной плитке за окно, поэтому сетка авто-заполняемая:
   третья плитка встанет сама, без правки вёрстки. */
.settings-tiles { display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.settings-tile { display: flex; flex-direction: column; gap: 6px;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface); text-decoration: none; color: inherit; }
.settings-tile:hover { border-color: var(--accent); }
.settings-tile strong { font-size: 16px; }
.settings-tile .muted { font-size: 13px; line-height: 1.4; }

/* Иконки шапки: заявки (колокольчик) и учётки (шестерёнка) владельца.
   Тот же размер, что у кнопки темы, — ряд иконок читается одним блоком. */
.icon-btn { display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 7px; text-decoration: none;
  font-size: 15px; border: 1px solid var(--line); background: var(--surface); }
.icon-btn:hover { border-color: var(--accent); }

/* ─────────────── Шапка карточки договора и цвета направлений ───────────────
   Владелец, 26.08.2026: все части шапки одинаково видны; группа — цветом
   группы (то же правило, что в сетке: groupHueClass), курс — цветом
   направления (courseHueClass, холодная семья: «Академ рисунок в синих
   оттенках», без пересечения с тёплыми детскими). Цвет — рамкой и лёгкой
   rgba-заливкой: работает в обеих темах без дублирования палитры. */
.head-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  color: var(--ink); font-size: 14px; }
.chip { display: inline-block; padding: 2px 10px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--surface); white-space: nowrap; }
.chip.g-blue0 { border-color: #3f83d9; background: rgba(63, 131, 217, .13); }
.chip.g-blue1 { border-color: #2b9d9d; background: rgba(43, 157, 157, .13); }
.chip.g-blue2 { border-color: #5a6fd9; background: rgba(90, 111, 217, .13); }
.chip.g-warm0 { border-color: #6fa832; background: rgba(111, 168, 50, .15); }
.chip.g-warm1 { border-color: #d9884f; background: rgba(217, 136, 79, .15); }
.chip.g-warm2 { border-color: #d94f4f; background: rgba(217, 79, 79, .13); }
.chip.g-warm3 { border-color: #c9a227; background: rgba(201, 162, 39, .15); }
.chip.g-summer { border-color: #d05f9b; background: rgba(208, 95, 155, .13); }
.chip.c-acad { border-color: #3f83d9; background: rgba(63, 131, 217, .13); }
.chip.c-cold0 { border-color: #5a6fd9; background: rgba(90, 111, 217, .13); }
.chip.c-cold1 { border-color: #2b9d9d; background: rgba(43, 157, 157, .13); }
.chip.c-cold2 { border-color: #8a5ad9; background: rgba(138, 90, 217, .13); }
/* Курс-чип в таблицах сетки — мельче, чтобы не распирал строку; длинное
   имя ПЕРЕНОСИТСЯ построчно внутри своей колонки (владелец, 26.08.2026:
   «таб должен удерживать текст целиком внутри себя» — nowrap-чип наезжал
   на колонку «Режим», многоточие прятало имя). */
td.stu-course .chip { font-size: 11.5px; padding: 1px 7px; max-width: 100%;
  box-sizing: border-box; white-space: normal; overflow-wrap: break-word; }

/* Кнопки печати в блоке «Бумаги договора» переносятся строкой. */
.paper-buttons { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* ─────────────── FAQ у форм (владелец, 26.08.2026) ───────────────
   «Подсветить аккуратно»: складные, закрыты по умолчанию, тонкая
   цветная кромка слева — вопросы отвечают, а не кричат. */
details.faq.faq-situations { border-left: 3px solid var(--accent-line); }
details.faq.faq-mistakes { border-left: 3px solid var(--warn); }
.faq-item { margin: 8px 0 12px; }
.faq-q { font-weight: 600; font-size: 13px; }
.faq-a { font-size: 12.5px; color: var(--muted); margin-top: 2px; line-height: 1.45; }
/* Предварительная группа (0042): её занятие видно, но оно не деньги —
   пометка спокойная, не тревожная (владелец, 26.08.2026). */
.mini-badge.prelim { border-style: dashed; opacity: .85; }
