/* AI-Школа — дизайн-система «школа будущего»: светлая, дружелюбная, со вкусом.
   Без фреймворков. Единый стиль для лендинга, кабинетов, класса, УРОКА, админки.
   Переменные → компоненты (кнопки, карточки, формы, таблицы, тосты) → типографика. */

/* ШРИФТ — СВОЙ ФАЙЛ, НЕ CDN (TASK-91 Ф2, требование ТЗ).
   До этой задачи сайт был набран `"Segoe UI", system-ui` — то есть Segoe на Windows,
   Roboto на Android, SF Pro на iPhone. Один сайт выглядел тремя разными, и ни одну
   вёрстку нельзя было проверить один раз: межбуквенные и высоты у этих трёх разные.
   Golos Text (SIL OFL, лицензия рядом в fonts/LICENSE-golos-text.txt) — гротеск,
   нарисованный под кириллицу; три начертания, кириллица и латиница отдельными
   файлами по unicode-range, все шесть вместе 68 КБ.
   `font-display:swap` — текст виден сразу системным шрифтом и подменяется, когда
   приедет свой: у ребёнка на мобильном интернете это разница между «страница есть»
   и «страница белая». Латиница нужна не для красоты — в школе есть английский.

   ИЗВЕСТНАЯ ГРАНИЦА: ЗНАКА РУБЛЯ ₽ (U+20BD) В ЭТИХ ФАЙЛАХ НЕТ. Google Fonts не
   включает его ни в кириллический поднабор (U+0301,U+0400-045F,U+0490-0491,
   U+04B0-04B1,U+2116), ни в латинский — проверено не чтением диапазонов, а
   попиксельным сравнением: ₽, нарисованный шрифтом Golos, совпал с ₽ из DejaVu
   байт в байт, тогда как буква «Ц» у них разная. Значит, ₽ на всех ценниках
   школы рисует системный шрифт. Ширина при этом совпадает (64 к 64 на кегле
   100), раскладка не едет, а форма у всех запасных гротесков близкая — на
   кегле 17 и 34 разницу не видно (снимок var/task91/ruble-look.png).
   Чинить это значит дорисовывать глиф в шрифт; расширять unicode-range НЕЛЬЗЯ —
   тогда браузер нарисует пустой квадрат вместо подмены, и станет хуже. */
@font-face{font-family:Golos;font-style:normal;font-weight:400;font-display:swap;
  src:url(/app/fonts/golos-cyrillic-400.woff2) format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:Golos;font-style:normal;font-weight:400;font-display:swap;
  src:url(/app/fonts/golos-latin-400.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Golos;font-style:normal;font-weight:600;font-display:swap;
  src:url(/app/fonts/golos-cyrillic-600.woff2) format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:Golos;font-style:normal;font-weight:600;font-display:swap;
  src:url(/app/fonts/golos-latin-600.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Golos;font-style:normal;font-weight:800;font-display:swap;
  src:url(/app/fonts/golos-cyrillic-800.woff2) format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:Golos;font-style:normal;font-weight:800;font-display:swap;
  src:url(/app/fonts/golos-latin-800.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

:root{
  /* поверхности */
  --bg:#eef2fc; --bg2:#e7ecfb; --card:#ffffff; --card2:#f5f7ff;
  /* текст */
  --ink:#1e2542; --ink2:#2b3357;
  /* TASK-71 Ф5: было #6f77a0 — 4.35:1 на белом, ниже нормы 4.5 для обычного
     текста (Lighthouse: «Background and foreground colors do not have a
     sufficient contrast ratio»). Этим цветом набрана половина пояснений сайта,
     включая подписи в дневнике. Один шаг темнее — 5.04:1, на глаз тот же серо-
     синий. */
  /* TASK-91 Ф3в: ещё шаг темнее, #656d94 -> #5a6184.
     Прежнее значение держало 5.04:1 НА БЕЛОМ и этого хватало, пока фон был
     только белый. В Ф2 я добавил пять пастельных подложек секций — и тот же
     серый на сиреневой дал 4.47 при норме 4.5, то есть мои собственные
     подложки вывели из нормы половину пояснений сайта. Поймал Lighthouse на
     живой главной («.lead», «.carousel-hint», «summary»), а не глаз: разница
     между 4.47 и 4.50 не видна никому.
     Новое значение: 6.04 на белом и не ниже 5.39 на любой из подложек —
     запас, которого хватит и следующей подложке. */
  --muted:#5a6184; --line:#e4e8f6;
  /* бренд и акценты */
  --brand:#5b7cfa; --brand2:#8a6cf5; --accent:#ff8a5c; --accent2:#ffd166;
  --link:#4358c4;          /* цвет ссылки в тексте: 6.1:1 на белом (TASK-71 Ф5) */
  --ok:#1fbf95; --warn:#f5a524; --bad:#f4526b;
  --grad:linear-gradient(135deg,#5b7cfa,#8a6cf5);
  --grad-warm:linear-gradient(135deg,#ff8a5c,#ffb84d);
  --radius:18px; --radius-sm:12px;
  --shadow:0 10px 30px rgba(45,55,105,.10); --shadow-sm:0 3px 10px rgba(45,55,105,.08);
  --fs:16px;

  /* ---- ДОБАВЛЕНО В TASK-91 Ф2 ---------------------------------------------
     ПОДЛОЖКИ СЕКЦИЙ. Главная до этой задачи — двенадцать секций подряд одного
     веса: заголовок по центру, подзаголовок по центру, сетка белых карточек.
     Двенадцать раз одно и то же, 33 экрана на телефоне. Ритм делается не
     новыми картинками, а чередованием фона — так у Skysmart (пять пастельных
     подложек) и у Тетрики. Цвета светлые настолько, что тёмный текст на них
     даёт тот же контраст, что на белом: проверено замером, не на глаз. */
  --tint-cool:#eef4ff;   /* холодная, под блоки про устройство учёбы */
  --tint-warm:#fff4ec;   /* тёплая, под блоки про ребёнка и заботу */
  --tint-mint:#eafaf3;   /* мятная, под «получилось / результат» */
  --tint-lilac:#f5f1ff;  /* сиреневая, под «учителя» — самая тёмная из пяти, см. --muted */
  --tint-sand:#fff8e8;   /* песочная, под честные оговорки и цены */

  /* ШКАЛА ОТСТУПОВ, кратная 4. До этого в разметке встречались 5, 6, 7, 9, 11,
     13, 14, 18, 22 px — числа из ниоткуда, и два соседних блока никогда не
     выравнивались. */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:64px;

  /* ВЫСОТА НАЖИМАЕМОГО. 44 px — не вкус, а порог Apple HIG и WCAG 2.5.8;
     держим одним числом, чтобы кнопка урока и кнопка сайта не разошлись. */
  --tap:44px;

  /* ДВИЖЕНИЕ. Один набор длительностей: иначе каждая анимация получает свою,
     и интерфейс начинает дёргаться вразнобой. Переменными — ещё и чтобы
     «уменьшить движение» выключалось в одном месте (см. ниже). */
  --t-fast:.12s; --t-base:.2s; --t-slow:.4s;

  /* Контурная рамка фокуса. Общая, чтобы клавиатурный обход не терял курсор. */
  --focus:0 0 0 3px rgba(91,124,250,.45);
}

/* «УМЕНЬШИТЬ ДВИЖЕНИЕ» (ТЗ Ф3в: «анимации аккуратные и короткие, учесть
   уменьшить движение в системе»). У ребёнка с вестибулярной чувствительностью
   или с укачиванием движущийся интерфейс вызывает дурноту; системный флаг —
   это его просьба, а не настройка оформления. Гасим здесь, у корня: иначе
   каждый новый компонент забывал бы про него. Полностью в 0.01s, а не в 0 —
   событие transitionend у некоторых обработчиков единственный способ узнать,
   что анимация кончилась, и при 0 оно не приходит вовсе. */
@media (prefers-reduced-motion: reduce){
  :root{ --t-fast:.01s; --t-base:.01s; --t-slow:.01s; }
  *,*::before,*::after{ animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important }
}
*{box-sizing:border-box}
html,body{margin:0}
body{
  font:var(--fs)/1.6 Golos,"Segoe UI",system-ui,-apple-system,Roboto,Ubuntu,sans-serif;
  color:var(--ink);
  background:
    radial-gradient(1100px 500px at 85% -10%,rgba(138,108,245,.14),transparent 60%),
    radial-gradient(900px 500px at -10% 10%,rgba(91,124,250,.14),transparent 55%),
    linear-gradient(180deg,var(--bg),var(--bg2));
  background-attachment:fixed;
  min-height:100vh;
}
/* TASK-71 Ф5. Ссылка в тексте — своим цветом, а не брендовым.
   `--brand` (#5b7cfa) создан для заливок: по нему пишут белым, и там он хорош. Как
   ЦВЕТ ТЕКСТА по белому он даёт 3.67:1 при норме 4.5 — Lighthouse ругался на ссылки
   предметов на странице класса, на ссылки классов в витрине демо и на КТП в карточке
   курса. Заливки остаются прежними, меняется только текст ссылки. */
a{color:var(--link); text-decoration:none}
a:hover{text-decoration:underline}
/* «Links rely on color to be distinguishable»: ссылка внутри абзаца или списка
   отличается от текста ТОЛЬКО цветом — человеку с нарушением цветовосприятия она не
   видна вовсе. Подчёркиваем ссылки в тексте; ссылки-кнопки, карточки и пункты меню
   узнаются по форме, их не трогаем. */
p a:not(.btn), li a:not(.btn), td a:not(.btn), .lead a{text-decoration:underline}
.wrap{max-width:1080px; margin:0 auto; padding:24px}
.narrow{max-width:560px}

/* Шапка */
header.top{display:flex; align-items:center; gap:14px; padding:14px 24px; border-bottom:1px solid var(--line);
  background:rgba(255,255,255,.72); position:sticky; top:0; z-index:20; backdrop-filter:blur(10px)}
header.top .logo{font-weight:800; letter-spacing:.2px; font-size:20px; color:var(--ink)}
header.top .logo b{background:var(--grad); -webkit-background-clip:text; background-clip:text; color:transparent}
header.top nav{margin-left:auto; display:flex; gap:18px; align-items:center; flex-wrap:wrap}
header.top nav a{color:var(--ink2); font-weight:500}

/* Типографика */
h1,h2,h3{line-height:1.2; color:var(--ink)}
h1{font-size:clamp(26px,4vw,34px); margin:.2em 0; letter-spacing:-.5px}
h2{font-size:22px} h3{font-size:18px}
.muted{color:var(--muted)}
.center{text-align:center}

/* Карточки */
.card{background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:22px; box-shadow:var(--shadow-sm)}
/* КАРТОЧКА-ССЫЛКА ЧИТАЕТСЯ ЧЁРНЫМ, А НЕ СИНИМ (TASK-71 Ф5).
   `a{color:var(--brand)}` красит ВЕСЬ текст внутри ссылки, и карточка целиком (заголовок,
   подпись, числа) уходила в брендовый #5b7cfa — это 3.67:1 на белом при норме 4.5, то
   есть Lighthouse справедливо ругался на контраст одиннадцати карточек классов. Ссылкой
   тут является вся карточка, а не слово в тексте: подчёркивать и красить её незачем. */
a.card{color:var(--ink)}
a.card:hover{text-decoration:none}
.card:hover{box-shadow:var(--shadow)}
.grid{display:grid; gap:18px}
.grid.cols2{grid-template-columns:1fr 1fr}
.grid.cols3{grid-template-columns:repeat(3,1fr)}
/* TASK-71 Ф2: cols4 — для одиннадцати карточек классов. В одну колонку на телефоне
   они превратились бы в простыню на одиннадцать экранов, поэтому здесь не `1fr`, а
   `auto-fill` от 150 px: на 360 px это два класса в ряд, на 390 — тоже два, на
   планшете три-четыре. Правило общее, чтобы следующий такой блок не изобретал своё. */
.grid.cols4{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
@media(max-width:760px){.grid.cols2,.grid.cols3{grid-template-columns:1fr}}

/* Формы */
label{display:block; font-size:13px; color:var(--muted); margin:12px 0 6px; font-weight:600}
/* TASK-70 Ф2: добавлены date, time и search. Список типов перечислением — та самая
   ловушка, из-за которой поле выбора дня на /programma осталось браузерным серым
   прямоугольником 152×34: его тип в этот список не попал, потому что в день написания
   правила страниц с датой в школе ещё не было. Новый тип поля появляется чаще, чем
   кто-нибудь вспоминает про этот список. */
input[type=text],input[type=email],input[type=password],input[type=tel],input[type=number],
input[type=date],input[type=time],input[type=search],select,textarea{
  width:100%; padding:12px 14px; background:#fff; color:var(--ink);
  border:1.5px solid var(--line); border-radius:var(--radius-sm); font-size:15px; outline:none; transition:.15s}
input:focus,select:focus,textarea:focus{border-color:var(--brand); box-shadow:0 0 0 3px rgba(91,124,250,.15)}
textarea{min-height:90px; resize:vertical}

/* Кнопки */
.btn{display:inline-flex; align-items:center; gap:8px; justify-content:center; cursor:pointer;
  padding:12px 20px; border-radius:12px; border:1.5px solid transparent; font-weight:700; font-size:15px;
  background:var(--grad); color:#fff; box-shadow:0 6px 16px rgba(91,124,250,.28); transition:.15s}
.btn:hover{filter:brightness(1.05); transform:translateY(-1px); text-decoration:none}
.btn:active{transform:translateY(0)}
.btn.ghost{background:#fff; border-color:var(--line); color:var(--ink); box-shadow:var(--shadow-sm)}
.btn.ghost:hover{border-color:var(--brand); color:var(--brand)}
.btn.warm{background:var(--grad-warm); box-shadow:0 6px 16px rgba(255,138,92,.30)}
.btn.sm{padding:8px 13px; font-size:13px; border-radius:10px}
.btn.bad{background:linear-gradient(135deg,#ff7a8f,#f4526b); box-shadow:0 6px 16px rgba(244,82,107,.28)}
.btn:disabled{opacity:.5; cursor:not-allowed; transform:none; box-shadow:none}

.row{display:flex; gap:12px; align-items:center; flex-wrap:wrap}
.right{margin-left:auto; display:flex; flex-wrap:wrap; gap:0 4px}
/* На узком экране блок ссылок в подвале не помещался в строку и вылезал за экран —
   замер в браузере на 390px показал горизонтальный перелив 221px по всему лендингу.
   `margin-left:auto` без переноса удерживал ссылки в одну строку любой длины. */
@media(max-width:760px){ .right{margin-left:0; width:100%} }

/* Пилюли/бейджи */
.pill{display:inline-block; padding:4px 11px; border-radius:999px; background:var(--card2); border:1px solid var(--line); font-size:12px; color:var(--muted); font-weight:600}
/* TASK-71 Ф5: цвет пилюли по её же бледной подложке давал 2.18:1 («сдано»,
   «на проверке», «включается автоматически» — те самые подписи, которые родитель
   ищет глазами). Оттенок тот же, светлота ниже: 5.3–6.7:1. */
.pill.ok{color:#0a7458; background:rgba(31,191,149,.10); border-color:rgba(31,191,149,.30)}
.pill.warn{color:#8a5a00; background:rgba(245,165,36,.12); border-color:rgba(245,165,36,.30)}
.pill.bad{color:#b02138; background:rgba(244,82,107,.10); border-color:rgba(244,82,107,.30)}

/* Слайдеры (фабрика учителей) */
.sliderrow{display:grid; grid-template-columns:130px 1fr 40px; align-items:center; gap:10px; margin:8px 0}
input[type=range]{width:100%; accent-color:var(--brand)}

/* Галерея аватаров */
.gallery{display:flex; gap:12px; flex-wrap:wrap}
.ava{border:2px solid var(--line); border-radius:14px; padding:10px; cursor:pointer; width:140px; text-align:center; font-size:12px; color:var(--muted); background:var(--card2); transition:.15s}
.ava.sel{border-color:var(--brand); color:var(--ink)}
.ava .dot{width:100%; height:64px; border-radius:10px; background:var(--grad); margin-bottom:6px; display:flex; align-items:center; justify-content:center; font-size:28px}

pre.prompt{white-space:pre-wrap; background:var(--card2); border:1px solid var(--line); border-radius:12px; padding:14px; font-size:13px; color:var(--ink2); max-height:340px; overflow:auto}

/* Тосты */
.toast{position:fixed; right:18px; bottom:18px; background:#fff; border:1px solid var(--line); padding:13px 18px; border-radius:12px; box-shadow:var(--shadow); opacity:0; transform:translateY(10px); transition:.25s; z-index:50; color:var(--ink)}
.toast.show{opacity:1; transform:none}
.toast.ok{border-color:rgba(31,191,149,.5)}
.toast.bad{border-color:rgba(244,82,107,.5)}

.tcard{display:flex; gap:14px; align-items:center}
.tcard .ava{cursor:default}

/* Таблицы */
table{width:100%; border-collapse:collapse}
th,td{text-align:left; padding:11px 9px; border-bottom:1px solid var(--line); font-size:14px}
th{color:var(--muted); font-weight:700; font-size:13px}
tr:hover td{background:var(--card2)}

.hidden{display:none !important}
.err{color:var(--bad); font-size:13px; margin-top:6px}

/* Прогресс-бар */
.progressbar{height:12px; background:var(--card2); border:1px solid var(--line); border-radius:999px; overflow:hidden}
.progressbar > i{display:block; height:100%; background:var(--grad); transition:width .4s}

/* Баннеры (расписание/дневник) */
.banner{padding:11px 15px; border-radius:12px; border:1px solid var(--line); margin:5px 0; font-size:14px; background:var(--card2)}
.banner.warn{border-color:rgba(245,165,36,.5); background:rgba(245,165,36,.10)}
.banner.bad{border-color:rgba(244,82,107,.45); background:rgba(244,82,107,.08)}
.banner.ok{border-color:rgba(31,191,149,.5); background:rgba(31,191,149,.09)}

/* Модалки поверх затемнения */
#backdrop{background:rgba(30,37,66,.45) !important; backdrop-filter:blur(2px)}

/* --- Мобильная адаптация (Фаза 7): лендинг и кабинеты от 360px --- */
@media(max-width:640px){
  .wrap{padding:16px}
  /* ШАПКА НА ТЕЛЕФОНЕ ПЕРЕНОСИТСЯ, А НЕ НАЕЗЖАЕТ НА ЛОГОТИП (TASK-89 Ф4).
     Снимок главной на 390 px: меню из девяти ссылок переносилось ВНУТРИ nav на три
     строки, а сама шапка переноса не допускала — и второй ряд меню ложился поверх
     слова «AIШкола». Горизонтальной прокрутки при этом не было, поэтому обход сайта
     (он мерит именно прокрутку) этого не видел ни в одной прошлой задаче.
     `flex-wrap:wrap` ничего не меняет там, где меню и так помещается в строку:
     переносится только то, что иначе наехало бы. */
  /* …И НЕ ЛИПНЕТ К ВЕРХУ, РАЗ УЖ ПЕРЕНОСИТСЯ. Перенос чинит наезд, но меню из девяти
     ссылок на 360 px занимает три строки — то есть почти треть экрана. Липкая шапка
     такой высоты закрывала бы содержимое всю дорогу вниз, и лечение вышло бы хуже
     болезни. На телефоне шапка уезжает вверх как обычный блок; на компьютере, где она
     в одну строку и низкая, липкость остаётся. Страницы урока это не касается:
     web/lesson.html этот файл стилей не подключает. */
  header.top{padding:11px 15px; gap:10px 12px; flex-wrap:wrap; position:static}
  header.top .logo{font-size:18px}
  header.top nav{gap:12px; font-size:14px; row-gap:8px}
  h1{font-size:25px} h2{font-size:19px}
  .card{padding:16px; border-radius:15px}
  .grid{gap:14px}
  .btn{padding:11px 16px}
  .sliderrow{grid-template-columns:96px 1fr 32px}
  /* широкие таблицы (дневник/эксперимент) — горизонтальный скролл внутри карточки */
  .card{overflow-x:auto}
  table{font-size:13px} th,td{padding:9px 7px}
  /* модалки почти во весь экран */
  .card[style*="position:fixed"]{inset:3% 50% auto 50% !important; width:94% !important; max-height:92vh !important}
}
@media(max-width:400px){
  header.top nav{gap:9px; font-size:13px}
  .btn.sm{padding:7px 10px}
}
/* …но не мельче 14 px, если тычут пальцем: на 360–393 px правило выше давало
   13 px ссылкам шапки во всех детских кабинетах (замер /kid, /diary, /homework). */
@media(max-width:400px) and (pointer:coarse){ header.top nav{font-size:14px} }

/* --- ПАЛЕЦ ВМЕСТО МЫШИ (TASK-44 Ф1) ---------------------------------------
   Замер в браузере на шести устройствах (var/task44/mobile.json) показал, что
   почти всё, во что ребёнок и родитель тычут пальцем, ниже 44 px: ссылки шапки
   21 px, «Читать биографию» на /teachers — 16 px, «Весь план» и «Открыть
   дневник» в классе — 37 px, ссылки «← На главную» в оферте — 19 px. 44×44 —
   это не вкусовщина, а совпавшая рекомендация Apple и Google: меньше — палец
   промахивается, и ребёнок нажимает соседнее.
   Условие — НЕ ширина окна, а вид указателя: у планшета в альбоме экран шире
   иного ноутбука, но тычут в него всё равно пальцем. */
@media(pointer:coarse){
  /* TASK-73 Ф1. ВЫСОТУ ПОДНЯЛИ В TASK-44, А ШИРИНУ ЗАБЫЛИ — и на этом попалась
     самая короткая ссылка школы. Замер телефона: на /oge ссылка «ЕГЭ» приходит
     27×44 на Android 360, 29×44 на iPhone SE, 31×44 на iPad. Высота честные 44,
     ширина — вдвое меньше нужного, а соседи справа («Кабинет», «Справка») — тоже
     ссылки: промах пальцем уводит не туда, куда ребёнок тянулся.
     min-width, а НЕ padding: padding расширил бы и длинные ссылки тоже, а на экране
     360 px шапка и так на грани — лишние 16 px с каждой из трёх дали бы
     горизонтальную прокрутку, то есть мы бы починили одно и сломали худшее.
     min-width трогает только те ссылки, что УЖЕ уже сорока четырёх. */
  header.top nav a,
  header.top nav > a,
  header.top .logo{min-height:44px; min-width:44px; display:inline-flex; align-items:center; justify-content:center}
  /* TASK-71 Ф5. Lighthouse на мобильной главной: «82% appropriately sized tap
     targets» — не хватало ПОДВАЛА. Ссылки подвала («Блог», «Вопросы», «Оферта»…)
     приходили 25 px высотой и вплотную друг к другу: попасть пальцем в «Оферту», не
     задев «Конфиденциальность», нельзя. Шапку подняли ещё в TASK-44, а подвал тогда
     никто не мерил — он же «неважный». Он важный: там юридические страницы, которые
     родитель ищет именно с телефона. */
  footer.foot a{min-height:44px; display:inline-flex; align-items:center; padding:0 4px}
  .btn, .btn.sm, button, input[type=submit], input[type=button]{min-height:44px}
  /* TASK-70 Ф2. ПЕРЕЧИСЛЕНИЕ ЗАМЕНЕНО НА ИСКЛЮЧЕНИЕ, И ЭТО ГЛАВНАЯ ПРАВКА ФАЗЫ.
     Здесь стоял список типов полей, и он честно работал — до первого нового типа.
     Поле выбора дня на /programma (`input type=date`) в список не попало и осталось
     152×34: палец в него попадает через раз, а страницу эту родитель открывает
     каждое утро. Такая правка чинит один случай и оставляет ловушку на месте.
     Теперь наоборот: под палец растут ВСЕ поля, кроме тех, которым 44 px не нужны
     или вредны, — флажок и радиокнопка растут не сами, а вместе со своей меткой
     (правило ниже), ползунок задан отдельно, у скрытого поля размера нет вовсе,
     а выбор файла рисует браузер своей кнопкой. */
  select,
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=hidden]):not([type=file]){
    min-height:44px;
  }
  /* Кегль системного шрифта у голой кнопки и голого поля — 13.3 px (браузерное
     умолчание). Наш .btn задаёт свой, но не всякая кнопка в школе носит класс: на
     /programma «Показать день» — просто <button>, и замер нашёл 13.3 px. Поднимаем
     низ у самих элементов формы: это ровно те места, куда смотрят перед нажатием. */
  button, select, input, textarea{font-size:14px}
  details summary{min-height:44px; display:flex; align-items:center}
  /* Одиночные ссылки-действия («← На главную», «учебники класса →») — тоже цель
     для пальца, но подчёркивать их рамкой некуда: даём высоту отступами. */
  .backlink, a.btn{min-height:44px; display:inline-flex; align-items:center}
  /* Шрифт мельче 14 px с планшета в руках не читается, а в классе ребёнка (/kid)
     им набрано всё, что он смотрит каждый день: «🔥 Серия: 0 дн.», «Баланс: 0 XP»,
     «До уровня 2: ещё 100 XP» — 12 px, «Весь план», «Открыть задания» — 13 px.
     Замер: /kid, phone-se, 9 мест ниже порога. 14 px — нижняя граница для
     третьеклассника, дальше он начинает подносить планшет к лицу. */
  .pill{font-size:14px}
  .btn.sm{font-size:14px}
  th{font-size:14px}
  label{font-size:14px}
  .err{font-size:14px}
  /* Ссылки-стрелки («← На главную» в оферте, «учебники класса →» в кабинете) —
     это отдельные действия, а не ссылки внутри фразы: по ним тоже тычут пальцем,
     и 14–19 px высоты им мало. Помечены классом .taplink там, где это действие. */
  a.taplink{min-height:44px; display:inline-flex; align-items:center}
  /* TASK-67 Ф6. Замер восьми размеров × трёх браузеров (var/task67/f6f7.json)
     поймал ещё три места ниже порога — все на страницах, куда ребёнок и родитель
     заходят с телефона каждый день. */
  /* .muted — это не «неважное»: им набраны подписи в дневнике («сдано», «на
     проверке»), пояснения в кабинете родителя и подсказки на входе по картинке.
     13 px третьеклассник читает, поднося телефон к лицу. */
  /* !important здесь ВЫНУЖДЕННОЕ, и это важно объяснить, а не прятать.
     Кегль 13 px на этих страницах задан не таблицей стилей, а ПРЯМО В РАЗМЕТКЕ —
     style="font-size:13px" внутри шаблонов, которыми дневник и кабинет рисуют
     карточки (diary.html:101, 103, 116, 148…). Inline-стиль сильнее любого правила
     из файла, поэтому обычное .muted{font-size:14px} не делало ровно ничего:
     замер после него показал те же 13 px. Переписывать десятки шаблонов ради
     одного пикселя рискованнее, чем одно правило, действующее только на
     устройствах с пальцем вместо мыши. */
  .muted{font-size:14px !important}
  /* Моноширинный текст кода входа на /kid-login — то самое, что ребёнок
     переписывает или диктует родителю. */
  pre{font-size:14px !important}
  /* Плитки выбора картинки при входе ребёнка (и подписи под ними) — 12 px. */
  .ava{font-size:14px}
  /* Флажки в кабинете родителя (отметки «сделано» напротив ребёнка) приходили
     13×13 px — в такой квадрат не попадает даже взрослый палец. Растим сам
     флажок: оборачивать каждый в подложку с отступами пришлось бы во всех
     карточках сразу, а это правка всех страниц ради одного правила. */
  /* `flex:0 0 auto` ОБЯЗАТЕЛЕН, И ВОТ ПОЧЕМУ (TASK-79 Ф5). Правило ниже делает
     метку с флажком flex-контейнером (`display:flex !important`), а во flex-строке
     у элемента по умолчанию `flex-shrink:1` — то есть `width:24px` для него не
     обязательство, а пожелание. Длинный текст метки («ставить отметку, когда
     ребёнок пришёл к репетитору со своим заданием») сжимал флажок обратно: замер
     из браузера на 390 px показал 13×24 и 15×24 вместо задуманных 24×24. То есть
     правка TASK-67, растившая флажок, на самых длинных метках не работала вовсе —
     и именно там, где текста больше всего, то есть на телефоне. */
  input[type=checkbox], input[type=radio]{width:24px; height:24px; flex:0 0 auto}
  /* TASK-68 Ф4. 24×24 — всё ещё не 44×44, и владелец прав: палец мимо. Но растить
     САМ флажок до 44 px нельзя — квадрат размером с кнопку рядом с одной строкой
     текста выглядит поломкой, а не заботой. Поэтому целью пальца становится не
     квадрат, а ВСЯ СТРОКА: флажки в кабинете родителя все до одного лежат внутри
     своего <label>, а нажатие на label переключает флажок — это поведение самого
     HTML, не наша выдумка. Даём строке высоту 44 px, и зона нажатия выходит
     44 px в высоту и во всю ширину карточки, а квадратик остаётся 24×24.
     ПОЧЕМУ display СО ЗВЁЗДОЧКОЙ, А ВСЁ ОСТАЛЬНОЕ БЕЗ. Три метки в кабинете несут
     `display:block` прямо в разметке (cabinet.html:600, 601, 608), и без !important
     min-height честно применится к блоку, но флажок и текст останутся на базовой
     линии — строка станет выше, а палец будет по-прежнему целиться в квадрат.
     А вот align-items и gap важными делать НЕЛЬЗЯ: метка согласия на отзыв
     (cabinet.html:62) — абзац в три строки, и она нарочно просит flex-start,
     чтобы флажок стоял у первой строки, а не посреди абзаца.

     TASK-70 Ф2. К `:has()` добавлен КЛАСС, и вот зачем. `:has()` появился в Safari
     только с 15.4, и в ОТЧЁТ-68 п.7 это честно записано как недоделка: на iPhone,
     который обновляют последним, строка остаётся 24 px — то есть правка не работает
     ровно у того, кому она нужнее всех. Селектор по классу понимает любой браузер, и
     `class="tap"` проставлен всем тринадцати меткам с флажком и радиокнопкой в школе
     (cabinet, alerts, anketa, bio, admin-content). Двум меткам он НЕ проставлен
     нарочно — тем самым абзацам в три строки с `align-items:flex-start`.
     `:has()` оставлен рядом: он подхватит метку, которую забудут пометить классом. */
  label:has(> input[type=checkbox]), label:has(> input[type=radio]), label.tap{
    min-height:44px; display:flex !important; align-items:center; gap:10px;
  }
  /* Кегль меток — 14 px даже там, где он задан прямо в разметке. Правило `label`
     выше (14 px, без !important) молча проигрывало inline-стилю `font-size:13px`
     в карточках кабинета родителя: замер TASK-67 нашёл там 13 px и после правки,
     и это попало в «чего не сделано». */
  label{font-size:14px !important}
}

/* Длинная почта родителя в шапке (#who) — единственный неразрывный кусок текста
   на странице. На /tariffs при экране 375 px она растягивала документ до 395 px
   и давала горизонтальную прокрутку по всей странице: замер tariffs/phone-se,
   виновник span#who. Разрешаем перенос, а на телефоне убираем совсем — почта
   родителя в шапке платёжной страницы не нужна никому. */
header.top nav #who{overflow-wrap:anywhere; min-width:0; max-width:100%}
@media(max-width:640px){ header.top nav #who{display:none} }

/* Крупный режим для 1–4 классов (body.kid-large) */
body.kid-large{--fs:19px}
body.kid-large .btn{padding:14px 24px; font-size:17px; border-radius:14px}
body.kid-large h1{font-size:clamp(30px,5vw,40px)}
body.kid-large .card{border-radius:22px}

/* Бейдж мозга учителя (TASK-22 Ф4): родитель видит модель прямо в карточке выбора. */
.brainbadge { display:inline-block; font-size:11px; font-weight:700; color:#fff;
  padding:2px 8px; border-radius:999px; background:#8a90a8; margin:2px 0; cursor:help; }
.brainbadge.deepseek { background:#2f6df6; }
.brainbadge.gigachat { background:#12b26a; }
.brainbadge.anthropic { background:#a05c2c; }
.brainbadge.mock { background:#8a90a8; }

/* Общие элементы контентных страниц (TASK-28 Ф5). Раньше .lead и раскрывающиеся
   вопросы жили только во внутреннем <style> лендинга, поэтому любая новая страница
   получала их «на глаз» и расходилась с ним по виду. Теперь это часть дизайн-системы. */
.lead{color:var(--muted); max-width:680px; font-size:17px; line-height:1.6}
section .lead{text-align:center; margin:0 auto 26px}
details{border:1px solid var(--line); border-radius:12px; padding:12px 16px; margin-bottom:10px; background:var(--card)}
details summary{cursor:pointer; font-weight:600; color:var(--ink)}
details[open] summary{margin-bottom:8px}
details p{margin:0; color:var(--ink2)}

/* ===========================================================================
   TASK-91 Ф2. КОМПОНЕНТЫ ДИЗАЙН-СИСТЕМЫ.
   Всё ниже писалось от 390 px вверх, а не от десктопа вниз: media-запросы здесь
   только `min-width`. Это не стиль оформления кода — это проверка. Правило,
   написанное для широкого экрана и «поджатое» запросом под телефон, на телефоне
   проверяется последним и ломается первым.
   =========================================================================== */

/* --- ФОКУС КЛАВИАТУРОЙ -----------------------------------------------------
   Браузерный контур фокуса у части элементов был снят (`outline:none` в полях
   ввода), а взамен ничего не дано, кроме цвета рамки. Для того, кто ходит по
   сайту клавишей Tab, это значит «курсор потерян». :focus-visible, а не :focus —
   чтобы рамка не вспыхивала от мышиного клика по кнопке. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--brand); outline-offset:2px; border-radius:6px}

/* --- РИТМ СЕКЦИЙ -----------------------------------------------------------
   `.sec` — полоса во всю ширину со своим фоном; содержимое внутри держит
   `.wrap`. Подложка идёт ДО КРАЁВ ЭКРАНА, иначе чередование читается как
   «карточки разного цвета», а не как смена главы. */
.sec{padding:var(--s7) 0}
.sec > .wrap{padding-top:0; padding-bottom:0}
.sec.tint-cool{background:var(--tint-cool)}
.sec.tint-warm{background:var(--tint-warm)}
.sec.tint-mint{background:var(--tint-mint)}
.sec.tint-lilac{background:var(--tint-lilac)}
.sec.tint-sand{background:var(--tint-sand)}
.sec.plain{background:#fff}
/* Заголовок секции: надзаголовок-метка, заголовок, пояснение. Надзаголовок —
   дешёвый способ дать странице ориентир «где я», не удлиняя её. */
.sec-head{text-align:center; margin-bottom:var(--s6)}
/* ЦВЕТ ТУТ `--link`, А НЕ `--brand`, И ЭТО НЕ ВКУС.
   Я покрасил надзаголовок секции брендовым синим — тем самым, про который
   в этом же файле двадцатью строками выше написано: как ЦВЕТ ТЕКСТА он даёт
   3.68:1 при норме 4.5. Lighthouse поймал это на живой главной сразу после
   правки («Background and foreground colors do not have a sufficient contrast
   ratio» → три `.sec-kicker`). Правило существовало, было записано словами
   рядом — и всё равно нарушено в первом же новом компоненте. `--link`
   (#4358c4) даёт 6.12 на белом и 5.54 на самой тёмной из наших подложек. */
.sec-kicker{display:inline-block; font-size:13px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--link); margin-bottom:var(--s2)}
.sec-head h2{font-size:clamp(22px,3.4vw,30px); margin:0 0 var(--s3)}
.sec-head .lead{margin:0 auto}

/* --- ПЕРВЫЙ ЭКРАН ----------------------------------------------------------
   Одна колонка на телефоне, две от 880 px. Текст слева, показ урока справа —
   и именно показ урока, а не картинка: ни один из пяти разобранных сайтов не
   показывает на первом экране свой продукт в работе, а у нас он показуем. */
.hero2{display:grid; gap:var(--s6); align-items:center; padding:var(--s6) 0 var(--s7)}
@media(min-width:880px){ .hero2{grid-template-columns:1.05fr .95fr; gap:var(--s7); padding:var(--s7) 0} }
.hero2 h1{font-size:clamp(28px,5.2vw,44px); line-height:1.1; margin:0 0 var(--s4); letter-spacing:-.6px}
/* Подзаголовок — ОДНО предложение. До этой задачи их было четыре, и в них было
   три разных жирных куска: жирность перестаёт выделять, когда ею набрана
   половина абзаца. Остальное переехало в строку фактов под кнопками. */
.hero2 .sub{font-size:clamp(16px,2.2vw,19px); color:var(--ink2); margin:0 0 var(--s5); max-width:34em}
.hero2 .cta{display:flex; flex-wrap:wrap; gap:var(--s3); align-items:center}
.hero2 .cta .btn{min-height:52px; font-size:16px}
.hero2 .note{color:var(--muted); font-size:14px; margin-top:var(--s3)}
/* Строка фактов под кнопками: то, что раньше было вторым и третьим
   предложением подзаголовка. Разделена точками, а не запятыми: читается
   как перечень, а не как речь. */
.hero2 .facts{display:flex; flex-wrap:wrap; gap:var(--s2) var(--s4); margin-top:var(--s4);
  font-size:14px; color:var(--ink2); font-weight:600}
.hero2 .facts span{display:inline-flex; align-items:center; gap:6px}

/* --- ПОЛОСА ЧИСЕЛ ----------------------------------------------------------
   Числа из базы. Были мелкими белыми карточками в ряд и читались как служебные;
   стали одной полосой с крупной цифрой — это главное, чем мы доказываем, что
   школа не макет. На телефоне два в ряд, а не один: пять штук в столбик — это
   пять экранов прокрутки ради пяти чисел. */
.numbers{display:grid; grid-template-columns:repeat(2,1fr); gap:var(--s3)}
@media(min-width:720px){ .numbers{grid-template-columns:repeat(5,1fr); gap:var(--s4)} }
.numbers .n{background:#fff; border:1px solid var(--line); border-radius:var(--radius-sm);
  padding:var(--s4) var(--s3); text-align:center}
.numbers .n b{display:block; font-size:clamp(22px,4vw,30px); font-weight:800; color:var(--brand); line-height:1.1}
.numbers .n span{display:block; font-size:13px; color:var(--muted); margin-top:var(--s1); line-height:1.35}

/* --- ЛИПКАЯ КНОПКА НА ТЕЛЕФОНЕ --------------------------------------------
   ТЗ: «липкая кнопка „Бесплатный урок“ на телефоне». Только на телефоне и
   только на продающих страницах (класс .has-stickycta на body): в кабинете и
   на уроке она была бы помехой.
   `env(safe-area-inset-bottom)` — не украшение: на iPhone без него кнопка
   уезжает под полосу-индикатор жеста «домой» и нажимается мимо. */
.stickycta{position:fixed; left:0; right:0; bottom:0; z-index:40; display:none;
  padding:var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom,0px));
  background:rgba(255,255,255,.94); backdrop-filter:blur(10px); border-top:1px solid var(--line)}
.stickycta .btn{width:100%; min-height:var(--tap)}
.stickycta .sub{display:block; text-align:center; font-size:12px; color:var(--muted); margin-top:4px}
@media(max-width:879px){
  body.has-stickycta .stickycta{display:block}
  /* Место под неё — иначе она закрывает подвал и последнюю кнопку страницы. */
  body.has-stickycta{padding-bottom:84px}
}

/* ===========================================================================
   СОСТОЯНИЯ ОЖИДАНИЯ, ПУСТОТЫ И ОШИБКИ (TASK-91 Ф3в).
   Отдельный раздел, потому что до этой задачи их не было как класса вещей:
   каждая страница придумывала своё «Загрузка…» или не придумывала ничего.
   =========================================================================== */

/* --- КРУТИЛКА --------------------------------------------------------------
   Правило системы: КРУТИЛКА НИКОГДА НЕ ХОДИТ ОДНА. Рядом с ней всегда строка
   «что происходит» человеческим языком. Крутилка без подписи отвечает на
   вопрос «работает ли», но не на вопрос «чего я жду», а ждут люди именно
   второе. Для «уменьшить движение» вращение гасится глобальным правилом
   выше — остаётся статичное кольцо, и это честнее, чем ничего. */
.spin{display:inline-block; width:20px; height:20px; border-radius:50%;
  border:2.5px solid rgba(91,124,250,.25); border-top-color:var(--brand);
  animation:spin .8s linear infinite; vertical-align:-4px; flex:none}
.spin.lg{width:36px; height:36px; border-width:3.5px}
@keyframes spin{to{transform:rotate(360deg)}}
/* Блок ожидания целиком: кольцо + что происходит + (через время) что делать. */
.waiting{display:flex; flex-direction:column; align-items:center; gap:var(--s3);
  padding:var(--s6) var(--s4); text-align:center; color:var(--ink2)}
.waiting .what{font-weight:600}
.waiting .why{font-size:14px; color:var(--muted); max-width:30em}
/* Подсказка «долго» и кнопка «повторить» появляются не сразу, их показывает
   util.js по таймеру. В разметке они есть всегда — чтобы не прыгала высота. */
.waiting .slow,.waiting .stuck{display:none}
.waiting.is-slow .slow{display:block}
.waiting.is-stuck .stuck{display:flex; gap:var(--s2); flex-wrap:wrap; justify-content:center}

/* --- СКЕЛЕТОН --------------------------------------------------------------
   Для списков и карточек, где заранее известна форма содержимого: он не
   врёт про прогресс и не прыгает, когда данные приедут. */
.skel{background:linear-gradient(90deg,#eef1fa 25%,#f7f9ff 37%,#eef1fa 63%);
  background-size:400% 100%; animation:skel 1.4s ease infinite; border-radius:8px; color:transparent}
.skel.line{height:14px; margin:8px 0}
.skel.line.w60{width:60%} .skel.line.w40{width:40%} .skel.line.w80{width:80%}
.skel.block{height:120px}
@keyframes skel{0%{background-position:100% 50%}100%{background-position:0 50%}}

/* --- ПУСТОЕ СОСТОЯНИЕ ------------------------------------------------------
   ТЗ: «пустые состояния — с объяснением и следующим шагом». Пустой список без
   объяснения неотличим от сломанного списка, и родитель читает его как поломку.
   Поэтому в разметке .empty кнопка обязательна. */
.empty{text-align:center; padding:var(--s7) var(--s4); color:var(--ink2)}
.empty .ico{width:56px; height:56px; margin:0 auto var(--s3); color:var(--brand); opacity:.55}
.empty h3{margin:0 0 var(--s2); font-size:18px}
.empty p{margin:0 auto var(--s4); color:var(--muted); max-width:34em}

/* --- ОШИБКА ----------------------------------------------------------------
   ТЗ: «человеческим языком, без кодов, с кнопкой действия». Код ошибки не
   исчезает совсем — он уезжает в <details> «подробности»: родителю он не нужен,
   а тому, кто будет чинить, нужен обязательно. */
.errbox{border:1px solid #f3c6ce; background:#fff5f6; border-radius:var(--radius-sm);
  padding:var(--s4); color:#7a2230}
.errbox h3{margin:0 0 var(--s2); font-size:17px; color:#8c1f31}
.errbox p{margin:0 0 var(--s3)}
.errbox details{background:transparent; border:0; padding:0; margin-top:var(--s3)}
.errbox details summary{font-size:13px; color:#8a5560; font-weight:600}
.errbox code{font-size:12px; color:#6a3540; word-break:break-all}

/* --- ПЛОХАЯ СЕТЬ -----------------------------------------------------------
   Полоса сверху, а не тост: тост уезжает, а «связь пропала» должно висеть,
   пока оно правда. */
.netbar{position:fixed; left:0; right:0; top:0; z-index:60; display:none;
  padding:9px var(--s4); text-align:center; font-size:14px; font-weight:600;
  background:#fff1cf; color:#6b4a06; border-bottom:1px solid #f0d79a}
body.is-offline .netbar{display:block}

/* --- КНОПКА В РАБОТЕ -------------------------------------------------------
   Нажатая кнопка, которая выглядит как ненажатая, — причина двойных заявок и
   двойных оплат. `aria-busy` вместо класса: о состоянии узнаёт и экранный
   диктор, а не только глаз. */
.btn[aria-busy="true"]{pointer-events:none; opacity:.75; position:relative}
.btn[aria-busy="true"]::before{content:""; width:16px; height:16px; border-radius:50%;
  border:2px solid rgba(255,255,255,.4); border-top-color:#fff; animation:spin .8s linear infinite}
.btn.ghost[aria-busy="true"]::before{border-color:rgba(91,124,250,.3); border-top-color:var(--brand)}

/* --- ТОСТ «СОХРАНЕНО» ------------------------------------------------------
   Тост уже был (.toast), но только как «что-то произошло». Нужны виды:
   получилось / не получилось. Без этого «сохранено» и «не сохранилось»
   выглядели одинаково — худший вид молчания. */
.toast.ok{border-left:4px solid var(--ok)}
.toast.bad{border-left:4px solid var(--bad)}
.toast .ti{margin-right:8px; font-weight:800}
.toast.ok .ti{color:var(--ok)} .toast.bad .ti{color:var(--bad)}
/* На телефоне тост во всю ширину снизу: 18 px справа — это десктопная привычка,
   на 390 px такой тост обрезается. */
@media(max-width:620px){ .toast{right:12px; left:12px; bottom:12px} }

/* --- ИКОНКИ ----------------------------------------------------------------
   Свои SVG вместо эмодзи. Эмодзи рисует система: один и тот же значок выглядит
   по-разному в iOS, Android и Windows, в старом Android его может не быть
   вовсе, а экранный диктор читает его вслух («женщина-учитель»). Управляемым
   дизайном это не назовёшь. `currentColor` — чтобы иконка всегда была цвета
   текста рядом и не требовала отдельной правки на каждый фон. */
.i{width:1.25em; height:1.25em; flex:none; vertical-align:-.22em; fill:none;
  stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round}
.i.lg{width:28px; height:28px} .i.xl{width:40px; height:40px; stroke-width:1.5}

/* --- МИКРОВЗАИМОДЕЙСТВИЯ ---------------------------------------------------
   Нажатие должно быть видно пальцем, а не только мышью: на телефоне нет
   :hover, и без :active кнопка не отвечает вовсе. */
.btn:active{transform:scale(.985)}
.card.clickable{cursor:pointer; transition:transform var(--t-fast), box-shadow var(--t-base)}
.card.clickable:active{transform:scale(.995)}

/* --- ТАРИФЫ ----------------------------------------------------------------
   Выделенный тариф. Было пять карточек в раскладке 3+2 без единого акцента —
   родителю не на что опереться, и он не выбирает вовсе. */
.plan{position:relative; display:flex; flex-direction:column}
.plan .price{font-size:clamp(24px,4vw,32px); font-weight:800; color:var(--ink); line-height:1.1}
.plan .price small{font-size:14px; font-weight:600; color:var(--muted)}
.plan ul{margin:var(--s3) 0 var(--s4); padding-left:0; list-style:none}
.plan li{position:relative; padding-left:26px; margin:var(--s2) 0; font-size:15px; color:var(--ink2)}
.plan li::before{content:""; position:absolute; left:4px; top:.55em; width:11px; height:6px;
  border-left:2px solid var(--ok); border-bottom:2px solid var(--ok); transform:rotate(-45deg)}
.plan .btn{margin-top:auto}
.plan.best{border-color:var(--brand); box-shadow:0 12px 34px rgba(91,124,250,.22)}
/* ПЛАШКА НЕ ВЫСТУПАЕТ ЗА КАРТОЧКУ. Первая версия висела на `top:-12px`, то
   есть торчала над карточкой, — и в сетке с зазором 18 px её верх срезался
   нижним краем карточки, стоящей выше (замер: плашка на y=14651 при карточке
   на y=14662). Выступающий элемент в сетке всегда чем-нибудь обрежется;
   плашка переехала внутрь карточки, а место под неё даёт отступ сверху. */
.plan.best{padding-top:34px}
.plan.best .tag{position:absolute; top:12px; left:50%; transform:translateX(-50%);
  background:var(--grad); color:#fff; font-size:12px; font-weight:800; padding:4px 14px;
  border-radius:999px; white-space:nowrap}

/* --- ШАПКА САЙТА НА ТЕЛЕФОНЕ (TASK-91 Ф3) --------------------------------
   Замер «до»: шапка занимала 230 px из 844 на экране 390 — 27 % первого
   экрана, девять ссылок в две строки плюс кнопка. Ссылки не удалены, они
   уехали в раскрывающееся меню; в полосе остаются логотип, «Вход» и кнопка
   урока. Меню на <details>, а не на скрипте: навигация обязана работать,
   даже если JS не приехал. */
header.top.topnav{gap:var(--s2); padding:var(--s2) var(--s3); flex-wrap:nowrap}
header.top.topnav .logo{font-size:18px; margin-right:auto}
header.top .burger{border:0; background:transparent; padding:0; margin:0; position:relative}
header.top .burger > summary{display:inline-flex; align-items:center; gap:6px; list-style:none;
  min-height:var(--tap); padding:0 var(--s3); border-radius:10px; border:1px solid var(--line);
  background:#fff; font-size:14px; font-weight:600; color:var(--ink2); cursor:pointer}
header.top .burger > summary::-webkit-details-marker{display:none}
header.top .burger[open] > summary{border-color:var(--brand); color:var(--brand)}
.burger-menu{position:absolute; right:0; top:calc(100% + 8px); z-index:30; display:flex;
  flex-direction:column; min-width:200px; padding:var(--s2); border-radius:14px;
  background:#fff; border:1px solid var(--line); box-shadow:var(--shadow)}
.burger-menu a{padding:11px var(--s3); border-radius:9px; color:var(--ink2); font-weight:600; min-height:var(--tap);
  display:flex; align-items:center}
.burger-menu a:hover{background:var(--card2); text-decoration:none}
header.top .nav-login{font-weight:600; color:var(--ink2); padding:0 var(--s2)}
header.top .nav-cta{min-height:var(--tap); white-space:nowrap}
/* До 879 px широкое меню скрыто, после — наоборот прячется гамбургер.
   Одно и то же меню в двух местах разметки было бы двумя списками, которые
   разойдутся: здесь это один список в <details> и один в <nav>, и оба
   правятся в одном файле рядом. */
@media(max-width:879px){
  header.top .wide-nav{display:none}
  /* «Вход» на телефоне уезжает в меню — ему там место, а в полосе важнее
     кнопка урока. Ссылка остаётся в подвале и в меню. */
  header.top .nav-login{display:none}
  .burger-menu{right:auto; left:0; min-width:min(260px,calc(100vw - 24px))}
}
@media(min-width:880px){
  header.top .burger{display:none}
  header.top.topnav{padding:var(--s3) var(--s5)}
  header.top .wide-nav{display:flex; gap:16px; align-items:center; flex-wrap:wrap; margin-left:auto}
}

/* Первый экран на телефоне: кнопки во всю ширину (TASK-91 Ф3).
   На снимке «до правки» две кнопки стояли одна под другой разной ширины —
   «Бесплатный урок» уже, «Посмотреть урок» шире, — и главная кнопка выглядела
   менее важной, чем второстепенная. Во всю ширину они ещё и попадают под палец
   без прицеливания. На широком экране остаётся обычный ряд. */
@media(max-width:620px){
  .hero2 .cta{flex-direction:column; align-items:stretch}
  .hero2 .cta .btn{width:100%}
  /* Воздуха в первом экране на телефоне меньше, чем на ноутбуке: там он
     украшает, здесь — отодвигает показ урока за край экрана. */
  .hero2{padding:var(--s4) 0 var(--s5); gap:var(--s5)}
  .hero2 .sub{margin-bottom:var(--s4)}
  .hero2 .note{font-size:13px}
}

/* Показ урока доиграл — звуковые полоски замирают (TASK-91 Ф3в). */
.lessondemo[data-state="done"] .ld-wave{background:var(--muted)}
.lessondemo[data-state="done"] .ld-wave i{animation:none;height:4px}
.lessondemo[data-state="done"] .ld-state{color:var(--muted)}

/* --- КАРУСЕЛЬ УЧИТЕЛЕЙ (TASK-91 Ф3, ТЗ: «учителя каруселью») ---------------
   Была сетка из 21 карточки в три колонки — семь рядов почти одинаковых
   нарисованных лиц, которые на мелком масштабе читаются как стена клонов и
   занимают четверть всей страницы. Карусель решает ровно это: в поле зрения
   два-три учителя, остальные листаются.
   БЕЗ СКРИПТА, на прокрутке с привязкой: стрелки «вперёд-назад» на скрипте —
   это и отдельная кнопка под палец, и поломка, когда скрипт не приехал, а
   пальцем и колесом такая лента листается на всех устройствах одинаково.
   `scroll-snap` не даёт карточке остановиться наполовину за краем. */
.carousel{display:grid; grid-auto-flow:column; grid-auto-columns:minmax(230px,78vw);
  gap:var(--s4); overflow-x:auto; scroll-snap-type:x mandatory; padding:4px 4px var(--s3);
  -webkit-overflow-scrolling:touch; overscroll-behavior-x:contain;
  scrollbar-width:thin}
.carousel > *{scroll-snap-align:start}
@media(min-width:720px){ .carousel{grid-auto-columns:minmax(240px,1fr); } }
/* Подсказка, что лента листается: без неё половина людей не догадывается, что
   справа ещё что-то есть, — горизонтальная прокрутка на вид неотличима от
   обрезанного блока. */
.carousel-hint{display:flex; align-items:center; gap:6px; justify-content:center;
  font-size:14px; color:var(--muted); margin-top:var(--s2)}

/* Текст только для экранного диктора. Нужен там, где ячейка или кнопка
   обязана иметь имя, но показывать его на экране незачем (угловая ячейка
   таблицы сравнения). `clip-path` вместо `display:none`: скрытое display'ем
   диктор не читает вовсе — то есть «спрятали» означало бы «удалили». */
.sr-only{position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0}
/* Заголовок строки в таблице сравнения выглядит как обычная ячейка:
   жирность ему не нужна, нужна только связь для диктора. */
table.cmp th.row{font-weight:600; text-align:left}


/* «Вход в кабинет» в мобильном меню — отделён от разделов сайта: это действие,
   а не раздел, и в общем списке он теряется среди восьми ссылок. */
.burger-menu .burger-login{margin-top:var(--s2); border-top:1px solid var(--line);
  padding-top:var(--s3); font-weight:700; color:var(--link)}

/* --- ССЫЛКИ-ДЕЙСТВИЯ ПОД ПАЛЕЦ (TASK-91 Ф5) -------------------------------
   Замер нашёл ссылки-действия высотой 22 px при пороге 44: «Весь урок →» в
   показе урока, «Создать кабинет» и «Забыли пароль?» под формой входа. Это не
   ссылки внутри фразы (у тех порог другой) — это отдельные строки, по которым
   бьют пальцем, и промах по «Забыли пароль?» на форме входа стоит человеку
   попытки входа. Правило только для сенсорного экрана: на мыши 22 px хватает
   (WCAG 2.5.8 требует 24), и раздувать ссылки на ноутбуке незачем. */
@media (pointer: coarse){
  .ld-link, .authlinks a, .lead a.btn-ish{min-height:var(--tap); display:inline-flex; align-items:center}
}
