/* style-01-chrome.css — часть бывшего style.css (распил 22.10.2026): шапка, шестерёнка настроек, экран входа, каркас страницы.
   Файлы style-NN-*.css — ОДИН каскад: index.html подключает их подряд и по номерам, порядок значим
   (правило ниже по каскаду перебивает равное выше). Стережёт tools/check.js. */
  /* Design tokens live in theme.css (loaded first). Legacy aliases kept so the
     older component rules below keep resolving while they migrate. */
  :root{
    /* высота sticky-шапки; настоящее значение подставляет core.js (trackHeaderHeight),
       здесь — запасное на случай, если модуль ещё не выполнился */
    --hdr-h:66px;
    --accent-dark:var(--accent-ink);
    --checked:var(--ok);
    --red:var(--danger);
    --green:var(--ok);
  }

  /* ---- app chrome ---------------------------------------------------------- */
  /* blox31 #1: три зоны — «назад» слева, логотип строго по центру, правый кластер (dev-список,
     ник, шестерёнка) справа. Боковые колонки равной ширины (minmax(0,1fr)) держат логотип по
     центру; длинное «назад» режется многоточием — но только потому, что слот .hdr-back растянут
     по своей дорожке (см. его правило ниже, blox52 #16 п.1). */
  /* env(safe-area-inset-*) через max() — фон шапки тянется до физических краёв (viewport-fit=cover),
     а содержимое (логотип, ник, шестерёнка) отодвинуто от выреза/скруглённого угла в горизонтали.
     Без выреза env()=0 → max() берёт базовые 14/18px, раскладка не меняется. */
  header{
    position:sticky;top:0;z-index:40;
    /* ДВА СЛОЯ ФОНА: сверху свет в углу (--hdr-sheen), под ним сама заливка схемы.
       Здесь не переопределяется НИЧЕГО: и заливка, и форма света — токены в theme.css,
       а силу света каждая схема объявляет у себя (у «Lingo» она вполсилы, по замеру
       контраста белого текста). */
    background:var(--hdr-sheen),var(--grad-header);color:var(--on-dark);
    padding:max(14px,env(safe-area-inset-top)) max(18px,env(safe-area-inset-right))
            14px max(18px,env(safe-area-inset-left));
    /* Три колонки: назад · логотип · правый кластер. У ПРАВОЙ минимум = min-content, а не 0
       (blox37 #7). С minmax(0,1fr) её дорожка сжималась уже 375px, но содержимое (выпадашка
       ребёнка + шестерёнка) не сжималось вместе с ней и вылезало ВЛЕВО — прямо на слово «Lingo»
       (перекрытие 30px). Теперь дорожка не бывает уже своего содержимого: тесно — логотип
       уезжает от центра влево, но столкновения не будет никогда. Логотип — украшение,
       переключатель ребёнка и шестерёнка — органы управления; уступать обязано украшение. */
    display:grid;grid-template-columns:minmax(0,1fr) auto minmax(min-content,1fr);
    align-items:center;gap:14px;
    /* ПЛАНКА, А НЕ КАРТОЧКА (blox52 #5). Была --sh-2 — ровно та же мягкая тень, что у
       любого листа, и шапка читалась большой карточкой. Планка собрана своим рецептом:
       волосок по нижней кромке + чёткая линия контакта + короткая тень (theme.css, «ПЛАНКА
       ШАПКИ»).
       ЭТА СТРОКА — ЗАПАСНОЙ ВАРИАНТ, и она нарочно лежит СНАРУЖИ @supports ниже. Браузер,
       который не умеет привязывать анимацию к прокрутке, видит только её и получает
       постоянную тень — сегодняшнее поведение, просто новой формы. Перенести её внутрь
       @supports значит молча оставить такие браузеры вообще без тени; за этим следит
       секция «планка шапки» в npm run check. */
    box-shadow:var(--plank);
  }
  /* ТЕНЬ ПОЯВЛЯЕТСЯ ОТ ПРОКРУТКИ — и ни строчки на JS. Пока страница в нуле, бумага начинается
     вплотную под шапкой: тени взяться неоткуда, и планка плоская. Тень набирает полную силу за
     первые 40px прокрутки — ровно на том пути, где под шапку заезжает содержимое.
     Почему CSS, а не обработчик scroll: обработчик считался бы на каждом кадре прокрутки (на
     телефоне это самый дорогой кадр из всех) и требовал бы записи в DOM; здесь же браузер сам
     двигает анимацию по позиции прокрутки, вне основного потока вычислений. Ничего не
     перерисовывается и не переставляется — значит и «прыжка экрана» здесь взяться неоткуда.
     @supports обязателен: привязка к прокрутке есть не везде. Где её нет — правило целиком
     не применяется, и остаётся постоянная тень из header выше. Деградация незаметная.
     Число слоёв в --plank-flat и --plank совпадает намеренно — иначе браузеру нечего
     интерполировать и тень включалась бы рывком. */
  @supports (animation-timeline: scroll()){
    @keyframes hdr-plank{
      from{box-shadow:var(--plank-flat)}
      to{box-shadow:var(--plank)}
    }
    header{
      animation-name:hdr-plank;
      animation-timing-function:linear;
      animation-fill-mode:both;
      /* длительность НЕ пишем: при живой шкале прокрутки её значение по умолчанию (auto)
         и означает «растянуть на весь диапазон ниже». Записать сюда секунды — сломать связь. */
      animation-timeline:scroll(root block);
      animation-range:0 40px;
    }
  }
  /* justify-self:stretch, НЕ start (blox52 #16 п.1, нашли оба судьи): start-выравненный
     грид-элемент ширится ПО СОДЕРЖИМОМУ и переливается через свою дорожку — на 375 кнопка
     «‹ Кабинет» (113px при дорожке 84px) въезжала прямо в точку у слова Lingo. Stretch
     прижимает слот к ширине дорожки, и многоточие .mlabel наконец получает право резать
     подпись; кнопка внутри и так стоит слева (flex). Знак не столкнётся ни в каком шрифте:
     ограничение геометрическое, а не подобранное под Onest. */
  .hdr-back{justify-self:stretch;display:flex;align-items:center;min-width:0;overflow:hidden}
  /* в шапке сбрасываем margin-bottom тела-версии .mback — иначе он занимает место снизу и при
     align-items:center кнопка визуально уезжает вверх (blox31 #… — «съехала чуть вверх») */
  /* та же контурная кнопка B, но на тёмной шапке: полупрозрачно-белый контур (язык .set-btn),
     margin сброшен — иначе margin-bottom тела-версии уводит кнопку вверх при align центре. */
  .hdr-back .mback{color:var(--on-dark);border-color:rgba(255,255,255,.35);max-width:100%;margin:0;
    /* отклик нажатия — тот же язык, что у шестерёнки и колокольчика рядом (redesign 27.10) */
    transition:border-color var(--dur-state) var(--ease-standard),background-color var(--dur-state) var(--ease-standard),
      color var(--dur-state) var(--ease-standard),transform var(--dur-release) var(--ease-spring)}
  .hdr-back .mback:active{transform:scale(var(--press-scale));
    transition-duration:var(--dur-press-in);transition-timing-function:var(--ease-standard)}
  @media (prefers-reduced-motion:reduce){.hdr-back .mback:active{transform:none}}
  @media (hover:hover){.hdr-back .mback:hover{border-color:rgba(255,255,255,.55);background:rgba(255,255,255,.14);color:var(--on-dark)}}
  /* УЗКО — ТОЛЬКО СТРЕЛКА (blox60 #5, решение владельца 18.09.2026). Левая дорожка имеет минимум
     НОЛЬ (см. grid-template-columns выше), правая — min-content: значит при тесноте схлопывается
     именно «назад», и схлопывается ДО КОНЦА. 17.09 колокольчик открыли ученикам (blox60 #3) — в
     правый кластер ребёнка добавилось 38px, и слот «назад» ужался до 6.2px: подпись «Homework»
     получила НУЛЕВУЮ ширину, а кнопка вылезла за свой слот и наехала на логотип (на 375px — на
     11.8px, на 320px — на 18px). Выход из чата группы у ребёнка стал невидимым — кнопка жила и
     нажималась, но увидеть её было нельзя.
     Лечим не колокольчик, а правило: ниже 620px подпись прячется целиком, остаётся стрелка в
     честном квадрате 44×44 (цель касания, lingo-ui §3), а дорожка получает пол min-content и
     больше не схлопывается. Пусто в слоте — min-content равен нулю, дорожка снова чистая 1fr, и
     логотип стоит по центру ровно как раньше: экраны БЕЗ кнопки «назад» не меняются ни на пиксель.
     ПОЧЕМУ 620, а не 375. Порог выбран замером, а не на глаз, и он про САМУЮ ДЛИННУЮ подпись:
     «Homework» у ребёнка режется многоточием вплоть до 560px (у ребёнка правый кластер шире —
     в нём блок аккаунта) и становится целым только на 620. У Лу «Кабинет» помещается уже с 414px,
     так что на планшете она слово теряет — сознательный размен: лучше честная стрелка везде, чем
     смазанный огрызок на части ширин. Появится подпись ДЛИННЕЕ «Homework» — порог надо пересчитать
     тем же замером (ширина .mlabel: scrollWidth против clientWidth). За нулевой шириной и наездом
     на логотип следит геометрия ночного обходчика (G2/G6, tools/crawl.js) — она этот дефект и нашла. */
  @media (max-width:620px){
    header{grid-template-columns:minmax(min-content,1fr) auto minmax(min-content,1fr)}
    .hdr-back .mback .mlabel{display:none}
    .hdr-back .mback{width:44px;height:44px;justify-content:center;padding:0;gap:0}
  }
  .hdr-right{justify-self:end;display:flex;align-items:center;gap:10px;min-width:0}
  /* ЗНАК ШКОЛЫ — картинка (см. index.html). Прежде здесь было слово «Lingo» текстом плюс
     точка на ::before; и точка, и подбор шрифта ушли вместе с текстом: у рукописной надписи
     есть своя россыпь крапинок, и правильная точка рядом с ней читалась бы вторым знаком.
     Токен --brand-dot остался — его берёт та же точка на экране входа. */
  header .logo{
    font-weight:800;font-size:var(--fs-2xl);letter-spacing:var(--tracking-tight);
    display:flex;align-items:center;justify-self:center;white-space:nowrap;min-width:0;
  }
  /* Высоту задаём картинке, ширину она добирает сама — пропорции знака не искажаются никогда
     (это же проверяет G12 в ночном обходе). max-width страхует узкую дорожку сетки: знак
     сожмётся, но не столкнётся с правым кластером. */
  header .logo img{height:34px;width:auto;max-width:100%;object-fit:contain;display:block}
  header .who{display:flex;align-items:center;gap:8px;min-width:0}
  header .auth{display:flex;align-items:center;gap:10px}
  /* на телефоне режем отступы/зазоры шапки — иначе правый кластер не влезает в одну строку */
  @media(max-width:430px){
    header{padding:max(12px,env(safe-area-inset-top)) max(10px,env(safe-area-inset-right))
                   12px max(10px,env(safe-area-inset-left));gap:8px}
    header .who{gap:6px}
    header .auth{gap:8px}
    .hdr-right{gap:8px}
    header .logo img{height:26px}   /* знак уступает место правому кластеру, а не наоборот */
    header .who select{max-width:72px}   /* dev-элемент; ужат, чтобы не наезжать на центр-логотип */
    header .who span{display:none}   /* «Кто я:» — dev-подпись, на телефоне прячем ради ширины */
  }
  /* КОЛЕСИКО ЗАГРУЗКИ (blox72 #11) — кольцо вокруг колокольчика; включает core.js (netPaint), когда
     передний запрос ждёт ответа дольше секунды. ПОЧЕМУ КОЛЬЦО ВОКРУГ, А НЕ ЗНАЧОК РЯДОМ: на
     телефоне в шапке нет свободного места — замер у всех ролей на 320–414px показал между знаком
     школы и правым кластером ровно зазор сетки (8px). Значок в потоке растолкал бы кластер и на
     узком экране ребёнка выдавил бы шапку за край. Кольцо висит поверх слота (position:absolute,
     вне потока): шапка не сдвигается ни на пиксель ни при появлении, ни при исчезновении.
     Диаметр 50 — чтобы кольцо обошло скруглённые углы кнопки 38×38 (угол на 22.7px от центра),
     не задев их. Клики проходят насквозь: кольцо ничего не блокирует. Цвет — тот же
     полупрозрачно-белый язык, что у контура колокольчика и шестерёнки на тёмной шапке. */
  .notif-slot{position:relative;display:flex;align-items:center}
  .netwait{position:absolute;left:50%;top:50%;width:0;height:0;pointer-events:none;z-index:1}
  .netwait[hidden]{display:none}
  .netwait-ring{position:absolute;left:-25px;top:-25px;width:50px;height:50px;box-sizing:border-box;
    border-radius:50%;border:2px solid rgba(255,255,255,.22);border-top-color:var(--on-dark);
    border-right-color:var(--on-dark);animation:btn-spin .8s linear infinite}
  @media (prefers-reduced-motion:reduce){.netwait-ring{animation-duration:2s;
    --motion-reduced:btn-spin 2s linear infinite}}   /* тихая версия для общего правила, theme.css */
  /* Колокольчика нет (роль без ленты, экран входа) — кольцо обходит шестерёнку: слот пуст и
     шириной ноль, следующий в ряду — .settings через зазор .hdr-right (10px; 8px на телефоне). */
  .notif-slot:has(> .notif:empty) .netwait{left:calc(100% + 10px + 19px)}
  @media(max-width:430px){.notif-slot:has(> .notif:empty) .netwait{left:calc(100% + 8px + 19px)}}
  /* 15 секунд без ответа — строка под шапкой у правого края, прямо под колесиком. Не в ряду шапки
     по той же причине, что и кольцо (места нет); висит под ней, ничего не блокирует
     (pointer-events:none) и уходит сама, как только ответ пришёл. */
  .netwait-msg{position:absolute;top:calc(100% + 6px);right:max(10px,env(safe-area-inset-right));
    max-width:calc(100vw - 20px);box-sizing:border-box;padding:8px 12px;border-radius:var(--r-sm);
    background:var(--card);color:var(--ink);box-shadow:var(--sheet-pop);
    font-size:var(--fs-sm);font-weight:700;line-height:var(--lh-tight);text-wrap:balance;pointer-events:none}
  .netwait-msg[hidden]{display:none}
  /* строка выбора шрифта — используется в попапе настроек (settings.js, blox18 #9) */
  .fsw-item{display:grid;grid-template-columns:1fr auto;align-items:center;gap:2px 10px;
    background:none;border:none;border-radius:var(--r-sm);padding:9px 11px;cursor:pointer;text-align:left;
    color:var(--ink);font-size:var(--fs-md);font-weight:700}
  @media (hover:hover){.fsw-item:hover{background:var(--accent-tint)}}
  .fsw-item.on{background:var(--accent-tint)}
  .fsw-item .fsw-note{grid-column:1;font-size:var(--fs-xs);font-weight:600;color:var(--muted)}
  .fsw-item .fsw-tick{grid-column:2;grid-row:1 / span 2;color:var(--accent-dark);font-weight:800;
    opacity:0}
  .fsw-item.on .fsw-tick{opacity:1}

  /* единый попап настроек (шестерёнка) — шрифт + цветовая схема (blox18 #9).
     Пункты шрифта переиспользуют .fsw-item выше. */
  .settings{position:relative;display:flex;align-items:center}
  .set-btn{width:38px;height:38px;border-radius:var(--r-sm);border:1px solid rgba(255,255,255,.35);
    background:rgba(255,255,255,.12);color:var(--on-dark);cursor:pointer;
    display:flex;align-items:center;justify-content:center;
    /* redesign 27.10 — у шестерёнки был только ховер: нажатие и открытое меню не отличались от
       покоя. Теперь: вдавливание (--press-scale-sm, сухо), пружина назад, и пока меню открыто —
       кнопка «включена» (подложка гуще, рамка ярче), как у колокольчика-близнеца. */
    position:relative;-webkit-tap-highlight-color:transparent;
    transition:background-color var(--dur-state) var(--ease-standard),border-color var(--dur-state) var(--ease-standard),
      transform var(--dur-release) var(--ease-spring)}
  @media (hover:hover){.set-btn:hover{background:rgba(255,255,255,.22)}}
  .set-btn:active{transform:scale(var(--press-scale-sm));
    transition-duration:var(--dur-press-in);transition-timing-function:var(--ease-standard)}
  .set-btn[aria-expanded="true"]{background:rgba(255,255,255,.26);border-color:rgba(255,255,255,.6)}
  /* палец — 44px (G5): кнопка 38px видом, касание ловит невидимый ободок в 3px. Шапка не растёт:
     её высоту держат и пересчитывают (--hdr-h), сдвиг на 6px увёл бы все прилипающие полосы */
  .set-btn::before{content:"";position:absolute;inset:-3px;border-radius:inherit}
  @media (prefers-reduced-motion:reduce){.set-btn:active{transform:none}}
  .set-menu{display:none;position:absolute;top:calc(100% + 8px);right:0;z-index:50;
    width:max-content;max-width:min(300px,calc(100vw - 24px));
    max-height:calc(100vh - 84px);overflow-y:auto;   /* не обрезаем «Выйти» на низкой ПК-высоте (blox31 #1) */
    /* РАМКИ НЕТ (blox52 #4, п.1): край листа задан обрезным краем внутри --sheet-pop и
       контрастом к тому, на чём меню висит. Рамка поверх — второе объявление того же факта.
       Бортик здесь ослаблен (--sheet-pop): меню висит вплотную под ТЁМНОЙ шапкой, и
       95%-белая грань блестела бы над ним полосой. */
    background:var(--card);border-radius:var(--r-lg);box-shadow:var(--sheet-pop);
    padding:8px;flex-direction:column;gap:4px;
    /* ПОЯВЛЕНИЕ И УХОД (redesign 27.10). Меню открывает класс .open (settings.js): display
       none ↔ flex. @starting-style даёт приезд — проявление и короткий спуск из-под кнопки
       (половина --enter-shift: меню висит в 8px от шапки, длинный путь читался бы падением);
       allow-discrete держит меню на экране, пока оно гаснет при закрытии. Угол роста — правый
       верхний, у шестерёнки. Закрывающееся меню не ловит касаний: JS уже считает его закрытым. */
    transform-origin:top right;opacity:1;translate:none;
    transition:opacity var(--dur-panel-out) var(--ease-exit),translate var(--dur-panel-out) var(--ease-exit),
      display var(--dur-panel-out);
    transition-behavior:allow-discrete}
  .set-menu:not(.open){pointer-events:none;opacity:0;translate:0 calc(var(--enter-shift) / -2)}
  .set-menu.open{display:flex;
    transition-duration:var(--dur-panel);transition-timing-function:var(--ease-enter)}
  @starting-style{.set-menu.open{opacity:0;translate:0 calc(var(--enter-shift) / -2)}}
  .set-sec{display:flex;flex-direction:column;gap:2px}
  /* blox55 #22 — ДВЕ КОЛОНКИ вместо столбика (почему — комментарий в settings.js над mountSettings).
     Сетка объявлена ЗДЕСЬ, а не у каждой секции: и шрифты, и схемы — один и тот же список выбора
     из четырёх, и раскладка у них обязана быть одна. Ширину меню на широких экранах поднимаем
     до 380px: в 300px ячейка получается 139px, и подпись схемы («Графитовая» + «графит и Maya
     Blue») ломается на три строки — выигрыш от двух колонок съедается обратно. На телефоне
     ширину не трогаем: там меню и так во весь экран минус поля. */
  .set-grid{display:grid;grid-template-columns:1fr 1fr;gap:2px}
  @media(min-width:761px){ .set-menu{max-width:min(380px,calc(100vw - 24px))} }
  /* blox69 #7 расширял меню до 560px и ставил шрифты в три колонки — их было шесть. С blox72 #7
     шрифтов два (остальные под заглушкой) — обычные две колонки, одна строка, ширина прежняя. */
  /* В ячейке вдвое меньше ширины, поэтому в сетке всё поджато: точки мельче, зазор до текста
     меньше, поля кнопки уже. Сами точки остаются главным превью палитры — ассерт «цветовая схема»
     сверяет их цвет с токенами включённой схемы, и уменьшение размера ему безразлично. */
  .set-grid .set-scheme{gap:2px 8px;padding:9px 8px}
  .set-grid .set-dots i{width:11px;height:11px}
  .set-grid .fsw-item{padding:9px 9px}
  /* ПОДПИСЬ СХЕМЫ В СЕТКЕ НЕ ПОКАЗЫВАЕМ. В половинной ячейке «ночная, виноградный якорь» ломается
     на три строки, и секция из двух колонок выходит почти такой же высокой, как столбик, — то есть
     правка не срабатывает. Потеря тут небольшая: подпись пересказывает словами то, что рядом уже
     нарисовано точками (первая = шапка схемы), а имя схемы остаётся. У ШРИФТОВ подпись остаётся —
     она не дублирует ничего: «мягкий, для младших» и «шрифт устройства» — это совет, как выбрать. */
  .set-grid .set-snote{display:none}
  /* А на ТЕЛЕФОНЕ схемы остаются столбиком: меню там 300px, половинная ячейка — 145px, и в неё
     не помещается «точки + Sneakers + галочка» (подпись вылезала за край меню). Шрифтов это не
     касается — их ячейка укладывается. Столбик схем на телефоне ничего не ломает: без подписей
     секция всё равно вдвое ниже прежней, и меню целиком влезает в экран. */
  @media(max-width:760px){ .set-grid-sch{grid-template-columns:1fr} }
  /* ГРАВИРОВАННАЯ ЛИНЕЙКА (blox52 #4, п.3): волосок + светлый блик ПОД ним — то же
     тиснение, что на карточке, только в одну строку. Так разделитель перестаёт быть
     просто серой чертой поверх бумаги и читается оттиском В бумаге. */
  .set-sec + .set-sec{margin-top:6px;padding-top:8px;border-top:1px solid var(--line-soft);
    box-shadow:var(--rule-t)}
  .set-h{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.06em;text-transform:uppercase;
    color:var(--muted);padding:2px 11px 4px}
  .set-scheme{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:2px 11px;
    background:none;border:none;border-radius:var(--r-sm);padding:9px 11px;cursor:pointer;text-align:left;
    color:var(--ink);width:100%}
  @media (hover:hover){.set-scheme:hover{background:var(--accent-tint)}}
  .set-scheme.on{background:var(--accent-tint)}
  .set-dots{grid-row:1 / span 2;display:flex;gap:3px}
  .set-dots i{width:13px;height:13px;border-radius:50%;border:1px solid rgba(0,0,0,.08)}
  .set-sbody{grid-column:2;display:flex;flex-direction:column}
  .set-sname{font-size:var(--fs-md);font-weight:700}
  .set-snote{font-size:var(--fs-xs);font-weight:600;color:var(--muted)}
  .set-scheme .fsw-tick{grid-column:3;grid-row:1 / span 2;color:var(--accent-dark);font-weight:800;opacity:0}
  .set-scheme.on .fsw-tick{opacity:1}
  .auth .auth-me{font-weight:700;font-size:var(--fs-sm);opacity:.95}
  /* переключатель детей в шапке ребёнка: без ограничения ширины нативный select раздувается
     до самого длинного пункта («➕ Добавить») и вся шапка ломается на две строки на телефоне.
     Ограничиваем ширину и обрезаем длинное имя многоточием — как у учителя, одна строка. */
  .auth .kid-switch{max-width:150px;text-overflow:ellipsis;padding:9px 10px}
  /* «Выйти» переехал из шапки вниз всплывашки настроек (blox31 #1). Отдельная секция снизу,
     отбита линией; мягкий красноватый акцент как у деструктивного действия, но негромкий. */
  .set-sec-logout{margin-top:6px;padding-top:8px;border-top:1px solid var(--line-soft);
    box-shadow:var(--rule-t)}
  .set-logout{width:100%;background:none;border:none;border-radius:var(--r-sm);padding:10px 11px;
    cursor:pointer;text-align:left;color:var(--alert-ink);font-weight:700;font-size:var(--fs-md)}
  @media (hover:hover){.set-logout:hover{background:var(--alert-tint)}}
  /* blox37 #1 — «Сообщить о проблеме». Тот же пункт-строка, что «Выйти», но виден
     ВСЕМ ролям: застревают чаще родители и дети. min-height 44px — палец (WCAG 2.5.5). */
  .set-sec-support{margin-top:6px;padding-top:8px;border-top:1px solid var(--line-soft);
    box-shadow:var(--rule-t)}
  .set-support{display:block;width:100%;min-height:44px;background:none;border:none;border-radius:var(--r-sm);
    padding:10px 11px;text-align:left;color:var(--ink);font-weight:700;font-size:var(--fs-md);cursor:pointer}
  @media (hover:hover){.set-support:hover{background:var(--surface-2)}}
  /* Подсказка «как установить» в меню настроек (blox55 #18). НАРОЧНО не кнопка и не похожа на
     неё — ни рамки, ни фона, ни наведения: нажимать в ней не на что (жест ручной, его делает сам
     человек через меню браузера), а контрол, который ничего не делает, — это мёртвый клик.
     Ширина задана здесь, а не у меню: меню тянется по содержимому, и без ограничения одна длинная
     строка растянула бы его до предела на всех экранах. */
  .set-hint{padding:0 11px 8px;color:var(--muted);font-size:var(--fs-xs);line-height:1.45;max-width:230px}
  /* на телефоне запас по ширине минимальный — режем селект сильнее, чтобы шапка держала одну строку.
     Стоит ПОСЛЕ базового max-width:150px, иначе при равной специфичности победит базовое правило. */
  @media(max-width:430px){ .auth .kid-switch{max-width:120px} }
  .ya-btn{display:inline-flex;align-items:center;gap:7px;background:#fff;color:#000;
    text-decoration:none;font-weight:700;font-size:var(--fs-sm);padding:8px 14px;border-radius:var(--r-sm);
    border:none;cursor:pointer}
  /* «Я» — фирменный знак Яндекса, а не иконка интерфейса: и кегль, и скругление привязаны
     к СВОЕЙ плашке (20px и 26px), а не к нашим лестницам --ic-* и --r-*. Поэтому здесь и в
     -lg числа оставлены числами: сдвинь мы ступень — знак перестанет попадать в свой
     квадрат, а его угол разойдётся с углом квадрата. */
  .ya-btn::before{content:"Я";display:inline-flex;align-items:center;justify-content:center;
    width:20px;height:20px;border-radius:5px;background:var(--ya-red);color:#fff;font-weight:800;font-size:14px}
  .ya-btn-lg{font-size:var(--fs-lg);padding:14px 22px;border-radius:var(--r-md);box-shadow:var(--sh-2)}
  .ya-btn-lg::before{width:26px;height:26px;font-size:18px;border-radius:7px}
  .landing{min-height:70vh;display:flex;align-items:center;justify-content:center;padding:24px}
  .landing-card{max-width:380px;text-align:center;background:var(--card);
    border-radius:var(--r-2xl);padding:38px 30px;box-shadow:var(--sheet-3)}
  .landing-logo{font-weight:800;font-size:var(--fs-4xl);letter-spacing:var(--tracking-tight);margin-bottom:10px;
    background:var(--grad-wordmark);
    -webkit-background-clip:text;background-clip:text;color:transparent}
  .landing-sub{color:var(--muted-strong);font-size:var(--fs-md);line-height:1.5;margin:0 0 22px}
  /* Две двери входа — «Ученик» и «Учитель» — стоят столбиком и НАМЕРЕННО одинаковы: роль
     решает строка в users, а не кнопка. Подпись БЕЗ «Я»: значок Яндекса рисуется через
     .ya-btn::before (красный квадрат с буквой «Я»), и «Я ученик» читалось как «Я Я ученик».
     Выделять одну из дверей нечем. Растягиваем по ширине карточки, иначе inline-flex сажает
     их в одну строку. */
  .landing-doors{display:flex;flex-direction:column;gap:10px}
  .landing-doors .ya-btn{width:100%;justify-content:center;box-sizing:border-box}
  /* 44px высоты — это ссылка-кнопка на экране входа, палец промахивается по 18-пиксельной строке */
  .switch-link{display:block;margin:8px auto 0;padding:12px 4px;min-height:44px;box-sizing:border-box;
    color:var(--accent-ink);font-size:var(--fs-sm);text-decoration:underline}
  /* Ошибка входа. Живёт НА экране входа, а не в alert: почти всегда причина в том, что браузер уже
     залогинен не в тот Яндекс-аккаунт, и рядом с текстом обязана быть кнопка «выбрать другой». */
  .login-err{text-align:left;border:1px solid var(--alert-line);border-radius:var(--r-lg);
    background:var(--alert-tint);padding:12px 14px;margin:0 0 18px}
  .login-err-msg{display:flex;gap:8px;font-size:var(--fs-md);line-height:1.45;font-weight:600;color:var(--ink)}
  .login-err-msg svg{width:18px;height:18px;flex:0 0 18px;margin-top:2px;color:var(--alert-ink)}
  .login-err-em{margin-top:8px;font-size:var(--fs-sm);color:var(--muted-strong);overflow-wrap:anywhere}
  /* Подсказка «а если аккаунт верный» — вторым планом: она нужна меньшинству, а первую строку
     перебивать не должна. */
  .login-err-hint{margin-top:8px;font-size:var(--fs-sm);line-height:1.4;color:var(--muted-strong);
    padding-top:8px;border-top:1px solid var(--alert-line)}
  /* blox78 #4 — как добавить аккаунт, которого нет в окне выбора Яндекса. Под главной кнопкой,
     вторым планом: нужна тем, кто уже раз нажал «выбрать» и не нашёл себя в списке. */
  .login-pick-tip{margin:8px 2px 4px;font-size:var(--fs-sm);line-height:1.4;color:var(--muted-strong)}
  select{
    border:1px solid var(--line);border-radius:var(--r-sm);padding:9px 12px;font-size:var(--fs-md);
    background:var(--card);color:var(--ink);font-weight:600;
  }
  header select{border-color:transparent}
  /* боковые/нижний отступы контента учитывают вырез (viewport-fit=cover): в горизонтали карточки
     не заезжают под вырез слева/справа, а низ страницы не прячется под home-индикатор. env()=0 без
     выреза → max()/сумма дают базовые значения, обычный экран не меняется. */
  main{max-width:900px;margin:0 auto;
    padding:var(--sp-5) max(var(--sp-4),env(safe-area-inset-right))
            calc(var(--sp-8) + env(safe-area-inset-bottom)) max(var(--sp-4),env(safe-area-inset-left))}
  /* blox53 #29 — КОЛОНТИТУЛ ШКОЛЫ у нижнего края. Лежит на СТОЛЕ, а не на бумаге, поэтому цвет
     --on-bg (у --faint на столе 1.9:1 — подпись исчезла бы). Тише контента и по центру: это
     подпись документа, а не сообщение — она не должна спорить с последней карточкой листа.
     Отступ снизу учитывает вырез телефона тем же способом, что и main. */
  .pfoot{max-width:900px;margin:0 auto;
    padding:0 max(var(--sp-4),env(safe-area-inset-right))
            calc(var(--sp-6) + env(safe-area-inset-bottom)) max(var(--sp-4),env(safe-area-inset-left));
    text-align:center;color:var(--on-bg);font-size:var(--fs-xs);line-height:1.5}
  .pfoot-b{font-weight:700;white-space:nowrap}
  .sub{color:var(--muted);margin:4px 0 18px;font-size:var(--fs-md)}
  h2{margin:0 0 2px;font-size:var(--fs-2xl);font-weight:800;color:var(--ink-strong)}

  .badge{font-size:var(--ic-lg)}


  /* ═══════════════════════════════════════════════════════════════════════
     ПЕРЕРИСОВКА B — ПОЛОСА ГРУППЫ (redraw-b, агент 2 «общие части»).
     Верх трёх экранов — монитор учителя, «сдачи по таску», Домашка ребёнка — лежит на ОДНОЙ
     сплошной полосе цвета текущей группы: шапка + то, что экран пометил классом .gband
     (лента групп и каретка дней; шапка таска; заголовок «Homework» с чипами). Цвет ставит
     applyGroupColor(document.body, gid) (public/group-color.js): корнем выбран body, потому что
     только он держит и шапку, и экран — шапка живёт вне #view и переживает любую перерисовку.
     ПОЧЕМУ :has(), А НЕ КЛАСС НА body. Класс пришлось бы снимать при уходе на любой другой
     экран (оплаты, документы, чаты), а таких дверей десятки. :has() ничего не помнит: экран с
     полосой на месте — шапка цвета группы; ушли — та же шапка снова нейтральна (--grad-header,
     сланец B). Старый браузер без :has() просто оставит шапку нейтральной — полоса под ней
     всё равно цветная. */
  .gband{background:var(--group);color:var(--on-group);display:flow-root;
    /* ВО ВСЮ ШИРИНУ ОКНА, хотя main ограничен 900/1400px. Не отрицательные поля и не 100vw
       (вызвали бы горизонтальную прокрутку под полосой прокрутки) — border-image с выносом:
       заливка дорисовывается на 100vmax вбок как «чернила», в раскладку и в scrollWidth не
       входит, а выпадающие меню внутри полосы (гамбургер) не режутся — clip-path резал бы их. */
    border-image:linear-gradient(var(--group),var(--group)) fill 0 // 0 100vmax}
  /* первая полоса экрана примыкает к шапке без шва: у main снимается верхний отступ, полоса
     берёт его себе внутрь (тем же значением --sp-3) */
  main:has(.gband-top){padding-top:0}
  .gband-top{padding-top:var(--sp-3)}
  /* Планка шапки (волосок + тень от прокрутки) остаётся прежней и на полосе: её стережёт проба
     «blox52 #5 · планка шапки», а светлый волосок на цвете группы почти не виден. */
  body:has(#view .gband) header{background:var(--group)}
  /* заголовок экрана на полосе («Homework») — белым; кегль и витринный шрифт ставит экран */
  .gband h2{color:var(--on-group)}
