/* Стили платформы Lessona.
   Принцип палитры: хром нейтральный (чернила), единственный яркий цвет —
   жёлтый маркер — закреплён строго за заметками и выделениями. Тема урока
   красит только область урока (см. applyTheme в core.js), но не хром. */
:root{
  /* Палитра платформы под именами --c-*. Тема урока их не переопределяет —
     благодаря этому класс .unthemed возвращает платформенные цвета внутри
     оформленного урока (поля редактора не должны краситься темой). */
  --c-ink:#171A21; --c-ink-2:#3A3F4A; --c-muted:#7C7A72;
  --c-paper:#FBFAF7; --c-surface:#FFFFFF; --c-surface-2:#F1EFEA;
  --c-line:#E6E4DE; --c-line-2:#D2CFC6;
  --c-marker:#E8A317; --c-marker-soft:#FBEBC4; --c-marker-ink:#7A5406;
  --c-ok:#2E7D4F; --c-ok-bg:#E7F2EB; --c-err:#C33A2B; --c-err-bg:#FAEAE7; --c-err-line:#F0C9A8;

  /* Хром платформы */
  --ink:var(--c-ink); --ink-2:var(--c-ink-2); --muted:var(--c-muted);
  --marker:var(--c-marker); --marker-soft:var(--c-marker-soft); --marker-ink:var(--c-marker-ink);
  --paper:var(--c-paper); --surface:var(--c-surface);
  --line:var(--c-line); --line-2:var(--c-line-2);
  --ok:var(--c-ok); --ok-bg:var(--c-ok-bg);
  --err:var(--c-err); --err-bg:var(--c-err-bg); --err-line:var(--c-err-line);
  --radius:12px; --radius-sm:9px;
  /* Шкала отступов (хендофф v2). Двенадцать величин, выбранных по месту,
     сведены к шести ступеням — иначе соседние блоки не выравниваются. */
  --s-1:4px;   /* внутри плашек, значок↔текст */
  --s-2:8px;   /* связанные элементы */
  --s-3:12px;  /* строки списков, gap сеток */
  --s-4:16px;  /* отступ карточки — он же --pad */
  --s-5:24px;  /* между разделами страницы */
  --s-6:32px;  /* поля страницы, крупные развязки */
  /* Шкала кегля ХРОМА — шесть ступеней из хендоффа v2 (раздел «Дизайн-токены»).
     Урочные кегли сюда не входят: они живут в темах оформления, и тема вправе
     набрать инструкцию задания своим размером. Лендинг тоже вне шкалы — у него
     свой типографический ряд с clamp().

     Соответствие уровням спеки:
       t-1 22px Onest 700     → --t-h1    заголовок страницы
       t-2 16px Onest 600     → --t-lg    заголовок карточки или раздела
       t-3 14px Manrope 400   → --t-md    основной текст хрома
       t-4 13px Onest 600     → --t-base  кнопки, меню, вкладки
       t-5 12.5px Manrope 400 → --t-sm    подписи
       t-6 10.5px Mono 600    → --t-label eyebrow, служебное

     Полупиксельные ступени не ошибка: на 10.5 набраны моношрифтовые метки, и
     округление до целого делает метку крупнее подписи, рядом с которой она
     стоит. Спека их и задаёт такими.

     Что осталось мимо шкалы, считает npm run css-scale. */
  --t-label:10.5px;
  --t-sm:12.5px;
  --t-base:13px;
  --t-md:14px;
  --t-lg:16px;
  --t-h1:22px;
  /* Вне шкалы хрома: заголовок текстового блока и заголовок части урока — это
     содержимое урока, а не платформа вокруг него. Отдельным именем, чтобы
     не читалось как седьмая ступень хрома. */
  --t-lesson-h:19px;

  --font-head:'Onest',system-ui,sans-serif;
  --font-body:'Manrope',system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,monospace;
  --pad:var(--s-4); --fs:var(--t-md);
  --shadow:0 6px 20px rgba(23,26,33,.08);

  /* Алиасы под старые имена переменных — чтобы существующие компоненты
     взяли палитру Lessona без правок. В контексте урока applyTheme
     переопределяет эти же переменные на палитру темы. */
  --bg:var(--paper);
  --surface-2:var(--c-surface-2);
  --line-strong:var(--line-2);
  --accent:var(--ink); --accent-ink:var(--paper);
  --accent-soft:#F1EFEA; --accent-soft-ink:var(--ink);
  --note:var(--marker); --note-bg:var(--marker-soft); --note-ink:var(--marker-ink);
  /* Рамка и «скотч» заметки — тоже переменные: тема урока красит заметку своим
     акцентом, и жёлтый кант на её фоне выглядел бы чужим. */
  --note-line:#EBD9A0; --note-tape:rgba(232,163,23,.45);
}

/* Тёмная тема хрома (обязательна по брифу — половина учеников занимается вечером).
   Класс ставится на <html> из core.js; учитывает системную настройку. */
html[data-chrome="dark"]{
  /* Переопределяем только --c-*: остальные имена ссылаются на них, поэтому
     .unthemed в тёмном хроме тоже получает тёмные платформенные цвета. */
  --c-ink:#E9E9E6; --c-ink-2:#C4C4C0; --c-muted:#8C8C86;
  --c-paper:#16181D; --c-surface:#1D2027; --c-surface-2:#23262D;
  --c-line:#2B2F37; --c-line-2:#3A3F4A;
  --c-ok:#5FBF86; --c-ok-bg:#1C2A22; --c-err:#E88579; --c-err-bg:#2E211F; --c-err-line:#5A3A2E;
  --c-marker-soft:#3A3320; --c-marker-ink:#E8C77A;
  --note-line:#5A4A22; --note-tape:rgba(232,199,122,.30);
  /* --accent задаём через --ink, а не --paper: в тёмной палитре --paper это цвет
     фона, и текст вроде a{color:var(--accent)} становился невидим. */
  --accent:var(--ink); --accent-ink:var(--paper); --accent-soft:var(--c-surface-2);
  --shadow:0 8px 24px rgba(0,0,0,.4);
}

/* Повышенный контраст — настройка доступности платформы (Настройки →
   Оформление). Раньше это была седьмая тема урока, то есть включалась там, где
   её почти не видно, и только для одного урока. Переопределяем базовый слой
   --c-*, поэтому контраст доходит и до .unthemed-островков внутри занятия. */
html[data-contrast="high"]{
  --c-ink:#000000; --c-ink-2:#111111; --c-muted:#333333;
  --c-paper:#FFFFFF; --c-surface:#FFFFFF; --c-surface-2:#EDEDED;
  --c-line:#111111; --c-line-2:#000000;
  --c-ok:#12662F; --c-ok-bg:#E4F3E9; --c-err:#B00020; --c-err-bg:#FBE6EA; --c-err-line:#B00020;
  --c-marker-ink:#4A3300;
}
html[data-chrome="dark"][data-contrast="high"]{
  --c-ink:#FFFFFF; --c-ink-2:#F0F0F0; --c-muted:#D0D0D0;
  --c-paper:#000000; --c-surface:#0B0B0B; --c-surface-2:#1C1C1C;
  --c-line:#EDEDED; --c-line-2:#FFFFFF;
  --c-ok:#7BE0A2; --c-ok-bg:#0C2114; --c-err:#FF9C90; --c-err-bg:#2A0F0C; --c-err-line:#FF9C90;
  --c-marker-soft:#4A3300; --c-marker-ink:#FFE9B8;
}

/* Островок платформенной палитры внутри оформленного урока.
   Тема урока пишет свои цвета в контейнер урока (applyTheme), и всё внутри их
   наследует — включая поля редактора, которые темой краситься не должны:
   панель «Стиль» обещает «как урок выглядит у ученика», а не «покрасить
   конструктор». Здесь возвращаем платформенные --c-* обратно. */
.unthemed{
  --ink:var(--c-ink); --ink-2:var(--c-ink-2); --muted:var(--c-muted);
  --paper:var(--c-paper); --surface:var(--c-surface); --surface-2:var(--c-surface-2);
  --line:var(--c-line); --line-2:var(--c-line-2); --line-strong:var(--c-line-2);
  --accent:var(--c-ink); --accent-ink:var(--c-paper);
  --accent-soft:var(--c-surface-2); --accent-soft-ink:var(--c-ink);
  /* Скругления тоже платформенные: тема урока задаёт свои (от 6 до 20), и хром
     внутри занятия менял форму вместе с уроком — панель хода становилась то
     острой, то круглой, хотя к уроку не относится. */
  --radius:12px; --radius-sm:9px;
  /* Зелёное и красное хрома: тема урока переопределяет и их, и «в классе» в
     шапке занятия бралось зелёным темы — на платформенной бумаге оно линяло. */
  --ok:var(--c-ok); --ok-bg:var(--c-ok-bg);
  --err:var(--c-err); --err-bg:var(--c-err-bg); --err-line:var(--c-err-line);
  font-family:var(--font-body);   /* иначе дети наследуют шрифт темы, а не переменную */
  /* маркер тоже возвращаем платформенный: тема урока красит свои заметки своим
     акцентом, но элементов хрома внутри страницы урока это не касается */
  --marker:var(--c-marker); --marker-soft:var(--c-marker-soft); --marker-ink:var(--c-marker-ink);
  --note:var(--marker); --note-bg:var(--marker-soft); --note-ink:var(--marker-ink);
  --font-head:'Onest',system-ui,sans-serif;
  --font-body:'Manrope',system-ui,sans-serif;
  color:var(--ink);
}
/* .btn.primary светлеет сама (background:var(--ink)), но её ховер в светлой теме
   уходит в чёрный — на тёмном фоне это нечитаемо, поэтому здесь наоборот. */
html[data-chrome="dark"] .btn.primary:hover{background:#FFFFFF;border-color:#FFFFFF}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--font-body);background:var(--bg);color:var(--ink);font-size:var(--fs);line-height:1.55;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4,.head{font-family:var(--font-head)}
button,input,textarea,select{font-family:inherit;color:inherit}
a{color:var(--accent)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}html{scroll-behavior:auto}}

/* ---------- Раскладка с левым меню ----------
   Меню — на страницах-списках (Сегодня, Уроки, Ученики, кабинет ученика).
   В конструкторе и классе меню нет: там своя левая колонка (рельса структуры,
   панель хода урока), две левые колонки сделали бы экран теснее без пользы. */
.app{display:grid;grid-template-columns:212px minmax(0,1fr);min-height:100vh}
.app-main{min-width:0;display:flex;flex-direction:column}

.sidebar{background:var(--paper);border-right:1px solid var(--line);padding:var(--s-4) var(--s-3);display:flex;flex-direction:column;gap:2px;position:sticky;top:0;height:100vh;overflow-y:auto}
.sidebar .brand{margin:0 var(--s-1) var(--s-4);font-size:var(--t-lg)}
.sidebar a,.sidebar button{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);border-radius:8px;border:none;background:transparent;width:100%;text-align:left;cursor:pointer;font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--ink-2);text-decoration:none}
.sidebar a:hover,.sidebar button:hover{background:var(--surface)}
/* Знак — не пункт меню: подсветка под ним выглядит как выделенный раздел */
.sidebar .brand:hover,.topbar .brand:hover{background:none}
.sidebar a.on,.sidebar button.on{background:var(--ink);color:var(--paper)}
.sidebar .sep{height:1px;background:var(--line);margin:var(--s-3) var(--s-1)}
.sidebar .spacer{flex:1}
/* Счётчик у «Проверки» — единственный элемент меню с цветом маркера */
.sidebar .count{margin-left:auto;background:var(--marker-soft);color:var(--marker-ink);border-radius:99px;font-family:var(--font-mono);font-size:var(--t-label);font-weight:500;padding:1px var(--s-2)}
.sidebar a.on .count,.sidebar button.on .count{background:var(--marker);color:#171A21}
/* Раздел плана, который ещё не построен — виден, но не ведёт в пустоту */
.sidebar .soon{opacity:.4;cursor:default;pointer-events:none}

/* Шапка — бумага, как и левое меню: белое на платформе значит «содержимое», а
   шапка содержимого не несёт. На занятии это и вовсе обязательно — материал
   урока там единственная белая область, и белая шапка спорила бы с ним.
   Отделяет её линия снизу, а не своя подложка. */
.topbar{background:var(--paper);border-bottom:1px solid var(--line);height:56px;display:flex;align-items:center;gap:var(--s-3);padding:0 var(--s-4);position:sticky;top:0;z-index:60}
/* Внутри раскладки с меню лого и навигация живут в меню, а не в топбаре */
.app-main .topbar{justify-content:flex-end}
/* Кроме телефона: там меню спрятано, и знак остаётся единственным, по чему
   видно, где ты находишься (кабинет ученика, хендофф v2, Р-3). */
@media(min-width:641px){.app-main .topbar .brand{display:none}}
/* Лицо в шапке — вся остальная опознавательная часть хрома кабинета */
.top-ava .stu-ava{width:34px;height:34px;font-size:12px;
  background:linear-gradient(135deg,var(--ink-2),var(--ink));color:var(--paper)}

/* На телефоне меню ложится полосой поверх страницы, а шапка встаёт над ним:
   «Выйти» и переключение темы — про вход, а не про раздел, и стоять они должны
   выше навигации, а не между ней и содержимым. Порядок задаём флексом: сама
   шапка лежит внутри .app-main, и без display:contents её из этой обёртки не
   вынуть, не трогая разметку девяти страниц. */
@media(max-width:860px){
  .app{grid-template-columns:minmax(0,1fr);display:flex;flex-direction:column}
  .app-main{display:contents}
  .app-main>*{order:3}
  .app-main>.topbar{order:1}
  .app>.sidebar{order:2}
  /* Полоса меню прокручивается вбок, но не вниз: overflow-x:auto делает
     прокручиваемой и вертикаль, и полосу можно было стянуть на несколько
     пикселей — под ней открывалась щель до всего, что ниже. */
  .sidebar{position:static;height:auto;flex-direction:row;align-items:center;gap:var(--s-1);
    overflow-x:auto;overflow-y:hidden;padding:var(--s-3) var(--s-3);border-right:none;border-bottom:1px solid var(--line)}
  .sidebar .brand,.sidebar .sep,.sidebar .spacer,.sidebar .soon{display:none}
  .sidebar a,.sidebar button{width:auto;white-space:nowrap;padding:var(--s-2) var(--s-3);flex-shrink:0}
}
.brand{display:flex;align-items:center;gap:var(--s-2);font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);letter-spacing:-.01em;flex-shrink:0;color:var(--ink);text-decoration:none}
.brand svg{flex-shrink:0;display:block}
/* контур знака берёт цвет текста — корректно инвертируется в тёмном хроме */
.brand svg .lsn-stroke{stroke:var(--ink)}
.brand svg .lsn-pad{fill:var(--surface);stroke:var(--surface)}
/* Возврат и название открытого — вместо прежних вкладок навигации */
.top-back{display:inline-flex;align-items:center;text-decoration:none;color:var(--muted);
  font-family:var(--font-head);font-weight:600;font-size:var(--t-base);white-space:nowrap;
  padding:var(--s-1) var(--s-3);border-radius:8px;margin-left:var(--s-1)}
.top-back:hover{color:var(--ink);background:var(--surface-2)}
.top-step{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--muted);white-space:nowrap}
.top-sep{color:var(--line-2);font-size:12px}
.top-title{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;margin-left:var(--s-1)}
/* Ряд действий сжимается, а не уезжает за край: на занятии в нём набирается
   больше всего — присутствие, поиск слова, смена материала, выход. Место отдаёт
   поиск: он всегда под рукой, а плашка присутствия отвечает на вопрос, который
   на занятии важнее, и ширину держит до последнего. */
.top-actions{display:flex;gap:var(--s-2);align-items:center;min-width:0;margin-left:auto}
.ws-host{display:flex;min-width:0}
.top-actions .presence{flex-shrink:0}
.top-user{font-size:var(--t-sm);color:var(--muted);white-space:nowrap}
/* На странице без левого меню (занятие, конструктор) шапка несёт сразу и путь,
   и все действия. Своё имя оттуда убираем: кто вошёл — видно по кнопке «Выйти»,
   а место нужнее присутствию и поиску слова. */
body>.topbar .top-user{display:none}

.btn{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-family:var(--font-head);font-weight:600;font-size:var(--t-base);cursor:pointer;display:inline-flex;align-items:center;gap:var(--s-2);transition:border-color .15s,background .15s;white-space:nowrap;text-decoration:none;color:var(--ink)}
.btn:hover{border-color:var(--line-strong);background:var(--surface-2)}
.btn.primary{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.btn.primary:hover{background:#000;border-color:#000}
html[data-chrome="dark"] .btn.primary:hover{background:#fff;border-color:#fff}
.btn.danger{color:var(--err);border-color:var(--line-2)}
.btn.danger:hover{border-color:var(--err);background:var(--err-bg)}
/* ---------- Кнопка с ИИ ----------
   Маркер здесь не спорит с правилом «жёлтый только для заметок»: на лендинге
   тем же маркером помечены ровно ИИ-места (плашка «ИИ» с пульсирующей точкой),
   и внутри продукта знак должен быть тот же, что в обещании. Иначе главная
   функция платформы выглядит как пятая кнопка в ряду одинаковых серых.

   Заливка сплошная, а не бледная подложка маркера. Подложка красила кнопку в
   акцентный цвет, но делала её тише соседей: бледно-жёлтое на почти белой
   бумаге отличается от фона слабее, чем чёрная primary или белая с рамкой, —
   выходило «и выделяется, и блёклое». Сплошной маркер даёт кнопке тот же вес,
   что у чёрной, но другим тоном, поэтому они не спорят за одну роль.

   Чернила текста заданы числом, а не переменной: маркер светлый в обеих темах
   хрома, а --ink в тёмной становится светлым и на жёлтом пропал бы. Так же
   набран счётчик в выбранном пункте меню.

   Правило одно на все экраны: одна такая кнопка на страницу, шире соседних на
   ступень отступа, с искрой слева, и называет она результат («Собрать урок с
   ИИ»), а не средство («ИИ»). Рядом с ней чёрной primary-кнопки не ставим —
   два тяжёлых пятна в одном ряду гасят друг друга. */
.btn.ai{background:var(--marker);border-color:var(--marker);color:#171A21;
  padding-left:var(--s-4);padding-right:var(--s-4)}
.btn.ai:hover{background:var(--marker);border-color:var(--marker);filter:brightness(.93)}
/* Вторая дверь к тому же: перенос учебника делает та же модель, просто материал
   свой, а не придуманный. Без знака он читался как техническое «перенести
   файл» — обычная кнопка рядом с волшебной, — хотя на лендинге именно с него
   начинается рассказ про ИИ. Знак тот же, вес меньше: обычная кнопка с искрой
   маркером. Так на экране видно семью из двух входов и порядок внутри неё. */
.btn.ai-soft .spark{color:var(--marker)}
.btn.ai-soft:hover{border-color:var(--marker)}
.btn .spark{width:15px;height:15px;flex-shrink:0;display:block}
/* Искра в заголовке окна: та же примета и тот же вес, что у кнопки, которая его
   открыла, — сплошная у сборки с нуля, приглушённая у переноса учебника. */
.head-ai{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;flex-shrink:0;
  border-radius:8px;background:var(--marker);color:#171A21;margin-right:var(--s-2);vertical-align:-6px}
.head-ai.soft{background:var(--marker-soft);color:var(--marker)}
.head-ai svg{width:16px;height:16px;display:block}
.btn.soft{background:var(--accent-soft);border-color:transparent;color:var(--accent-soft-ink)}
.btn.soft:hover{filter:brightness(.96)}
.btn:disabled{opacity:.45;cursor:default}
.btn.sm{padding:6px var(--s-3);font-size:var(--t-sm)}
.icon-btn{border:1px solid transparent;background:transparent;color:var(--muted);width:28px;height:28px;border-radius:7px;cursor:pointer;font-size:var(--t-base);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.icon-btn:hover{background:var(--surface-2);color:var(--ink);border-color:var(--line)}

.workspace{display:grid;grid-template-columns:236px minmax(0,1fr);gap:var(--s-5);max-width:1180px;margin:0 auto;padding:var(--s-5) var(--s-5) 120px}
.canvas{min-width:0}

.rail{position:sticky;top:78px;align-self:start;max-height:calc(100vh - 100px);display:flex;flex-direction:column}
.rail-head{display:flex;align-items:center;justify-content:space-between;font-size:var(--t-label);text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:700;padding:0 var(--s-1) var(--s-2)}
.rail-list{overflow-y:auto;overflow-x:hidden;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:3px;padding-right:2px}
.rail-item{display:flex;align-items:center;gap:var(--s-2);height:34px;padding:0 var(--s-2);border-radius:8px;cursor:pointer;font-size:var(--t-base);color:var(--muted);border:1px solid transparent;position:relative;flex-shrink:0}
.rail-item:hover{background:var(--surface);border-color:var(--line);color:var(--ink)}
.rail-item.active{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.rail-item.active .rail-num{color:var(--paper);opacity:.6}
/* Иконки блоков рисуются currentColor, поэтому в активном пункте и в тёмной
   теме они перекрашиваются сами — отдельных правил для них больше не нужно. */
.rail-item.is-note{color:var(--note-ink)}
/* Выбранный пункт всегда читается по-своему: правило .is-note стоит после
   .active и перекрывало его цвет, из-за чего выбранная заметка в рельсе была
   маркерной по чернилам — 1.34 в тёмном хроме, 2.57 в светлом. */
.rail-item.active.is-note{color:var(--paper)}
.rail-item.dragging{opacity:.4}
.rail-item.drop-before::before{content:'';position:absolute;left:0;right:0;top:-3px;height:2px;background:var(--accent);border-radius:2px}
.rail-num{width:20px;flex-shrink:0;font-family:var(--font-mono);font-weight:600;font-size:var(--t-label);color:var(--muted);text-align:right}
.rail-ic{width:22px;height:22px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.rail-ic svg{width:18px;height:18px}
.rail-item.is-note .rail-ic svg [stroke="#171A21"]{stroke:var(--marker)}
.rail-item.is-note .rail-ic svg [fill="#171A21"]{fill:var(--marker)}
.rail-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.rail-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;background:transparent}
.rail-dot.ok{background:var(--ok)}
.rail-dot.err{background:var(--err)}
.rail-dot.todo{background:transparent;border:1.5px dashed var(--line-strong)}
.rail-add{flex-shrink:0;margin-top:var(--s-2);border:1px dashed var(--line-strong);background:transparent;color:var(--muted);border-radius:var(--radius-sm);padding:var(--s-2);font-family:var(--font-head);font-weight:600;font-size:var(--t-base);cursor:pointer;width:100%}
.rail-add:hover{border-color:var(--accent);color:var(--accent)}

.cover{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;margin-bottom:var(--s-3)}
.cover-img{width:100%;height:200px;object-fit:cover;display:block;background:var(--surface-2)}
.cover-body{padding:var(--pad)}
.cover-title{font-family:var(--font-head);font-weight:700;font-size:26px;letter-spacing:-.015em;line-height:1.2}
.cover-sub{color:var(--muted);margin-top:var(--s-2);font-size:15px}
.cover-meta{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-3)}
.pill{background:var(--surface-2);border-radius:99px;padding:6px var(--s-3);font-size:var(--t-sm);color:var(--muted)}
.pill b{color:var(--ink);font-weight:600}
.cover-edit input,.cover-edit textarea{width:100%;border:1px solid transparent;border-radius:var(--radius-sm);padding:var(--s-2) var(--s-2);font-size:var(--t-md);background:transparent;color:var(--ink);transition:background .15s}
.cover-edit input:hover,.cover-edit textarea:hover{background:var(--surface-2)}
.cover-edit input:focus,.cover-edit textarea:focus{outline:none;background:var(--surface-2);border-color:var(--line)}
.cover-edit .t{font-family:var(--font-head);font-weight:700;font-size:24px;letter-spacing:-.015em}
.cover-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-1);margin-top:var(--s-2)}
.cover-grid input{font-size:var(--t-base)}

.block{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);margin-bottom:2px;scroll-margin-top:82px;transition:border-color .15s,box-shadow .15s}
.block:hover{border-color:var(--line-strong)}
.block.focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.block.flash{animation:flash 1.4s ease-out}
.block.is-note{background:var(--note-bg);border-color:#EBD9A0}
@keyframes flash{0%{box-shadow:0 0 0 4px var(--accent-soft)}100%{box-shadow:0 0 0 0 transparent}}
.bhead{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-3) var(--pad);cursor:pointer;user-select:none}
.bnum{font-family:var(--font-mono);font-weight:500;font-size:var(--t-label);letter-spacing:.08em;color:var(--muted);background:var(--surface-2);border-radius:6px;padding:3px var(--s-2);flex-shrink:0;min-width:30px;text-align:center}
.bnum svg{width:16px;height:16px;display:block;margin:0 auto}
.is-note .bnum{background:#F1E4B5;color:var(--note-ink)}
/* Название блока — его содержимое, а не имя типа: карточка должна называть то
   же, что стоит о ней в рельсе, иначе урок читается на двух языках. */
.bname{font-family:var(--font-head);font-weight:600;font-size:var(--t-md);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Тип — подписью справа: он нужен, когда пробегаешь урок глазами в поисках
   «где тут тест», и не нужен в тот момент, когда блок правят. */
.btype{color:var(--muted);font-size:var(--t-sm);flex-shrink:0}
.block.open .btype{opacity:0}
/* На телефоне имя типа уходит: в шапке блока он спорит за ширину со значками
   правки, и они вылезали за край листа. Что это за блок, говорит значок слева. */
@media(max-width:640px){.block .btype{display:none}}
.btools{display:flex;gap:2px;margin-left:var(--s-3);opacity:0;transition:opacity .15s}
.block:hover .btools,.block.focus .btools{opacity:1}
.bbody{padding:0 var(--pad) var(--pad)}
.chev{color:var(--muted);font-size:var(--t-label);transition:transform .2s;flex-shrink:0;width:14px}
.block.open .chev{transform:rotate(90deg)}
/* Тип урока в обложке: подпись, переключатель и «Адаптировать» одним рядом,
   пояснение — строкой под ним во всю ширину. */
.mode-row{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-2) var(--s-3);margin-top:var(--s-3);
  padding-top:var(--s-3);border-top:1px solid var(--line)}
.mode-row .seg{margin-bottom:0}
.mode-row .mode-lbl{font-family:var(--font-head);font-weight:600;font-size:var(--t-sm);color:var(--muted)}
.mode-row .hint{flex-basis:100%;margin:0}
.seg{display:inline-flex;background:var(--surface-2);border-radius:8px;padding:2px;margin-bottom:var(--s-3)}
.seg button{border:none;background:transparent;padding:6px var(--s-3);border-radius:6px;font-size:var(--t-sm);font-weight:600;font-family:var(--font-head);color:var(--muted);cursor:pointer}
.seg button.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.08)}

.insert{height:22px;display:flex;align-items:center;justify-content:center;position:relative;opacity:0;transition:opacity .15s}
.insert:hover{opacity:1}
.insert::before{content:'';position:absolute;left:0;right:0;height:1px;background:var(--accent);opacity:.35}
.insert button{position:relative;border:1px solid var(--line);background:var(--surface);color:var(--accent);width:24px;height:24px;border-radius:50%;cursor:pointer;font-size:var(--t-md);line-height:1;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow)}

.field{margin-bottom:var(--s-3)}
.field label{display:block;font-size:11.5px;color:var(--muted);margin-bottom:var(--s-1);font-weight:600}
.field input,.field textarea,.field select{width:100%;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-md);background:var(--surface-2);color:var(--ink)}
.field input:focus,.field textarea:focus,.field select:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.field textarea{resize:vertical;line-height:1.6}
.md-bar{display:flex;gap:var(--s-1);margin-bottom:var(--s-1)}
.md-btn{border:1px solid var(--line-2);background:var(--surface);color:var(--ink);border-radius:6px;min-width:30px;height:28px;cursor:pointer;font-size:var(--t-md);line-height:1;display:inline-flex;align-items:center;justify-content:center}
.md-btn:hover{border-color:var(--marker)}
.hint{font-size:11.5px;color:var(--muted);margin-top:var(--s-1)}
.ed-row{display:flex;gap:var(--s-2);margin-bottom:var(--s-2);align-items:center}
.ed-row input,.ed-row select{flex:1;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface-2)}
.ed-row input:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.ed-row select{flex:0 0 78px}
.ed-row .grip{color:var(--muted);font-size:12px;width:16px;text-align:center;flex-shrink:0}

/* ---------- Единая строка списка (хендофф v2) ----------
   Одна анатомия вместо четырёх: .day-row, .attn-row, .hw и .stu-row делали одно
   и то же — значок, текст, статус, действие, — но различались историей
   появления, а не смыслом. Четыре слота, разница между вариантами только в
   содержимом:

     [якорь 44px] аватар 40 · время mono · значок
     [основное 1fr] имя 14 Onest 600 + подпись 12.5 Manrope muted
     [статус auto] .tag
     [действие auto] .btn.sm

   Строка живёт на бумаге, а не на листе: карточка белая, список — фон
   страницы, иначе лента из десяти строк читается как десять карточек. */
/* Колонка имени не сжимается до нуля. У «auto»-колонок предел — их содержимое
   целиком, а у minmax(0,1fr) низ нулевой: колонка статуса и кнопок забирала всю
   ширину, и «Petr» превращался в «Pet…» рядом с двумя кнопками во всю строку.
   Нижняя граница переворачивает правило — тесно становится тому, что справа. */
.row{display:grid;grid-template-columns:44px minmax(6rem,1fr) auto auto;align-items:center;
  gap:var(--s-3);background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:10px 14px;margin-bottom:var(--s-2);text-decoration:none;color:var(--ink)}
.row:hover{border-color:var(--line-2)}
/* Строка без якоря — когда ни лица, ни времени нет */
.row.bare{grid-template-columns:minmax(6rem,1fr) auto auto}
/* Действие — сама строка: когда вести из неё некуда, кроме одного места,
   кнопка рядом со статусом только отнимает ширину у названия */
.row.act{cursor:pointer}
.row.act:hover{border-color:var(--line-2);background:var(--surface)}
/* Якорь: любой из трёх видов встаёт в одну колонку и центрируется */
.row .r-anchor{display:flex;align-items:center;justify-content:center;min-width:0}
.row .r-time{font-family:var(--font-mono);font-weight:600;font-size:var(--t-base);color:var(--ink-2);text-align:center}
.row .r-main{min-width:0}
.row .r-title{font-family:var(--font-head);font-weight:600;font-size:var(--t-md);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .r-sub{font-size:var(--t-sm);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Подпись, которую нельзя обрывать: «занятия кончились · срок кончился» — это и
   есть повод, по которому строка попала в список, а не пояснение к нему. */
.row .r-sub.wrap{white-space:normal;overflow:visible;text-overflow:clip}
/* Подпись может идти в строку с названием — «Weather & Small Talk · сегодня» */
.row .r-title .r-sub{display:inline;font-weight:400}
/* Кнопки переносятся, а не вылезают за край: в узкой колонке пара действий
   («Провести» + «Не состоялось») шире, чем вся колонка, и строка уводила
   страницу в горизонтальную прокрутку. */
.row .r-side{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;justify-content:flex-end}
.row.off{opacity:.55}
.row.off:hover{opacity:1}
/* Действие проявляется по наведению — кроме основного, оно видно всегда.
   На устройствах без мыши показываем сразу: наводить там нечем. */
.row .r-act{transition:opacity .12s}
@media (hover:hover){
  .row .r-act:not(.always){opacity:0}
  .row:hover .r-act,.row:focus-within .r-act{opacity:1}
}

.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--pad);margin-bottom:var(--s-3)}
.ex-head{display:flex;align-items:flex-start;gap:var(--s-3);margin-bottom:var(--s-3)}
.ex-badge{background:var(--surface-2);color:var(--muted);font-family:var(--font-mono);font-weight:500;font-size:11px;letter-spacing:.06em;border-radius:7px;padding:3px var(--s-2);flex-shrink:0;margin-top:1px}
.ex-badge svg{width:16px;height:16px;display:block}
.ex-instr{font-family:var(--font-head);font-weight:600;font-size:15px;line-height:1.45}
/* ---------- Образец задания ----------
   В учебнике первый пункт сделан за ученика и набран иначе — курсивом, другим
   цветом. Здесь так же: тихая полоса между инструкцией и заданием, чтобы
   образец не читался как ещё одно упражнение, которое надо выполнить. */
.ex-example{display:flex;gap:var(--s-3);align-items:flex-start;margin:0 0 var(--s-3);padding:var(--s-2) var(--s-3);
  border-left:2px solid var(--line-2);background:var(--surface-2);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.ex-example .exe-label{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--muted);padding-top:3px;flex-shrink:0}
.ex-example .exe-text{font-size:var(--t-md);line-height:1.6;color:var(--ink-2);font-style:italic}

.block-img{width:100%;border-radius:var(--radius-sm);display:block;margin-bottom:var(--s-3);max-height:340px;object-fit:cover}
.block-caption{font-size:var(--t-sm);color:var(--muted);text-align:center;margin-bottom:var(--s-3)}
.block-text{font-size:15.5px;line-height:1.75}
.block-text p{margin-bottom:var(--s-3)}
.block-text p:last-child{margin-bottom:0}
.block-title{font-family:var(--font-head);font-weight:700;font-size:var(--t-lesson-h);margin-bottom:var(--s-3)}
.block-text .block-h{font-family:var(--font-head);font-weight:700;font-size:15.5px;margin:var(--s-3) 0 var(--s-1)}
.block-text .block-h:first-child{margin-top:0}
/* Списки задания: пункты, варианты, фразы под одним заголовком. Маркер и номер
   вынесены на поля, чтобы текст пунктов держал общую левую границу с абзацами. */
.block-list{margin:0 0 var(--s-3);padding-left:1.35em}
.block-list:last-child{margin-bottom:0}
.block-list li{margin-bottom:var(--s-1)}
.block-list li:last-child{margin-bottom:0}
.block-list li::marker{color:var(--muted)}
/* Вопрос задания набран как текст, а не одной строкой: в него тоже попадают
   списки и переносы — «Answer the questions» с тремя пунктами это обычный вид. */
.ex-question{font-family:var(--font-head);font-weight:600;font-size:15px;line-height:1.6;margin-bottom:var(--s-3)}
.ex-question p{margin-bottom:var(--s-2)}
.ex-question p:last-child{margin-bottom:0}
.ex-question .block-list{margin-bottom:var(--s-2);font-weight:500}

/* ---------- Диалог ----------
   Реплики в учебнике набраны как «1 A: … / B: …». Номер обмена платформа ставит
   сама на карточке задания, а кто говорит — показывает вёрстка, а не буква в
   тексте: у каждого собеседника своя черта слева, вторая реплика с отступом.
   Между обменами воздух, поэтому пары читаются парами, а не сплошной лентой. */
.dlg{font-size:15.5px}
.dlg-turn{position:relative;padding:2px 0 2px var(--s-3);margin-bottom:var(--s-1);line-height:2.2;
  border-left:2px solid var(--line-2)}
.dlg-turn.s1{margin-left:var(--s-5);border-left-color:var(--accent)}
.dlg-turn.s2{margin-left:52px;border-left-color:var(--marker)}
.dlg-turn.s3{margin-left:78px;border-left-color:var(--ok)}
.dlg-turn.start{margin-top:var(--s-4)}
.dlg-turn.start:first-child{margin-top:0}
.dlg-who{font-family:var(--font-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);display:block;line-height:1.6;margin-bottom:-2px}
.gap-text{font-size:15.5px;line-height:2.4}

/* ---------- «Слово и картинка» ----------
   Разворот учебника: слева фразы с местом под номер, справа пронумерованные
   фотографии. Фраза выбирается кликом, следом кликают по фотографии — так же,
   как в «По группам». На узком экране колонки встают друг под друга. */
.imgm{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:var(--s-4);align-items:start}
.imgm-list{display:flex;flex-direction:column;gap:var(--s-1)}
.imgm-row{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-2) var(--s-3);border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface);cursor:pointer;font-size:14.5px;transition:border-color .15s;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.imgm-row:hover{border-color:var(--ink-2)}
.imgm-row.selected{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-soft-ink)}
.imgm-row.ok{border-color:var(--ok);background:var(--ok-bg)}
.imgm-row.err{border-color:var(--err);background:var(--err-bg)}
.imgm-slot{flex-shrink:0;width:30px;height:26px;display:inline-flex;align-items:center;justify-content:center;
  border:1.5px dashed var(--line-strong);border-radius:6px;background:var(--surface-2);
  font-family:var(--font-mono);font-size:11.5px;font-weight:500}
.imgm-row.selected .imgm-slot,.imgm-row.ok .imgm-slot,.imgm-row.err .imgm-slot{border-style:solid}
.imgm-text{min-width:0}
.imgm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:var(--s-2)}
.imgm-photo{position:relative;padding:0;border:1px solid var(--line);border-radius:var(--radius-sm);
  overflow:hidden;background:var(--surface-2);cursor:pointer;aspect-ratio:1;transition:border-color .15s}
.imgm-photo:hover{border-color:var(--accent)}
.imgm-photo.used{opacity:.4}
.imgm-photo img{width:100%;height:100%;object-fit:cover;display:block}
.imgm-n{position:absolute;left:4px;top:4px;background:var(--ink);color:var(--paper);
  font-family:var(--font-mono);font-size:10px;font-weight:500;border-radius:5px;padding:2px var(--s-1)}
@media(max-width:720px){.imgm{grid-template-columns:1fr}}
/* Строка редактора: миниатюра слева, фраза и ссылка справа */
.imgm-ed{display:flex;align-items:flex-start;gap:var(--s-2);margin-bottom:var(--s-2)}
.imgm-ed-pic{width:56px;height:56px;flex-shrink:0;padding:0;overflow:hidden;cursor:pointer;
  border:1.5px dashed var(--line-strong);border-radius:var(--radius-sm);background:var(--surface-2);
  color:var(--muted);font-size:var(--t-label);font-family:var(--font-head)}
.imgm-ed-pic:hover{border-color:var(--accent);color:var(--ink)}
.imgm-ed-pic img{width:100%;height:100%;object-fit:cover;display:block}
audio{width:100%}
/* Подпись под плеером на занятии: звук общий, и об этом надо сказать — иначе
   неожиданно, что нажатие у себя запускает дорожку у второго. */
.aud-sync{font-family:var(--font-mono);font-size:var(--t-label);letter-spacing:.04em;color:var(--muted);margin-top:6px}
.aud-sync.warn{font-family:var(--font-body);font-size:12px;letter-spacing:0;color:var(--err)}
.aud-sync.blocked{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-family:var(--font-body);font-size:12px;letter-spacing:0}
.embed{position:relative;padding-top:56.25%;border-radius:var(--radius-sm);overflow:hidden;background:var(--surface-2);margin-bottom:var(--s-3)}
.embed iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.callout{border-left:3px solid var(--accent);background:var(--accent-soft);border-radius:0 var(--radius-sm) var(--radius-sm) 0;padding:var(--s-3) var(--s-4)}
.callout.tip{border-color:var(--ok);background:var(--ok-bg)}
.callout.warn{border-color:var(--err);background:var(--err-bg)}
.callout .ct{font-family:var(--font-head);font-weight:700;font-size:14.5px;margin-bottom:var(--s-1)}
.callout .block-text{font-size:14.5px}

/* ---------- Заголовок части урока ----------
   В учебнике части отбиты цветной полосой: SPEAKING, VOCABULARY, GRAMMAR.
   Здесь то же самое чертой акцента темы урока — часть выглядит как в печатном
   оригинале, и видно, где кончилась одна и началась другая. */
.sec-head{display:flex;align-items:baseline;gap:var(--s-3);margin:var(--s-6) 0 var(--s-4);padding-bottom:var(--s-2);
  border-bottom:2px solid var(--accent)}
.sec-head .sh-title{font-family:var(--font-head);font-weight:800;font-size:var(--t-lesson-h);
  letter-spacing:-.01em;line-height:1.2}
.sec-head .sh-kicker{margin-left:auto;font-family:var(--font-mono);font-size:11px;
  letter-spacing:.1em;color:var(--muted);white-space:nowrap;flex-shrink:0}

/* В рельсе структуры заголовок набран заголовком: по ней читается устройство урока */
.rail-item.is-head{margin-top:var(--s-2);padding-top:var(--s-2);height:auto;border-radius:0;
  border-top:1px solid var(--line);color:var(--ink);
  font-family:var(--font-head);font-weight:700;font-size:12px;letter-spacing:.04em}
.rail-item.is-head:hover{background:none;border-color:var(--line);color:var(--ink)}
.rail-item.is-head.active{background:none;color:var(--accent)}
.rail-item.is-head .rail-dot{display:none}

/* ---------- Таблица: грамматика, парадигмы, фразы ----------
   В учебнике это плашка с сеткой, и на платформе она должна читаться так же
   тихо: тонкие линии, шапка на подложке, первый столбец — заголовочным шрифтом
   (в учебниках слева всегда метка: форма, часть фреймворка, инфинитив).
   Цвета берёт из темы урока, поэтому таблица выглядит частью материала. */
/* Регистр надписи оставляем как написал преподаватель: в учебниках метки плашек
   набраны капсом («THE FRAMEWORK»), а заголовки грамматических таблиц — обычным
   («Past simple»). Переводить всё в капс значит спорить с источником. */
/* .eyebrow ниже в файле переводит текст в капс — здесь перебиваем обоими классами */
.eyebrow.tbl-label{margin-bottom:var(--s-2);text-transform:none;letter-spacing:.08em}
.tbl-wrap{overflow-x:auto;margin-bottom:2px}
.tbl{border-collapse:collapse;width:100%;font-size:14.5px;line-height:1.5}
.tbl th,.tbl td{border:1px solid var(--line);padding:var(--s-2) var(--s-3);text-align:left;vertical-align:top}
.tbl th{background:var(--surface-2);font-family:var(--font-head);font-weight:600;font-size:var(--t-base)}
.tbl td:first-child{font-family:var(--font-head);font-weight:600}
/* Продолжение строки — метки нет, рамку между ними убираем: читается как список */
.tbl td.tbl-cont{border-top-color:transparent}
.tbl td.tbl-cont:first-child{border-right-color:transparent}
.tbl .tbl-gap{width:96px;margin:0}

.margin-slot{position:relative}
.sticky{background:var(--note-bg);border:1px solid var(--note-line);border-radius:10px;padding:var(--s-3) var(--s-4);box-shadow:2px 3px 0 rgba(138,106,0,.08);position:relative}
.sticky::before{content:'';position:absolute;top:-6px;left:20px;width:34px;height:12px;background:var(--note-tape);border-radius:2px;transform:rotate(-2deg)}
.sticky .sw{font-family:'Caveat',cursive;font-size:20px;font-weight:600;color:var(--note-ink);line-height:1.3}
.sticky .sw b{font-family:var(--font-head);font-size:15px;font-weight:700;display:block;margin-bottom:2px}
.sticky .stag{position:absolute;top:9px;right:11px;font-size:var(--t-label);font-weight:700;font-family:var(--font-head);color:var(--note-ink);opacity:.55;text-transform:uppercase;letter-spacing:.05em}
.class-canvas{position:relative}
.sticky.aside{width:230px}

/* ---------- Лист урока (хендофф v2) ----------
   Тема красит лист, а не страницу. Раньше applyTheme писал переменные в body,
   кремовый заливал весь вьюпорт до краёв экрана, платформа исчезала — урок
   читался как отдельный сайт, и темами поэтому не пользовались. Теперь урок —
   оформленный документ на платформенном столе: фон страницы, топбар и рельса
   всегда платформенные, а лист виден тенью.
   Шрифт и кегль объявлены здесь: body берёт их у платформы, и лист должен
   назвать свои сам, иначе переменные темы никто не читает. */
.lesson-sheet{background:var(--bg);color:var(--ink);
  font-family:var(--font-body);font-size:var(--fs);
  border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:var(--pad)}
/* В тёмном хроме лист виден кантом, а не тенью: тень платформы там чёрная, и на
   тёмном столе её нет вовсе — а если и урок тёмный, лист сливался со страницей
   (1.05 против 17.9 в светлом хроме) и «документ на столе» переставал читаться.
   Кант — снаружи рамки: рамка принадлежит уроку, кант — столу под ним. */
html[data-chrome="dark"] .lesson-sheet{box-shadow:0 0 0 1px rgba(255,255,255,.09),var(--shadow)}
/* Заметки на полях лежат снаружи листа — они и в тетради на полях. Считаются
   они от колонки блоков, которая уже листа на его поле, поэтому вылет
   складывается из прежних 26px зазора и этого поля. Ширина листа при этом
   остаётся прежней шириной колонки — иначе занятие с заметками перестало бы
   помещаться на экранах чуть шире 1300px. */
@media(min-width:1300px){
  .lesson-sheet{max-width:700px}
  .sticky.aside{position:absolute;right:calc(-256px - var(--pad));width:230px;margin:0;
    transform:rotate(-1.5deg);transition:top .2s ease}
}
@media(max-width:1299px){.sticky.aside{margin:0 0 var(--s-3);transform:rotate(-.5deg)}}
.sticky .sdel{position:absolute;top:-9px;right:-9px;width:22px;height:22px;border-radius:50%;border:1px solid var(--note-line);background:var(--note-bg);color:var(--note-ink);font-size:11px;cursor:pointer;display:none;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,.12)}
.sticky:hover .sdel{display:flex}
/* Выключатель «в словарь» на стикере. Строкой внизу, а не значком в углу:
   значок пришлось бы разгадывать, а тут прямо написано, куда уйдёт заметка.
   Выключенный тихий, включённый набран чернилами заметки — разница видна, но
   ни один не спорит с самим словом наверху. */
.sticky .svoc{display:block;width:100%;margin-top:var(--s-2);padding:3px 0;border:none;background:none;
  font-family:var(--font-head);font-weight:600;font-size:var(--t-label);letter-spacing:.04em;
  text-transform:uppercase;text-align:left;cursor:pointer;color:var(--note-ink);opacity:.45}
.sticky .svoc:hover{opacity:.8}
.sticky .svoc.on{opacity:.85}
.sticky .sw[contenteditable]{outline:none;min-width:60px;cursor:text}
.sticky .sw[contenteditable]:empty::before{content:'фраза – перевод';opacity:.45}
.note-hint{font-size:var(--t-label);color:var(--note-ink);opacity:.6;margin-top:var(--s-1);font-family:var(--font-body)}
/* Кнопка «заметка» стоит на полях справа — там же, где появится сама заметка,
   и на расстоянии от блока: она не часть блока. На узких экранах поля исчезают,
   поэтому там она возвращается над блоком. */
.note-insert{height:0;display:flex;align-items:center;justify-content:flex-end;position:relative;z-index:2}
/* Кнопка видна всегда. По наведению её было не найти: на занятии заметку кидают
   на ходу, и искать невидимую кнопку мышью посреди урока некогда. Приглушена,
   чтобы не спорить с материалом, и наливается цветом под курсором. */
.note-insert button{border:1px dashed var(--note-line);background:var(--note-bg);color:var(--note-ink);border-radius:99px;padding:3px var(--s-3);font-size:11.5px;font-weight:700;font-family:var(--font-head);cursor:pointer;opacity:.5;transition:opacity .15s}
.note-insert:hover button,.note-insert button:focus-visible{opacity:1}
@media(min-width:1300px){
  .note-insert{margin:0}
  .note-insert button{position:absolute;left:calc(100% + 26px + var(--pad));white-space:nowrap}
  /* полоса наведения на полях, чтобы кнопку было где поймать */
  .note-insert::before{content:'';position:absolute;left:100%;width:260px;height:44px;top:-22px}
}
@media(max-width:1299px){
  .note-insert{height:22px;margin-bottom:var(--s-1)}
  .note-insert button{opacity:.75}
}

.pool{border:1.5px dashed var(--line-strong);border-radius:var(--radius-sm);padding:var(--s-3);display:flex;flex-wrap:wrap;gap:var(--s-2);min-height:46px;margin-bottom:var(--s-3);background:var(--surface-2)}
/* font/color наследуем явно: плашки-слова ставятся тегом span, а выбор дней в
   расписании ученика — кнопкой, и без этого она бы взяла шрифт браузера */
.chip{font:inherit;font-weight:600;color:inherit;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:6px var(--s-3);cursor:pointer;user-select:none}
.chip:hover{border-color:var(--accent)}
.chip.selected{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-soft-ink)}
.chip.used{opacity:.22;pointer-events:none}
/* Плашка после проверки — используется «По группам», где верным/неверным помечена
   не рамка вокруг слота, а сама переносимая плашка */
.chip.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.chip.err{border-color:var(--err);background:var(--err-bg);color:var(--err)}

/* Плашки выбора в панели профиля — цели ученика и дни регулярного расписания.
   Мельче плашек-слов в заданиях: их много, а панель узкая.
   .add — вариант, который ещё не выбран: пунктир и приглушённый цвет, чтобы
   список предложенного не спорил за внимание с уже выбранным.
   .flat — то же, но для чтения: без рамки и без указателя мыши. */
.chip-row{display:flex;flex-wrap:wrap;gap:var(--s-1)}
.chip.sm{padding:5px 10px;font-size:var(--t-sm);border-radius:7px}
.chip.add{border-style:dashed;color:var(--muted);font-weight:500}
.chip.add:hover{border-style:solid;color:var(--ink)}
.chip.flat{background:var(--surface-2);border-color:transparent;cursor:default;font-weight:500}
.chip.flat:hover{border-color:transparent}
.chip .x{color:var(--muted);margin-left:var(--s-1)}
.chip:hover .x{color:inherit}

/* Отчёт временного переноса из tutorapp — таблица моноширинным шрифтом длиннее
   панели настроек, поэтому скроллится сама и не тянет за собой всю страницу. */
.tutorapp-out{margin-top:var(--s-3);padding:var(--s-3) var(--s-3);background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:11.5px;line-height:1.6;
  white-space:pre;overflow-x:auto;max-height:320px;overflow-y:auto}
.slot{display:inline-flex;align-items:center;justify-content:center;min-width:46px;height:36px;border:1.5px dashed var(--line-strong);border-radius:8px;background:var(--surface-2);cursor:pointer;font-weight:600;padding:0 var(--s-2);vertical-align:middle;margin:0 3px}
.slot.filled{border-style:solid;border-color:var(--line);background:var(--surface)}
.slot.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.slot.err{border-color:var(--err);background:var(--err-bg);color:var(--err)}
.letter-slot{width:40px;height:40px;font-size:17px;min-width:0}
.type-gap{display:inline-block;width:112px;border:none;border-bottom:2px solid var(--line-strong);background:transparent;font-weight:600;font-size:15px;text-align:center;padding:2px var(--s-1);margin:0 3px}
.type-gap:focus{outline:none;border-bottom-color:var(--accent)}
.type-gap.ok{border-bottom-color:var(--ok);color:var(--ok)}
.type-gap.err{border-bottom-color:var(--err);color:var(--err)}
/* Ряд кнопок под заданием: проверить · сбросить · результат */
.ex-acts{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;margin-top:var(--s-3)}
.check-btn{border:none;background:var(--accent-soft);color:var(--accent-soft-ink);font-family:var(--font-head);font-weight:700;font-size:var(--t-base);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-4);cursor:pointer}
.check-btn:hover{filter:brightness(.96)}
.check-btn:disabled{opacity:.5;cursor:default}
.check-btn.ghost{background:none;color:var(--muted);box-shadow:inset 0 0 0 1px var(--line-2);padding:var(--s-2) var(--s-3)}
.check-btn.ghost:hover{color:var(--ink)}
.result-tag{font-weight:700;font-size:var(--t-base);font-family:var(--font-head)}
.result-tag.ok{color:var(--ok)}
.result-tag.err{color:var(--err)}
.match-wrap{position:relative}
.match-cols{display:flex;gap:52px}
.match-col{flex:1;display:flex;flex-direction:column;gap:var(--s-2)}
/* Плашка — кнопка, а не текст: нажатие на длинную фразу в две-три строки Safari
   нередко понимает как начало выделения, и до задания клик уже не доходит.
   Слева стоят слова в одну строку, справа — определения в две-три, и выглядело
   это как «правая колонка не работает». */
.match-item{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);padding:var(--s-3);text-align:center;font-weight:600;cursor:pointer;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.match-item:hover{border-color:var(--accent)}
.match-item.selected{border-color:var(--accent);background:var(--accent-soft)}
.match-item.done{border-color:var(--ok);background:var(--ok-bg);cursor:default}

/* ---------- «По группам»: слова разложить по колонкам ----------
   Колонки — цель, банк слов ниже, как поднос под корзинами. Выбранное слово
   кладётся кликом по колонке; плашка внутри колонки кликом возвращается в банк. */
.sort-cols{display:flex;gap:var(--s-3);margin-bottom:var(--s-3);flex-wrap:wrap}
.sort-col{flex:1;min-width:120px;border:1.5px dashed var(--line-strong);border-radius:var(--radius-sm);
  padding:var(--s-3);background:var(--surface-2);cursor:pointer}
.sort-col:hover{border-color:var(--accent)}
.sort-head{font-family:var(--font-head);font-weight:700;font-size:var(--t-base);text-align:center;margin-bottom:var(--s-2)}
.sort-items{display:flex;flex-wrap:wrap;gap:var(--s-1);justify-content:center;min-height:30px}

/* ---------- «Опорный план»: подписанные поля своими словами ---------- */
.frame-grid{display:flex;flex-direction:column;gap:var(--s-3);margin-bottom:2px}
.frame-row{display:flex;flex-direction:column;gap:var(--s-1)}
.frame-label{font-family:var(--font-head);font-weight:700;font-size:13.5px}
.frame-area{width:100%;min-height:52px;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:var(--s-2) var(--s-3);font-size:14.5px;background:var(--surface-2);resize:vertical}
.frame-area:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.frame-area:disabled{opacity:.7}
/* Размер холста задаёт коробка, а не атрибуты width/height: их проставляет
   drawLines по замеру, и на узком экране замер, сделанный до перестроения
   колонок, оставлял холст шире урока — страница уезжала вбок на эту разницу.
   Атрибуты по-прежнему нужны: по ним считается система координат линий. */
.match-svg{position:absolute;inset:0;pointer-events:none;width:100%;height:100%}
/* Как и у «Соответствий»: вариант ответа — кнопка, и выделять его текст мышью
   незачем, а Safari на этом теряет клик (см. .match-item). */
.opt{display:flex;align-items:center;gap:var(--s-3);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);margin-bottom:var(--s-2);cursor:pointer;background:var(--surface);
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.opt:hover{border-color:var(--accent)}
.opt.selected{border-color:var(--accent);background:var(--accent-soft)}
.opt.ok{border-color:var(--ok);background:var(--ok-bg)}
.opt.err{border-color:var(--err);background:var(--err-bg)}
.opt .radio{width:16px;height:16px;border:2px solid var(--line-strong);border-radius:50%;flex-shrink:0}
.opt .box{width:16px;height:16px;border:2px solid var(--line-strong);border-radius:5px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:11px;color:#fff}
.opt.selected .radio{border-color:var(--accent);background:radial-gradient(circle,var(--accent) 45%,transparent 50%)}
.opt.selected .box{border-color:var(--accent);background:var(--accent)}
.opt.ok .box{border-color:var(--ok);background:var(--ok)}
.tf-row{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-3) 0;border-bottom:1px solid var(--surface-2)}
.tf-row:last-of-type{border:none}
.tf-text{flex:1}
.tf-btn{border:1px solid var(--line);background:var(--surface);border-radius:7px;padding:6px var(--s-3);font-family:var(--font-head);font-weight:700;font-size:12px;cursor:pointer;color:var(--muted);margin-left:var(--s-1)}
.tf-btn.selected{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-soft-ink)}
.tf-btn.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.tf-btn.err{border-color:var(--err);background:var(--err-bg);color:var(--err)}
.order-item{display:flex;align-items:center;gap:var(--s-3);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);margin-bottom:var(--s-2);cursor:pointer;background:var(--surface);
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.order-item:hover{border-color:var(--accent)}
.order-num{width:26px;height:26px;border-radius:7px;border:1.5px dashed var(--line-strong);display:flex;align-items:center;justify-content:center;font-family:var(--font-head);font-weight:700;font-size:var(--t-sm);color:var(--muted);flex-shrink:0}
.order-item.numbered .order-num{border-style:solid;border-color:var(--accent);background:var(--accent-soft);color:var(--accent-soft-ink)}
.order-item.ok{border-color:var(--ok);background:var(--ok-bg)}
.order-item.err{border-color:var(--err);background:var(--err-bg)}
.open-area{width:100%;min-height:88px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3);font-size:14.5px;background:var(--surface-2);resize:vertical}
.open-area:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.sent-tag{color:var(--ok);font-weight:700;font-family:var(--font-head);font-size:var(--t-base)}
.saved-word{border-bottom:2px solid var(--note);border-radius:2px;background:linear-gradient(transparent 60%,var(--note-bg) 60%)}

.class-grid{display:grid;grid-template-columns:250px minmax(0,1fr);gap:var(--s-5);max-width:1180px;margin:0 auto;padding:var(--s-5) var(--s-5) 120px}
/* Шире, когда появляются поля с заметками: им нужно 256px справа от листа.
   Правило стояло выше по файлу, где его перебивала строка над ним, и полосу
   заметок на экранах чуть шире 1300px срезало краем страницы. */
@media(min-width:1300px){.class-grid{max-width:1320px}}
.class-grid.solo{grid-template-columns:minmax(0,1fr)}
.class-grid.solo .tpanel{display:none}
/* Без панели хода (ученик, просмотр) лист встаёт по центру, а место справа
   остаётся заметкам на полях: лист 700 + вылет 26 + стикер 230. */
@media(min-width:1300px){.class-grid.solo .class-canvas{max-width:956px;margin:0 auto;width:100%}}
@media(max-width:1299px){.class-grid.solo .class-canvas{max-width:700px;margin:0 auto;width:100%}}
/* ---------- Панель «Ход урока» ----------
   Материал занятия — единственная белая область экрана, панель отступает на
   бумагу платформы и говорит тихо: mono-номер, название блока, галочка. Своей
   карточки у неё нет — карточка здесь ровно одна, и это место, где ученик
   сейчас. Бумагу панель красит сама: тема урока внизу может быть тёмной, а
   панель платформенная, и её чернила на такой странице пропали бы. */
.tpanel{position:sticky;top:78px;align-self:start;max-height:calc(100vh - 100px);overflow:auto;
  background:var(--paper);border-radius:var(--radius);padding:var(--s-2)}
.tp-head{margin:0 var(--s-2) var(--s-2)}
.tpanel .bar{height:5px;margin:0 var(--s-2) var(--s-3)}
.tpanel .bar>span{background:var(--marker)}
.tp-list{display:flex;flex-direction:column;gap:2px}
.tp-row{display:flex;align-items:center;gap:var(--s-2);padding:5px var(--s-2);border:1px solid transparent;
  border-radius:var(--radius-sm);font-size:var(--t-sm);color:var(--muted);cursor:pointer}
.tp-row:hover{background:var(--surface-2)}
.tp-num{font-family:var(--font-mono);font-size:var(--t-label);font-weight:500;flex-shrink:0}
/* Название блока — то же, что в шапке его карточки: панель работает
   оглавлением, и строка должна называть то, к чему прокручивает. Длинное
   режем: в 250px колонке важнее узнать блок, чем дочитать инструкцию. */
.tp-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-status{margin-left:auto;font-weight:700;font-size:12px;font-family:var(--font-head);flex-shrink:0}
.tp-status.ok{color:var(--ok)}
.tp-status.err{color:var(--err)}
/* Устный блок платформа не проверяет — вместо галочки словом, чтобы пустой
   статус не читался как «ещё не сделано» */
.tp-status.oral{color:var(--muted);font-weight:500;font-size:var(--t-label);
  font-family:var(--font-mono);letter-spacing:.04em}
/* Ещё не дошли: там пока ничего не случилось, и строка отступает дальше
   сделанных. Ставится только когда известно, где ученик, — иначе «впереди»
   не от чего отсчитывать. */
.tp-row.ahead{opacity:.55}
/* Ученик прямо сейчас вводит ответ. Маркерная точка — одна из трёх живых вещей
   на экране, и единственная, что двигается в панели. */
.tp-row .type-dot{margin-left:auto;width:8px;height:8px;border-radius:50%;
  background:var(--marker);flex-shrink:0;animation:pulse 1.4s infinite}
/* ---------- Кто на связи ----------
   Главный вопрос занятия: слышат ли меня. Точка пульсирует только при живой
   связи — замершая точка врала бы, что всё в порядке. Серый значит «нет в
   классе», и это тоже ответ, а не отсутствие информации. */
/* Плашка всегда в одну строку: в узкой панели «Ход урока» имя переносилось на
   вторую и плашка расползалась овалом в два этажа. Длинное имя обрезаем
   многоточием — «на связи или нет» читается и по обрезанному. */
.presence{display:inline-flex;align-items:center;gap:var(--s-2);margin-bottom:var(--s-2);padding:5px var(--s-3);
  border:1px solid var(--line);border-radius:99px;background:var(--surface-2);
  font-family:var(--font-head);font-weight:600;font-size:var(--t-sm);color:var(--muted);
  max-width:100%;white-space:nowrap}
.presence.on{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.presence .pr-text{min-width:0;overflow:hidden;text-overflow:ellipsis}

/* Где второй сейчас — язычком на верхней границе блока, снаружи рамки: внутри
   метка спорила бы с самим заданием, а строкой в шапке ничего не говорила о
   том, к какому блоку относится. */
.cls-host{position:relative}
.peer-mark{position:absolute;top:-10px;left:16px;z-index:2;
  display:inline-flex;align-items:center;gap:var(--s-1);padding:2px var(--s-2);border-radius:99px;
  border:1px solid var(--ok);background:var(--ok-bg);color:var(--ok);
  font-family:var(--font-head);font-weight:600;font-size:var(--t-label);white-space:nowrap;
  max-width:calc(100% - 32px);overflow:hidden;text-overflow:ellipsis}
/* Присутствие живёт в шапке занятия у обоих: это ответ на вопрос «слышат ли
   меня», к ходу урока он не относится. */
.topbar .presence{margin-bottom:0}

/* Строка блока, на котором ученик сейчас, — единственная заметная в панели:
   белая карточка среди приглушённого списка. Рамка сильной линией, а не обычной:
   лист и бумага различаются мягко, и в тёмном хроме единственная заметная строка
   переставала быть заметной — обе почти чёрные. */
.tp-row.here,.tp-row.here:hover{background:var(--surface);border-color:var(--line-2);
  color:var(--ink);font-family:var(--font-head);font-weight:600;font-size:var(--t-base);padding:6px var(--s-2)}

.tp-open{font-size:12px;color:var(--muted);background:var(--surface-2);border-radius:var(--radius-sm);padding:var(--s-2);margin:0 0 2px;line-height:1.4}
.bar{height:7px;border-radius:99px;background:var(--surface-2);overflow:hidden;margin:var(--s-3) 0 var(--s-1)}
.bar>span{display:block;height:100%;background:var(--ok);border-radius:99px;transition:width .35s}
/* Светофор остатка: полная полоса зелёным говорила «всё хорошо» как раз там,
   где занятия кончились. .warn — вот-вот, .low — кончилось или срок прошёл. */
.bar.warn>span{background:var(--marker)}
.bar.low>span{background:var(--err)}
/* .live — только сама пульсирующая точка. Контейнерам этот класс не давать:
   он задаёт им размер 7×7, и содержимое вываливается наружу. Состояние
   «занятие идёт» у карточки называется is-live. */
.live{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--ok);margin-right:var(--s-1);animation:pulse 1.8s infinite}
.live.off{background:var(--line-strong);animation:none}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}}
.muted{color:var(--muted)}
.small{font-size:var(--t-sm)}

.cab{display:grid;grid-template-columns:200px minmax(0,1fr);gap:var(--s-5);max-width:1180px;margin:0 auto;padding:var(--s-5) var(--s-5) 120px}
.cab-nav{position:sticky;top:78px;align-self:start;display:flex;flex-direction:column;gap:2px}
.cab-nav button{border:none;background:transparent;text-align:left;padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--muted);cursor:pointer;display:flex;align-items:center;gap:var(--s-2)}
.cab-nav button:hover{background:var(--surface)}
.cab-nav button.on{background:var(--surface);color:var(--ink);box-shadow:var(--shadow)}
.cab-nav .badge{margin-left:auto;background:var(--accent);color:var(--accent-ink);border-radius:99px;font-size:var(--t-label);padding:1px var(--s-2);font-weight:700}
.hero{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--pad);margin-bottom:var(--s-3);display:flex;gap:var(--pad);align-items:center;flex-wrap:wrap}
.hero .when{font-family:var(--font-head);font-weight:700;font-size:30px;letter-spacing:-.02em;line-height:1.1}
/* ---------- Показатели: одна карточка крупнее остальных ----------
   Три равные плитки-счётчика («12 · 8 · 40 из 120») не говорят, много это или
   мало. Поэтому главный показатель крупнее и с историей — рядом с соседними
   месяцами или неделями видно, куда всё движется, — а остальные помельче
   рядом. Отсюда ширина 1.6 у первой карточки: в ней живёт график.
   Компонент общий: «Оплаты» у преподавателя и «Прогресс» в кабинете ученика. */
.stats{display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:var(--s-4);margin-bottom:var(--s-4);align-items:stretch}
/* Второй показатель — не одна карточка, а две стопкой. Когда у первой есть
   история, а у остальных только число, в ряду их растягивает до её высоты и
   рядом встают ящики с полутора сотнями пикселей пустоты. Стопкой они делят ту
   же высоту пополам и стоят вровень с соседкой. */
.stats.duo{grid-template-columns:1.6fr 1fr}
.stat-col{display:flex;flex-direction:column;gap:var(--s-4);min-width:0}
.stat-col>.stat{flex:1}
@media(max-width:820px){.stats,.stats.duo{grid-template-columns:1fr}}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s-4);display:flex;flex-direction:column;gap:var(--s-2)}
.stat-big{font-family:var(--font-head);font-weight:700;font-size:32px;letter-spacing:-.01em;line-height:1.1}
.stat-unit{font-family:var(--font-body);font-weight:400;font-size:var(--t-md);color:var(--muted);margin-left:var(--s-1)}
/* Сноска прижата к низу: у карточек разной высоты подписи иначе висят вразнобой */
.stat-note{font-size:var(--t-sm);color:var(--muted);margin-top:auto}

/* Полгода дохода столбиками. Маркер тут — цвет данных, а не заметок: урока на
   этом экране нет, спорить не с чем (решение Р-5 хендоффа). Текущий месяц
   маркером, прошлые — маркером по бумаге. */
.mini-chart{display:flex;align-items:flex-end;gap:6px;height:64px;margin-top:auto}
.mini-chart i{flex:1;background:var(--marker-soft);border-radius:3px 3px 0 0;min-height:3px}
.mini-chart i.now{background:var(--marker)}
.mini-chart-x{display:flex;gap:6px;font-family:var(--font-mono);font-weight:500;font-size:10px;
  color:var(--muted);text-transform:uppercase}
.mini-chart-x span{flex:1;text-align:center}
.mini-chart-x span.now{color:var(--marker-ink);font-weight:600}
.sec-title{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);margin:var(--s-5) 0 var(--s-3);display:flex;align-items:center;gap:var(--s-2)}
.sec-title .more{margin-left:auto;font-size:var(--t-sm);font-weight:600;color:var(--accent);cursor:pointer;background:none;border:none}
.tag{font-size:11.5px;font-weight:700;font-family:var(--font-head);border-radius:99px;padding:3px var(--s-3);white-space:nowrap}
.tag.new{background:var(--accent-soft);color:var(--accent-soft-ink)}
.tag.due{background:var(--err-bg);color:var(--err)}
.tag.sent{background:var(--surface-2);color:var(--muted)}
.tag.done{background:var(--ok-bg);color:var(--ok)}
.lib{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:var(--s-3)}
.lib-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;cursor:pointer;transition:transform .15s,box-shadow .15s}
.lib-card:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
.lib-card img{width:100%;height:106px;object-fit:cover;display:block;background:var(--surface-2)}
.lib-card .b{padding:var(--s-3) var(--s-3)}
.lib-card .t{font-family:var(--font-head);font-weight:600;font-size:var(--t-md);line-height:1.35}
/* Поиск по своим словам и отбор по отметке. Двести слов сплошной лентой не
   найти, а строка выше ищет во внешнем словаре — по своим искать было нечем. */
.vocab-tools{display:flex;gap:var(--s-3);align-items:center;flex-wrap:wrap;margin-bottom:var(--s-3)}
.vocab-tools .search-inp{flex:1;min-width:180px;max-width:320px}
.card-acts{display:flex;gap:9px;margin:var(--s-3) 0 var(--s-2)}
/* Переносится: три поля в ряд не помещались на телефон и уводили страницу в
   горизонтальную прокрутку — вместе с ней уезжала и нижняя навигация. */
.vocab-add{display:flex;gap:var(--s-2);margin-bottom:var(--s-2);flex-wrap:wrap}
.vocab-add input{flex:1 1 150px;min-width:0;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-md)}
.vocab-add input:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.flashcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:38px var(--pad);text-align:center;cursor:pointer;user-select:none;min-height:168px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-2)}
.flashcard .w{font-family:var(--font-head);font-weight:700;font-size:29px;letter-spacing:-.02em}
/* Строка фактов в кабинете — вместо плиток-счётчиков: цифры полезны, но не
   настолько, чтобы занимать экран выше того, что надо сделать. */
.facts-line{font-size:var(--t-sm);color:var(--muted);margin:0 0 var(--s-1);padding:0 2px}
/* Просроченное — отдельной строкой над списком: срок прошёл, это надо увидеть первым */
.late-line{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-3);padding:var(--s-3) var(--s-3);
  border:1px solid var(--err-line);background:var(--err-bg);border-radius:var(--radius-sm);
  cursor:pointer;font-size:var(--t-base)}
.late-line .muted{margin-left:auto}


/* Тултип перевода слова — тёмный (по хендоффу «Выделение слова»): фиксированный
   #171A21 вне зависимости от темы урока, транскрипция mono, «↵ В словарь»
   маркерным цветом. */
.lookup{position:absolute;z-index:90;background:#171A21;color:#EDECE8;border-radius:12px;box-shadow:0 18px 44px -14px rgba(0,0,0,.5);width:270px;display:none;overflow:hidden}
.lookup.open{display:block}
.lookup .lhead{padding:var(--s-3) var(--s-4) var(--s-2);display:flex;align-items:baseline;gap:var(--s-2);flex-wrap:wrap}
.lookup .lw{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);color:#FBFAF7}
.lookup .ipa{font-family:var(--font-mono);color:#8C8C86;font-size:12px;letter-spacing:.03em}
.lookup .lbody{padding:2px var(--s-4) var(--s-3)}
.lookup .tr-chips{display:flex;flex-wrap:wrap;gap:var(--s-1)}
.lookup .tr-chip{border:1px solid #33363D;background:#22252B;color:#EDECE8;border-radius:99px;padding:6px var(--s-3);font-size:var(--t-sm);font-weight:600;cursor:pointer}
.lookup .tr-chip:hover{border-color:#4A4E56}
.lookup .tr-chip.on{border-color:var(--marker);background:rgba(232,163,23,.14);color:var(--marker)}
.lookup .ldetail{margin-top:var(--s-2);background:#22252B;border-radius:8px;padding:var(--s-2) var(--s-3);font-size:var(--t-sm);line-height:1.5;color:#C4C4C0;display:none}
.lookup .ldetail.on{display:block}
.lookup .ldetail .dpos{font-family:var(--font-mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:#8C8C86;margin-bottom:3px}
.lookup .ldetail .dex{margin-top:var(--s-1);color:#9A9A94;font-style:italic}
.lookup .lfoot{padding:0 var(--s-4) var(--s-3)}
.lookup .add-word{background:none;border:none;color:var(--marker);font-family:var(--font-head);font-weight:700;font-size:var(--t-base);cursor:pointer;padding:var(--s-1) 0;display:inline-flex;align-items:center;gap:var(--s-1)}
.lookup .add-word:hover{color:#F4B838}
.lookup .add-word.done{color:#8C8C86;cursor:default}
.lookup .add-word .kbd{font-family:var(--font-mono);font-size:var(--t-label);opacity:.8}
.lookup .lmsg{font-size:12px;color:#9A9A94;padding:2px 0 var(--s-1)}
.lookup .lspin{width:15px;height:15px;border:2px solid #33363D;border-top-color:var(--marker);border-radius:50%;animation:spin .8s linear infinite;margin:var(--s-3) 0}
.lookup .arrow{position:absolute;top:-5px;left:20px;width:11px;height:11px;background:#171A21;transform:rotate(45deg)}

.scrim{position:fixed;inset:0;background:rgba(20,20,18,.34);display:none;align-items:center;justify-content:center;z-index:100;padding:var(--s-5)}
.scrim.open{display:flex}
.modal{background:var(--surface);border-radius:16px;width:600px;max-width:100%;max-height:88vh;overflow:auto;padding:var(--s-5);box-shadow:0 24px 60px -20px rgba(0,0,0,.35)}
.modal h2{font-size:18px;margin-bottom:3px}
.modal .sub{color:var(--muted);font-size:var(--t-base);margin-bottom:var(--s-4)}
.modal textarea{width:100%;min-height:140px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3);font-size:var(--t-md);background:var(--surface-2);resize:vertical}
.modal textarea:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.drop{border:1.5px dashed var(--line-strong);border-radius:var(--radius-sm);padding:var(--s-3);text-align:center;color:var(--muted);font-size:var(--t-base);margin:var(--s-3) 0;cursor:pointer}
.drop:hover{border-color:var(--accent);color:var(--accent)}
.actions{display:flex;gap:var(--s-2);margin-top:var(--s-3);justify-content:flex-end;align-items:center}
.spin{width:16px;height:16px;border:2.5px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;display:none}
@keyframes spin{to{transform:rotate(360deg)}}
.status{font-size:var(--t-sm);color:var(--muted);margin-right:auto;line-height:1.4}
.status.bad{color:var(--err)}
.file-tag{display:inline-flex;align-items:center;gap:var(--s-2);background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:6px var(--s-3);font-size:var(--t-sm);margin-top:var(--s-1);margin-right:var(--s-1)}
/* номер страницы в списке файлов — порядок разбора виден до нажатия «Перенести» */
.file-tag .fnum{font-family:var(--font-mono);font-size:var(--t-label);color:var(--muted);background:var(--surface);
  border:1px solid var(--line);border-radius:5px;padding:1px var(--s-1);font-weight:500}
.note-box{background:var(--surface-2);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);font-size:var(--t-sm);color:var(--muted);margin-bottom:var(--s-3);line-height:1.5}
.seg-target{display:flex;gap:var(--s-2);margin:var(--s-3) 0}
.seg-target label{flex:1;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);cursor:pointer;font-size:var(--t-base)}
.seg-target label.on{border-color:var(--accent);background:var(--accent-soft)}
.seg-target input{margin-right:var(--s-2)}

/* Уровень и объём в окне сборки урока. Кнопками, а не выпадающим списком:
   вариантов мало, и все они должны быть видны сразу — выбор уровня это
   решение, а не настройка, которую ищут в списке. */
.gen-opts{display:flex;gap:18px;flex-wrap:wrap;margin:var(--s-3) 0 var(--s-1)}
.gen-opts>div{display:flex;flex-direction:column;gap:6px}
.seg-row{display:flex;gap:6px;flex-wrap:wrap}
.seg-row .seg{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);
  padding:7px var(--s-3);font-size:var(--t-base);font-weight:600;color:var(--ink-2);cursor:pointer}
.seg-row .seg:hover{border-color:var(--line-2);color:var(--ink)}
.seg-row .seg.on{border-color:var(--accent);background:var(--accent-soft);color:var(--ink)}

.picker{width:470px}
.picker input.search{width:100%;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);font-size:var(--t-md);background:var(--surface-2);margin-bottom:var(--s-3)}
.picker input.search:focus{outline:none;border-color:var(--accent);background:var(--surface)}
.pgroup{font-size:var(--t-label);text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:700;margin:var(--s-3) 0 var(--s-2)}
.pitem{display:flex;align-items:center;gap:var(--s-3);width:100%;border:1px solid transparent;background:transparent;border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);cursor:pointer;text-align:left}
.pitem:hover{background:var(--surface-2);border-color:var(--line)}
.pitem .ic{width:34px;height:34px;border-radius:8px;background:var(--surface-2);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.pitem .ic svg{width:20px;height:20px}
.pitem .n{font-family:var(--font-head);font-weight:600;font-size:var(--t-md)}
.pitem .d{font-size:12px;color:var(--muted)}

.drawer{position:fixed;top:0;right:0;bottom:0;width:320px;background:var(--surface);border-left:1px solid var(--line);z-index:110;padding:var(--s-5);overflow:auto;transform:translateX(100%);transition:transform .25s ease;box-shadow:-20px 0 50px -30px rgba(0,0,0,.4)}
.drawer.open{transform:none}
.drawer h3{font-size:var(--t-md);margin-bottom:2px}
.dgroup{margin-top:var(--s-5)}
.dgroup>label{display:block;font-size:var(--t-label);text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:700;margin-bottom:var(--s-2)}
.theme-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-2)}
.theme-card{border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2);cursor:pointer;background:var(--surface);text-align:left}
.theme-card.on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.theme-card .sw{height:34px;border-radius:6px;display:flex;align-items:center;justify-content:center;margin-bottom:var(--s-2);font-weight:700;font-size:var(--t-md)}
.theme-card .nm{font-size:var(--t-sm);font-weight:600;font-family:var(--font-head)}
.swatches{display:flex;gap:var(--s-2);flex-wrap:wrap}
.swatch{width:28px;height:28px;border-radius:8px;border:2px solid transparent;cursor:pointer}
.swatch.on{border-color:var(--ink)}
/* Что зафиксировано — сказано словами, а не пустой группой с одной кнопкой:
   иначе непонятно, ручку убрали или потеряли. */
.dfix{margin-top:var(--s-5);padding-top:var(--s-3);border-top:1px solid var(--surface-2);
  font-size:11.5px;line-height:1.6;color:var(--muted)}
.opts{display:flex;gap:var(--s-1);flex-wrap:wrap}
.opts button{border:1px solid var(--line);background:var(--surface);border-radius:8px;padding:var(--s-2) var(--s-3);font-size:var(--t-sm);cursor:pointer;font-weight:600;font-family:var(--font-head);color:var(--muted)}
.opts button.on{border-color:var(--accent);color:var(--accent-soft-ink);background:var(--accent-soft)}
/* Пустое состояние: глиф «Поле» и слова. Глиф рисуется псевдоэлементами самой
   строки — поэтому он появляется в каждом пустом состоянии платформы сам, и ни
   одно не может обзавестись своим значком. Отступ сверху и положение стикера
   связаны переменной: стикер стоит абсолютом, а линия — в потоке. */
.empty{--glyph-top:32px;position:relative;text-align:center;
  padding:var(--glyph-top) var(--s-5) var(--s-6);color:var(--muted);
  border:1.5px dashed var(--line-strong);border-radius:var(--radius)}
.empty .big{font-size:var(--t-lg);font-family:var(--font-head);font-weight:700;color:var(--ink);margin-bottom:var(--s-1)}
/* Линия поля — в потоке, она же держит место под весь глиф */
.empty::before{content:'';display:block;width:56px;height:56px;margin:0 auto var(--s-2);
  background:linear-gradient(var(--line-2),var(--line-2)) no-repeat 40% 4px/1.5px 48px}
/* Стикер — отдельным слоем: фоновый слой не повернёшь, а поворот −4° и заход на
   линию и есть весь мотив */
.empty::after{content:'';position:absolute;top:calc(var(--glyph-top) + 16px);
  left:calc(50% - 16.6px);width:26px;height:26px;
  background:var(--marker);border-radius:3px;transform:rotate(-4deg)}
/* Не получилось: стикер пустой и пунктиром — на поле ничего не приклеилось */
.empty.error::after{background:var(--surface-2);border:1.5px dashed var(--line-2)}
/* «Пока пусто»: у ученика ещё ничего нет не потому, что сломалось, — стикер на
   месте, но приглушён */
.empty.soft::after{opacity:.45}
/* Пустое состояние в строку — короткая приписка внутри карточки, глифу там
   негде развернуться */
.empty.bare{padding:var(--s-4) var(--s-5)}
.empty.bare::before,.empty.bare::after{content:none}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--ink);color:var(--bg);padding:var(--s-3) var(--s-4);border-radius:99px;font-size:var(--t-base);font-weight:600;font-family:var(--font-head);opacity:0;transition:.25s;z-index:200;pointer-events:none}
.toast.on{opacity:1;transform:translateX(-50%)}
/* С действиями тост становится кликабельным — но только пока он виден: класс
   with-acts снимается вместе с on (см. hideToast), и это подстраховано здесь,
   иначе прозрачная полоса внизу экрана глотала бы чужие клики. */
.toast.with-acts{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-2) var(--s-3) var(--s-2) var(--s-4)}
.toast.with-acts.on{pointer-events:auto}
.toast-act{border:1px solid rgba(255,255,255,.28);background:transparent;color:inherit;
  font:inherit;font-size:var(--t-sm);border-radius:99px;padding:var(--s-1) var(--s-3);cursor:pointer;white-space:nowrap}
.toast-act:hover{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.5)}

/* ---------- Каталог, ученики ---------- */
/* width:100% обязателен: .app-main — флекс-колонка, а `margin:0 auto` на
   поперечной оси отменяет растягивание, и страница сжималась по содержимому.
   На «Сегодня» это было незаметно (широкие блоки сами держали ширину), а
   кабинет ученика из-за этого выглядел узкой мобильной колонкой. */
.page{max-width:1180px;width:100%;margin:0 auto;padding:var(--s-5) var(--s-5) 120px}
/* Заголовок страницы: подпись и название слева, действие — у правого края и по
   нижней линии заголовка, чтобы кнопка не «висела» рядом с надзаголовком. */
.page-head{display:flex;align-items:flex-end;gap:var(--s-3);margin-bottom:var(--s-4);flex-wrap:wrap}
.page-head h1{font-size:var(--t-h1);letter-spacing:-.015em}
.page-head .spacer{flex:1}
.search-inp{border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface);width:220px}
.search-inp:focus{outline:none;border-color:var(--accent)}
.folder-chips{display:flex;gap:var(--s-2);flex-wrap:wrap;margin-bottom:var(--s-4)}
.folder-chip{border:1px solid var(--line);background:var(--surface);border-radius:99px;padding:6px var(--s-3);font-size:var(--t-sm);font-weight:600;font-family:var(--font-head);cursor:pointer;color:var(--muted)}
.folder-chip.on{border-color:var(--ink);background:var(--ink);color:var(--paper)}
.folder-chip.on span{opacity:.7}
.cat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:var(--s-4)}
.cat-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;display:flex;flex-direction:column;transition:box-shadow .15s,transform .15s;position:relative}
.cat-card:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
.cat-card img{width:100%;height:72px;object-fit:cover;display:block;background:var(--surface-2)}
/* Обложка урока без картинки — мотив «Поле» вместо нейтрального градиента:
   линия поля, стикер с первой буквой темы и две строки текста за ним. Градиент
   говорил «здесь могла быть картинка», а мотив говорит, что это урок Lessona,
   и по букве урок различим в каталоге из тридцати таких же. */
.field-cover{position:relative;background:var(--paper);overflow:hidden}
.field-cover::before{content:'';position:absolute;top:0;bottom:0;left:28%;width:1.5px;background:var(--line-2)}
.field-cover::after{content:'';position:absolute;left:calc(28% + 32px);right:14px;top:50%;
  height:19px;margin-top:-9px;
  background:linear-gradient(var(--line),var(--line)) no-repeat 0 0/78% 6px,
             linear-gradient(var(--line),var(--line)) no-repeat 0 13px/54% 6px}
/* Буква на стикере — не токеном: маркер #E8A317 один и тот же в обеих темах
   хрома, а --marker-ink в тёмной становится светло-золотым (он для текста на
   приглушённой подложке, не на самом маркере) — буква пропадала бы на стикере.
   Пара «яркий маркер + это чернило» постоянна, как и в счётчике меню. */
.field-cover i{position:absolute;left:calc(28% - 14px);top:50%;margin-top:-17px;
  width:34px;height:34px;background:var(--marker);border-radius:4px;transform:rotate(-4deg);
  display:flex;align-items:center;justify-content:center;font-style:normal;
  font-family:var(--font-head);font-weight:700;font-size:15px;color:#7A5406}
.cat-card .field-cover{height:72px}
.lib-card .field-cover{height:106px}
.cat-card .cb{padding:var(--s-3) var(--s-3);flex:1;display:flex;flex-direction:column;gap:var(--s-1)}
.cat-card .ct2{font-family:var(--font-head);font-weight:700;font-size:var(--t-md);line-height:1.3}
.cat-card .cm{font-size:12px;color:var(--muted)}
.cat-card .ca{display:flex;flex-wrap:wrap;gap:var(--s-1);padding:0 var(--s-4) var(--s-3)}
.cat-card .ca .btn{flex:1 1 auto;min-width:66px;justify-content:center;padding:var(--s-2) var(--s-1)}
/* «В домашку» в шапке задания на занятии: тихая, пока на неё не навели, — она
   про после урока, а не про то, что делают сейчас. На устройствах без мыши
   видна всегда: наводить там нечем. */
.card .hw-add-btn{margin-left:auto;flex-shrink:0;border:none;background:none;cursor:pointer;
  font-family:var(--font-head);font-weight:600;font-size:var(--t-label);letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted);padding:2px var(--s-2);border-radius:6px}
.card .hw-add-btn:hover{color:var(--ink);background:var(--surface-2)}
.card .hw-add-btn.on{color:var(--accent-soft-ink);background:var(--accent-soft)}
@media (hover:hover){
  .card .hw-add-btn:not(.on){opacity:0;transition:opacity .12s}
  .card:hover .hw-add-btn,.card:focus-within .hw-add-btn{opacity:1}
}

/* ---------- Выбор кадра у картинки ----------
   Рамка ровно тех пропорций, в которых картинка встанет на место, картинка
   внутри двигается мышью. Обрезает не вёрстка, а сам преподаватель — обложка
   узкая, и object-fit:cover резал портрет по центру, оставляя вместо лица
   что придётся. */
.crop-frame{position:relative;overflow:hidden;border-radius:var(--radius-sm);background:var(--surface-2);
  border:1px solid var(--line);cursor:grab;touch-action:none;user-select:none;width:100%}
.crop-frame.grabbing{cursor:grabbing}
.crop-frame img{position:absolute;left:0;top:0;transform-origin:0 0;max-width:none;display:block;pointer-events:none}
.crop-zoom{display:flex;align-items:center;gap:var(--s-3);margin:var(--s-3) 0 var(--s-4)}
.crop-zoom input{flex:1;accent-color:var(--ink)}

/* Окно выбора ученика: имя целиком, действия справа, длинный список прокручен */
.sp-list{display:flex;flex-direction:column;max-height:min(52vh,420px);overflow:auto;margin:0 -4px;padding:0 4px}
.sp-row{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-2) var(--s-2);border-radius:8px}
.sp-row:hover{background:var(--surface-2)}
.sp-row .sp-n{flex:1;min-width:0;font-family:var(--font-head);font-weight:600;font-size:var(--t-md);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sp-row .sp-a{display:flex;gap:var(--s-2);flex-shrink:0}

/* ---------- Окно выбора урока ----------
   Каталог в окне: те же чипы папок, тот же поиск и те же обложки, что во
   вкладке «Уроки». Плоский список названий, который был здесь раньше, годился,
   пока уроков десяток. */
.modal.wide{width:min(760px,calc(100vw - 32px))}
.lp-search{margin-bottom:var(--s-3)}
.lp-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--s-2);
  max-height:min(52vh,440px);overflow:auto;padding:2px}
.lp-card{display:flex;flex-direction:column;text-align:left;padding:0;overflow:hidden;cursor:pointer;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);position:relative}
.lp-card:hover{border-color:var(--accent)}
.lp-card.on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.lp-card>img,.lp-card>.field-cover{width:100%;height:84px;object-fit:cover;display:block;flex-shrink:0}
.lp-card .lp-b{display:flex;flex-direction:column;gap:2px;padding:var(--s-2) var(--s-3) var(--s-3)}
.lp-card .lp-t{font-family:var(--font-head);font-weight:600;font-size:var(--t-md);line-height:1.3}
.lp-card .lp-m{font-size:var(--t-sm);color:var(--muted)}
.lp-card .lp-now{position:absolute;top:6px;right:6px;background:var(--ink);color:var(--paper);
  border-radius:99px;padding:2px var(--s-2);font-size:var(--t-label);font-family:var(--font-head);font-weight:600}
@media(max-width:560px){.lp-grid{grid-template-columns:1fr;max-height:56vh}
  .lp-card>img,.lp-card>.field-cover{height:64px}}

.assign-pop{position:absolute;left:10px;right:10px;bottom:10px;background:var(--surface);border:1px solid var(--line);border-radius:11px;box-shadow:0 14px 34px -10px rgba(0,0,0,.3);padding:var(--s-2);z-index:5}
.assign-pop .ttl{font-size:var(--t-label);text-transform:uppercase;letter-spacing:.07em;color:var(--muted);font-weight:700;padding:var(--s-1) var(--s-2)}
.assign-pop .ap-row{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-2);border-radius:8px;font-size:var(--t-base)}
.assign-pop .ap-row:hover{background:var(--surface-2)}
.assign-pop .ap-row .btn{margin-left:auto}
/* Инициалы лежат в кружке всегда, фото — картинкой поверх них. Не открылось —
   картинка убирает себя, и буквы уже на месте (см. avatar() в core.js). */
.stu-ava{position:relative;overflow:hidden;width:40px;height:40px;border-radius:50%;background:var(--accent-soft);color:var(--accent-soft-ink);display:flex;align-items:center;justify-content:center;font-family:var(--font-head);font-weight:700;font-size:var(--t-md);flex-shrink:0}
.stu-ava img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.stu-ava.xs{width:26px;height:26px;font-size:var(--t-label)}
.stu-ava.sm{width:28px;height:28px;font-size:var(--t-label)}
.stu-ava.lg{width:64px;height:64px;font-size:var(--t-h1)}
.stu-back{background:none;border:none;color:var(--accent);font-weight:600;font-family:var(--font-head);font-size:var(--t-base);cursor:pointer;padding:0;margin-bottom:var(--s-3)}
.invite-box{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-4) var(--s-4);margin-bottom:var(--s-4)}
.invite-url{display:flex;gap:var(--s-2);margin-top:var(--s-3)}
.invite-url input{flex:1;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface-2);font-family:ui-monospace,Menlo,monospace}

/* ---------- Вход / регистрация ---------- */
.auth-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:var(--s-5)}
.auth-card{background:var(--surface);border:1px solid var(--line);border-radius:16px;padding:var(--s-6);width:400px;max-width:100%;box-shadow:var(--shadow)}
.auth-card h1{font-size:21px;margin-bottom:var(--s-1)}
.auth-card .sub{color:var(--muted);font-size:var(--t-base);margin-bottom:var(--s-5)}
.auth-card .btn{width:100%;justify-content:center;padding:var(--s-3);font-size:var(--t-md);margin-top:var(--s-1)}
.auth-err{background:var(--err-bg);color:var(--err);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);font-size:var(--t-base);margin-bottom:var(--s-3);display:none;border:1px solid var(--err-line)}
.auth-err.on{display:block}
/* Письмо ушло. Зелёным, но без галочки-иконки: отправили — не значит дошло,
   и обещать больше, чем знаем, здесь нечем. */
.auth-ok{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok);border-radius:var(--radius-sm);
  padding:14px;font-size:var(--t-base);line-height:1.55;margin-bottom:var(--s-1);display:none}
.auth-ok.on{display:block}
.auth-ok b{display:block;font-family:var(--font-head);font-size:var(--t-md);margin-bottom:var(--s-1)}
.auth-ok span{color:var(--ink-2)}
/* «Забыли пароль?» — под полем пароля, справа: у поля это единственный
   сосед, и в общий ряд ссылок внизу карточки он бы потерялся. */
.field-aside{display:flex;justify-content:flex-end;margin-top:6px}
.field-aside a{font-weight:600;text-decoration:none;color:var(--muted)}
.field-aside a:hover{color:var(--ink);text-decoration:underline}
.auth-card .field input{background:var(--surface);border-color:var(--line-2)}

/* Предпросмотр «Как у ученика» внутри карточки: тема урока со своим фоном */
.themed-preview{border-radius:var(--radius-sm);padding:var(--s-3);margin:0 -2px}

/* Панель редактирования внутри оформленной карточки блока: платформенные цвета
   островком, чтобы поля оставались читаемыми в любой теме урока. Отделяем её
   от оформленной части рамкой и фоном — видно, где кончается урок и начинается
   работа с ним. */
.beditor{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:var(--s-3);margin-top:2px}
/* поля ввода на оформленной подложке: держим контраст за счёт --surface-2 темы */
.beditor .field input,.beditor .field textarea,.beditor .field select,.beditor .row input{
  background:var(--surface-2);border-color:var(--line)}

/* Служебные подписи конструктора — тип блока, переключатель, инструменты —
   набраны шрифтами платформы: тема урока задаёт им цвет, но не типографику,
   иначе serif-тема превращала служебные надписи в текст урока. */
.rail,.block .bhead,.block .seg,.block .btools,.beditor label,.beditor .hint,.beditor .btn,
.tnote-add,.tnote-field label{
  --font-head:'Onest',system-ui,sans-serif;
  --font-body:'Manrope',system-ui,sans-serif;
  font-family:var(--font-body);
}
.beditor .field:last-child,.beditor .row:last-child{margin-bottom:0}
/* Инструменты блока тоже платформенные: иконки не должны тонуть в тёмной теме */
.btools{border-radius:8px}

/* Куда девать блок — под раскрытым блоком и словами, а не значками в шапке */
.bfoot{display:flex;gap:var(--s-4);flex-wrap:wrap;margin-top:var(--s-3);padding-top:var(--s-3);
  border-top:1px solid var(--line)}
.bfoot button{border:none;background:none;padding:0;cursor:pointer;color:var(--muted);
  font-family:'Onest',system-ui,sans-serif;font-weight:600;font-size:var(--t-sm)}
.bfoot button:hover{color:var(--ink)}
/* На карточке заметки подложка маркерная, и приглушённый цвет на ней тонет
   (3.8 вместо 4.5): там свои чернила. */
.block.is-note .bfoot button,.block.is-note .btype{color:var(--note-ink)}
.block.is-note .bfoot{border-top-color:var(--note-line)}

/* ---------- Методические заметки преподавателя ----------
   Не маркерные: жёлтый закреплён за заметками на полях, которые видит ученик.
   Здесь наоборот — то, чего ученик не видит, поэтому пунктир и служебное моно. */
.tnote-add{display:inline-flex;align-items:center;gap:var(--s-2);margin-top:var(--s-3);padding:6px var(--s-3);
  border:1px dashed var(--line-2);border-radius:var(--radius-sm);background:none;color:var(--muted);
  font-family:var(--font-head);font-size:var(--t-sm);font-weight:600;cursor:pointer}
.tnote-add:hover{border-color:var(--ink);color:var(--ink)}
.tnote-add svg{width:14px;height:14px;flex-shrink:0}
.tnote-field{margin-top:var(--s-3)}
.tnote-field label{display:flex;align-items:center;gap:var(--s-1)}
.tnote-field label svg{width:13px;height:13px;flex-shrink:0}
.tnote-field textarea{border-style:dashed;background:var(--surface-2);resize:vertical}
.tnote-mark{margin-left:var(--s-1);color:var(--muted);display:inline-flex;align-items:center;flex-shrink:0}

/* ---------- Разбор преподавателя в проверенной работе ----------
   Голос преподавателя, обращённый к ученику: сплошной кант акцентом темы урока,
   в отличие от пунктирной методической заметки (её ученик не видит вовсе) и от
   жёлтой заметки на полях. Маркер здесь не занимаем — он за заметками. */
.teacher-mark{display:flex;align-items:flex-start;gap:var(--s-3);margin-top:var(--s-3);padding:var(--s-3) var(--s-3);
  border-left:2px solid var(--accent);background:var(--surface-2);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.teacher-mark .tm-tag{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--muted);padding-top:3px;flex-shrink:0}
.teacher-mark .tm-score{font-family:var(--font-head);font-weight:700;font-size:13.5px;margin-bottom:3px}
.teacher-mark .tm-text{font-size:var(--t-md);line-height:1.55;color:var(--ink-2)}

/* Полоса над проверенной работой: статус, оценка целиком, где искать разбор */
.review-bar{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;margin-bottom:var(--s-3);
  padding:var(--s-3) var(--s-4);background:var(--ok-bg);border:1px solid var(--ok);
  border-radius:var(--radius-sm)}
.review-bar .rb-label{font-family:var(--font-head);font-weight:700;font-size:13.5px;color:var(--ok)}
.review-bar .rb-score{font-family:var(--font-head);font-weight:700;font-size:13.5px}

/* В классе: полоса поверх блока, только у преподавателя */
.tnote-live{display:flex;align-items:flex-start;gap:var(--s-2);margin:0 0 var(--s-3);padding:var(--s-2) var(--s-3);
  border-left:2px dashed var(--line-2);background:var(--surface-2);border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  font-size:13.5px;line-height:1.5;color:var(--ink-2)}
.tnote-live .tl-tag{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--muted);padding-top:3px;flex-shrink:0}

/* Поле картинки в конструкторе: файл с компьютера + миниатюра */
.img-field{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;margin-bottom:var(--s-2)}
.img-thumb{width:56px;height:42px;object-fit:cover;border-radius:6px;border:1px solid var(--line)}

/* ---------- Поиск слова по словарю (ученик) ---------- */
.ws{position:relative;display:flex;align-items:center;gap:var(--s-2);background:var(--surface);
  border:1px solid var(--line-2);border-radius:99px;padding:var(--s-1) var(--s-3);min-width:220px;max-width:420px;width:100%}
.ws:focus-within{border-color:var(--ink)}
.ws .ws-ic{color:var(--muted);display:flex;flex-shrink:0}
.ws input{flex:1;min-width:0;border:none;background:none;outline:none;font-size:var(--t-base)}
.ws .ws-x{border:none;background:none;color:var(--muted);cursor:pointer;font-size:12px;padding:2px var(--s-1)}
.ws .ws-x:hover{color:var(--ink)}
.ws-drop{display:none;position:absolute;top:calc(100% + 7px);left:0;right:0;z-index:60;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:var(--s-2);max-height:60vh;overflow:auto}
.ws-drop.on{display:block}
.ws-sec{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);padding:var(--s-2) var(--s-2) var(--s-1)}
.ws-row{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-2);border-radius:var(--radius-sm);font-size:var(--t-base)}
.ws-row:hover{background:var(--surface-2)}
.ws-row.muted{color:var(--muted)}
.ws-row .ws-en{font-weight:700;font-family:var(--font-head);flex-shrink:0}
.ws-row .ws-ru{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-row .ws-tag,.ws-sense .ws-tag{font-size:var(--t-label);color:var(--ok);font-weight:700;flex-shrink:0}

/* Карточка слова: заголовок с транскрипцией, значения по одному */
.ws-word{display:flex;align-items:baseline;gap:var(--s-2);padding:var(--s-2) var(--s-2) var(--s-1);border-top:1px solid var(--line);margin-top:var(--s-1)}
.ws-word .ws-en{font-family:var(--font-head);font-weight:700;font-size:var(--t-md)}
.ws-ipa{font-family:var(--font-mono);font-size:12px;color:var(--muted)}
.ws-sense{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-1) var(--s-2);border-radius:var(--radius-sm)}
.ws-sense:hover{background:var(--surface-2)}
.ws-sense .ws-ru{font-size:var(--t-md);color:var(--ink);flex-shrink:0;font-weight:600}
.ws-pos{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);border:1px solid var(--line-2);border-radius:5px;padding:1px var(--s-1);flex-shrink:0}
.ws-near{font-size:var(--t-sm);color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-sense .ws-btn.add{min-width:30px;text-align:center;font-size:var(--t-md);line-height:1;padding:var(--s-1) var(--s-2)}
.ws-ex{font-size:var(--t-sm);color:var(--muted);padding:0 var(--s-2) var(--s-2) var(--s-2);font-style:italic}
.ws-eng{display:flex;gap:var(--s-2);align-items:baseline;padding:var(--s-1) var(--s-2);font-size:var(--t-base);line-height:1.5;color:var(--ink-2)}

/* В занятии строка поиска шире — это рабочий инструмент. Цветом её не выделяем:
   она часть хрома и не должна перекрашиваться темой урока. Ширина желаемая, а не
   обязательная: когда в шапке тесно, поиск уступает место первым (см. .top-actions),
   и нижняя граница здесь оставляет ровно столько, чтобы видеть набранное слово. */
.topbar .ws.big{flex:1 1 300px;min-width:110px;max-width:340px}
.ws-btn{border:1px solid var(--line-2);background:none;color:var(--ink-2);border-radius:99px;
  padding:3px var(--s-3);font-size:12px;font-weight:600;font-family:var(--font-head);cursor:pointer;flex-shrink:0}
.ws-btn:hover{border-color:var(--ink);color:var(--ink)}
.ws-btn.add{background:var(--marker-soft);border-color:var(--marker-soft);color:var(--marker-ink)}
/* В классе строка поиска стоит в верхней панели и не должна её распирать */
.topbar .ws{max-width:300px;min-width:170px}

/* ---------- Свои диалоги и выпадающие списки ----------
   Системные prompt/confirm и родной <select> открывают окна операционной
   системы — чужой шрифт и чужие кнопки посреди платформы. */
.modal.dlg{width:440px}
.btn.danger{background:var(--err);border-color:var(--err);color:#FFFFFF}
.btn.danger:hover{filter:brightness(.94)}

/* Ответ у утверждения True/False/NG — три кнопки вместо системного списка:
   вариантов всего три, выбирать их кликом быстрее, чем через выпадашку. */
.tf-pick{display:flex;gap:var(--s-1);flex-shrink:0}
.tf-pick .tf-btn{min-width:38px}

.usel{position:relative}
.usel-btn{display:flex;align-items:center;gap:var(--s-3);width:100%;text-align:left;cursor:pointer;
  border:1px solid var(--line-2);border-radius:var(--radius-sm);background:var(--surface-2);
  padding:var(--s-2) var(--s-3);font-size:var(--t-md);font-family:inherit;color:var(--ink)}
.usel-btn:hover{border-color:var(--ink-2)}
.usel.open .usel-btn{border-color:var(--ink);background:var(--surface)}
.usel-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.usel-chev{color:var(--muted);font-size:var(--t-label);flex-shrink:0}
.usel-list{display:none;position:absolute;top:calc(100% + 5px);left:0;right:0;z-index:70;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:var(--shadow);padding:var(--s-1);max-height:260px;overflow:auto}
.usel.open .usel-list{display:block}
.usel-opt{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);border-radius:6px;cursor:pointer;font-size:var(--t-base)}
.usel-opt:hover{background:var(--surface-2)}
.usel-opt.on{background:var(--accent-soft);color:var(--accent-soft-ink);font-weight:600}

/* ---------- Настройки ---------- */
.set-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:var(--s-3);align-items:start}
.set-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--pad)}
.set-card h3{font-size:15.5px;margin-bottom:2px}
.set-card .btn{margin-top:var(--s-1)}
.set-row{display:flex;align-items:center;gap:var(--s-3);justify-content:space-between;flex-wrap:wrap}
.set-row .sr-t{font-family:var(--font-head);font-weight:600;font-size:var(--t-md)}
.set-facts{display:flex;gap:var(--s-5);flex-wrap:wrap}
.set-facts>div{display:flex;flex-direction:column}
.set-facts .sf-n{font-family:var(--font-head);font-weight:800;font-size:var(--t-h1);letter-spacing:-.02em}
.set-facts .sf-l{font-size:var(--t-sm);color:var(--muted)}

/* Окно сбора домашки: раздел «Домашка» и задания урока в одном списке */
.mhead{display:flex;align-items:flex-start;gap:var(--s-3);margin-bottom:var(--s-4)}
.mhead>div:first-child{flex:1;min-width:0}
.mrow{display:flex;align-items:center;gap:var(--s-2);margin-top:var(--s-4);padding-top:var(--s-3);border-top:1px solid var(--line);flex-wrap:wrap}
.hwp-sec{margin-bottom:var(--s-4)}
.hwp-sec-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  font-family:var(--font-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);padding-bottom:var(--s-1);border-bottom:1px solid var(--line);margin-bottom:var(--s-1)}
.hwp-row{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-2) var(--s-1);border-radius:var(--radius-sm);cursor:pointer}
.hwp-row:hover{background:var(--surface-2)}
.hwp-row.on{background:var(--accent-soft)}
.hwp-row .hwp-ic{color:var(--muted);display:flex;flex-shrink:0}
.hwp-row .hwp-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--t-base)}
.hwp-row .hwp-type{font-size:11.5px;color:var(--muted);flex-shrink:0}
.hw-add{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;margin-bottom:var(--s-3)}
.ap-note{padding:var(--s-2) var(--s-3) 2px;line-height:1.45;border-top:1px solid var(--line);margin-top:var(--s-1)}

/* Переключатель разделов урока в рельсе: занятие и домашка */
.rail-tabs{display:flex;gap:var(--s-1);margin-bottom:var(--s-2)}
.rail-tabs .rt{flex:1;border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);
  padding:var(--s-1) var(--s-2);font-family:var(--font-head);font-weight:600;font-size:var(--t-sm);color:var(--muted);
  cursor:pointer;display:flex;align-items:center;justify-content:center;gap:var(--s-1)}
.rail-tabs .rt:hover{color:var(--ink)}
.rail-tabs .rt.on{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.rail-tabs .rt-n{font-family:var(--font-mono);font-size:var(--t-label);opacity:.7}

/* ---------- Черновик урока ---------- */
/* Метка нейтральная, не маркерная: маркер закреплён за заметками. */
.draft-tag{font-family:var(--font-mono);font-size:var(--t-label);font-weight:500;text-transform:uppercase;
  letter-spacing:.04em;color:var(--muted);border:1px solid var(--line-2);border-radius:5px;
  padding:1px var(--s-1);vertical-align:middle;white-space:nowrap}
.btn.draft{border-color:var(--line-2);color:var(--ink-2);font-weight:600}
.btn.draft:hover{border-color:var(--ink);color:var(--ink)}

/* ---------- Поле пароля с кнопкой показа ---------- */
.pw-wrap{position:relative;display:flex}
.pw-wrap input{flex:1;padding-right:40px}
.pw-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);border:none;background:transparent;
  color:var(--muted);cursor:pointer;width:28px;height:28px;border-radius:6px;display:inline-flex;
  align-items:center;justify-content:center;padding:0}
.pw-eye:hover{color:var(--ink);background:var(--surface-2)}
.pw-eye svg{width:17px;height:17px;display:block}
/* Требование выполнено — подсказка гаснет */
.hint.done{color:var(--ok);opacity:.65}

.auth-links{display:flex;align-items:center;gap:var(--s-2);margin-top:var(--s-4);flex-wrap:wrap}
.auth-links a{font-weight:600;text-decoration:none}
.auth-links a:hover{text-decoration:underline}
.consent{display:flex;align-items:flex-start;gap:var(--s-2);margin:var(--s-1) 0 var(--s-1);cursor:pointer;line-height:1.45}
.consent input{margin-top:2px;flex-shrink:0}

/* Экран по ссылке-приглашению начинается с того, кто пригласил */
.inviter{display:flex;align-items:center;gap:var(--s-3);background:var(--paper);border:1px solid var(--line);
  border-radius:var(--radius);padding:var(--s-3) var(--s-4);margin-bottom:var(--s-3)}
.inviter .inv-title{font-family:var(--font-head);font-weight:700;font-size:var(--t-md);line-height:1.35}

.invite-form{display:flex;gap:var(--s-2);margin:var(--s-3) 0 var(--s-1);flex-wrap:wrap}
.invite-form input{flex:1;min-width:150px;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface)}
.invite-form input:focus{outline:none;border-color:var(--ink)}
.invite-item{border-top:1px solid var(--line);padding-top:var(--s-3);margin-top:var(--s-3)}

/* ---------- Онбординг: развилка «С чего начнём?» ---------- */
.start-page{max-width:1000px}
.start-head{margin:var(--s-3) 0 var(--s-5)}
.start-head h1{font-family:var(--font-head);font-weight:800;font-size:clamp(26px,4vw,36px);
  letter-spacing:-.025em;line-height:1.1;margin:var(--s-2) 0 var(--s-3)}
.start-sub{color:var(--ink-2);font-size:15.5px;line-height:1.6;max-width:560px}
.start-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--s-3)}
.start-card{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-2);text-align:left;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-5);
  cursor:pointer;transition:box-shadow .15s,transform .15s,border-color .15s}
.start-card:hover{box-shadow:var(--shadow);transform:translateY(-2px);border-color:var(--line-2)}
.start-card .sc-ic{width:38px;height:38px;border-radius:10px;background:var(--surface-2);color:var(--ink);
  display:inline-flex;align-items:center;justify-content:center;margin-bottom:3px}
.start-card .sc-ic svg{width:20px;height:20px}
/* Карточка ИИ на развилке первого входа — единственная цветная из четырёх:
   выбор здесь свободный, но подсказать, с чего начать, стоит. Цветной здесь
   значок, а не вся карточка: залить маркером площадь в четверть экрана —
   это уже не акцент, а фон. */
.start-card.ai .sc-ic{background:var(--marker);color:#171A21}
.start-card.ai{border-color:var(--marker)}
.start-card.ai .sc-go{color:var(--marker-ink)}
/* Перенос учебника — та же модель, поэтому та же семья, но тише */
.start-card.ai-soft .sc-ic{background:var(--marker-soft);color:var(--marker-ink)}
.start-card .sc-t{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);letter-spacing:-.01em}
.start-card .sc-d{font-size:var(--t-base);color:var(--muted);line-height:1.55}
.start-card .sc-go{margin-top:auto;padding-top:var(--s-1);font-family:var(--font-head);font-weight:600;
  font-size:var(--t-base);color:var(--accent)}
.start-skip{margin-top:var(--s-5)}

/* ---------- Служебная типографика (JetBrains Mono) ---------- */
.eyebrow{font-family:var(--font-mono);font-size:var(--t-label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}
/* Надстрочник бренд-цветом — чернилами маркера, а не самим маркером: #E8A317
   по бумаге даёт 2.07, и надпись 10.5px капсом на нём не читается. Тон тот же,
   тёплый, но её видно. */
.eyebrow.marker{color:var(--marker-ink)}
.code-box{font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:var(--s-2) var(--s-3)}

/* ---------- Переключатель темы хрома ---------- */
.chrome-toggle{border:1px solid var(--line-2);background:var(--surface);color:var(--muted);width:30px;height:30px;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.chrome-toggle:hover{color:var(--ink);border-color:var(--ink)}
.chrome-toggle svg{width:16px;height:16px}

/* ---------- Состояния: пустые и ошибки ---------- */
.empty{border:1.5px dashed var(--line-2)}
.card.error,.empty.error{border:1px solid var(--err-line)}

/* ---------- Лендинг ---------- */
/* Одна прокручиваемая страница по хендоффу design_handoff_lessona_landing:
   hero, шесть блоков с «живыми» макетами интерфейса, финальный CTA, футер.
   Цвета берутся платформенными токенами — в хендоффе стоят те же значения.
   Вся «жизнь» макетов — CSS-циклы по 9с; JS на странице нет. */
.lp{
  /* Чего нет в палитре платформы: жёлоб полосы прогресса и цвета тёмных
     блоков лендинга — они тёмные всегда, а не по теме хрома. */
  --lp-track:#EFEDE7;
  --lp-dark:#171A21; --lp-dark-panel:#1F232B; --lp-dark-line:#2F343D;
  --lp-dark-track:#2A2E36; --lp-dark-fill:#5D636E;
  --lp-dark-ink:#F2F2EF; --lp-dark-ink-2:#B9BAB5; --lp-dark-muted:#8B8D88;
  background:var(--paper);color:var(--ink);font-size:15px;line-height:1.65;overflow-x:hidden}
.lp a{color:inherit;text-decoration:none}
.lp a:not(.lp-btn):hover{color:var(--marker-ink)}
/* Программное отключение движения (проп motion в хендоффе). Системное
   prefers-reduced-motion снимает анимации выше, глобально по платформе. */
.lp[data-motion="off"] *{animation:none !important}

/* Шапка и кнопки */
.lp-head{position:sticky;top:0;z-index:20;background:rgba(251,250,247,.9);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.lp-head-in{max-width:1160px;margin:0 auto;padding:14px 28px;display:flex;align-items:center;gap:var(--s-3)}
/* Лендинг вне шкалы хрома намеренно: у него свой ряд с clamp() из хендоффа */
.lp-head .brand{font-size:19px;letter-spacing:-.02em;gap:9px}
.lp-head nav{margin-left:auto;display:flex;align-items:center;gap:var(--s-4)}
.lp-login{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--ink-2)}
.lp a.lp-login:hover{color:var(--ink)}
/* Три кнопки страницы названы по-разному намеренно — не сводить к одной формуле */
.lp-btn{display:inline-flex;align-items:center;justify-content:center;text-align:center;
  font-family:var(--font-head);font-weight:600;white-space:nowrap}
.lp-btn.dark{background:var(--ink);color:var(--paper)}
.lp a.lp-btn.dark:hover{background:#000;color:#fff}
.lp-btn.sm{font-size:var(--t-base);padding:9px 15px;border-radius:9px}
.lp-btn.md{font-size:15px;padding:13px 22px;border-radius:10px}
.lp-btn.accent{background:var(--marker);color:var(--ink);font-size:15px;padding:14px 22px;border-radius:11px}
.lp a.lp-btn.accent:hover{filter:brightness(1.06);color:var(--ink)}

/* Ритм страницы: 110px между секциями, 96px перед финальным CTA */
.lp-sec{max-width:1160px;margin:0 auto;padding:110px 28px 0}
.lp-sec-hero{padding-top:64px}
.lp-row{display:flex;flex-wrap:wrap;gap:56px;align-items:center}
/* Модификаторы с префиксом lp-: голые .hero, .cab и .block уже заняты
   платформой и притащили бы сюда свои сетки и рамки. */
.lp-row.lp-top{gap:52px}
/* wrap-reverse: при схлопывании текст встаёт над макетом — так задумано */
.lp-row.rev{flex-wrap:wrap-reverse}
.lp-side{flex:1 1 360px;min-width:0}
.lp-side.w380{flex:1 1 380px}
.lp-side.w420{flex:1 1 420px}
.lp-shot{flex:1.1 1 440px;min-width:0}
.lp-shot.w420{flex:1.1 1 420px}
.lp-shot.w460{flex:1.15 1 460px}
.lp-head-group{max-width:60ch;margin-bottom:34px}
.lp-head-group.wide{max-width:62ch}
.lp-cta-sec{max-width:1160px;margin:96px auto 0;padding:0 28px}
.lp-cta-btn{flex:0 1 280px;display:flex;flex-direction:column;gap:10px}
.lp-footer{max-width:1160px;margin:0 auto;padding:34px 28px 64px;display:flex;flex-wrap:wrap;gap:20px;align-items:center}

/* Типографика: ширина в символах, а не в пикселях */
.lp h1{font-family:var(--font-head);font-weight:800;font-size:clamp(34px,4.4vw,52px);
  line-height:1.06;letter-spacing:-.03em;margin-bottom:18px;text-wrap:pretty}
.lp h2{font-family:var(--font-head);font-weight:700;font-size:clamp(27px,3.2vw,38px);
  line-height:1.12;letter-spacing:-.025em;margin-bottom:var(--s-4);text-wrap:pretty}
.lp .nw{white-space:nowrap}
.lp-lead{font-size:17px;line-height:1.62;color:var(--ink-2);max-width:48ch;margin-bottom:14px;text-wrap:pretty}
.lp-body{font-size:var(--t-lg);line-height:1.62;color:var(--ink-2);max-width:48ch;margin-bottom:26px;text-wrap:pretty}
.lp-txt p{color:var(--ink-2);max-width:48ch;margin-bottom:14px;text-wrap:pretty}
.lp-txt p:last-child{margin-bottom:0}
.lp-txt.wide p{max-width:none;margin-bottom:var(--s-3)}
.lp-txt p.lp-quiet{color:var(--muted);font-size:13.5px}
.lp-cta{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.lp-cta-note{font-size:var(--t-base);color:var(--muted)}
.lp-marker{display:inline-flex;align-items:center;gap:9px;margin-top:18px;background:var(--surface);
  border:1px solid var(--line);border-radius:99px;padding:7px 14px 7px var(--s-2);font-size:var(--t-sm);color:var(--ink-2)}
.lp-marker .g{width:24px;height:24px;border-radius:50%;background:var(--ink);color:var(--paper);
  font-size:12px;display:flex;align-items:center;justify-content:center;flex-shrink:0}

/* Общее для макетов интерфейса */
.lp-card{border:1px solid var(--line);border-radius:16px;background:var(--surface);
  box-shadow:0 20px 50px rgba(23,26,33,.07);overflow:hidden}
.lp-card.paper{background:var(--paper)}
.lp-card.lp-top{box-shadow:0 26px 64px rgba(23,26,33,.09)}
.lp-card.lp-dash{box-shadow:0 22px 54px rgba(23,26,33,.08)}
.lp-card.pad{padding:20px 22px}
.lp-card.pad22{padding:22px}
.lp-card.notes{padding:22px 20px;position:relative}
.lp-bar{display:flex;align-items:center;gap:9px;padding:11px var(--s-4);border-bottom:1px solid var(--line)}
.lp-bar svg{flex-shrink:0;display:block}
.lp-bar-t{font-family:var(--font-head);font-weight:700;font-size:var(--t-base)}
.lp-bar .lp-sub{margin-left:auto}
.lp-card-head{display:flex;align-items:center;margin-bottom:var(--s-4)}
.lp-card-t{font-family:var(--font-head);font-weight:700;font-size:13.5px}
.lp-card-top{display:flex;align-items:center;gap:var(--s-2);padding:10px 14px;border-bottom:1px solid var(--line);
  font-family:var(--font-mono);font-size:10px;color:var(--muted)}
.lp-card-foot{display:flex;align-items:center;gap:var(--s-2);margin-top:var(--s-4);padding-top:13px;
  border-top:1px solid var(--line);font-family:var(--font-mono);font-size:var(--t-label);color:var(--muted)}
.lp-meta{font-family:var(--font-mono);font-size:10px;color:var(--muted)}
.lp-meta.tr{letter-spacing:.1em}
.lp-meta.tr08{letter-spacing:.08em}
.lp-mono{font-family:var(--font-mono);font-size:11px;color:var(--muted)}
.lp-mono.ink{color:var(--marker-ink)}
.lp-name{font-family:var(--font-head);font-weight:600;font-size:var(--t-sm)}
.lp-name.dim{color:var(--ink-2)}
.lp-sub{font-size:11.5px;color:var(--muted)}
.lp-sub.ink{color:var(--marker-ink)}
.lp-h3{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg)}
.lp-h3.sm{font-size:15px}
.lp-dot{width:7px;height:7px;border-radius:50%;background:var(--ok);flex-shrink:0;animation:lsnPulse 1.6s ease-in-out infinite}
.lp-dot.still{animation:none}
.lp-dot.grey{width:8px;height:8px;background:var(--line-2);animation:none}
.lp-live{margin-left:auto;display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-2)}
.lp-ava{width:24px;height:24px;border-radius:50%;background:var(--line);font-family:var(--font-head);
  font-weight:600;font-size:11px;color:var(--ink-2);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.lp-ava.lg{width:34px;height:34px;font-size:var(--t-base)}
.lp-ok{width:16px;height:16px;border-radius:50%;background:var(--ok-bg);color:var(--ok);font-size:10px;
  display:flex;align-items:center;justify-content:center;flex-shrink:0}
.lp-ok.lg{width:19px;height:19px;font-size:11px;background:var(--ok);color:var(--lp-dark-ink)}
.lp-prog{display:flex;align-items:center;gap:10px}
/* .trk, а не .bar: глобальная .bar принесла бы свою высоту и margin */
.lp-prog .trk{flex:1;height:5px;border-radius:3px;background:var(--lp-track);overflow:hidden}
.lp-prog .trk i{display:block;height:100%;border-radius:3px;background:var(--marker)}
.lp-prog .n{font-family:var(--font-mono);font-size:var(--t-label);color:var(--muted)}
.lp-note{background:var(--marker-soft);border:1px solid var(--marker);border-radius:8px;padding:7px 9px;
  font-size:11.5px;line-height:1.45;color:var(--marker-ink)}
.lp-note.dashed{background:none;border:1px dashed var(--line-2);color:var(--muted)}
.lp-pill{border:1px solid var(--line-2);border-radius:99px;padding:2px 10px;white-space:nowrap;
  font-family:var(--font-head);font-weight:600;font-size:11.5px}
.lp-pill.sm{padding:1px 9px;font-size:11px}
.lp-pill.off{color:var(--muted)}
.lp-pills{margin-left:auto;display:flex;gap:6px}
.lp-gap{display:inline-block;min-width:56px;border-bottom:2px solid var(--ink)}
.lp-gap.w58{min-width:58px}
.lp-gap.w62{min-width:62px}
.lp-gap.accent{border-bottom-color:var(--marker)}
.lp-hl{background:var(--marker-soft);border-radius:3px;padding:0 3px}
.lp-chipbtn{margin-left:auto;background:var(--marker-soft);color:var(--marker-ink);border-radius:99px;
  padding:var(--s-1) 11px;font-family:var(--font-head);font-weight:600;font-size:11.5px;white-space:nowrap}
.lp-chipbtn.lp-full{display:block;margin-left:0;border-radius:9px;padding:var(--s-2) var(--s-3);font-size:var(--t-sm);text-align:center}

/* 1. Рабочее окно преподавателя */
.lp-desk{display:grid;grid-template-columns:132px minmax(0,1fr) 122px;min-height:346px}
.lp-desk>.l{border-right:1px solid var(--line);padding:14px var(--s-3);display:flex;flex-direction:column;gap:7px}
.lp-desk>.c{background:var(--surface);padding:18px 20px;display:flex;flex-direction:column;gap:var(--s-3)}
.lp-desk>.r{border-left:1px solid var(--line);padding:14px 10px;position:relative}
.lp-desk>.l>.lp-meta{margin-bottom:2px}
.lp-desk>.r>.lp-meta{margin-bottom:10px}
.lp-desk>.r .lp-note.dashed{margin-top:14px}
.lp-desk>.c .lp-prog{margin-top:auto}
.lp-slot{padding:var(--s-2) 9px;display:flex;flex-direction:column;gap:2px}
.lp-slot.on{background:var(--surface);border:1px solid var(--line);border-radius:9px;box-shadow:0 1px 0 rgba(23,26,33,.03)}
.lp-slot .lp-sub{font-size:11px}
.lp-foot{margin-top:auto;border-top:1px solid var(--line);padding-top:10px;display:flex;flex-direction:column;gap:3px}
.lp-foot .lp-sub{font-size:11px}
.lp-task{border:1px solid var(--line);border-radius:10px;padding:11px 13px;position:relative}
.lp-task>.lp-meta{margin-bottom:6px}
.lp-task.plain{font-size:var(--t-base);line-height:1.9}
.lp-task.dashed{border-style:dashed;border-color:var(--line-2);font-size:var(--t-sm);color:var(--muted)}
.lp-line{font-size:13.5px;line-height:1.9}
.lp-line.sm{font-size:var(--t-sm);line-height:1.8}
/* «печатается» ответ: внешний span держит ширину пропуска, внутренний растёт */
.lp-type{display:inline-flex;align-items:baseline;vertical-align:baseline;min-width:74px;overflow:hidden;
  white-space:nowrap;border-bottom:2px solid var(--ink);font-family:var(--font-body)}
.lp-type .t{display:inline-block;overflow:hidden;white-space:nowrap}
.lp-tick{position:absolute;top:9px;right:11px;animation:lsnTick 9s ease-out infinite}
.lp-tf{display:flex;align-items:center;gap:10px;font-size:13.5px}
.lp-tf.sm{gap:var(--s-2);font-size:var(--t-sm)}
.lp-tf.sm .lp-pills{gap:5px}

/* 2. Импорт учебника */
.lp-tag{margin-left:auto;display:flex;align-items:center;gap:6px;background:var(--marker-soft);
  color:var(--marker-ink);border-radius:99px;padding:3px 10px;font-family:var(--font-mono);font-size:10px;letter-spacing:.08em}
.lp-tag .d{width:5px;height:5px;border-radius:50%;background:var(--marker);animation:lsnPulse 1.4s ease-in-out infinite}
.lp-imp{display:flex;gap:14px;align-items:stretch}
.lp-src{flex:0 0 178px;background:var(--paper);border:1px solid var(--line);border-radius:11px;padding:14px;
  position:relative;overflow:hidden;display:flex;flex-direction:column;gap:var(--s-2)}
.lp-src>.lp-meta{margin-bottom:2px}
.lp-src .ln{height:8px;border-radius:4px;background:var(--line)}
.lp-src .ln.mk{height:9px;background:var(--marker-soft)}
.lp-beam{position:absolute;left:0;right:0;top:6px;height:30px;border-top:1.5px solid var(--marker);
  background:linear-gradient(180deg,rgba(232,163,23,.20),transparent);animation:lsnScan 9s ease-in-out infinite}
.lp-arrow{flex:0 0 30px;display:flex;align-items:center;justify-content:center;font-size:20px;
  color:var(--marker);animation:lsnNudge 2.6s ease-in-out infinite}
.lp-res{flex:1;min-width:0;display:flex;flex-direction:column;gap:9px}
.lp-chip{border:1px solid var(--line);border-radius:10px;padding:10px var(--s-3);animation:lsnRise 9s ease-in-out infinite}
.lp-chip .cl{font-family:var(--font-head);font-weight:600;font-size:11px;color:var(--muted);margin-bottom:5px}
.lp-opts{display:flex;flex-direction:column;gap:5px;font-size:var(--t-sm)}
.lp-opts>span{display:flex;align-items:center;gap:7px}
.lp-opts>span.dim{color:var(--ink-2)}
.lp-opts .rd{width:12px;height:12px;border-radius:50%;border:2px solid var(--line-2);flex-shrink:0}
.lp-opts .rd.on{border-color:var(--ink);background:var(--ink)}

/* 3 и 9. Тёмные блоки */
.lp-dark{background:var(--lp-dark);color:var(--lp-dark-ink);border-radius:20px;
  padding:clamp(30px,4vw,48px);display:flex;flex-wrap:wrap;gap:44px;align-items:center}
.lp-dark.end{padding:clamp(36px,5vw,64px);gap:36px}
.lp h2.on-dark{font-size:clamp(26px,3.2vw,36px);line-height:1.14}
.lp-dark.end h2.on-dark{font-size:clamp(26px,3.4vw,38px);margin-bottom:14px}
.lp-txt.on-dark p{color:var(--lp-dark-ink-2);max-width:46ch}
.lp-sub-dark{color:var(--lp-dark-ink-2);max-width:46ch;text-wrap:pretty}
.lp-meta.on-dark{color:var(--lp-dark-muted)}
.lp-panel{background:var(--lp-dark-panel);border:1px solid var(--lp-dark-line);border-radius:14px;padding:20px 22px}
.lp-panel>.lp-meta{margin-bottom:var(--s-4)}
.lp-drow{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-3)}
.lp-drow.last{margin-bottom:0;padding-bottom:18px;border-bottom:1px solid var(--lp-dark-line)}
.lp-drow .k{flex:0 0 92px;font-size:var(--t-base);color:var(--lp-dark-ink-2)}
.lp-drow .k.strong{font-family:var(--font-head);font-weight:600;color:var(--lp-dark-ink)}
.lp-drow .v{flex:0 0 74px;text-align:right;font-family:var(--font-mono);font-size:11px;color:var(--lp-dark-muted)}
.lp-drow .v.accent{color:var(--marker)}
.lp-dtrack{flex:1;height:8px;border-radius:4px;background:var(--lp-dark-track);overflow:hidden}
.lp-dtrack>i{display:block;height:100%;border-radius:4px;background:var(--lp-dark-fill)}
.lp-dtrack>i.grow{background:none}
.lp-dtrack>i.grow>b{display:block;height:100%;border-radius:4px;background:var(--marker);animation:lsnGrow 4.5s ease-out infinite}
.lp-dnote{display:flex;align-items:center;gap:11px;margin-top:18px}
.lp-dnote .t{font-family:var(--font-head);font-weight:600;font-size:13.5px}
.lp-dnote .s{font-size:12px;color:var(--lp-dark-muted)}

/* 4. Заметки на полях */
.lp-sheet{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:18px 20px;
  margin:0 108px 0 6px;display:flex;flex-direction:column;gap:var(--s-3);min-height:280px}
.lp-sheet-foot{display:flex;align-items:center;gap:10px;margin:14px 108px 0 6px}
.lp-sticky{position:absolute;right:8px;width:88px;border-radius:9px}
.lp-sticky.note{top:62px;background:var(--marker-soft);border:1px solid var(--marker);padding:7px var(--s-2);
  font-size:11px;line-height:1.4;color:var(--marker-ink)}
.lp-sticky.pic{top:152px;background:var(--surface);border:1px solid var(--line);padding:7px}
.lp-sticky.pic .ph{height:40px;border-radius:6px;background:linear-gradient(135deg,#EFEDE7,#E1DED6);margin-bottom:5px}
.lp-sticky.pic .cap{font-size:var(--t-label);line-height:1.35;color:var(--muted)}
.lp-typing{margin-left:auto;display:flex;align-items:center;gap:6px;background:var(--ink);color:var(--paper);
  border-radius:99px;padding:var(--s-1) 10px;font-size:11px;white-space:nowrap}
.lp-typing .d{width:6px;height:6px;border-radius:50%;background:var(--marker)}

/* 5. Темы оформления: три слоя кроссфейдятся, платформа вокруг не меняется */
.lp-themes{padding:22px;min-height:262px}
.lp-themes-in{position:relative;height:214px}
.lp-th{position:absolute;inset:0;border-radius:12px;padding:18px 20px;animation:lsnCyc 12s ease-in-out infinite}
.lp-th .t{margin-bottom:9px}
.lp-th .g{margin-top:var(--s-3)}
.lp-th .cap{position:absolute;bottom:16px;left:20px;font-family:var(--font-mono);font-size:10px}
.lp-th.std{background:var(--surface);border:1px solid var(--line)}
.lp-th.std .t{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg)}
.lp-th.std p{font-family:var(--font-body);font-size:13.5px;line-height:1.7;color:var(--ink-2)}
.lp-th.std .hl{background:var(--marker-soft);border-radius:3px;padding:0 3px;color:var(--ink)}
.lp-th.std .g{font-size:13.5px;color:var(--ink-2)}
.lp-th.std .cap{color:var(--muted)}
.lp-th.book{background:#F6F1E6;border:1px solid #E2D8C4}
.lp-th.book .t{font-family:'Source Serif 4',Georgia,serif;font-weight:600;font-size:17px;color:#2E2A22}
.lp-th.book p{font-family:Georgia,serif;font-size:var(--t-md);line-height:1.7;color:#4A4436}
.lp-th.book .hl{background:#EFDDB0;border-radius:3px;padding:0 3px}
.lp-th.book .g{font-family:Georgia,serif;font-size:var(--t-md);color:#4A4436}
.lp-th.book .lp-gap{border-bottom-color:#B08A38}
.lp-th.book .cap{color:#8A8069}
.lp-th.night{background:#1B1E25;border:1px solid #2C3038}
.lp-th.night .t{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);color:var(--lp-dark-ink)}
.lp-th.night p{font-family:var(--font-body);font-size:13.5px;line-height:1.7;color:#C3C4C0}
.lp-th.night .hl{background:#4A4028;color:#F5D98A;border-radius:3px;padding:0 3px}
.lp-th.night .g{font-size:13.5px;color:#C3C4C0}
.lp-th.night .cap{color:var(--lp-dark-muted)}
.lp-accents{border-top:1px solid var(--line);padding:13px 22px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.lp-accents .sw{display:flex;gap:var(--s-2)}
.lp-sw{width:18px;height:18px;border-radius:50%}
.lp-sw.on{box-shadow:0 0 0 2px var(--paper),0 0 0 3.5px var(--ink)}

/* 6. Синхронная работа: две одинаковые карточки, у ученика заметка на .25с позже */
.lp-pair{display:flex;flex-wrap:wrap;gap:18px;align-items:stretch}
.lp-card.sync{flex:1 1 340px;min-width:0;box-shadow:0 20px 50px rgba(23,26,33,.06);
  padding:20px 22px;display:flex;flex-direction:column;gap:13px}
.lp-card.sync .lp-card-head{margin-bottom:0;gap:var(--s-2)}
.lp-card.sync .lp-card-t{font-size:var(--t-md)}
.lp-card.sync .lp-note{border-radius:9px;padding:7px 10px}
.lp-card.sync .lp-prog{margin-top:auto}
.lp-ask{background:var(--paper);border:1px solid var(--line);border-radius:11px;padding:13px 15px}
.lp-ask>.lp-meta{margin-bottom:7px}
.lp-ask .q{font-size:13.5px;line-height:1.8;margin-bottom:var(--s-2)}
.lp-input{background:var(--surface);border:1px solid var(--line-2);border-radius:8px;padding:var(--s-2) 10px;
  font-size:13.5px;display:flex;align-items:center}
.lp-input.accent{border-color:var(--marker)}
/* Курсор идёт за текстом, а не по всему полю.
   Раньше .tw лежала прямо во flex-контейнере поля, и её width:100% в конце
   анимации разворачивался на всю ширину поля — курсор уезжал в пустой конец
   строки, отрываясь от текста, который «печатается».
   Обёртка сжата по содержимому (width:max-content), поэтому 100% у .tw — это
   ширина самого текста: курсор встаёт вплотную и едет вместе с ним. */
.lp-input .lp-tw{display:inline-flex;align-items:center;width:max-content;max-width:100%;min-width:0}
.lp-input .tw{overflow:hidden;white-space:nowrap}
.lp-input .car{width:1.5px;height:15px;background:var(--ink);margin-left:2px;flex-shrink:0;animation:lsnBlink 1s step-end infinite}

/* 7. Оплаты */
.lp-sum{display:flex;align-items:flex-end;gap:var(--s-4);margin-bottom:18px}
.lp-sum .lp-meta{margin-bottom:var(--s-1)}
.lp-money{font-family:var(--font-head);font-weight:700;font-size:32px;letter-spacing:-.025em}
.lp-spark{margin-left:auto;display:flex;align-items:flex-end;gap:7px;height:62px}
.lp-spark .c{width:16px;height:62px;display:flex;align-items:flex-end}
.lp-spark i{display:block;width:100%;border-radius:3px;background:var(--marker-soft);
  transform-origin:bottom;animation:lsnBar 2.4s ease-out infinite}
.lp-spark i.now{background:var(--marker)}
.lp-metrics{display:flex;gap:22px;flex-wrap:wrap;padding:13px 0;margin-bottom:var(--s-4);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.lp-metrics .n{font-family:var(--font-head);font-weight:700;font-size:17px}
.lp-metrics .l{font-size:11.5px;color:var(--muted)}
.lp-people{display:flex;flex-direction:column;gap:9px}
.lp-person{display:flex;align-items:center;gap:var(--s-3);padding:10px 13px}
.lp-person.on{background:var(--paper);border:1px solid var(--line);border-radius:10px}
.lp-person .who{min-width:0}
.lp-person .lp-name{font-size:13.5px}
.lp-person .sub{margin-left:auto;display:flex;flex-direction:column;align-items:flex-end;gap:5px}
.lp-person .ticks{display:flex;gap:3px}
.lp-person .ticks span{width:9px;height:5px;border-radius:2px;background:var(--marker)}
/* седьмое деление гаснет — занятие списывается прямо сейчас */
.lp-person .ticks .off-now{animation:lsnDim 4.5s ease-in-out infinite}
.lp-person .ticks .spent{background:var(--lp-track)}

/* 8. Кабинет ученика — десктопный дашборд, а не телефон */
.lp-cab{display:grid;grid-template-columns:158px minmax(0,1fr) 232px;min-height:330px}
.lp-cab>.l{border-right:1px solid var(--line);padding:14px var(--s-3);display:flex;flex-direction:column;gap:3px}
.lp-cab>.c{background:var(--surface);padding:20px 22px;display:flex;flex-direction:column;gap:var(--s-4)}
.lp-cab>.r{border-left:1px solid var(--line);padding:var(--s-4) 14px;display:flex;flex-direction:column;gap:9px}
.lp-cab .lp-foot{padding-top:11px;gap:2px}
.lp-cab .nav{padding:var(--s-2) 10px;font-size:var(--t-sm);color:var(--ink-2)}
.lp-cab .nav.on{display:flex;align-items:center;gap:var(--s-2);background:var(--surface);border:1px solid var(--line);
  border-radius:8px;font-family:var(--font-head);font-weight:600;color:var(--ink)}
.lp-cab .nav.on .d{width:6px;height:6px;border-radius:50%;background:var(--marker)}
.lp-cab .next{display:flex;align-items:flex-end;gap:var(--s-4);flex-wrap:wrap}
.lp-cab .next .lp-sub{font-size:var(--t-sm);margin-bottom:3px}
.lp-cab .next .when{font-family:var(--font-head);font-weight:700;font-size:26px;letter-spacing:-.02em;line-height:1.1}
.lp-cab .next .lp-btn{margin-left:auto;font-size:var(--t-sm)}
.lp-cab>.c .lp-meta{margin-bottom:var(--s-2)}
.lp-due{border:1px solid var(--line);border-radius:11px;padding:var(--s-3) 14px;display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap}
.lp-due .who{min-width:0}
.lp-due .lp-name{font-size:13.5px}
.lp-due .lp-prog{margin-left:auto;min-width:130px;gap:9px}
.lp-past{display:flex;flex-direction:column;gap:7px}
.lp-past .it{display:flex;align-items:center;gap:10px;padding:9px var(--s-3);font-size:var(--t-sm);color:var(--ink-2)}
.lp-past .it.bx{border:1px solid var(--line);border-radius:9px;color:var(--ink)}
.lp-past .it .lp-sub{margin-left:auto}
.lp-voc-head{display:flex;align-items:center;gap:7px}
.lp-voc-head .lp-mono{margin-left:auto;font-size:10px}
.lp-word{background:var(--surface);border:1px solid var(--line);border-radius:9px;padding:9px 11px;
  display:flex;flex-direction:column;gap:2px}
.lp-word .w{font-family:var(--font-head);font-weight:600;font-size:var(--t-base)}
.lp-voc-foot{margin-top:auto;display:flex;flex-direction:column;gap:7px}
.lp-voc-foot .lp-prog{gap:9px}
.lp-voc-foot .lp-prog .n{font-size:10px}

/* ---------- Сборка урока с нуля (#build) ----------
   Поле запроса набрано как настоящий текст преподавателя, а не как подпись
   к макету: в нём вся мысль блока — урок описывают словами. */
.lp-prompt{border:1px solid var(--line);border-radius:11px;background:var(--paper);padding:11px var(--s-3);margin-bottom:11px}
.lp-prompt p{margin:6px 0 0;font-size:var(--t-sm);line-height:1.5;color:var(--ink-2)}
/* Уровень и объём — не выбор на макете, а показ уже выбранного: подпись
   и значение рядом, как в настройке, которую преподаватель уже сделал. */
.lp-opts.gen{flex-direction:row;flex-wrap:wrap;align-items:center;gap:var(--s-2);margin-bottom:11px}
.lp-opt{display:inline-flex;align-items:center;gap:6px;font-family:var(--font-mono);
  font-size:10px;color:var(--muted)}
.lp-opt b{font-family:var(--font-body);font-size:11.5px;font-weight:600;color:var(--ink-2);
  background:var(--surface-2);border-radius:99px;padding:2px 9px}
/* Строка отчёта о сборке: замер, а не обещание */
.lp-run{display:flex;align-items:center;gap:var(--s-2);margin:0 0 10px}
.lp-run .a{color:var(--marker);font-size:var(--t-base);line-height:1}
.lp-run .lp-meta{letter-spacing:.06em;color:var(--marker-ink)}
.lp-res.gen{gap:6px}
.lp-res.gen .lp-chip{display:flex;align-items:center;gap:9px;padding:8px 11px}
.lp-res.gen .nn{font-family:var(--font-mono);font-size:10px;color:var(--muted);flex-shrink:0}
.lp-res.gen .lp-line{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-res.gen .cl{margin:0;flex-shrink:0}
/* На узком экране подпись поджимала текст задания до многоточия. В мобильном
   макете хендоффа этот блок сложен иначе: сначала само задание, под ним номер
   с подписью — так читается и то и другое. */
@media(max-width:620px){
  .lp-res.gen .lp-chip{flex-wrap:wrap;gap:3px 7px}
  .lp-res.gen .lp-line{flex:1 0 100%;order:-1;white-space:normal;overflow:visible;text-overflow:clip}
  /* «01 · карточки слов» одной строкой под заданием, как в мобильном макете */
  .lp-res.gen .cl::before{content:'· '}
  .lp-run .a{transform:rotate(90deg)}
}

/* ---------- Мобильный макет хендоффа ----------
   Мобильная версия в пакете сверстана отдельно, а не сжата из десктопной: там
   короче подписи и меньше второстепенных деталей в макетах. Держим это одной
   разметкой — иначе два файла разъедутся при первой же правке текста.

   .lp-de — то, что остаётся только на широком экране, .lp-mo — наоборот. */
.lp-mo{display:none}
@media(max-width:620px){
  .lp-de{display:none}
  .lp-mo{display:inline}

  /* Hero: расписание слева и подпись «ПОЛЯ» на телефоне уходят — в мобильном
     макете первый экран показывает сам урок и заметки к нему, без рабочего
     стола вокруг. */
  .lp-top .lp-desk>.l{display:none}
  .lp-top .lp-desk>.r>.lp-meta{display:none}

  /* Прогресс в панелях «У вас / У ученика»: на телефоне полосы дублируют друг
     друга дважды подряд и только шумят. */
  #live .lp-prog{display:none}

  /* Правило открытия у пройденного и текущего урока: состояние уже показано
     галочкой и точкой. У запертых правило остаётся — там дата и есть ответ
     на вопрос «когда». */
  #courses .lp-crs-row.done .r,#courses .lp-crs-row.now .r{display:none}

  /* Кабинет ученика: полоса словаря и остаток абонемента — детали, которые на
     узком экране только тянут карточку вниз. */
  #student .lp-voc-foot .lp-prog{display:none}
}

/* ---------- Курсы (#courses) ---------- */
.lp-course-t{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg);letter-spacing:-.01em;margin:2px 0 3px}
/* Подзаголовок внутри макета: отбивка сверху больше, чем снизу — так список
   читается как продолжение подписи, а не как отдельная плашка. */
.lp-meta.sec{margin:var(--s-4) 0 7px;letter-spacing:.08em}

.lp-crs{display:flex;flex-direction:column;gap:1px}
.lp-crs-row{display:flex;align-items:center;gap:9px;padding:7px 0;border-top:1px solid var(--line);font-size:var(--t-sm)}
.lp-crs-row:first-child{border-top:none}
.lp-crs-row .n{width:18px;flex-shrink:0;text-align:center;font-family:var(--font-mono);font-size:10px;color:var(--muted)}
.lp-crs-row .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-crs-row .r{font-family:var(--font-mono);font-size:10px;color:var(--muted);flex-shrink:0}
.lp-crs-row .lp-ok{font-size:11px;color:var(--ok);flex-shrink:0;width:12px;text-align:center}
/* Точка у текущего урока пульсирует, замок у запертых — нет: первое про
   «идёт сейчас», второе про «сюда пока нельзя». */
.lp-crs-row .lp-dot{width:7px;height:7px;border-radius:50%;background:var(--marker);flex-shrink:0;
  margin:0 3px;animation:lsnPulse 1.6s ease-in-out infinite}
.lp-lock{width:12px;flex-shrink:0;color:var(--muted);display:flex;align-items:center;justify-content:center}
.lp-lock svg{width:11px;height:11px;display:block}
.lp-crs-row.done .t{color:var(--muted)}
/* Текущий урок — единственная строка с акцентом: взгляд должен падать на «где
   ученик сейчас», а не пересчитывать галочки. */
.lp-crs-row.now{background:var(--marker-soft);border-radius:7px;margin:0 -7px;padding-left:7px;padding-right:7px;border-top-color:transparent}
.lp-crs-row.now .n{color:var(--marker-ink);font-weight:600}
.lp-crs-row.now .r{color:var(--marker-ink)}
/* Запертый показан, а не спрятан: скрытый читался бы как «курс короткий» */
.lp-crs-row.lock{opacity:.5}

.lp-who{display:flex;flex-direction:column;gap:9px}
.lp-who-row{display:flex;align-items:center;gap:9px;font-size:var(--t-sm)}
.lp-who-row .t{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.3}
.lp-who-row .t .s{font-size:10.5px;color:var(--muted)}
.lp-who-row .v{font-family:var(--font-mono);font-size:10.5px;color:var(--muted);flex-shrink:0}
/* Тот, кто встал, помечен цветом ошибки: экран курса отвечает на вопрос
   «кто застрял», и ответ должен быть виден раньше цифр. */
.lp-who-row.warn .t .s{color:var(--err)}
/* Жёлоб на светлой карточке свой: --lp-dark-track сделан для тёмного блока */
.lp-dtrack.sm{flex:0 0 54px;height:5px;border-radius:3px;background:var(--line)}
.lp-dtrack.sm>i{background:var(--marker)}
.lp-dtrack.sm>i.full{background:var(--ok)}

/* ---------- Плеер в блоке «одновременно» ----------
   Звук на занятии общий: нажал один — играет у обоих. Поэтому дорожка в обеих
   панелях идёт без задержки, в отличие от заметки над ней. */
.lp-audio{display:flex;align-items:center;gap:11px;background:var(--paper);border:1px solid var(--line);
  border-radius:11px;padding:9px var(--s-3);margin-top:9px}
.lp-audio .pl{width:22px;height:22px;border-radius:50%;background:var(--ink);color:var(--paper);
  font-size:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.lp-audio .b{flex:1;min-width:0}
.lp-audio .t{display:flex;align-items:center;gap:var(--s-2);margin-bottom:5px}
.lp-audio .nm{font-family:var(--font-head);font-weight:600;font-size:11.5px}
.lp-audio .tm{margin-left:auto;font-family:var(--font-mono);font-size:10px;color:var(--muted)}
.lp-audio .trk{height:4px;border-radius:2px;background:var(--line);overflow:hidden}
.lp-audio .trk>i{display:block;height:100%;width:35%;border-radius:2px;background:var(--marker)}

/* Раскладка держится на flex-wrap: колонки схлопываются сами. Медиазапросы
   нужны только внутренним сеткам макетов — в хендоффе они не решены. */
@media(max-width:1000px){.lp-sec{padding-top:88px}}
@media(max-width:760px){
  .lp-desk,.lp-cab{grid-template-columns:1fr;min-height:0}
  .lp-desk>.l,.lp-cab>.l{border-right:none;border-bottom:1px solid var(--line)}
  .lp-desk>.r,.lp-cab>.r{border-left:none;border-top:1px solid var(--line)}
  .lp-foot{margin-top:var(--s-3)}
  .lp-desk>.c .lp-prog{margin-top:var(--s-3)}
  .lp-voc-foot{margin-top:var(--s-3)}
}
@media(max-width:620px){
  .lp-sec{padding:80px var(--s-4) 0}
  .lp-sec-hero{padding-top:36px}
  .lp-head-in{padding:var(--s-3) var(--s-4);gap:10px}
  .lp-head nav{gap:var(--s-3)}
  .lp-row,.lp-row.lp-top{gap:36px}
  .lp-cta-sec{margin-top:72px;padding:0 var(--s-4)}
  .lp-footer{padding:28px var(--s-4) 48px}
  .lp-imp{flex-direction:column}
  .lp-src{flex:0 0 auto}
  .lp-arrow{flex:0 0 22px;animation:none;transform:rotate(90deg)}
  .lp-sheet,.lp-sheet-foot{margin-right:94px}
  .lp-sticky{width:80px}
  .lp-money{font-size:28px}
  /* «Подготовка юнита»: подпись (92px) и цифра (74px) на узком экране
     оставляли полосе прогресса ~65px, и заливка 11% на такой ширине выглядела
     оторванной точкой, а не полосой. Мобильный хендофф сужает те же колонки
     до 74/54px — этого достаточно, чтобы 11%-заливка снова читалась баром. */
  .lp-panel{padding:16px 17px;border-radius:13px}
  .lp-drow{gap:10px}
  .lp-drow .k{flex-basis:74px;font-size:var(--t-sm)}
  .lp-drow .v{flex-basis:54px;font-size:var(--t-label)}
  .lp-dnote{gap:10px;margin-top:16px}

  /* Типографика мобильной вёрстки. У неё в хендоффе свой ряд, а не нижняя
     граница десктопного clamp(): заголовки там мельче на 3–4px. Разница
     решает — на 393px «И работает на всех тарифах» неразрывной строкой при
     27px упиралась в край тёмного блока, хотя абзацы под ней заканчивались
     сильно левее, и блок читался кривым. При 23px строка встаёт на место. */
  /* 34px, а не 31px из хендоффа: на 31px «Lessona – AI-платформа» помещается
     в одну строку, и имя перестаёт стоять отдельно. На 34px перенос после
     «Lessona –» происходит сам, без принудительного <br> — а он здесь только
     вредит: text-wrap:pretty перебалансирует остаток и оставляет
     «AI-платформа» одинокой строкой. Сознательное отступление от макета. */
  .lp h1{font-size:34px}
  .lp h2{font-size:24px}
  /* 23px только у блока про тарифы: там неразрывная фраза, которой на 24px
     не хватает ширины. Финальный призыв переносится свободно и идёт как все. */
  .lp h2.on-dark{font-size:23px}
  .lp-dark.end h2.on-dark{font-size:24px}
  .lp-lead{font-size:var(--t-lg)}
  .lp-body{font-size:15px}
  .lp-txt p{font-size:14.5px}
  .lp-txt p.lp-quiet{font-size:13.5px}
  .lp-dark{padding:26px 22px;border-radius:18px}
  .lp-dark.end{padding:26px 22px}
}

/* Анимации макетов. Общий цикл 9с — он и создаёт впечатление живого продукта,
   поэтому длительности и задержки перенесены из хендоффа как есть. */
@keyframes lsnScan{0%{transform:translateY(-6px);opacity:0}6%{opacity:1}42%{transform:translateY(148px);opacity:1}54%{opacity:0}100%{transform:translateY(148px);opacity:0}}
@keyframes lsnRise{0%,6%{opacity:0;transform:translateY(9px)}16%,88%{opacity:1;transform:none}97%,100%{opacity:0;transform:translateY(-5px)}}
@keyframes lsnPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.82)}}
@keyframes lsnBlink{0%,45%{opacity:1}46%,100%{opacity:0}}
@keyframes lsnGrow{0%,12%{width:0}44%,88%{width:100%}98%,100%{width:0}}
@keyframes lsnCyc{0%{opacity:0}2%,35%{opacity:1}38%,98%{opacity:0}100%{opacity:0}}
@keyframes lsnNote{0%,10%{opacity:0;transform:translate(8px,12px) rotate(-7deg)}22%{opacity:1;transform:translate(0,0) rotate(-3deg)}52%{opacity:1;transform:translate(0,0) rotate(-3deg)}68%,88%{opacity:1;transform:translate(-7px,-14px) rotate(-1deg)}98%,100%{opacity:0;transform:translate(-7px,-14px) rotate(-1deg)}}
@keyframes lsnBar{0%,8%{transform:scaleY(.12)}34%,100%{transform:scaleY(1)}}
@keyframes lsnTick{0%,34%{opacity:0;transform:scale(.5)}44%,90%{opacity:1;transform:scale(1)}99%,100%{opacity:0;transform:scale(1)}}
@keyframes lsnDim{0%,46%{opacity:1}58%,100%{opacity:.16}}
@keyframes lsnNudge{0%,100%{transform:translateX(0)}50%{transform:translateX(5px)}}

/* ---------- Заготовки: библиотека кусков урока ---------- */
.sn-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:var(--s-3)}
.sn-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-4) var(--s-4)}
.sn-card .snc-head{display:flex;align-items:flex-start;gap:var(--s-2);margin-bottom:var(--s-3)}
.sn-card .snc-name{font-family:var(--font-head);font-weight:700;font-size:var(--t-md);line-height:1.3}
.sn-card .snc-meta{font-family:var(--font-mono);font-size:var(--t-label);letter-spacing:.06em;color:var(--muted);margin-top:3px}
.snc-blocks{display:flex;flex-direction:column;gap:var(--s-1);border-top:1px solid var(--line);padding-top:var(--s-3)}
.snc-block{display:flex;align-items:center;gap:var(--s-2);font-size:var(--t-sm);min-width:0}
.snc-ic{width:18px;height:18px;flex-shrink:0;color:var(--ink)}
.snc-ic svg{width:16px;height:16px;display:block}
.snc-type{font-family:var(--font-head);font-weight:600;flex-shrink:0}
.snc-sum{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* Режим выбора блоков в конструкторе */
.bpick{width:16px;height:16px;border:2px solid var(--line-2);border-radius:5px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;font-size:10px;color:var(--paper);font-weight:700}
.bpick.on{border-color:var(--ink);background:var(--ink)}
.block.picked{border-color:var(--ink);box-shadow:0 0 0 2px var(--surface-2)}
.select-bar{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:120;
  display:flex;align-items:center;gap:var(--s-3);background:var(--surface);border:1px solid var(--line-2);
  border-radius:99px;padding:var(--s-2) var(--s-3);box-shadow:0 12px 34px -12px rgba(23,26,33,.4)}
.select-bar .sb-text{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);white-space:nowrap}
.icon-btn svg{width:15px;height:15px;display:block}

/* ---------- Карточка ученика: рабочее досье ----------
   Слева профиль, справа вкладками занятия, домашние, словарь и приватные заметки. */
.stu-grid{display:grid;grid-template-columns:290px minmax(0,1fr);gap:var(--s-5);align-items:start}
.stu-panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-4);position:sticky;top:74px}
.stu-panel .sp-head{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-4)}
.stu-panel .sp-name{font-family:var(--font-head);font-weight:700;font-size:17px;letter-spacing:-.01em}
.sp-facts{display:flex;flex-direction:column;gap:var(--s-3);padding:var(--s-3) 0;border-top:1px solid var(--line)}
.sp-fact{display:flex;flex-direction:column;gap:2px;font-size:var(--t-base)}
.sp-balance{border-top:1px solid var(--line);padding-top:var(--s-3);margin-top:3px}
.sp-bal-n{font-family:var(--font-head);font-weight:700;font-size:20px;letter-spacing:-.02em}
/* Полоса расхода абонемента нейтральная: это остаток пакета, а не успех
   ученика — зелёным здесь хвалить нечего. Кончился — цвет ошибки. */
.sp-balance .bar>span{background:var(--ink-2)}
.sp-balance .bar.low>span{background:var(--err)}
.sp-note-line{margin-top:var(--s-3);background:var(--marker-soft);color:var(--marker-ink);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-sm)}
.sp-note-line a{color:inherit;font-weight:700}
.stu-panel .field{margin-bottom:var(--s-3)}

.pt-nav{display:flex;gap:3px;border-bottom:1px solid var(--line);margin-bottom:var(--s-4);overflow-x:auto}
.pt-nav button{border:none;background:transparent;padding:var(--s-2) var(--s-3);border-bottom:2px solid transparent;margin-bottom:-1px;
  font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--muted);cursor:pointer;white-space:nowrap;
  display:inline-flex;align-items:center;gap:var(--s-2)}
.pt-nav button:hover{color:var(--ink)}
.pt-nav button.on{color:var(--ink);border-bottom-color:var(--ink)}
.pt-count{background:var(--surface-2);color:var(--muted);border-radius:99px;font-family:var(--font-mono);font-size:var(--t-label);padding:1px var(--s-1)}
.pt-nav button.on .pt-count{background:var(--ink);color:var(--paper)}

/* Приватные заметки об ученике */
.sn-add{display:flex;gap:var(--s-2);align-items:flex-start;margin-bottom:var(--s-3)}
.sn-add textarea{flex:1;border:1px solid var(--line-2);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-md);background:var(--surface);resize:vertical;line-height:1.5}
.sn-add textarea:focus{outline:none;border-color:var(--ink)}
.sn-item{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-4);margin-bottom:var(--s-2)}
.sn-item.editing{border-color:var(--ink)}
.sn-item textarea{width:100%;border:1px solid var(--line-2);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-md);background:var(--paper);resize:vertical;line-height:1.6}
.sn-text{font-size:14.5px;line-height:1.6}
.sn-meta{display:flex;align-items:center;gap:var(--s-1);margin-top:var(--s-2)}
.sn-meta .eyebrow{flex:1}

@media(max-width:900px){
  .stu-grid{grid-template-columns:minmax(0,1fr)}
  .stu-panel{position:static}
}

/* ---------- Очередь проверки ----------
   Слева колонка работ, справа сама работа. Экран рабочий: преподаватель идёт
   подряд, «Проверено, дальше» ведёт к следующей без возврата в список. */
.review-grid{display:grid;grid-template-columns:262px minmax(0,1fr);align-items:start;min-height:calc(100vh - 56px)}
.review-list{border-right:1px solid var(--line);padding:var(--s-4);position:sticky;top:56px;max-height:calc(100vh - 56px);overflow-y:auto;display:flex;flex-direction:column}
/* Список работ: заголовок, карточки, массовое действие прижато к низу колонки —
   «принять всё» это выход из очереди, а не первый шаг в ней. */
.review-list .rl-head{display:flex;align-items:center;gap:var(--s-2);margin-bottom:var(--s-3)}
.rl-title{font-family:var(--font-head);font-weight:700;font-size:var(--t-lg)}
.review-list .rl-head .count-pill{margin-left:auto}
.rl-item{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);
  padding:10px var(--s-3);margin-bottom:var(--s-2);cursor:pointer}
.rl-item:hover{border-color:var(--line-2)}
.rl-item.on{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink)}
.rl-item .rl-name{display:block;font-family:var(--font-head);font-weight:600;font-size:13.5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rl-item .rl-lesson{display:block;font-size:12px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rl-bulk{margin-top:auto;width:100%;justify-content:center}
.review-work{padding:var(--s-5) var(--s-5) 90px;min-width:0}
.rw-top{display:flex;align-items:baseline;gap:var(--s-3);margin-bottom:var(--s-4);flex-wrap:wrap}
.rw-title{font-family:var(--font-head);font-weight:700;font-size:17px;letter-spacing:-.015em}
.rw-sub{font-size:var(--t-sm);color:var(--muted);flex-shrink:0}

/* ---------- Одна анатомия ответа на все 19 типов (хендофф v2) ----------
   Показ ответа складывался по одному блоку и в каждом типе выглядел по-своему:
   где-то плашки, где-то список, где-то «верно: …» строкой. Теперь рамка общая —
   шапка с номером, типом и вердиктом, под ней две колонки «что ответил» и
   «как правильно», — а тип задания меняет только содержимое колонок. */
.rw-item{border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:var(--s-3) var(--s-4);margin-bottom:var(--s-3);display:flex;flex-direction:column;gap:var(--s-2)}
/* Задание, которое ждёт живой оценки, стоит на бумаге: рядом с автопроверенными
   белыми карточками оно так само отделяется, без рамки-акцента. */
.rw-item.open{background:var(--paper)}
.rw-head{display:flex;align-items:center;gap:var(--s-2)}
.rw-num{font-family:var(--font-mono);font-weight:600;font-size:var(--t-label);color:var(--ink-2);
  background:var(--surface-2);border-radius:6px;padding:2px var(--s-2);flex-shrink:0}
.rw-instr{font-family:var(--font-head);font-weight:600;font-size:13.5px;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Вердикт — плашка, а не цветное слово: у трёх исходов три роли, и «нужна
   оценка» это не ошибка, а работа, которая ещё впереди. */
.rw-verdict{margin-left:auto;flex-shrink:0;font-family:var(--font-head);font-weight:600;
  font-size:11px;border-radius:99px;padding:var(--s-1) var(--s-3);white-space:nowrap}
.rw-verdict.ok{background:var(--ok-bg);color:var(--ok)}
.rw-verdict.err{background:var(--err-bg);color:var(--err)}
.rw-verdict.wait{background:var(--marker-soft);color:var(--marker-ink)}
.rw-verdict.none{background:var(--surface-2);color:var(--muted)}
.rw-cols{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-3)}
@media(max-width:720px){.rw-cols{grid-template-columns:1fr}}
.rw-col-label{font-family:var(--font-mono);font-weight:600;font-size:10px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-bottom:var(--s-1)}
.rw-val{font-size:var(--t-md);line-height:1.5}
/* Правая колонка — справка, а не второй ответ: приглушена целиком */
.rw-val.right,.rw-val.right *{color:var(--muted)}
.rw-question{font-size:13.5px;color:var(--ink-2);line-height:1.5}
.rw-open-text{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);font-size:14.5px;line-height:1.6}
.rw-grade{display:flex;gap:var(--s-2);margin-top:var(--s-3);align-items:flex-start;flex-wrap:wrap}
.rw-grade .rw-score{width:110px;flex-shrink:0;border:1px solid var(--line-2);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface)}
.rw-grade .rw-comment{flex:1;min-width:180px;border:1px solid var(--line-2);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-base);background:var(--surface);resize:vertical;line-height:1.5}
.rw-grade .rw-score:focus,.rw-grade .rw-comment:focus{outline:none;border-color:var(--ink)}

.rw-foot{display:flex;align-items:flex-end;gap:var(--s-3);flex-wrap:wrap;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s-4) var(--s-4);margin-top:var(--s-4)}
.rw-foot .btn{padding:var(--s-3) var(--s-5)}

/* Ответ ученика — только чтение, преподаватель не может ответить за него */
.ans-row{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.ans-list{display:flex;flex-direction:column;gap:var(--s-1)}
.ans-line{font-size:var(--t-base);line-height:1.5}
/* Ответ «Слова и картинки» — миниатюрой: номер фотографии был из перемешанного
   порядка ученика и преподавателю ничего не скажет. Рядом с неверной показана
   правильная, приглушённая, как подсказка «должно было быть так». */
.ans-thumb{width:34px;height:34px;object-fit:cover;border-radius:6px;flex-shrink:0;border:2px solid transparent}
.ans-thumb.ok{border-color:var(--ok)}
.ans-thumb.err{border-color:var(--err)}
.ans-thumb.hint-thumb{opacity:.45;border-style:dashed;border-color:var(--line-strong)}
.ans-gap{display:inline-flex;align-items:center;gap:var(--s-1);font-size:var(--t-base);color:var(--muted)}
.ans-chip{display:inline-block;border-radius:7px;padding:3px var(--s-3);font-weight:600;font-size:var(--t-base);border:1px solid var(--line-2);background:var(--paper)}
.ans-chip.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)}
.ans-chip.err{border-color:var(--err);background:var(--err-bg);color:var(--err)}
.ans-chip.miss{border-style:dashed;color:var(--muted)}
.ans-correct{font-size:var(--t-sm);color:var(--ok)}
.ans-empty{font-size:var(--t-base);color:var(--muted);font-style:italic}
.ans-legend{font-size:11.5px;color:var(--muted)}

@media(max-width:1100px){
  .review-grid{grid-template-columns:minmax(0,1fr)}
  .review-list{position:static;max-height:none;border-right:none;border-bottom:1px solid var(--line);display:flex;gap:var(--s-2);overflow-x:auto;padding:var(--s-3) var(--s-3)}
  .review-list .rl-head{display:none}
  .rl-item{width:auto;min-width:200px;flex-shrink:0;margin:0}
  .review-work{padding:var(--s-4) var(--s-4) 80px}
}

/* ---------- Полоса режима просмотра урока ----------
   Узкая, чтобы не спорить с уроком: чей это режим, что ответы не сохраняются,
   и два выхода — в конструктор и обратно в каталог. */
.preview-bar{position:sticky;top:0;z-index:60;display:flex;align-items:center;gap:var(--s-3);
  background:var(--surface);border-bottom:1px solid var(--line);padding:var(--s-2) var(--s-4);min-height:44px}
.preview-bar .pb-label{font-family:var(--font-mono);font-size:var(--t-label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);white-space:nowrap}
.preview-bar .pb-title{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
.preview-bar .pb-seg{margin-bottom:0;flex-shrink:0}
.preview-bar .pb-actions{margin-left:auto;display:flex;gap:var(--s-2);flex-shrink:0}
@media(max-width:700px){.preview-bar .pb-title{display:none}}
/* На телефоне от подписи остаётся «Просмотр»: с полной фразой полоса вместе с
   кнопками не влезала в ширину экрана и уводила урок в боковую прокрутку. */
@media(max-width:560px){.preview-bar .pb-note{display:none}}

/* ---------- «Сегодня»: домашняя преподавателя ---------- */
/* Карточка ближайшего занятия — единственная на экране с тенью: это то, ради
   чего страницу открывают. Лицо 64px, чтобы узнавать с одного взгляда, и
   остаток абонемента прямо в подписи — за ним больше не надо идти в профиль. */
.now-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s-4);margin-bottom:var(--s-3);box-shadow:0 6px 20px rgba(23,26,33,.06)}
/* «Единственная карточка с тенью» — в тёмном хроме тень чёрная на чёрном, то
   есть её нет, и карточка занятия переставала выделяться совсем. Кантом. */
html[data-chrome="dark"] .now-card{box-shadow:0 0 0 1px rgba(255,255,255,.09)}
.now-card.is-live{border-color:var(--marker);box-shadow:0 0 0 3px var(--marker-soft)}
/* Карточка держит ширину контейнера — на «Расписании» её правый край совпадает
   с краем строк дня под ней, на «Сегодня» — с краем боковой колонки.

   У отсчёта постоянное место: правый верхний угол карточки. Он стоял то сразу
   за подписью, то у края — в зависимости от длины названия урока, — и каждый раз
   его приходилось искать заново. Угол не зависит ни от чего: пришёл на экран,
   посмотрел в одну точку. */
.now-card .nc-head{display:grid;grid-template-columns:64px minmax(0,1fr) auto;gap:var(--s-4);align-items:center}
.now-card .nc-body{min-width:0}
.now-card .until,.now-card .nc-badge{align-self:start}
/* Лицо в главной карточке — на чернилах, а не на подложке: оно тут якорь всего
   экрана, и светло-серый кружок эту роль не держал. */
.now-card .stu-ava{width:64px;height:64px;font-size:20px;
  background:linear-gradient(135deg,var(--ink-2),var(--ink));color:var(--paper)}
.now-card .nc-title{font-family:var(--font-head);font-weight:700;font-size:17px;letter-spacing:-.015em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.now-card .nc-sub{font-size:var(--t-sm);color:var(--muted);margin-top:2px}
.now-card .nc-right{display:flex;flex-direction:column;align-items:flex-end;gap:var(--s-2)}
/* На телефоне отсчёт и кнопки уходят под текст: втроём в ряд они оставляли
   названию урока восемьдесят пикселей. */
@media(max-width:560px){
  .now-card .nc-head{grid-template-columns:48px minmax(0,1fr);gap:var(--s-3)}
  .now-card .stu-ava{width:48px;height:48px;font-size:var(--t-lg)}
  /* .until/.nc-badge — третья колонка сетки, а на телефоне колонок только две:
     без явного grid-column элемент садился в первую, узкую (48px) колонку под
     лицом и вылезал текстом «через 2 дня» за её пределы. Отдаём ему вторую
     строку целиком, рядом с лицом, а не поверх текста. */
  .now-card .until,.now-card .nc-badge{grid-column:2;grid-row:2}
  .now-card .nc-actions{justify-content:flex-start}
}
.now-card .nc-badge{display:inline-flex;align-items:center;gap:var(--s-1);background:var(--marker-soft);color:var(--marker-ink);border-radius:99px;padding:3px var(--s-3);font-family:var(--font-head);font-weight:700;font-size:11.5px;white-space:nowrap}
.now-card .nc-progress{margin-bottom:var(--s-3)}
.now-card .nc-progress .bar{margin-top:0}

/* ---------- Кабинет ученика: «когда» крупно (хендофф v2, Р-3) ----------
   Компоненты общие с преподавательскими, отличается масштаб и порядок, не язык.
   У преподавателя главное в карточке — с кем занятие, поэтому там лицо 64px;
   у ученика преподаватель один, и главное — когда. «Сегодня, 19:15» — самый
   крупный текст экрана, ради этой строки кабинет и открывают. */
.next-card{display:flex;flex-direction:column;gap:10px;padding:20px}
.next-card .eyebrow{display:flex;align-items:center;gap:6px}
.next-card .nc-when{font-family:var(--font-head);font-weight:700;font-size:28px;
  line-height:1.15;letter-spacing:-.01em}
.next-card .nc-what{font-size:13.5px;color:var(--ink-2)}
.next-card .nc-actions{justify-content:flex-start;margin-top:var(--s-1)}
/* На телефоне «Войти в класс» тянется во всю оставшуюся ширину: это
   единственное действие первого экрана, и мельчить ему незачем. На большом
   экране карточка шириной с полосу — растянутая кнопка была бы во весь стол. */
@media(max-width:640px){
  .next-card .nc-actions .btn.primary{flex:1;justify-content:center}
}

/* Свой абонемент в кабинете ученика: остаток занятий и полоса расхода — та же,
   что у преподавателя, с тем же светофором. Цены здесь нет и быть не должно. */
.sub-card{display:flex;flex-direction:column;gap:6px}
.sub-card .sub-left{font-family:var(--font-head);font-weight:600;font-size:var(--t-md)}
.sub-card .bar{margin:2px 0 2px}
.sub-card .sub-warn{color:var(--err);margin-top:2px}

/* Слова с прошлого занятия — плашками маркером. Правило «жёлтое = заметки и
   выделения» здесь не нарушено, а исполнено: это и есть выделения с полей
   урока, просто собранные в одно место. */
.deck-chips{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-bottom:var(--s-1)}
.deck-word{background:var(--marker-soft);color:var(--marker-ink);border-radius:99px;
  padding:6px var(--s-3);font-size:var(--t-base)}
.deck-more{background:none;border:1px dashed var(--line-2);color:var(--muted);
  border-radius:99px;padding:6px var(--s-3);font-size:var(--t-base);font-family:inherit;cursor:pointer}
.deck-more:hover{border-style:solid;color:var(--ink)}

/* Отсчёт до занятия — mono, как всё измеримое на платформе. Без плашки: в
   карточке он и так стоит один в своём углу, а обводка делала из него кнопку. */
.until{font-family:var(--font-mono);font-weight:600;font-size:var(--t-md);color:var(--ink-2);
  white-space:nowrap;flex-shrink:0}
/* Кнопки карточки — слева, под сведениями о занятии, а не прижаты к правому
   краю: в широкой карточке между «Открыть класс» и тем, к чему она относится,
   лежала половина экрана, а слева стояла пустота. */
.nc-actions{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;justify-content:flex-start}
.now-card .nc-actions{margin-top:var(--s-3)}

/* ---------- Рабочий стол «Сегодня»: главная колонка и боковая ----------
   Было две равные половины, и в день с пустой очередью проверки левая стояла
   пустой рамкой в пол-экрана, пока справа лежали абонементы. Теперь колонки
   разного веса: слева ход дня (занятие, лента, кто выпадает), справа — что
   ждёт (проверка, абонементы, забытые отметки). Главная уже, чем весь экран,
   поэтому карточка занятия перестала растягиваться на всю ширину. */
.desk{display:grid;grid-template-columns:1.6fr 1fr;gap:var(--s-4);align-items:start}
.desk-main,.desk-side{display:flex;flex-direction:column;gap:var(--s-4);min-width:0}
/* Внутри секции отступы прежние; обнуляем только последний, иначе к зазору
   колонки прибавляется хвостовой margin блока и секции разъезжаются. */
.desk-main>section>:last-child,.desk-side>section>:last-child{margin-bottom:0}
/* Схлопывается раньше, чем боковая колонка становится теснее своих строк:
   в «Без отметки» у строки два действия, и в колонке уже ~320px они не стоят. */
@media(max-width:1100px){.desk{grid-template-columns:1fr}}

/* Панель — карточка со своим заголовком и плотным списком внутри */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s-4);display:flex;flex-direction:column;gap:var(--s-2)}
.panel-head{display:flex;align-items:center;gap:var(--s-2);font-family:var(--font-head);
  font-weight:600;font-size:var(--t-lg)}
.panel-head .count-pill{margin-left:auto}

/* Строка внутри панели: та же анатомия, но плотнее — панель уже сама карточка,
   и вторая рамка внутри неё лишняя. Разделяет волосяная линия. */
.row.tight{background:transparent;border:none;border-bottom:1px solid var(--surface-2);
  border-radius:0;padding:var(--s-2) 0;margin:0;grid-template-columns:40px minmax(5rem,1fr) auto;gap:var(--s-3)}
.row.tight:last-child{border-bottom:none}
.row.tight:hover{border-color:transparent;border-bottom-color:var(--surface-2)}
.row.tight.bare{grid-template-columns:minmax(5rem,1fr) auto}
/* Строка с двумя действиями в узкой колонке: кнопки встают под именем, а не
   рядом. В боковой колонке «Провести» и «Не состоялось» занимают её половину, и
   имени оставалось на «Pet…» — но выбирать исход занятия по обрезанному имени
   как раз и нельзя. Под именем места ровно столько же, сколько у самой строки. */
.row.tight.stack{grid-template-columns:40px minmax(0,1fr)}
.row.tight.stack>.r-side,.row.tight.stack>.r-act{grid-column:2;justify-content:flex-start}
.row.tight .stu-ava{width:36px;height:36px;font-size:12px}
.row.tight .r-title{font-size:13.5px}
.row.tight .r-sub{font-size:12px}
.row.tight .r-time{font-size:12px}

/* Хвост ленты занятий: тихая строка, а не ссылка акцентом — это подпись, что
   дальше смотреть в расписании, а не главное действие экрана. */
.more-line{font-size:var(--t-sm);color:var(--muted);padding:2px 14px;background:none;border:none;
  cursor:pointer;text-align:left;font-family:var(--font-body)}
.more-line:hover{color:var(--ink-2)}
/* Статус и инструменты — в колонках постоянной ширины. У .row две последние
   колонки auto, каждая строка — своя сетка, и ширина этих колонок считалась по
   содержимому строки: «проведено», «через 2 дня» и «отменено» разной длины, а
   у проведённого занятия на одну кнопку меньше. Из-за этого статусы вставали
   лесенкой — у каждой строки на своём месте. Теперь у всех на одном, по левому
   краю своей колонки. */
.sch-row{grid-template-columns:44px minmax(6rem,1fr) 190px auto}
/* Статус — одной строкой и по левому краю колонки: он читается как столбец, и
   начало у всех строк на одной вертикали. Переносить нечего — колонка
   рассчитана на самую длинную пару «статус + плашка». */
.sch-row .r-side{justify-content:flex-start;flex-wrap:nowrap;white-space:nowrap}
/* Исход занятия и инструменты — одной группой справа. Кнопки исхода видны
   всегда, значки правки проявляются по наведению; вместе они переносятся на
   вторую строку, когда колонке тесно, а не выдавливают имя ученика. */
.sch-acts{display:flex;align-items:center;justify-content:flex-end;gap:var(--s-2);flex-wrap:wrap}
.sch-row .sch-tools{display:flex;gap:3px;justify-content:flex-end;flex-shrink:0}
/* У ученика ни кнопок исхода, ни инструментов нет — колонку под них не держим */
.sch-row:not(:has(.sch-acts)){grid-template-columns:44px minmax(6rem,1fr) 190px auto}
.sch-row.past{opacity:.6}
.sch-row.off .r-title{text-decoration:line-through}

/* Лента строк: контейнера-карточки больше нет — строка .row сама себе граница */
.day-list{margin-bottom:var(--s-3)}

.count-pill{background:var(--marker-soft);color:var(--marker-ink);border-radius:99px;font-family:var(--font-mono);font-size:var(--t-label);padding:1px var(--s-2);font-weight:500}
.more-link{background:none;border:none;color:var(--accent);font-family:var(--font-head);font-weight:600;font-size:var(--t-base);cursor:pointer;padding:var(--s-1) 0}
.more-link:hover{text-decoration:underline}



/* ---------- «Оплаты»: доход по месяцам ----------
   Единственный раздел, где месяц листается назад: это отчёт, а не рабочий стол.
   Сумма в строке набрана заголовочным шрифтом и стоит справа — по суммам идут
   глазами, а не по именам. Цветом деньги не выделяем: маркер закреплён за
   заметками, и «доход» не повод его занимать. */
.month-nav{display:flex;align-items:center;gap:var(--s-1)}
.month-nav .mn-label{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);
  min-width:104px;text-align:center;text-transform:capitalize}
.month-nav .icon-btn:disabled{opacity:.3;cursor:default}
.month-nav .icon-btn:disabled:hover{background:none;color:var(--muted);border-color:transparent}

.pay-row{display:flex;align-items:center;gap:var(--s-3);background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-3) var(--s-3);margin-bottom:var(--s-2)}
.pay-row .t{font-family:var(--font-head);font-weight:600;font-size:var(--t-md)}
.pay-row .s{font-size:var(--t-sm);color:var(--muted);margin-top:1px}
.pay-sum{font-family:var(--font-head);font-weight:700;font-size:15px;letter-spacing:-.01em;
  white-space:nowrap;flex-shrink:0}
/* Доход не от ученика — вместо аватара нейтральный значок */
/* Расход пакета в строке оплаты: полоса и подпись под ней */
.pay-used{display:flex;flex-direction:column;align-items:flex-end;gap:3px;min-width:120px}
.pay-used .bar{width:110px;margin:0}
.pay-ext{width:28px;height:28px;border-radius:50%;background:var(--surface-2);color:var(--muted);
  display:flex;align-items:center;justify-content:center;font-family:var(--font-head);
  font-weight:700;font-size:12px;flex-shrink:0}

/* Состояние обрыва связи во время занятия */
/* ---------- Сплэш загрузки класса ----------
   Занятие открывается с запросом к серверу, и до ответа страница была белым
   листом — на живом уроке это самые тревожные полторы секунды. Здесь тот же
   мотив «Поле», собранный на глазах: линия прочерчивается, стикер приклеивается.
   Разметка лежит в class.html, поэтому видна сразу, ещё до первого скрипта.
   Заставка помечена .unthemed: applyTheme успевает покрасить body раньше, чем
   она снимается, и без этого шрифт и бумага на секунду уезжали в тему урока. */
.class-splash{position:fixed;inset:0;z-index:100;background:var(--paper);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-4)}
.class-splash .cs-glyph{position:relative;width:72px;height:72px}
.class-splash .cs-glyph::before{content:'';position:absolute;top:0;bottom:0;left:40%;width:1.5px;
  background:var(--line-2);transform-origin:top;animation:csLine .5s ease-out both}
.class-splash .cs-glyph::after{content:'';position:absolute;left:calc(40% - 14px);top:20px;
  width:34px;height:34px;background:var(--marker);border-radius:4px;
  animation:csStick .4s cubic-bezier(.34,1.3,.64,1) .35s both}
.class-splash .cs-t{font-family:var(--font-head);font-weight:600;font-size:var(--t-base);color:var(--muted)}
@keyframes csLine{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes csStick{from{transform:rotate(-14deg) scale(.6);opacity:0}
  to{transform:rotate(-4deg) scale(1);opacity:1}}
/* Без анимации мотив всё равно собран: обе части на месте и в конечном виде */
@media (prefers-reduced-motion:reduce){
  .class-splash .cs-glyph::after{transform:rotate(-4deg)}
}

.conn-lost{background:var(--surface);border:1px solid var(--err-line);border-radius:var(--radius);padding:var(--s-3) var(--s-4);margin-bottom:var(--s-4)}
.conn-lost .lbl{display:flex;align-items:center;gap:var(--s-2);font-family:var(--font-mono);font-size:var(--t-label);letter-spacing:.12em;text-transform:uppercase;color:var(--err);font-weight:500}
.conn-lost .lbl .dot{width:8px;height:8px;border-radius:50%;background:var(--err);animation:pulse 1.5s infinite}
.conn-lost .t{font-family:var(--font-head);font-weight:700;font-size:15px;margin:var(--s-2) 0 var(--s-1)}
.conn-lost .s{font-size:var(--t-base);color:var(--muted);line-height:1.5}
.conn-lost .btn{margin-top:var(--s-3)}

.mobile-nav{display:none}
@media(max-width:640px){
  /* Граница с содержимым — сильной линией: под полосу уезжает текст страницы, а
     её собственный фон отличается от бумаги мягко, и в тёмном хроме полоса
     переставала быть краем экрана. */
  .mobile-nav{display:grid;grid-template-columns:repeat(4,1fr);position:fixed;left:0;right:0;bottom:0;
    z-index:50;background:var(--surface);border-top:1px solid var(--line-2)}
  /* Где ты сейчас — верхней рамкой чернилами: подчёркивание сверху читается как
     вкладка, а закраска пункта — как нажатая кнопка. */
  .mobile-nav button,.mobile-nav a{border:none;border-top:2px solid transparent;background:transparent;
    color:var(--muted);font-family:var(--font-head);font-weight:600;font-size:11px;
    padding:var(--s-3) 0;text-align:center;cursor:pointer;text-decoration:none}
  .mobile-nav button.on{color:var(--ink);border-top-color:var(--ink)}
  .cab{padding-bottom:80px}
  .cab-nav{display:none}
  /* на телефоне нижняя навигация заменяет меню — не дублируем */
  .app.with-mobile-nav>.sidebar{display:none}
  .app.with-mobile-nav .page{padding-bottom:80px}
}

/* Шапка конструктора и класса несёт сразу и путь, и все действия страницы: там
   и состояние урока, и заготовка, и стиль, и оба входа к модели. Когда ряд
   перестаёт помещаться, он переносится на вторую строку, а не уезжает за край —
   боковая прокрутка страницы хуже, чем шапка в два этажа. */
@media(max-width:1280px){
  body>.topbar{height:auto;min-height:56px;flex-wrap:wrap;row-gap:var(--s-2);
    padding-top:var(--s-2);padding-bottom:var(--s-2)}
  .top-actions{flex-wrap:wrap;row-gap:var(--s-2)}
}

/* ---------- Шапка страницы без меню на телефоне ----------
   На занятии в шапке собирается больше всего: знак, путь до ученика, название
   урока, присутствие, поиск слова, смена материала, выход. В 375px этот ряд не
   встаёт и просто уезжал за край экрана — страницу приходилось отдалять
   пальцами. Путь сворачиваем до возврата (с кем ты в комнате, говорит плашка
   присутствия), а ряду действий разрешаем перенос — на случай, если и после
   этого тесно. */
@media(max-width:640px){
  body>.topbar{height:auto;min-height:56px;flex-wrap:wrap;row-gap:var(--s-2);
    padding-top:var(--s-2);padding-bottom:var(--s-2)}
  body>.topbar .brand,body>.topbar .top-sep,
  body>.topbar .top-step,body>.topbar .top-back~.top-back{display:none}
  /* Ряд действий начинается с нулевой ширины и потому остаётся на одной строке с
     возвратом, а переносится уже внутри себя: иначе он целиком уходил на свою
     строку и шапка вырастала в три этажа поверх урока. */
  .top-actions{flex-wrap:wrap;row-gap:var(--s-2);flex:1 1 0;min-width:0}
  /* Строка поиска слова из шапки уходит: она шире всех кнопок вместе взятых, а
     слово в уроке и так ищется выделением (initLookup), не набором. */
  body>.topbar .ws-host{display:none}
  .top-actions .presence{flex-shrink:1;min-width:0}
}

/* ---------- Строка на телефоне: в две полосы ----------
   Рядом имя, статус и кнопки на 375px не стоят. Сетка отдавала место правым
   колонкам — они «auto» и меряются по содержимому, — и от имени оставалось
   «Ал…», а строка вдобавок вылезала за край экрана: страницу приходилось
   отдалять. Флекс с переносом кладёт лицо и имя в первую полосу, статус и
   действия — во вторую, и обрезать больше нечего. */
@media(max-width:640px){
  .row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2) var(--s-3);padding:10px 12px}
  .row>.r-anchor,.row>.r-time{flex:0 0 auto}
  /* имя забирает остаток первой полосы, поэтому всё, что за ним, переносится */
  .row>.r-main{flex:1 1 60%;min-width:0}
  /* вторая полоса: статус и кнопки идут подряд и не растягиваются на всю ширину */
  .row>.r-side{flex:0 1 auto;justify-content:flex-start;flex-wrap:wrap;white-space:normal}
  .row>*{min-width:0}
  .sch-row .r-side{flex-wrap:wrap;white-space:normal}
}

@media(max-width:1079px){.sticky.aside{margin:0 0 var(--s-3)}}
@media(max-width:960px){
  .workspace,.class-grid,.cab{grid-template-columns:minmax(0,1fr)}
  .rail,.tpanel,.cab-nav{position:static;max-height:none}
  .rail{flex-direction:column}
  .rail-list{max-height:230px}
  .cab-nav{flex-direction:row;overflow:auto;gap:var(--s-1)}
  .cover-grid{grid-template-columns:1fr 1fr}
  .match-cols{gap:var(--s-5)}
  .drawer{width:100%}
  .top-title{display:none}   /* на телефоне в панели помещается только возврат */
  /* Своё имя на узком экране убираем: кнопка «Выйти» рядом и так говорит, чей
     это вход. */
  .top-user{display:none}
}

/* ---------- Курсы ---------- */
/* Две колонки: из чего курс состоит и кто его проходит. На узком экране
   встают друг под друга — «проходят» ниже, потому что сначала собирают курс,
   а потом записывают. */
.course-cols{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:18px;align-items:start}
@media (max-width:900px){.course-cols{grid-template-columns:1fr}}

.crs-list{display:flex;flex-direction:column}
.crs-row{display:flex;align-items:flex-start;gap:var(--s-3);padding:var(--s-3) 0;border-top:1px solid var(--line)}
.crs-row:first-child{border-top:none}
/* Номер моноширинным: в курсе он не украшение, а порядок прохождения, и
   колонка не должна ездить от ширины цифр. */
.crs-num{font-family:var(--font-mono);font-size:var(--t-sm);color:var(--muted);padding-top:2px;flex-shrink:0}
.crs-main{flex:1;min-width:0}
.crs-title{font-size:var(--t-md);font-weight:600;line-height:1.35}
.crs-rule{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;margin-top:5px;font-size:var(--t-sm);color:var(--muted)}
.crs-rule select,.crs-rule input{font-size:var(--t-sm);padding:var(--s-1) var(--s-2);border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface-2);color:var(--ink)}
.crs-acts{display:flex;gap:2px;flex-shrink:0}

.crs-stu{display:flex;align-items:flex-start;gap:10px;padding:var(--s-3) 0;border-top:1px solid var(--line)}
.crs-stu:first-child{border-top:none}
/* Полоса прохождения. Жёлоб виден всегда — по пустой полосе сразу понятно,
   что человек курс ещё не начинал, а отсутствие полосы читалось бы как сбой. */
.crs-bar{height:4px;border-radius:99px;background:var(--line);margin-top:7px;overflow:hidden}
.crs-bar span{display:block;height:100%;background:var(--accent);border-radius:99px}

/* Курс глазами ученика: строка урока кликабельна, запертая — приглушена
   и не реагирует. Замок вместо номера, потому что номер запертого урока
   ученику ничего не даёт — ему нужно знать, что туда пока нельзя. */
.crs-head{display:flex;align-items:center;gap:var(--s-2)}
.crs-row.locked{opacity:.55;cursor:default}
.crs-row:not(.locked):hover{background:var(--surface-2)}
.crs-row{border-radius:var(--radius-sm);padding-left:var(--s-2);padding-right:var(--s-2);margin:0 -var(--s-2)}
.lib-card .crs-bar{margin-top:var(--s-2)}

/* ---------- Помощь в самостоятельном уроке ----------
   Оба блока набраны как «Пример»: полосой слева и служебной меткой. Разница
   в цвете полосы — подсказка нейтральная, разбор идёт по следам ошибки и
   потому берёт цвет ошибки. Курсива здесь нет: в отличие от примера, это не
   образец задания, а обращённая к ученику речь. */
.ex-hint,.ex-explain{display:flex;gap:var(--s-3);align-items:flex-start;margin:10px 0 0;padding:var(--s-2) var(--s-3);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.ex-hint{border-left:2px solid var(--accent);background:var(--accent-soft)}
.ex-explain{border-left:2px solid var(--err);background:var(--err-bg)}
.exh-label,.exx-label{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;padding-top:3px;flex-shrink:0}
.exh-label{color:var(--accent-soft-ink)}
.exx-label{color:var(--err)}
.exh-text,.exx-text{font-size:var(--t-md);line-height:1.6;color:var(--ink-2)}
