/* Экраны рабочего места.
 *
 * Плотно, как в таблицах, но читаемо: администратор сидит здесь смену
 * целиком, и «нарядно» тут проигрывает «не устают глаза» (владелец,
 * 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;

  /* Филиалы на плитках групп «Сегодня» (владелец, 01.11.2026: «делить по
     филиалам по цветам»): синий, фиолетовый, бирюзовый — не спорят ни со
     светофором загрузки (зелёный/жёлтый/оранжевый), ни с красным акцентом. */
  --branch-1: #2f6fd6;
  --branch-2: #8a4fd0;
  --branch-3: #0f8080;
}

: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;

  --branch-1: #7aa7f2;
  --branch-2: #b896ef;
  --branch-3: #5fc8c8;
}

@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;

    --branch-1: #7aa7f2;
    --branch-2: #b896ef;
    --branch-3: #5fc8c8;
  }
}

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

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

:root[data-brand='avrora'] {
  --accent: #6cbede; --accent-ink: #10222b; --accent-soft: #eaf6fc; --accent-line: #b9e2f4;
  /* Цвет ТЕКСТА акцента — ссылки, бейджи, пункт меню, рамка фокуса (README-35 §16.2, ЛК-4): фирменный
     голубой на белом даёт 2,09 : 1 при норме 4,5 : 1 (WCAG 1.4.3), этот — 5,63 : 1. Голубой остаётся
     заливкой кнопок и рамками, где под ним тёмные чернила. */
  --accent-text: #1f6f8f;
}
:root[data-brand='arta'] {
  --accent: #0f6e72; --accent-ink: #ffffff; --accent-soft: #e8f4f4; --accent-line: #a8d2d3;
}
/* Сводная владельца — ЗЕЛЁНАЯ (владелец, 09.11.2026: «цвет оформления
   сводной поменять на зелёный»): с первого взгляда не путается ни с одной
   школой. Контраст: текст акцента к белому 5,34 : 1, к фону 4,81 : 1, белые
   чернила на кнопке 5,34 : 1; в тёмной теме — от 7,86 : 1 (норма 4,5 : 1). */
:root[data-brand='hub'] {
  --accent: #1d7a4a; --accent-ink: #ffffff; --accent-soft: #e6f4ec; --accent-line: #a7d5b9;
}
:root[data-theme='dark'][data-brand='avrora'] {
  --accent: #8ed3ef; --accent-ink: #0d1d26; --accent-soft: #16303c; --accent-line: #2c5468; --accent-text: #8ed3ef;
}
:root[data-theme='dark'][data-brand='arta'] {
  --accent: #5fc3c7; --accent-ink: #0d1e1f; --accent-soft: #122c2e; --accent-line: #2c4d4f;
}
:root[data-theme='dark'][data-brand='hub'] {
  --accent: #5bcf8c; --accent-ink: #0b1f14; --accent-soft: #15291d; --accent-line: #2c5a3d;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light'])[data-brand='avrora'] {
    --accent: #8ed3ef; --accent-ink: #0d1d26; --accent-soft: #16303c; --accent-line: #2c5468; --accent-text: #8ed3ef;
  }
  :root:not([data-theme='light'])[data-brand='arta'] {
    --accent: #5fc3c7; --accent-ink: #0d1e1f; --accent-soft: #122c2e; --accent-line: #2c4d4f;
  }
  :root:not([data-theme='light'])[data-brand='hub'] {
    --accent: #5bcf8c; --accent-ink: #0b1f14; --accent-soft: #15291d; --accent-line: #2c5a3d;
  }
}

/* ─────────────── Шрифт направления: 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; }

/* Атрибут hidden — ВСЕГДА display:none, каким бы ни был элемент.
   Стиль браузера `[hidden] { display: none }` живёт в таблице агента, и
   ЛЮБОЙ авторский display его перебивает: .field — grid, .row3 и
   .inline-form — flex, button — inline-block. Элемент с hidden оставался
   на экране: под «Пробное» в приёме наличных владелец видел ВЫКЛЮЧЕННЫЕ
   поля договора, месяца графика, суммы и причины (22.09.2026) — скрипт
   кассы ставил hidden на .field, а grid его перебивал. Форма договора
   обходила это плоскими div-обёртками (contractForm.ts: «у .field он
   перебит grid-ом»); правило общее, чтобы обход не требовался нигде.
   !important — правило обязано победить любой авторский display, в том
   числе будущий. */
[hidden] { display: none !important; }

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-text, 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-text, 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);
}
/* ВЫСОТА ШАПКИ — `--top-h`. Шапка закреплена и бывает в одну, две и три
   строки, поэтому всё, что закрепляется под ней или прыгает по якорю,
   отступает на её ФАКТИЧЕСКУЮ высоту: её ставит сценарий
   (`initTopHeight`, app.js); без сценария — запас на две строки меню.
   Без отступа якорь «#what» карточки и закреплённая колонка купюр
   уходили под шапку (владелец, 08.10.2026, ночь). */
:root { --top-h: 96px; }
html { scroll-padding-top: calc(var(--top-h) + 8px); }
/* Шапка ОДНОЙ строкой: логотип · меню · пользователь (владелец,
   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 { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light'])[data-brand='iartpro'] .top .brand img { filter: invert(1); }
}
/* Знак AVRORA (пакет 31.08.2026) несёт фирменный голубой #6cbede —
   инверсия перекрасила бы его в оранжевый, поэтому темы меняют ФАЙЛ:
   светлой видна чернильная версия, тёмной — белая. Селекторы темы —
   те же, что у палитры выше. */
.top .brand img.logo-dark { display: none; }
:root[data-theme='dark'] .top .brand img.logo-light { display: none; }
:root[data-theme='dark'] .top .brand img.logo-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .top .brand img.logo-light { display: none; }
  :root:not([data-theme='light']) .top .brand img.logo-dark { display: block; }
}

.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-text, 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-text, 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; }
/* Второй список в том же складном блоке (индивидуальные в «Не оплатили», 01.11.2026). */
.foldbody h3.sub-title { margin-top: 14px; }
.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; }
/* Текущий и следующий месяц под чертой в плитке денег «Сегодня» (01.11.2026). */
.tile .tile-months { margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--line); display: grid; gap: 2px; font-size: 13px; }
.tile .tile-months > div { display: flex; justify-content: space-between; gap: 8px; }
.tile .tile-months .num { font-variant-numeric: tabular-nums; font-weight: 600; }
.tile .tile-months .tile-ind { color: var(--muted); border-top: 1px dashed var(--line-soft); padding-top: 3px; margin-top: 2px; }
/* В красной плитке «Долг» строки месяцев — обычным цветом: красная — только цифра. */
.tile.bad .tile-months { color: var(--ink); }
/* Пометка под строкой месяца («скидка оплативших пакетом … уже вычтена», ответ 69 «а»). */
.tile .tile-months .tile-months-note { display: block; font-size: 12px; color: var(--muted); 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; }
/* Стрелочка внутри ячейки таблицы: «Занятия — 12» раскрывает группы и
   даты, по умолчанию свёрнуто (владелец, 04.10.2026). */
details.inline-fold > summary { cursor: pointer; }
details.inline-fold ul.plain { margin: 6px 0 0 18px; padding: 0; font-size: 13px; color: var(--muted); }
details.inline-fold ul.plain li { list-style: none; }
/* «Последние бланки» формы приёма (30.10.2026): строка — бланк, по пункту на строку. */
.recent-bso h3 { margin: 0 0 4px; font-size: 15px; }
.recent-bso ul.plain { margin: 6px 0 0; padding-left: 0; font-size: 13px; }
.recent-bso ul.plain li { list-style: none; margin: 3px 0; }
/* Причины в ячейке таблицы — по строке на причину (30.10.2026, «ждут возврата из отпуска»). */
td ul.plain { margin: 0; padding-left: 0; }
td ul.plain li { list-style: none; margin: 0 0 3px; }

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

.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; }
/* Выключенное поле — видно, что выключено (Щ-2): без этого правила поле суммы
   выглядело рабочим, а печать в него не давала ничего и без объяснения.
   Бледность 0,65, подсказка внутри поля — без своей прозрачности (Э-2): в
   выключенных полях лежат объяснения («не из кассы — …», «1 — по виду»).
   Галочки и переключатели — браузерного вида: у плитки выбранного кадра своя
   бледность, и вместе «✓» терялась (Э-3). `:where` — нулевой вес: у
   выключенных кнопок своё правило выше, и оно не перебивается. Одно правило на
   платформу — поля кассы окна аванса, выбор договора в выписке, время в
   очереди съёмки, «мест» у индивидуальной группы, поля при загрузке фото (Э-5). */
:where(input:not([type="checkbox"], [type="radio"]), select, textarea):disabled { opacity: .65; cursor: not-allowed; }
:where(input, textarea):disabled::placeholder { opacity: 1; }
/* Поле текста бумаги в «Текстах бумаг» и черновик, не сохранённый из-за
   сменившейся версии (аудит партии 6.1, НИЗК-2): моноширинный шрифт —
   разметка `**`, `{{…}}` и `|` читается по колонкам. Классом, а не
   атрибутом style: политика страниц (`style-src 'self'`) встроенный стиль
   отбрасывает. */
textarea.paper-text { font: 13px/1.45 ui-monospace, Consolas, monospace; }
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; }
.client-kind { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 4px; }
.client-kind .mini { padding: 2px 10px; font-size: 12px; }
/* Ответ «новый / старый» — цветом: зелёный новому, красный старому
   (владелец, 12.09.2026: «а то не видно»). */
.client-kind .is-new { color: var(--ok, #1d7a3a); font-weight: 600; }
.client-kind .is-returning { color: var(--bad); font-weight: 600; }
.day-row select { min-width: 0; }
.client-kind-radio { display: inline-flex; gap: 10px; align-items: center; flex-wrap: wrap; font-size: 12.5px; }
.client-kind-radio label { white-space: nowrap; }
/* Три поля в строку — сколько помещается: в узкой колонке формы (≈450px)
   три сетки с номерами полей налезали друг на друга, поэтому строка
   переносит поля (пробное: занятие → платёж → способ; владелец,
   11.09.2026). */
.row3 { display: flex; flex-wrap: wrap; gap: 0 9px; }
.row3 > * { flex: 1 1 190px; min-width: 0; }
@media (max-width: 560px) { .row2 { grid-template-columns: 1fr; } }
/* «Разбор» сводной: на телефоне «что за строка» и заметка о решении — под
   днём и суммой во всю ширину, а не узким третьим столбцом по слову в строке. */
@media (max-width: 560px) {
  table.review-rows, table.review-rows tbody { display: block; }
  table.review-rows thead { display: none; }
  table.review-rows tr { display: grid; grid-template-columns: 1fr auto; border-bottom: 1px solid var(--line-soft); }
  table.review-rows td { border-bottom: 0; }
  table.review-rows td.facts, table.review-rows td.note { grid-column: 1 / -1; padding-top: 0; }
}
.check { display: flex; gap: 7px; align-items: baseline; }
.check input { width: auto; }

/* ─── Кнопки: одна база на всё приложение ───
   «Кнопки в стиле win 98 убрать везде» (владелец, 11.09.2026): кнопка
   без класса рисовалась системным бевелом браузера — таких в разметке
   было 49. База ниже — у ВСЕХ <button> и submit; классы .primary,
   .ghost, .link, .theme, .iconbtn, .big-choice и контекстные правила
   (.part-form button и др.) переопределяют её, как и раньше:
   у класса специфичность выше независимо от порядка. */
button, input[type="submit"], input[type="button"], a.button-like, span.button-like {
  display: inline-block; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 14px;
  font: inherit; font-size: 13.5px; line-height: 1.25; cursor: pointer;
  transition: border-color .12s, background .12s;
}
/* `button-like` без вида (primary/ghost) рисовался ссылкой — правил у него не было (README-35 §16.2, ЛК-5). */
a.button-like { text-decoration: none; }
a.button-like:hover { border-color: var(--accent-line); background: var(--surface-2); }
button:hover, input[type="submit"]:hover, input[type="button"]:hover {
  border-color: var(--accent-line); background: var(--surface-2);
}
button:focus-visible, input[type="submit"]:focus-visible, input[type="button"]:focus-visible {
  /* Рамка фокуса — цветом текста акцента: бледная линия акцента давала 1,38 : 1 (README-35 §16.2, ЛК-4). */
  outline: 2px solid var(--accent-text, var(--accent)); outline-offset: 1px;
}
button[disabled], input[type="submit"][disabled], input[type="button"][disabled] {
  opacity: .45; cursor: not-allowed;
}

/* Квиз перевода — выбор карточкой (владелец, 23.09.2026, ответ 69; макет
   «карточка-договора-что-делаем», экран 3). Выбранная — рамка цвета
   акцента и галочка, невыбранная — серая; цвета у ответов нет: два
   цветных блока читались как «выбрано оба» (22.09.2026). Одна карточка
   и в окне, и в запасной форме без скрипта; всё на токенах темы —
   тёмная тема через те же переменные, своих правил ей не нужно. */
.quiz-choices .choice {
  display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 8px; align-items: start;
  position: relative; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px;
  margin: 0 0 8px; background: var(--surface-2); cursor: pointer;
}
/* Радио видимое: общая база input (width 100%, рамка, подложка) ему не годится. */
.quiz-choices .choice input[type='radio'] {
  width: 16px; height: 16px; margin: 3px 0 0; padding: 0; border: 0; background: none;
  accent-color: var(--accent);
}
.quiz-choices .choice .t { display: block; font-weight: 600; padding-right: 22px; }
.quiz-choices .choice .d { display: block; color: var(--muted); font-size: 12.5px; margin-top: 3px; }
.quiz-choices .choice.is-on { border: 2px solid var(--accent); background: var(--surface); padding: 9px 11px; }
.quiz-choices .choice.is-on::after {
  content: '✓'; position: absolute; right: 10px; top: 8px; color: var(--accent); font-weight: 700;
}
.quiz-choices .choice:has(input:focus-visible) { outline: 2px solid var(--accent-line); outline-offset: 2px; }
.quiz-reason { margin-top: 8px; }
.quiz-reason label { display: block; font-size: 12.5px; color: var(--muted); margin-bottom: 3px; }
/* Само окно — <dialog> со стилями системы, как окно подтверждения. */
dialog.quiz-dialog {
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink);
  padding: 16px 18px; width: min(560px, calc(100vw - 32px)); box-shadow: var(--shadow);
}
dialog.quiz-dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog.quiz-dialog h3 { margin: 0 0 8px; }
dialog.quiz-dialog .quiz-error { color: var(--bad); font-weight: 600; margin: 8px 0 0; }
dialog.quiz-dialog .btnrow { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }

button.primary, a.button-like.primary, span.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, span.button-like.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); }
/* Выбранный месяц на «Зарплате» подсвечен (владелец, 05.10.2026). */
a.ghost.active, button.ghost.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
/* Одна строка на сотрудника (владелец, 05.10.2026): подробности
   раскрываются кликом по ФИО, второй строки-заголовка нет; закрытая
   строка подробностей не занимает места. */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Прячется по СВОЕЙ складке, не по вложенной («ЗП руководителя» внутри строки, 06.10.2026). */
tr.row-fold:has(> td > details.fold:not([open])) { display: none; }
tr.row-fold details.fold > summary.visually-hidden::before { content: none; }

/* Панель фильтра — над таблицей, в одну строку, без «применить». */
.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; }
/* Подпись месяца — по центру своего столбца (владелец, 09.11.2026:
   «сейчас они сбоку и путают»): прижатая вправо, как число, она стояла у
   границы со следующим месяцем и читалась как его подпись. */
.dashboard th.mcol { text-align: center; }
/* Шапка «Учеников» видна при прокрутке вниз (владелец, 09.11.2026). Её
   сдвигает app.js (`initStickyHead`): таблица едет вбок внутри .scroll, и
   position: sticky липнет к рамке, а не к экрану. Шапка — над ячейками
   месяцев (у них свой фон) и под шапкой экрана; закреплённая — с тенью,
   чтобы край читался над строками. В печати сдвига нет. */
.dashboard[data-sticky-head] thead th { z-index: 6; will-change: transform; }
.dashboard.head-stuck thead th { box-shadow: 0 1px 0 var(--line), 0 3px 6px rgba(0, 0, 0, .08); }
@media print { .dashboard[data-sticky-head] thead th { transform: none !important; box-shadow: none; } }
.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); }
td.pay-zero, .legend .pay-zero { background: var(--surface-2); color: var(--muted); }
td.pcell .leave-note { font-size: 12px; color: var(--muted); }
: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; }

/* Ряд кнопок групп под легендой (владелец, 14.09.2026, вечер): «все
   группы», филиалы, далее группы филиала — детские, потом взрослые.
   Одной строкой, пока помещается; переносится, а не прячется. */
.group-tabs { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0 0 10px; }
.gtab {
  display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12.5px; line-height: 1.4;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); text-decoration: none;
}
.gtab:hover { background: var(--surface-2); text-decoration: none; }
.gtab.active { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Полоса горизонтальной прокрутки, закреплённая СВЕРХУ таблицы (владелец,
   14.09.2026, вечер): дублёр прокрутки .scroll — липнет под шапкой
   (высоту шапки ставит app.js), синхронизирован с таблицей в обе
   стороны. Без JS полосы нет вовсе: работает прежняя под таблицей. */
.hscroll-top { display: none; }
.js .hscroll-top {
  display: block; overflow-x: auto; overflow-y: hidden; height: 14px;
  position: sticky; top: 0; z-index: 6; margin: 0 -17px 4px; padding: 0 17px;
  background: var(--surface);
}
.js .hscroll-top.is-idle { display: none; }
.hscroll-inner { height: 1px; }

/* Телефоны дашборда: по номеру на строку, звонок касанием (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; }
/* Срок гарантийного письма подходит — громко всем ролям (владелец, 03.09.2026). */
.pay-alert { color: var(--bad); font-size: 12px; font-weight: 700; }
/* Архив дашборда: «⛔ прекращён с …» в колонке комментария. */
.ended-note { color: var(--bad); }
.stu-sub { font-size: 11.5px; line-height: 1.35; }
/* «Не будет» (0041): ученик зачёркнут, но остаётся в табе — наполняемость
   видна; краткая причина — подстрокой предупреждающим цветом. */
.notice-sub { color: var(--warn); font-weight: 600; }
/* Бумага выдана на подпись и не вернулась (владелец, 13.09.2026): пометка
   педагогу «забрать договор и график» под ФИО — заметна, но не тревога. */
.paper-todo { color: var(--ink); background: var(--warn-bg, #fff4d6); border-radius: 5px; padding: 1px 6px; display: inline-block; margin-top: 2px; font-weight: 600; }
/* Форма отказа в карточке заявки: стили атрибутом CSP ('self') не применяла — классом. */
.approval-reject { margin-top: 8px; }
.approval-reject .align-end { align-self: end; }
/* Допуск к мероприятию дня (0159): «не допущен» — красным и жирно, педагог не пускает; «допущен, но…» — спокойно. */
.event-admission.bad { color: var(--bad); font-weight: 700; white-space: normal; }
.event-admission.ok { color: var(--warn); white-space: normal; }
/* Черновик договора в составе (0036): ожидаемый ученик — блеклой строкой,
   чтобы отличался от заключённых договоров (владелец, 26.08.2026). */
.draft-row { opacity: .62; font-style: italic; }
/* Ученик в академе — серой строкой «в академе до ДД.ММ» (владелец, 30.10.2026: «в сетке сереньким»). */
.leave-row td { color: var(--muted); }
.leave-row .stu-fio { opacity: .75; }
/* Записан на место ученика в академе — подпись под ФИО (30.10.2026). */
.leave-seat-sub { color: var(--warn); font-size: 12px; }
.lesson-sub { margin: 14px 0 4px; font-size: 14px; }
.checkline { display: flex; align-items: center; gap: 7px; padding-top: 24px; }

/* Комбобокс поля «Договор» кассы (27.09.2026): поле ввода поверх обычного
 * select, список строк раскрывается под полем; без скрипта виден select. */
.combo { position: relative; }
.combo-list {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 30; margin-top: 3px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .14); max-height: 19rem; overflow-y: auto;
}
.combo-item {
  display: block; width: 100%; text-align: left; padding: 7px 10px; margin: 0;
  background: none; border: 0; border-bottom: 1px solid var(--line-soft); border-radius: 0;
  color: var(--ink); font: inherit; cursor: pointer; box-shadow: none;
}
.combo-item:last-child { border-bottom: 0; }
.combo-item:hover, .combo-item:focus-visible { background: var(--accent-soft); outline: none; }
.combo-item .sub { display: block; font-size: 12px; color: var(--muted); }
.combo-note { padding: 8px 10px; font-size: 12px; color: var(--muted); }
.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); }
/* Условия зачёта пробного словами (владелец, 22.09.2026, ответ 2) —
   строка блока «Пробное» на карточке договора. */
.trial-condition { color: var(--warn); }
/* Пробное, не зачтённое в курс, ВНУТРИ ячейки месяца занятия дашборда
   (владелец, 22.09.2026, ответ 3): мелко и красным — «ПР 700р 28.08 —
   условия ❌». В сумму месяца не входит, потому и набрано иначе. */
.dashboard td.pcell .trial-bad {
  color: var(--bad);
  font-size: 10.5px;
  font-weight: 600;
  margin-top: 2px;
}

/* Текст владельца, набранный абзацами (инструкция к мероприятию, 0073):
   переносы строк сохраняются — иначе список «что взять с собой»
   склеивается в одну строку и перестаёт быть списком. */
.pre-wrap { white-space: pre-wrap; }

/* Ссылка «подготовка дня →» в строке дня-мероприятия сетки (0073):
   отметки живут в журнале, подготовка — в дашборде мероприятий. */
.hg-event-link { white-space: nowrap; font-size: 12.5px; }
.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; }

/* ─────────────── Сетка-гибрид AVRORA (0051, проект §5) ───────────────
   Шапку карточки занимают ПРЕДМЕТЫ дня, состав — раскрытием; карточка
   с формами педагога предмета — div, журнал открывается явной ссылкой. */
.lesson-card.hybrid { cursor: default; }
.lesson-card.hybrid .lesson-head a { color: var(--accent); }
.subject-head { margin: 6px 0 2px; }
.subject-line { font-size: 13px; margin: 2px 0; }
.subject-line .part-form select { max-width: 180px; font-size: 12.5px; }
.part-form button { font-size: 12px; padding: 2px 8px; }
.plan-line { font-size: 12px; margin: 4px 0 2px; }
/* Недобор плана сезона — подсветка (владелец, 31.08.2026): недобор,
   замеченный в мае, уже не исправить. */
.mini-badge.plan-warn { background: var(--bad-bg, #fde3e3); color: var(--bad); font-weight: 600; }
.mini-badge.event-kind { background: var(--accent-bg, var(--warn-bg)); color: var(--accent); }
.roster-details summary { cursor: pointer; font-size: 12.5px; color: var(--muted); margin: 4px 0 2px; }

.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;
}
/* Строка ученика берёт всё место слева и переносит длинные пометки (допуск
   к мероприятию, 0159) — кнопки «Был / Не был» остаются справа, а не уезжают вниз. */
.lesson-list .stu-fio { font-size: 15px; flex: 1 1 0; min-width: 0; }
.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); }
/* «⋯» строки ученика (0190; владелец, 26.10.2026: «в трёх точках справа от
   ученика»): квадрат под палец, 44 px, как кнопки отметки. На телефоне —
   в правом верхнем углу строки рядом с ФИО, а не пустой полосой под
   кнопками «Был / Не был». */
details.actions.stu-more > summary {
  min-width: 44px; min-height: 44px; padding: 0; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; font-size: 20px; line-height: 1;
}

/* Телефон: логотип и пользователь остаются вместе первой строкой
   (гарантия 24.08.2026), меню уходит второй — прокручиваемой; журнал —
   столбцом. */
/* Узкий экран — планшет и уже (владелец, 07.10.2026): шапка в ДВЕ
   строки вместо трёх — логотип слева, под ним по центру роль, справа
   иконки чуть меньше и по три в ряд; меню — следующей строкой во всю
   ширину. Блок пользователя раскрыт в сетку (display: contents), чтобы
   роль и иконки встали в разные ячейки. Телефонная раскладка меню —
   ниже. */
.who-icons { display: inline-flex; align-items: center; gap: 10px; }
@media (max-width: 1000px) {
  .top-row {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
    grid-template-areas: "brand . icons" "role . icons" "nav nav nav"; row-gap: 4px; column-gap: 10px;
  }
  .brand { grid-area: brand; justify-self: center; }
  .who { display: contents; }
  /* Первый столбец — по ширине знака: роль центрируется ровно под ним. */
  .who-role { grid-area: role; justify-self: stretch; text-align: center; font-size: 12.5px; }
  .who > button.theme { grid-area: icons; }
  .who-icons { grid-area: icons; align-self: center; flex-wrap: wrap; justify-content: flex-end; gap: 6px; max-width: 118px; }
  .who-icons .iconbtn, .who-icons button.theme { padding: 3px 7px; }
  .who-icons .iconbtn svg, .who-icons button.theme svg { width: 17px; height: 17px; }
  .nav { grid-area: nav; }
}
@media (max-width: 700px) {
  .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; }
  .lesson-list .stu.has-more { position: relative; }
  .lesson-list .stu.has-more .stu-fio { padding-right: 54px; }
  .lesson-list .stu.has-more > details.stu-more { position: absolute; top: 9px; right: 0; }
  .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-info, .cell-roster td.stu-info { width: 20px; 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 td.stu-pay .pay-alert { display: block; font-size: 10.5px; white-space: normal; }
.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); }
}

/* Колонка ℹ️ строки ученика (владелец, 14.09.2026): 📷 фото, 🚪 уход домой,
   📄 договор подписан — СТОЛБИКОМ вплотную; чего нет — тот же значок
   перечёркнут (правило фотоаппарата 23.08.2026 — на все три). */
/* Зазор между значками — «буквально чуть-чуть», иначе сливаются
   (владелец, 14.09.2026, вечер). */
.info-stack { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; line-height: 1.1; vertical-align: middle; }
.info-stack .payicon { display: block; }
.info-inline { display: inline-flex; gap: 2px; vertical-align: middle; }
.dashboard td.icons { padding-top: 2px; padding-bottom: 2px; }
.ico-off { position: relative; opacity: .55; }
.ico-off::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; }
/* «Новый ученик или старый?» — окно НА ВЕСЬ ЭКРАН (владелец, 11.09.2026):
   вопрос про деньги доли не должен теряться в углу. Показ — только [open]:
   display на самом dialog перебил бы скрытие закрытого окна. */
dialog.client-kind-dialog[open] {
  display: grid; place-items: center; width: 100vw; height: 100vh; max-width: 100vw; max-height: 100vh;
  margin: 0; padding: 16px; border: 0; border-radius: 0; background: var(--bg); color: var(--ink); box-sizing: border-box;
}
dialog.client-kind-dialog::backdrop { background: rgba(0, 0, 0, .6); }
.client-kind-box { max-width: 520px; width: 100%; text-align: center; }
.client-kind-box h2 { margin: 0 0 12px; font-size: 24px; }
.client-kind-box p { margin: 0 0 18px; font-size: 16px; color: var(--muted); }
.client-kind-box .choice { display: block; width: 100%; padding: 16px 18px; font-size: 18px; margin-top: 10px; }

/* ── Переключатель темы: контурные иконки ──
   Какую иконку показать, знает только браузер (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; }
/* Прежняя группа и стрелка перевода в шапке карточки (владелец, 07.10.2026):
   закрытое членство приглушено пунктиром, стрелка несёт дату перевода. */
.chip.chip-closed { opacity: .6; border-style: dashed; }
.chip.chip-arrow { border-color: transparent; background: transparent; padding: 2px 4px; }
/* «Копия для отладки» (владелец, 23.09.2026): кнопка владельца между
   заголовком карточки и чипами — компактнее обычной, чтобы не спорить с
   шапкой; после копирования — короткая пометка на самой кнопке. */
a.debug-copy { padding: 4px 10px; font-size: 13px; margin: 0 0 8px; }
a.debug-copy.is-copied { border-color: var(--accent-line); }
.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); }
/* Чип пробного в шапке карточки (22.09.2026): цвет — условия зачёта;
   это ссылка к блоку «Пробное», но выглядит как остальные чипы. */
.chip.chip-ok { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); }
.chip.chip-warn { border-color: var(--warn); background: var(--warn-bg); color: var(--warn); }
.chip.chip-bad { border-color: var(--bad); background: var(--bad-bg); color: var(--bad); }
a.chip.trial-chip { text-decoration: none; }
a.chip.trial-chip:hover { filter: brightness(1.06); text-decoration: underline; }
.trial-bind ul, .trial-bind-hint p { margin: 4px 0 8px; }
/* Курс-чип в таблицах сетки — мельче, чтобы не распирал строку; длинное
   имя ПЕРЕНОСИТСЯ построчно внутри своей колонки (владелец, 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; }

/* ─────── Доска плана над сеткой AVRORA (Этап 9 §4) ───────
   «Дано/план» по предметам + конструктор недели составляемого
   расписания; художкины группы сюда не попадают — блок пуст. */
.plan-board .plan-board-group { border-top: 1px solid var(--line);
  padding: 8px 0 4px; }
.plan-board .plan-board-group:first-of-type { border-top: none; }
.plan-board .plan-subjects { margin: 4px 0; }
.plan-board .plan-subj { display: inline-block; margin-right: 4px; }
.plan-board .plan-week { margin: 4px 0 8px; }
.plan-board .plan-week ul { margin: 4px 0; }
.plan-board .plan-week .inline-form { display: inline-flex; gap: 6px;
  align-items: center; margin-top: 4px; }

/* Галочки предметов в строке педагога (Этап 9 §5). */
.subj-line { margin-top: 3px; }
.subj-line .subj-toggle { display: inline-block; margin: 1px 2px 1px 0; }
.subj-line button.mini-badge { cursor: pointer; }
/* Выплата строки ведомости — «выдано» и кнопка отмены в строке (15.09.2026). */
.mini-badge.ok { background: #e6f4ea; color: #1b7f3b; border-color: #b7dfc2; }
.paid-line { margin: 2px 0; }
/* Ведомость одной таблицей (владелец, 21.09.2026): строка человека и её
   расшифровка — соседние строки таблицы. Фамилия открывает расшифровку. */
.row-open { cursor: pointer; text-decoration: none; color: inherit; }
.row-open:hover { text-decoration: underline; }
.row-x > td { border-top: 0; padding-top: 0; }
/* Выбор «почему» в форме (снятие и перенос записанной отработки, п. 2.6.3):
   без рамки браузера — подпись поля и варианты столбцом, как у соседних полей. */
fieldset.choice { border: 0; padding: 0; margin: 0 0 10px; min-width: 0; }
fieldset.choice > legend { padding: 0; margin-bottom: 4px; font-size: 13px; color: var(--muted); }
fieldset.choice > label { display: flex; gap: 8px; align-items: flex-start; margin: 4px 0; }
/* Шапка карточки колокольчика: что — слева, когда (или сколько) — справа.
   Без этого правила время прилипало к ФИО («Анна Петрова26.10.2026»):
   соседние строчные теги стоят без пробела (проверка снимком 27.10.2026). */
.feed-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 2px 12px; }
.row-x .fold > summary { color: var(--muted); font-size: 12.5px; }
.row-x .dialog-host, td.dialog-host { padding: 0; border: 0; }
/* Поле формы, не прошедшее проверку (aria-invalid с сервера, 15.09.2026). */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--bad) !important; box-shadow: 0 0 0 2px var(--bad-bg);
}
.subj-line .subj-on { border-color: var(--ok, #3f9d4f); }
.subj-line .subj-off { opacity: .65; border-style: dashed; }

/* ─────────── Сетка 2.0 AVRORA: месячный и недельный виды (Этап 10) ───────────
   Группы РЯДОМ колонками, как в боевой таблице «Расписание 25\26»
   (владелец, 01.09.2026); листается вбок при нехватке ширины. Недельный
   вид — те же колонки, но шире художкиных: в строках дня живут формы. */
.hybrid-grid { display: flex; gap: 12px; overflow-x: auto; align-items: flex-start; padding-bottom: 8px; }
.hg-group {
  flex: 0 0 380px; min-width: 380px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); padding: 10px 12px;
}
/* Недельный вид — тот же месяц, отфильтрованный до недели: колонки той же
   ширины и раскладки (владелец, 01.09.2026: «по факту это просто фильтр»). */
/* Цветная полоска группы — то же правило groupHueClass, что карточки недели. */
.hg-group.g-blue0 { border-top: 4px solid #3f83d9; }
.hg-group.g-blue1 { border-top: 4px solid #2b9d9d; }
.hg-group.g-blue2 { border-top: 4px solid #5a6fd9; }
.hg-group.g-warm0 { border-top: 4px solid #6fa832; }
.hg-group.g-warm1 { border-top: 4px solid #d9884f; }
.hg-group.g-warm2 { border-top: 4px solid #d94f4f; }
.hg-group.g-warm3 { border-top: 4px solid #c9a227; }
.hg-group.g-summer { border-top: 4px solid #d05f9b; }
/* Шапка колонки ОДНОЙ строкой: чип группы · старт · «предв.» · ⚙ (владелец,
   01.09.2026: код филиала убран — он уже в названии группы). */
.hg-group-title { margin: 0 0 4px; font-size: 14px; display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; white-space: nowrap; }
.hg-group-title .chip { overflow: hidden; text-overflow: ellipsis; }
.hg-group-title .mini-badge.prelim { flex: none; }
.date-clear { margin-left: 3px; padding: 0 6px; font-size: 13px; line-height: 1.3; }
/* ⓘ у подсказки: причина рекомендации во всплывающей подсказке. */
.hg-info { display: inline-block; margin-left: 4px; font-size: 11px; color: var(--muted); cursor: help; border: 1px solid var(--line); border-radius: 999px; width: 1.2em; height: 1.2em; line-height: 1.2em; text-align: center; }
.hg-group-title .chip a { color: inherit; text-decoration: none; }
.hg-gear { padding: 0 7px; font-size: 13px; }
/* План в шапке по умолчанию СВЁРНУТ (владелец, 01.09.2026). */
.hg-plan-fold summary { cursor: pointer; font-size: 12.5px; color: var(--muted); }
.hg-plan-list { margin: 4px 0; padding-left: 18px; font-size: 12.5px; }
.hg-kinds { font-size: 12.5px; margin: 4px 0; }
.hg-day { border-top: 1px solid var(--line); padding: 6px 0 8px; }
.hg-day.is-cancelled { opacity: .65; }
.hg-day-head { font-size: 13px; }
.hg-day-head a { color: var(--ink); text-decoration: none; }
.hg-day-head a:hover { color: var(--accent); }
.hg-row { font-size: 12.5px; margin: 3px 0; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.hg-row-form select { max-width: 170px; font-size: 12.5px; }
.hg-row-form select[data-teacher-select] { max-width: 140px; }
.hg-row-form input { max-width: 130px; font-size: 12.5px; }
.hg-row-form button { font-size: 12px; padding: 2px 8px; }
/* Подсказка месяца: предзаполненная строка подсвечена, пока не записана. */
.hg-suggested { background: var(--warn-bg); border-radius: 6px; padding: 2px 4px; }
.hg-hint { white-space: nowrap; }
.hg-photo { font-size: 13px; }
.hg-photo-wrap { margin: 3px 0; }
.hg-pro { border-top: 1px dashed var(--line); margin-top: 6px; padding-top: 6px; font-size: 12.5px; }
.hg-add-next { color: var(--accent); }
/* Попапы справочников — системные <dialog> со стилями системы. */
.hg-dialog { border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); max-width: 560px; padding: 16px 18px; }
.hg-dialog::backdrop { background: rgba(0, 0, 0, .45); }
.hg-dialog h3 { margin-top: 0; }
.hg-dialog label { display: block; font-size: 12.5px; color: var(--muted); margin-top: 8px; }
.hg-dialog input, .hg-dialog select { width: 100%; box-sizing: border-box; }
.hg-dialog .inline-form input { width: auto; }
/* Окно, открытое СЕРВЕРОМ (<dialog open>, работа без скрипта), стоит в
   потоке карточки обычным блоком; с живым скриптом то же окно открывается
   модально поверх затемнения (0073, пересборка графика). */
.hg-dialog:not(:modal) { position: static; margin: 12px 0; max-width: none; }
.rebuild-dialog { max-width: 960px; }
.rebuild-opener { font-size: 13px; font-weight: normal; margin-left: 10px; padding: 5px 11px; vertical-align: middle; }
.rebuild-credits { margin: 10px 0; }
.hg-subjects-set { border: 1px solid var(--line); border-radius: 8px; margin-top: 10px; }
.hg-subjects-set .checkline { padding: 2px 0; font-size: 13px; }
.hg-subj-list { list-style: none; padding: 0; margin: 6px 0; font-size: 13px; }
.hg-subj-list li { padding: 2px 0; }
.hg-slot-row input { max-width: 90px; }
/* Телефон: колонки во всю ширину, листание вниз. */
@media (max-width: 700px) {
  .hybrid-grid { flex-direction: column; overflow-x: visible; }
  .hg-group { min-width: 0; flex-basis: auto; }
  .hybrid-grid[data-view="week"] .hg-group { min-width: 0; flex-basis: auto; }
}

/* Дни группы таблицей «Число · Время · Предмет · Педагог» (показ
   владельца 01.09.2026 — как строки боевой таблицы). */
/* Раскладка фиксирована: селект с длинным пунктом иначе распирает свою
   колонку и выталкивает педагога за край карточки (скриншот 01.09.2026);
   при table-layout: fixed селекты ужимаются в ячейку, текст режется. */
.hg-days { width: 100%; border-collapse: collapse; font-size: 12.5px; table-layout: fixed; }
.hg-days th.hg-c-subj { width: 45%; }
.hg-days th { text-align: left; font-size: 11.5px; color: var(--muted); padding: 4px 6px 2px 0; border-bottom: 1px solid var(--line); }
.hg-days td { padding: 3px 4px 3px 0; vertical-align: top; }
.hg-dayblock { border-top: 1px solid var(--line); }
.hg-dayblock tr:first-child td { padding-top: 7px; }
.hg-c-when { white-space: nowrap; width: 6.8em; line-height: 1.3; }
.hg-c-when a { color: var(--ink); text-decoration: none; }
.hg-c-when a:hover { color: var(--accent); }
.hg-c-when .muted { font-size: 11.5px; }
/* Место сборного или совместного дня — с переносом: одной строкой оно
   вылезало из узкой колонки поверх соседней ячейки (12.10.2026). */
.hg-c-when .hg-when-place { white-space: normal; }
.hg-c-subj select, .hg-c-teach select { max-width: 100%; width: 100%; min-width: 0; font-size: 12.5px; }
.hg-c-subj .hg-hint { margin-top: 0; }
.hg-c-teach form.hg-row-form { display: inline; }
.hg-c-form form.hg-row-form { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
/* «Как в таблице по onEdit»: при JS кнопки записи скрыты — запись идёт по
   изменению поля; без JS кнопка остаётся и форма живёт. */
.js .hg-autosave-btn { display: none; }
.hg-start-form { display: inline; }
.hg-start-form input[type="date"] { font-size: 12px; padding: 1px 4px; width: 9.6em; }
.hg-start-form .date-clear { padding: 0 4px; font-size: 12px; }
.hg-badges td { font-size: 11.5px; padding-top: 0; }
.hg-roster-row td { padding: 0 0 6px; }
/* План группы таблицей «предмет · дано · план» с правкой часов. */
.hg-plan-table { border-collapse: collapse; font-size: 12.5px; margin: 6px 0; }
.hg-plan-table th, .hg-plan-table td { text-align: left; padding: 2px 10px 2px 0; }
.hg-plan-table .num { text-align: right; }
.hg-plan-table input { max-width: 4.5em; text-align: right; }
.hg-plan-total td { border-top: 1px solid var(--line); font-weight: 600; }
.hg-plan-total [data-plan-left] { font-weight: 400; font-size: 11.5px; white-space: nowrap; }
.hg-plan-off td:first-child { color: var(--muted); }
.hg-plan-kind td:first-child { font-style: italic; }
/* Кнопки-глазики видимости групп в шапке сетки — все в ряд
   (владелец, 01.09.2026); скрытая — перечёркнутый глаз, приглушена. */
.hg-eyes { display: flex; gap: 6px; flex-wrap: wrap; margin: 4px 0 8px; flex-basis: 100%; width: 100%; }
.hg-eye {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; padding: 3px 9px;
  border-radius: 999px; border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  cursor: pointer;
}
.hg-eye svg { flex: none; }
.hg-eye.is-off { opacity: .55; border-style: dashed; }
/* Ссылка «журнал» в сводке состава дня сетки AVRORA (владелец, 15.09.2026). */
.hg-journal { margin-left: 8px; font-size: 12px; font-weight: 400; white-space: nowrap; }
.hg-eye.is-off span { text-decoration: line-through; }
/* Значок «копия» расписания (владелец, 13.09.2026): у дня — мелкий рядом с
   датой, у всего периода — чип в ряду глазиков; «✓» на время после клика. */
.hg-copy { display: inline-flex; align-items: center; margin-left: 5px; padding: 0 3px; border: 0; background: none; color: var(--muted); cursor: pointer; vertical-align: middle; }
.hg-copy:hover, .hg-copy-all:hover { color: var(--accent); }
.hg-copy.is-copied, .hg-copy-all.is-copied { color: var(--ok, #2e7d32); }
.hg-copy.is-copied::after, .hg-copy-all.is-copied::after { content: '✓'; font-size: 11px; margin-left: 2px; }
/* Поделить день между двумя педагогами — складной блок под строками дня. */
.hg-split-row td { padding: 0 0 6px; }
.hg-split summary { font-size: 11.5px; color: var(--muted); cursor: pointer; }
.hg-split-form { padding: 4px 0 0 6px; }
.hg-split-part { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 3px 0; }
.hg-split-part select { max-width: 150px; font-size: 12.5px; }

/* Дополнительный день сверх расписания (0102) — складной блок под днями
   колонки недельной группы; половина дня помечается той же меткой, что
   день, с приставкой. */
.hg-extra { border-top: 1px dashed var(--line); margin-top: 6px; padding-top: 6px; font-size: 12.5px; }
.hg-extra summary { cursor: pointer; color: var(--muted); font-size: 12px; }
.hg-extra-form { padding: 4px 0 0 4px; }
.hg-extra-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; margin: 4px 0; }
.hg-extra-field { display: inline-flex; flex-direction: column; gap: 2px; font-size: 11.5px; color: var(--muted); }
.hg-extra-field select, .hg-extra-field input { font-size: 12.5px; max-width: 170px; }
.hg-extra-size label { display: block; margin: 2px 0; }
.mini-badge.extra-day { background: var(--accent-bg, var(--warn-bg)); color: var(--accent); }
/* Чипы групп перетаскиваются «как в Trello» (0096). */
.hg-chip { display: inline-flex; }
.hg-chip[draggable="true"] { cursor: grab; }
.hg-chip.is-dragging { opacity: .45; }
/* Скрытые группы — одним выпадающим списком (владелец, 12.09.2026). */
.hg-eyes-hidden { position: relative; }
.hg-eyes-hidden > summary { list-style: none; }
.hg-eyes-hidden > summary::-webkit-details-marker { display: none; }
.hg-eyes-hidden > summary span { text-decoration: none; }
.hg-eyes-hidden-list {
  position: absolute; z-index: 5; top: calc(100% + 4px); left: 0; min-width: 220px;
  display: flex; flex-direction: column; gap: 4px; padding: 8px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
}
.hg-eyes-hidden-list .hg-eye { width: 100%; justify-content: flex-start; }
a.hg-eye.hg-nav { text-decoration: none; font-weight: 600; }
.hg-hintline { display: flex; align-items: center; gap: 4px; max-width: 100%; margin-top: 2px; }
.hg-hintline .mini-badge { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.hg-roster-list { list-style: none; margin: 4px 0; padding: 0; font-size: 12.5px; }
.hg-roster-list li { padding: 1px 0; }
/* Крестик строки плана и строка «+» внизу. */
.hg-plan-x { width: 1.6em; }
.hg-plan-x button { padding: 0 6px; font-size: 13px; line-height: 1.4; }
.hg-plan-add select { max-width: 11em; font-size: 12px; }

/* Этап 11: «+ пробное» под карточкой занятия и строки ожидаемых в журнале */
.cell-actions { margin: -4px 0 10px; display: flex; gap: 8px; justify-content: flex-end; align-items: center; flex-wrap: wrap; }
/* Заметка руководителя к занятию (0094): видна всем в карточке; форма —
   руководству под карточкой. */
/* Заметка педагогу об ученике (0095): текст под ФИО всем, поле по месту —
   руководству; правка по изменению без кнопки (data-autosave). */
.stu-note-text { color: var(--ink); background: var(--warn-bg, #fff4d6); border-radius: 5px; padding: 1px 6px; display: inline-block; margin-top: 2px; }
.stu-note input { width: 100%; max-width: 100%; font-size: 12px; padding: 2px 6px; margin-top: 3px; box-sizing: border-box; }
.stu-note-form { display: inline; }
.js .stu-note-form { display: none; }
.lesson-card[data-href] { cursor: pointer; }
.lesson-card .lesson-link { color: inherit; text-decoration: none; }
/* Переходное расписание — мельче, чтобы помещалось (владелец, 12.09.2026). */
.mode-transitional { font-size: 11px; color: var(--muted); }
.cell-actions .mini { padding: 2px 10px; font-size: 12px; text-decoration: none; }
.expected-row .stu-fio { opacity: 0.9; }
.lead-trial-chip { display: inline-block; padding: 2px 8px; border-radius: 6px; background: rgba(46, 160, 67, 0.16); font-weight: 600; }
.lead-note { width: 100%; max-width: 22em; }

/* ── «Печатные формы» — ГРУППЫ ПЛИТОК (владелец, 11.10.2026, ночь:
   «сгруппировать и сделать в виде плиток, а не на всю ширину страницы»).
   Плитки одной строки — одной высоты, кнопки — внизу плитки. Плитка с
   формой или длинной инструкцией — <details>: свёрнутая стоит в ряду,
   раскрытая встаёт во всю ширину группы. Узкий экран — одна колонка без
   выхода за край (min(100%, …)). ── */
.paper-group { margin: 0 0 22px; }
.paper-group > h2 { margin: 0 0 6px; }
.paper-group > .sub { margin: 0 0 10px; }
.paper-tiles { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.paper-tile {
  display: flex; flex-direction: column; gap: 8px; min-width: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 14px 16px;
}
.paper-tile h3 { margin: 0; font-size: 16px; line-height: 1.3; }
.paper-tile p, .paper-tile ol { margin: 0; }
.paper-tile > .paper-buttons, .paper-tile summary > .paper-buttons { margin-top: auto; }
.paper-tile .hint { margin: 0; }
details.paper-tile > summary {
  display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto;
  cursor: pointer; list-style: none;
}
details.paper-tile > summary::-webkit-details-marker { display: none; }
details.paper-tile > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
details.paper-tile[open] { grid-column: 1 / -1; }
details.paper-tile[open] > summary { flex: 0 0 auto; }
.paper-tile .paper-tile-text { display: block; }
details.paper-tile .when-open, details.paper-tile[open] .when-closed { display: none; }
details.paper-tile[open] .when-open { display: inline; }

/* ── Бумаги договора — ТАБЛИЦА «что · состояние · действие» (проект
   «Карточка договора — Что делаем?», ответы 66–70 от 23.09.2026; раньше —
   строки 03.09.2026 «сэкономить место, оставить функционал»): кнопки печати
   одной строкой над таблицей, кнопка «Отметить …» стоит сразу за
   состоянием, а не у правого края — таблица не тянется на всю ширину. ── */
.papers .paper-buttons { margin: 0 0 8px; }
.papers table.pt { width: auto; max-width: 100%; margin: 4px 0 6px; }
.papers .pt th { position: static; }
.papers .pt td { vertical-align: middle; }
.papers .pt td:first-child, .papers .pt td.act { white-space: nowrap; }
.papers .pt td.act .inline-form { margin: 0; }
.papers .pt td.act input[type='date'] { max-width: 150px; width: auto; }
.papers .pt td.act input[name='reason'] { width: auto; }
.papers .paper-revoked { white-space: normal; }
.papers .appendix-reprint { margin: 0 0 8px; }

/* ── Всплывающие сообщения (владелец, 03.09.2026, как в KOMOD): отказ — по
   центру поверх затемнения с кнопкой «Понятно», успех — полосой внизу,
   гаснет сам. Серверный блок остаётся на странице как запись. ── */
dialog.notice-dialog {
  border: 1px solid var(--bad); border-radius: 10px; background: var(--surface);
  color: var(--ink); padding: 18px 20px; max-width: 540px; box-shadow: var(--shadow);
}
dialog.notice-dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog.notice-dialog .notice-body { color: var(--bad); margin-bottom: 14px; }
dialog.notice-dialog.ok .notice-body { color: var(--ok); }
/* Способ расчёта отпуска (0071): два радио с пояснениями строками. */
.settlement-choice { border: 1px solid var(--line, #ccc); border-radius: 7px; padding: 8px 12px; margin-top: 8px; }
.settlement-choice legend { padding: 0 6px; font-weight: 600; }
.settlement-choice label { display: block; margin: 4px 0; }
.settlement-choice input[type="radio"] { margin-right: 6px; }
dialog.notice-dialog .notice-body h3 { margin: 0 0 6px; color: inherit; }
dialog.notice-dialog .notice-body ul { margin: 5px 0 0 18px; padding: 0; }
dialog.notice-dialog .notice-body li { margin: 3px 0; }
dialog.notice-dialog .btnrow { display: flex; gap: 8px; justify-content: flex-end; }
dialog.notice-dialog.ok { border-color: var(--ok); }
/* Тихий успех — окном по центру без затемнения, гаснет сам (16.09.2026). */
dialog.notice-dialog.toast {
  position: fixed; top: 45%; left: 50%; transform: translate(-50%, -50%); margin: 0;
  z-index: 60; cursor: pointer; animation: notice-in .2s ease-out;
}
dialog.notice-dialog.toast.gone { opacity: 0; transition: opacity .3s; }
.notice-strip {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%);
  max-width: min(720px, calc(100vw - 32px)); z-index: 60; box-sizing: border-box;
  display: flex; align-items: center; gap: 12px;
  background: var(--ok-bg); border: 1px solid var(--ok); color: var(--ok);
  border-radius: 9px; padding: 10px 14px; box-shadow: var(--shadow);
  animation: notice-in .2s ease-out; cursor: pointer;
}
.notice-strip.gone { opacity: 0; transition: opacity .3s; }
.notice-strip button { flex-shrink: 0; }
@keyframes notice-in {
  from { opacity: 0; transform: translate(-50%, 8px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* ── «Промокоды и агенты»: без inline-стилей — CSP их отбрасывает
   (аудит 03.09.2026, находка 8). ── */
.promo-second { margin-top: 6px; }
.promo-note { max-width: 24em; }
.promo-reason { max-width: 20em; }
.promo-pending { margin-top: 10px; }

/* Предпросмотр начислений по педагогам (08.09.2026): заголовок человека
   с итогом строк под ним и общий итог таблицы. */
.schedule-grid tr.subhead th { text-align: left; background: #f3f4f6; }
.schedule-grid tr.subhead th.num,
.schedule-grid tr.total th.num { text-align: right; }
.schedule-grid tr.total th { text-align: left; border-top: 2px solid #d1d5db; }

/* «Принял договор» под шапкой карточки (0088): ОДНА flex-строка с
   переносом — принявший · доля · второй · новый/старый · «Сохранить»
   (проект «Что делаем?», экран 1); на телефоне переносится. Рамка — как у
   карточки, но ниже: это строка шапки, а не раздел. */
.signer-line {
  margin: 6px 0 12px; display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center;
  padding: 8px 12px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface); font-size: 13px;
}
.signer-line .signer-form { display: inline-flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; }
.signer-line select { width: auto; max-width: 18em; padding: 4px 8px; font-size: 13px; }
.signer-line .signer-form button { padding: 4px 10px; font-size: 12.5px; }

/* ── Реквизиты договора — одна карточка в две колонки (экран 1):
   подпись мелким блеклым, значение рядом; на телефоне — столбиком. ── */
.req th {
  width: 1%; white-space: nowrap; color: var(--muted); font-weight: 500; font-size: 12.5px;
  padding-right: 12px; position: static;
}
.req td { padding-right: 18px; }
@media (max-width: 760px) {
  .req th, .req td { display: block; padding: 2px 0; border-bottom: none; }
  .req td { margin-bottom: 6px; }
}

/* ── «Что делаем?» — строка вкладок в трёх группах (ответы 66–68, макет
   экраны 1–2). Вкладка — ссылка `?tab=…` (работает без скрипта), панель
   под строкой ровно одна; выбранная — цвет акцента и полоска сверху,
   «Прекратить» — цвет опасной операции. На телефоне с живым скриптом строку
   заменяет выпадающий список с теми же группами. Цвета — токены темы,
   тёмная тема через те же переменные. ── */
.what { margin: 0 0 14px; }
.what-tabs {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 4px;
  padding: 0 4px; border-bottom: 1px solid var(--line);
}
.what-tabs .q-label { align-self: center; font-weight: 700; padding: 0 10px 6px 4px; }
.what-tabs .grp {
  align-self: center; color: var(--muted); font-size: 11.5px; text-transform: uppercase;
  letter-spacing: .06em; padding: 0 6px 6px 8px; border-left: 1px solid var(--line); margin-left: 6px;
}
.what-tabs .tab {
  display: inline-block; padding: 6px 11px; border: 1px solid var(--line); border-bottom: none;
  border-radius: 8px 8px 0 0; background: var(--surface-2); color: var(--ink);
  font-size: 13px; margin-bottom: -1px; text-decoration: none; white-space: nowrap;
}
.what-tabs .tab:hover { border-color: var(--accent-line); }
.what-tabs .tab.on {
  background: var(--surface); border-color: var(--accent-line); border-bottom: 1px solid var(--surface);
  color: var(--accent); font-weight: 600; box-shadow: inset 0 3px 0 var(--accent);
}
.what-tabs .tab.bad { color: var(--bad); }
.what-tabs .tab .count { color: var(--muted); font-weight: 400; font-size: 12px; }
.what-tabs .tab-none { margin-left: auto; color: var(--muted); border-style: dashed; font-size: 12.5px; }
.tabpanel {
  border: 1px solid var(--line); border-top: none; border-radius: 0 0 9px 9px;
  background: var(--surface); padding: 14px;
}
.tabs-hint {
  border: 1px dashed var(--line); border-top: none; border-radius: 0 0 9px 9px;
  padding: 8px 14px; color: var(--muted); font-size: 12.5px; background: var(--surface-2);
}
/* Блок внутри панели — прежний складной <details>, принудительно раскрытый:
   панель и есть выбор человека, вторая складка внутри неё лишняя. Заголовок
   складки остаётся заголовком панели, стрелка и клик сняты. */
.tabpanel > details.fold, .tabpanel > details.fold.card { border: 0; margin: 0; padding: 0; background: transparent; }
.tabpanel > details.fold > summary { pointer-events: none; cursor: default; padding: 0 0 10px; font-size: 15px; }
.tabpanel > details.fold > summary::before { display: none; }
.tabpanel > details.fold > .foldbody { padding: 0; }
/* Телефон: та же строка «Что делаем?», но рядами по группам — подпись
   группы занимает свою строку, вкладки под ней пилюлями с переносом.
   Выпадающий список снят 25.09.2026: на Android он раскрывался
   модальным списком радиокнопок на весь экран. */
@media (max-width: 700px) {
  .what-tabs { border-bottom: none; gap: 6px; padding: 0; }
  .what-tabs .q-label { flex-basis: 100%; padding: 0 0 2px; }
  .what-tabs .grp {
    flex-basis: 100%; border-left: none; margin: 4px 0 0; padding: 0 0 2px 2px;
  }
  .what-tabs .tab {
    border-bottom: 1px solid var(--line); border-radius: 999px; margin-bottom: 0;
    padding: 7px 12px; font-size: 13.5px; white-space: normal;
  }
  .what-tabs .tab.on { border-bottom-color: var(--accent); }
  .what-tabs .tab-none { margin-left: 0; }
  .what .tabpanel { border-radius: 9px; border-top: 1px solid var(--line); margin-top: 8px; }
  .what .tabs-hint { border-radius: 9px; border-top: 1px dashed var(--line); margin-top: 8px; }
}

/* ─── Подстановка ученика/представителя в форме договора (09.09.2026) ───
   Список кандидатов под полем: кнопки, не datalist — у кандидата две
   строки (ученик, представитель · договор · хвост телефона). */
.lookup-box { margin: 4px 0 8px; border: 1px solid var(--border, #d8d8d8); border-radius: 8px; background: var(--card, #fff); max-width: 36em; }
.lookup-box .lookup-item {
  display: block; width: 100%; text-align: left; padding: 6px 10px; border: 0; background: transparent;
  border-bottom: 1px solid var(--border, #eee); cursor: pointer; font: inherit; color: inherit;
}
.lookup-box .lookup-item:last-child { border-bottom: 0; }
.lookup-box .lookup-item:hover, .lookup-box .lookup-item:focus { background: var(--warn-bg, #fff6d6); outline: none; }
.lookup-box .lookup-sub { display: block; font-size: 12.5px; color: var(--muted); }
.lookup-box .lookup-note { padding: 6px 10px; font-size: 12.5px; color: var(--muted); }
.lookup-run { display: inline-block; margin: 4px 0 0; font-size: 12.5px; padding: 2px 8px; }

/* Деление занятия по урокам (владелец, 15.09.2026, макеты 1–2): номера
   уроков «с … по …» в одну строку, своя группа — подставленное поле. */
.inline-lessons { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.inline-lessons label { margin: 0; }
.inline-lessons select { width: 64px; }
input[readonly].auto { color: var(--muted); }
/* Режим семьи деления — строками (владелец, 16.09.2026: «в столбик, чтобы не занимать место»). */
.stu-mode, .mode-transitional { white-space: pre-line; }

/* ── Посещаемость (владелец, 16.09.2026): матрица «ученики × даты», клетка — кнопка окна отметки ── */
.att-matrix { border-collapse: collapse; font-size: 13px; }
.att-matrix th, .att-matrix td { border: 1px solid var(--line-soft); padding: 4px 6px; text-align: center; white-space: nowrap; }
.att-matrix th.fio, .att-matrix td.fio { text-align: left; min-width: 180px; }
.att-matrix th .wd { display: block; font-weight: 400; font-size: 11px; color: var(--muted); }
.att-matrix th .ev { display: block; font-weight: 400; font-size: 11px; color: var(--warn, #a0620a); }
.att-matrix td.att-cell { cursor: pointer; min-width: 44px; }
.att-matrix td.att-cell:hover, .att-matrix td.att-cell:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.att-matrix td.att-present { background: rgba(47, 158, 111, .16); }
.att-matrix td.att-absent { background: rgba(217, 79, 79, .14); }
.att-matrix td.future { color: var(--muted); }
.att-matrix td.cancelled, .att-matrix th.cancelled { color: var(--muted); background: repeating-linear-gradient(45deg, var(--line-soft), var(--line-soft) 4px, transparent 4px, transparent 8px); }
.att-matrix td.total { font-weight: 600; }
.att-matrix .badge-notice { display: block; font-size: 10px; color: var(--warn, #a0620a); }
.att-matrix .att-sub { font-size: 11px; }
.att-today-lesson { margin: 10px 0 14px; }
.att-today-lesson h3 { margin: 0 0 6px; font-size: 14px; }
.att-dialog { min-width: 300px; }
.att-dialog h3 { margin: 0 0 4px; }
.att-dialog .att-mark-form { margin: 8px 0 10px; }
.att-dialog .att-mark-form .mark-btn { flex: 1; padding: 9px 6px; font-size: 14px; }
.att-dialog .att-dialog-row { display: flex; gap: 12px; align-items: center; justify-content: space-between; }
:root[data-theme='dark'] .att-matrix td.att-present { background: rgba(47, 158, 111, .22); }
:root[data-theme='dark'] .att-matrix td.att-absent { background: rgba(217, 79, 79, .18); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .att-matrix td.att-present { background: rgba(47, 158, 111, .22); }
  :root:not([data-theme='light']) .att-matrix td.att-absent { background: rgba(217, 79, 79, .18); }
}

/* Описание «как подготовиться» под строкой предмета (0105, 16.09.2026). */
.hg-trow.hg-prep td.hg-prep-text { font-size: 12px; color: var(--muted); white-space: normal; padding-top: 0; }
.subject-prep { font-size: 12px; color: var(--muted); margin: 0 0 4px 12px; white-space: normal; }
.hg-prep-form { display: flex; gap: 6px; align-items: flex-start; margin: 4px 0 8px; }
.hg-prep-form textarea { flex: 1; min-width: 220px; font: inherit; font-size: 12.5px; }

/* Справочники (25.09.2026): оглавление разделов с числом строк; подсказки свёрнуты под «ⓘ». */
.catalog-contents { margin: 4px 0 12px; font-size: 14px; }
.catalog-contents a { margin-right: 2px; }
h2 .count { color: var(--muted); font-weight: 400; font-size: 13px; }

/* Справочники в попапах (26.09.2026): строка группы, меню «Действия ▾», окна правки. */
.catalog-row td { vertical-align: top; }
.catalog-row .sched { font-size: 13px; }
.catalog-row .sched .muted { font-size: 12px; }
details.actions { position: relative; display: inline-block; }
details.actions > summary { list-style: none; cursor: pointer; border: 1px solid var(--line); border-radius: 6px; padding: 4px 10px; font-size: 13px; background: var(--surface); white-space: nowrap; }
details.actions > summary::-webkit-details-marker { display: none; }
details.actions[open] > summary { border-color: var(--accent-line); }
details.actions .menu { position: absolute; right: 0; z-index: 20; min-width: 220px; margin-top: 4px; padding: 6px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); box-shadow: 0 6px 20px rgba(0, 0, 0, .12); display: flex; flex-direction: column; gap: 2px; }
details.actions .menu button, details.actions .menu a { text-align: left; background: none; border: 0; padding: 6px 8px; border-radius: 6px; font: inherit; color: var(--ink); cursor: pointer; text-decoration: none; }
details.actions .menu button:hover, details.actions .menu a:hover { background: var(--accent-bg, rgba(0, 0, 0, .05)); }
details.actions .menu form { display: contents; }
details.actions .menu .danger { color: var(--danger, #b3261e); }
.catalog-dialog { max-width: 720px; width: min(720px, calc(100vw - 32px)); }
.catalog-dialog .inline-form { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: flex-end; }
.catalog-dialog .inline-form label { display: block; flex: 0 1 auto; margin: 0; }
.catalog-dialog .inline-form input, .catalog-dialog .inline-form select { width: auto; }
.catalog-dialog .inline-form button { margin-top: 4px; }
.catalog-dialog .refusal { margin-top: 10px; }
.catalog-dialog .card.preview { margin-top: 10px; }
.catalog-dialog .dialog-close { position: absolute; top: 8px; right: 10px; }
.catalog-dialog table.season-prices td, .catalog-dialog table.season-prices th { padding: 3px 6px; font-size: 13px; }
.catalog-dialog table.season-prices input { width: 7em; }
.course-card { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) auto; gap: 8px 16px; align-items: start; padding: 10px 0; border-top: 1px solid var(--line); }
.course-card:first-of-type { border-top: 0; }
.course-card .prices .inline-form { margin: 2px 0; }
.course-card .drill summary { cursor: pointer; font-size: 13px; color: var(--accent); }
.course-card .drill ul { margin: 4px 0 6px 16px; padding: 0; font-size: 13px; }
@media (max-width: 720px) { .course-card { grid-template-columns: 1fr; } }

/* Компактные поля попапов «Справочников» — ширина КЛАССОМ, не атрибутом
   style: CSP «style-src 'self'» инлайн-стили не применяет вовсе (браузер
   26.09.2026 насчитал 1 588 отказов на одной странице), и поле «минут»
   растягивалось на всю строку. На узком экране поля снова во всю ширину,
   как остальные (правило .inline-form выше). */
input.w4, select.w4 { max-width: 4em; }
input.w5, select.w5 { max-width: 5em; }
input.w6, select.w6 { max-width: 6em; }
input.w7, select.w7 { max-width: 7em; }
input.w8, select.w8 { max-width: 8em; }
input.w9, select.w9 { max-width: 9em; }
@media (max-width: 700px) {
  input.w4, select.w4, input.w5, select.w5, input.w6, select.w6, input.w7, select.w7, input.w8, select.w8, input.w9, select.w9 { max-width: none; }
}

/* Заявка владельцу: КРУПНО комментарий руководителя и описание договора
   (владелец, 04.10.2026, п. 5). */
.request-headline { background: var(--surface-2); border: 1px solid var(--line); border-radius: 9px; padding: 12px 16px; margin: 10px 0 12px; }
.request-comment { font-size: 18px; font-weight: 600; margin: 0 0 6px; }
.request-brief { margin: 0; font-size: 14px; }

/* Заявка сверх лимита месяца (0127) — строка с жёлтым фоном: решает владелец. */
tr.warn-row td { background: var(--warn-bg, #fff8e1); }


/* ───────── Пакет ЗП-2 (владелец, 05.10.2026): табы месяцев, плитки, ⓘ, поп-апы, колокольчик ───────── */
/* Табы месяцев с состоянием: на телефоне — горизонтальная прокрутка,
   а не перенос на три строки (владелец: «чтобы на андроиде нормально»). */
.month-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--line); margin: 0 0 12px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
.month-tabs .mtab {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; padding: 9px 14px;
  border: 1px solid transparent; border-bottom: 0; border-radius: 9px 9px 0 0;
  color: var(--muted); text-decoration: none; white-space: nowrap; font-weight: 500;
}
.month-tabs .mtab.active { border-color: var(--line); background: var(--surface); color: var(--ink); font-weight: 700; margin-bottom: -1px; }
.month-tabs .mtab:hover { color: var(--ink); }
.mini-badge.ok { background: var(--ok-bg); color: var(--ok); }
.mini-badge.warn { background: var(--warn-bg); color: var(--warn); }
/* Плитки как в Комоде: крупная сумма, подпись сверху, заметка снизу. */
.tile.warn { border-color: var(--warn); background: var(--warn-bg); }
.tile.warn .value { color: var(--warn); }
.tile.bad { border-color: var(--bad); background: var(--bad-bg); }
/* ⓘ у заголовка столбца и у плитки — в одну строку с заголовком, цветом;
   подсказка по наведению и по нажатию (tabindex — фокус на телефоне). */
.nw { white-space: nowrap; }
.info-i {
  display: inline-block; width: 16px; height: 16px; margin-left: 4px; border-radius: 50%;
  border: 1.5px solid var(--accent-text, var(--accent)); color: var(--accent-text, var(--accent)); font: 700 10px/13px system-ui, sans-serif;
  text-align: center; vertical-align: 1px; cursor: help; position: relative; font-style: normal;
}
/* Значок (i) — цветом ТЕКСТА акцента: фирменный голубой Авроры на белом давал
   2 : 1, «i» читалась хуже нормы (WCAG 1.4.3 / 1.4.11, окно «Этап 39 Аврора»,
   разбор макета плана показа). Место нажатия — 28 px вокруг значка 16 px
   (WCAG 2.5.8): прозрачная подложка ::before; ::after занята запасной подсказкой. */
.info-i::before { content: ''; position: absolute; inset: -6px; }
.info-i::after {
  content: attr(data-tip); position: absolute; left: 50%; top: 22px; transform: translateX(-50%);
  min-width: 220px; max-width: 320px; width: max-content; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font: 400 12.5px/1.4 inherit;
  text-align: left; white-space: normal; box-shadow: var(--shadow); z-index: 30; display: none;
}
.info-i:hover::after, .info-i:focus::after, .info-i:focus-visible::after { display: block; }
th .info-i::after { font-weight: 400; }
/* Панель кнопок: кнопки-попапы в ряд со вкладками, счётчик ожидающих — кружком. */
.tabs.toolbar { align-items: center; }
.tabs.toolbar button.tab { font: inherit; cursor: pointer; position: relative; }
.tabs .cnt, .iconbtn .cnt {
  display: inline-block; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink); font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
.iconbtn { position: relative; }
.iconbtn .cnt { position: absolute; top: -7px; right: -7px; }
/* Широкий поп-ап для таблиц; крестик в заголовке; инфо-блок как в Комоде. */
.hg-dialog.wide { max-width: min(960px, 96vw); width: 96vw; }
.hg-dialog h3 .dlg-x { float: right; color: var(--muted); text-decoration: none; font-weight: 400; padding: 0 4px; }
.hg-dialog h4 { margin: 14px 0 6px; font-size: 14px; }
.hg-dialog .inline-form input, .hg-dialog .inline-form select { width: auto; }
.hg-dialog .inline-form label { display: inline-block; margin: 0; }
.hg-dialog [aria-invalid="true"] { border-color: var(--bad); background: var(--bad-bg); }
.info { border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: 8px; padding: 10px 12px; font-size: 13px; background: var(--surface-2); margin-bottom: 10px; }
.info b { display: block; margin-bottom: 4px; }
/* Форма уборки одной-двумя строками (владелец, 05.10.2026). */
.compact-row { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: end; }
.compact-row label { display: inline-flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--muted); }
/* Снятая / исправленная позиция (0129). */
tr.fixed-row td { color: var(--muted); }
button.ghost.small { padding: 3px 9px; font-size: 12.5px; }
.net { display: inline-flex; align-items: center; gap: 5px; }
.net-ic { width: 18px; height: 18px; vertical-align: middle; }

/* «Моя зарплата» по структуре Комода (05.10.2026): громкое правило, плитка-кнопка, список ставок. */
.loud-rule h3 { margin: 0 0 6px; font-size: 17px; }
.loud-rule p { margin: 0; color: var(--ink); }
.tile.clickable { cursor: pointer; }
.tile.clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
ul.rates li { margin: 4px 0; }

/* ЗП-3 (06.10.2026): экраны зарплаты уже, чтобы читались; подсказки ⓘ не выходят за край; табы без вертикальной прокрутки. */
.narrow { max-width: 1240px; margin: 0 auto; }
.month-tabs { overflow-y: hidden; padding-bottom: 1px; }
.info-i::after { max-width: min(320px, 80vw); }
.tile .info-i::after { left: 0; transform: none; }
.tile:last-child .info-i::after, .tile.tip-left .info-i::after { left: auto; right: 0; transform: none; }
.tabs.toolbar.self-tools { margin: 6px 0 12px; }
h1 + .who-line { margin: -8px 0 10px; }
/* ЗП-4 (06.10.2026): плитка эффективности из двух полей; суммы в заголовках складок. */
.tile.tile-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.tile.tile-split .half + .half { border-left: 1px solid var(--line); padding-left: 14px; }
/* Плитка педагога на «Зарплате» (07.10.2026): ФИО — шапкой во всю
   ширину, под ним две половины; раньше ФИО занимало левую колонку, а
   половины ехали лесенкой. «мало данных» — не как число. */
.tile.tile-split .tile-head { grid-column: 1 / -1; font-weight: 600; margin-bottom: 8px; line-height: 1.25; }
.tiles.teachers { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.tiles.teachers .tile .value { font-size: 20px; }
.tiles.teachers .tile .value.small { font-size: 14px; font-weight: 600; color: var(--muted); }
.tiles.teachers .tile .note { white-space: normal; }
.tiles.two { grid-template-columns: repeat(2, minmax(180px, 1fr)); }
details.fold summary .sum { float: right; color: var(--muted); font-weight: 600; }
.row-summary { color: var(--muted); font-size: 12.5px; }
.tiles-title { font-size: 14px; margin: 4px 0 8px; color: var(--muted); }
.tile .month-switch { position: relative; z-index: 2; margin-top: 6px; font-size: 12.5px; }

/* «Ещё ждёт» строками как в Комоде (07.10.2026): главное крупно, сумма справа, расшифровка мелко.
   Без маркеров и отступа списка: строки разделяет линия (снимок 390 px, окно «Этап 37 Аврора»). */
.wait-list { list-style: none; margin: 6px 0; padding-left: 0; }
.wait-list li { padding: 6px 0; border-bottom: 1px solid var(--line); }
.wait-list li:last-child { border-bottom: 0; }
.wait-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; font-size: 14.5px; }
.wait-head .sum { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.wait-detail { font-size: 12.5px; margin-top: 2px; }
/* Смены администратора — как сложилась сумма (окно «Этап 37 Аврора»):
   подытог группы — справа от её заголовка, итог вычетов — своей строкой. */
.shifts-fold h4 { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; margin: 14px 0 4px; }
.shifts-fold h4 .sum { white-space: nowrap; font-variant-numeric: tabular-nums; }
.shift-total { display: flex; justify-content: space-between; gap: 10px; border-top: 1px solid var(--line); padding-top: 8px; margin-top: 8px; }
.shift-total strong { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Кнопка необратимого действия (удалить педагога, 07.10.2026). */
button.danger { color: var(--danger, #b3261e); border-color: var(--danger, #b3261e); }

/* Плитки групп на «Сегодня» (08.10.2026): загрузка по дням и выручка месяца. */
.tiles.groups { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.tile.group-load .label { font-size: 13.5px; color: var(--ink); font-weight: 600; margin-bottom: 6px; }
.tile.group-load .label a { color: inherit; text-decoration: none; }
.tile.group-load .load-day { display: flex; align-items: baseline; gap: 6px; font-variant-numeric: tabular-nums; line-height: 1.5; }
.tile.group-load .load-dayname { font-weight: 600; min-width: 2.2em; }
.tile.group-load .load-pct { font-weight: 700; margin-left: auto; }
.load-free { color: var(--ok); }
.load-mid { color: var(--warn); }
.load-high { color: #e07b1a; }
.tile.group-load .load-revenue { margin-top: 6px; white-space: normal; }
/* Филиал — своим блоком: заголовок с точкой цвета, полоса цвета слева у плиток (01.11.2026). */
.branch-block { --branch: var(--branch-1); margin-top: 10px; }
.branch-block[data-branch-tone="2"] { --branch: var(--branch-2); }
.branch-block[data-branch-tone="3"] { --branch: var(--branch-3); }
.branch-block .branch-title { font-size: 14px; margin: 8px 0 6px; display: flex; align-items: center; gap: 8px; }
.branch-block .branch-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--branch); flex: none; }
.branch-block .tile.group-load { border-left: 4px solid var(--branch); }
.tile.group-load .ind-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; font-size: 13px; }
.tile.group-load .ind-list a { color: var(--ink); }

/* Проверка купюр на приёме наличных (владелец, 08.10.2026): закреплённый
   блок справа от формы на ПК; на узком экране — обычная карточка. */
/* Правая колонка «Приёма наличных» закреплена целиком: купюры сверху видны всегда (владелец, 08.10.2026). */
/* Отступ сверху — ВЫСОТА ШАПКИ (`--top-h`): шапка сама закреплена, и колонка с
   отступом 12 px уходила под неё (владелец, 08.10.2026, ночь: «прокрутка не
   учитывает шапку и блок прячется под неё»). СВОЕЙ ПРОКРУТКИ У КОЛОНКИ НЕТ:
   колонка с overflow забирала колесо мыши, и страница под курсором не
   листалась — «для неподготовленного пользователя это зависший ПК». Колонка
   выше экрана дочитывается в конце страницы: там закрепление отпускает её. */
.cash-side { position: sticky; top: calc(var(--top-h) + 12px); }
.cash-check h3 { margin: 0 0 8px; font-size: 15px; }
.cash-check .banknotes { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.cash-check .banknote { max-width: 100%; height: auto; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,.18); }
.cash-check ul { margin: 0; padding-left: 18px; }
.cash-check li { margin: 2px 0; }
@media (max-width: 1000px) { .cash-side { position: static; } }

/* ─── ГАЛОЧКА — ПЕРЕД ТЕКСТОМ, КОТОРЫЙ ОНА УТВЕРЖДАЕТ, В ОДНОЙ СТРОКЕ ───
   Владелец, 09.10.2026: «галочка должна стоять перед тем текстом, который
   она утверждает; это правило, частая ошибка кода». Причина была одна на
   все экраны: общее правило полей `input { width: 100% }` растягивало и
   галочку, и кружок выбора на всю строку — галочка уезжала НАД текст, по
   центру, а в узкой форме (`.inline-form label` столбиком) — и того дальше.
   Здесь, в конце файла, правило перекрывает любой контекст: подпись с
   галочкой — строка «галочка, затем текст», текст переносится сам, галочка
   остаётся слева. Разметку (галочка ПЕРВОЙ в своей подписи) и это правило
   сторожит тест `apps/web/src/checkboxFirst.test.ts`. */
input[type="checkbox"], input[type="radio"] { width: auto; flex: none; padding: 0; margin: 0; }
/* `:not([hidden])` — спрятанная подпись остаётся спрятанной: `[hidden]` выше тоже
   с !important, и без исключения эта строка его бы перебила. */
label:not([hidden]):has(> input[type="checkbox"]), label:not([hidden]):has(> input[type="radio"]) {
  display: flex !important; flex-direction: row !important; align-items: baseline;
  gap: 7px; white-space: normal;
}

/* ─── СУММА — НА ОДНОЙ СТРОКЕ (владелец, 09.10.2026: «частая системная
   ошибка — перенос одной числовой суммы на две строки; правило: сумма
   должна быть на одной строке»). Сами пробелы суммы неразрывны с сервера
   (`keepAmountsTogether`, apps/web/src/html.ts — одно место вывода всех
   экранов). Здесь — место для неразрывной суммы: плитка «Уже выдано»
   делит сумму на части, и в узкой плитке части встают друг под друга, а не
   рвут число («41 / 800,00 ₽»). Малая сумма части — меньшим кеглем. */
.tile .value.small { font-size: 15px; font-weight: 600; }
.tile .value { overflow-wrap: normal; }
.tile.tile-parts { container-type: inline-size; }
.tile-parts .parts { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; margin-top: 8px; }
.tile-parts .part + .part { border-left: 1px solid var(--line); padding-left: 14px; }
@container (max-width: 250px) {
  .tile-parts .parts { grid-template-columns: 1fr; gap: 6px; }
  .tile-parts .part + .part { border-left: none; padding-left: 0; border-top: 1px solid var(--line); padding-top: 6px; }
}

/* ─── СБОРНЫЙ ДЕНЬ (0160): список по времени, группы блоками. Строка
   несёт несколько маленьких форм — время, макияж и причёска, «Пришёл»;
   на телефоне формы встают друг под друга, а не растягивают строку. */
.gathering-list tr.subhead td { background: var(--accent-bg, var(--warn-bg)); padding-top: 8px; }
.gathering-list form.inline { display: inline-flex; gap: 4px; align-items: center; flex-wrap: wrap; margin: 2px 0; }
.gathering-list input[type="time"] { max-width: 110px; }
/* Карточка ученика (0187) — шириной по названию подпроекта, а не по узкой
   колонке «Ученик»: общее правило `select { width: 100% }` сжимало поле до
   колонки, и на экране 1280 «Эмоциональный портрет в движении» читался
   «…портрет в движен» (окно 37, снимок базы знаний). Таблица и так
   прокручивается внутри себя на телефоне. */
.gathering-list form.inline select[name="card"] { width: auto; max-width: 22em; }
/* Название подпроекта в справочнике — та же длина, что видит родитель: общее
   `.inline-form input { max-width: 190px }` показывало «Эмоциональный порт…». */
.subprojects .inline-form input[name="name"] { max-width: 22em; width: 22em; }
/* «Карточки на картах» (0199): адрес карточки — одно длинное «слово», и на
   ширине телефона он уходил за край карточки; переносится в любом месте. */
.map-cards .url-text { overflow-wrap: anywhere; }
/* Строка QR-кодов под п. 3.1 (0203; владелец, 02.11.2026, ответы 70 а и 71 а) —
   та же разметка, что на листе «Согласие» (`qrCodesHtml`), в размере экрана:
   код 96 px — камера телефона берёт его с монитора; подпись под кодом. */
.map-cards-qr .tp-qr-row { display: flex; flex-wrap: wrap; gap: 12px 16px; margin: 4px 0 8px; }
.map-cards-qr .tp-qr-item, .map-cards-qr .tp-qr { display: block; width: 140px; text-align: center; font-size: 12.5px; line-height: 1.25; }
.map-cards-qr svg { display: block; width: 96px; height: 96px; margin: 0 auto 4px; }
.map-cards-qr .tp-qr-cap { display: block; overflow-wrap: anywhere; }
button.primary.small { padding: 3px 9px; font-size: 12.5px; }
/* Шаги возврата во всплывающей ⓘ (владелец, 14.10.2026: «всплывающим окном
   с эмодзи по шагам»): строки шагов — с новой строки, окно шире обычного. */
.info-i.steps::after { white-space: pre-line; min-width: min(300px, 80vw); max-width: min(460px, 90vw); }
summary .info-i.steps::after { left: 0; transform: none; }
/* ── ВСПЛЫВАЮЩЕЕ НЕ ВЫХОДИТ ЗА ЭКРАН (владелец, 15.10.2026: «в экране
   возвраты (i) всплывающее окно выходит за экран, это частая ошибка…»).
   Подсказку ⓘ ставит app.js (`initTips` → `placeFloating`): одна плавающая
   подсказка у значка, по ширине — в пределах экрана с полем 8 px, вниз не
   помещается — вверх. Пока работает сценарий, прежняя `::after`
   выключена (`tips-js` на <html>); без сценария она — запасной путь. */
.tips-js .info-i::after { display: none !important; }
.tip-pop {
  position: fixed; z-index: 70; box-sizing: border-box;
  max-width: min(320px, calc(100vw - 16px));
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 10px; font-family: inherit; font-size: 12.5px; font-weight: 400; line-height: 1.4;
  text-align: left; white-space: normal; overflow-wrap: anywhere; box-shadow: var(--shadow);
}
.tip-pop.steps { white-space: pre-line; max-width: min(460px, calc(100vw - 16px)); }
.tip-pop[hidden] { display: none; }
/* Запасной путь без сценария — тоже не шире экрана. */
.info-i::after { max-width: min(320px, calc(100vw - 16px)); }
.info-i.steps::after { max-width: min(460px, calc(100vw - 16px)); }

/* База знаний (владелец, 15.10.2026): шаги — нумерованным списком с
   воздухом, надписи экрана — жирным (`knowledgeBase.ts`). */
.kb-steps li,
.kb-notes li { margin: 6px 0; line-height: 1.45; }
.kb-toc ol { margin: 0; padding-left: 22px; }
.kb h2 { margin-bottom: 4px; }
/* Снимки экранов к шагам (17.10.2026) — по ширине карточки, крупно по нажатию. */
.kb-shot { margin: 10px 0 14px; }
.kb-shot img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px; }
.kb-shot figcaption { margin-top: 4px; font-size: 12.5px; color: var(--muted); }
/* Файлы для пересылки клиенту (макет футболки, 26.10.2026): по строке на файл,
   ссылка — во всю строку и не ниже 44 px, чтобы попасть пальцем на телефоне. */
.kb-files { list-style: none; margin: 8px 0 10px; padding: 0; display: grid; gap: 6px; }
.kb-files a { display: flex; align-items: center; min-height: 44px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 8px; text-decoration: none; }
.kb-files a:hover, .kb-files a:focus-visible { border-color: var(--accent); }
.kb-legend .kb-press { color: #c2185b; }
.kb-legend .kb-read { color: #1565c0; }
.kb-legend .kb-dont { color: #c62828; }
/* Готовый текст для клиента (объявление о форме AVRORA): как есть, с переносами строк. */
.kb-quote { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 8px; }
.kb-quote h3 { margin: 0 0 6px; font-size: 15px; }
.kb-quote pre { white-space: pre-wrap; word-break: break-word; font: inherit; line-height: 1.45; margin: 0;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }

/* ── Выбор фото с фотопроекта (0171): ЛК родителя и выбор с планшета ── */
.lk { max-width: 1100px; margin: 0 auto; padding: 0 12px 32px; }
.lk-head h1 { margin: 12px 0 2px; font-size: 22px; }
.lk-head p { margin: 0 0 12px; }
.lk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin: 12px 0; }
.lk-shot { margin: 0; background: var(--surface); border: 2px solid var(--line); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; }
.lk-shot img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; background: var(--surface-2); }
/* Карточка «в движении» (0187): превью выше — 2:3, как кадр на листе, поза не срезается и при выборе. */
.lk-grid-motion .lk-shot img { aspect-ratio: 2 / 3; }
/* Просмотрщик руководства (окно 37): заголовки дней и учеников — строками во
   всю ширину общей сетки (галерея листает подряд); кадр в клетке — целиком,
   а не обрезанным: руководство смотрит кадры, а не выбирает их. */
.viewer-grid > .viewer-head { grid-column: 1 / -1; margin: 14px 0 0; }
.viewer-grid > h3.viewer-head { font-size: 15px; margin-top: 8px; }
.viewer-grid .lk-shot img { object-fit: contain; }
.lk-shot figcaption { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 6px; padding: 4px 8px; font-size: 12px; color: var(--muted); }
/* Узкая плитка телефона: имя файла — в строку с многоточием, отметка выбора — следом, а не за краем. */
.lk-shot figcaption > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lk-shot.picked-free { border-color: var(--ok); }
.lk-shot.picked-paid { border-color: var(--accent); }
.lk-badge { font-weight: 600; white-space: nowrap; }
.lk-badge.free { color: var(--ok); }
.lk-badge.paid { color: var(--accent-text, var(--accent)); }
.lk-actions { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 6px 8px; margin-top: auto; }
.lk-inline { display: inline; margin: 0; }
.lk-sum { white-space: nowrap; }
.lk-qr { max-width: 260px; margin: 8px 0; background: #ffffff; padding: 8px; border-radius: 8px; }
.lk-qr svg { display: block; width: 100%; height: auto; }
.lk-collage img { display: block; max-width: 320px; width: 100%; height: auto; border: 1px solid var(--line); }
.lk-order-cancelled { opacity: .65; }
.lk-uniform summary, .lk-reviews summary { cursor: pointer; font-weight: 600; }
/* Фото футболки в блоке о форме (владелец, 21.10.2026): макет и вышивка «Комода» рядом, на телефоне — друг под другом. */
.lk-uniform-photos { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin: 10px 0; }
.lk-uniform-photo { margin: 0; }
.lk-uniform-photo img { display: block; width: 100%; height: auto; border-radius: 8px; border: 1px solid var(--line); }
.lk-uniform-photo figcaption { font-size: 12.5px; color: var(--muted); margin-top: 4px; }
/* ЛК родителя глазами навыков дизайна (README-35 §16.2). Кнопки и складки — не ниже 44 px: норма
   пальца (WCAG 2.5.5), 27 px давали промахи (ЛК-3). Кнопки кадра — во всю ширину карточки, по одной
   в строку: на телефоне карточка в 170 px, и две кнопки рядом не помещались. */
.lk button, .lk a.button-like, .lk a.ghost { min-height: 44px; }
.lk summary { min-height: 44px; display: flex; align-items: center; gap: 6px; }
.lk-actions { flex-direction: column; align-items: stretch; gap: 6px; }
.lk-actions .lk-inline { display: block; }
.lk-actions button, .lk-actions a.button-like { width: 100%; text-align: center; }
.lk a.button-like { display: inline-flex; align-items: center; justify-content: center; }
/* Фото готовится к скачиванию (0178): состояние словами на месте кнопки «Скачать» — той же высоты,
   чтобы карточка не прыгала, когда кнопка появится. */
.lk-wait { display: flex; align-items: center; justify-content: center; min-height: 44px; font-size: 14px; color: var(--muted); text-align: center; }
.lk-wait.warn-inline { color: var(--warn); }
.lk-wait-card { border-color: var(--accent-line); }
/* Место в коллаже — две стрелки в одну строку (владелец, 21.10.2026). */
.lk-move { display: flex; gap: 6px; }
.lk-move .lk-inline { flex: 1 1 0; }
.lk-move button.small { font-size: 22px; line-height: 1; }
/* Фильтр «Все / Выбранные / К покупке» над фото (владелец, 21.10.2026) — одной строкой из трёх
   сегментов: на телефоне 360 px помещается целиком. */
.lk-filter { display: flex; flex-wrap: wrap; margin: 12px 0 0; }
.lk-filter button { flex: 1 1 auto; min-width: 0; padding: 0 8px; font-size: 15px; white-space: nowrap; border-radius: 0; }
.lk-filter button + button { margin-left: -1px; }
.lk-filter button:first-child { border-radius: 8px 0 0 8px; }
.lk-filter button:last-child { border-radius: 0 8px 8px 0; }
.lk-filter button[aria-pressed='true'] { position: relative; background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
.lk-count { opacity: .75; }
/* Галерея во всплывающем окне (владелец, 21.10.2026: «в поп апе как галерея»): фото на тёмном,
   внизу — подпись и те же кнопки, что в карточке. */
dialog.lk-gallery {
  width: 100vw; max-width: 100vw; height: 100vh; height: 100dvh; max-height: 100dvh; margin: 0; padding: 0;
  border: 0; background: #111214; color: #fff; display: none; flex-direction: column;
}
dialog.lk-gallery[open] { display: flex; }
dialog.lk-gallery::backdrop { background: rgba(0, 0, 0, .85); }
.lk-gallery-top { display: flex; justify-content: space-between; align-items: center; padding: 6px 10px; }
.lk-gallery-counter { font-size: 14px; opacity: .85; }
.lk-gallery-close { min-width: 44px; min-height: 44px; background: transparent; color: #fff; border: 0; font-size: 24px; }
.lk-gallery-stage { position: relative; flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center; touch-action: pan-y; }
.lk-gallery-img { max-width: 100%; max-height: 100%; object-fit: contain; user-select: none; }
.lk-gallery-nav {
  position: absolute; top: 50%; transform: translateY(-50%); min-width: 48px; min-height: 64px;
  background: rgba(255, 255, 255, .14); color: #fff; border: 0; border-radius: 8px; font-size: 30px; line-height: 1;
}
.lk-gallery-prev { left: 6px; }
.lk-gallery-next { right: 6px; }
.lk-gallery-close:hover, .lk-gallery-nav:hover { background: rgba(255, 255, 255, .24); }
.lk-gallery-bottom { background: var(--surface); color: var(--ink); padding: 8px 12px 12px; }
.lk-gallery-caption { margin: 0 0 6px; font-size: 13px; color: var(--muted); }
.lk-gallery-caption > * { display: inline; }
.lk-gallery-actions { flex-direction: row; flex-wrap: wrap; padding: 0; }
.lk-gallery-actions > .lk-inline, .lk-gallery-actions > .lk-move { flex: 1 1 140px; }
.lk-gallery-actions button, .lk-gallery-actions a.button-like { width: 100%; min-height: 44px; }
.lk p.hint { font-size: 14px; color: var(--ink); background: var(--accent-soft); border-radius: 7px; padding: 8px 10px; }
.lk figure.lk-collage { margin: 10px 0 6px; }
/* Полоса внизу экрана — как корзина магазина (ЛК-2): счёт и главная кнопка видны, пока листаются
   кадры. Последний ребёнок <main>, поэтому стоит у края экрана, пока виден список, и не закрывает
   конец страницы. */
.lk-bar {
  position: sticky; bottom: 0; z-index: 5; margin: 14px -12px 0; padding: 10px 12px;
  background: var(--surface); border-top: 1px solid var(--line); box-shadow: 0 -4px 14px rgba(0, 0, 0, .08);
  display: flex; flex-direction: column; gap: 8px;
}
.lk-bar-part { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.lk-bar-part .lk-inline { display: inline-block; }
.lk-bar-left { color: var(--muted); }
@media (min-width: 720px) {
  .lk-bar { flex-direction: row; justify-content: space-between; border: 1px solid var(--line); border-bottom: none; border-radius: 10px 10px 0 0; margin: 14px 0 0; }
  .lk-bar-part { flex: 1 1 0; }
}
/* Страница серии (0175): плитка — подпись своей галочки; галочка СЛЕВА от кадра (правило «галочка —
   перед своим текстом» держит общий стиль подписи строкой), кадр с именем — одним блоком справа. */
.photo-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin: 10px 0; }
.photo-tile { padding: 6px; border: 2px solid var(--line); border-radius: 8px; cursor: pointer; background: var(--surface); }
.photo-tiles label.photo-tile:has(> input[type="checkbox"]) { align-items: flex-start; gap: 6px; }
.photo-tile:has(input:checked) { border-color: var(--accent); background: var(--surface-2); }
.photo-tile.picked { cursor: not-allowed; opacity: .75; }
.photo-tile-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.photo-tile img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 4px; }
.photo-tile-name { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.photo-tile-pick { font-size: 12px; color: var(--warn); }
.photo-move-actions p { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.photo-thumbs { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0; }
.photo-thumbs img { width: 72px; height: 90px; object-fit: cover; border-radius: 4px; border: 1px solid var(--line); }
.photo-upload label { display: inline-flex; gap: 6px; align-items: center; }
/* Отчёт загрузки кадров (владелец, 21.10.2026: «писать просто списком… чтобы было проще найти
   и загрузить нужные фотографии снова»): итог пунктами, незагруженные — по причинам, имя на строке. */
.photo-upload-status { margin-top: 8px; }
.photo-upload-status progress { width: 100%; max-width: 420px; height: 10px; }
.photo-upload-head { font-weight: 600; margin: 4px 0; }
.photo-upload-facts { margin: 6px 0; padding-left: 20px; color: var(--muted); }
.photo-upload-failed { margin-top: 10px; padding: 10px 14px; border: 1px solid var(--warn); border-radius: 8px; background: var(--warn-bg); }
.photo-upload-failed h3 { margin: 0 0 6px; color: var(--warn); }
.photo-upload-reason { margin: 8px 0 2px; font-weight: 600; }
.photo-upload-names { margin: 0 0 6px; padding-left: 20px; columns: 3 180px; column-gap: 24px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px; }
.photo-upload-names li { break-inside: avoid; }
.photo-upload-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 10px 0 4px; }
.photo-upload-done { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }

/* ─── Оплата мастерам и расходы из средств владельца (0181; навыки дизайна,
   26.10.2026). Итог строки одной фразой, выдачи — списком без точек. На
   телефоне таблица встаёт столбиком: строка — карточка, имя первой строкой,
   короткие числа — в одну строку с подписью, кнопки — под палец. Общее
   правило «плотная таблица прокручивается внутри карточки» здесь прятало
   «Выдать…» за правый край, а клетка выдачи сжималась до слова и вытягивала
   строку на высоту экрана. ─── */
.mp-state { margin: 0 0 4px; }
.mp-done { color: var(--ok); }
.mp-payouts { list-style: none; margin: 2px 0 6px; padding: 0; font-size: 13.5px; }
.mp-payouts li { padding: 3px 0; }
/* Утверждённая ведомость с выдачами: факты — списком, по строке на пункт (И-2). */
div.warn-inline > p { margin: 0 0 4px; }
.mp-facts { margin: 2px 0 6px; padding-left: 18px; }
.mp-facts li { margin: 2px 0; }
@media (max-width: 700px) {
  .card table.stack-table, .stack-table tbody, .stack-table tr, .stack-table td { display: block; width: auto; max-width: 100%; }
  .card table.stack-table { overflow-x: visible; }
  .stack-table thead { display: none; }
  .stack-table tr { border-top: 1px solid var(--line); padding: 10px 0; }
  .stack-table td { border: 0; padding: 2px 0; text-align: left; }
  .stack-table td.stack-main { font-weight: 600; font-size: 15px; }
  .stack-table td.stack-inline { display: inline-block; margin-right: 14px; }
  .stack-table td[data-label]::before { content: attr(data-label) ': '; color: var(--muted); font-size: 12.5px; font-weight: 400; }
  .stack-table button { min-height: 44px; }
  /* Под палец, но со своим «▸»: flex снял бы значок раскрытия. */
  .stack-table details.mp-cancel > summary { padding: 12px 0; }
}

/* ─── Табель смен «шашечкой» (окно «Этап 38 Аврора»; макет 03.11.2026).
   Строки — сотрудники, столбцы — дни месяца; имена стоят на месте, таблица
   листается вбок внутри своей рамки. Клетка — ссылка на окно клетки: с
   клавиатуры и читалкой экрана, на телефоне — 44 × 44 px под палец. Цвета
   смен — те же «ok» и «warn» платформы: зелёный — смена, оранжевый — заявка
   ждёт, контур — план без денег. ─── */
.sg-page h1 { margin: 6px 0 8px; }
.sg-back { margin: 0; font-size: 14px; }
.sg-nav { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; justify-content: space-between; margin: 6px 0 10px; }
.sg-nav .tabs { margin: 0; }
.sg-months { display: flex; flex-wrap: wrap; gap: 8px; }
.sg-lead { margin: 4px 0 6px; }
.sg-rule { margin-top: 10px; }
.sg-rule > summary { cursor: pointer; color: var(--muted); font-size: 13px; padding: 6px 0; }
.sg-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); -webkit-overflow-scrolling: touch; }
table.sg { border-collapse: separate; border-spacing: 0; font-size: 13px; min-width: 100%; }
table.sg th, table.sg td { border-bottom: 1px solid var(--line); border-right: 1px solid var(--line-soft); padding: 0; text-align: center; vertical-align: middle; }
table.sg .sg-who { position: sticky; left: 0; z-index: 2; background: var(--surface); text-align: left; padding: 6px 10px; min-width: 128px; max-width: 170px; font-weight: 600; white-space: normal; line-height: 1.25; border-right: 1px solid var(--line); }
table.sg .sg-who .mini-badge { display: inline-block; margin-top: 2px; font-weight: 400; }
table.sg .sg-day { min-width: 32px; padding: 4px 0; font-weight: 600; }
table.sg .sg-day.hours { min-width: 46px; }
table.sg .sg-day small { display: block; font-weight: 400; color: var(--muted); }
table.sg .sg-day .sg-span { font-size: 9.5px; line-height: 11px; margin-top: 2px; }
table.sg .sg-day.sun { color: var(--accent); }
table.sg .sg-day.today { background: var(--warn-bg); }
table.sg .sg-day.nolessons span { color: var(--muted); font-weight: 400; }
/* День без занятий — тихой штриховкой: главное в клетке — отметка, а не фон. */
table.sg td.nolessons { background-image: repeating-linear-gradient(135deg, transparent 0 7px, var(--line-soft) 7px 8px); }
table.sg td.future { background-color: var(--surface-2); }
table.sg td.today { box-shadow: inset 0 0 0 2px var(--warn); }
table.sg td.shared { background-color: var(--ok-bg); }
table.sg td.sg-cell { height: 40px; }
table.sg a.sg-hit { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; height: 40px; text-decoration: none; color: var(--ink); }
table.sg a.sg-hit:hover, table.sg a.sg-hit:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
table.sg .sg-sum { font-weight: 700; padding: 0 8px; white-space: nowrap; }
/* Текст отметки — цветом поверхности: белый в светлой теме, тёмный в тёмной,
   где --ok/--warn/--bad светлеют и белый на них нечитаем (аудит единого вида). */
.sg-ok, .sg-req { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 6px; font-weight: 700; color: var(--surface); }
.sg-ok { background: var(--ok); }
/* «!» — данные с ошибкой (смена в день без занятий), «?» — ждёт решения:
   два смысла — два цвета (критика экрана 03.11.2026). */
.sg-req { background: var(--warn); }
.sg-ok.warn { background: var(--bad); }
.sg-plan { display: inline-block; padding: 1px 4px; border: 1.5px dashed var(--muted); border-radius: 6px; color: var(--muted); font-size: 10.5px; line-height: 14px; }
.sg-plan.now { border-color: var(--ok); color: var(--ok); font-weight: 700; }
/* Код филиала под отметкой: единый табель на все филиалы (03.11.2026). */
.sg-code { display: block; font-size: 10px; line-height: 12px; margin-top: 2px; color: var(--muted); font-weight: 600; letter-spacing: 0.01em; }
/* Руководитель «на месте» — без денег: нейтральный круг, не «ok» (деньги) и
   не акцент (у художки он красный и спорил бы с «!»). */
.sg-here { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; border: 1.5px solid var(--muted); background: var(--surface-2); color: var(--ink); font-size: 13px; line-height: 1; }
table.sg tr.sg-director th.sg-who { background: var(--surface-2); }
.sg-branches { margin: 0; color: var(--muted); }
.sg-howto { margin: 4px 0 12px; border: 1px solid var(--line); border-radius: 10px; padding: 0 12px; background: var(--surface); }
.sg-howto > summary { cursor: pointer; padding: 10px 0; font-weight: 600; }
.sg-howto h3 { font-size: 15px; margin: 10px 0 4px; }
.sg-howto p, .sg-howto ul { margin: 0 0 8px; font-size: 14px; line-height: 1.45; }
.sg-howto ul { padding-left: 20px; }
.sg-howto li { margin: 2px 0; }
.sg-dialog .sg-where { margin: 6px 0 8px; flex-wrap: wrap; }
.sg-dialog .sg-where .tab { min-height: 36px; display: inline-flex; align-items: center; }
.sg-edit { margin: 8px 0; border-top: 1px solid var(--line-soft); padding-top: 6px; }
.sg-edit > summary { cursor: pointer; font-weight: 600; padding: 6px 0; min-height: 32px; }
.sg-presence { padding-left: 18px; margin: 6px 0; }
.sg-presence li { margin: 4px 0; }
.sg-bar { display: flex; gap: 1px; height: 12px; width: 40px; margin: 0 auto; }
.sg-bar i { flex: 1; background: var(--line); border-radius: 1px; }
.sg-bar i.gap { background: transparent; }
.sg-bar i.on { background: var(--ok); }
.sg-bar i.out { background: repeating-linear-gradient(135deg, var(--ok) 0 2px, var(--ok-bg) 2px 4px); }
.sg-bar i.plan { background: transparent; box-shadow: inset 0 0 0 1px var(--muted); }
.sg-bar i.plan.out { box-shadow: inset 0 0 0 1px var(--muted); background: repeating-linear-gradient(135deg, transparent 0 2px, var(--line-soft) 2px 4px); }
.sg-bar i.request { background: var(--warn); }
.sg-bar i.request.out { background: repeating-linear-gradient(135deg, var(--warn) 0 2px, var(--warn-bg) 2px 4px); }
.sg-bar i.here { background: var(--muted); }
.sg-bar i.here.out { background: repeating-linear-gradient(135deg, var(--muted) 0 2px, var(--surface-2) 2px 4px); }
/* Художка: полоса, часы и код филиала — три строки в клетке. */
table.sg td.sg-cell.hours, table.sg td.sg-cell.hours a.sg-hit { height: 52px; }
.sg-bar.big { height: 18px; width: 100%; max-width: 380px; margin: 6px 0; }
.sg-h { display: block; font-size: 10.5px; line-height: 13px; margin-top: 2px; }
.sg-h.plan { color: var(--muted); }
.sg-h.plan.now { color: var(--ok); font-weight: 700; }
.sg-h.req { color: var(--warn); font-weight: 700; }
.sg-legend { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; font-size: 13px; margin: 8px 0 12px; }
.sg-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.sg-legend .sg-bar { width: 56px; margin: 0; }
.sg-hint { font-size: 13px; color: var(--muted); margin: 8px 0 0; }
.sg-add { margin-top: 12px; }
.sg-dialog { max-width: 460px; }
.sg-dialog .times { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.sg-dialog .times label { flex: 1 1 120px; }
.sg-dialog .btnrow { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.sg-dialog .btnrow button, .sg-dialog .btnrow a.button-like { min-height: 44px; }
.sg-sumline { margin: 6px 0; }
@media (max-width: 700px) {
  table.sg .sg-day { min-width: 44px; }
  table.sg td.sg-cell, table.sg a.sg-hit { height: 48px; }
  table.sg td.sg-cell.hours, table.sg td.sg-cell.hours a.sg-hit { height: 54px; }
  .sg-dialog .sg-where .tab { min-height: 44px; }
  /* Под палец — отступом, а не flex: flex у <summary> прячет треугольник раскрытия. */
  .sg-edit > summary, .sg-howto > summary { padding: 12px 0; }
  table.sg .sg-who { min-width: 112px; max-width: 124px; font-size: 12.5px; }
  .sg-nav .tabs .tab, .sg-months a { min-height: 44px; display: inline-flex; align-items: center; }
  .sg-rule > summary { padding: 12px 0; }
}

/* Мерки ученика (0217): поля в сетку, на телефоне — по одному в ряд. */
.measure-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); gap: 8px 12px; margin: 8px 0; }
.measure-grid label { display: grid; gap: 2px; font-size: 13px; }
.measure-grid input { width: 100%; box-sizing: border-box; }
