/* Кабинеты школы: родитель, партнёр, админка, страница эфира. Шрифты и reset —
   из /styles.css (подключать после него), но заголовки лендинга (Cormorant)
   на утилитарном интерфейсе не нужны: h1–h3 здесь переопределены на Manrope.

   Дизайн v2 (issue 070). Два правила, которые держат всю систему:
   1. Один акцент на весь портал — синий --s-accent, и он означает «здесь действие».
      Семантические цвета (ok/warn/bad) носят статус: пара цвет+фон — только в бейджах,
      одиночный цвет — только на статусной подписи («сделано», грейс доступа).
      На кнопке или ссылке статусного цвета не бывает никогда.
   2. Одна система скруглений — 8 px у всего, что нажимают и заполняют,
      12 px у обособленных поверхностей (таблица, плитка), 6 px у бейджей.
      Никаких 10/14/18 — если понадобилось новое число, ошибка в другом месте.
   Теней нет: иерархию держат разделители, воздух и вес шрифта. */
:root {
  color-scheme: light;
  --s-bg: #FFFFFF;
  --s-surface-2: #F4F5F7;
  --s-hover: #F7F8FA;
  --s-border: #E4E7EC;
  --s-border-strong: #CDD2DA;
  --s-text: #15171C;
  --s-text-2: #3D434E;
  --s-text-3: #5E6470;
  --s-accent: #1B63D6;
  --s-accent-dark: #1552B4;
  --s-accent-weak: #EAF1FD;
  --s-danger: #B3261E;
  --s-ok: #1E6B3A;
  --s-ok-bg: #E6F4EA;
  --s-warn: #7A5200;
  --s-warn-bg: #FFF4D6;
  --s-bad: #B3261E;
  --s-bad-bg: #FDECEA;
  --s-off: #5E6470;
  --s-off-bg: #EEF0F3;
}

/* ── страница ── */
html, body { margin: 0; background: var(--s-bg); color: var(--s-text); font-family: var(--f-ui); }
body { min-height: 100dvh; display: flex; flex-direction: column; }
h1, h2, h3 { font-family: var(--f-ui); }
.wrap { width: 100%; max-width: 640px; margin: 0 auto; padding: 16px 16px 40px; flex: 1; display: flex; flex-direction: column; }
/* Админка и кабинет партнёра: таблицы 065/067 перестают скроллиться на десктопе. */
.wrap.wide { max-width: 920px; }
/* Вкладка учеников (172): пять колонок помещаются без прокрутки — широкий контейнер только ей. */
.wrap.wide:has(#family-list), .wrap.wide:has(#table-box), .wrap.wide:has(#pg-root), .wrap.wide:has(#lv-root) { max-width: 1440px; }
/* /styles.css даёт section { padding: 120px 0 } для лендинга — кабинетам это не нужно. */
.wrap section { padding: 0; }
[hidden] { display: none !important; }

/* ── шапка: заголовок слева, язык и «Выйти» текстом справа ── */
.top { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.top h1 { font-size: 20px; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; margin: 0; }
.top-right { display: flex; align-items: baseline; gap: 14px; flex: none; }
.langs { display: flex; align-items: baseline; gap: 8px; }
.langs a { color: var(--s-text-3); text-decoration: none; font-size: 13px; }
.langs a.on { color: var(--s-text); font-weight: 600; }
.langs a + a::before { content: "·"; margin-right: 8px; color: var(--s-border-strong); }
.top-right .link { color: var(--s-text-3); font-size: 13px; }
.top-right .link:hover { color: var(--s-text); }
.roles { display: flex; gap: 14px; margin: -8px 0 16px; }
.roles a { color: var(--s-text-3); text-decoration: none; font-size: 13px; }
.roles a.on { color: var(--s-text); font-weight: 600; }

/* ── вкладки: подчёркивание, а не пилюли ── */
.tabs { display: flex; gap: 20px; overflow-x: auto; border-bottom: 1px solid var(--s-border); margin-bottom: 4px; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs button { flex: none; background: none; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; color: var(--s-text-2); padding: 10px 2px; font: 500 14px/1.2 var(--f-ui); cursor: pointer; white-space: nowrap; }
.tabs button:hover { color: var(--s-text); }
.tabs button.on { color: var(--s-text); font-weight: 600; border-bottom-color: var(--s-accent); }

/* ── разделы: .card — не коробка, а раздел с разделителем сверху ── */
.card { padding: 20px 0; }
.card + .card { border-top: 1px solid var(--s-border); }
.card h2 { font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--s-text); margin: 0 0 12px; }
/* Свёрнутая карточка ученика (074) — раздел без .card, но заголовки в ней те же. */
.card h3, .wk-fold h3 { font-size: 13px; font-weight: 500; color: var(--s-text-3); margin: 16px 0 6px; }
/* Вертикальный ритм раздела: соседние блоки не слипаются. Специфичность выше
   одиночного класса — иначе собственные margin: 0 у .muted и .list обнуляли бы шаг.
   Строки .row идут вплотную: у них свой шаг и разделитель. */
.card > *:not(:first-child) { margin-top: 12px; }
.card > .row + .row { margin-top: 0; }

/* ── текст ── */
.muted { color: var(--s-text-3); font-size: 13px; line-height: 1.55; margin: 0; }
/* Ведущий абзац раздела — это текст, а не подпись под полем: 15 px по шкале. */
.card > p.muted:first-child { color: var(--s-text-2); font-size: 15px; }
.row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0; color: var(--s-text-3); font-size: 13px; }
.row + .row { border-top: 1px solid var(--s-border); }
.row b { color: var(--s-text); font-weight: 500; font-size: 15px; text-align: right; }
.link { background: none; border: 0; padding: 0; color: var(--s-accent); font: 500 14px/1.4 var(--f-ui); text-decoration: none; cursor: pointer; }
.link:hover { text-decoration: underline; }
.center-text { text-align: center; margin-top: 14px; font-size: 13px; }
.center-text a { color: var(--s-accent); text-decoration: none; }
.center-text a:hover { text-decoration: underline; }
.code { font: 600 15px/1.2 var(--f-ui); letter-spacing: 0.06em; color: var(--s-text); }
.device-code { font: 700 28px/1.2 var(--f-ui); letter-spacing: 0.14em; color: var(--s-text); margin: 8px 0; }
.center { text-align: center; padding: 48px 0; }
.center h2 { font-size: 20px; font-weight: 600; margin: 0 0 10px; }
.center p { color: var(--s-text-2); font-size: 15px; line-height: 1.55; margin: 0 auto 6px; max-width: 420px; }
.foot { margin-top: auto; padding-top: 28px; color: var(--s-text-3); font-size: 12px; line-height: 1.5; text-align: center; }
.foot a { color: var(--s-text-3); }

/* ── кнопки. Одна залитая на форму или раздел, остальное — вторичные и ссылки ── */
.cta { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: auto; height: 40px; box-sizing: border-box; border: 1px solid transparent; border-radius: 8px; padding: 0 16px; font: 600 14px/1.2 var(--f-ui); cursor: pointer; text-decoration: none; margin-top: 12px; }
.cta-primary { background: var(--s-accent); border-color: var(--s-accent); color: #FFFFFF; }
.cta-primary:hover { background: var(--s-accent-dark); border-color: var(--s-accent-dark); }
.cta-second { background: #FFFFFF; color: var(--s-text); border-color: var(--s-border-strong); }
.cta-second:hover { background: var(--s-hover); }
.cta:active { transform: scale(0.98); }
.cta:focus-visible, .adm-btn:focus-visible, .link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--s-accent-weak); }
/* Кнопки подряд — в .actions: они встают в строку, а не столбиком во всю ширину. */
.actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.actions .cta { margin-top: 0; }
/* Во всю ширину — только экраны входа, писем и приглашения: там кнопка одна и она же цель экрана. */
#auth .cta, #reset .cta, #complete .cta, #invite-email .cta, #invite-setup .cta, #new-password .cta { width: 100%; }

/* ── поля: подпись над полем, подсказка под ним ── */
.field { display: grid; gap: 6px; margin-bottom: 14px; font: 500 13px/1.4 var(--f-ui); color: var(--s-text-2); }
.field input, .field select, .field textarea { width: 100%; height: 40px; box-sizing: border-box; background: #FFFFFF; border: 1px solid var(--s-border-strong); color: var(--s-text); border-radius: 8px; padding: 0 12px; font: 400 15px/1.3 var(--f-ui); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--s-accent); box-shadow: 0 0 0 3px var(--s-accent-weak); }
.field textarea { height: auto; min-height: 120px; padding: 10px 12px; line-height: 1.5; resize: vertical; }
.check { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; color: var(--s-text-2); line-height: 1.5; margin: 4px 0 10px; }
.check input { margin-top: 2px; accent-color: var(--s-accent); }
.check a { color: var(--s-accent); }
/* Формы в широком контейнере читаются строкой в 560 px; строчные .adm-line — исключение.
   Ведущий абзац раздела ограничен мерой строки: 920 px текста в одну строку не читаются. */
.wide form.card, .wide .card form, .wide .card > .field, .wide .card > .adm-grid { max-width: 560px; }
.wide .card form.adm-line, .wide .card .adm-line { max-width: none; }
.wide .card > p.muted:first-child { max-width: 68ch; }

/* ── бейджи: единственное место, где живут семантические цвета ── */
.badge { display: inline-block; padding: 2px 8px; border-radius: 6px; font: 600 12px/1.5 var(--f-ui); }
.badge-ok { color: var(--s-ok); background: var(--s-ok-bg); }
.badge-warn { color: var(--s-warn); background: var(--s-warn-bg); }
.badge-bad { color: var(--s-bad); background: var(--s-bad-bg); }
.badge-off { color: var(--s-off); background: var(--s-off-bg); }
/* Бейджи легенды воронки (172) — кнопки-фильтры: выбранный обведён акцентом, как плитка. */
button.badge { border: 0; cursor: pointer; }
.badge.on { outline: 2px solid var(--s-accent); outline-offset: 1px; }

/* .msg — не только ошибки: сюда же падают «письмо отправлено» и счётчики рассылки.
   Хелперы message()/showMessage() принимают один лишь текст и успех от ошибки не
   отличают, поэтому коробка нейтральная; красный оставлен за .access.bad. */
.msg { margin: 10px 0 0; padding: 8px 10px; border-radius: 8px; background: var(--s-surface-2); color: var(--s-text); font-size: 13px; line-height: 1.45; }

/* ── списки ── */
.list { display: grid; margin: 0; padding: 0; list-style: none; }
.list li { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--s-border); }
.list li:last-child { border-bottom: 0; }
.avatar { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--s-accent-weak); color: var(--s-accent); font-weight: 600; font-size: 13px; flex: none; }
.list li a { display: grid; gap: 3px; width: 100%; color: var(--s-text); text-decoration: none; font-size: 15px; }
.tasks li { justify-content: space-between; font-size: 15px; }

/* ── строки с формой внутри: партнёры и коды, эфиры, FAQ, приглашения ── */
.list li.adm-row { flex-direction: column; align-items: stretch; gap: 6px; }
.adm-row > b { font-size: 15px; font-weight: 600; color: var(--s-text); }
/* Строка «Ждут решения», на которую вела ссылка из Telegram (106). */
.list li.adm-row.on { margin: 0 -10px; padding: 10px; border-radius: 8px; background: var(--s-accent-weak); }
.adm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.adm-line { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 2px; }
.adm-line input, .adm-line select { flex: 1 1 200px; min-width: 0; height: 32px; box-sizing: border-box; background: #FFFFFF; border: 1px solid var(--s-border-strong); color: var(--s-text); border-radius: 8px; padding: 0 10px; font: 400 13px/1.3 var(--f-ui); }
.adm-line input:focus, .adm-line select:focus { outline: none; border-color: var(--s-accent); box-shadow: 0 0 0 3px var(--s-accent-weak); }
/* Строчная кнопка в списке — всегда вторичная: 16 залитых «Добавить код» подряд
   сделали бы список стеной акцента, в которой не видно самих школ. */
.adm-btn { flex: none; height: 32px; box-sizing: border-box; background: #FFFFFF; border: 1px solid var(--s-border-strong); color: var(--s-text); border-radius: 8px; padding: 0 12px; font: 500 13px/1.2 var(--f-ui); cursor: pointer; }
.adm-btn:hover { background: var(--s-hover); }
.adm-btn:active { transform: scale(0.96); }
.adm-btn[disabled], .adm-btn.busy { opacity: 0.55; cursor: default; transform: none; }
.adm-row summary { color: var(--s-accent); font-size: 13px; font-weight: 500; margin-top: 2px; }
.adm-row details .field { margin-top: 10px; margin-bottom: 0; }
.adm-row details[open] { padding-bottom: 4px; }

/* ── таблицы (065 сводка по школам, 067 ученики) ── */
.adm-scroll { overflow-x: auto; border: 1px solid var(--s-border); border-radius: 12px; }
.adm-table { border-collapse: collapse; width: 100%; font-size: 13px; line-height: 1.4; color: var(--s-text-2); }
.adm-table th, .adm-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--s-border); white-space: nowrap; vertical-align: top; }
/* Шапка переносится по словам — иначе «Активных устройств за август 2026» одной строкой
   уводит сводку по школам в горизонтальный скролл даже на 920 px. */
.adm-table th { color: var(--s-text-3); font: 500 12px/1.4 var(--f-ui); white-space: normal; }
.adm-table tbody tr:hover { background: var(--s-hover); }
.adm-table tbody tr:last-child td { border-bottom: 0; }
.adm-table td:first-child, .adm-table td b { color: var(--s-text); font-weight: 500; }
.adm-table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* Ссылка в ячейке (171) — тем же кеглем, что и текст строки: строки соседних колонок не разъезжаются. */
.adm-table .link { font-size: 13px; }
/* Кнопки строки — в последней колонке: при горизонтальной прокрутке она остаётся у правого края, кнопки — столбиком. */
.adm-table td:last-child:has(.adm-btn) { position: sticky; right: 0; background: var(--s-bg); box-shadow: inset 1px 0 0 var(--s-border); }
.adm-table tbody tr:hover td:last-child:has(.adm-btn) { background: var(--s-hover); }
.adm-table td:last-child .adm-line { flex-direction: column; align-items: stretch; }
/* Таблица учеников (172): под значением ячейки — вторая строка, ученик — блок. Переносится всё, кроме почты,
   бейджей, ссылок и кнопок: иначе пять колонок не поместились бы без прокрутки уже на 1100 px.
   Заголовок «Последнее занятие» — переключатель сортировки. */
.adm-scroll.students td > div:not(:first-child) { margin-top: 4px; }
.adm-scroll.students td { white-space: normal; }
.adm-scroll.students td b, .adm-scroll.students .badge, .adm-scroll.students .link, .adm-scroll.students .adm-btn { white-space: nowrap; }
.adm-scroll.students td.kids { min-width: 260px; }
.adm-scroll.students td.kids > div:not(:first-child) { margin-top: 6px; }
.adm-scroll.students + .muted { margin-top: 8px; }
.adm-table th button { background: none; border: 0; padding: 0; font: inherit; color: inherit; text-decoration: underline dotted; text-underline-offset: 3px; cursor: pointer; }
.adm-table th button:hover, .adm-table th button[aria-pressed="true"] { color: var(--s-text); }
/* Широкий экран: прокрутки внутри таблицы нет, шапка липнет к верху окна. Линия под шапкой — тенью:
   граница схлопнутой таблицы остаётся на месте и уезжала бы из-под прилипшей шапки. */
@media (min-width: 1100px) {
  .adm-scroll.students { overflow: visible; }
  .adm-scroll.students thead th { position: sticky; top: 0; z-index: 1; background: var(--s-bg); border-bottom: 0; box-shadow: inset 0 -1px 0 var(--s-border); }
  .adm-scroll.students td:last-child:has(.adm-btn) { box-shadow: none; }
}

/* ── оферта партнёра (112, 179): шапка документа, плитки, текст с оглавлением, акцепт.
   Длинные слова и адреса переносятся, таблица реквизитов прокручивается внутри себя —
   страница вбок не едет. ≥ 1100 px оглавление встаёт липкой колонкой слева; уже — сворачивается. ── */
.offer-toc { display: grid; gap: 4px; font-size: 13px; line-height: 1.4; }
.offer-toc a { color: var(--s-accent); }
.card .offer-title { font-size: 20px; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; margin: 0 0 6px; }
.offer-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.offer-status .cta { margin-top: 0; }
.offer-stamp { display: none; }
/* Таблица-обёртка ради колонтитула печати (179): на экране это обычные блоки без шапки. */
.offer-frame, .offer-frame > tbody, .offer-frame > tbody > tr, .offer-frame > tbody > tr > td { display: block; padding: 0; border: 0; }
.offer-frame > thead { display: none; }
.offer-doc { display: block; }
.offer-aside { display: none; }
.offer-fold { margin-bottom: 20px; }
.offer-main { max-width: 68ch; }
.offer { color: var(--s-text-2); font-size: 15px; line-height: 1.6; overflow-wrap: anywhere; }
.offer p { margin: 0 0 10px; }
.offer h2, .offer h3 { color: var(--s-text); font-weight: 600; line-height: 1.3; margin: 28px 0 10px; scroll-margin-top: 12px; }
.offer h2 { font-size: 18px; }
.offer h3 { font-size: 15px; margin-top: 20px; }
.offer ul { margin: 0 0 10px; padding-left: 1.3em; }
.offer li { margin: 0 0 4px; }
.offer blockquote { margin: 0 0 10px; padding: 6px 14px; border-left: 2px solid var(--s-border-strong); color: var(--s-text); }
.offer .clause { padding-left: 3.8em; }
.offer .clause-no { display: inline-block; width: 3.8em; margin-left: -3.8em; color: var(--s-text); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.offer-table { overflow-x: auto; margin: 0 0 14px; }
.offer-table table { border-collapse: collapse; width: 100%; font-size: 13px; line-height: 1.5; }
.offer-table th, .offer-table td { border-bottom: 1px solid var(--s-border); padding: 7px 12px 7px 0; text-align: left; vertical-align: top; overflow-wrap: normal; }
.offer-table th { color: var(--s-text); font-weight: 600; border-bottom-color: var(--s-border-strong); }
.offer-after { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--s-border); }
.offer-after .check { font-size: 15px; color: var(--s-text); margin: 0; }
.offer-after .check input { flex: none; width: 18px; height: 18px; margin: 1px 0 0; }
.offer-accepted { padding: 12px 16px; border-radius: 12px; background: var(--s-ok-bg); color: var(--s-ok); font: 600 14px/1.5 var(--f-ui); }
.cta[disabled] { opacity: 0.55; cursor: default; transform: none; }
@media (min-width: 1100px) {
  .offer-doc { display: grid; grid-template-columns: 220px minmax(0, 68ch); gap: 40px; align-items: start; }
  .offer-aside { display: block; position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto; }
  .offer-fold { display: none; }
}

/* ── плитки сводки: школа партнёра и инфографика условий ── */
.info-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 12px 0 4px; }
.info-card { background: var(--s-surface-2); border: 1px solid var(--s-border); border-radius: 12px; padding: 14px 16px; }
.info-card b { display: block; font: 600 26px/1.15 var(--f-ui); color: var(--s-text); font-variant-numeric: tabular-nums; margin-bottom: 4px; }
.info-card span { display: block; color: var(--s-text-3); font-size: 13px; line-height: 1.35; }
/* Плитки воронки (105) — кнопки-фильтры: выбранная ступень обведена. */
button.info-card { font: inherit; text-align: left; cursor: pointer; }
.info-card.muted b { font-size: 18px; color: var(--s-text-3); }
.info-card.on { border-color: var(--s-accent); }
/* Степпер «Сколько телефонов» (158): число между «−» и «+». */
.stepper { display: inline-flex; align-items: center; gap: 10px; }
.stepper .adm-btn { width: 32px; padding: 0; font-size: 16px; }
.stepper b { min-width: 20px; text-align: center; font-variant-numeric: tabular-nums; }
.pay-phones-btn[disabled] { opacity: 0.55; cursor: default; transform: none; }

/* Телефоны в подписке (159): имя, «заходили» и подпись про бесплатный режим — столбиком рядом с флажком. */
.pay-phone > span { display: grid; gap: 2px; }
.pay-phone b { color: var(--s-text); font-weight: 500; font-size: 15px; }

/* ── свёрнутый раздел: заголовок остаётся заголовком, содержимое прячется.
   Смена пароля и смена школы в «Аккаунте» нужны редко, а полями занимали пол-экрана. ── */
.fold > summary { display: flex; align-items: baseline; gap: 10px; cursor: pointer; list-style: none; color: var(--s-text); font: 600 15px/1.3 var(--f-ui); }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after { content: "+"; margin-left: auto; font-weight: 400; color: var(--s-text-3); }
.fold[open] > summary::after { content: "−"; }
.fold > summary ~ * { margin-top: 12px; }

/* ── эфиры у родителя: «экранчики» как у видео. Постер тёмный и типографический —
   картинок у эфиров нет; единственный цвет на нём — красный бейдж идущего эфира. ── */
.wb-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 16px; }
.wb a { display: block; color: var(--s-text); text-decoration: none; }
.wb-poster { position: relative; display: flex; flex-direction: column; justify-content: flex-end; aspect-ratio: 16 / 9; box-sizing: border-box; padding: 14px 16px; border-radius: 12px; background: #1B1E26; color: #FFFFFF; overflow: hidden; transition: filter 160ms ease; }
.wb a:hover .wb-poster { filter: brightness(1.12); }
.wb-kicker { position: absolute; top: 12px; left: 16px; font: 500 12px/1.3 var(--f-ui); color: #A3A9B5; }
.wb-live { position: absolute; top: 12px; left: 16px; display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px; border-radius: 6px; background: #D93636; color: #FFFFFF; font: 600 12px/1.3 var(--f-ui); }
.wb-live::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #FFFFFF; }
.wb-big { font: 700 22px/1.15 var(--f-ui); letter-spacing: -0.01em; }
.wb-time { margin-top: 2px; font: 500 14px/1.3 var(--f-ui); color: #C9CDD6; font-variant-numeric: tabular-nums; }
.wb-len { position: absolute; right: 10px; bottom: 10px; padding: 2px 6px; border-radius: 6px; background: rgba(0, 0, 0, 0.55); color: #FFFFFF; font: 600 12px/1.4 var(--f-ui); font-variant-numeric: tabular-nums; }
.wb-play { position: absolute; left: 50%; top: 50%; width: 46px; height: 46px; margin: -23px 0 0 -23px; border-radius: 50%; background: rgba(255, 255, 255, 0.92); }
.wb-play::after { content: ""; position: absolute; left: 19px; top: 14px; border-style: solid; border-width: 9px 0 9px 14px; border-color: transparent transparent transparent #15171C; }
.wb-after .wb-big, .wb-after .wb-time { opacity: 0.55; }
.wb-title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-top: 10px; font: 600 15px/1.35 var(--f-ui); }
.wb-meta { display: block; margin-top: 4px; font-size: 13px; color: var(--s-text-3); }

/* ── видеоуроки (054) ── */
.video { display: block; width: 100%; max-height: 420px; border-radius: 12px; background: #15171C; }
/* В админке (182) превью уже кабинетного плеера; прогресс загрузки — акцентным цветом. */
.adm-row .video { max-width: 360px; max-height: 220px; }
.adm-row .adm-line .check { margin: 0; white-space: nowrap; }
.adm-row .adm-line .check input { flex: none; width: 18px; height: 18px; padding: 0; margin: 0; }
.adm-progress { display: block; width: 100%; height: 8px; margin-top: 10px; accent-color: var(--s-accent); }

/* ── FAQ: аккордеон в кабинете и свёрнутая правка в админке ── */
.faq { display: grid; }
.faq details { padding: 12px 0; border-bottom: 1px solid var(--s-border); }
.faq details:last-child { border-bottom: 0; }
.faq summary, .adm-row summary { cursor: pointer; list-style: none; }
.faq summary::-webkit-details-marker, .adm-row summary::-webkit-details-marker { display: none; }
.faq summary { display: flex; gap: 10px; align-items: baseline; color: var(--s-text); font: 500 15px/1.45 var(--f-ui); }
.faq summary::after { content: "+"; margin-left: auto; color: var(--s-text-3); }
.faq details[open] summary::after { content: "−"; }
.faq details p { color: var(--s-text-2); font-size: 14px; line-height: 1.55; margin: 8px 0 2px; white-space: pre-wrap; }

/* ── неделя и курс ученика (issue 041) ── */
.who { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.who b { font-size: 15px; font-weight: 600; }

/* ── неделя ученика (074): полоса семи дней — герой карточки, всё остальное под ней.
   Красного в норме нет: пропущенный день — просто пустая клетка, а не ошибка. ── */
.wk-head { display: flex; align-items: center; gap: 10px; }
.wk-head b { font-size: 15px; font-weight: 600; }
.wk-head .badge { margin-left: auto; }
.wk-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.wk-day { display: grid; gap: 4px; justify-items: center; }
.wk-day i { position: relative; display: block; width: 100%; height: 36px; box-sizing: border-box; border-radius: 8px; background: var(--s-surface-2); }
.wk-day.on i { background: var(--s-accent-weak); }
/* Точка — статус «занимался», а не действие: заливка --s-accent-weak на белом
   почти не отличается от пустой клетки, и полоса переставала читаться формой. */
.wk-day.on i::after { content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--s-accent); }
.wk-day.now i { border: 1px solid var(--s-accent); }
.wk-day b { font: 400 11px/1.2 var(--f-ui); color: var(--s-text-3); }
.wk-day.on b { color: var(--s-text); }
.wk-day.now b { color: var(--s-text); font-weight: 600; }
.wk-meta { margin: 0; color: var(--s-text-2); font-size: 13px; line-height: 1.5; font-variant-numeric: tabular-nums; }
/* ── этапы недели гармошкой (094): текущий раскрыт, остальные свёрнуты. Статус
   этапа — подпись справа: «пройден» несёт одиночный цвет статуса, «впереди» — серый. ── */
.wk-stages-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.wk-stages { display: grid; border-top: 1px solid var(--s-border); }
.wk-stage { padding: 10px 0; border-bottom: 1px solid var(--s-border); }
.wk-stage > summary { font-size: 14px; }
.wk-stage > summary::after { margin-left: 0; }
.wk-stage-status { margin-left: auto; font: 500 12px/1.4 var(--f-ui); color: var(--s-text-3); }
.wk-stage.done .wk-stage-status { color: var(--s-ok); }
.wk-stage.on .wk-stage-status { color: var(--s-text); font-weight: 600; }
.wk-stage .tasks li:last-child { padding-bottom: 0; }
.wk-left { flex: none; font-size: 12px; line-height: 1.3; color: var(--s-text-3); }
/* «Задания пройдены» — статусная строка: одиночный цвет статуса на ней разрешён. */
.wk-done { margin: 0; color: var(--s-ok); font: 600 14px/1.45 var(--f-ui); }
/* ── строка задания (102): крупная иконка упражнения из игры, название, напротив —
   медаль или галочка и под ней подпись в две строки. «пройдено» несёт одиночный
   цвет статуса; синяя в строке — только ссылка «открыть в приложении». ── */
.tk-icon { flex: none; width: 40px; height: 40px; object-fit: contain; }
.tk-name { flex: 1 1 auto; min-width: 0; display: grid; justify-items: start; gap: 2px; line-height: 1.35; }
.tk-name .link { width: auto; font-size: 13px; color: var(--s-accent); }
.tk-right { flex: none; display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 84px; text-align: center; }
.tk-check { width: 24px; height: 24px; color: var(--s-ok); }
.tk-cap { display: grid; font: 400 12px/1.35 var(--f-ui); color: var(--s-text-3); white-space: nowrap; }
.tk-cap b { font-weight: 600; color: var(--s-text); }
.tk-cap b.ok { color: var(--s-ok); }
.wk-course { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--s-text-2); }
.wk-bar { height: 4px; border-radius: 8px; background: var(--s-surface-2); overflow: hidden; }
.wk-bar i { display: block; height: 100%; background: var(--s-accent); }
/* «весь курс» ведёт на соседнюю вкладку, но синей на карточке остаётся одна
   ссылка — «открыть в приложении»: иначе родитель не видит, куда идти первым. */
.wk-more { flex: none; background: none; border: 0; padding: 0; color: var(--s-text-3); font: 500 13px/1.4 var(--f-ui); cursor: pointer; }
.wk-more:hover { color: var(--s-text); }
/* ── совет недели (075): одна мысль, одна кнопка, поверхность второго плана ── */
.wk-advice { background: var(--s-surface-2); border-radius: 12px; padding: 14px 16px; }
.wk-advice b { display: block; font: 600 15px/1.3 var(--f-ui); color: var(--s-text); }
.wk-advice p { margin: 6px 0 0; color: var(--s-text-2); font-size: 14px; line-height: 1.5; }
.wk-advice .cta { margin-top: 12px; }
/* Следующая медаль (094): целевой медальон слева от совета. */
.wk-next { display: flex; align-items: flex-start; gap: 12px; }
.wk-next .tm-trio { margin-top: 2px; }

/* PREMIUM (094, решение М.) — единственный бейдж на акцентной заливке: родитель
   должен с одного взгляда видеть, что Премиум открыт. Это осознанное
   исключение из правила «акцент — только действие». */
.badge-premium { color: #FFFFFF; background: var(--s-accent); letter-spacing: 0.04em; }

/* ── постер рекорда (076): «экранчик» эфиров, медаль вместо хронометража ── */
.wk-record { max-width: 320px; }
.wk-record .wb-poster { display: flex; }
.wk-record .cta { width: 100%; }
/* Медаль на тёмном постере — светлая плашка: цвета на постере по системе нет. */
.wb-medal { position: absolute; right: 10px; bottom: 10px; background: #FFFFFF; color: var(--s-text); }
/* Рекорд сложности (114): медальон испытания, как в игре, — в правом верхнем углу, строкам цепочки не мешает. */
.wb-trial { position: absolute; top: 10px; right: 12px; display: flex; }

.wk-fold { padding: 14px 0; }
.wk-fold + .wk-fold { border-top: 1px solid var(--s-border); }
.wk-fold > summary .wk-sum { color: var(--s-text-3); font: 400 13px/1.4 var(--f-ui); }

/* ── дневник курса (085): 25 тем главами и страница темы. Глава различается
   шапкой и иконкой книги, а не цветным тинтом: четыре тинта на белом — радуга,
   и --s-accent-weak уже занят под «сейчас здесь». ── */
.dy-head { display: flex; align-items: center; gap: 10px; }
.dy-head b { font-size: 15px; font-weight: 600; }
.dy-pos { margin-left: auto; color: var(--s-text-3); font-size: 13px; font-variant-numeric: tabular-nums; }
.dy-chapter { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; margin-top: 18px; padding-bottom: 6px; border-bottom: 1px solid var(--s-border); }
.dy-chapter img { flex: none; width: 28px; height: 28px; }
.dy-ch-title { font: 600 13px/1.3 var(--f-ui); letter-spacing: 0.04em; color: var(--s-text); }
.dy-ch-note { color: var(--s-text-3); font-size: 13px; }
.dy-list { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 2px; }
.dy-row { display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box; padding: 8px 10px; border: 0; border-radius: 8px; background: none; color: var(--s-text-3); font: 400 14px/1.35 var(--f-ui); text-align: left; cursor: pointer; }
.dy-row:hover { background: var(--s-hover); }
.dy-row .n { flex: none; width: 22px; text-align: right; font-size: 12px; font-variant-numeric: tabular-nums; }
.dy-row.done { color: var(--s-text-2); }
.dy-row.on { color: var(--s-text); background: var(--s-accent-weak); font-weight: 500; }
.dy-row.on:hover { background: var(--s-accent-weak); }
.dy-row em { font-style: normal; font-size: 12px; font-weight: 600; color: var(--s-accent); }

.dy-title { display: flex; align-items: flex-start; gap: 14px; }
.dy-title-text { display: grid; gap: 2px; min-width: 0; }
.dy-kicker { font: 600 12px/1.3 var(--f-ui); letter-spacing: 0.04em; color: var(--s-text-3); }
.dy-theme { font: 600 20px/1.25 var(--f-ui); letter-spacing: -0.01em; color: var(--s-text); }
.dy-title .badge, .dy-title .dy-now, .dy-title .dy-status { flex: none; margin-left: auto; }
.dy-status { display: grid; justify-items: end; gap: 4px; }
.dy-status .badge { margin-left: 0; }
.dy-nodate { color: var(--s-text-3); font-size: 12px; line-height: 1.3; }
/* «Сейчас» — тот же приём, что у строки «сейчас здесь» в списке. */
.dy-now { display: inline-block; padding: 2px 8px; border-radius: 6px; background: var(--s-accent-weak); color: var(--s-accent); font: 600 12px/1.5 var(--f-ui); }
.dy-early { color: var(--s-ok); font-weight: 600; }
.dy-next { margin: 0; }

/* ── подробности темы (086): мини-факт в строке и постер самого длинного
   примера. Мини-факт — вторая строка той же кнопки: отдельная строка списка
   разорвала бы попадание по теме надвое. ── */
.dy-row { flex-wrap: wrap; }
.dy-fact { flex: 1 0 100%; padding-left: 32px; color: var(--s-text-3); font-size: 12px; line-height: 1.35; }
.dy-row.on .dy-fact { color: var(--s-text-2); }
.dy-best { max-width: 320px; }
.dy-best .wb-poster { display: flex; }

/* ── три медали испытаний (091): настоящий медальон уровня, а в правом нижнем
   углу — иконка испытания, как на экране медалей в игре. Медальоны — те самые
   «единственные цветные картинки»: вокруг них ни тинтов, ни рамок. Непройденное
   испытание — пустой круг той же формы и без предупреждающего цвета. ── */
.tm-trio { flex: none; display: inline-flex; align-items: center; gap: 10px; }
.tm { position: relative; flex: none; width: 40px; height: 40px; }
.tm-face { display: block; width: 100%; height: 100%; box-sizing: border-box; border-radius: 50%; }
i.tm-face { border: 1px solid var(--s-border-strong); }
.tm-icon { position: absolute; right: -4px; bottom: -4px; width: 16px; height: 16px; }
.tm-24 { gap: 6px; }
.tm-24 .tm { width: 24px; height: 24px; }
.tm-24 .tm-icon { right: -3px; bottom: -3px; width: 12px; height: 12px; }
.dy-row .dy-extern { margin-left: auto; }
.dy-row .dy-extern + .tm-trio { margin-left: 0; }
.dy-row .tm-trio { margin-left: auto; }
.dy-trio-row { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; }
/* «Экстерном» — сдержанная плашка словом: тёмная, без салюта. */
.dy-extern { flex: none; display: inline-block; padding: 2px 8px; border-radius: 6px; background: var(--s-text); color: #FFFFFF; font: 600 12px/1.5 var(--f-ui); letter-spacing: 0.02em; }
.dy-trials { list-style: none; margin: 0; padding: 0; }
.dy-trial { display: grid; grid-template-columns: 20px 1fr auto; column-gap: 10px; align-items: center; padding: 8px 0; font-size: 14px; line-height: 1.4; color: var(--s-text); }
.dy-trial + .dy-trial { border-top: 1px solid var(--s-border); }
.dy-trial b { font-weight: 600; font-size: 13px; }
.dy-trial b.muted { font-weight: 400; color: var(--s-text-3); }
/* Приговор барометра — статусная строка: одиночный цвет статуса на ней правилами разрешён. */
.dy-baro { grid-column: 2 / -1; margin: 2px 0 0; color: var(--s-text-3); font-size: 13px; line-height: 1.45; }
.dy-baro.ok, .dy-baro.raise { color: var(--s-ok); }
.dy-baro.lower { color: var(--s-warn); }
.dy-baro .wk-more { margin-left: 4px; }
.dy-trial-best { grid-column: 2 / -1; margin: 2px 0 0; color: var(--s-text-2); font-size: 13px; line-height: 1.45; font-variant-numeric: tabular-nums; }
.dy-trial-best.up { color: var(--s-ok); }
.dy-frame { color: var(--s-text-3); font-size: 12px; line-height: 1.4; }

/* ── кубки недели (103): уголок ачивок — плитки обособленной поверхности,
   рисованный кубок, под ним число и подпись. Нулевой кубок серый — «ещё не взят». ── */
.wk-cups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; max-width: 360px; }
.cup { display: grid; justify-items: center; gap: 2px; padding: 14px 12px 12px; border-radius: 12px; background: var(--s-surface-2); color: var(--s-text); text-align: center; }
.cup svg { width: 44px; height: 44px; margin-bottom: 4px; }
.cup-n { font: 700 22px/1.2 var(--f-ui); font-variant-numeric: tabular-nums; }
.cup-cap { font: 500 12px/1.35 var(--f-ui); color: var(--s-text-3); }
.cup.off { color: var(--s-border-strong); }
.cup.off .cup-n { color: var(--s-text-3); }

/* ── установка приложения (073): у каждого магазина кнопка, QR и подпись со словом
   «бесплатно» — код без подписи в Казахстане читается как счёт к оплате. ── */
.install { display: flex; flex-wrap: wrap; gap: 12px; }
.install-store { flex: 1 1 200px; max-width: 250px; box-sizing: border-box; display: grid; justify-items: center; gap: 10px; padding: 16px; border: 1px solid var(--s-border); border-radius: 12px; text-align: center; }
.install-store .cta { width: 100%; margin-top: 0; }
.install-qr { display: block; width: 140px; height: 140px; border-radius: 8px; }
.install-cap { color: var(--s-text-3); font-size: 13px; line-height: 1.35; }

/* ── первый экран (104): приглашение в три шага. Шапка — «окно в игру»: ночное
   небо игры (палитра Neurogenie DS: bg/elevated → bg/base, свечение accent/cyan),
   на ней три шага картинками; дальше — шаги лесенкой с номером в круге и линией
   между ними. Текущий шаг — тёмный номер, пройденный — галочка и приглушённый текст. ── */
.wl { padding: 20px 0 8px; }
.wl-hero { position: relative; overflow: hidden; padding: 28px 24px 24px; border-radius: 12px; color: #FFFFFF;
  background: radial-gradient(90% 110% at 100% 0%, rgba(115, 178, 213, 0.30) 0%, rgba(115, 178, 213, 0) 60%), linear-gradient(160deg, #1B2348 0%, #11152C 72%); }
.wl-hero h2 { margin: 0; max-width: 22ch; font: 700 26px/1.2 var(--f-ui); letter-spacing: -0.015em; color: #FFFFFF; }
.wl-hero p { margin: 12px 0 0; max-width: 52ch; font-size: 15px; line-height: 1.55; color: #C9CDD6; }
.wl-rail { display: flex; align-items: center; margin-top: 22px; max-width: 320px; }
.wl-rail-item { flex: none; display: grid; place-items: center; width: 52px; height: 52px; box-sizing: border-box; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.16); background: rgba(255, 255, 255, 0.06); }
.wl-rail-item .wl-art { width: 34px; height: 34px; }
.wl-rail-item.on { border-color: rgba(255, 255, 255, 0.7); }
.wl-rail-item.done { border-color: #64C256; }
.wl-rail-line { flex: 1 1 auto; height: 2px; margin: 0 6px; border-radius: 2px; background: rgba(255, 255, 255, 0.16); }
.wl-steps { list-style: none; margin: 28px 0 0; padding: 0; }
.wl-step { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr); column-gap: 16px; padding-bottom: 28px; }
.wl-step:last-child { padding-bottom: 0; }
.wl-step:not(:last-child)::before { content: ""; position: absolute; left: 15px; top: 48px; bottom: 6px; width: 2px; border-radius: 2px; background: var(--s-border); }
.wl-step.done:not(:last-child)::before { background: var(--s-ok-bg); }
.wl-num { display: grid; place-items: center; width: 32px; height: 32px; margin-top: 8px; box-sizing: border-box; border-radius: 50%; border: 1px solid var(--s-border-strong); color: var(--s-text-2); font: 600 14px/1 var(--f-ui); font-variant-numeric: tabular-nums; }
.wl-step.on .wl-num { border-color: var(--s-text); background: var(--s-text); color: #FFFFFF; }
svg.wl-num { border: 0; color: var(--s-ok); }
.wl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; }
.wl-head h3 { margin: 0; font: 600 18px/1.3 var(--f-ui); color: var(--s-text); }
.wl-art { flex: none; width: 48px; height: 48px; object-fit: contain; }
.wl-text { margin: 6px 0 0; color: var(--s-text-2); font-size: 15px; line-height: 1.6; }
.wl-body > .install, .wl-body > .wl-tg, .wl-body > .cta { margin-top: 16px; }
.wl-ok { margin: 12px 0 0; color: var(--s-ok); font: 600 14px/1.5 var(--f-ui); }
.wl-step.done .wl-head h3, .wl-step.done .wl-text { color: var(--s-text-3); }
.wl-step.done .wl-head .wl-art { opacity: 0.45; }
.wl-tg { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; }
.wl-qr { margin: 0; display: grid; justify-items: center; gap: 8px; }
.welcome-qr { box-sizing: content-box; width: 160px; height: 160px; padding: 16px; border: 1px solid var(--s-border); border-radius: 12px; background: #FFFFFF; }
.welcome-qr svg { display: block; width: 160px; height: 160px; }
.wl-qr figcaption { color: var(--s-text-3); font-size: 12px; line-height: 1.35; }
.wl-actions { flex-direction: column; align-items: flex-start; margin-top: 0; }
.wl-later { background: none; border: 0; padding: 6px 0; color: var(--s-text-3); font: 500 14px/1.4 var(--f-ui); cursor: pointer; }
.wl-later:hover { color: var(--s-text); }
.wl-tg .msg { flex-basis: 100%; }

/* ── доступ семьи (issue 042): строка в разделе «Ученики», а не отдельная коробка.
   Грейс красится текстом — «продлите» должно читаться как срочное; цвет статуса
   при этом несёт бейдж, поэтому рамки и заливки у самой строки нет. ── */
.access { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; padding: 0 0 4px; font-size: 15px; line-height: 1.45; color: var(--s-text); }
.access.bad { color: var(--s-danger); }

/* ── устройства (129): у каждого телефона своя рамка; ученики аккаунта — отдельной
   карточкой выше, они общие для всех телефонов. Рамка — не .card, поэтому ритм
   раздела повторён для её детей. ── */
.device { padding: 14px 16px; border: 1px solid var(--s-border); border-radius: 12px; }
.device > * + * { margin-top: 12px; }
.device-head { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }
.device-head > div { flex: 1 1 auto; }
.device-head .cta { margin-top: 0; }

/* ── «Успеваемость» (174): сетка карточек учеников. Один акцент: этап, полоска недели и
   медали — его оттенки; ошибки — графитовые полоски. Без теней и градиентов, красного на
   ребёнке нет: «стоит заглянуть» — серый бейдж, жёлтый только у «много» в ошибках. ── */
.pg { display: grid; gap: 16px; padding: 20px 0; min-width: 0; }
.pg-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.pg-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; }
.pg-bar-l, .pg-bar-r { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-width: 0; }
.pg-seg { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--s-border-strong); border-radius: 8px; }
.pg-seg button { height: 30px; padding: 0 12px; border: 0; border-radius: 6px; background: none; color: var(--s-text-3); font: 500 13px/1.2 var(--f-ui); cursor: pointer; }
.pg-seg button:hover { color: var(--s-text); }
.pg-seg button[aria-pressed="true"] { background: var(--s-surface-2); color: var(--s-text); font-weight: 600; }
.pg-bar-r input, .pg-bar-r select { height: 36px; box-sizing: border-box; background: #FFFFFF; border: 1px solid var(--s-border-strong); color: var(--s-text); border-radius: 8px; padding: 0 12px; font: 400 14px/1.3 var(--f-ui); }
.pg-bar-r input { width: 260px; max-width: 100%; }
.pg-bar-r input:focus, .pg-bar-r select:focus { outline: none; border-color: var(--s-accent); box-shadow: 0 0 0 3px var(--s-accent-weak); }

.pg-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 4px; }
@media (min-width: 700px) { .pg-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .pg-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pg-card { display: flex; flex-direction: column; gap: 18px; min-width: 0; padding: 20px; border: 1px solid var(--s-border); border-radius: 12px; background: var(--s-bg); }
.pg-top { display: grid; gap: 6px; }
.pg-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.pg-head .badge { flex: none; margin-left: auto; }
.pg-who { display: grid; gap: 2px; min-width: 0; }
.pg-who b { font: 600 15px/1.3 var(--f-ui); color: var(--s-text); overflow-wrap: anywhere; }
.pg-who span { color: var(--s-text-3); font-size: 13px; line-height: 1.35; }
.pg-who .link { font-size: 13px; }
.pg-theme { display: grid; gap: 8px; }
.pg-card .msg { margin: 0; }
.pg-why { margin: 0 0 0 44px; color: var(--s-text-2); font-size: 13px; line-height: 1.45; }

/* Этап — три точки: пройден и текущий залиты акцентом, текущий — с ореолом, впереди — пустая. */
.pg-stage { display: flex; align-items: center; gap: 8px; font: 400 12px/1.3 var(--f-ui); color: var(--s-text-3); }
.pg-st { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.pg-st::before { content: ""; width: 10px; height: 10px; box-sizing: border-box; border-radius: 50%; border: 1.5px solid var(--s-border-strong); background: var(--s-bg); }
.pg-st.done::before, .pg-st.on::before { border-color: var(--s-accent); background: var(--s-accent); }
.pg-st.on::before { outline: 3px solid var(--s-accent-weak); }
.pg-st.on { color: var(--s-text); font-weight: 600; }
.pg-link { flex: 1 1 8px; min-width: 8px; height: 1px; background: var(--s-border-strong); }
.pg-link.done { background: var(--s-accent); }

/* Неделя: семь клеток, три тона акцента по числу подходов; пропуск — пустая клетка. */
.pg-week { display: grid; gap: 10px; }
.pg-strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.pg-day { display: grid; gap: 4px; justify-items: center; font: 400 11px/1.2 var(--f-ui); color: var(--s-text-3); }
.pg-day i { display: block; width: 100%; height: 30px; box-sizing: border-box; border-radius: 8px; background: var(--s-surface-2); }
.pg-day.d1 i { background: color-mix(in srgb, var(--s-accent) 22%, var(--s-bg)); }
.pg-day.d2 i { background: color-mix(in srgb, var(--s-accent) 52%, var(--s-bg)); }
.pg-day.d3 i { background: var(--s-accent); }
.pg-day.later i { background: none; border: 1px dashed var(--s-border-strong); }
.pg-day.now b { color: var(--s-text); font-weight: 600; }
.pg-meta { margin: 0; color: var(--s-text-2); font-size: 13px; line-height: 1.5; font-variant-numeric: tabular-nums; }

.pg-body { display: grid; gap: 18px; padding-top: 18px; border-top: 1px solid var(--s-border); }
.pg-body:empty { display: none; }
.pg-sec { display: grid; gap: 8px; }
.pg-card h3.pg-label { margin: 0; font: 500 12px/1.3 var(--f-ui); color: var(--s-text-3); }
.pg-medals { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px; }
.pg-plus { color: var(--s-text-2); font: 600 13px/1.3 var(--f-ui); }
.pg-lines, .pg-errs { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.pg-lines li { display: flex; flex-wrap: wrap; gap: 2px 8px; color: var(--s-text-2); font-size: 13px; line-height: 1.45; font-variant-numeric: tabular-nums; }
.pg-lines b { color: var(--s-text); font-weight: 600; }
/* Ошибки: иконка испытания, имя, «7 из 40 примеров», под ними тонкая графитовая полоска доли. */
.pg-err { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; align-items: center; gap: 6px 10px; font-size: 13px; line-height: 1.4; }
.pg-err img { width: 24px; height: 24px; object-fit: contain; }
.pg-err-name { color: var(--s-text); }
.pg-err-val { color: var(--s-text-2); text-align: right; font-variant-numeric: tabular-nums; }
.pg-err-val .badge { margin-left: 6px; }
.pg-err > .muted { grid-column: 3; text-align: right; }
.pg-track { grid-column: 2 / -1; height: 4px; border-radius: 8px; background: var(--s-surface-2); overflow: hidden; }
.pg-track i { display: block; height: 100%; background: var(--s-text-2); }
.pg-foot { display: flex; flex-wrap: wrap; gap: 2px 16px; margin-top: auto; color: var(--s-text-3); font-size: 12px; line-height: 1.5; }
.pg-foot span { overflow-wrap: anywhere; }

/* ── Telegram в карточке (180): статус, под ним две кнопки в строку, ниже последнее сообщение нити и свёрнутая переписка.
   Пустой .pg-thread не прячем: пока в нём пусто, за его появлением в окне следит IntersectionObserver. ── */
.pg-tg { padding-top: 18px; border-top: 1px solid var(--s-border); font-size: 13px; line-height: 1.45; }
.pg-tg-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.pg-tg-state { display: flex; flex: 1 0 100%; flex-wrap: wrap; align-items: center; gap: 4px 6px; color: var(--s-text-2); }
.pg-tg a.adm-btn { display: inline-flex; align-items: center; text-decoration: none; }
.pg-thread:not(:empty) { display: grid; gap: 4px; margin-top: 10px; }
.pg-thread p { margin: 0; }
.pg-last-who { color: var(--s-text-3); font-size: 12px; }
.pg-last-who b { color: var(--s-text); font-weight: 600; }
.pg-last-text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; color: var(--s-text-2); white-space: pre-line; overflow-wrap: anywhere; }
.pg-all summary { width: fit-content; margin-top: 4px; color: var(--s-accent); font: 500 13px/1.4 var(--f-ui); cursor: pointer; }
.pg-conv { display: grid; gap: 10px; margin: 8px 0 0; padding: 0; list-style: none; }
.pg-conv li { display: grid; gap: 2px; font-size: 12px; color: var(--s-text-3); }
.pg-conv li.in { padding-left: 10px; border-left: 2px solid var(--s-border-strong); }
.pg-conv b { color: var(--s-text); font-weight: 600; }
.pg-conv p { color: var(--s-text-2); font-size: 13px; white-space: pre-wrap; overflow-wrap: anywhere; }
.pg-dialog { width: min(520px, calc(100% - 32px)); box-sizing: border-box; padding: 20px; border: 1px solid var(--s-border); border-radius: 12px; background: var(--s-bg); color: var(--s-text); }
.pg-dialog::backdrop { background: rgba(21, 23, 28, 0.4); }
.pg-dlg { display: grid; gap: 12px; }
.pg-dlg h3 { margin: 0; font: 600 16px/1.3 var(--f-ui); }
.pg-dlg textarea { width: 100%; box-sizing: border-box; min-height: 140px; padding: 10px 12px; background: #FFFFFF; border: 1px solid var(--s-border-strong); border-radius: 8px; color: var(--s-text); font: 400 14px/1.5 var(--f-ui); resize: vertical; }
.pg-dlg textarea:focus { outline: none; border-color: var(--s-accent); box-shadow: 0 0 0 3px var(--s-accent-weak); }
.pg-dlg .msg { margin: 0; }
.pg-count { text-align: right; font-variant-numeric: tabular-nums; }

/* ── мобильный: широкий контейнер схлопывается, кнопки и плитки — в колонку ── */
@media (max-width: 640px) {
  .info-grid, .pg-tiles { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .wb-grid { grid-template-columns: 1fr; }
  /* Карточки магазинов встают в колонку во всю ширину, QR остаётся по центру. */
  .install-store { max-width: none; flex-basis: 100%; }
  /* Вкладок шесть — жмём шаг и кегль, чтобы в строку влезло как можно больше;
     остальное доскроллит render(), подводящий активную вкладку в поле зрения. */
  .tabs { gap: 16px; }
  .tabs button { font-size: 13px; }
  .cta { width: 100%; }
  .actions { flex-direction: column; align-items: stretch; }
  /* Шапка темы на телефоне: название во всю ширину, статус — строкой ниже. */
  .dy-title { flex-wrap: wrap; gap: 10px; }
  .dy-title-text { flex: 1 1 60%; }
  .dy-title .badge, .dy-title .dy-now, .dy-title .dy-status { margin-left: 0; }
  .dy-status { justify-items: start; }
  .dy-theme { font-size: 17px; }
  .dy-best { max-width: none; }
  /* Первый экран на телефоне: шапка плотнее, кнопки Telegram — над QR и во всю ширину. */
  .wl-hero { padding: 24px 20px 20px; }
  .wl-hero h2 { font-size: 23px; }
  .wl-step { column-gap: 12px; }
  .wl-head h3 { font-size: 17px; }
  .wl-tg { flex-direction: column; align-items: stretch; }
  .wl-actions { order: -1; align-items: stretch; }
  .wl-qr { align-self: center; }
  /* Строка задания на телефоне — в две: иконка и название, под ними медаль и подпись. */
  .tk-row { flex-wrap: wrap; row-gap: 6px; }
  .tk-name { flex-basis: calc(100% - 52px); }
  .tk-right { flex-direction: row; gap: 8px; min-width: 0; margin-left: 52px; text-align: left; }
  .adm-grid { grid-template-columns: 1fr; }
  /* Длинное значение уходит на свою строку влево, короткое остаётся напротив подписи. */
  .row { flex-wrap: wrap; row-gap: 2px; }
  .row b { text-align: left; }
}
@media (max-width: 400px) {
  .info-grid { grid-template-columns: 1fr; }
}

/* Действия закрытой темы (088): столбик под постером лучшего примера — той же
   ширины, что кнопка отправки рекорда недели. */
.dy-actions { display: grid; gap: 10px; max-width: 320px; margin-top: 4px; }
.dy-actions .wk-more { justify-self: start; }

/* ── печать оферты (179): только документ — A4, чёрным; хром кабинета, оглавление, плитки и акцепт скрыты.
   Кто принял — в штампе под заголовком, куда ведёт — в колонтитуле: Chrome повторяет шапку таблицы на каждой
   странице, поэтому колонтитул — thead, текст — tbody таблицы .offer-frame (на экране она — обычные блоки). ── */
@page { size: A4; margin: 18mm 16mm; }
@media print {
  body { display: block; min-height: 0; background: #FFFFFF; color: #000000; }
  .wrap, .wrap.wide { display: block; max-width: none; padding: 0; }
  .top, .roles, .tabs, .foot, .offer-aside, .offer-fold, .offer-brief, .offer-status, .offer-after, .offer-history, .msg, .cta, .check, .info-grid, button { display: none !important; }
  .card, .card + .card { padding: 0; border: 0; }
  .card > *:not(:first-child) { margin-top: 0; }
  .card .offer-title { font-size: 16pt; margin: 0 0 4pt; }
  .offer-head *, .offer, .offer * { color: #000000 !important; }
  .offer-head .muted { font-size: 10pt; }
  .offer-doc { display: block; }
  .offer-main { max-width: none; }
  .offer { font-size: 11pt; line-height: 1.45; }
  .offer h2 { font-size: 13pt; margin: 14pt 0 5pt; }
  .offer h3 { font-size: 11.5pt; margin: 10pt 0 4pt; }
  .offer h2, .offer h3 { break-after: avoid; }
  .offer .clause, .offer tr, .offer blockquote { break-inside: avoid; }
  .offer h2.offer-appendix { break-before: page; }
  .offer blockquote { border-left-color: #000000; }
  .offer-table { overflow: visible; }
  .offer-table table { font-size: 10pt; }
  .offer-table th, .offer-table td { border-bottom: 0.5pt solid #000000; }
  .offer-stamp { display: block; margin: 8pt 0 12pt; padding: 5pt 8pt; border: 0.75pt solid #000000; font-size: 10pt; }
  .offer-frame { display: table; width: 100%; border-collapse: collapse; }
  .offer-frame > thead { display: table-header-group; }
  .offer-frame > tbody { display: table-row-group; }
  .offer-frame > thead > tr, .offer-frame > tbody > tr { display: table-row; }
  .offer-frame > thead > tr > td, .offer-frame > tbody > tr > td { display: table-cell; padding: 0; }
  .offer-run { margin-bottom: 10pt; padding-bottom: 2pt; border-bottom: 0.5pt solid #000000; color: #000000; font-size: 8pt; }
  a { color: #000000; text-decoration: none; }
}

/* ── Live (185): таблица детей, которые решают сейчас. Корень — .pg: плитки и строка поиска его же,
   здесь только таблица. Статус несут точки полоски и стрелка подуровня; «свернул» — серый текст,
   «не в сети» — бледность строки. Текст ряда — в две линии; на телефоне ряд перестраивается в сетку. ── */
.adm-scroll.students .lv-table td { white-space: nowrap; vertical-align: middle; font-variant-numeric: tabular-nums; }
/* Название упражнения переносится: иначе на 920 px шесть колонок не помещаются и название срезается. */
.adm-scroll.students .lv-table td.lv-c-where b { white-space: normal; }
.lv-table td.lv-c-who { min-width: 150px; }
@media (min-width: 641px) {
  .adm-scroll.students .lv-table th, .adm-scroll.students .lv-table td { padding: 10px 8px; }
  .adm-scroll.students .lv-table th:first-child, .adm-scroll.students .lv-table td:first-child { padding-left: 12px; }
  .adm-scroll.students .lv-table th:last-child, .adm-scroll.students .lv-table td:last-child { padding-right: 12px; }
}
.lv-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lv-two { display: grid; gap: 1px; min-width: 0; }
.lv-c-who .lv-two { max-width: 18ch; }
.lv-c-who b { overflow: hidden; text-overflow: ellipsis; }
.lv-sub { color: var(--s-text-3); font-size: 12px; line-height: 1.35; }
.lv-state { color: var(--s-text-2); }
.lv-ico, .lv-face { flex: none; width: 24px; height: 24px; }
.lv-ico { object-fit: contain; }
.lv-arrow { margin-left: 4px; font-weight: 700; }
.lv-arrow.up { color: var(--s-ok); }
.lv-arrow.down { color: var(--s-bad); }
.lv-checks { margin-left: 8px; letter-spacing: 0.06em; }
.lv-strip { display: inline-flex; gap: 3px; vertical-align: middle; }
.lv-strip i { width: 8px; height: 8px; border-radius: 8px; background: var(--s-border); }
.lv-strip i.ok { background: var(--s-ok); }
.lv-strip i.bad { background: var(--s-bad); }
.lv-plate { display: inline-flex; align-items: center; gap: 6px; }
.lv-plate img { width: 16px; height: 16px; }
.lv-table tr.lv-background td, .lv-table tr.lv-background td b, .lv-table tr.lv-background .lv-state { color: var(--s-text-3); }
.lv-table tr.lv-offline { opacity: 0.55; }
.adm-scroll.students .lv-table tr.lv-sep td { padding: 6px 12px; background: var(--s-surface-2); color: var(--s-text-3); font: 500 12px/1.4 var(--f-ui); }
/* «↻ обновить порядок» под заголовком: действие, поэтому акцентный цвет, а не серая пунктирная кнопка сортировки.
   Переносится и ограничена по ширине, чтобы колонка «Подход» не раздвигала таблицу. */
.adm-scroll.students .lv-table th .lv-refresh { display: block; max-width: 7.5em; margin-top: 2px; font-size: 12px; font-weight: 500; text-align: left; white-space: normal; color: var(--s-accent); text-decoration: none; }
.adm-scroll.students .lv-table th .lv-refresh:hover { text-decoration: underline; }

/* Вспышка строки (186): класс на tr, снимается по animationend. Красная — неверный пример и подуровень вниз,
   зелёная — подуровень вверх, успешный подход, медалька. Фон — смесь статусного цвета с белым: --s-bad-bg и --s-ok-bg
   на белом почти не отличить от пустой строки, а при 18 % текст ещё читается. Без анимации (prefers-reduced-motion)
   — тот же фон на 0,6 с, без затухания. */
.lv-flash-bad { animation: lv-flash-bad 1.5s ease-out; }
.lv-flash-good { animation: lv-flash-good 1.5s ease-out; }
@keyframes lv-flash-bad {
  0%, 25% { background-color: color-mix(in srgb, var(--s-bad) 18%, var(--s-bg)); }
  100% { background-color: transparent; }
}
@keyframes lv-flash-good {
  0%, 25% { background-color: color-mix(in srgb, var(--s-ok) 18%, var(--s-bg)); }
  100% { background-color: transparent; }
}
@keyframes lv-hold-bad { 0%, 100% { background-color: color-mix(in srgb, var(--s-bad) 18%, var(--s-bg)); } }
@keyframes lv-hold-good { 0%, 100% { background-color: color-mix(in srgb, var(--s-ok) 18%, var(--s-bg)); } }
@media (prefers-reduced-motion: reduce) {
  .lv-flash-bad { animation: lv-hold-bad 0.6s; }
  .lv-flash-good { animation: lv-hold-good 0.6s; }
}

/* Телефон: ряд — сетка в две линии. Первая: ник, иконка упражнения, медалька с «2 из 3»; вторая: полоска и «12 из 14».
   «Пример» и подписи «Где» скрыты, вне подхода остаётся короткая подпись состояния; шапки нет — сортировка только на широком экране. */
@media (max-width: 640px) {
  .lv-table, .lv-table tbody { display: block; }
  .lv-table thead { display: none; }
  .lv-table tr.lv-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 6px 12px; padding: 10px 12px; border-bottom: 1px solid var(--s-border); }
  .lv-table tr.lv-sep, .lv-table tr.lv-sep td { display: block; }
  .adm-scroll.students .lv-table td { padding: 0; border: 0; }
  .lv-table td:empty, .lv-c-example, .lv-c-who .lv-sub, .lv-c-where .lv-two, .lv-medal, .lv-checks, .lv-c-set .lv-sub { display: none; }
  .lv-c-who { grid-column: 1; grid-row: 1; }
  .lv-c-where { grid-column: 2; grid-row: 1; }
  .lv-c-medal { grid-column: 3; grid-row: 1; }
  .lv-c-strip { grid-column: 1; grid-row: 2; }
  .lv-c-set { grid-column: 2 / 4; grid-row: 2; justify-self: end; }
}
