
:root {
  --bg: #ffffff;
  --surface: #ffffff;
  --sunken: #f4f5f8;
  --fg: #16181d;
  --muted: #6b7280;
  --faint: #9aa1ac;
  --line: #e6e8ee;
  --brand: #5b3ce0;
  --brand-soft: #efeaff;
  --ok: #17915e;
  --ok-soft: #e6f5ee;
  --warn: #b25e00;
  --warn-soft: #fdf0e0;
  /* Приглушённо-красный, как в бумажных календарях: число выходного и
     праздничного дня — второй признак нерабочего дня поверх заливки клетки,
     виден и там, где сама заливка на слабом экране теряется. */
  --rest-num: #b3261e;
  /* «Не сдал» в таблицах опроса (Ш31.9) — тот же красный, что у числа
     выходного дня, и его бледный фон для пилюли статуса. */
  --bad: #b3261e;
  --bad-soft: #fbe9e7;
  --shadow: 0 1px 2px rgba(20, 22, 30, 0.05), 0 6px 16px -8px rgba(20, 22, 30, 0.14);
}

/*
 * Тёмной темы нет ([D111]): кабинетом пользуются вперемешку с бумажными
 * списками и при свете класса, а не в темноте, и владелец её не хочет.
 * Раньше здесь стоял @media (prefers-color-scheme: dark), менявший все
 * переменные :root при тёмной настройке телефона, — кабинет уезжал в
 * тёмный вид не по своей воле. Блок убран целиком, а не подогнан под вкус:
 * переменные выше — единственное определение цветов, других мест, где они
 * переопределяются, в файле нет.
 */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--sunken);
  color: var(--fg);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
}

.page { padding-bottom: 5rem; background: var(--sunken); }

@media (min-width: 52rem) {
  .page { padding-bottom: 2rem; }
}

/* ── Оболочка ──────────────────────────────────────────────────────────────
 *
 * На широком экране — боковое меню слева и страница справа. На телефоне
 * меню уезжает вниз, к большому пальцу, а сверху остаётся узкая полоска со
 * знаком и кружком человека. Разметка одна, оформление разное.
 */

.shell { display: block; }
.page { min-height: 100vh; }

.topbar {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.side .brand, .side .me { display: none; }

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 650;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: var(--fg);
  text-decoration: none;
}

.brand svg { display: block; flex: 0 0 auto; }

.ava {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  flex: 0 0 auto;
}

/*
 * Инструменты шапки на телефоне: аватар — ссылка на профиль, «?» — на
 * справку ([Э25]). Обе цели касания держат минимум 44 px, хотя сам кружок и
 * значок внутри мельче — на пальце важна область нажатия, а не рисунок.
 */
.topbar-tools { margin-left: auto; display: flex; align-items: center; gap: 0.1rem; }

.topbar-tools a {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  color: var(--muted);
  text-decoration: none;
}

.topbar-tools .spravka-link svg { width: 20px; height: 20px; }
.topbar-tools .spravka-link:hover { color: var(--brand); }

.me { display: flex; align-items: center; gap: 0.6rem; padding: 0.75rem 0.9rem; border-top: 1px solid var(--line); }
/* .me-link — аватар и имя, ссылка на профиль; форма выхода стоит рядом, вне
   неё (Ш25.70, п.22: <form> внутри <a> — невалидная разметка). */
.me-link { display: flex; align-items: center; gap: 0.6rem; flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.me-help { font-size: 0.8rem; color: var(--faint); text-decoration: none; }
.me-help:hover { color: var(--brand); }
.me-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.9rem; }
.me form { flex: 0 0 auto; }

.me button {
  background: none;
  border: none;
  color: var(--faint);
  font-size: 0.85rem;
  padding: 0 0.5rem;
  min-height: 2.5rem;
  cursor: pointer;
}

.me button:hover { color: var(--brand); filter: none; }

/* ── Меню ───────────────────────────────────────────────────────────────── */

.tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
  display: flex;
  justify-content: space-around;
  gap: 0.1rem;
  padding: 0.35rem 0.3rem calc(0.35rem + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--line);
}

.tabs a {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 44px;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0.1rem;
  padding: 0.35rem 0.2rem;
  border-radius: 10px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.72rem;
  line-height: 1.2;
}

.tabs a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.tabs a .wide { display: none; }
.tabs a svg { width: 22px; height: 22px; }
.tabs a.here { color: var(--brand); }

/* Счётчик дел: на телефоне — точкой у значка, в меню — числом у имени. */
.tabs a b {
  position: absolute;
  top: 0.15rem;
  right: 50%;
  margin-right: -1.05rem;
  min-width: 1.05rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.05rem;
  text-align: center;
}

/*
 * Матрица ролей и справка ([Э25]).
 *
 * На узком экране этот ряд не рисуется вовсе: у справки на телефоне своя
 * ссылка в шапке, у матрицы — на странице «Класс» и в профиле, а второй
 * нижней панели, дублирующей главную, здесь больше нет. Список появляется
 * только в боковом меню широкого экрана, ниже.
 */
.side-extra { display: none; }

@media (min-width: 52rem) {
  .shell { display: grid; grid-template-columns: 15.5rem 1fr; align-items: start; }
  .topbar { display: none; }

  .side-extra {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.25rem 0.6rem;
  }

  .side-extra a {
    display: grid;
    grid-auto-flow: column;
    grid-template-columns: 22px 1fr auto;
    justify-items: start;
    align-items: center;
    gap: 0.65rem;
    width: 100%;
    padding: 0.6rem 0.7rem;
    border-radius: 10px;
    color: var(--muted);
    text-decoration: none;
    font-size: 0.95rem;
  }

  .side-extra a svg { width: 22px; height: 22px; }
  .side-extra a.here { background: var(--brand-soft); color: var(--brand); font-weight: 600; }

  .side {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-right: 1px solid var(--line);
  }

  .side .brand { display: flex; padding: 1.1rem 1rem 0.9rem; }
  .side .me { display: flex; margin-top: auto; }

  .tabs {
    position: static;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0.15rem;
    padding: 0.25rem 0.6rem;
    background: none;
    border-top: none;
  }

  .tabs a {
    flex: 0 0 auto;
    grid-auto-flow: column;
    grid-template-columns: 22px 1fr auto;
    justify-items: start;
    align-items: center;
    gap: 0.65rem;
    width: 100%;
    padding: 0.6rem 0.7rem;
    font-size: 0.95rem;
  }

  .tabs a .wide { display: inline; }
  .tabs a .narrow { display: none; }
  .tabs a.here { background: var(--brand-soft); font-weight: 600; }

  .tabs a b {
    position: static;
    margin: 0;
    justify-self: end;
  }
}

/* Второй ряд — разделы внутри выбранного. Всегда наверху страницы.
 * Один ряд без переноса (D129, A6: ui-1 общ. №5 — «Закупка класса» одна во
 * второй строке выглядела как что-то другое): если подвкладки не помещаются,
 * ряд прокручивается пальцем внутри себя, страница вбок не едет. Полоса
 * прокрутки спрятана — на телефоне её и так нет, на широком экране ряд
 * помещается целиком. */
.tabs.sub {
  position: static;
  flex-direction: row;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 0.35rem;
  max-width: 46rem;
  margin: 0.9rem auto 0;
  padding: 0.15rem 1rem;
  background: none;
  border: none;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tabs.sub::-webkit-scrollbar { display: none; }

.tabs.sub a {
  flex: 0 0 auto;
  display: inline-block;
  width: auto;
  font-size: 0.88rem;
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
}

.tabs.sub a.here { border-color: transparent; background: var(--brand-soft); color: var(--brand); font-weight: 600; }

/* ── Страница ──────────────────────────────────────────────────────────── */

main {
  max-width: 46rem;
  margin: 0 auto;
  padding: 0.75rem 1rem 2rem;
}

main.wide-main {
  max-width: 72rem;
}

/* Карточки главной: как на панели управления — крупное число и подпись. */
.cards { display: grid; gap: 0.75rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); margin: 1rem 0 1.5rem; }

.card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  padding: 1rem 1.1rem;
  color: inherit;
  text-decoration: none;
}

/* Карточка-ссылка стола: стрелка «›» у правого края, тень на наведении,
   сжатие под пальцем (D129, A3: ui-1 №8, ui-3 №2 — «ссылки целиком, но
   ничем не показывают, что нажимаются»). */
a.card { position: relative; padding-right: 2.4rem; transition: box-shadow 0.15s, border-color 0.15s, transform 0.1s; }
a.card::after { content: "›"; position: absolute; right: 1rem; top: 50%; transform: translateY(-50%); font-size: 1.6rem; line-height: 1; color: var(--faint); }
a.card:hover { border-color: var(--brand); box-shadow: 0 2px 4px rgba(20, 22, 30, 0.06), 0 10px 22px -10px rgba(91, 60, 224, 0.35); }
a.card:hover::after { color: var(--brand); }
a.card:active { transform: scale(0.99); box-shadow: var(--shadow); }
a.card.accent::after { color: rgba(255, 255, 255, 0.75); }
.card-title { color: var(--muted); font-size: 0.85rem; }
.card-value { font-size: 1.7rem; font-weight: 650; letter-spacing: -0.02em; margin: 0.3rem 0 0.15rem; }
.card-value.small { font-size: 1.15rem; line-height: 1.3; }

.card.accent {
  background: linear-gradient(135deg, #6b46e5, #3f24b8);
  border-color: transparent;
  color: #fff;
}

.card.accent .card-title, .card.accent .quiet { color: rgba(255, 255, 255, 0.78); }

h1 {
  font-size: 1.7rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0.5rem 0 1rem;
}

h2 {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--faint);
  font-weight: 650;
  margin: 1.75rem 0 0.6rem;
}

p { margin: 0.6rem 0; }
a { color: var(--brand); }

.quiet { color: var(--muted); font-size: 0.92rem; }
.ok { color: var(--ok); }
.error { color: var(--warn); font-size: 0.92rem; }
.crumbs { color: var(--faint); font-size: 0.88rem; margin: 0 0 0.25rem; }
/* Область нажатия крошки, заголовка-ссылки и мелких ссылок-действий —
   не ниже 40 px (D129, A5: «← сборы» 57×19, «Входы» 42×20 — пальцу не
   попасть). Отступы внутрь и такие же отрицательные наружу: строка на
   экране остаётся той же высоты, а цель под пальцем — 2.5rem. */
.crumbs a, .link-title, .void-entry, .row-tail > a:not([class]) { display: inline-flex; align-items: center; min-height: 2.5rem; padding: 0 0.3rem; margin: -0.55rem 0 -0.55rem -0.3rem; }
.crumbs a { color: var(--faint); text-decoration: none; }

/* Заголовок-ссылка: без подчёркивания он читается как обычный жирный текст,
   а нажатие на него не даёт видимого действия. */
.link-title { color: var(--brand); text-decoration: none; }
.link-title:hover { text-decoration: underline; }

/* «Отменить» у строки книги фонда: мелко и в стороне — действие на каждый
   день, а не то, на чём должен спотыкаться взгляд. */
.void-entry { color: var(--faint); font-size: 0.8rem; text-decoration: none; }
.void-entry:hover { color: var(--warn); text-decoration: underline; }

/* ── Сворачиваемые списки книги фонда ─────────────────────────────────────
 *
 * Нативные <details>/<summary>: без них пришлось бы городить скрипт ради
 * того, что браузер умеет сам. Поступления и траты подсвечены каждый своим
 * тоном, чтобы деньги, идущие в класс и из класса, различались с одного
 * взгляда, даже когда список свёрнут и видна только итоговая сумма.
 */
.ledger { margin: 0.5rem 0 1.25rem; }
/* Управление сбором — одна карточка с рядами вместо пяти плавающих блоков
 * (замечание владельца 22.09.2026: «панель несуразная, разрозненная»). Цвет —
 * только у сумм, сами ряды одинаковые, разделены линией. */
.ledger-stack { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); margin: 0.75rem 0 1.25rem; overflow: hidden; }
.ledger-stack .ledger { margin: 0; }
.ledger-stack .ledger summary { border: 0; border-radius: 0; box-shadow: none; background: var(--surface); border-bottom: 1px solid var(--line); padding: 0.75rem 0.9rem; font-weight: 600; }
.ledger-stack .ledger:last-child summary { border-bottom: 0; }
.ledger-stack .ledger[open] summary { margin-bottom: 0; background: var(--sunken); }
.ledger-stack .ledger[open] > :not(summary) { padding: 0.6rem 0.9rem 0.8rem; border-bottom: 1px solid var(--line); }
.ledger-stack .ledger.income summary, .ledger-stack .ledger.spending summary { background: var(--surface); }
/* Стрелка «›» у каждой раскрывашки, не только у рядов стека (D129, A3:
 * ui-1 №16, ui-3 №36 — ряды «Поступления / Траты / Кто сколько сдал» и
 * «Дни рождения» выглядели карточками-итогами, а не тем, что раскрывается).
 * Открытая — стрелка вниз. Заголовок — сразу за стрелкой, сумма — у правого
 * края. */
.ledger summary::before, details.fold summary::before { content: "›"; display: inline-block; flex: 0 0 auto; width: 1rem; color: var(--faint); font-size: 1.25rem; line-height: 1; font-weight: 700; transform: rotate(0deg); transition: transform 0.15s; margin-right: 0.2rem; }
.ledger summary .sum, details.fold summary .sum { margin-left: auto; }
.ledger[open] > summary::before, details.fold[open] > summary::before { transform: rotate(90deg); }

.ledger summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  font-weight: 650;
}

.ledger summary::marker, .ledger summary::-webkit-details-marker { display: none; }
.ledger[open] summary { margin-bottom: 0.6rem; }

.ledger.income summary { background: var(--ok-soft); }
.ledger.income summary .sum { color: var(--ok); }

/* Приглушённо-красный — тот же тон, что у выходного дня в календаре
   (--rest-num), а не отдельный кричащий красный. */
.ledger.spending summary { background: color-mix(in srgb, var(--rest-num) 16%, var(--surface)); }
.ledger.spending summary .sum { color: var(--rest-num); }

/* ── Свёрнутый список дней рождения (К4) ──────────────────────────────────
 *
 * Тот же приём `<details>`/`<summary>`, что у книги фонда: список на весь
 * класс отвлекал от самих событий, а свёрнутым он всё равно отвечает на
 * главный вопрос — сколько дней рождения впереди и когда ближайшее.
 */
details.fold { margin: 0.5rem 0 1.25rem; }

details.fold summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  font-weight: 650;
}

details.fold summary::marker, details.fold summary::-webkit-details-marker { display: none; }
details.fold[open] summary { margin-bottom: 0.6rem; }

/* Раскрывашка без своего класса («Изменить заявку», «Отменить событие»):
   заголовок — второстепенной кнопкой со стрелкой, не ниже 40 px (D129,
   A5: голый summary был строкой в 24 px с треугольником браузера). Через
   :where — нулевая специфичность, чтобы класс на самом summary (например,
   .btn) побеждал целиком. */
:where(details:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class])) {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 2.5rem;
  padding: 0 0.95rem 0 0.7rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--fg);
  font-weight: 600;
  font-size: 0.92rem;
  list-style: none;
  white-space: nowrap;
  cursor: pointer;
}
:where(details:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class]))::-webkit-details-marker { display: none; }
:where(details:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class]))::before { content: "›"; display: inline-block; width: 0.8rem; color: var(--faint); font-size: 1.2rem; line-height: 1; font-weight: 700; transition: transform 0.15s; }
:where(details[open]:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class]))::before { transform: rotate(90deg); }
:where(details:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class])):hover { border-color: var(--brand); color: var(--brand); }
:where(details[open]:not(.ledger):not(.fold):not(.exempt-list)) > :where(summary:not([class])) { margin-bottom: 0.5rem; }

/* ── Списки ────────────────────────────────────────────────────────────────
 *
 * Карточка вместо строки с чертой: строка теряется среди других строк, а
 * карточку видно, не вчитываясь.
 */

.deeds, .checklist, .news-list { list-style: none; padding: 0; margin: 0.5rem 0 1rem; display: grid; gap: 0.5rem; }

.deeds li, .checklist li, .news-list li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 0.8rem 0.9rem;
}

.checklist li, .news-list li { display: flex; align-items: center; gap: 0.75rem; }
.checklist li > span:first-child, .news-list li > div:first-child { flex: 1; min-width: 0; }
.checklist li > form { flex: 0 0 auto; }

/* Объявление несёт больше одной строки — текст, картинку, отметку, ссылку —
   и в один ряд, как обычная новость, уже не укладывается. */
.news-list li { display: block; }
.news-list li > * + * { margin-top: 0.5rem; }
.news-list li form { margin: 0.5rem 0 0; }

/* Картинка объявления: не шире карточки и с тем же скруглением, что у неё самой. */
.shot { display: block; max-width: 100%; border-radius: 10px; }

/* Та же картинка, но на форме правки: не во всю ширину, просто снимок для памяти — кружок здесь не нужен. */
.shot-small { display: block; width: 8rem; max-width: 100%; border-radius: 10px; }

/* Карточка события в ленте — целиком ссылка, а не заголовок внутри строки ([Э13]). */
.card-link { display: block; color: inherit; text-decoration: none; }
.card-link:hover .ev-title { color: var(--brand); }
.ev-title { font-weight: 650; font-size: 1.02rem; margin: 0.15rem 0; }

/* Снимки итогов события: три колонки на широком экране, две на узком, снимок квадратом. */
.photos { list-style: none; padding: 0; margin: 0.5rem 0 1rem; display: grid; gap: 0.6rem; grid-template-columns: repeat(2, 1fr); }

@media (min-width: 40rem) {
  .photos { grid-template-columns: repeat(3, 1fr); }
}

.photos li { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); padding: 0.5rem; }
.shot-sq { display: block; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 10px; }

/* Выполненное не исчезает, но перестаёт требовать внимания. */
.checklist li.done, .deeds li.done { background: var(--sunken); box-shadow: none; }
.checklist li.done > span:first-child { color: var(--muted); }
.deeds li.done b { color: var(--muted); font-weight: 500; }

/* Строка списка с правкой на месте: поле имени и действия под ним. */
.rows { list-style: none; padding: 0; margin: 0.5rem 0 1rem; display: grid; gap: 0.5rem; }

.rows li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 0.7rem 0.8rem;
}

.rows .row { display: flex; gap: 0.4rem; align-items: center; }
/* Карточка-ссылка: заголовок несёт адрес, а его псевдоэлемент накрывает всю
 * карточку — нажать можно куда угодно; кнопки и ссылки внутри подняты над ним. */
.card-click { position: relative; padding-right: 2rem; }
/* Стрелка «›» у правого края первой строки — знак «ведёт дальше» (D129, A3).
   Псевдоэлемент самой карточки, не ссылки: у ссылки `::after` уже занят
   накрывающим слоем. */
.card-click::after { content: "›"; position: absolute; right: 0.8rem; top: 0.55rem; font-size: 1.6rem; line-height: 1; color: var(--faint); pointer-events: none; }
.card-click:hover::after { color: var(--brand); }
.card-click .card-link { color: var(--brand); text-decoration: none; }
.card-click .card-link::after { content: ""; position: absolute; inset: 0; border-radius: 14px; }
.card-click { transition: box-shadow 0.15s, transform 0.1s, border-color 0.15s; }
.card-click:hover { border-color: var(--brand); box-shadow: 0 2px 4px rgba(20, 22, 30, 0.06), 0 10px 22px -10px rgba(91, 60, 224, 0.35); }
.card-click:active { transform: scale(0.99); box-shadow: var(--shadow); }
.card-click .card-link:focus-visible::after { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Всё, что внутри карточки нажимается само, поднято над псевдоэлементом
   ссылки. Раскрывашка (details/summary) — тоже: «Изменить заявку» на
   «Деньгах» не раскрывалась, а уводила на страницу сбора — под пальцем
   лежала a.card-link (ui-2 №1, D129). */
.card-click a:not(.card-link), .card-click button, .card-click form,
.card-click details, .card-click summary, .card-click label, .card-click input, .card-click select { position: relative; z-index: 1; }
.rows .row input { flex: 1; min-width: 0; }

.row-tail {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.45rem;
  font-size: 0.85rem;
}

.row-tail > span:first-child { margin-right: auto; }
.row-tail button { font-size: 0.82rem; padding: 0.25rem 0.6rem; min-height: 2.5rem; }

/* Назначение должности: выбор и кнопка рядом, во весь ряд — вместо прежних
   пяти кнопок-переключателей, которые на узком экране расползались по
   несколько строк на каждого человека. */
.row-tail .assign { display: flex; flex: 1 1 100%; gap: 0.4rem; align-items: center; }
/* Та же высота и те же отступы, что у обычного select ниже — раньше поле
   здесь было ниже прочих (30 px), у остальных полей кабинета цель касания
   не меньше 44 px ([Ш25.22]). */
.row-tail .assign select { flex: 1; min-width: 0; width: auto; min-height: 2.75rem; padding: 0.55rem 0.7rem; font-size: 0.92rem; }

/* Список детей/взрослых только для чтения (Э25, D106): вся строка — ссылка
   на карточку, а не поля ввода — на телефоне палец промахивался мимо
   маленькой кнопки в каждой из тридцати строк. Имя — заголовком, всё
   остальное под ним — мельче и тише (класс .quiet уже есть). */
.rows a.roster-row { display: block; position: relative; padding-right: 1.6rem; color: inherit; text-decoration: none; }
.rows a.roster-row .name { font-size: 1.05rem; font-weight: 700; }
.rows a.roster-row .quiet { margin-top: 0.15rem; }
.rows a.roster-row:hover .name { color: var(--brand); }
/* Строка-ссылка выглядит нажимаемой (D129, A3: ui-3 №36 — «лиловеет только
   имя, сама карточка не отзывается, стрелки нет»): стрелка «›» справа, на
   наведении — рамка и тень всей карточки, под пальцем — сжатие. Правила с
   `:has()` стоят отдельно: браузер без него выбросит только их, а стрелка
   и цвет имени останутся. */
.rows a.roster-row::after { content: "›"; position: absolute; right: 0; top: 50%; transform: translateY(-50%); font-size: 1.6rem; line-height: 1; color: var(--faint); }
.rows a.roster-row:hover::after { color: var(--brand); }
.rows li:has(> a.roster-row) { transition: box-shadow 0.15s, border-color 0.15s, transform 0.1s; }
.rows li:has(> a.roster-row:hover) { border-color: var(--brand); box-shadow: 0 2px 4px rgba(20, 22, 30, 0.06), 0 10px 22px -10px rgba(91, 60, 224, 0.35); }
.rows li:has(> a.roster-row:active) { transform: scale(0.99); box-shadow: var(--shadow); }

/* Контакты взрослого (Ш30.1, D121): подпись «Телефон» с пометкой о MAX и
   строка номера с кнопкой копирования — под именем в списке и блоком
   «Контакты» на карточке, только тем, у кого есть class.view_contacts.
   В строке списка блок стоит вне ссылки-строки, чуть отступив от ролей; на
   карточке — под своим заголовком, без отступа сверху. */
.contact { display: grid; gap: 0.35rem; }
.rows li .contact { margin-top: 0.55rem; }
.contact .quiet { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }
.contact .copy { padding: 0.45rem 0.6rem; }

/* Срок сбора: начало и конец в один ряд, как в банковской карточке. */
.period {
  display: flex;
  gap: 1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 0.8rem 0.9rem;
  margin: 0.75rem 0;
}

.period div { flex: 1; min-width: 0; }
.period div + div { text-align: right; border-left: 1px solid var(--line); padding-left: 1rem; }

.rows .row { display: flex; gap: 0.5rem; align-items: center; }
.rows .row input { flex: 1; min-width: 4rem; }
.rows .row > b:first-child { flex: 1; min-width: 0; }
.rows .row .sum { flex: 0 0 auto; }

select {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.55rem 0.7rem;
  width: 100%;
  min-height: 2.6rem;
}

input[type="file"] { padding: 0.45rem; background: var(--sunken); border-style: dashed; }

/*
 * Кнопка выбора файла в стиле кабинета, не системная «Choose File»
 * (Ш25.70, п.12). Родной input остаётся в разметке и кликабельным —
 * визуально скрыт тем же приёмом, что экранные подсказки для читалок с
 * экрана: он не display:none (такой элемент клик от внешнего label обычно
 * не принимает), просто сжат в точку и обрезан. Имя выбранного файла
 * подставляет script.ts.
 */
.file-pick { position: relative; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }

.file-pick-btn {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--fg);
  font-weight: 600;
  font-size: 0.92rem;
}

.file-pick:hover .file-pick-btn { border-color: var(--brand); color: var(--brand); }

.file-pick input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  background: none;
}

.file-pick-name { color: var(--muted); font-size: 0.88rem; overflow-wrap: anywhere; }

/* ── Метки ─────────────────────────────────────────────────────────────── */

.tag {
  display: inline-block;
  margin-bottom: 0.3rem;
  padding: 0.08rem 0.5rem;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand);
  font-size: 0.72rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.due {
  display: inline-block;
  padding: 0.08rem 0.5rem;
  border-radius: 999px;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.who-child { color: var(--faint); font-size: 0.85rem; }
.deeds li b { font-weight: 600; }
.deeds li > span.tag + b { display: block; }

/* Полоска выполненного. Ширина — единственное, что здесь считается, и
 * считается она на сервере: скрипта на странице нет. */
.bar {
  height: 6px;
  border-radius: 999px;
  background: var(--sunken);
  overflow: hidden;
  margin: 0.5rem 0 0.25rem;
}

.bar i { display: block; height: 100%; background: var(--brand); border-radius: 999px; }
.bar.done i { background: var(--ok); }

/*
 * Полоска сбора денег в три доли (Ш25.54, п.2): «сдали» зелёным, «ждёт
 * подтверждения» тем же янтарным, что и «due» у срока, «не сдали» — серым
 * track-цветом, но темнее самого track, чтобы доля была видна даже тому, кто
 * цвета различает плохо, — а числа рядом подписаны всегда, не только цветом.
 *
 * Ширина — классом `p5`…`p100` (шаг в 5%), не строкой `style="…"`: у
 * кабинета строгий CSP (default-src 'self', style-src своего значения не
 * имеет — значит наследует его, а 'unsafe-inline' в нём нет), и инлайновый
 * атрибут `style` браузер тихо отбрасывает без единой ошибки в разметке —
 * заметно только по нулевой ширине в живом браузере, jsdom-тест такого не
 * увидит (самопроверка на стенде при показе Playwright-снимка, Ш25.54, п.2).
 */
.bar-3 { display: flex; }
.bar-3 i { border-radius: 0; flex: 0 1 auto; }
.bar-3 i:first-child { border-radius: 999px 0 0 999px; }
.bar-3 i:last-child { border-radius: 0 999px 999px 0; }
.bar-3 i:only-child { border-radius: 999px; }
.bar-3 i.ok { background: var(--ok); }
.bar-3 i.warn { background: var(--warn); }
.bar-3 i.rest { background: var(--faint); }
/* Отступ перед пояснением: классом, а не встроенным стилем — его запрещает
   политика безопасности кабинета (см. bar в html.ts). */
.otstup { margin-top: 1rem; }

.bar i.p0, .bar-3 i.p0 { width: 0; flex-basis: 0; }
.bar i.p5, .bar-3 i.p5 { width: 5%; flex-basis: 5%; }
.bar i.p10, .bar-3 i.p10 { width: 10%; flex-basis: 10%; }
.bar i.p15, .bar-3 i.p15 { width: 15%; flex-basis: 15%; }
.bar i.p20, .bar-3 i.p20 { width: 20%; flex-basis: 20%; }
.bar i.p25, .bar-3 i.p25 { width: 25%; flex-basis: 25%; }
.bar i.p30, .bar-3 i.p30 { width: 30%; flex-basis: 30%; }
.bar i.p35, .bar-3 i.p35 { width: 35%; flex-basis: 35%; }
.bar i.p40, .bar-3 i.p40 { width: 40%; flex-basis: 40%; }
.bar i.p45, .bar-3 i.p45 { width: 45%; flex-basis: 45%; }
.bar i.p50, .bar-3 i.p50 { width: 50%; flex-basis: 50%; }
.bar i.p55, .bar-3 i.p55 { width: 55%; flex-basis: 55%; }
.bar i.p60, .bar-3 i.p60 { width: 60%; flex-basis: 60%; }
.bar i.p65, .bar-3 i.p65 { width: 65%; flex-basis: 65%; }
.bar i.p70, .bar-3 i.p70 { width: 70%; flex-basis: 70%; }
.bar i.p75, .bar-3 i.p75 { width: 75%; flex-basis: 75%; }
.bar i.p80, .bar-3 i.p80 { width: 80%; flex-basis: 80%; }
.bar i.p85, .bar-3 i.p85 { width: 85%; flex-basis: 85%; }
.bar i.p90, .bar-3 i.p90 { width: 90%; flex-basis: 90%; }
.bar i.p95, .bar-3 i.p95 { width: 95%; flex-basis: 95%; }
.bar i.p100, .bar-3 i.p100 { width: 100%; flex-basis: 100%; }

.sum { font-variant-numeric: tabular-nums; font-weight: 650; }
.big-sum { font-size: 1.5rem; letter-spacing: -0.02em; }

/* ── Кнопки ────────────────────────────────────────────────────────────── */

/* a.danger — та же кнопка видом, что button.danger, но настоящая ссылка, не
   кнопка формы (Ш25.70, п.18): «Удалить» на правке задачи/траты/списка ведёт
   на отдельную страницу подтверждения, а не отправляет эту форму. */
button, a.danger {
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  padding: 0.45rem 0.95rem;
  border-radius: 10px;
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
  /* Палец попадает в цель размером с ноготь, а не в текст. Одна высота у
     всех кнопок кабинета — 2.5rem, 40 px (D129, A5: были 30/38/40). */
  min-height: 2.5rem;
}

a.danger { display: inline-flex; align-items: center; text-decoration: none; box-sizing: border-box; }

button:hover, a.danger:hover { filter: brightness(1.07); }
button.danger, a.danger { background: #d93838; color: white; border-color: transparent; }
button.danger:hover, a.danger:hover { background: #c22929; }
button.off { background: transparent; color: var(--muted); border-color: var(--line); font-weight: 500; }

.cancel {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  border-color: var(--muted);
  color: var(--fg);
  background: var(--surface);
  font-size: 0.92rem;
  font-weight: 500;
  text-decoration: none;
}

.cancel:hover { border-color: var(--brand); color: var(--brand); }

/* Кнопка отправки и «Отмена» в одном ряду внизу формы — рядом, а не кнопка
   внутри формы и отдельный абзац под ней. */
.form-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }

/* Выданная должность: та же кнопка, но видно, что она нажата. */
button.on { background: var(--brand-soft); color: var(--brand); border-color: transparent; }
button.on::before { content: '✓ '; }
button.off:hover { color: var(--fg); border-color: var(--muted); filter: none; }

/* Карточка персоны на стенде ([D98]): роль крупно, ребёнок под ней помельче.
   Кнопка на всю ширину строки и не ниже 44 px — с телефона в это нельзя не
   попасть пальцем, даже с одной попытки. */
.stend-personas { max-width: 26rem; }
.stend-persona {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  width: 100%;
  min-height: 3rem;
  padding: 0.75rem 1rem;
  text-align: left;
  white-space: normal;
  background: var(--surface);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  font-size: 1.05rem;
}
.stend-persona:hover { border-color: var(--brand); filter: none; }
.stend-persona b { font-size: 1.05rem; }
.stend-persona span { font-size: 0.85rem; }

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

/* Подпись поля для скринридера без места на виду (Ш25.70, п.17) — поле
   узнаваемо и так по соседству (имя ребёнка строкой выше), но у `<label
   for>` должен быть текст, который скринридер прочитает вместо пустоты. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.block {
  display: grid;
  gap: 0.7rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 1rem;
  margin: 0.5rem 0 1.5rem;
}

/* min-width: 0 — иначе поле-сетка не сжимается уже своего содержимого:
   у `<input type="date">` в части браузеров собственный размер больше, чем
   у соседних текстовых полей, и без этой строки грид-ячейка вынуждена расти
   под него, выталкивая поле за правый край карточки. */
.block label { display: grid; gap: 0.3rem; min-width: 0; color: var(--fg); font-weight: 600; font-size: 0.92rem; }
.block button { justify-self: start; }
.block label.check { display: flex; flex-direction: row; align-items: center; gap: 0.55rem; min-height: 2.5rem; font-size: 0.92rem; color: var(--fg); }

/* Кнопка «?» рядом с чекбоксом и подсказка, которую она раскрывает
   ([раздел 3]). Подсказка без скрипта просто видна всегда — см. script.ts. */
/* Сама кнопка — 2.5rem (цель касания, D129 A5), а кружок в 1.4rem внутри
   неё нарисован фоном-градиентом; отрицательный отступ оставляет ей в
   строке прежнее место, чтобы флажок и подпись не разъехались. */
.hint-btn {
  width: 2.5rem;
  height: 2.5rem;
  min-height: 0;
  padding: 0;
  margin: -0.55rem;
  border-radius: 999px;
  background: radial-gradient(circle, var(--brand-soft) 0.7rem, transparent calc(0.7rem + 1px));
  color: var(--brand);
  font-weight: 700;
  font-size: 0.78rem;
  line-height: 1;
}
.hint-btn:hover { filter: none; color: var(--fg); }
.hint { color: var(--muted); font-size: 0.85rem; margin: 0.2rem 0 0; }

/*
 * Подсказка (D129, «подсказки в непонятных местах») — один приём на весь
 * кабинет: мелкий серый текст под полем, кнопкой или парой кнопок. Без
 * скрипта и без кнопки «?»: раньше подсказка у флажка «Требуется моё
 * подтверждение» раскрывалась кнопкой, а везде ещё шла серым текстом — два
 * вида на одно и то же. Здесь остаётся один.
 *
 *   <p class="podskazka">Сбор — одна сумма с каждого; опрос — …</p>
 *   <p class="podskazka q">Закрыть — сбор состоялся, итог остаётся в фонде; …</p>
 *   <p class="podskazka q nad">…над парой кнопок: отступ снизу, не сверху</p>
 *
 * Вариант `.q` ставит слева «?» в кружке — там, где подсказка объясняет
 * действие рядом (пара кнопок, флажок), а не просто подписывает поле.
 * Ссылка внутри — цвета кабинета, чтобы «указать реквизиты» в подсказке
 * оставалось видимым переходом.
 */
.podskazka {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  margin: 0.35rem 0 0;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1.4;
}
.podskazka.q::before {
  content: "?";
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.05rem;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
}
.podskazka a { color: var(--brand); }
.podskazka.nad { margin: 0 0 0.45rem; }

.pair { display: flex; align-items: center; gap: 0.5rem; }
.pair input { flex: 1; min-width: 0; }
.dash { color: var(--faint); flex: 0 0 auto; }

/* На телефоне (390 px) два `datetime-local` в ряд не помещаются — у поля свой
   отрисованный минимум, который `flex:1;min-width:0` не сжимает (Ш25.70,
   п.1: страница «Новое событие» была 516 px вместо 390). Ставим поля друг
   под другом; разделитель между ними в столбик не нужен. */
@media (max-width: 42rem) {
  .pair { flex-direction: column; align-items: stretch; }
  .dash { display: none; }
}

input[type="checkbox"], input[type="radio"] {
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  margin: 0;
  accent-color: var(--brand);
}

input, textarea {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.55rem 0.7rem;
  width: 100%;
  /* Своей ширины поле не диктует — ширину задаёт контейнер (width: 100%
     выше), а не собственный размер поля. Без этого у полей вроде
     `<input type="date">`, чей рисунок в части браузеров шире обычного
     текстового, есть свой запрет сжиматься уже содержимого — он и толкает
     поле за край карточки на узком экране. */
  min-width: 0;
  min-height: 2.6rem;
}

input:focus, textarea:focus { outline: 2px solid var(--brand); outline-offset: -1px; border-color: transparent; }
textarea { resize: vertical; line-height: 1.45; }
.checklist input { width: 4.5rem; min-height: 2.5rem; }
.checklist form { display: flex; gap: 0.4rem; align-items: center; }

/* ── Врезки ────────────────────────────────────────────────────────────── */

.news {
  background: var(--brand-soft);
  border-radius: 14px;
  padding: 0.25rem 1rem 0.9rem;
  margin-bottom: 1.25rem;
}

.news h2 { color: var(--brand); }
.news ul { margin: 0; padding-left: 1.1rem; }
.news li { margin: 0.3rem 0; }
.news-list form { margin: 0; }

.link {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
  word-break: break-all;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
}

/* Ссылка (или код) с кнопкой копирования ([D44]). Строка не должна
 * разъезжаться на узком экране — как и в других местах файла, это
 * overflow-wrap: anywhere и min-width: 0 на том, что может оказаться длинным. */
.copy {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
}

.copy code {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  background: none;
  padding: 0;
  font-size: inherit;
}

.copy-do {
  flex: 0 0 auto;
  font-size: 0.82rem;
  padding: 0.35rem 0.7rem;
  min-height: 2.5rem;
}

a.big {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.6rem 1.2rem;
  border-radius: 10px;
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}

/*
 * Кнопка «Открыть в MAX» — разметка и цвета площадки, снятые с живой
 * страницы дословно. Ниже нарочно не палитра файла (--brand и соседи): эта
 * кнопка принадлежит MAX, а не нам, и подгонять её под свой стиль нельзя.
 */
.max-open {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px;
  padding: 12px 20px;
  font-size: 14px; font-weight: 700; line-height: 20px;
  color: #fff;
  background-color: #3b5ceb;
  background-image:
    radial-gradient(at 0 100%, #31c6f4 0%, transparent 60%),
    radial-gradient(at 100% 100%, #c247e2 0%, transparent 70%),
    radial-gradient(at 100% 0, #6542d0 0%, transparent 65%),
    radial-gradient(at 0 0, #3b5ceb 0%, transparent 60%);
  box-shadow: 0 8px 20px -10px rgba(69, 96, 243, 0.7);
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  text-decoration: none;
}
.max-open:hover { transform: translateY(-2px); opacity: 0.9; }
.max-mark { width: 20px; height: 20px; margin-right: 8px; flex: none; }

/* Чаты класса — той же формой кнопки, что и «Открыть в MAX», в один ряд. */
.chat-buttons { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0.5rem 0 1rem; }

/*
 * Кнопки «Сбербанк» / «Т-Банк»: постоянная ссылка на сбор из реквизитов
 * класса, в цвет банка, а не площадки — это чужой сервис, не MAX.
 */
.bank-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px;
  padding: 12px 20px;
  font-weight: 700;
  text-decoration: none;
}

.bank-sber { background: #21a038; color: #fff; }
.bank-tbank { background: #ffdd2d; color: #000; }
.bank-other { background: var(--sunken); color: var(--fg); }
.bank-btn:hover { filter: brightness(1.05); }
/* Кнопки банков — в одну строку со значками: на 390 px две-три кнопки
 * должны стоять рядом, а не столбиком, поэтому отступы уже, чем у одиночной
 * кнопки, и значок несёт узнавание вместо длинной подписи. */
.bank-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.6rem 0 0.2rem; }
.bank-row .bank-btn { padding: 0.55rem 0.9rem; gap: 0.45rem; border-radius: 10px; font-size: 0.95rem; }
.bank-mark { width: 22px; height: 22px; flex: none; }
.bank-sber .bank-mark { color: #fff; }

code {
  background: var(--sunken);
  border-radius: 6px;
  padding: 0.08rem 0.35rem;
  font-size: 0.9em;
}

/* Ряд действий над разделом: то, что здесь можно завести. Стоит наверху, а не
 * в подвале, — иначе, чтобы записать трату, надо пролистать всю книгу. */
.actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 1.25rem; }

.actions a {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.45rem 0.9rem;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow);
}

.actions a:first-child { background: var(--brand); border-color: transparent; color: #fff; }
.actions a:hover { border-color: var(--brand); color: var(--brand); }
.actions a:first-child:hover { color: #fff; filter: brightness(1.07); }

/* ── Календарь ─────────────────────────────────────────────────────────────
 *
 * Сетка и лента рядом на широком экране, друг под другом на телефоне.
 * Сама сетка месяца — библиотека Event Calendar ([D58]), подключённая своим
 * файлом kabinet-cal.css, ссылкой только на /sobytiya — см. html.ts.
 * Здесь остаётся только обёртка .cal-mount: карточка вокруг чужой разметки,
 * оформленная так же, как остальные карточки кабинета.
 */

.split { display: grid; gap: 1rem; align-items: start; }

@media (min-width: 62rem) {
  .split { grid-template-columns: minmax(0, 1fr) 22rem; }
}

.cal-mount {
  background: var(--surface);
  border: none;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
  padding: 1.5rem;
  min-width: 0;

  --ec-bg-color: transparent;
  --ec-border-color: var(--line);
  --ec-today-bg-color: var(--warn-soft);
  --ec-highlight-color: var(--brand-soft);
  --ec-event-bg-color: var(--brand);
  --ec-event-text-color: #ffffff;
}

.cal-mount .ec-main {
  border: none;
  background: var(--surface);
}

.cal-mount .ec-col-head {
  border: none;
  padding: 1rem 0;
  color: var(--muted);
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.05em;
}

.cal-mount .ec-day-head a {
  font-weight: 600;
  color: var(--fg);
  text-decoration: none;
}

.cal-mount .ec-other-month .ec-day-head a {
  color: var(--muted);
  opacity: 0.5;
}

/* Event styling */
.cal-mount .ec-event {
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.85rem;
  font-weight: 500;
  border: none;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}

.cal-mount .ec-event:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 6px rgba(0,0,0,0.08);
}

.cal-mount .ec-event-title {
  color: #fff;
  text-shadow: 0 1px 1px rgba(0,0,0,0.1);
  font-weight: 600;
}

.cal-mount .ec-event-time {
  color: rgba(255, 255, 255, 0.9);
  font-weight: 600;
}

/* Toolbar buttons */
/*
 * Панель переносится по строкам, а не сжимается.
 *
 * Сеткой в две колонки выбор месяца наезжал на стрелки «назад-вперёд»:
 * названию «Сентябрь» нужна своя ширина, ужиматься ему некуда, и в узкой
 * колонке он вылезал на соседей. Гибкая строка с переносом отправляет его на
 * вторую строку — там он целиком и ни на что не налезает.
 */
.cal-mount .ec-toolbar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.9rem 1rem;
  align-items: center;
  margin-bottom: 1.25rem;
}

.cal-mount .ec-start,
.cal-mount .ec-center {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-width: 0;
}

.cal-mount .ec-center {
  justify-content: flex-end;
  flex: 1 1 auto;
  flex-wrap: wrap;
}

.cal-mount .ec-end {
  display: none;
}

.cal-mount .ec-button-group {
  display: inline-flex;
  align-items: stretch;
  overflow: hidden;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.cal-mount .ec-button {
  min-height: 2.9rem;
  padding: 0 1rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(244, 245, 248, 0.92));
  border: 1px solid var(--line);
  color: var(--fg);
  border-radius: 14px;
  font-weight: 650;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease;
  box-shadow: var(--shadow);
}

.cal-mount .ec-button-group .ec-button {
  min-width: 3.25rem;
  padding: 0;
  border: 0;
  border-right: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
}

.cal-mount .ec-button-group .ec-button:last-child {
  border-right: 0;
}

.cal-mount .ec-button:hover {
  background: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(239, 234, 255, 0.92));
  border-color: rgba(91, 60, 224, 0.24);
  color: var(--fg);
  transform: translateY(-1px);
}

.cal-mount .ec-button.ec-active {
  background-color: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

.cal-mount .ec-button:focus-visible,
.calendar-month-select:focus-visible {
  outline: 2px solid rgba(91, 60, 224, 0.35);
  outline-offset: 2px;
}

.cal-mount .ec-today {
  background: var(--brand-soft);
  color: var(--brand);
  border-color: rgba(91, 60, 224, 0.14);
}

/* Выключенная кнопка (текущий месяц уже на экране — «Сегодня» нажимать
   нечего) выглядела как активная, подсвеченной (ui-3 №28, D129 A8). */
.cal-mount .ec-button:disabled,
.cal-mount .ec-button:disabled:hover {
  background: var(--sunken);
  color: var(--faint);
  border-color: var(--line);
  box-shadow: none;
  transform: none;
  cursor: default;
}

/*
 * Месяц и год держатся вместе и переносятся одним куском.
 *
 * Переносить их порознь незачем: год без месяца — половина подписи, и панель
 * растягивается на три строки там, где хватает двух. Место под перенос даёт
 * сама панель, а не эта пара.
 */
.calendar-toolbar-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  min-width: 0;
}

.calendar-month-select {
  /*
   * Ширина — под самое длинное название («Сентябрь») вместе со стрелкой:
   * сжатый до «Се» месяц не читается. Переносит его на другую строку сама
   * панель (.ec-toolbar с flex-wrap), поэтому ужиматься ему не нужно, а
   * налезать на стрелки — тем более.
   */
  flex: 0 0 auto;
  min-width: 9.5rem;
  min-height: 2.9rem;
  padding: 0 2.5rem 0 0.95rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  color: var(--fg);
  font: inherit;
  font-weight: 650;
  box-shadow: var(--shadow);
}

/* Заголовок библиотеки («2026 г.») не показывается: месяц и год стоят
   одной строкой в самом выборе месяца — «Сентябрь 2026» (D129, A8: «2026
   Г.» капителью читалось как обрубок). Текст в разметке остаётся — по
   нему скрипт узнаёт текущий месяц. */
.cal-mount .ec-title { display: none; }

@media (max-width: 42rem) {
  .cal-mount .ec-toolbar {
    grid-template-columns: 1fr;
  }

  .cal-mount .ec-center {
    justify-content: flex-start;
  }

  .calendar-toolbar-meta {
    justify-content: flex-start;
    flex-wrap: wrap;
  }
}

/* Rest days background */
.cal-mount .ec-bg-event {
  opacity: 0.5;
  border-radius: 8px;
}

.cal-mount .ec-bg-event.ec-day-picked,
.cal-mount .ec-bg-event.ec-range-picked {
  opacity: 1;
  border-radius: 10px;
}

.cal-mount .ec-bg-event.ec-day-picked {
  background: rgba(91, 60, 224, 0.18);
  box-shadow: inset 0 0 0 2px rgba(91, 60, 224, 0.35);
}

.cal-mount .ec-bg-event.ec-range-picked {
  background: rgba(91, 60, 224, 0.12);
}

.cal-mount .ec-day-head {
  padding: 0.5rem 0.8rem 0.2rem 0;
  justify-content: flex-end;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  font-size: 0.8rem;
}

/*
 * «Ещё N» — одной строкой (Ш19.9/Э25).
 *
 * С фиксированной высотой сетки строка недели получает ровно свою долю
 * высоты, без запаса. Перенос «ещё N» на второй ряд в узкой колонке (телефон,
 * 375 px) утапливал цифру: она рисовалась ниже границы своей клетки и её
 * закрашивал фон уже следующей недели, рисуемый позже в разметке. Без
 * переноса строка остаётся одной высоты и всегда помещается в отведённое
 * место; если самой ссылке не хватает ширины — обрезаем многоточием, а не
 * второй строкой.
 */
.cal-mount .ec-day-foot {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * Телефон: событие в клетке — точка, многодневное — тонкая полоса через
 * дни (D129, A8: ui-2 №22, ui-3 №11 — в клетках стояло только «ещё 1», а
 * самих событий не было видно). Классы `ec-odin`/`ec-mnogo` ставит
 * calendar-init.ts; цвет — тот же фон, что у плашки. Название и время
 * спрятаны: что в дне, показывает список под сеткой по нажатию на день.
 */
@media (max-width: 42rem) {
  .cal-mount { padding: 1rem 0.6rem 0.75rem; }
  /* Недели — равными долями высоты, как делает сама библиотека при
     dayMaxEvents: true (класс ec-uniform). На телефоне предел снят, точки
     помещаются и так, а без равных долей строки росли по 5em и месяц
     обрезался на третьей неделе. */
  .cal-mount .ec-day-grid .ec-main { --ec-row-height: minmax(0, 1fr); flex-grow: 1; overflow: hidden; }
  .cal-mount .ec-day-grid .ec-main .ec-day { min-block-size: auto; }
  .cal-mount .ec-toolbar { margin-bottom: 0.75rem; gap: 0.6rem 0.75rem; }
  .cal-mount .ec-button, .cal-mount .ec-button-group .ec-button, .calendar-month-select { min-height: 2.5rem; }
  .cal-mount .ec-day-head { padding: 0.3rem 0.4rem 0.1rem 0; font-size: 0.75rem; }
  .cal-mount .ec-day-grid.ec-month-view .ec-day-head { padding: 0.3rem 0.4rem 0.1rem 0; }
  .cal-mount .ec-day-grid .ec-event {
    block-size: 0.5rem;
    min-block-size: 0;
    padding: 0;
    margin-block-end: 2px;
    border-radius: 999px;
    box-shadow: none;
    overflow: hidden;
  }
  .cal-mount .ec-day-grid .ec-event.ec-odin { inline-size: 0.5rem; margin-inline: auto; }
  .cal-mount .ec-day-grid .ec-event .ec-event-body { display: none; }
  .cal-mount .ec-day-grid .ec-event:hover { transform: none; box-shadow: none; }
  .cal-mount .ec-day-grid .ec-day-foot { display: none; }
}

/* События выбранного дня под сеткой (script.ts рисует по выбору дня): на
   телефоне список «События · N» уходит под сетку и подписку, и без этого
   нажатие на день ничего видимого не меняло. На широком экране список
   справа виден и так — блок спрятан. */
.cal-den { margin: 0.75rem 0 0; }
.cal-den h2 { margin: 0.5rem 0 0.4rem; }
.cal-den .rows { margin: 0; }
@media (min-width: 62rem) { .cal-den { display: none; } }
/* Пока блок дня под сеткой на экране, вторая подсказка о том же («выберите
   день… поднимутся наверх») в колонке списка — лишняя: одна мысль дважды. */
@media (max-width: 61.99rem) { [data-calendar-selection] { display: none; } }

.ava.plain { background: var(--sunken); color: var(--fg); font-size: 1rem; }
.big-ava { width: 5rem; height: 5rem; font-size: 1.6rem; margin-bottom: 0.75rem; }
img.ava { object-fit: cover; }

/* Цвета событий: постоянные, выбираются по названию. */
.sky { background: #3b82f6; }
.grass { background: #17915e; }
.sun { background: #d97706; }
.rose { background: #e11d48; }
.lilac { background: #7c3aed; }
.sand { background: #92794f; }

.ava.sky, .ava.grass, .ava.sun, .ava.rose, .ava.lilac, .ava.sand { color: #fff; }

.beside h2:first-child { margin-top: 0; }
.beside .rows li { padding: 0.6rem 0.7rem; }

.calendar-create-box {
  margin: 0 0 0.75rem;
}

.calendar-create-box a {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  width: 100%;
  box-sizing: border-box;
  padding: 0.65rem 0.9rem;
  border-radius: 12px;
  background: var(--brand);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  box-shadow: var(--shadow);
}

.calendar-create-box a:hover { filter: brightness(1.05); }

.calendar-match {
  background: #f7f3ff;
  border-color: rgba(91, 60, 224, 0.28);
  box-shadow: 0 0 0 2px rgba(91, 60, 224, 0.12), var(--shadow);
  position: relative;
}

.calendar-match::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 0.28rem;
  border-radius: 14px 0 0 14px;
  background: var(--brand);
}

.calendar-match .ev-title { color: var(--brand); }

.feed { display: flex; gap: 0.6rem; align-items: flex-start; }
.feed .ava { margin-top: 0.1rem; }
.feed > span:last-child { min-width: 0; }

/* Пусто — это тоже ответ, и он должен выглядеть спокойным, а не сломанным. */
.empty {
  text-align: center;
  color: var(--muted);
  background: var(--sunken);
  border-radius: 14px;
  padding: 2rem 1rem;
  margin: 1rem 0;
}

.empty b { display: block; color: var(--fg); font-size: 1.05rem; margin-bottom: 0.25rem; }

/* Матрица ролей и фильтры */
.bottom-menu { margin-top: auto; display: flex; flex-direction: column; width: 100%; }
.side .bottom-menu .me { margin-top: 0; }

.role-filters { display: flex; flex-wrap: wrap; gap: 0.4rem; }
label.role-filter { display: inline-flex; align-items: center; cursor: pointer; user-select: none; margin: 0; padding: 0; }
label.role-filter input[type="checkbox"] { display: none !important; opacity: 0; width: 0; height: 0; position: absolute; }
label.role-filter span { display: inline-block; padding: 0.4rem 0.9rem; background: var(--sunken); border-radius: 2rem; font-size: 0.85rem; border: 1px solid transparent; transition: all 0.15s ease; color: var(--faint); }
label.role-filter input[type="checkbox"]:checked + span { background: var(--bg); border-color: var(--line); color: var(--fg); font-weight: 500; box-shadow: 0 1px 2px rgba(0,0,0,0.05); }
label.role-filter:hover span { filter: brightness(0.95); }

/* min-width: 0 — .matrix-container стоит грид-ячейкой формы .block (класс
   matrix-form) и без этого не сжимается уже max-content таблицы (846 px):
   вбок едет вся страница, а не только таблица (Ш25.70, п.2). Тот же приём,
   что и у .block label выше. Саму прокрутку даёт .table-scroll внутри. */
.matrix-container { width: 100%; min-width: 0; }
.matrix-table { width: max-content; border-collapse: separate; border-spacing: 0; text-align: left; }
.matrix-table tbody tr { transition: background-color 0.2s ease; }
.matrix-table tbody tr:hover, .matrix-table tbody tr:hover .col-perm { background-color: var(--sunken); }
.matrix-table th, .matrix-table td { padding: 0.75rem 1rem; border-bottom: 1px solid var(--line); }
.matrix-table th { padding: 1rem; border-bottom: 2px solid var(--line); font-weight: 600; color: var(--faint); text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.05em; background: var(--bg); position: sticky; top: 0; z-index: 2; text-align: center; }
.matrix-table td { text-align: center; vertical-align: middle; }
.matrix-table .col-perm { position: sticky; left: 0; background: var(--bg); z-index: 1; text-align: left; font-size: 0.95rem; }
.matrix-table thead th.col-perm { z-index: 3; text-align: left; }

.perm-name { font-weight: 500; }
.perm-key { color: var(--faint); font-family: monospace; font-size: 0.85rem; margin: 0 0.5rem; }
.perm-desc { font-size: 0.95rem; }

.matrix-filter-section { margin: 1.5rem 0 1rem 0; display: flex; flex-direction: column; gap: 0.5rem; }
.matrix-filter-title { font-size: 0.8rem; text-transform: uppercase; color: var(--faint); font-weight: bold; letter-spacing: 0.05em; }

.matrix-form { display: inline-block; width: max-content; padding: 0; }
.matrix-form-actions { padding: 1rem; }

/* На телефоне width: max-content выше растягивает саму форму под ширину
   таблицы (846 px) — прокрутка .table-scroll внутри ничего не спасает,
   пока сама форма шире экрана (Ш25.70, п.2). На узком экране форма — во всю
   ширину, а прокручивается только таблица внутри неё. */
@media (max-width: 42rem) {
  .matrix-form { display: block; width: 100%; }
}
.matrix-legend-title { margin-top: 3rem; margin-bottom: 1rem; font-size: 0.85rem; text-transform: uppercase; color: var(--faint); font-weight: bold; letter-spacing: 0.05em; }

.legend-table { width: 100%; border-collapse: separate; border-spacing: 0; text-align: left; }
.legend-table tbody tr { transition: background-color 0.2s ease; }
.legend-table tbody tr:hover { background-color: var(--sunken); }
.legend-th { padding: 1rem; border-bottom: 2px solid var(--line); font-weight: 600; color: var(--faint); text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.05em; background: var(--bg); position: sticky; top: 0; z-index: 1; }
.legend-td { padding: 1rem; border-bottom: 1px solid var(--line); vertical-align: top; line-height: 1.5; }
.legend-td:first-child { width: 25%; font-weight: 500; font-size: 1rem; color: var(--fg); }
.legend-td:nth-child(2) { width: 25%; }
.legend-td:last-child { width: 50%; color: var(--fg); }
.legend-td .perm-key { display: inline-block; padding: 0.2rem 0.5rem; background: var(--sunken); border: 1px solid var(--line); border-radius: 4px; font-family: monospace; font-size: 0.8rem; color: var(--faint); }
.legend-td .perm-desc { font-size: 0.95rem; }

/* Таблица ответов анкеты (Э26) — широкая таблица скроллится в себе, страница вбок не едет. */
.table-scroll { overflow-x: auto; margin: 0.75rem 0; }
.anketa-table { width: max-content; min-width: 100%; border-collapse: separate; border-spacing: 0; text-align: left; }
.anketa-table th, .anketa-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); white-space: nowrap; }
.anketa-table th { color: var(--faint); font-weight: 600; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; }
.anketa-table tr.dim td { color: var(--muted); }
.anketa-table td.miss { color: var(--warn); font-weight: 600; }

/* ── D129, анкеты и класс (Ш31.11, C2) ────────────────────────────────────
 *
 * Таблица-карточки `.tab-kart` — одна разметка на два вида. На широком окне
 * это обычная таблица (ответы анкеты «дети × поля», список детей); на
 * телефоне (< 42rem) каждая строка складывается в карточку: номер и имя в
 * одну строку, состояние биркой, остальные ячейки построчно с подписью из
 * `data-label`. Строка нажимается целиком — ссылка `.tab-kart-link`
 * растянута на карточку псевдоэлементом, тем же приёмом, что `.card-link`;
 * раскрывашки и кнопки внутри подняты над ней. Горизонтальной прокрутки на
 * телефоне не остаётся (ui-3 №32, §6) — обёртка `.tab-kart-wrap` перестаёт
 * быть прокручиваемой, чтобы не резать тени и стрелку карточек.
 */
table.tab-kart { width: 100%; border-collapse: separate; border-spacing: 0; text-align: left; }
.anketa-table.tab-kart { width: max-content; min-width: 100%; }
.tab-kart th, .tab-kart td { padding: 0.55rem 0.75rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tab-kart th { color: var(--faint); font-weight: 600; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; }
.tab-kart td.who a.tab-kart-link { color: inherit; text-decoration: none; font-weight: 600; }
.tab-kart td.who a.tab-kart-link:hover { color: var(--brand); }
.tab-kart td.num { color: var(--muted); }
.tab-kart tbody tr:hover td { background: var(--sunken); }
.tab-kart td:empty::before { content: "—"; color: var(--faint); }
.tab-kart td.state .tag { margin: 0; }
.deti-table td.who, .deti-table td.born, .deti-table td.state { white-space: nowrap; }
.deti-table td.family { width: 45%; }

@media (max-width: 42rem) {
  .tab-kart-wrap { overflow: visible; }
  table.tab-kart, .tab-kart tbody, .tab-kart tr, .tab-kart td { display: block; width: auto; min-width: 0; }
  .tab-kart thead { display: none; }
  .tab-kart tbody { display: grid; gap: 0.5rem; }
  .tab-kart tr {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: var(--shadow);
    padding: 0.7rem 2.1rem 0.7rem 0.8rem;
    transition: box-shadow 0.15s, transform 0.1s, border-color 0.15s;
  }
  .tab-kart tr::after { content: "›"; position: absolute; right: 0.9rem; top: 0.5rem; font-size: 1.4rem; line-height: 1; color: var(--faint); }
  .tab-kart tr:hover { border-color: var(--brand); box-shadow: 0 2px 4px rgba(20, 22, 30, 0.06), 0 10px 22px -10px rgba(91, 60, 224, 0.35); }
  .tab-kart tr:active { transform: scale(0.99); box-shadow: var(--shadow); }
  .tab-kart tbody tr:hover td { background: transparent; }
  .tab-kart td, .tab-kart th { padding: 0; border: 0; white-space: normal; }
  .tab-kart td.num { display: inline; margin-right: 0.35rem; font-size: 0.9rem; }
  .tab-kart td.who { display: inline; font-size: 1.05rem; }
  .tab-kart td.state { margin: 0.25rem 0 0.35rem; }
  .tab-kart td[data-label] { padding: 0.12rem 0; font-size: 0.92rem; overflow-wrap: anywhere; }
  .tab-kart td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
  .tab-kart td[data-pref] { padding: 0.12rem 0; font-size: 0.92rem; color: var(--muted); }
  .tab-kart td[data-pref]::before { content: attr(data-pref) " "; }
  .tab-kart td.family { font-size: 0.9rem; color: var(--muted); }
  .tab-kart td:empty { display: none; }
  .tab-kart a.tab-kart-link::after { content: ""; position: absolute; inset: 0; border-radius: 14px; }
  .tab-kart a.tab-kart-link:focus-visible::after { outline: 2px solid var(--brand); outline-offset: 2px; }
  .tab-kart tr details, .tab-kart tr form, .tab-kart tr button, .tab-kart tr a:not(.tab-kart-link) { position: relative; z-index: 1; }
}

/* Роли на карточке взрослого (D129, ui-3 №40, №49): каждая роль — словом в
   своей строке, справа второстепенная «Снять» у тех, что смотрящий вправе
   снять. Не «пилюля с галочкой», которую нажимают не глядя. */
.roli { list-style: none; margin: 0.5rem 0 0.25rem; padding: 0; display: grid; gap: 0.35rem; max-width: 26rem; }
.roli li.rol {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  min-height: 2.6rem;
  padding: 0.35rem 0.45rem 0.35rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.roli li.rol b { font-weight: 600; }
.roli .btn { min-height: 2.75rem; }
.roli + .podskazka { margin-bottom: 0.9rem; }
/* «Назначить»: выпадающий список и кнопка в одну строку, той же ширины, что и список ролей над ними. */
form.assign { display: flex; align-items: center; gap: 0.4rem; max-width: 26rem; margin: 0.25rem 0 1.25rem; }
form.assign select { flex: 1; min-width: 0; width: auto; min-height: 2.75rem; padding: 0.55rem 0.7rem; font-size: 0.92rem; }

/* Матрица ролей по D129 (C2-6). Широкое окно: таблица «право × роль» с
   фильтром столбцов. Телефон (< 43.75rem): вид «по ролям» — пилюли-роли
   (радио без скрипта) переключают, CSS через :has прячет столбцы всех
   ролей, кроме выбранной; строка — «право · галочка», без горизонтальной
   прокрутки. Полоса «Сохранить права» прилипает к низу окна над нижней
   панелью; без скрипта видна всегда, со скриптом — при изменении. */
.matrix-narrow-only { display: none; }
.matrix-table .perm-name { cursor: help; }
.matrix-table td label.mcell { display: flex; align-items: center; justify-content: center; min-height: 2.5rem; margin: -0.5rem 0; cursor: pointer; }
.matrix-table input[type="checkbox"] { width: 1.3rem; height: 1.3rem; cursor: pointer; }
.matrix-table input[type="checkbox"]:disabled { cursor: default; }
.matrix-bar {
  position: sticky;
  bottom: 0.75rem;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 -2px 6px rgba(20, 22, 30, 0.06), 0 8px 24px -8px rgba(20, 22, 30, 0.35);
}
.matrix-bar[hidden] { display: none; }
.matrix-bar .btn { min-height: 2.5rem; }
.matrix-bar-count { color: var(--muted); font-size: 0.9rem; margin-right: auto; }
.matrix-bar-count:empty { display: none; }
label.matrix-rol { display: inline-flex; align-items: center; cursor: pointer; user-select: none; margin: 0; padding: 0; }
label.matrix-rol input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
label.matrix-rol span { display: inline-block; padding: 0.55rem 0.9rem; min-height: 2.5rem; background: var(--surface); border: 1px solid var(--line); border-radius: 2rem; font-size: 0.9rem; color: var(--fg); transition: all 0.15s ease; }
label.matrix-rol input[type="radio"]:checked + span { background: var(--brand-soft); border-color: transparent; color: var(--brand); font-weight: 600; }
label.matrix-rol input[type="radio"]:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }
label.matrix-rol:active span { transform: scale(0.98); }
.matrix-roles { margin: 1rem 0 0.75rem; flex-direction: column; gap: 0.5rem; }

/* Справка по правам — списком «право — описание», не таблицей. */
.perm-legend { display: grid; gap: 0; padding: 0.25rem 1rem; }
.perm-legend .perm-legend-row { padding: 0.7rem 0; border-bottom: 1px solid var(--line); }
.perm-legend .perm-legend-row:last-child { border-bottom: 0; }
.perm-legend dt { font-weight: 600; margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.perm-legend dt .perm-key { margin: 0; }
.perm-legend dd { margin: 0.2rem 0 0; color: var(--muted); font-size: 0.92rem; line-height: 1.45; }

@media (max-width: 43.75rem) {
  .matrix-wide-only { display: none; }
  .matrix-narrow-only { display: flex; }
  .matrix-table { width: 100%; }
  .matrix-table thead { display: none; }
  .matrix-table .col-perm { position: static; font-size: 0.95rem; padding: 0.55rem 0.5rem 0.55rem 0.9rem; }
  .matrix-table td { padding: 0.55rem 0.5rem; }
  .matrix-table td[data-role] { width: 3rem; }
  .matrix-vid:has(input[name="vid_roli"][value="teacher"]:checked) .matrix-table [data-role]:not([data-role="teacher"]),
  .matrix-vid:has(input[name="vid_roli"][value="treasurer"]:checked) .matrix-table [data-role]:not([data-role="treasurer"]),
  .matrix-vid:has(input[name="vid_roli"][value="committee"]:checked) .matrix-table [data-role]:not([data-role="committee"]),
  .matrix-vid:has(input[name="vid_roli"][value="parent"]:checked) .matrix-table [data-role]:not([data-role="parent"]),
  .matrix-vid:has(input[name="vid_roli"][value="student"]:checked) .matrix-table [data-role]:not([data-role="student"]) { display: none; }
  .matrix-bar { bottom: calc(4rem + env(safe-area-inset-bottom)); }
  .matrix-bar-count { flex-basis: 100%; margin-right: 0; }
  .perm-legend .perm-key { display: none; }
}

/* Ряд равных входов (D129, C2-7): те же пилюли, что .actions, но первая не
   закрашена как главная — на «Классе» это настройки, а не команда. */
.actions.ravno a:first-child { background: var(--surface); border-color: var(--line); color: var(--fg); }
.actions.ravno a:first-child:hover { border-color: var(--brand); color: var(--brand); filter: none; }

/* «Значения» в форме поля анкеты — только у типов выбора (D129, C2-9):
   поле прячется, пока в «Тип» выбран не «Выбор одного» / «Выбор нескольких».
   Без поддержки :has поле просто видно всегда — подсказка под ним объясняет. */
form:has(select[name="tip"] option[value="text"]:checked) .anketa-znacheniya,
form:has(select[name="tip"] option[value="phone"]:checked) .anketa-znacheniya,
form:has(select[name="tip"] option[value="date"]:checked) .anketa-znacheniya,
form:has(select[name="tip"] option[value="bool"]:checked) .anketa-znacheniya,
form:has(select[name="tip"] option[value="number"]:checked) .anketa-znacheniya,
form:has(select[name="tip"] option[value="long_text"]:checked) .anketa-znacheniya { display: none; }
.anketa-znacheniya .podskazka { font-weight: 400; }

/* Поле анкеты с вариантами (D129, C2-10, ui-2 №25): подпись сверху, как у
   остальных полей формы, варианты — в рамке в тон полю ввода, каждый
   вариант строкой не ниже 40 px. Не сырая рамка fieldset с подписью в
   разрыве. */
fieldset.anketa-pole { border: 0; padding: 0; margin: 0; min-width: 0; display: grid; gap: 0.3rem; }
fieldset.anketa-pole legend { padding: 0; font-weight: 600; font-size: 0.92rem; color: var(--fg); margin-bottom: 0.3rem; }
fieldset.anketa-pole .podskazka { margin: 0; }
fieldset.anketa-pole .varianty { display: grid; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); padding: 0.15rem 0.75rem; }
fieldset.anketa-pole .varianty label.check { min-height: 2.6rem; padding: 0.3rem 0; margin: 0; border-bottom: 1px solid var(--line); cursor: pointer; font-weight: 500; }
fieldset.anketa-pole .varianty label.check:last-child { border-bottom: 0; }
fieldset.anketa-pole .varianty label.check:has(input:checked) { color: var(--brand); }
fieldset.anketa-pole .prezhnie-otvety { margin-top: 0.2rem; }

/* Опасное действие внизу страницы (D129, решение прораба): красная кнопка
   отдельно от безопасных — за чертой и с отступом, подсказка под ней. */
.opasno { margin: 1.75rem 0 1rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.opasno .podskazka { margin-top: 0.5rem; }

/* Опрос по позициям (Э31, Ш31.3). Не ответивший в таблице ответов подсвечен
   классом — рамкой слева и фоном, — а не встроенным style: CSP кабинета его
   отбросил бы молча (см. widthClass в html.ts). Список позиций на экране
   ответа — галочка с названием и ценой слева, поле «сколько» справа. */
.opros-table td.num { text-align: right; }
.opros-table tr.opros-miss td { background: var(--sunken); color: var(--warn); }
.opros-table tr.opros-miss td:first-child { border-left: 3px solid var(--warn); }
.opros-list { list-style: none; padding: 0; margin: 0.5rem 0 1rem; display: grid; gap: 0.5rem; }
.opros-list li { display: flex; align-items: center; gap: 0.6rem; }
.opros-list li > label.check { flex: 1; min-width: 0; }
.opros-list .qty-label { flex: 0 0 auto; margin: 0; }
.opros-list input.qty { width: 4rem; min-height: 2.5rem; text-align: center; }
/* Правка позиций тем, кто ведёт сбор (Ш31.7): своя форма у каждой позиции —
   название во всю ширину, ниже цена, количество и две кнопки одной строкой
   с переносом, чтобы в 390 px ничего не уезжало за край. */
.opros-edit { display: grid; gap: 0.45rem; }
.opros-edit-title { margin: 0; }
.opros-edit-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.opros-edit-row .qty-label { flex: 0 0 auto; margin: 0; }
.opros-edit-row input.qty { width: 4.5rem; min-height: 2.5rem; text-align: center; }

/* ── Опрос по макету (Ш31.9, D127/D128) ─────────────────────────────────
 *
 * Экраны опроса и открытого сбора с позициями (`opros.ts`,
 * `otchet-protsessa.ts`) — по макету `maket-opros.html`, утверждённому
 * владельцем 22.09.2026, теми же токенами, что и остальной кабинет.
 * Карточка `.ocard` — бумага с тенью; кнопки `.btn` — обводка, `.btn.p` —
 * фирменная, `.btn.sm` — мелкая; таблица `.ot` с нумерованными столбцами
 * позиций; полоса `.obar` в доли; пилюли статуса `.st`. Ни одного
 * встроенного стиля: ширина долей — классами `p5`…`p100` (см. `.bar-3`). */
.opros .oh1 { margin: 0.2rem 0 0.2rem; font-size: 1.5rem; }
.oh1 { margin: 0.2rem 0 0.2rem; font-size: 1.5rem; }
.osub { color: var(--muted); font-size: 0.92rem; margin: 0 0 0.7rem; }
.tag.ok { background: var(--ok-soft); color: var(--ok); }

.ocard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 0.8rem 0.9rem;
  margin: 0 0 0.7rem;
}
.ocard h2 { margin: 0 0 0.5rem; font-size: 0.8rem; letter-spacing: 0.05em; color: var(--muted); }
.ocard .legend.gap { margin-bottom: 0.5rem; }

.orow { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
/* Номер столбца позиции — кружок в цвет кабинета с цифрой: символы ①② в системных
 * шрифтах тонкие и невзрачные, свой значок одинаков везде. */
.cn { display: inline-flex; align-items: center; justify-content: center; width: 1.35rem; height: 1.35rem; border-radius: 50%; background: var(--brand-soft); color: var(--brand); font-style: normal; font-weight: 700; font-size: 0.78rem; line-height: 1; vertical-align: middle; }
/* Освобождённые — свёрнутый список под таблицей, не строки в ней. */
.exempt-list { margin: 0.6rem 0 0; }
.exempt-list summary { cursor: pointer; display: flex; align-items: center; min-height: 2.5rem; color: var(--muted); font-size: 0.82rem; font-weight: 400; }
.legend-list { list-style: none; margin: 0.4rem 0 0; padding: 0; font-size: 0.82rem; color: var(--muted); }
.legend-list li { padding: 0.12rem 0; }
.legend-list .cn { margin-right: 0.3rem; }
table.ot td.words { white-space: normal; font-size: 0.78rem; font-weight: 600; line-height: 1.25; min-width: 4.6rem; }
.exempt-list .rows { margin-top: 0.5rem; }
.exempt-list .orow { align-items: center; }
.orow .sum { font-size: 1.35rem; font-weight: 800; }
.orow.gap { margin-top: 0.5rem; }

/* Строка позиции переносит цену на вторую строку, когда вместе с названием
   она не помещается (D129, A7: «520 ₽ · нужно 2» вылезала за карточку на
   18 px, ui-1 прокрутки). Название сжимается до слова, цена не режется. */
.checks .check-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.6rem; padding: 0.55rem 0; border-bottom: 1px solid var(--line); }
.checks .check-row:last-child { border-bottom: 0; }
.check-row > span:not(.box):not(.price):not(.mark) { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.check-row .price { margin-left: auto; flex: 0 0 auto; color: var(--muted); white-space: nowrap; }
.box { width: 20px; height: 20px; border: 2px solid var(--faint); border-radius: 5px; flex: none; }
.box.on { background: var(--brand); border-color: var(--brand); position: relative; }
.box.on::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 6px;
  height: 11px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Кнопки макета: обводка по умолчанию, `.p` — фирменная, `.sm` — мелкая.
   Класс сильнее общего `button` (0,0,1 против 0,1,0), поэтому и <button>,
   и <a> одного вида. Формы в ряду кнопок не добавляют отступов. */
.btns { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; margin-top: 0.6rem; }
.btns form { margin: 0; display: contents; }
.btn, button.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  padding: 0.55rem 0.95rem;
  min-height: 2.5rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.92rem;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: none;
}
.btn.p, button.btn.p { background: var(--brand); color: #fff; border-color: var(--brand); }
/* «Мелкая» кнопка — уже, но не ниже остальных: цель касания та же. */
.btn.sm, button.btn.sm { padding: 0.35rem 0.65rem; font-size: 0.85rem; min-height: 2.5rem; }
.btn:hover { border-color: var(--brand); color: var(--brand); filter: none; }
.btn.p:hover { color: #fff; filter: brightness(1.07); }

.obar { height: 8px; border-radius: 999px; background: var(--line); overflow: hidden; display: flex; margin: 0.5rem 0; }
.obar i { display: block; height: 100%; border-radius: 0; }
.obar i.g { background: var(--ok); }
.obar i.w { background: #e0a11c; }
.obar i.r { background: var(--bad); }
.obar i.n { background: var(--faint); }

.legend { display: flex; gap: 0.7rem; flex-wrap: wrap; font-size: 0.8rem; color: var(--muted); }
.legend b { color: var(--fg); }
.legend i { display: inline-block; width: 0.6rem; height: 0.6rem; border-radius: 2px; margin-right: 0.3rem; vertical-align: middle; }
.legend i.g { background: var(--ok); }
.legend i.w { background: #e0a11c; }
.legend i.r { background: var(--bad); }
.legend i.n { background: var(--faint); }

/* Таблица «ребёнок × позиции → сумма»: при 2–4 позициях помещается в
   390 px без прокрутки — столбцы позиций нумерованы ①②, расшифровка под
   таблицей; при пяти и более (`.wide`) — прокрутка вбок широкой полосой,
   столбец имени закреплён. */
.owrap { overflow-x: auto; scrollbar-width: auto; }
.owrap::-webkit-scrollbar { height: 12px; }
.owrap::-webkit-scrollbar-thumb { background: var(--faint); border-radius: 6px; }
table.ot { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
table.ot th, table.ot td { padding: 0.4rem 0.25rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; white-space: nowrap; }
/* Имя — единственный столбец, который умеет сжиматься: переносится по
   словам, а в крайнем случае и внутри слова, но не уже 3rem; столбцы
   позиций — 1.8rem ровно (кружок номера 1.35rem и по 0.1rem по бокам),
   сумма и статус — по содержимому. Так таблица
   с четырьмя позициями укладывается в 390 px без прокрутки (D129, A7:
   ui-2 №17 — 334 > 327 уже при четырёх; ui-1 №32 — «освобождён» обрезан). */
table.ot td.name { white-space: normal; min-width: 3rem; overflow-wrap: anywhere; line-height: 1.25; }
table.ot th { font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
table.ot td.n, table.ot th.n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; width: 1.8rem; min-width: 1.8rem; padding-left: 0.1rem; padding-right: 0.1rem; }
table.ot td:last-child, table.ot th:last-child { padding-right: 0; }
table.ot td.n:last-child, table.ot th.n:last-child { padding-right: 0.1rem; }
table.ot tr.miss td { background: var(--warn-soft); }
table.ot tr.ex td { color: var(--muted); white-space: normal; }
table.ot tr.ex form { display: block; margin-top: 0.3rem; }
table.ot tr.tot td { font-weight: 700; border-top: 2px solid var(--line); border-bottom: 0; }
table.ot.wide { width: max-content; min-width: 100%; }
table.ot.wide th:first-child, table.ot.wide td:first-child { position: sticky; left: 0; background: var(--surface); z-index: 1; }
table.ot.wide tr.miss td:first-child { background: var(--warn-soft); }
table.ot.wide th.n, table.ot.wide td.n { min-width: 3.2rem; }
table.ot.wide td.name, table.ot.wide th:first-child { white-space: nowrap; min-width: 0; max-width: 7.5rem; overflow: hidden; text-overflow: ellipsis; }
.tbl-note { font-size: 0.78rem; color: var(--muted); margin: 0.3rem 0 0; }

.st { display: inline-block; font-size: 0.7rem; font-weight: 700; padding: 0.1rem 0.4rem; border-radius: 999px; white-space: nowrap; }
.st.ok { background: var(--ok-soft); color: var(--ok); }
.st.w { background: var(--warn-soft); color: var(--warn); }
.st.r { background: var(--bad-soft); color: var(--bad); }
.st.n { background: var(--line); color: var(--muted); }

.note { font-size: 0.85rem; color: var(--muted); margin: 0.4rem 0 0; }
.note.nb { margin: 0 0 0.7rem; }
.note.ok { color: var(--ok); }
.alert { background: var(--warn-soft); color: var(--warn); border-radius: 10px; padding: 0.55rem 0.7rem; font-size: 0.88rem; margin: 0 0 0.7rem; }
.okmsg { background: var(--ok-soft); color: var(--ok); border-radius: 10px; padding: 0.55rem 0.7rem; font-size: 0.88rem; margin: 0 0 0.7rem; }

/* Форма «Новый опрос» / «Позиции» (макет, экран 1): подписи полей,
   позиция — название во всю ширину, под ним два поля с подписями «цена, ₽»
   и «штук на ребёнка»; все поля одной высоты, ничего не режется. */
.oform { display: grid; gap: 0.6rem; }
.oform .ofield, .oform label.ofield { display: grid; gap: 0.25rem; font-size: 0.85rem; font-weight: 600; color: var(--fg); min-width: 0; }
.oform .olabel { font-size: 0.85rem; font-weight: 600; }
.oform input { min-height: 2.6rem; font-weight: 400; }
.inp-static { border: 1px solid var(--line); border-radius: 10px; padding: 0.55rem 0.7rem; min-height: 2.6rem; background: var(--sunken); font-weight: 400; font-size: 0.95rem; }
.prows { display: grid; gap: 0; }
.prow { display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem; margin-bottom: 0.6rem; padding-bottom: 0.6rem; border-bottom: 1px dashed var(--line); }
.prow label { display: grid; gap: 0.15rem; min-width: 0; font-weight: 400; }
.prow .full { grid-column: 1 / -1; }
.prow .lbl { font-size: 0.75rem; color: var(--muted); font-weight: 500; }
.prow input { min-height: 2.4rem; padding: 0.45rem 0.5rem; font-size: 0.9rem; }
/* «+ ещё позиция» — кнопка с рамкой, как .btn.sm, а не строка-ссылка
   (D129 мелочь, ui-1 №35–36: без рамки читалась ссылкой и терялась среди
   полей). Цвет остаётся фирменным — это действие формы, не переход. */
.oform button.add {
  justify-self: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--brand);
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.35rem 0.85rem;
  min-height: 2.5rem;
  box-shadow: none;
}
.oform button.add:hover { filter: none; border-color: var(--brand); }

/* ── D129, деньги ────────────────────────────────────────────────────────
 *
 * Правки экранов «Деньги» по мерилу D129 (Ш31.11, исполнитель B). Общие
 * правила — отклик `:active`, стрелки у раскрывашек, высота кнопок, класс
 * подсказки `.podskazka` — в блоке исполнителя A выше; здесь только то, что
 * нужно самим денежным экранам. */
/* Опасное действие в ряду кнопок макета (`.btns`): «Отменить взнос»,
   «Отменить сбор» — красная, как `button.danger`, но того же размера, что
   соседние `.btn`; правило ниже общего `.btn`, поэтому побеждает. */
.btn.danger, button.btn.danger { background: #d93838; color: #fff; border-color: transparent; }
.btn.danger:hover, button.btn.danger:hover { background: #c22929; color: #fff; filter: none; }
/* Бейдж «Срок прошёл …, сбор ещё открыт» (B2): предупреждение, не ошибка. */
.tag.warn { background: var(--warn-soft); color: var(--warn); }
/* Позиции в карточке ребёнка — список, не флажки (B8): «✓» у отмеченной,
   «—» у неотмеченной (она приглушена), пусто — ответа ещё нет. */
.check-row .mark { flex: none; width: 1.2rem; text-align: center; font-weight: 700; color: var(--brand); }
.check-row.off .mark { color: var(--faint); }
.check-row.off > span:nth-child(2), .check-row.off .price { color: var(--muted); }
/* Раскрывашка-кнопка (B22): `summary.btn` выглядит и стоит в ряду `.btns` как
   кнопка, за ней — форма; открытая занимает весь ряд, соседние кнопки
   уходят ниже. */
.fold-btn { display: inline-block; }
.fold-btn > summary { list-style: none; }
.fold-btn > summary::-webkit-details-marker { display: none; }
.fold-btn > summary::marker { content: ""; }
.btns .fold-btn[open] { flex: 1 1 100%; }
.fold-btn[open] > summary { margin-bottom: 0.5rem; }
.fold-btn .block, .fold-btn .fold-body { margin: 0.3rem 0 0; }
.fold-btn .fold-body .podskazka { margin: 0 0 0.5rem; }
/* Подпись «Принято, ₽» у поля суммы в панели сбора (B17): над полем, мелко,
   поле и кнопка — в строку под ней. */
.row-tail form.prinyat { display: grid; grid-template-columns: auto 1fr auto; gap: 0.2rem 0.4rem; align-items: center; flex: 1 1 100%; }
.row-tail form.prinyat .lbl { grid-column: 1 / -1; font-size: 0.78rem; color: var(--muted); font-weight: 500; }
.row-tail form.prinyat input { grid-column: 1 / 3; min-width: 0; width: auto; }
.ledger summary .sum small { display: block; font-size: 0.72rem; font-weight: 500; color: var(--muted); text-align: right; }
/* Подпись у крупной цифры («В кассе сейчас 470 ₽», «100 ₽ с человека», B11/B14):
   обычным весом и размером текста, сама цифра — крупно. */
.big-sum .quiet { font-weight: 500; font-size: 0.95rem; letter-spacing: 0; }
/* Итог таблицы «По классу: N детей» (B16) переносится, а не режется троеточием. */
table.ot tr.tot td.name { white-space: normal; max-width: 7.5rem; overflow: visible; text-overflow: clip; line-height: 1.2; }
/* «шт.» под номером столбца позиции и у поля количества (B16). */
table.ot th .unit { display: block; font-size: 0.62rem; letter-spacing: 0; text-transform: none; font-weight: 500; }
.opros-list .qty-label { display: flex; align-items: center; gap: 0.3rem; }
.qty-label .unit { color: var(--muted); font-size: 0.85rem; }
/* Связка сбора с задачей, событием, закупкой (B15): кнопка-действие и имя серым рядом. */
.link-line { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 0.35rem 0; font-size: 0.9rem; }


/* ── D129, стол и события ──────────────────────────────────────────────────
 *
 * Правки C1 круга Ш31.11: стол, задачи, события, профиль. Общие правила
 * (:active, стрелки, высота кнопок, .podskazka) — в блоке A выше, здесь
 * только то, что нужно этим экранам.
 */

/* «Выйти» в профиле и на «Входах» (C1-1): отдельной строкой под ролями, с
   воздухом от текста над ней. */
.vyhod-form { margin: 1.25rem 0 0; }

/* Карточка события (C1-2): ряд команд организатора под шапкой и раскрывашка
   «Отменить событие» внизу — заголовок в виде кнопки-обводки опасного цвета,
   кнопка внутри — обычная `danger`. */
.sobytie-komandy { margin: 0.25rem 0 1rem; }
.otmena-fold { margin: 1.5rem 0 0.5rem; }
.otmena-fold summary.btn { color: var(--bad); border-color: var(--bad); list-style: none; }
.otmena-fold summary::marker, .otmena-fold summary::-webkit-details-marker { display: none; }
.otmena-fold summary.btn:hover { color: #fff; background: var(--bad); border-color: var(--bad); }
.otmena-fold[open] summary.btn { color: #fff; background: var(--bad); }
.otmena-fold .block { margin-top: 0.75rem; }

/* Опасная кнопка отдельно от безопасных (решение прораба D129): свой ряд с
   воздухом сверху — «Убрать задачу» на карточке и под формой правки (C1-3). */
.btns.opasnoe { margin-top: 1.5rem; }

/* Профиль и «Входы» (C1-15): карточка устройств с кнопкой стоит в потоке,
   не в сетке карточек стола; «Закрыть все остальные» — под списком. */
main > .card { margin: 0.75rem 0 0; }
.vhody-vse { margin: 0.75rem 0 1rem; }

/* Простой список имён (C1-14): «Кто согласился», «Кто прочитал» — строки не
   нажимаются, и карточками с тенью выглядеть не должны. */
.spisok-prostoj { list-style: none; padding: 0; margin: 0.5rem 0 1.25rem; }
.spisok-prostoj li { padding: 0.55rem 0; border-bottom: 1px solid var(--line); }
.spisok-prostoj li:last-child { border-bottom: 0; }

/* Подробность дела на столе («принести», «сдать 420 ₽») — своей строкой под
   заголовком-ссылкой, рядом бирка срока и ребёнок. */
.deed-detail { margin-right: 0.35rem; }

/* Вводная строка ученика на столе (C1-6): под заголовком, до карточек. */
.vvodnaya { margin: -0.25rem 0 1rem; }

/* Прошедший срок (C1-7): та же бирка, что «до 11 сентября», но красная —
   просрочку видно, не вчитываясь в дату. */
.due.proshel { background: var(--bad-soft); color: var(--bad); }

/* «Кому» в новой задаче (C1-9): пока отмечено «Всему классу», список детей
   приглушён — флажки исключают друг друга, и это видно до нажатия. `:has()`
   без поддержки просто ничего не приглушает; скрипт взаимного снятия
   (script.ts) работает и так. */
.komu-ili { margin: 0.1rem 0 0; }
.komu-deti { display: grid; gap: 0.7rem; transition: opacity 0.15s; }
.komu:has([data-vse-vsem]:checked) .komu-deti { opacity: 0.45; }

/* «Когда» у события (C1-5): два поля с подписями «Начало» и «Окончание (если
   нужно)» — рядом на широком окне, друг под другом на телефоне. Тире между
   ними больше нет: подписи говорят сами. */
.kogda { display: grid; gap: 0.7rem; grid-template-columns: 1fr 1fr; }
@media (max-width: 42rem) {
  .kogda { grid-template-columns: 1fr; }
}

/* Отклик на нажатие — общий блок A, последним: его :active не должен перекрываться :hover других блоков той же силы. */
/* ── D129, оболочка: отклик на наведение и нажатие (Ш31.11, A2/A9) ─────────
 *
 * До этого во всём кабинете было одно правило `:active` — у карточки-ссылки
 * (`.card-click`), а у кнопок только `:hover`. На телефоне наведения нет,
 * и нажатие ничем не подтверждалось (ui-1 общ. №1, ui-2 №32, ui-3). Одно
 * общее правило на всё, что нажимается: кнопки, ссылки-кнопки, вкладки,
 * пункты нижней панели и бокового меню. Сжатие на 2 % и лёгкое потемнение —
 * заметно под пальцем, но не прыгает.
 *
 * Стоит в самом конце файла нарочно: `:active` должен побеждать все
 * `:hover` той же силы выше (`.btn:hover { filter: none }`, `button.off:hover`),
 * а при равной специфичности побеждает то, что ниже.
 */
button:active, .btn:active, button.btn:active, a.big:active, a.danger:active, .cancel:active,
.actions a:active, .tabs a:active, nav a:active, .file-pick:active .file-pick-btn,
.bank-btn:active, .max-open:active, .calendar-create-box a:active, .stend-persona:active {
  transform: scale(0.98);
  filter: brightness(0.94);
}
button.off:active, .btn:active, .cancel:active, .actions a:active { filter: brightness(0.94); }
button:disabled:active, .btn:disabled:active { transform: none; filter: none; }

/* Наведение там, где его не было: подвкладки, пункты панелей, ряды книги
   фонда и панели управления сбором. Фон — тот же тон, что у нажатой
   вкладки, чтобы «здесь можно нажать» читалось одинаково везде. */
.tabs a:hover { color: var(--brand); background: var(--sunken); }
.tabs a.here:hover { background: var(--brand-soft); }
.side-extra a:hover { color: var(--brand); background: var(--sunken); }
.tabs.sub a:hover { border-color: var(--brand); color: var(--brand); background: var(--surface); }
.tabs.sub a.here:hover { border-color: transparent; background: var(--brand-soft); }
.ledger summary:hover, details.fold summary:hover { background: var(--sunken); }
.ledger.income summary:hover { background: color-mix(in srgb, var(--ok-soft) 70%, var(--sunken)); }
.ledger.spending summary:hover { background: color-mix(in srgb, var(--rest-num) 22%, var(--surface)); }
.ledger summary:active, details.fold summary:active { transform: scale(0.99); }
:where(details) > :where(summary:not([class])):active { transform: scale(0.98); filter: brightness(0.94); }

/* ── Пробный кабинет (Э32) ─────────────────────────────────────────────── */

.demo-plashka {
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.82rem;
  line-height: 1.35;
  padding: 0.5rem 1rem;
  text-align: center;
  border-bottom: 1px solid #f0d9b8;
}
