/* Стили оболочки кабинета — СНИМОК прототипа cabinet-flow-v1.html.
   Живой связи с эталоном больше нет (на сервере его папки не существует):
   правка прототипа сюда сама НЕ долетит, файл пересобирается build-site.py.
   Источник: design/prototypes/cabinet-flow-v1.html, репозиторий cubi-platform. */
/* ==================================================================
   ТОКЕНЫ — источник: business/assets/design-system/tokens/tokens.css.
   Скопировано as-is (SSOT). НЕ РЕДАКТИРОВАТЬ ВРУЧНУЮ — правки в tokens/*.json,
   пересборка build-tokens.ps1. Файл на токены не линкуется (открывается офлайн).
   ================================================================== */
:root{
  /* Semantic roles (stable names) */
  --bg-page: #F7F6F2;
  --bg-card: #FFFFFF;
  --bg-subtle: #EFEDE6;
  --text-primary: #2A2318;
  --text-secondary: #6B6353;
  --text-strong: #17110A;
  --border-default: #E1DDD1;
  --border-interactive: #7A7263;
  --border-focus: #2A2318;
  --border-secondary: #A39C8B;
  --focus-ring: #0C833E;
  --menu-selected: #0A6F34;
  --shim-base: #EDEAE2;
  --shim-hi: #F6F4EF;
  --scroll-track: transparent;
  --scroll-thumb: rgba(122,114,99,.50);
  --scroll-thumb-hover: rgba(122,114,99,.72);
  --scroll-size: 10px;
  --neo-bg: #F7F6F2;
  --neo-dark: rgba(150,136,102,.30);
  --neo-light: rgba(255,255,255,.94);
  --neo-grad: linear-gradient(45deg,#F2F0EA 0%,#FCFBF8 100%);
  --neo-r: 30px;
  --action-primary-bg: #E6F3EA;
  --action-primary: #0C833E;
  --action-primary-hover: #0A6F34;
  --action-primary-pressed: #075325;
  --action-on-primary: #FFFFFF;
  --action-bright: #17B26A;
  --state-success: #0E8C6A;
  --state-success-bg: #E3F5EE;
  --state-warning: #B7791F;
  --state-warning-bg: #FFF3D6;
  --state-error: #9C3643;
  --state-error-bg: #F9E3E6;
  --state-info: #2458D3;
  --state-info-bg: #E9EEFF;
  --state-info-bright: #4C82F0;
  --state-locked: #6B6353;
  --state-locked-bg: #EFEDE6;
  --subject-primary: #0F7A3D;
  --subject-bg-soft: #E6F3EA;
  --subject-border: #B9DCC5;
  --brand-course: #00C83A;
  --brand-logo-ink: #2A2A2A;
  --font-weight-action: 600;
  --font-weight-heading: 700;
  --quantity-green-text: #0A6F34;
  --quantity-green-soft: #E6F3EA;
  --quantity-violet-text: #6A34C0;
  --quantity-violet-soft: #EEE7FB;
  --quantity-blue-text: #2458D3;
  --quantity-blue-soft: #E9EEFF;
  --quantity-amber-text: #92500F;
  --quantity-amber-soft: #FDEFE0;
  --quantity-pink-text: #9C2F6B;
  --quantity-pink-soft: #FBE5F0;
  /* Spacing / radii - rem, base 16px */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1.125rem;
  --radius-xl: 1.375rem;
  --radius-pill: 999px;
  /* Helpers: fonts, metrics, breakpoints (manual zone) */
  --font-head: 'Onest', sans-serif;
  --font-body: 'IBM Plex Sans', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  --font-formula: KaTeX_Main, 'Computer Modern', serif;
  --font-graph: KaTeX_Math, 'Computer Modern', serif;
  --katex-scale: 1.17; --katex-tracking: -0.010em; --code-scale: 0.94;
  --measure: 62ch; --container-max: 75rem;   /* мера чтения 62ch — как в эталоне оболочки */
  --bp-mobile: 32.5em; --bp-tablet: 56.25em;
  /* Метрика лейбла секции. Зазор «лейбл → блок» считается ОТ БУКВ (§9.2а): половина
     интерлиньяжа лежит под чернилами и читается как лишний воздух, поэтому её вычитаем.
     Связь, а не константа: поменяется кегль или строка — поправка пересчитается сама. */
  --lab-size: 11px; --lab-line: 22px;
  --lab-cap: calc(var(--lab-size) * .72);                     /* высота прописных ≈ 0.72em */
  --lab-lead: calc((var(--lab-line) - var(--lab-cap)) / 2);   /* интерлиньяж под чернилами */
}
/* Dark theme (для справки: в прототипе НЕ активируется — тумблер даёт тост) */
:root[data-theme="dark"]{
  --bg-page: #1B1C1F; --bg-card: #242528; --bg-subtle: #2D2F33;
  --text-primary: #E7E8EA; --text-secondary: #A6A9AF; --text-strong: #F6F7F8;
  --border-default: #3A3C42; --border-interactive: #6A6E76; --border-focus: #D8DBE0;
  --border-secondary: #52565E; --focus-ring: #39C831; --menu-selected: #57C878;
  --neo-bg: #1B1C1F; --neo-dark: rgba(3,4,7,.55); --neo-light: rgba(62,66,76,.40);
  --neo-grad: linear-gradient(45deg,#17181B 0%,#212328 100%);
  --action-primary-bg: #123322; --action-primary: #178036;
  --state-success: #3FC59B; --state-success-bg: #123028;
  --subject-primary: #57C878; --subject-bg-soft: #17311E; --subject-border: #2E5238;
}

/* ==================================================================
   ПРОИЗВОДНЫЕ КАРКАСА (не токены — геометрия прототипа оболочки)
   ================================================================== */
:root{
  --pbar-h:44px;            /* полоса демо-навигации прототипа (не часть продукта) */
  --topbar-h:64px;
  --rail-w:72px;            /* рейл свёрнут */
  --toc-w:320px;           /* оглавление */
  --chat-w:360px;          /* чат-колонка (desktop) */
  --lesson-px:56px;        /* гориз. паддинг блока урока */
  --gutter:calc(var(--space-4) + 72px + var(--space-4));  /* жёлоб под рейл на кабинетных экранах */
  /* вся мобильная навигация отсчитывается отсюда: капсула выше системной полосы Android/iOS */
  --nav-safe:max(env(safe-area-inset-bottom, 0px), 14px);
  --cap-w-factor:0.80;      /* доля ширины блока, которую занимает капсула */
  --cap-inset:var(--space-5);  /* поле страницы, от которого считается капсула и FAB */
  --shadow-card:0 1px 2px rgba(23,33,43,.04), 0 10px 28px rgba(23,33,43,.05);
  --neo-shadow:10px 10px 24px var(--neo-dark), -10px -10px 24px var(--neo-light);
  --chrome-top:calc(var(--pbar-h) + var(--topbar-h) + var(--space-5));  /* верх плавающих панелей */
}
body.pbar-off{ --pbar-h:0px; }
body.rail-open{ --rail-w:224px; }

/* ==================================================================
   БАЗА
   ================================================================== */
*{ box-sizing:border-box; }
html,body{ margin:0; }
html{ scroll-padding-top:calc(var(--pbar-h) + var(--topbar-h));
  /* место под полосу прокрутки зарезервировано ВСЕГДА: иначе при переходе
     на экран без скролла страница прыгает по горизонтали (правка 2026-07-29) */
  scrollbar-gutter:stable; }
body{
  background:var(--bg-page); color:var(--text-primary);
  font-family:var(--font-body),-apple-system,'Segoe UI',Roboto,sans-serif;
  font-size:17px; line-height:1.7; -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; border-radius:4px; }
h1,h2,h3{ font-family:var(--font-head); letter-spacing:-.01em; color:var(--text-strong); }
/* заголовок только для скринридера: на экране его роль играет хром и лейблы секций */
.sr-only{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* скроллбары: тонкие, скруглённые, без стрелок */
@supports (-moz-appearance:none){
  html, .toc-scroll, .chat .scrollbox{ scrollbar-width:thin; scrollbar-color:var(--scroll-thumb) transparent; }
}
::-webkit-scrollbar{ width:12px; height:12px; }
::-webkit-scrollbar-button{ display:none !important; width:0 !important; height:0 !important; }
::-webkit-scrollbar-track,::-webkit-scrollbar-corner{ background:transparent; }
::-webkit-scrollbar-thumb{
  background:var(--scroll-thumb); border:4px solid transparent; background-clip:padding-box;
  border-radius:var(--radius-pill); min-height:48px;
}
::-webkit-scrollbar-thumb:hover{ background:var(--scroll-thumb-hover); border:4px solid transparent; background-clip:padding-box; }
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ transition:none !important; animation:none !important; }
}

/* иконки */
.ic{ width:22px; height:22px; flex:none; }
.icon-btn{
  width:40px; height:40px; border:0; border-radius:var(--radius-md);
  background:transparent; color:var(--text-secondary); cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition:background-color .15s, color .15s;
}
.icon-btn:hover{ background:var(--bg-subtle); color:var(--text-primary); }
.icon-btn .ic{ width:22px; height:22px; }

/* формулы KaTeX: канон scale 1.17, tracking −0.010em; текстовый фоллбэк без сети */
.tex .katex{ font-size:calc(1em * var(--katex-scale)); letter-spacing:var(--katex-tracking); }
.tex{ font-family:var(--font-graph); font-style:italic; }

/* ==================================================================
   КНОПКИ — канон components/buttons.md (.btn + .sz-* + .v-*)
   ================================================================== */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  font-family:var(--font-head); font-weight:var(--font-weight-action); font-size:var(--btn-fs);
  min-height:var(--btn-minh); padding:var(--btn-py) var(--btn-px); border-radius:var(--btn-r);
  border:0; cursor:pointer; text-decoration:none; line-height:1;
  transition:background-color .2s ease,border-color .2s ease,color .2s ease,transform .1s ease,box-shadow .2s ease;
}
.btn:disabled,.btn[aria-disabled="true"]{ opacity:.45; cursor:not-allowed; box-shadow:none; transform:none; }
.sz-s{ --btn-py:var(--space-2); --btn-px:var(--space-4); --btn-minh:36px; --btn-r:var(--radius-md); --btn-fs:15px; }
.sz-m{ --btn-py:var(--space-3); --btn-px:var(--space-5); --btn-minh:44px; --btn-r:var(--radius-md); --btn-fs:16px; }
.sz-l{ --btn-py:var(--space-4); --btn-px:var(--space-6); --btn-minh:52px; --btn-r:var(--radius-lg); --btn-fs:17px; }
.btn svg{ width:1.1em; height:1.1em; flex:none; }
.v-hero{
  position:relative; color:var(--action-on-primary);
  background:linear-gradient(135deg,var(--action-primary) 0%,var(--action-primary) 58%,var(--action-bright) 100%);
  box-shadow:0 8px 20px color-mix(in srgb,var(--action-primary) 42%,transparent);
}
.v-hero:hover{ box-shadow:0 10px 26px color-mix(in srgb,var(--action-primary) 55%,transparent); }
.v-hero:active{ transform:scale(.96); }
.v-primary{ color:var(--action-on-primary); background:var(--action-primary);
  box-shadow:0 4px 12px color-mix(in srgb,var(--action-primary) 34%,transparent); }
.v-primary:hover{ background:var(--action-primary-hover); box-shadow:0 6px 16px color-mix(in srgb,var(--action-primary) 44%,transparent); }
.v-primary:active{ background:var(--action-primary-pressed); transform:scale(.98); }
.v-secondary{ border:1.5px solid var(--border-secondary); background:transparent; color:var(--text-primary); font-weight:500; }
.v-secondary:hover{ border-color:var(--action-primary); color:var(--action-primary); background:var(--action-primary-bg); }
.v-secondary:active{ transform:scale(.98); }
.v-link{ background:none; color:var(--text-primary); min-height:auto; font-size:inherit; padding:4px 0; border-radius:0; box-shadow:none; }
.v-link .u{ position:relative; padding-bottom:3px; }
.v-link .u::after{ content:""; position:absolute; left:0; bottom:0; width:100%; height:2px;
  background:var(--action-primary); transform:scaleX(0); transform-origin:bottom right; transition:transform .25s ease-out; }
.v-link:hover .u::after{ transform:scaleX(1); transform-origin:bottom left; }
.btn.is-loading{ pointer-events:none; }
.btn .spin{ width:1.05em; height:1.05em; flex:none; border-radius:50%;
  border:2px solid color-mix(in srgb,currentColor 30%,transparent); border-top-color:currentColor; animation:spin .7s linear infinite; }
@keyframes spin{ to{ transform:rotate(360deg); } }
.btn-wide{ width:100%; }

/* ==================================================================
   ПИЛЮЛИ СТАТУСА (locked — нейтраль, психобезопасность: без красного)
   ================================================================== */
.pill{
  display:inline-flex; align-items:center; gap:6px; width:max-content;
  font-size:12.5px; font-weight:600; line-height:1.4; padding:4px 12px; border-radius:var(--radius-pill);
  background:var(--bg-subtle); color:var(--text-secondary);
}
.pill svg{ width:14px; height:14px; flex:none; }
.pill.open{ background:var(--subject-bg-soft); color:var(--subject-primary); }
.pill.doing{ background:var(--action-primary-bg); color:var(--action-primary); }
.pill.soon{ background:var(--state-locked-bg); color:var(--state-locked); }
.pill.done{ background:var(--state-success-bg); color:var(--state-success); }
.pill.wait{ background:var(--state-warning-bg); color:var(--state-warning); }

/* ==================================================================
   ТОПБАР (модель эталона: grid из 3 зон; центральный слот меняется по странице)
   ================================================================== */
.topbar{
  position:sticky; top:var(--pbar-h); z-index:50; height:var(--topbar-h);
  /* боковые зоны — ПО СОДЕРЖИМОМУ, центр забирает остаток (правка 2026-07-29).
     Логотип уже блока иконок, поэтому при равных долях плашка сообщения вставала
     ближе к иконкам; теперь она центрируется между их внутренними краями и держит
     одинаковый зазор слева и справа. Ширина самой плашки ограничена (--priority-max) */
  display:grid; grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center; gap:var(--space-4); padding:0 var(--space-5);
  background:var(--bg-page); border-bottom:0;
  transition:transform .25s ease;
}
/* боковые зоны не сжимаются ниже своего содержимого и не выдавливаются за край:
   центральная колонка minmax(0,1fr) отдаёт им место первой (правка 2026-07-29) */
.tb-left{ display:flex; align-items:center; gap:var(--space-2); min-width:max-content; }
/* логотип: производственный wordmark (business/assets/logo/cubi, logo-usage.md).
   Пара light/dark переключается темой; в зелёной зоне телефона (тёмный хром)
   показывается dark-вариант — прототипное отступление: full-color на градиенте
   канон запрещает, white-версия wordmark ещё не утверждена (logo-usage §12).
   Высота 30px < канонного минимума 160px ширины — осознанно для топбара прототипа. */
.brand{
  display:inline-flex; align-items:center; width:max-content;
  background:none; border:0; padding:0; cursor:pointer;
}
.brand img{ display:block; height:30px; width:auto; }
.brand .logo-dark{ display:none; }
:root[data-theme="dark"] .brand .logo-light{ display:none; }
:root[data-theme="dark"] .brand .logo-dark{ display:block; }
/* Только телефон: тёмный зелёный хром живёт в @media (max-width:860px). На десктопе
   у «Моего пути» и «Деталей урока» тот же data-zone="green", но топбар светлый —
   без этой рамки на светлый лист выезжал логотип для тёмного фона (правка Игоря 2026-08-10). */
@media (max-width:860px){
  body[data-zone="green"] .brand .logo-light{ display:none; }
  body[data-zone="green"] .brand .logo-dark{ display:block; }
}
/* центральный слот — вариант «крошки» (страницы урока) */
.context{
  justify-self:center; max-width:100%; overflow:hidden;
  border:0; border-radius:var(--radius-pill); background:var(--bg-subtle);
  padding:7px var(--space-4); display:flex; align-items:center;
}
.crumbs{ display:flex; align-items:center; gap:10px; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.crumbs a{ color:var(--text-secondary); text-decoration:none; cursor:pointer; }
.crumbs a:hover{ color:var(--subject-primary); }
.crumbs .sep{ color:var(--border-interactive); }
.crumbs [aria-current]{ color:var(--text-strong); font-weight:600; }
/* центральный слот — вариант «одно приоритетное сообщение» (К19, кабинетные экраны) */
.priority{
  justify-self:center; max-width:min(100%, var(--priority-max,560px)); min-width:0;
  border:0; border-radius:var(--radius-pill);
  background:var(--bg-subtle); color:var(--text-primary); padding:7px var(--space-4);
  font:inherit; font-size:14px; white-space:nowrap; overflow:hidden; cursor:pointer;
}
.priority b{ color:var(--subject-primary); }
/* бегущая строка — только когда текст физически не влезает (класс ставит JS замером).
   Ход «туда-обратно», не карусель: спокойнее и не требует дубля текста. */
.pr-track{ display:inline-block; white-space:nowrap; will-change:transform; }
.priority.is-marquee .pr-track{
  animation:pr-marquee var(--mq-dur,12s) ease-in-out infinite alternate;
  animation-delay:1.2s;                       /* дать прочитать начало, прежде чем ехать */
}
@keyframes pr-marquee{
  from{ transform:translateX(0); }
  to{ transform:translateX(calc(-1 * var(--mq-shift,0px))); }
}
@media (prefers-reduced-motion: reduce){
  .priority.is-marquee .pr-track{ animation:none; }
  .priority.is-marquee{ text-overflow:ellipsis; }
}
/* переключение слота по странице + К19: в focus-mode центр пуст */
.context, .priority{ display:none; }
body[data-center="crumbs"] .context{ display:flex; }
body[data-center="priority"] .priority{ display:block; }
body.focus-mode .context, body.focus-mode .priority{ display:none; }
/* право — Уведомления → Чат → Профиль */
.tb-actions{ justify-self:end; display:flex; align-items:center; gap:var(--space-1); }
.tb-actions .icon-btn{ position:relative; }
.notif-dot{
  position:absolute; top:8px; right:9px; width:8px; height:8px; border-radius:var(--radius-pill);
  background:var(--subject-primary); border:2px solid var(--bg-page);
}
.profile-btn{ width:auto; min-width:40px; padding:0 3px; border:0; background:transparent; border-radius:var(--radius-pill); cursor:pointer; }
.profile-btn .avatar{
  width:36px; height:36px; border-radius:var(--radius-pill); margin:0;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head); font-weight:600; font-size:14px; color:var(--subject-primary);
  background:var(--neo-grad);
  box-shadow:5px 5px 12px var(--neo-dark), -5px -5px 12px var(--neo-light);
  transition:box-shadow .3s ease, transform .3s ease;
}
.profile-btn:hover .avatar{ box-shadow:7px 7px 16px var(--neo-dark), -7px -7px 16px var(--neo-light); }
.profile-btn:active .avatar{ transform:scale(.95);
  box-shadow:2px 2px 6px var(--neo-dark), -2px -2px 6px var(--neo-light),
    inset 4px 4px 10px var(--neo-dark), inset -4px -4px 10px var(--neo-light); }
.profile-btn[aria-expanded="true"] .avatar{ box-shadow:inset 4px 4px 10px var(--neo-dark), inset -4px -4px 10px var(--neo-light); }
.toc-fab{ display:none; }
.nav-fade{ display:none; }

/* ==================================================================
   ЛЕВЫЙ РЕЙЛ (эталон: неоморфная панель, порядок К21)
   ================================================================== */
.rail{
  position:fixed; z-index:45; left:var(--space-4);
  top:var(--chrome-top); bottom:var(--space-4);
  width:var(--rail-w); padding:var(--space-3);
  background:var(--neo-bg); border:0; border-radius:var(--neo-r);
  box-shadow:var(--neo-shadow);
  display:flex; flex-direction:column;
  transition:width .2s ease, transform .25s ease;
}
.rail-top{ display:flex; flex-direction:column; gap:10px; min-height:0; overflow:visible; flex:1 1 auto; }
.rail-spacer{ flex:1 1 auto; min-height:10px; }
.rail-bottom{ margin-top:auto; display:flex; flex-direction:column; gap:10px; flex:none; }
.rail-btn{
  position:relative; height:48px; border:0; border-radius:16px;
  background:transparent; color:var(--text-secondary); cursor:pointer;
  display:flex; align-items:center; justify-content:center; gap:var(--space-3);
  font:inherit; font-size:15px; font-weight:500;
  box-shadow:4px 4px 10px transparent, -4px -4px 10px transparent,
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
  transition:box-shadow .3s ease, background-color .3s ease, color .3s ease, transform .3s ease;
}
.rail-btn .ic{ width:24px; height:24px; transition:transform .3s ease; }
.rail-btn:hover{
  background:var(--neo-bg); color:var(--text-primary);
  box-shadow:3px 3px 7px var(--neo-dark), -3px -3px 7px var(--neo-light),
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
}
.rail-btn:active{
  transform:scale(.95); background:var(--neo-bg);
  box-shadow:2px 2px 6px var(--neo-dark), -2px -2px 6px var(--neo-light),
    inset 4px 4px 10px var(--neo-dark), inset -4px -4px 10px var(--neo-light);
}
.rail-btn:active .ic{ transform:scale(.9); }
/* ВЫБРАН (канон neo-style v1.11): плоскость + цвет --menu-selected + черта 3px */
.rail-btn::before{
  content:''; position:absolute; left:-13px; top:12px; bottom:12px; width:3px;
  border-radius:var(--radius-pill); background:var(--menu-selected);
  opacity:0; transition:opacity .3s ease;
}
.rail-btn.on{
  background:transparent; color:var(--menu-selected); font-weight:600;
  box-shadow:4px 4px 10px transparent, -4px -4px 10px transparent,
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
}
.rail-btn.on:hover{
  background:transparent;
  box-shadow:4px 4px 10px transparent, -4px -4px 10px transparent,
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
}
.rail-btn.on::before{ opacity:1; }
.rail-label{ display:none; white-space:nowrap; }
body.rail-open .rail-btn{ justify-content:flex-start; padding:0 12px; }
body.rail-open .rail-label{ display:inline; }
.rail-btn::after{
  content:attr(data-tip); position:absolute; left:calc(100% + 16px); top:50%;
  transform:translateY(-50%); white-space:nowrap;
  background:#17212B; color:#E7EAF0; font-size:13px; line-height:1.4;
  padding:5px 10px; border-radius:var(--radius-sm);
  opacity:0; pointer-events:none; transition:opacity .15s; z-index:2;
}
body:not(.rail-open) .rail-btn:hover::after,
body:not(.rail-open) .rail-btn:focus-visible::after{ opacity:1; }
.rail-divider{ height:1px; background:var(--border-default); margin:var(--space-1) var(--space-2); }
.rail-collapse{
  flex:none; margin-top:var(--space-1); min-height:44px; border:0; background:transparent;
  border-radius:16px; color:var(--text-secondary); cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  box-shadow:4px 4px 10px transparent, -4px -4px 10px transparent,
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
  transition:box-shadow .3s ease, color .3s ease, transform .3s ease;
}
.rail-collapse:hover{
  background:var(--neo-bg); color:var(--text-primary);
  box-shadow:3px 3px 7px var(--neo-dark), -3px -3px 7px var(--neo-light),
    inset 4px 4px 10px transparent, inset -4px -4px 10px transparent;
}
.rail-collapse:active{
  transform:scale(.95); background:var(--neo-bg);
  box-shadow:2px 2px 6px var(--neo-dark), -2px -2px 6px var(--neo-light),
    inset 4px 4px 10px var(--neo-dark), inset -4px -4px 10px var(--neo-light);
}
.rail-collapse .ic{ width:16px; height:16px; transform:rotate(-90deg); }
body.rail-open .rail-collapse .ic{ transform:rotate(90deg); }
/* видимость пунктов по слою доступа (guest/trial/paid) */
.rail-btn[data-layers]{ display:none; }
body[data-layer="trial"] .rail-btn[data-layers~="trial"],
body[data-layer="paid"]  .rail-btn[data-layers~="paid"]{ display:flex; }

/* ==================================================================
   ПОПОВЕРЫ (уведомления / профиль)
   ================================================================== */
.popover{
  display:none; position:fixed; z-index:56; top:calc(var(--pbar-h) + var(--topbar-h) + var(--space-2));
  width:min(330px, calc(100vw - 32px)); padding:var(--space-2);
  background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);
}
.notif-pop{ right:var(--space-5); }
body.notif-open .notif-pop{ display:block; }
body.profile-open .profile-pop{ display:block; }
.np-item{ display:flex; gap:var(--space-3); padding:var(--space-3); border-radius:var(--radius-md); }
.np-item:hover{ background:var(--bg-subtle); }
.np-item .ic{ width:18px; height:18px; flex:none; color:var(--subject-primary); margin-top:3px; }
.np-t{ font-size:14px; font-weight:600; line-height:1.4; color:var(--text-primary); }
.np-s{ font-size:13px; color:var(--text-secondary); line-height:1.45; }

/* ---- меню профиля (макет 2026-08-06): светлое тёплое окно ----
   Префикс pp- (profile pop): pm- занят аккордеоном StudyPeriod «Моего пути».
   Геометрия — токены ДС (шкала --space-*, радиусы --radius-*, типографика §3:
   Body 17 / Body Small 15 / Caption 13, веса через --font-weight-*).
   Тёплая палитра окна и градиент карточки — по утверждённому макету, в токенах
   аналогов нет → компонентные --pp-* переменные, кандидат на канонизацию */
.profile-pop{
  --pp-text:#241F19; --pp-muted:#746E65; --pp-line:#E6E0D7;
  --pp-hover:#F2F7F0;      /* очень светлый зелёный — ТОЛЬКО у баланса кубитов */
  --pp-hover-warm:#F4EEE3; /* бежевый hover обычных пунктов — как тёплая палитра окна */
  --pp-tap:44px;           /* тач-цель ≥44 (dim.tap.comfort ДС; токена в прототипе ещё нет) */
  right:var(--space-4); width:min(348px, calc(100vw - 24px)); padding:var(--space-4);
  background:#FFFFFF; border:1px solid var(--pp-line); border-radius:var(--radius-xl);
  box-shadow:0 18px 44px rgba(58,45,24,.12);   /* тёплая float-тень макета */
  color:var(--pp-text); line-height:1.45;
}
.pp-head{ display:flex; align-items:center; gap:var(--space-3); min-width:0; }
.pp-ava{
  width:48px; height:48px; flex:none; border-radius:var(--radius-pill);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head); font-weight:var(--font-weight-heading); font-size:17px;
  color:var(--pp-text); background:#F4EEE3;
}
.pp-id{ min-width:0; }
.pp-id b{
  display:block; font-family:var(--font-head); font-weight:var(--font-weight-heading);
  font-size:17px;          /* Body-ступень шкалы */
  color:var(--pp-text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pp-id span{ display:block; font-size:13px; color:var(--pp-muted); white-space:nowrap; }  /* Caption */
/* баланс кубитов — UI-действие → Onest 600 (typography §1), цель ≥44px, ведёт в историю кубитов.
   Hover-подсветка ТОЛЬКО у этой зоны (правка Игоря 2026-08-06) — шапка целиком не заливается */
.pp-balance{
  margin-left:auto; flex:none; display:flex; align-items:center; gap:var(--space-1);
  min-height:var(--pp-tap); padding:var(--space-1) var(--space-2); border:0; border-radius:var(--radius-md);
  background:transparent; cursor:pointer; font:inherit;
  font-family:var(--font-head); font-weight:var(--font-weight-action); font-size:17px; color:var(--pp-text);
  transition:background-color .15s ease;
}
.pp-balance:hover{ background:var(--pp-hover); }
.pp-balance .pp-cubit{ width:19px; height:19px; color:var(--brand-course); }  /* бренд-глиф, своя сетка, ≥16px */
.pp-balance .pp-chev{ width:14px; height:14px; color:var(--pp-muted); }
/* реферальная карточка: вихревой градиент бренд-зелёный (--brand-course) × синий (--state-info).
   Conic крутит зелёные тона, два radial-слоя дают синие «плюмы»; тёмный radial слева
   подпирает читаемость текстовой зоны, сверху лёгкая вуаль */
.pp-ref{
  position:relative;   /* якорь для кнопки-i и тултипа */
  width:100%; margin-top:var(--space-4); padding:var(--space-4);
  border-radius:var(--radius-lg); color:#FFFFFF;
  background:
    linear-gradient(rgba(8,24,16,.08), rgba(8,24,16,.14)),
    radial-gradient(120% 110% at 4% 10%, rgba(6,64,32,.42) 0%, rgba(6,64,32,0) 55%),
    radial-gradient(130% 100% at 92% 0%, color-mix(in srgb, var(--state-info) 72%, transparent) 0%, transparent 58%),
    radial-gradient(100% 90% at 70% 100%, color-mix(in srgb, var(--state-info) 40%, transparent) 0%, transparent 52%),
    conic-gradient(from 205deg at 115% -25%, var(--brand-course), #00A936 30%, var(--action-primary) 55%, #00B23C 76%, var(--brand-course));
    /* центр conic вынесен ЗА карточку (115% -25%): в центре все сектора сходятся
       в видимую точку-сингулярность — внутри карточки ей быть нельзя */
}
.pp-ref-t{
  font-family:var(--font-head); font-weight:var(--font-weight-heading); font-size:17px; line-height:1.25;
  padding-right:36px; text-shadow:0 1px 2px rgba(0,0,0,.20);
}
/* кнопка-i: что такое кубиты; тултип показывается на hover и на фокусе (тап на мобиле) */
.pp-info{
  position:absolute; top:10px; right:10px; width:32px; height:32px;
  display:flex; align-items:center; justify-content:center;
  border:0; border-radius:var(--radius-pill); background:transparent;
  color:rgba(255,255,255,.85); cursor:pointer; transition:background-color .15s ease, color .15s ease;
}
.pp-info:hover{ background:rgba(255,255,255,.18); color:#FFFFFF; }
.pp-info .ic{ width:18px; height:18px; }
.pp-tip{
  position:absolute; top:42px; right:8px; z-index:2; width:min(272px, calc(100% - 16px));
  padding:10px 12px; border-radius:var(--radius-md);
  background:#17212B; color:#E7EAF0; font-size:13px; line-height:1.5;
  box-shadow:0 12px 32px rgba(23,33,43,.25);
  opacity:0; transform:translateY(4px); pointer-events:none;
  transition:opacity .15s ease, transform .15s ease;
}
/* показом управляет JS (класс tip-open на карточке): чистый CSS-hover рвётся на
   диагональном пути «i → плашка», JS даёт льготные ~350мс на перелёт курсора */
.pp-ref.tip-open .pp-tip{ opacity:1; transform:translateY(0); pointer-events:auto; }
.pp-tip-more{
  display:inline-block; margin-top:6px; color:#7FE0A0; font-weight:600;
  text-decoration:underline; text-underline-offset:2px;
}
.pp-tip-more:hover{ color:#A5EFC0; }
.pp-ref-s{ margin-top:var(--space-1); font-size:13px; line-height:1.4; opacity:.9; text-shadow:0 1px 2px rgba(0,0,0,.18); }
/* строка адреса: полупрозрачное поле, длинный адрес режется многоточием */
.pp-ref-row{ display:flex; align-items:center; gap:var(--space-2); margin-top:var(--space-3); }
.pp-ref-link{
  flex:1; min-width:0; display:flex; align-items:center; min-height:var(--pp-tap);
  padding:0 var(--space-3); border-radius:var(--radius-md);
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.30);
  font-size:13px; color:#FFFFFF;
}
.pp-ref-link span{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* кнопка копирования: белая плитка без «стопки»-слоёв (веер убран — правка Игоря 2026-08-07) */
.pp-copy{
  flex:none; width:var(--pp-tap); height:var(--pp-tap);
  border:0; border-radius:var(--radius-md); background:#FFFFFF; color:#00A936;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  box-shadow:0 10px 22px rgba(0,82,31,.22), 0 2px 5px rgba(0,0,0,.08);
  transition:transform .18s ease, box-shadow .18s ease;
}
.pp-copy:hover{ transform:translateY(-2px); box-shadow:0 14px 26px rgba(0,82,31,.26), 0 3px 6px rgba(0,0,0,.08); }
.pp-copy:active{ transform:translateY(0); box-shadow:0 10px 22px rgba(0,82,31,.22), 0 2px 5px rgba(0,0,0,.08); }
.pp-copy:focus-visible{ outline:3px solid #FFFFFF; outline-offset:3px; border-radius:var(--radius-md); }
.pp-copy .ic{ width:22px; height:22px; }   /* канон отрисовки иконок 22×22 (iconography.md) */
.pp-copy .ic-check{ display:none; }
.pp-copy.is-copied .ic-copy{ display:none; }
.pp-copy.is-copied .ic-check{ display:block; }
/* пункты меню: строка ≥44px, спокойный hover */
.pp-list{ margin-top:var(--space-2); }
.pp-item{
  width:100%; min-height:var(--pp-tap); display:flex; align-items:center; gap:var(--space-3);
  padding:0 var(--space-2); border:0; background:transparent; border-radius:var(--radius-md);
  cursor:pointer; font:inherit; font-size:15px; color:var(--pp-text); text-align:left;  /* Body Small */
  transition:background-color .15s ease, color .15s ease;
}
.pp-item:hover{ background:var(--pp-hover-warm); }   /* бежевый; зелёный — кубиты, красный — выход */
.pp-item .ic{ width:22px; height:22px; flex:none; color:var(--pp-muted); }  /* канон 22×22 */
.pp-sep{ height:1px; background:var(--pp-line); margin:var(--space-2) 0; }
/* выход: нейтральный в покое, красный только на hover */
.pp-exit:hover{ background:var(--state-error-bg); color:var(--state-error); }
.pp-exit:hover .ic{ color:var(--state-error); }
@media (max-width:520px){
  .profile-pop{ right:var(--space-3); }   /* при width:100vw-24px поля = 12px с каждой стороны */
}
/* ==================================================================
   ГЕОМЕТРИЯ: колонка чтения (урок) и кабинетная сетка
   ================================================================== */
/* верхний отступ ужат (правка Игоря 2026-07-29): после снятия черты у топбара
   прежние 24px читались как провал между шапкой и заголовком экрана */
.page{ padding:var(--space-3) 0 var(--space-4); transition:padding .2s ease; }
.col{ max-width:calc(var(--measure) + 2 * var(--lesson-px)); margin:0 auto; }   /* урок: центр экрана */
.wrap{ max-width:var(--container-max); margin:0 auto; padding:0 var(--space-5); }  /* кабинет */
.screen{ display:none; }
.screen.is-on{ display:block; }
/* слой guest: кабинета ещё нет — виден только экран входа */
body[data-layer="guest"] .topbar,
body[data-layer="guest"] .rail,
body[data-layer="guest"] .page,
body[data-layer="guest"] .toc,
body[data-layer="guest"] .toc-tab,
body[data-layer="guest"] .chat,
body[data-layer="guest"] .popover{ display:none !important; }
.view-head{ margin:0 0 var(--space-5); }
.view-head h1{ margin:0 0 6px; font-size:32px; line-height:1.15; font-weight:700; }
.view-head p{ margin:0; color:var(--text-secondary); max-width:56ch; }
.eyebrow{
  margin:0 0 var(--space-2); font-size:12px; font-weight:600; letter-spacing:.06em;
  text-transform:uppercase; color:var(--subject-primary);
}
/* приоритетная строка на мобиле — первой строкой ленты (К37), не в шапке */
.priority-mobile{ display:none; }

/* ==================================================================
   ЭКРАН ВХОДА (guest): автовход и, если он не сработал, — код на ТОМ ЖЕ экране
   ================================================================== */
.auth{
  display:none; min-height:calc(100dvh - var(--pbar-h)); place-items:center; padding:var(--space-5);
}
body[data-layer="guest"] .auth{ display:grid; }
.auth-card{
  width:100%; max-width:460px; padding:var(--space-6);
  background:var(--neo-bg); border:0; border-radius:var(--neo-r); box-shadow:var(--neo-shadow);
  display:flex; flex-direction:column; align-items:center; gap:var(--space-4); text-align:center;
}
.auth-card .brand img{ height:44px; }
.auth-target{
  display:flex; align-items:center; gap:var(--space-2); width:100%;
  padding:10px var(--space-4); border-radius:var(--radius-lg);
  background:var(--subject-bg-soft); color:var(--subject-primary);
  font-size:13.5px; font-weight:600; text-align:left; line-height:1.4;
}
.auth-target .ic{ width:18px; height:18px; }
.auth-h{ margin:0; font-size:22px; font-weight:700; line-height:1.25; }
.auth-p{ margin:0; color:var(--text-secondary); font-size:14.5px; line-height:1.6; max-width:38ch; }
.auth-p b{ color:var(--text-primary); }
.spinner{
  width:38px; height:38px; border-radius:50%;
  border:3px solid var(--border-default); border-top-color:var(--action-primary);
  animation:spin 1s linear infinite;
}
.auth-mark{
  width:48px; height:48px; border-radius:var(--radius-lg);
  background:var(--bg-subtle); color:var(--text-secondary); display:grid; place-items:center;
}
.auth-mark .ic{ width:24px; height:24px; }
/* блок «не сработало» появляется на том же экране, не отдельным шагом */
.auth-fallback{
  width:100%; display:flex; flex-direction:column; align-items:center; gap:var(--space-4);
  overflow:hidden; max-height:0; opacity:0; transition:max-height .35s ease, opacity .3s ease;
}
body.auth-failed .auth-fallback{ max-height:520px; opacity:1; }
body.auth-failed .auth-checking{ display:none; }
.auth-sep{ width:100%; display:flex; align-items:center; gap:var(--space-3); color:var(--text-secondary); font-size:12.5px; }
.auth-sep::before, .auth-sep::after{ content:''; height:1px; flex:1; background:var(--border-default); }
/* поле кода — канон otp-input.md (в каноне 6 ячеек; здесь 8 по контракту К3) */
.otp{ display:flex; gap:8px; justify-content:center; }
.otp input{
  width:40px; height:52px; text-align:center; font-family:var(--font-mono); font-size:20px; font-weight:600;
  color:var(--text-primary); background:var(--bg-card); border:2px solid var(--border-interactive);
  border-radius:var(--radius-md); transition:.15s ease;
}
.otp input:focus{
  outline:none; border-color:var(--focus-ring);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--action-primary) 15%,transparent);
}
/* спокойный статус: нейтральная плашка, без красного и без креста */
.auth-status{
  display:none; width:100%; gap:var(--space-2); align-items:flex-start; text-align:left;
  padding:10px var(--space-3); border-radius:var(--radius-md);
  background:var(--bg-subtle); color:var(--text-secondary); font-size:13.5px; line-height:1.5;
}
.auth-status.show{ display:flex; }
.auth-status .ic{ width:17px; height:17px; flex:none; margin-top:2px; color:var(--text-secondary); }
.auth-hint{ margin:0; font-size:12.5px; color:var(--text-secondary); }
.auth-demo{ margin:0; font-size:12px; color:var(--text-secondary); opacity:.8; }

/* ==================================================================
   ТИЗЕР-КАБИНЕТ (слой trial) — переделан 2026-08-10 по ТЗ Игоря.
   Два пробных урока рядом: основной предмет открыт целиком, второй
   берётся входом через VK ID. Ниже — примеры визуализаций курса,
   открываются поп-апом прямо здесь.
   Каркас взят у Штаба (.hq-card / .hq-cover / .track / .section-label);
   новое здесь — только второй предмет, карусель виз и её поп-ап.
   ================================================================== */
.tz-lead{ display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr); gap:var(--space-5); align-items:stretch; }
.tz-lead > section{ min-width:0; display:flex; flex-direction:column; }
/* карточка тизера = карточка Штаба без внутреннего поля: обложка идёт от края до края,
   как в «Здесь и сейчас». Селектор парный (.tz-card.hq-card) — иначе padding из .hq-card
   стоит ниже по файлу и при равном весе побеждает, а обложка отходит от краёв рамкой */
.tz-card.hq-card{ padding:0; overflow:hidden; display:flex; flex-direction:column; flex:1; }
.tz-card .hq-cover{ flex:none; }
/* Обложка «Тепловой баланс» (макет Игоря 2026-08-17,
   _sandbox/lesson-thermal-balance-hero-variants/context-mockup.html): фон-поле
   на всю медиазону, лента-восьмёрка тепла в правом верхнем углу — синий конец
   снизу слева, оранжевый сверху справа (поворот 135°). Слои:
   фон → белый градиент .hq-cover::after (z-index:2) → лента НАД градиентом
   (правка Игоря 2026-08-17: сведение в белое её не глушит) → заголовок.
   Наведение/фокус на всю карточку:
   только transform/filter, без layout shift; reduced-motion и без hover — статика. */
.tb-hero-bg{
  /* запас 1px за обрез — ГЕОМЕТРИЕЙ, не transform: постоянный transform держит
     картинку на GPU-слое, его округление обреза давало постоянную полосу по
     низу; а без запаса кромка мигала швом на старте hover-анимации */
  position:absolute; inset:-1px; width:calc(100% + 2px); height:calc(100% + 2px);
  object-fit:cover; z-index:1; transform-origin:center;
  transition:transform .39s cubic-bezier(.22,1,.36,1);
}
/* стык с белым телом у физической карточки — асимметричный (правка Игоря
   2026-08-17): слева под текстом белого больше и он поднимается выше, справа
   у ленты — только тонкое сведение к низу, чтобы изображение не глушилось */
.tz-card:not(.tz-math) .hq-cover::after{
  height:100%;
  background:
    radial-gradient(105% 145% at 15% 103%, var(--bg-card) 30%, rgba(255,255,255,0) 66%),
    linear-gradient(to bottom, transparent 64%, var(--bg-card) 97%);
}
/* 310px/right:54 из макета были под герой 300px высотой; наша медиазона ниже,
   лента выпирала за фон — ужата и прижата в угол (правка Игоря 2026-08-17) */
.tb-hero-sym{
  position:absolute; top:36px; right:30px; width:255px; height:auto; z-index:3;
  transform:rotate(135deg); transform-origin:50% 50%;
  filter:drop-shadow(0 14px 18px rgba(28,92,70,.14));
  transition:transform .39s cubic-bezier(.22,1,.36,1), filter .39s ease;
}
@media (hover:hover) and (prefers-reduced-motion: no-preference){
  .tz-card:hover .tb-hero-sym, .tz-card:focus-within .tb-hero-sym{
    transform:translateY(4px) rotate(133deg) scale(1.06);
    filter:drop-shadow(0 18px 20px rgba(28,92,70,.20)); }
  .tz-card:hover .tb-hero-bg,  .tz-card:focus-within .tb-hero-bg{ transform:scale(1.025); }
}
.tz-body{ padding:var(--space-5); display:flex; flex-direction:column; gap:var(--space-4); flex:1; }
.tz-body > .now-cta-row{ margin-top:auto; }   /* строка действий всегда у нижнего края карточки */
.tz-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2) var(--space-4);
  font-size:14px; color:var(--text-secondary); }
.tz-meta > span{ display:inline-flex; align-items:center; gap:6px; }
.tz-meta .ic{ width:16px; height:16px; }
.tz-dot{ width:4px; height:4px; border-radius:50%; background:var(--border-secondary); }
.tz-desc{ margin:0; font-size:15px; line-height:1.6; color:var(--text-secondary); }
.tz-body .seg{ cursor:default; }           /* здесь лента — картинка прогресса, не кнопки */

/* ---- ВТОРОЙ ПРЕДМЕТ: спокойный синий, обложка-график ---- */
.tz-math{ --math-ink:#1E4AA8; --math-line:#C9D8F7; }
.tz-math .hq-cover{
  background:
    radial-gradient(120% 90% at 80% 6%, rgba(255,255,255,.6), transparent 62%),
    linear-gradient(135deg,#F3F6FE 0%, var(--quantity-blue-soft) 60%, #D8E3FA 100%);
}
.tz-math .tz-body{ gap:var(--space-3); }
/* Обложка «Вектора»: фон-рендер заполняет медиазону целиком, композиция трёх
   векторов ~71% ширины строго по центру (правка Игоря 2026-08-16: при наведении
   верхний шарик подходил к кромке — центр опущен с 44% на 50%, подъём убран,
   рост только из центра). Плавный переход в белое
   тело карточки даёт штатный градиент .hq-cover::after (z-index:2).
   Микроанимация — от наведения/фокуса на ВСЮ карточку: только transform,
   геометрия карточки и текст неподвижны; без hover и при reduced-motion — статика. */
.tz-hero-bg{
  /* запас 1px за обрез геометрией, не transform — см. .tb-hero-bg */
  position:absolute; inset:-1px; width:calc(100% + 2px); height:calc(100% + 2px);
  object-fit:cover; z-index:1; transform-origin:center;
  transition:transform .35s cubic-bezier(.22,1,.36,1);
}
.tz-hero-vec{
  position:absolute; left:50%; top:50%; width:71%; height:auto; z-index:3;
  transform:translate(-50%,-50%);
  transition:transform .35s cubic-bezier(.22,1,.36,1);
}
@media (hover:hover) and (prefers-reduced-motion: no-preference){
  .tz-math:hover .tz-hero-vec, .tz-math:focus-within .tz-hero-vec{
    transform:translate(-50%,-50%) scale(1.06); }
  .tz-math:hover .tz-hero-bg,  .tz-math:focus-within .tz-hero-bg{ transform:scale(1.015); }
  .tz-math:hover .tz-sigma,    .tz-math:focus-within .tz-sigma{ transform:translateY(-1px); }
}
.tz-sigma{
  position:absolute; top:var(--space-4); left:var(--space-5); z-index:4;
  transition:transform .35s cubic-bezier(.22,1,.36,1);
  width:46px; height:46px; border-radius:var(--radius-md);
  background:var(--bg-card); border:1px solid var(--math-line);
  box-shadow:0 4px 12px rgba(36,88,211,.12); display:grid; place-items:center;
  color:var(--math-ink); font-family:var(--font-head); font-size:23px; font-weight:700; line-height:1;
}
.tz-eyebrow{ font-size:11px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--math-ink); }
.tz-h{ margin:0; font-size:23px; font-weight:700; line-height:1.15; }
.tz-note{ margin:0; font-size:13px; line-height:1.55; color:var(--text-secondary); }
/* VK ID — светлая кнопка со знаком: способ сохранить кабинет, а не платный барьер */
.vk-btn{
  display:flex; align-items:center; gap:var(--space-3); width:100%; margin-top:auto;
  padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg);
  background:var(--bg-card); border:1.5px solid var(--math-line); cursor:pointer;
  font-family:var(--font-head); font-size:15.5px; font-weight:600; color:var(--text-strong);
  text-align:left; line-height:1.25;
  transition:border-color .2s ease, box-shadow .2s ease, transform .1s ease;
}
.vk-btn:hover{ border-color:#8FB4F2; box-shadow:0 6px 18px rgba(36,88,211,.14); }
.vk-btn:active{ transform:scale(.99); }
.vk-mark{ width:34px; height:34px; border-radius:10px; background:#0077FF; color:#fff; flex:none;
  display:grid; place-items:center; }
.vk-mark svg{ width:22px; height:22px; }

/* ---- ПРИМЕРЫ ВИЗУАЛИЗАЦИЙ: десктоп — карусель, телефон — аккордеон ---- */
.section-sub{ margin:var(--space-6) 0 var(--space-3); font-size:15px; font-weight:600; color:var(--text-primary); }
.tz-rail{ position:relative; }
/* Кромки ленты = края рабочей колонки (правка Игоря 2026-08-16): прежний трюк
   «padding 20px + margin -20px» давал тени место, но выносил линию обреза на
   20px за колонку — справа лента читалась ШИРЕ верхних карточек. Совместить
   «тень не режется» и «обрез ровно по колонке» нельзя (линия обреза одна и та
   же), выравнивание важнее. Тени это переживут: спокойная — 28px при 5%
   непрозрачности, ховерную смягчили до 22px ещё 2026-08-10; вертикальный ход
   тени и подъём карточки укладываются в поля 14px сверху / 30px снизу. */
.tz-rail-scroll{
  display:flex; gap:var(--space-4); overflow-x:auto; scroll-behavior:smooth;
  scroll-snap-type:x mandatory; padding:14px 0 30px;
  scrollbar-width:none;
}
.tz-rail-scroll::-webkit-scrollbar{ display:none; }
.tz-arrow{
  position:absolute; top:calc(50% - 22px); z-index:4; width:44px; height:44px; border-radius:50%;
  border:1px solid var(--border-default); background:rgba(255,255,255,.92);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  box-shadow:0 4px 14px rgba(23,33,43,.10); color:var(--text-secondary);
  display:grid; place-items:center; cursor:pointer;
  transition:opacity .2s ease, color .2s ease, border-color .2s ease;
}
.tz-arrow:hover{ color:var(--text-primary); border-color:var(--border-secondary); }
.tz-arrow .ic{ width:20px; height:20px; }
.tz-flip{ transform:scaleX(-1); }
.tz-arrow.left{ left:-14px; }
.tz-arrow.right{ right:-14px; }
.tz-arrow[disabled]{ opacity:0; pointer-events:none; }
/* карточка визы — один и тот же DOM в карусели и в аккордеоне */
.vcard{
  flex:0 0 clamp(268px, 25.5vw, 320px); scroll-snap-align:start; min-width:0;
  background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-xl);
  box-shadow:var(--shadow-card); overflow:hidden; display:flex; flex-direction:column;
  transition:transform .15s, box-shadow .2s;
}
/* Подъём — как у карточки каталога (.cat-card, правка Игоря 2026-08-06), но тень мягче:
   в горизонтальной ленте хвост 34px упирался в кромку прокрутки и слева читался швом.
   22px укладываются в боковое поле ленты с запасом (правка Игоря 2026-08-10).
   Обводки при наведении нет (правка Игоря 2026-08-10): подъёма и тени достаточно. */
.vcard:hover{ transform:translateY(-3px);
  box-shadow:0 10px 22px rgba(23,17,10,.13), 0 3px 8px rgba(23,17,10,.08); }
.vface{
  display:flex; flex-direction:column; width:100%; text-align:left;
  border:0; background:none; padding:0; cursor:pointer; font:inherit; color:inherit;
}
.vthumb{
  position:relative; aspect-ratio:16/10; width:100%; overflow:hidden;
  border-bottom:1px solid var(--border-default); display:grid; place-items:center;
  background:linear-gradient(160deg,#F4FAF5 0%,#E9F3EC 100%);
}
.vcard[data-subject="math"] .vthumb{ background:linear-gradient(160deg,#F6F8FE 0%,#EBF0FC 100%); }
.vthumb svg{ width:100%; height:100%; display:block; }
.vtext{ padding:var(--space-4) var(--space-4) var(--space-3); display:flex; flex-direction:column; gap:6px; flex:1; }
/* строки заголовка и подписи ЗАФИКСИРОВАНЫ: место под две строки резервируется всегда,
   лишнее подрезается. Одна строка в названии или две — нижние строки карточек стоят в ряд */
.vtitle{
  font-family:var(--font-head); font-size:16px; font-weight:600; line-height:1.3; color:var(--text-strong);
  min-height:calc(2 * 1.3em); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.vsub{
  font-size:13px; line-height:1.5; color:var(--text-secondary);
  min-height:calc(2 * 1.5em); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.vchip-row{ padding:0 var(--space-4) var(--space-4); display:flex; align-items:center; justify-content:space-between; gap:var(--space-2); }
.vchip{
  display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:600; line-height:1.4;
  padding:4px 11px; border-radius:var(--radius-pill); width:max-content;
  background:var(--subject-bg-soft); color:var(--subject-primary);
}
.vcard[data-subject="math"] .vchip{ background:var(--quantity-blue-soft); color:#1E4AA8; }
.vchip svg{ width:13px; height:13px; }
.vopen{ font-size:13px; font-weight:600; color:var(--text-secondary); display:inline-flex; align-items:center; gap:4px; }
.vopen svg{ width:15px; height:15px; }
.vcard:hover .vopen{ color:var(--action-primary); }
.acc-chev{ display:none; }
.acc-panel{ display:none; }

/* поп-ап с живой визой */
.vzm{ position:fixed; inset:0; z-index:90; display:none; }
.vzm.is-on{ display:block; }
.vzm-back{ position:absolute; inset:0; background:rgba(23,17,10,.42);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px); }
.vzm-panel{
  position:absolute; inset:0; margin:auto; width:min(1180px,94vw); height:min(820px,90vh);
  background:var(--bg-card); border-radius:var(--radius-xl); box-shadow:0 30px 80px rgba(23,33,43,.28);
  display:flex; flex-direction:column; overflow:hidden;
}
.vzm-panel:focus{ outline:none; }        /* панель ловит фокус служебно */
.vzm-head{ display:flex; align-items:center; gap:var(--space-3); padding:var(--space-3) var(--space-4);
  border-bottom:1px solid var(--border-default); flex:none; }
.vzm-head h2{ margin:0; font-size:17px; font-weight:600; line-height:1.3; flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.vzm-body{ position:relative; flex:1; min-height:0; background:var(--bg-page); }
.vzm-body iframe{ width:100%; height:100%; border:0; display:block; }
.vzm-load{ position:absolute; inset:0; display:grid; place-items:center; background:var(--bg-page); }
.vzm-load.is-off{ display:none; }
body.vzm-open{ overflow:hidden; }

/* телефон: карточки виз становятся вертикальным аккордеоном */
@media (max-width:860px){
  .tz-arrow{ display:none; }
  .tz-rail-scroll{ flex-direction:column; gap:var(--space-3); overflow:visible;
    padding:0 0 var(--space-2); margin:0; }   /* аккордеон не прокручивается — поле под тень не нужно */
  .vcard{ flex:none; width:100%; }
  .vcard:hover{ transform:none; box-shadow:var(--shadow-card); }
  .vface{ flex-direction:row; align-items:center; gap:var(--space-3); padding:var(--space-3); }
  .vthumb{ aspect-ratio:1; width:60px; flex:none; border:1px solid var(--border-default);
    border-radius:var(--radius-md); overflow:hidden; }
  .vthumb svg{ transform:scale(1.18); }
  .vtext{ padding:0; gap:2px; }
  .vtext .vsub{ display:none; }
  .acc-chev{ display:grid; place-items:center; width:28px; height:28px; flex:none;
    color:var(--text-secondary); transition:transform .25s ease; }
  .acc-chev svg{ width:20px; height:20px; }
  .vcard.is-open .acc-chev{ transform:rotate(180deg); color:var(--action-primary); }
  .vchip-row{ display:none; }
  .acc-panel{ display:block; overflow:hidden; max-height:0; opacity:0;
    transition:max-height .3s ease, opacity .25s ease; }
  .vcard.is-open .acc-panel{ max-height:420px; opacity:1; }
  .acc-in{ padding:var(--space-4) var(--space-4) var(--space-4); display:flex; flex-direction:column;
    gap:var(--space-3); border-top:1px solid var(--border-default); margin-top:var(--space-1); }
  .acc-in .vsub{ display:block; font-size:14px; }
  .vzm-panel{ width:100vw; height:100dvh; border-radius:0; }
}
/* узкий телефон: строка метаданных перестаёт быть строкой — точка на переносе повисала */
@media (max-width:26em){
  .tz-meta{ flex-direction:column; align-items:flex-start; gap:2px; }
  .tz-meta .tz-dot{ display:none; }
}

/* ВВОДНЫЙ ЭКРАН СНЯТ 2026-08-10 (решение Игоря): он пересказывал то, что уже
   говорят «Детали урока» (обзор блоков) и сам урок. Кнопка тизера теперь ведёт
   прямо в урок, «Обзор урока» — в «Детали урока». */

/* ==================================================================
   УРОК (каркас эталона: читаемая колонка, текст прямо на фоне)
   ================================================================== */
.lesson{ padding:var(--space-6) var(--lesson-px) 0; }
.lesson h1{
  margin:0 0 var(--space-3); font-family:var(--font-head); font-weight:700;
  font-size:34px; line-height:1.15; letter-spacing:-.02em; color:var(--text-strong);
}
.lesson p{ margin:var(--space-4) 0; max-width:var(--measure); }
/* интерактив — не шире текста (единый блок чтения) */
.hero{ margin:var(--space-6) 0; max-width:var(--measure); }
figure.hero{ margin-left:0; margin-right:0; }
.hero-frame{ border:1px solid var(--border-default); border-radius:var(--radius-lg); overflow:hidden; background:var(--bg-page); }
.hero-head{
  display:flex; align-items:center; gap:var(--space-2); padding:var(--space-3) var(--space-4);
  background:var(--bg-card); border-bottom:1px solid var(--border-default);
}
.hero-head .ic{ width:18px; height:18px; color:var(--subject-primary); }
.hero-head .ht{ font-size:13px; font-weight:600; color:var(--text-primary); }
.hero-chip{ margin-left:auto; font-size:13px; color:var(--text-secondary);
  background:var(--bg-subtle); border-radius:var(--radius-pill); padding:2px 12px; white-space:nowrap; }
.hero-body{ position:relative; background:var(--bg-card); }
.hero-body > svg{ display:block; width:100%; height:auto; }
figcaption{ padding:var(--space-3) var(--space-4) var(--space-4); font-size:13px; line-height:1.5; color:var(--text-secondary); }
/* контролы интерактива */
.viz-controls{ padding:var(--space-4); border-top:1px solid var(--border-default); background:var(--bg-card); display:flex; flex-direction:column; gap:var(--space-3); }
.range-label{ display:flex; align-items:baseline; justify-content:space-between; font-size:14px; color:var(--text-secondary); }
.range-label b{ font-family:var(--font-mono); font-size:15px; color:var(--text-strong); }
input[type="range"]{
  width:100%; height:6px; border-radius:var(--radius-pill); appearance:none; -webkit-appearance:none;
  background:linear-gradient(to right,var(--quantity-blue-soft),var(--quantity-amber-soft));
  border:1px solid var(--border-default); cursor:pointer;
}
input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance:none; width:22px; height:22px; border-radius:50%;
  background:var(--action-primary); border:3px solid var(--bg-card); box-shadow:0 2px 6px rgba(0,0,0,.18); cursor:grab;
}
input[type="range"]::-moz-range-thumb{
  width:20px; height:20px; border-radius:50%; background:var(--action-primary);
  border:3px solid var(--bg-card); box-shadow:0 2px 6px rgba(0,0,0,.18); cursor:grab;
}
.viz-readout{ font-family:var(--font-mono); font-size:13.5px; color:var(--text-secondary); background:var(--bg-subtle);
  border-radius:var(--radius-sm); padding:8px var(--space-3); line-height:1.5; }
.ask{ margin:0; font-size:15px; font-weight:600; color:var(--text-primary); }
.answers{ display:flex; flex-direction:column; gap:var(--space-2); }
.answer{
  text-align:left; padding:11px var(--space-4); border-radius:var(--radius-md);
  border:1.5px solid var(--border-default); background:var(--bg-page); color:var(--text-primary);
  font:inherit; font-size:15px; cursor:pointer; transition:border-color .15s, background-color .15s;
}
.answer:hover{ border-color:var(--border-interactive); }
.answer[aria-pressed="true"]{ border-color:var(--subject-primary); background:var(--subject-bg-soft); }
.answer.is-right{ border-color:var(--state-success); background:var(--state-success-bg); }
/* «мимо» — нейтрально: без красного и без вины */
.answer.is-miss{ border-color:var(--border-interactive); background:var(--bg-subtle); color:var(--text-secondary); }
.lesson-status{
  font-size:14px; line-height:1.55; color:var(--text-secondary);
  background:var(--bg-subtle); border-radius:var(--radius-md); padding:10px var(--space-3);
}
.lesson-status.ok{ background:var(--state-success-bg); color:var(--state-success); }
/* формула-карточка */
.callout{
  display:flex; gap:var(--space-4); align-items:center; margin:var(--space-6) 0; padding:var(--space-4);
  border:1px solid var(--border-default); border-left:3px solid var(--subject-primary);
  border-radius:var(--radius-lg); background:var(--bg-card); max-width:var(--measure);
}
.callout-f{ flex:none; padding:var(--space-4); background:var(--subject-bg-soft); border-radius:var(--radius-sm);
  font-size:19px; color:var(--text-strong); white-space:nowrap; }
.callout-b h2{ margin:0 0 2px; font-family:var(--font-head); font-weight:700; font-size:17px; line-height:1.3; color:var(--text-strong); }
.callout-b p{ margin:0; font-size:15px; line-height:1.6; color:var(--text-secondary); }
/* скелетон продолжения */
.skl-group{ margin-top:var(--space-7); max-width:var(--measure); }
.skl{ height:12px; border-radius:var(--radius-pill); background:var(--shim-base); margin:var(--space-4) 0; }
.skl.h{ height:20px; width:38%; margin-bottom:var(--space-5); }
.skl.w1{ width:96%; } .skl.w2{ width:88%; } .skl.w3{ width:93%; } .skl.w4{ width:64%; }
/* переход к следующему блоку */
.lesson-next{ margin-top:var(--space-7); max-width:var(--measure); }
.lesson-next .next-open{
  display:flex; align-items:center; gap:var(--space-2); width:100%;
  padding:14px var(--space-5); border:1px solid transparent; border-radius:var(--radius-pill);
  background:var(--subject-bg-soft); color:var(--subject-primary);
  font:inherit; font-family:var(--font-head); font-size:15px; font-weight:600; cursor:pointer; text-align:left;
}
.lesson-next .next-open:hover{ border-color:var(--subject-border); }
.lesson-next .next-open .ic{ width:18px; height:18px; margin-left:auto; }
.lesson-next .next-locked{
  display:flex; align-items:center; gap:var(--space-3); flex-wrap:wrap;
  padding:14px var(--space-5); border:1px dashed var(--border-default); border-radius:var(--radius-lg);
  background:var(--bg-card); color:var(--text-secondary); font-size:14px;
}
.lesson-next .next-locked .ic{ width:17px; height:17px; }
.lesson-next .tn-t{ display:flex; flex-direction:column; font-weight:600; line-height:1.45; }
.lesson-next small{ font-size:12.5px; font-weight:400; }
/* действие у закрытого блока прижато вправо; на узком экране падает на свою строку */
.lesson-next .tn-cta{ margin-left:auto; flex:none; }

/* ==================================================================
   ШТАБ — по утверждённым вайрфреймам (_sandbox/wireframe/wireframe-shtab-v1
   и -desktop-v1, решения Игоря 2026-07-22/23).
   Десктоп: «Здесь и сейчас» (2/3) + «Практика» под ним слева, «Ближайшие
   события» справа во всю высоту обоих. Телефон: одноколоночная лента §12.2
   (Здесь-и-сейчас → События → Практика), фон светлый — зелёная зона только
   на разделах, Штаб на телефоне остаётся на листе.
   ================================================================== */
.hq-grid{
  /* высота строки-шапки: лейбл секции и вкладки-закладки живут в ней вместе,
     поэтому «Здесь и сейчас», выбор предмета и «Ближайшие события» стоят на одном
     уровне, а блоки под ними начинаются с одной линии (правка Игоря 2026-07-27) */
  /* строка лейбла + зазор «лейбл → блок» 24 − интерлиньяж под чернилами (метрика в :root) */
  --hq-head-h:calc(var(--lab-line) + var(--space-5) - var(--lab-lead));
  display:grid; grid-template-columns:minmax(0,2fr) minmax(0,1fr);
  grid-template-areas:"now events" "practice events";
  gap:var(--space-6) var(--space-5);
  /* --hq-drop считает JS (alignHqToRail): опускает сетку так, чтобы верхние рёбра
     карточек легли на линию верха рейла (правка Игоря 2026-08-06). Подписи и
     вкладыши едут вместе с карточками и остаются над линией; на телефоне 0 */
  margin-top:var(--hq-drop, 0px);
}
/* ДЕСКТОП: переключатель предмета встаёт в строку лейбла справа (решение Игоря 2026-07-27).
   Порядок в разметке (лейбл → вкладки → карточка) не меняется — раскладку даёт grid,
   поэтому на телефоне те же элементы возвращаются в колонку и вкладки липнут к карточке. */
.zone-now{
  grid-area:now; min-width:0;
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"label tabs" "card card";
  align-items:stretch; column-gap:var(--space-4); row-gap:0;
}
.zone-now > .section-label{ grid-area:label; }
.zone-now > .hq-tabs{ grid-area:tabs; justify-self:end; }   /* закладки прижаты к правому краю карточки */
.zone-now > .hq-card{ grid-area:card; }
.zone-practice{ grid-area:practice; min-width:0; }
.zone-events{ grid-area:events; display:flex; flex-direction:column; min-width:0; }
.zone-events > .hq-card{ flex:1; }
/* строка-шапка одинаковой высоты во всех зонах: текст сверху, остаток — воздух до блока */
.section-label{
  font-size:var(--lab-size); font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--text-secondary); display:flex; align-items:flex-start;
  min-height:var(--hq-head-h); line-height:var(--lab-line);
}
/* дизайн-прогон 2026-07-27: карточка держится мягкой тенью, а не рамкой —
   внутренние плашки тоже лишились рамок, ушли «коробки в коробках» */
.hq-card{
  --hq-fade-bg:var(--bg-card);
  background:var(--bg-card); border:0; box-shadow:var(--shadow-card);
  border-radius:var(--radius-xl); padding:var(--space-5);
}

/* ---- ВКЛАДЫШИ-ЗАКЛАДКИ предмета (канон п.5 CONVENTIONS).
   Десктоп: стоят в строке-шапке справа, текст на одном уровне с лейблами секций,
   плашка занимает всю высоту шапки и перетекает в карточку вогнутыми уголками.
   Телефон: те же закладки во всю ширину карточки (media ≤860). ---- */
.hq-tabs{ display:flex; align-items:stretch; position:relative; z-index:3; }
/* текст закладки прижат к верху зоны — иначе кнопка центрует его и подпись
   уезжает ниже лейблов секций; плашка при этом остаётся во всю высоту шапки */
.hq-tab{
  position:relative; display:flex; align-items:flex-start; justify-content:center;
  cursor:pointer; white-space:nowrap;
  border:0; background:none; font:inherit; padding:0 16px; font-size:14.5px; font-weight:600;
  color:var(--text-secondary); transition:color .18s ease;
}
.hq-tab > span{ position:relative; z-index:2; line-height:22px; }
.hq-tab:not(.active):hover{ color:var(--text-primary); }
.hq-tab.active{ color:var(--text-strong); font-weight:700; }
/* плашка активной = вся зона закладки, цвет обложки; уходит на 1px в карточку */
.hq-tab.active::before{
  content:''; position:absolute; inset:0 0 -1px; z-index:1;
  background:var(--action-primary-bg); border-radius:var(--radius-md) var(--radius-md) 0 0;
}
/* вогнутые уголки-fillet: плашка перетекает в карточку без обрубка */
.hq-tab .f{ display:block; position:absolute; bottom:-1px; width:12px; height:12px; z-index:1;
  background:var(--action-primary-bg); }
.hq-tab .f.l{ left:-12px;
  -webkit-mask:radial-gradient(circle at top left, transparent 12px, #000 12px);
          mask:radial-gradient(circle at top left, transparent 12px, #000 12px); }
.hq-tab .f.r{ right:-12px;
  -webkit-mask:radial-gradient(circle at top right, transparent 12px, #000 12px);
          mask:radial-gradient(circle at top right, transparent 12px, #000 12px); }
.hq-tab:last-child .f.r{ display:none; }        /* крайняя справа доходит до края карточки */
.hq-now.sel-right{ border-top-right-radius:0; } /* угол под ней выпрямлен */
/* метка «придержано» на другом предмете — только в мягком приоритет-локе */
.hq-tab .held{
  display:none; margin-left:var(--space-2); font-size:9.5px; font-weight:700;
  text-transform:uppercase; letter-spacing:.03em; color:var(--state-warning);
  border:1px solid color-mix(in srgb, var(--state-warning) 40%, transparent);
  border-radius:var(--radius-pill); padding:1px 7px; vertical-align:middle;
}
body.pri-lock .hq-tab:not(.active) .held{ display:inline; }

/* ---- «Здесь и сейчас»: обложка + название модуля на ней + степпер + кнопки ---- */
.hq-now{
  border:0; box-shadow:var(--shadow-card); padding:0; overflow:hidden;
  display:flex; flex-direction:column; border-radius:var(--radius-xl);
}
/* (углы под вкладыш выпрямляются только на телефоне — там вкладыш касается карточки) */
.hq-cover{
  position:relative; overflow:hidden; flex:none; height:clamp(170px, 17vw, 224px);
  background:
    radial-gradient(120% 90% at 78% 8%, rgba(255,255,255,.55), transparent 60%),
    linear-gradient(135deg, var(--action-primary-bg) 0%, #CFE7D8 46%, #A9D6BC 100%);
}
/* низ обложки утекает под текст — ключевой приём карточки урока */
.hq-cover::after{
  content:''; position:absolute; left:0; right:0; bottom:-1px; height:58%; z-index:2;
  background:linear-gradient(to bottom, transparent, var(--bg-card)); pointer-events:none;
}
/* дата — лёгкая пилюля (тяжёлый бейдж перетягивал внимание с названия темы) */
/* одна левая линия: метки поверх обложки инсетятся так же, как название и тело карточки */
.date-chip{
  position:absolute; top:var(--space-4); left:var(--space-5); z-index:3;
  background:rgba(255,255,255,.86); -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  border-radius:var(--radius-pill); padding:4px 12px;
  font-size:12px; font-weight:700; color:var(--text-strong); letter-spacing:.02em;
}
.cov-pill{
  position:absolute; top:var(--space-4); right:var(--space-5); z-index:3;
  display:inline-flex; align-items:center; gap:6px;
  font-size:12px; font-weight:700; padding:4px 12px; border-radius:var(--radius-pill);
  background:rgba(255,255,255,.86); -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  color:var(--menu-selected);
}
.cov-pill i{ width:7px; height:7px; border-radius:50%; background:var(--action-bright); display:block; }
.cover-title{ position:absolute; left:var(--space-5); right:var(--space-5); bottom:var(--space-4); z-index:3; }
.cover-eyebrow{ font-size:11px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--menu-selected); }
.cover-h{ font-size:31px; font-weight:800; line-height:1.08; letter-spacing:-.01em;
  color:var(--text-strong); margin-top:4px; text-wrap:balance; }
.now-body{ padding:var(--space-5); display:flex; flex-direction:column; flex:1; }

/* ---- ПРОГРЕСС-ЛЕНТА блоков (§11.3): сегмент = блок урока.
   У каждого сегмента своя дорожка с рамкой — видно и всю долю, и сколько залито;
   заливка растёт по мере прохождения. Подпись блока — по центру под дорожкой. ---- */
.track{ display:flex; gap:var(--space-2); }
.seg{ flex:1; min-width:0; border:0; background:none; padding:0; cursor:pointer;
  display:flex; flex-direction:column; align-items:stretch; }
.seg .bar{
  height:10px; border-radius:var(--radius-pill); overflow:hidden;
  background:var(--bg-card); border:1px solid var(--border-secondary);
}
.seg .bar > span{ display:block; height:100%; width:0; background:var(--action-primary);
  border-radius:var(--radius-pill); transition:width .3s ease; }
.seg.done .bar{ border-color:var(--action-primary); }
.seg.current .bar{ border-color:var(--action-primary); }
.seg.locked .bar{ background:repeating-linear-gradient(135deg, var(--state-locked-bg) 0 6px, #E6E3DA 6px 12px);
  border-color:var(--border-default); }
/* подпись ближе к своей дорожке (4), чем дорожки друг к другу (8) — иначе привязка теряется */
.seg .st-lab{ display:block; margin-top:var(--space-1); text-align:center;
  font-size:12px; font-weight:600; color:var(--text-secondary); line-height:1.25; }
.seg.current .st-lab{ color:var(--menu-selected); font-weight:700; }
.seg.locked .st-lab{ color:var(--state-locked); }
.seg.locked{ cursor:default; }

/* зазор внутри меты меньше, чем до следующей группы — иначе проксимити читается наоборот */
.now-meta{ font-size:13px; color:var(--text-secondary); margin-top:var(--space-4);
  display:flex; gap:var(--space-4); flex-wrap:wrap; }
/* пояснение к закрытому блоку: место под ДВЕ строки заложено всегда, иначе карточка
   прыгает при переключении предмета (у одного пояснение длиннее, у другого короче) */
/* margin обнулён явно: у <p> во flex-колонке браузерный margin-bottom не схлопывается
   и молча добавлял 12.5px перед кнопкой — значение в коде расходилось с фактом */
.hq-quiet{
  display:flex; gap:var(--space-2); align-items:flex-start; margin:var(--space-3) 0 0;
  min-height:calc(2 * 1.5em);           /* резерв в em: две строки на любом кегле */
  font-size:13px; line-height:1.5; color:var(--text-secondary);
}
.hq-quiet .ic{ width:15px; height:15px; flex:none; margin-top:2px; color:var(--state-locked); }
/* мягкий приоритет-лок: метка и смена смысла кнопки — без жёлтого блока и без вины */
.overdue-banner{ display:none; gap:var(--space-2); align-items:flex-start; margin:var(--space-3) 0 0;
  min-height:calc(2 * 1.5em); font-size:13px; line-height:1.5; color:var(--state-warning); }
.overdue-banner .ic{ width:15px; height:15px; flex:none; margin-top:2px; }
.overdue-banner .ob-t{ font-weight:700; }
body.pri-lock .overdue-banner{ display:flex; }
body.pri-lock .hq-quiet{ display:none; }        /* одна причина за раз, не две подряд */
/* решение Игоря 2026-07-27: сигнал о просрочке несут ТОЛЬКО метка и подпись.
   Кнопка остаётся зелёной — действие есть действие; меняется лишь её текст. */

/* главное действие во всю ширину, второстепенное — ссылкой без черты (правка Игоря) */
.now-cta-row{ display:flex; align-items:center; gap:var(--space-4); margin-top:var(--space-5); }
.now-cta-row .btn.v-primary{ flex:1; }
/* «Обзор урока» — второстепенное действие: цвет приглушён, чтобы не спорить
   с главной зелёной кнопкой рядом (правка Игоря 2026-07-29) */
.now-cta-row .btn.v-link{ flex:none; text-decoration:none; color:var(--text-secondary); font-weight:500; }
.now-cta-row .btn.v-link:hover{ color:var(--text-primary); }

/* ---- «Ближайшие события»: цель недели + день-стрип + плашки.
   Плашка-заливка цели снята, черта-разделитель убрана — группы разделяет воздух.
   Правило зелёного (решение 2026-07-28): зелёный получают ДОСТИГНУТОЕ и действие —
   поэтому число «сделано» зелёное, а служебный текст вокруг остаётся нейтральным ---- */
.week-goal{ display:flex; align-items:center; gap:var(--space-3); margin-bottom:var(--space-5); }
.week-goal .wg-num{ font-family:var(--font-head); font-size:26px; font-weight:800;
  color:var(--menu-selected); line-height:1; flex:none; }
.week-goal .wg-num small{ font-size:15px; font-weight:600; color:var(--text-secondary); }
.week-goal .wg-body{ flex:1; min-width:0; }
.week-goal .wg-t{ font-size:13.5px; font-weight:600; color:var(--text-primary); }
.week-goal .wg-bar{ height:4px; border-radius:var(--radius-pill); margin-top:7px; overflow:hidden;
  background:var(--bg-subtle); }
.week-goal .wg-bar span{ display:block; height:100%; border-radius:var(--radius-pill); background:var(--action-primary); }
.week-goal .wg-meta{ font-size:12px; color:var(--text-secondary); flex:none; white-space:nowrap; }
/* день-стрип: целые дни, при сжатии их становится меньше (7 → 6 → 5), навигация стрелками */
.daynav{ position:relative; margin-bottom:var(--space-5); }
.daystrip{
  display:grid; grid-auto-flow:row; grid-template-columns:repeat(auto-fit, minmax(46px, 1fr));
  gap:var(--space-2); padding:0 26px; max-height:54px; overflow:hidden;
}
.daynav::before, .daynav::after{ content:''; position:absolute; top:0; bottom:0; width:30px; z-index:2; pointer-events:none; }
.daynav::before{ left:0;  background:linear-gradient(to right, var(--hq-fade-bg) 30%, transparent); }
.daynav::after{  right:0; background:linear-gradient(to left,  var(--hq-fade-bg) 30%, transparent); }
.daynav .arrow{ position:absolute; top:0; bottom:0; z-index:3; width:26px;
  border:0; background:transparent; color:var(--text-secondary); cursor:pointer;
  display:grid; place-items:center; }
.daynav .arrow .ic{ width:18px; height:18px; }
.daynav .arrow.left{ left:0; transform:rotate(180deg); }
.daynav .arrow.right{ right:0; }
.daynav .arrow:hover{ color:var(--action-primary); }
/* дни без рамок — только числа и точки-маркеры; выбранный = заливка */
.day{ height:52px; min-width:0; cursor:pointer; border:0; background:none;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  border-radius:var(--radius-md); font:inherit; padding:0; }
.day:hover{ background:var(--bg-subtle); }
.day .dow{ font-size:9px; text-transform:uppercase; letter-spacing:.03em; color:var(--text-secondary); }
.day .num{ font-size:15px; font-weight:700; color:var(--text-primary); line-height:1; }
.day .mark{ width:5px; height:5px; border-radius:var(--radius-pill); background:transparent; }
/* просрочка — только метка и подпись (решение 2026-07-28): день-стрип её НЕ красит.
   Точка = «в этот день есть задача», одинаковая для всех дней; жёлтые точки и жёлтые
   числа сняты — сигнал живёт в группе «Задолженности» (метка + подпись) */
.day .mark.has, .day .mark.due{ background:var(--action-primary); }
.day.today .num{ color:var(--action-primary); }
.day.sel{ background:var(--action-primary); }
.day.sel .dow, .day.sel .num{ color:#fff; }
.day.sel .mark.has{ background:#fff; }
/* плашки: сначала задолженности, потом очередь. Без рамок; просрочка = ТОЛЬКО
   жёлтая метка и подпись (решение 2026-07-28) — ни жёлтых блоков, ни жёлтых точек */
/* лестница зазоров в карточке событий: 24 (группа) > 16 (подгруппа) > 4 (строки).
   Значения не схлопываются — что написано, то и видно в DevTools */
.tgroup{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-secondary); margin:0 0 var(--space-1); }
.tgroup.up{ margin-top:var(--space-4); }
/* разделителей нет вовсе (правка Игоря 2026-07-27): строки разделяет только воздух */
.tasklist{ display:flex; flex-direction:column; gap:var(--space-1); }
.task{ display:flex; align-items:flex-start; gap:var(--space-3); width:100%; text-align:left;
  padding:10px 8px; border:0; border-radius:var(--radius-md); background:none; font:inherit; cursor:pointer; }
.task:hover{ background:var(--bg-subtle); }
.task .tdot{ width:8px; height:8px; border-radius:var(--radius-pill); background:var(--action-primary); margin-top:7px; flex:none; }
.task .tbody{ flex:1; min-width:0; display:block; }
.task .tt, .task .tdetails{ display:block; }
.task .tflag{ display:inline-block; font-size:10.5px; font-weight:700; text-transform:uppercase;
  letter-spacing:.04em; color:var(--state-warning); margin-bottom:3px; }
.task .tt{ font-size:14.5px; font-weight:600; color:var(--text-primary); line-height:1.35; }
.task .tsub{ font-size:12.5px; color:var(--text-secondary); margin-top:2px; display:flex; gap:var(--space-3); flex-wrap:wrap; }
.task .tdetails{ display:none; }                /* действие читается по строке и стрелке */
.task .ic{ width:16px; height:16px; color:var(--text-secondary); flex:none; margin-top:5px; }
.task:hover .ic{ color:var(--action-primary); }
/* у просроченной строки точка обычная: сигнал несут только метка .tflag и подпись */
/* выход к полному периоду — в «Календарь» (§16). Второстепенное действие = ссылка:
   рамка делала из него единственную «коробку» в карточке, из которой рамки убраны */
.tasks-all{ width:100%; margin-top:var(--space-4); border:0; background:none;
  border-radius:var(--radius-md); padding:12px; cursor:pointer; font:inherit;
  font-size:13.5px; font-weight:600; color:var(--menu-selected); min-height:44px; }
.tasks-all:hover{ background:var(--bg-subtle); }

/* ---- «Практика для тебя»: блоки-направления (не список задач) ---- */
/* плитка кликабельна целиком — стрелка убрана; описание в две строки */
.pdirs{ display:grid; grid-template-columns:1fr 1fr; gap:var(--space-4); }
.pdir{ display:flex; align-items:flex-start; gap:var(--space-3); text-align:left; font:inherit;
  padding:var(--space-4); border:0; box-shadow:var(--shadow-card);
  border-radius:var(--radius-lg); background:var(--bg-card); cursor:pointer;
  transition:box-shadow .18s ease, transform .12s ease; }
.pdir:hover{ box-shadow:0 2px 4px rgba(23,33,43,.05), 0 18px 40px rgba(23,33,43,.10); transform:translateY(-1px); }
.pdir .pd-ic{ width:44px; height:44px; border-radius:14px; flex:none;
  display:grid; place-items:center; background:var(--action-primary-bg); color:var(--action-primary);
  font-size:20px; font-weight:600; }
.pdir .pd-ic .ic{ width:22px; height:22px; }
.pdir .pd-body{ flex:1; min-width:0; display:block; }
.pdir .pd-t{ display:block; font-family:var(--font-head); font-size:15.5px; font-weight:700;
  color:var(--text-strong); line-height:1.2; }
.pdir .pd-s{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  font-size:12.5px; color:var(--text-secondary); margin-top:4px; line-height:1.4; }
/* слот под 4-й тип тренажёра */
.pdir.ghost{ background:none; box-shadow:none; border:1px dashed var(--border-secondary); cursor:default; }
.pdir.ghost:hover{ transform:none; box-shadow:none; }
.pdir.ghost .pd-ic{ background:none; border:1px dashed var(--border-secondary); color:var(--text-secondary); }
.pdir.ghost .pd-t{ color:var(--text-secondary); font-weight:600; }
/* раскладка направлений зафиксирована 2×2: в один ряд четыре блока сминают текст
   (проверено глазами 2026-07-27) — ряд из четырёх снят */

/* ==================================================================
   МОИ РАЗБОРЫ (минимальный P1-слой, §12.5)
   ================================================================== */
.review-toolbar{ display:flex; gap:var(--space-3); flex-wrap:wrap; margin-bottom:var(--space-4); }
.field{
  border:1.5px solid var(--border-interactive); border-radius:var(--radius-md); background:var(--bg-card);
  padding:9px var(--space-3); font:inherit; font-size:14.5px; color:var(--text-primary);
}
.field:focus{ outline:none; border-color:var(--focus-ring); }
.review-search-input{ min-width:min(320px,100%); }
.review-list{ display:flex; flex-direction:column; gap:var(--space-4); }
.review-card{
  background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-xl);
  padding:var(--space-5); display:flex; flex-direction:column; gap:var(--space-3);
}
.review-meta{ display:flex; gap:var(--space-3); align-items:center; flex-wrap:wrap; font-size:13px; color:var(--text-secondary); }
.review-card h2{ margin:0; font-size:18px; font-weight:700; }
.qa{ display:flex; flex-direction:column; gap:6px; font-size:14.5px; line-height:1.6; }
.qa b{ font-size:12px; letter-spacing:.05em; text-transform:uppercase; color:var(--text-secondary); }
.qa p{ margin:0 0 var(--space-2); }
.review-empty{ padding:var(--space-5); text-align:center; color:var(--text-secondary); }

/* ==================================================================
   МОЙ ПУТЬ (§11.5–11.6) + ДЕТАЛИ УРОКА (§11.2–11.4).
   Эталоны: _sandbox/wireframe/wireframe-moy-put-v1.html и wireframe-urok-v1.html.
   Телефон ≤860 — ЗЕЛЁНАЯ ЗОНА (CONVENTIONS п.4–5): тёмный топбар + хедер + полоса
   вкладышей несут ОДИН горизонтальный градиент 90deg #0A5A2A → --menu-selected.
   Десктоп — светлая неоморфная стилистика кабинета (карточки тенью, без рамок).
   Правило зелёного (2026-07-28) действует и здесь: зелёный — достигнутому
   (заливки прогресса/mastery, ✓) и действию; роли блоков и условия — нейтральные.
   ================================================================== */
:root{ --zone-grad:linear-gradient(90deg, #0A5A2A 0%, var(--menu-selected) 100%); }

/* ---- хедер страницы: на десктопе — обычный view-head, на телефоне — зелёный герой ---- */
.path-hero h1{ margin:0 0 4px; font-size:32px; line-height:1.15; font-weight:700; }
.path-hero .ph-sub{ margin:0; color:var(--text-secondary); font-size:15px; }
.path-hero{ margin:0 0 var(--space-5); }
.path-hero > .wrap{ padding-top:0; }

/* ---- МЕНЮ-ВКЛАДЫШ «предмет → курс»: ЕДИНЫЙ двухэтажный блок (ТЗ 2026-07-29).
   Геометрия: --jn-h — высота ОДНОЙ строки, R = h/2 считается от неё, а не от
   общей высоты двух строк (иначе торцы вырождаются в капсулу).
   Активный предмет — непрозрачная плашка цвета нижнего ряда; срастается с ним
   вогнутыми уголками-fillet <i class="f l/r"> (CONVENTIONS п.5) ---- */
/* тень-растворение под липким меню снята (правка Игоря 2026-07-29): читалась как лишняя полоса.
   Сверху 4px воздуха цветом листа — прилипнув, меню не касается топбара;
   снизу полосы нет: контент уходит прямо под меню */
.jnav-sticky{ position:sticky; top:calc(var(--pbar-h) + var(--topbar-h)); z-index:15;
  background:none; padding-top:4px; }
.jnav-wrap{ padding-top:var(--space-2); padding-bottom:0; }   /* полосы фона под меню нет */
/* фон верхнего ряда лежит на ВСЁМ блоке: тогда над скруглёнными верхними углами
   белого нижнего ряда виден цвет первого ряда, а не лист (правка Игоря 2026-07-29) */
.jnav{
  --jn-h:34px;                                    /* высота одной строки */
  --jn-r:calc(var(--jn-h) / 2);                   /* R = h / 2 */
  --jn-face:#FCFBF8;                              /* активный вкладыш = нижний ряд */
  /* НЕпрозрачный: липкая секция вокруг меню теперь прозрачна, и сквозь полупрозрачный
     фон просвечивал бы проезжающий текст страницы (правка Игоря 2026-07-29) */
  --jn-shade:color-mix(in srgb, var(--text-strong) 7%, var(--bg-page));
  /* --jn-gap = весь отступ от кромки липкой секции до блока меню: ровно на эту
     высоту поднимается шторка, иначе часть зазора остаётся прозрачной (десктоп) */
  --jn-gap:calc(4px + var(--space-2));
  background:var(--jn-shade); border-radius:var(--jn-r); position:relative;
}
/* шторка цветом листа: закрывает и зазор над меню, и ВЫРЕЗЫ скруглённых верхних
   углов, в которых просвечивала проезжающая страница. Лежит ПОД фоном меню
   (z-index:-1), поэтому скругления сохраняются; по ширине — ровно блок меню,
   так что сбоку от него страница по-прежнему видна */
.jnav::before{ content:''; position:absolute; z-index:-1; left:0; right:0;
  top:calc(-1 * var(--jn-gap)); height:calc(var(--jn-gap) + var(--jn-r)); background:var(--bg-page); }
.jn-top{ display:flex; align-items:stretch; }
.jn-subj{
  position:relative; flex:0 1 auto; min-height:var(--jn-h); padding:0 22px;
  display:inline-flex; align-items:center; justify-content:center;
  border:0; background:none; font:inherit; font-size:13.5px; font-weight:700;
  color:var(--text-secondary); cursor:pointer; white-space:nowrap; transition:color .18s ease;
}
.jn-subj > span{ position:relative; z-index:2; }
.jn-subj:not(.active):hover{ color:var(--text-primary); }
.jn-subj.active{ color:var(--text-strong); }
.jn-subj.active::before{
  content:''; position:absolute; inset:0 0 -1px; z-index:1;
  background:var(--jn-face); border-radius:var(--jn-r) var(--jn-r) 0 0;
}
/* левый и правый уголки одинаковые: оба радиусом R, оба цветом плашки */
.jn-subj .f{ display:none; position:absolute; bottom:-1px; width:var(--jn-r); height:var(--jn-r);
  z-index:1; background:var(--jn-face); }
.jn-subj.active .f{ display:block; }
.jn-subj .f.l{ left:calc(-1 * var(--jn-r));
  -webkit-mask:radial-gradient(circle at top left, transparent var(--jn-r), #000 var(--jn-r));
          mask:radial-gradient(circle at top left, transparent var(--jn-r), #000 var(--jn-r)); }
.jn-subj .f.r{ right:calc(-1 * var(--jn-r));
  -webkit-mask:radial-gradient(circle at top right, transparent var(--jn-r), #000 var(--jn-r));
          mask:radial-gradient(circle at top right, transparent var(--jn-r), #000 var(--jn-r)); }
/* уголок гасим только там, где вкладка реально упирается в край блока: слева — всегда
   (первая вкладка стоит у кромки), справа — лишь на телефоне, где зоны растянуты во всю
   ширину. На десктопе у последней вкладки справа остаётся серый фон, значит нужен скруг */
.jn-subj:first-child .f.l{ display:none; }
/* нижний ряд: те же R по углам, кроме угла, которым он сросся с вкладышем */
.jn-bot{ position:relative; display:flex; align-items:center; gap:var(--space-2);
  min-height:var(--jn-h); padding:var(--space-2) var(--space-3);
  background:var(--jn-face); border-radius:var(--jn-r); }
.jnav.first-active .jn-bot{ border-top-left-radius:0; }
.jnav.last-active  .jn-bot{ border-top-right-radius:0; }

/* лента курсов: горизонтальный скролл со скрытым ползунком (ТЗ §7) */
.jn-scroll-wrap{ position:relative; flex:1 1 auto; min-width:0; }
.jn-scroll-wrap::before, .jn-scroll-wrap::after{ content:''; position:absolute; top:0; bottom:0; width:22px; z-index:2;
  pointer-events:none; opacity:0; transition:opacity .18s ease; }
.jn-scroll-wrap::before{ left:0; background:linear-gradient(to right, var(--jn-face), transparent); }
.jn-scroll-wrap::after{ right:0; background:linear-gradient(to left, var(--jn-face), transparent); }
.jn-scroll-wrap.fade-left::before{ opacity:1; }
.jn-scroll-wrap.fade-right::after{ opacity:1; }
/* padding по вертикали обязателен: overflow-x:auto режет по вертикали, и нижняя
   грань контурных чипов срезалась (правка Игоря 2026-07-29) */
.jn-scroll{ display:flex; align-items:center; gap:var(--space-2); overflow-x:auto;
  padding:2px 0; scrollbar-width:none; -ms-overflow-style:none; -webkit-overflow-scrolling:touch; }
.jn-scroll::-webkit-scrollbar{ height:0; width:0; }
.jn-course{ flex:none; display:inline-flex; align-items:stretch; border-radius:var(--radius-pill); }
/* свой курс: мягкая mint-заливка, без подчёркивания и без рамки */
.jc-name{ border:0; background:none; font:inherit; font-size:12.5px; font-weight:600; white-space:nowrap;
  color:var(--text-secondary); padding:5px 12px; border-radius:var(--radius-pill); cursor:pointer;
  transition:background-color .18s ease, color .18s ease; }
.jc-name:hover{ color:var(--text-primary); }
.jn-course.active .jc-name{ background:var(--action-primary-bg); color:var(--menu-selected); font-weight:700; }
/* допкурс: контурный чип — название и «+» внутри ОДНОЙ рамки, между ними тонкий разделитель.
   Никаких «Купить», цен и корзины: «+» ведёт в описание курса (К15) */
.jn-course.extra{ border:1px solid var(--border-default); overflow:hidden; }
.jn-course.extra .jc-name{ border-radius:0; padding-right:9px; }
.jc-div{ flex:none; width:1px; align-self:stretch; margin:5px 0; background:var(--border-default); }
.jc-plus{ flex:none; border:0; background:none; font:inherit; font-size:14px; font-weight:700; line-height:1;
  color:var(--action-primary); padding:0 10px; cursor:pointer; align-self:stretch;
  transition:background-color .18s ease; }
.jc-plus:hover{ background:var(--action-primary-bg); }

/* ---- рабочая область: desktop = месяцы 30 / детали 70 (ТЗ §4) ---- */
.path-work{ display:grid; grid-template-columns:minmax(0,3fr) minmax(0,7fr); gap:var(--space-4);
  /* воздух под двухэтажным меню: было space-2 (8) — блоки липли к навигации (правка Игоря 2026-08-06) */
  align-items:start; margin-top:var(--space-5); }
.worklist{ padding:var(--space-2); }
.wl-head{ display:flex; align-items:center; gap:var(--space-2); padding:var(--space-2) var(--space-2) var(--space-3); }
.wl-head h2{ margin:0; flex:1; min-width:0; font-family:var(--font-head); font-size:14.5px; font-weight:700; color:var(--text-strong); }
.wl-body{ max-height:min(72vh, 660px); overflow-y:auto; }   /* §11.6: ~13–15 строк, внутренний скролл */
.path-detail{ min-width:0; }
.sf-btn{
  flex:none; display:inline-flex; align-items:center; gap:var(--space-2);
  padding:5px var(--space-3); border-radius:var(--radius-pill);
  border:1px solid var(--border-default); background:var(--bg-card);
  font:inherit; font-size:12px; font-weight:600; color:var(--text-secondary); cursor:pointer;
}
.sf-btn:hover{ border-color:var(--action-primary); color:var(--action-primary); }
.sf-btn .ic{ width:13px; height:13px; }

/* ---- ДЕТАЛИ ВЫБРАННОГО УРОКА (ТЗ §5–6): раздатка сверху, содержимое слева,
   этапы справа (70/30). Тот же рендер работает и в inline-раскрытии на телефоне ---- */
/* раздатка тянется над обеими колонками, содержимое и этапы стартуют с одного уровня;
   этапы расширены до 40% — в 30% названия жались (правка Игоря 2026-07-29) */
.ld{ display:grid; grid-template-columns:minmax(0,6fr) minmax(0,4fr);
  grid-template-areas:"mats mats" "main stages"; gap:var(--space-3) var(--space-4); align-items:start; }
.ld-mats{ grid-area:mats; display:flex; flex-wrap:wrap; gap:var(--space-2); }
.ld-main{ grid-area:main; }
.ld-stages{ grid-area:stages; }
.ld-main, .ld-stages{ background:var(--bg-card); border-radius:var(--radius-xl);
  box-shadow:var(--shadow-card); padding:var(--space-4); }
/* раздатка §11.7: иконка + название + формат, скачивание понятно без подписи «файл» */
.mat-btn{ display:inline-flex; align-items:center; gap:var(--space-2);
  padding:6px 14px 6px 11px; border:1px solid var(--border-default); border-radius:var(--radius-pill);
  background:var(--bg-card); box-shadow:var(--shadow-card);
  font:inherit; font-size:12.5px; font-weight:600; color:var(--text-primary); cursor:pointer; }
.mat-btn .ic{ width:15px; height:15px; flex:none; color:var(--text-secondary); }
.mat-btn small{ font-weight:500; color:var(--text-secondary); }
.mat-btn:hover{ border-color:var(--action-primary); color:var(--action-primary); }
.mat-btn:hover .ic{ color:var(--action-primary); }
.ld-head{ display:flex; align-items:center; gap:var(--space-2); margin-bottom:var(--space-3); }
.ld-head h3{ margin:0; flex:1; min-width:0; font-family:var(--font-head); font-size:15px; font-weight:700; color:var(--text-strong); }
.ld-step{ flex:none; font-size:11.5px; font-weight:700; color:var(--text-secondary);
  background:var(--bg-subtle); padding:3px 10px; border-radius:var(--radius-pill); white-space:nowrap; }
/* рабочая область интерактива: сцена рисуется inline-SVG, тянется по ширине */
.ld-stage{ border:1px solid var(--border-default); border-radius:var(--radius-lg);
  overflow:hidden; background:var(--bg-card); }
.ld-stage svg{ display:block; width:100%; height:auto; }
.ld-video{ position:relative; aspect-ratio:16/9; border-radius:var(--radius-lg); overflow:hidden;
  background:linear-gradient(135deg,#163626,var(--action-primary)); display:grid; place-items:center; }
.ld-video .play{ width:56px; height:56px; border-radius:50%; background:rgba(255,255,255,.93);
  display:grid; place-items:center; color:var(--action-primary); }
.ld-video .play .ic{ width:22px; height:22px; }
.ld-instr{ margin:var(--space-3) 0 0; font-size:13px; font-weight:600; color:var(--text-primary); }
/* та же стилистика, что у степпера Штаба: дорожка с рамкой, заливка = пройдено.
   Отступ снизу обязателен — шкала стоит НАД сценой и не должна её касаться */
.ld-prog{ height:10px; margin-bottom:var(--space-3); border-radius:var(--radius-pill); overflow:hidden;
  background:var(--bg-card); border:1px solid var(--action-primary); }
.ld-prog > span{ display:block; height:100%; border-radius:var(--radius-pill);
  background:var(--action-primary); transition:width .2s ease; }   /* заливка = достигнутое */
.ld-cta{ width:100%; margin-top:var(--space-4); }
.ld-empty{ padding:var(--space-6); font-size:14px; color:var(--text-secondary); }

/* этапы урока: статус + шкала + тихое текстовое действие (не CTA) */
.lst-head{ display:flex; align-items:baseline; gap:var(--space-2); margin-bottom:var(--space-2); }
.lst-head h3{ margin:0; flex:1; font-family:var(--font-head); font-size:14px; font-weight:700; color:var(--text-strong); }
.lst-head .lst-count{ flex:none; font-size:11.5px; font-weight:700; color:var(--text-secondary); }
/* колонка действия фиксированной ширины: длина шкалы не должна зависеть от того,
   что написано справа — «Повторить» или «Откроется позже» (правка Игоря 2026-07-29) */
.lst{ display:grid; grid-template-columns:22px minmax(0,1fr) 104px; align-items:start;
  gap:var(--space-3); padding:var(--space-2) 0; }
.lst-ic{ width:22px; height:22px; flex:none; border-radius:50%; display:grid; place-items:center;
  font-size:11px; font-weight:700; background:var(--bg-subtle); color:var(--text-secondary); }
.lst-ic .ic{ width:12px; height:12px; }
.lst.done .lst-ic{ background:var(--action-primary-bg); color:var(--menu-selected); }
.lst.current .lst-ic{ background:var(--action-primary); color:#fff; }
.lst-body{ flex:1; min-width:0; }
.lst-name{ font-size:12.5px; font-weight:600; color:var(--text-primary); line-height:1.25; }
.lst.locked .lst-name{ color:var(--text-secondary); font-weight:500; }
/* дорожка с рамкой — как у степпера «Здесь и сейчас»; закрытый этап штрихуется,
   не красится в тревожный цвет */
.lst-bar{ margin-top:6px; height:8px; border-radius:var(--radius-pill); overflow:hidden;
  background:var(--bg-card); border:1px solid var(--border-secondary); }
.lst-bar > span{ display:block; height:100%; border-radius:var(--radius-pill); background:var(--action-primary); transition:width .2s ease; }
.lst.done .lst-bar, .lst.current .lst-bar{ border-color:var(--action-primary); }
.lst.locked .lst-bar{ border-color:var(--border-default);
  background:repeating-linear-gradient(135deg, var(--state-locked-bg) 0 6px, #E6E3DA 6px 12px); }
.lst-act{ align-self:center; justify-self:end; border:0; background:none; padding:2px 0;
  font:inherit; font-size:11.5px; font-weight:600; color:var(--text-secondary); cursor:pointer;
  white-space:nowrap; text-align:right; }
.lst-act:hover{ color:var(--action-primary); }
.lst-act.is-next{ color:var(--menu-selected); font-weight:700; }   /* текущий этап — единственное «Продолжить» */
.lst-act.is-off{ color:var(--state-locked); cursor:default; }

/* ---- месяц (StudyPeriod) — аккордеон; разделяет воздух, не рамки ---- */
.pm-head{
  width:100%; display:flex; align-items:center; gap:var(--space-3);
  padding:var(--space-3) var(--space-3); border:0; background:none; font:inherit; cursor:pointer;
  border-radius:var(--radius-md); text-align:left;
}
.pm-head:hover{ background:var(--bg-subtle); }
.pm-head .chev{ width:16px; height:16px; flex:none; color:var(--text-secondary); transform:rotate(-90deg); transition:transform .15s; }
.pm.open > .pm-head .chev{ transform:rotate(0); }
.pm-name{ font-family:var(--font-head); font-size:15.5px; font-weight:700; color:var(--text-strong); flex:1; min-width:0; }
.pm-status{ font-size:12px; font-weight:600; color:var(--text-secondary); flex:none; }
.pm.done .pm-status{ color:var(--state-success); }          /* завершённый месяц — достигнутое, зелёное */
/* месяц не куплен (поздний ученик §13.5): спокойная плашка, не платный замок */
.pm.locked{ background:var(--state-locked-bg); border-radius:var(--radius-md); margin-bottom:var(--space-1); }
.pm.locked .pm-head{ cursor:default; }
.pm.locked .pm-head:hover{ background:none; }
.pm.locked .pm-name{ color:var(--state-locked); display:flex; align-items:center; gap:var(--space-2); }
.pm.locked .pm-name .ic{ width:15px; height:15px; }
.pm-upsell{ padding:0 var(--space-3) var(--space-3); }
.pm-upsell p{ margin:0 0 var(--space-3); font-size:13px; line-height:1.5; color:var(--text-secondary); }
/* подпись предмета в режиме «Все» (§11.5: обзор без деталей) */
.pm-subj{ margin:var(--space-3) var(--space-3) var(--space-1); font-size:11px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--text-secondary); }
.pm-subj:first-child{ margin-top:var(--space-1); }

/* ---- строка урока (§11.6: дата · тема · статус · progress) ---- */
.ples{ display:none; padding:0 var(--space-1) var(--space-2); flex-direction:column; gap:2px; }
.pm.open > .ples{ display:flex; }
.pl-row{
  width:100%; display:flex; align-items:center; gap:var(--space-3);
  padding:10px var(--space-2); border:0; background:none; font:inherit; cursor:pointer;
  border-radius:var(--radius-md); text-align:left;
}
.pl-row:hover{ background:var(--bg-subtle); }
.pl.sel > .pl-row{ background:var(--action-primary-bg); }   /* спокойная mint-подсветка выбранного */
.pl-date{
  flex:none; width:38px; text-align:center; border-radius:var(--radius-sm); overflow:hidden;
  background:var(--bg-card); box-shadow:0 1px 3px rgba(23,33,43,.10); line-height:1;
}
.pl-date .m{ display:block; font-size:8px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--action-on-primary); background:var(--action-primary); padding:3px 0 2px; }
.pl-date .d{ display:block; font-family:var(--font-head); font-size:15px; font-weight:800; color:var(--text-strong); padding:3px 0; }
.pl.locked .pl-date .m{ background:var(--border-interactive); }
.pl-body{ flex:1; min-width:0; }
.pl-title{ font-size:14.5px; font-weight:600; color:var(--text-primary); line-height:1.3; }
.pl.locked .pl-title{ color:var(--text-secondary); font-weight:500; }
.pl-meta{ display:flex; align-items:center; gap:var(--space-2); margin-top:3px; }
.pl-status{ font-size:10.5px; font-weight:700; padding:1px 8px; border-radius:var(--radius-pill); white-space:nowrap; }
.pl-status.done{ background:var(--state-success-bg); color:var(--state-success); }
.pl-status.current{ background:var(--action-primary-bg); color:var(--menu-selected); }
.pl-status.locked{ background:var(--state-locked-bg); color:var(--state-locked); }
.pl-status.open{ background:var(--bg-subtle); color:var(--text-secondary); }
/* шкала по образцу степпера «Здесь и сейчас» (Штаб): дорожка с рамкой видна и на
   мятной подсветке выбранного, и под курсором — сплошная заливка бы сливалась */
.pl-prog{ flex:1; max-width:120px; height:8px; border-radius:var(--radius-pill); overflow:hidden;
  background:var(--bg-card); border:1px solid var(--border-secondary); }
.pl-prog span{ display:block; height:100%; background:var(--action-primary); border-radius:var(--radius-pill); }  /* заливка = достигнутое */
.pl.sel .pl-prog, .pl-row:hover .pl-prog{ border-color:var(--action-primary); }
.pl-chev{ flex:none; width:16px; height:16px; color:var(--text-secondary); transform:rotate(-90deg); transition:transform .15s; }
.pl.sel .pl-chev{ transform:rotate(0); }
/* значок типа содержимого (видео / интерактив / теория) — у невыбранных строк */
.pl-type{ flex:none; width:24px; height:24px; border-radius:var(--radius-sm, 8px); display:grid; place-items:center;
  background:var(--bg-subtle); color:var(--text-secondary); }
.pl-type .ic{ width:13px; height:13px; }
.pl.sel .pl-type{ display:none; }
.pl.locked .pl-type{ opacity:.5; }
/* стрелка появляется ТОЛЬКО у раскрытого урока и означает «свернуть»: там, где детали
   живут в правой карточке, сворачивать нечего (правка Игоря 2026-07-29) */
.pl-chev{ display:none; }
.pl.is-open .pl-chev{ display:block; transform:rotate(0); }

/* ---- детали урока: на телефоне раскрываются ВНИЗ под строкой, на десктопе — правая карточка ---- */
/* inline-раскрытие (телефон): детали стоят СРАЗУ под своей строкой, внутри месяца */
.pl-detail{ display:none; }
.pl.sel > .pl-detail{ display:block; padding:var(--space-2) var(--space-2) var(--space-3); }
/* градиент раскрытого урока идёт ОДНОЙ заливкой: от верха строки урока до низа
   деталей, а не отдельно внутри каждой части (правка Игоря 2026-07-29) */
.pl.is-open{ border-radius:var(--radius-lg); background:linear-gradient(to bottom,
    color-mix(in srgb, var(--action-primary-bg) 85%, transparent) 0%,
    color-mix(in srgb, var(--action-primary-bg) 30%, transparent) 55%,
    transparent 100%); }
.pl.is-open > .pl-row{ background:none; }
/* при раскрытии на телефоне верх блока не должен уезжать под липкое меню */
.pl{ scroll-margin-top:calc(var(--pbar-h) + var(--topbar-h) + 96px); }

/* ссылка на раздатку внутри карточки блока (экран «Детали урока»): иконка + название + формат.
   Цвет нейтральный: зелёный экономим на достигнутое и главное действие (правило 2026-07-28) */
.mat-link{
  display:inline-flex; align-items:center; gap:6px;
  border:0; background:none; padding:2px 0; font:inherit; font-size:12.5px; font-weight:600;
  color:var(--text-primary); cursor:pointer; text-align:left;
}
.mat-link .ic{ width:15px; height:15px; flex:none; color:var(--text-secondary); }
.mat-link small{ font-size:11.5px; font-weight:500; color:var(--text-secondary); }
.mat-link:hover > span{ text-decoration:underline; }

/* ==================================================================
   ЭКРАН «ДЕТАЛИ УРОКА» — пересобран 2026-08-10 по макету Игоря.
   Было: обложка 16/9 + степпер + четыре rich-карточки 2×2.
   Стало: шапка (дата · предмет · тема · материалы · кольцо «сколько
   блоков закрыто» · иллюстрация) и ВЕРТИКАЛЬНЫЙ АККОРДЕОН этапов.
   Один DOM на оба макета: десктоп — широкая строка с правой колонкой
   действия, телефон — карточки в один столбец, иллюстрация сверху,
   главное действие уезжает в липкую панель над капсулой меню.
   Смыслы §11.2–11.4 сохранены: «пройдено» ≠ «освоено», порог у замка
   назван числом, роль блока подписана словом, цвет — только достигнутому.
   ================================================================== */
.det-crumbs{ display:none; }               /* зелёная полоса крошек — только на телефоне */
.det-wrap{ max-width:var(--container-max); }

/* ---- шапка урока ---- */
.ld2-hero{
  display:grid; gap:var(--space-5); align-items:center;
  grid-template-columns:minmax(0,1fr) auto minmax(0,clamp(260px,32%,430px));
  grid-template-areas:"main ring illu";
  background:var(--bg-card); border-radius:var(--radius-xl); box-shadow:var(--shadow-card);
  padding:var(--space-5); margin-bottom:var(--space-4);
}
.ld2-main{ grid-area:main; min-width:0; }
.ld2-idline{ display:flex; align-items:center; flex-wrap:wrap; gap:var(--space-3); }
.ld2-date{ flex:none; padding:3px 12px; border-radius:var(--radius-pill);
  border:1px solid var(--border-default); font-size:12.5px; font-weight:700; color:var(--text-strong); }
.ld2-eyebrow{ font-size:11.5px; font-weight:700; letter-spacing:.07em;
  text-transform:uppercase; color:var(--subject-primary); }
.ld2-title{ margin:var(--space-3) 0 0; font-size:34px; font-weight:800; line-height:1.08; letter-spacing:-.015em; }
.ld2-mats-lab{ margin:var(--space-4) 0 var(--space-2); font-size:13px; color:var(--text-secondary); }
.ld2-mats{ display:flex; flex-wrap:wrap; gap:var(--space-3); }

/* кольцо считает ЗАВЕРШЁННЫЕ БЛОКИ, а не проценты: «2 / 4» — та же мера,
   что у степпера строки урока, и её нельзя спутать с mastery */
.ld2-ring{ grid-area:ring; justify-self:center; text-align:center; }
.ld2-ring .dial{ position:relative; width:132px; height:132px; margin:0 auto; }
.ld2-ring .dial svg{ position:absolute; inset:0; width:100%; height:100%; }
/* flex, а не grid: в grid «2», «/» и «4» стали бы тремя строками-элементами */
.ld2-ring .dial b{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head); font-size:29px; font-weight:800; color:var(--text-strong); letter-spacing:-.01em; }
.ld2-ring .dial b i{ font-style:normal; font-weight:500; color:var(--text-secondary); margin:0 1px; }
.ld2-ring .cap{ margin-top:var(--space-2); font-size:13px; font-weight:600; color:var(--text-primary); }
.ld2-ring .sub{ font-size:12px; color:var(--text-secondary); }

.ld2-illu{ grid-area:illu; margin:0; border-radius:var(--radius-lg); overflow:hidden;
  background:var(--action-primary-bg); }
.ld2-illu.is-math{ background:var(--state-info-bg); }
.ld2-illu svg{ display:block; width:100%; height:auto; }

/* ---- аккордеон этапов: на десктопе один лист с разделителями ---- */
.ld2-acc{ background:var(--bg-card); border-radius:var(--radius-xl); box-shadow:var(--shadow-card); overflow:hidden; }
.sg{ position:relative; }
/* раскрытый этап = слабая подложка + зелёная черта слева: «вы здесь» держится
   двумя признаками сразу, не одним цветом */
.sg.is-open{ background:color-mix(in srgb, var(--bg-page) 55%, var(--bg-card)); }
.sg.is-open::before{ content:''; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--action-primary); }
/* у закрытого этапа черта нейтральная: зелёный держим за достигнутым и действием */
.sg.is-locked.is-open::before{ background:var(--border-secondary); }
.sg.is-locked .sg-name b{ color:var(--text-secondary); }

/* строка = ряд, а НЕ одна кнопка: внутри живут собственные кнопки (действие,
   кебаб), а вложенный <button> в <button> — невалидная разметка. Раскрытие
   вешаем на широкий .sg-toggle и на шеврон (тот декоративный, tabindex=-1) */
.sg-head{ display:flex; align-items:center; gap:var(--space-3); padding-right:var(--space-5); }
.sg-head:hover{ background:color-mix(in srgb, var(--bg-page) 45%, transparent); }
/* у раскрытого этапа строка не подсвечивается: наведение обещало бы «сейчас откроется»,
   а этап уже открыт — подсветка только делила карточку надвое */
.sg.is-open .sg-head:hover{ background:none; }
.sg-toggle{ flex:1; min-width:0; display:flex; align-items:center; gap:var(--space-4);
  padding:var(--space-4) var(--space-2) var(--space-4) var(--space-5);
  border:0; background:none; font:inherit; text-align:left; cursor:pointer; }
.sg-chev-btn{ flex:none; display:grid; place-items:center; width:24px; height:24px;
  border:0; background:none; padding:0; cursor:pointer; }
/* Нить между узлами рисуется НА СТРОКЕ (две половины через её центр), а не отрезком
   фиксированной длины у узла: у строки замка правая колонка «условие открытия» выше
   узла, и короткий отрезок не доставал до кромки — нить рвалась. Узел стоит поверх. */
.sg-head{ position:relative; }
.sg-head::before, .sg-head::after{ content:''; position:absolute; z-index:0; width:2px;
  left:calc(var(--space-5) + 17px); transform:translateX(-50%); background:var(--border-default); }
.sg-head::before{ top:0; height:50%; }
.sg-head::after{ top:50%; bottom:0; }
.sg-nodewrap{ position:relative; z-index:1; flex:none; display:grid; place-items:center; }
.sg.is-done .sg-head::before, .sg.is-done .sg-head::after,
.sg.is-current .sg-head::before{ background:var(--action-primary); }
/* у раскрытого этапа нитки нет ни сверху, ни снизу: рядом с приподнятой карточкой
   она вырождалась в зелёные огрызки. «Вы здесь» держит зелёная черта слева */
.sg:first-child .sg-head::before, .sg:last-child .sg-head::after,
.sg.is-open .sg-head::before, .sg.is-open .sg-head::after,
.sg:has(+ .sg.is-open) .sg-head::after, .sg.is-open + .sg .sg-head::before{ display:none; }
.sg.is-done .sg-nodewrap::before, .sg.is-done .sg-nodewrap::after,
.sg.is-current .sg-nodewrap::before{ background:var(--action-primary); }
.sg-node{ width:34px; height:34px; border-radius:var(--radius-pill); display:grid; place-items:center;
  font-family:var(--font-head); font-size:14px; font-weight:800;
  background:var(--bg-card); border:2px solid var(--border-default); color:var(--text-secondary); }
.sg-node .ic{ width:16px; height:16px; }
.sg.is-done .sg-node{ background:var(--action-primary); border-color:var(--action-primary); color:#fff; }
.sg.is-current .sg-node{ background:var(--action-primary); border-color:var(--action-primary); color:#fff;
  box-shadow:0 0 0 4px var(--action-primary-bg); }
.sg.is-open .sg-node{ background:var(--action-primary); border-color:var(--action-primary); color:#fff; }
.sg.is-locked .sg-node{ background:var(--state-locked-bg); border-color:var(--border-default); color:var(--state-locked); }
.sg-name{ flex:none; font-size:16px; color:var(--text-strong); line-height:1.3; }
.sg-name b{ font-family:var(--font-head); font-weight:700; }
.sg-name span{ color:var(--text-secondary); font-weight:500; }
.sg-head .pill{ flex:none; }
/* мета в одну строку: в узкой рабочей области она иначе рассыпается по слову на строку */
.sg-meta{ flex:1; min-width:0; font-size:13px; color:var(--text-secondary);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* у замка мета повторяла бы правую колонку «условие открытия» — на десктопе одна из них */
@media (min-width:861px){ .sg.is-locked .sg-meta{ display:none; } }
/* тихое действие строки: главная зелёная кнопка на экране одна, поэтому здесь — текст */
.sg-act{ flex:none; border:0; background:none; padding:2px 0; font:inherit; font-size:13.5px;
  font-weight:700; color:var(--action-primary); cursor:pointer; }
.sg-act:hover{ text-decoration:underline; }
.sg-act.is-off{ color:var(--state-locked); font-weight:600; cursor:default; }
/* у раскрытого этапа действие живёт в теле — в строке оно дублировало бы само себя */
.sg.is-open .sg-act{ display:none; }
.sg-chev{ flex:none; width:18px; height:18px; color:var(--text-secondary); transition:transform .18s ease; }
.sg.is-open .sg-chev{ transform:rotate(180deg); }
/* кебаб — только телефон: на узкой строке текстовое действие не помещается */
.sg-more-wrap{ position:relative; flex:none; display:none; }
.sg-more{ display:grid; place-items:center; width:28px; height:28px; border:0; background:none;
  border-radius:var(--radius-sm); color:var(--text-secondary); cursor:pointer; }
.sg-more .ic{ width:18px; height:18px; }
.sg-menu{ display:none; position:absolute; right:0; top:calc(100% + 4px); z-index:5; min-width:190px;
  padding:var(--space-1); background:var(--bg-card); border-radius:var(--radius-md);
  box-shadow:0 10px 30px rgba(23,17,10,.18); }
.sg.menu-open .sg-menu{ display:block; }
.sg-menu button{ display:block; width:100%; padding:10px var(--space-3); border:0; background:none;
  border-radius:var(--radius-sm); font:inherit; font-size:14px; color:var(--text-primary);
  text-align:left; cursor:pointer; }
.sg-menu button:hover{ background:var(--bg-subtle); }

/* условие открытия — прямо в свёрнутой строке замка (десктоп): ученик видит,
   сколько осталось, не раскрывая блок */
.sg-gate{ flex:none; width:230px; }
.sg-gate .g-lab{ display:block; font-size:12px; color:var(--text-secondary); }
.sg-gate .g-val{ display:block; font-size:13.5px; font-weight:600; color:var(--text-primary); margin-top:1px; }
.sg-gate .g-bar{ position:relative; display:block; height:8px; margin-top:6px; border-radius:var(--radius-pill);
  background:var(--bg-subtle); overflow:hidden; }
.sg-gate .g-goal{ position:absolute; top:0; bottom:0; left:0; background:var(--action-primary-bg); }
.sg-gate .g-fill{ position:relative; z-index:1; display:block; height:100%;
  border-radius:var(--radius-pill); background:var(--action-primary); }
.sg-gate .g-note{ display:block; margin-top:6px; font-size:12px; color:var(--text-secondary); }

/* ---- тело этапа ---- */
.sg-body{ display:none; padding:0 var(--space-5) var(--space-5) calc(var(--space-5) + 34px + var(--space-4)); }
.sg.is-open > .sg-body{ display:grid; gap:var(--space-5); align-items:start; }
/* панель замка — текст, а не таблица: во всю ширину листа она читалась бы строкой в 130 знаков */
.sg.is-open > .sg-body.cols-1{ grid-template-columns:minmax(0,760px); }
.sg.is-open > .sg-body.cols-2{ grid-template-columns:minmax(0,1.4fr) minmax(0,1fr); }
.sg.is-open > .sg-body.cols-3{ grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(200px,auto); }
.sg-col{ min-width:0; }
.sg-body.cols-2 > .sg-col + .sg-col, .sg-body.cols-3 > .sg-col + .sg-col{
  border-left:1px solid var(--border-default); padding-left:var(--space-5); }
.sg-next{ font-size:12.5px; font-weight:700; color:var(--action-primary); }
.sg-step{ margin:2px 0 var(--space-3); font-family:var(--font-head); font-size:16px;
  font-weight:700; color:var(--text-strong); }
/* роль отвечает только «обязателен ли этап»; число порога живёт у шкалы и в замке */
.sg-role{ margin-top:var(--space-3); font-size:12px; font-weight:600; color:var(--text-secondary); }
.sg-mlab{ font-size:14.5px; font-weight:600; color:var(--text-primary); margin-bottom:var(--space-2); }
.sg-mbar{ height:10px; border-radius:var(--radius-pill); background:var(--bg-subtle); overflow:hidden; }
.sg-mbar > span{ display:block; height:100%; border-radius:var(--radius-pill); background:var(--action-primary); }
.sg-mnote{ margin-top:var(--space-2); font-size:12px; color:var(--text-secondary); }
.sg-ctalab{ font-size:13px; color:var(--text-secondary); margin-bottom:var(--space-3); text-align:center; }
.sg-cta .btn{ width:100%; }
.sg-mat{ margin-top:var(--space-3); }

/* ---- липкая панель главного действия (телефон) ---- */
.ld2-sticky{ display:none; }

/* темы блока (§11.4): ✓ / ● / закрыто + причина; человек-гейт назван по имени */
.tp-list{ display:flex; flex-direction:column; gap:var(--space-2); }
.tp{ display:flex; align-items:flex-start; gap:var(--space-2); font-size:13px; line-height:1.4; }
.tp-ic{ width:18px; height:18px; flex:none; border-radius:var(--radius-pill); display:grid; place-items:center;
  background:var(--bg-card); border:1.5px solid var(--border-default); color:var(--text-secondary); margin-top:1px; }
.tp-ic .ic{ width:10px; height:10px; }
.tp-ic i{ width:7px; height:7px; border-radius:var(--radius-pill); background:currentColor; }
.tp.done .tp-ic{ background:var(--state-success); border-color:var(--state-success); color:#fff; }
.tp.open .tp-ic{ border-color:var(--action-primary); color:var(--action-primary); }
.tp.locked .tp-ic{ background:var(--state-locked-bg); color:var(--state-locked); }
.tp-body{ flex:1; min-width:0; }
.tp-name{ font-weight:600; color:var(--text-primary); }
.tp.locked .tp-name{ color:var(--text-secondary); font-weight:500; }
.tp-req{ font-size:11.5px; color:var(--text-secondary); }
/* метрики: «пройдено» ≠ «освоено» (§11.3); заливка mastery зелёная — это достигнутый
   уровень; недобор до порога показывает риска, а не тревожный цвет */
.mt-list{ display:flex; flex-direction:column; gap:var(--space-2); padding-top:var(--space-1); }
.mt-row{ display:flex; justify-content:space-between; font-size:11.5px; margin-bottom:3px; }
.mt-name{ color:var(--text-secondary); font-weight:600; }
.mt-val{ color:var(--text-primary); font-weight:700; }
.mt-bar{ position:relative; height:6px; border-radius:var(--radius-pill); background:var(--bg-subtle); overflow:hidden; }
.mt-bar > span{ display:block; position:relative; z-index:1; height:100%; border-radius:var(--radius-pill); background:var(--action-primary); }
.mt-bar.progress > span{ background:var(--border-secondary); }
/* порог БЕЗ цифр на шкале (правка Игоря 2026-07-28): «зона цели» — мягкая подложка
   от нуля до порога + тонкая засечка на её границе. Заливка дошла до конца подложки —
   порог взят. Числа живут только в строке значений над шкалой. */
.mt-goal{ position:absolute; top:0; bottom:0; left:0; background:var(--action-primary-bg); }
.mt-thr{ position:absolute; top:0; bottom:0; width:2px; z-index:2;
  background:color-mix(in srgb, var(--text-strong) 55%, transparent); }
/* закрытый блок: причина + действие + полное условие под ⓘ (без давления и вины) */
.lk-panel{ display:flex; flex-direction:column; gap:var(--space-2); }
.lk-reason{ display:flex; align-items:center; gap:var(--space-2); font-size:13px; font-weight:700; color:var(--state-locked); }
.lk-reason .ic{ width:15px; height:15px; flex:none; }
.lk-action{ font-size:13px; line-height:1.5; color:var(--text-primary); }
.lk-action b{ color:var(--text-strong); }
.lk-full{ border:1px solid var(--border-default); border-radius:var(--radius-md); background:var(--bg-card); }
.lk-full > summary{ cursor:pointer; list-style:none; padding:var(--space-2) var(--space-3);
  font-size:12.5px; font-weight:600; color:var(--text-primary); display:flex; align-items:center; gap:6px; }
.lk-full > summary:hover{ background:var(--bg-subtle); border-radius:var(--radius-md); }
.lk-full > summary::-webkit-details-marker{ display:none; }
.lk-full[open] > summary{ border-bottom:1px solid var(--border-default); }
.lk-cond{ padding:var(--space-3); font-size:12.5px; color:var(--text-secondary); display:flex; flex-direction:column; gap:6px; }
.lk-c{ display:flex; align-items:flex-start; gap:var(--space-2); }
.lk-c .ic{ width:14px; height:14px; flex:none; margin-top:2px; }
.lk-c.ok{ color:var(--state-success); }
.lk-c b{ color:var(--text-strong); }

/* ---- узкий десктоп: рабочая область в один столбец. Правая карточка деталей теряет
   смысл (она уезжала бы под весь список месяцев), поэтому детали раскрываются ВНУТРИ
   строки урока — ровно как при открытом чате (правка Игоря 2026-07-29) ---- */
@media (max-width:1150px){
  .path-work{ grid-template-columns:1fr; }
  .path-detail{ display:none !important; }
  .wl-body{ max-height:none; }
  /* «Детали урока» на узком десктопе: иллюстрация ложится над шапкой во всю
     ширину, кольцо остаётся справа от темы; тело этапа теряет колонку действия */
  .ld2-hero{ grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"illu illu" "main ring"; align-items:start; }
  /* иллюстрация во всю ширину раздулась бы в плиту ~500px — держим её полосой */
  .ld2-illu{ height:200px; display:grid; place-items:center; }
  .ld2-illu svg{ height:100%; width:auto; max-width:100%; }
  .ld2-title{ font-size:29px; }
  /* в узкой строке уточнение темы уступает место мете и действию */
  .sg-name span{ display:none; }
  .sg.is-open > .sg-body.cols-3{ grid-template-columns:minmax(0,1.4fr) minmax(0,1fr); }
  .sg-body.cols-3 > .sg-cta{ grid-column:1 / -1; border-left:0; padding-left:0;
    display:flex; align-items:center; gap:var(--space-4); }
  .sg-body.cols-3 > .sg-cta .sg-ctalab{ margin:0; text-align:left; }
  .sg-body.cols-3 > .sg-cta .btn{ width:auto; }
}
@media (min-width:861px) and (max-width:1150px){
  .pl.sel > .pl-detail{ display:block; padding:var(--space-3) var(--space-3) var(--space-4); }
}
@media (min-width:1151px){
  /* широкий десктоп: детали живут справа, строка не раскрывается — КРОМЕ открытого чата */
  body:not(.chat-open) .pl-detail{ display:none !important; }
}
/* ---- открытый чат (зона 3): рабочая область узкая, поэтому детали переезжают
   ВНУТРЬ строки урока — как на телефоне, но в десктопном оформлении
   (правка Игоря 2026-07-29). Правая карточка при этом не нужна ---- */
body.chat-open .path-work{ grid-template-columns:1fr; }
body.chat-open .path-detail{ display:none !important; }
body.chat-open .wl-body{ max-height:none; }
@media (min-width:861px){
  body.chat-open .pl.sel > .pl-detail{ display:block; padding:var(--space-3) var(--space-3) var(--space-4); }
}
@media (min-width:1151px){
  /* открытый чат сужает рабочую область — «Детали урока» переходят в ту же
     раскладку, что и на узком десктопе */
  body.chat-open .ld2-hero{ grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"illu illu" "main ring"; align-items:start; }
  body.chat-open .sg.is-open > .sg-body.cols-3{ grid-template-columns:minmax(0,1.4fr) minmax(0,1fr); }
  body.chat-open .sg-body.cols-3 > .sg-cta{ grid-column:1 / -1; border-left:0; padding-left:0;
    display:flex; align-items:center; gap:var(--space-4); }
  body.chat-open .sg-body.cols-3 > .sg-cta .sg-ctalab{ margin:0; text-align:left; }
  body.chat-open .sg-body.cols-3 > .sg-cta .btn{ width:auto; }
}
/* совсем узкая колонка (планшет с чатом) — этапы уходят под содержимое */
@media (max-width:1150px){
  body.chat-open .ld{ grid-template-columns:1fr; grid-template-areas:"mats" "main" "stages"; }
}

/* ==================================================================
   ТЕЛЕФОН ≤860 — ЗЕЛЁНАЯ ЗОНА разделов (CONVENTIONS п.4–5).
   Хром: тёмный топбар с тем же градиентом, белый логотип и иконки.
   ================================================================== */
@media (max-width:860px){
  body[data-zone="green"] .page{ padding-top:0; }
  body[data-zone="green"] .topbar{ background:var(--zone-grad); border-bottom:0; }
    body[data-zone="green"] .topbar .icon-btn{
    color:#fff; background:rgba(255,255,255,.10);
    border:1px solid rgba(255,255,255,.28); border-radius:var(--radius-pill);
  }
  body[data-zone="green"] .notif-dot{ background:var(--brand-course); border-color:transparent; }
  body[data-zone="green"] .profile-btn .avatar{
    background:rgba(255,255,255,.10); box-shadow:none;
    border:1px solid rgba(255,255,255,.28); color:#fff;
  }
  /* «Мой путь» на телефоне — светлый лист (решение 2026-07-29): зелёным красим
     только достигнутое и активный вкладыш. Топбар при этом всё так же уезжает
     при скролле вниз и возвращается вверх (механика ниже, --tb-off) */
  .path-hero{ margin:0; }
  .path-hero > .wrap{ padding-top:var(--space-3); padding-bottom:var(--space-2); }
  .path-hero h1{ font-size:22px; }
  .path-hero .ph-sub{ font-size:12.5px; }
  .jnav-sticky{ top:calc(var(--pbar-h) + var(--topbar-h) - var(--tb-off, 0px)); }
  .jnav-wrap{ padding-top:var(--space-1); padding-bottom:0; }
  .jnav{ --jn-gap:calc(4px + var(--space-1)); }   /* на телефоне отступ секции меньше */
  /* верхняя и нижняя строки одинаковой внешней ширины; сверху — три равные зоны */
  .jn-subj{ flex:1 1 0; padding:0 8px; font-size:13px; }
  .jn-subj:last-child .f.r{ display:none; }   /* крайняя зона доходит до кромки блока */
  /* рабочая область в колонку; правая карточка скрыта — детали раскрываются inline */
  .path-work{ grid-template-columns:1fr; margin-top:var(--space-2); }
  .path-detail{ display:none !important; }
  .worklist{ background:var(--bg-card); border:0;
    box-shadow:var(--shadow-card); border-radius:var(--radius-xl); }
  .wl-body{ max-height:none; overflow:visible; }
  /* внутри строки урока места мало — содержимое, потом этапы */
  .ld{ grid-template-columns:1fr; grid-template-areas:"mats" "main" "stages"; gap:var(--space-3); }
  .ld-main, .ld-stages{ padding:var(--space-3); box-shadow:none; border:1px solid var(--border-default); }
  .ld-mats .mat-btn{ flex:1 1 140px; justify-content:center; }
  /* экран «Детали урока»: зелёная полоса крошек продолжает зону под топбаром */
  .det-crumbs{
    display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2);
    background:var(--zone-grad); padding:0 var(--space-4) var(--space-4);
    font-size:12.5px; color:rgba(255,255,255,.82);
  }
  .det-crumbs .det-back{ border:0; background:none; font:inherit; color:#fff; font-weight:700; cursor:pointer; padding:0; }
  .det-crumbs .sep{ opacity:.55; }
  .det-wrap{ padding-top:var(--space-4); }
  /* ---- «Детали урока» на телефоне: иллюстрация сверху, всё в один столбец,
     этапы — отдельные карточки, главное действие — липкая панель над капсулой ---- */
  .ld2-hero{ grid-template-columns:minmax(0,1fr) auto; grid-template-areas:"illu illu" "main ring";
    align-items:start; gap:var(--space-4); padding:var(--space-4); }
  .ld2-illu{ margin:calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) 0;
    height:auto; border-radius:var(--radius-xl) var(--radius-xl) 0 0; }
  .ld2-illu svg{ width:100%; height:auto; }
  .ld2-title{ font-size:26px; }
  .ld2-ring .dial{ width:96px; height:96px; }
  .ld2-ring .dial b{ font-size:23px; }
  .ld2-ring .cap{ font-size:12px; }
  .ld2-ring .sub{ display:none; }              /* на телефоне подпись дублировала подсчёт блоков */
  /* два столбца ломали русские названия на три строки — на телефоне по одной кнопке в ряд */
  .ld2-mats{ display:grid; grid-template-columns:1fr; gap:var(--space-2); }
  .ld2-mats .mat-btn{ justify-content:center; text-align:center; }
  @media (min-width:521px){ .ld2-mats{ grid-template-columns:1fr 1fr; } }
  /* лист рассыпается на карточки: касание бьётся по одной строке, а не по всему листу */
  .ld2-acc{ background:none; box-shadow:none; border-radius:0; overflow:visible;
    display:flex; flex-direction:column; gap:var(--space-3); }
  /* overflow видимый: иначе карточка режет выпадающее меню кебаба */
  .sg{ background:var(--bg-card); border-radius:var(--radius-xl); box-shadow:var(--shadow-card); }
  .sg.is-open::before{ border-radius:3px; }
  .sg + .sg{ border-top:0; }
  .sg.is-locked{ background:var(--state-locked-bg); box-shadow:none; }
  .sg-head::before, .sg-head::after{ display:none; }   /* нитку рвут зазоры между карточками */
  .sg-head{ padding-right:var(--space-3); }
  .sg-toggle{ flex-wrap:wrap; gap:var(--space-2) var(--space-3);
    padding:var(--space-4) 0 var(--space-4) var(--space-4); }
  .sg-node{ width:30px; height:30px; font-size:13px; }
  .sg-name{ flex:1; min-width:0; font-size:15.5px; }
  .sg-name span{ display:none; }               /* уточнение темы не помещается — остаётся роль */
  .sg-meta{ flex-basis:100%; order:3; padding-left:calc(30px + var(--space-3)); margin-top:-4px; }
  .sg-act{ display:none; }                     /* его место занимает кебаб */
  .sg-gate{ display:none; }                    /* условие открытия уходит в meta и в тело */
  .sg-more-wrap{ display:block; }
  .sg-body{ padding:0 var(--space-4) var(--space-4); }
  .sg.is-open > .sg-body, .sg.is-open > .sg-body.cols-1,
  .sg.is-open > .sg-body.cols-2, .sg.is-open > .sg-body.cols-3{
    display:block; padding-top:0; }
  .sg-body > .sg-col + .sg-col{ border-left:0; padding-left:0; margin-top:var(--space-4); }
  /* действие живёт в липкой панели внизу; селектор повторяет узко-десктопный
     (.sg-body.cols-3 > .sg-cta), иначе тот перебивает по специфичности */
  .sg-body.cols-3 > .sg-cta, .sg-body > .sg-cta{ display:none; }
  /* панель встаёт НАД капсулой меню: капсула — единственная навигация на телефоне */
  .ld2-sticky{ display:block; position:fixed; left:0; right:0; z-index:48;
    bottom:calc(var(--nav-safe) + 62px);
    padding:var(--space-3) var(--space-4) var(--space-4);
    background:linear-gradient(to top, var(--bg-page) 68%, color-mix(in srgb, var(--bg-page) 0%, transparent));
  }
  .ld2-sticky .hint{ font-size:12.5px; color:var(--text-secondary); text-align:center; margin-bottom:var(--space-2); }
  body[data-screen="lessondet"] .page{ padding-bottom:calc(var(--nav-safe) + 210px); }
}
@media (max-width:520px){
  .jnav{ --jn-h:32px; }                 /* нижняя граница диапазона h 32–36; R едет следом */
  .jn-bot{ padding:var(--space-2); }
  .jc-name{ font-size:12px; padding:5px 10px; }
}

/* ---- оверлей «Все разделы» (§13.4 CurriculumSection): раздел → темы, modal-first ---- */
.popup-overlay{ position:fixed; inset:0; z-index:70; display:flex; align-items:center; justify-content:center; padding:var(--space-4); }
.popup-overlay[hidden]{ display:none; }
.popup-backdrop{ position:absolute; inset:0; background:rgba(23,17,10,.5);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px); }
.popup-card{ position:relative; z-index:1; width:min(400px,100%); max-height:80vh; display:flex; flex-direction:column;
  background:var(--bg-card); border-radius:var(--radius-xl); overflow:hidden; box-shadow:0 12px 40px rgba(23,17,10,.32); }
.popup-head{ display:flex; align-items:center; gap:var(--space-2); padding:var(--space-4); border-bottom:1px solid var(--border-default); }
.popup-back[hidden]{ display:none; }
.popup-back .ic{ transform:rotate(90deg); }
.popup-title{ flex:1; min-width:0; font-family:var(--font-head); font-size:16px; font-weight:700; color:var(--text-strong); }
.popup-body{ padding:var(--space-3); overflow-y:auto; }
.popup-hint{ font-size:12px; color:var(--text-secondary); padding:0 var(--space-1) var(--space-2); }
.popup-list{ display:flex; flex-direction:column; gap:var(--space-2); }
.sf-opt{ display:flex; align-items:center; justify-content:space-between; gap:var(--space-2);
  padding:var(--space-3); border:1px solid var(--border-default); border-radius:var(--radius-md);
  background:none; font:inherit; font-size:14px; color:var(--text-primary); cursor:pointer; text-align:left; }
.sf-opt:hover{ background:var(--bg-page); border-color:var(--border-secondary); }
.sf-opt .go{ color:var(--text-secondary); flex:none; width:14px; height:14px; transform:rotate(-90deg); }
.sf-opt.all{ background:var(--action-primary-bg); border-color:transparent; color:var(--menu-selected); font-weight:700; }

/* ==================================================================
   КАЛЕНДАРЬ (§16 спека + handoff 2026-07-31)

   ЦВЕТ = ПРЕДМЕТ, и только предмет (§16.8): физика зелёная, математика
   синяя — те же шкалы, что во всём кабинете (foundations/color/physics|math).
   Пара «мягкая заливка + насыщенный текст» взята механикой чип-слова
   (components/term-chip.md): quantity-*-soft / quantity-*-text, обе темы
   уже в токенах. ТИП события (Урок / Вебинар / ДЗ) несут иконка и подпись,
   СОСТОЯНИЕ (перенос, отмена, просрочка, замок) — текстовая метка.
   Ни один смысл не держится на одном цвете.
   ================================================================== */
/* верхняя строка = те же колонки, что у рабочей сетки: вкладыш стоит над agenda,
   управление периодом — над календарём, обе группы на одной линии */
.cal-top{ display:grid; grid-template-columns:minmax(300px,36fr) minmax(640px,64fr);
  gap:var(--space-6); align-items:center; margin-bottom:var(--space-5); }
.cal-scope{
  --cs-h:44px;
  display:flex; width:100%; padding:4px; gap:4px;
  background:var(--bg-subtle); border-radius:var(--radius-pill);
}
.cs-tab{
  flex:1 1 0; min-height:calc(var(--cs-h) - 8px);
  border:0; background:none; font:inherit; font-size:14.5px; font-weight:600;
  color:var(--text-secondary); border-radius:var(--radius-pill); cursor:pointer;
  transition:background-color .18s ease, color .18s ease;
}
.cs-tab:not(.active):hover{ color:var(--text-primary); }
.cs-tab.active{ background:var(--bg-card); color:var(--menu-selected); font-weight:700;
  box-shadow:0 1px 2px rgba(23,17,10,.07); }

/* ---- рабочая сетка: agenda 44 / месяц 56. Одна колонка — по ТОЙ ЖЕ границе,
   что и на «Моём пути» (1150px и открытый чат): ниже неё минимум месяца
   620px + agenda 360px + зазор просто не помещается в рабочую область ---- */
.cal-layout{ display:grid; grid-template-columns:minmax(300px,36fr) minmax(640px,64fr);
  gap:var(--space-6); align-items:start; }
.cal-agenda{ min-width:0; }
.cal-month{ min-width:0; position:relative; }
@media (max-width:1150px){
  .cal-top,
  .cal-layout{ grid-template-columns:1fr; gap:var(--space-4); }
  .cal-month{ order:1; } .cal-agenda{ order:2; }
}
body.chat-open .cal-top,
body.chat-open .cal-layout{ grid-template-columns:1fr; }
body.chat-open .cal-month{ order:1; } body.chat-open .cal-agenda{ order:2; }

/* ---- управление периодом: «Сегодня» слева, месяц — визуальный центр строки ---- */
.cal-toolbar{ display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
  gap:var(--space-3); }
.cal-today{
  justify-self:start; min-height:36px; padding:0 var(--space-5);
  border:0; border-radius:var(--radius-pill); cursor:pointer;
  font:inherit; font-size:14px; font-weight:700;
  color:var(--action-on-primary); background:var(--action-primary);
  transition:background-color .18s ease, opacity .18s ease;
}
.cal-today:hover{ background:var(--action-primary-hover); }
/* выбран не сегодняшний день — кнопка теряет заливку, но остаётся доступной (§7) */
.cal-today.is-off{ background:none; color:var(--menu-selected); }
.cal-today.is-off:hover{ background:var(--action-primary-bg); }
.cal-period{ grid-column:2; display:flex; align-items:center; gap:var(--space-4); }
.cal-month-name{ min-width:168px; text-align:center;
  font-family:var(--font-head); font-size:17px; font-weight:700; color:var(--text-strong); }
.cal-arrow{ flex:none; width:44px; height:44px; border:0; border-radius:50%; background:none;
  color:var(--text-secondary); cursor:pointer; display:grid; place-items:center;
  transition:background-color .18s ease, color .18s ease; }
.cal-arrow:hover{ background:var(--bg-subtle); color:var(--text-primary); }
.cal-arrow .ic{ width:18px; height:18px; }
#calPrev .ic{ transform:rotate(90deg); }
#calNext .ic{ transform:rotate(-90deg); }

/* ---- сетка месяца: рамок у дней нет, вертикальных линий нет,
   недели разделены тонкой горизонтальной линией (§8) ---- */
.cal-dow{ display:grid; grid-template-columns:repeat(7,1fr); padding-bottom:var(--space-2); }
.cal-dow span{ text-align:center; font-size:11.5px; font-weight:700; letter-spacing:.05em;
  color:var(--text-secondary); }
.cal-grid{ position:relative; --cal-ev-gap:2px; --cal-ev-r:6px; }
/* minmax(0,1fr), а не 1fr: иначе плашка с nowrap раздувает свою колонку,
   и последние дни недели не помещаются в ширину сетки (правка 2026-07-31) */
.cal-week{ display:grid; grid-template-columns:repeat(7,minmax(0,1fr));
  border-top:1px solid var(--border-default); }
.cal-day{
  display:flex; flex-direction:column; gap:5px; min-width:0; min-height:108px;
  padding:var(--space-2) 4px 8px; border:0; background:none; font:inherit;
  text-align:center; cursor:pointer; border-radius:var(--radius-sm);
  transition:background-color .18s ease;
}
.cal-day .d-num{ font-size:15.5px; font-weight:600; color:var(--text-primary); }
.cal-day.is-out .d-num{ color:var(--text-secondary); opacity:.5; }
.cal-day.is-today .d-num{ color:var(--menu-selected); font-weight:800; }
.cal-day:not(.is-sel):hover{ background:color-mix(in srgb, var(--text-strong) 5%, transparent); }
/* Выбранный день: заливка ПЛОТНЕЕ, чем плашка физики — иначе зелёная плашка
   растворяется в фоне дня. Рамки нет (правка Игоря 2026-07-31).
   «Сегодня» и «выбран» остаются независимыми состояниями (§9). */
.cal-day.is-sel{ background:color-mix(in srgb, var(--action-primary) 17%, var(--bg-page)); }
.cal-day:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:-2px; }

/* ---- плашки событий: группа дня не соприкасается, скруглены только внешние углы (§11) ---- */
.cal-stack{ display:flex; flex-direction:column; gap:var(--cal-ev-gap); margin-top:auto; }
/* содержимое плашки — по левому краю, иконка первой (правка Игоря 2026-07-31) */
.cal-ev{
  display:flex; align-items:center; justify-content:flex-start; gap:4px;
  min-width:0; min-height:23px; padding:3px 6px; border-radius:0;
  background:var(--ev-soft); color:var(--ev-text);
  font-size:11.5px; font-weight:600; line-height:1.2; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
}
.cal-ev .ic{ width:11px; height:11px; flex:none; opacity:.9; }
.cal-ev:first-child{ border-radius:var(--cal-ev-r) var(--cal-ev-r) 0 0; }
.cal-ev:last-child { border-radius:0 0 var(--cal-ev-r) var(--cal-ev-r); }
.cal-ev:only-child { border-radius:var(--cal-ev-r); }
.cal-ev.is-more{ background:var(--bg-subtle); color:var(--text-secondary); font-weight:700; }
.cal-ev.is-cancel b{ text-decoration:line-through; }

/* Предметная пара — та же, что у чип-слова; тёмная тема приходит из токенов.
   --subj-text держит ПРЕДМЕТ и не меняется от состояния: им красятся подпись
   и кнопка действия (у математики они синие, у физики зелёные — правка Игоря
   2026-07-31). --ev-* отвечает за плашку и может уходить в амбер/нейтраль. */
.s-physics{ --subj-text:var(--quantity-green-text);
            --ev-soft:var(--quantity-green-soft); --ev-text:var(--quantity-green-text); }
.s-math   { --subj-text:var(--quantity-blue-text);
            --ev-soft:var(--quantity-blue-soft);  --ev-text:var(--quantity-blue-text);  }
/* просрочка — амбер, не красный: срок прошёл, приём открыт (§16.8) */
.is-overdue{ --ev-soft:var(--quantity-amber-soft); --ev-text:var(--quantity-amber-text); }
/* отменено и закрытое — уходят в нейтраль, но остаются читаемыми */
.is-off{ --ev-soft:var(--bg-subtle); --ev-text:var(--text-secondary); }

/* ---- превью дня по наведению/фокусу: поверх сетки, без reflow (§13) ---- */
.cal-preview{
  /* 272px — ширина, при которой превью помещается сбоку от ЛЮБОЙ колонки недели
     и потому никогда не накрывает сам день */
  position:absolute; z-index:30; width:272px; max-height:360px; overflow-y:auto;
  padding:var(--space-4); border-radius:var(--radius-lg);
  background:var(--bg-card); border:1px solid var(--border-default);
  box-shadow:0 14px 36px rgba(23,17,10,.17);
  scrollbar-gutter:stable;                        /* ширина не прыгает при появлении бегунка */
}
/* канон components/scrollbar.md, ловушка 6: в контейнере со скруглением ход капсулы
   ограничен прямой частью края — трек отступает ровно на радиус контейнера */
.cal-preview::-webkit-scrollbar-track{ margin:var(--radius-lg) 0; }
.cal-preview[hidden]{ display:none; }
.cp-date{ font-family:var(--font-head); font-size:14.5px; font-weight:700; color:var(--text-strong); }
.cp-count{ font-size:12px; color:var(--text-secondary); margin-top:2px; }
.cp-list{ margin-top:var(--space-3); display:flex; flex-direction:column; gap:var(--space-3); }
.cp-it{ border-left:3px solid var(--ev-text); padding-left:var(--space-3); }
.cp-kick{ font-size:11.5px; font-weight:700; color:var(--ev-text); }
.cp-t{ font-size:13.5px; font-weight:600; color:var(--text-primary); margin-top:1px; }
.cp-s{ font-size:12px; color:var(--text-secondary); margin-top:3px; line-height:1.45; }
.cp-more{ margin-top:var(--space-3); font-size:12px; font-weight:600; color:var(--text-secondary); }
.cp-empty{ margin-top:var(--space-2); font-size:13px; color:var(--text-secondary); }

/* ---- agenda выбранного дня: события без карточек (§14) ---- */
/* соседние дни листаются стрелками в заголовке — отдельного перехода внизу нет */
/* Дата со стрелками — по центру блока, в рамке ПОСТОЯННОЙ ширины.
   Раньше строка центрировалась целиком, и стрелки ездили вслед за длиной даты
   («Сегодня, 5 октября» против «Воскресенье, 18 октября») — правка Игоря 2026-07-31.
   Теперь стрелки стоят по краям фиксированной рамки, дата центрируется внутри. */
.ag-headrow{ display:grid; grid-template-columns:34px minmax(0,1fr) 34px; align-items:center;
  gap:var(--space-2); width:min(356px,100%); margin:0 auto var(--space-4); }
.ag-head{ margin:0; text-align:center; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  font-family:var(--font-head); font-size:20px; font-weight:700; color:var(--text-strong); }
.ag-head:focus{ outline:none; }
.ag-nav{ flex:none; width:34px; height:34px; border:0; border-radius:50%; background:none;
  color:var(--text-secondary); cursor:pointer; display:grid; place-items:center;
  transition:background-color .18s ease, color .18s ease; }
.ag-nav:hover{ background:var(--action-primary-bg); color:var(--menu-selected); }
.ag-nav .ic{ width:17px; height:17px; }
#agPrev .ic{ transform:rotate(90deg); }
#agNextDay .ic{ transform:rotate(-90deg); }
.ag-ev{ display:grid; grid-template-columns:64px 24px minmax(0,1fr); }
.ag-time{ font-size:14.5px; font-weight:700; color:var(--text-primary); }
/* у просроченного события в колонке времени стоит срок просрочки, а не час занятия */
.ag-time.is-od{ font-size:13.5px; color:var(--quantity-amber-text); }
/* вертикальная ось снята: события держит одна точка (правка Игоря 2026-07-31) */
.ag-axis{ display:flex; justify-content:center; }
.ag-dot{ width:9px; height:9px; margin-top:5px; border-radius:50%; background:var(--subj-text); }
.ag-body{ padding:0 0 var(--space-6) var(--space-3); }
.ag-kick{ font-size:12.5px; font-weight:700; color:var(--subj-text); }
.ag-t{ margin-top:3px; font-size:15.5px; font-weight:700; color:var(--text-strong); }
/* Метка состояния — в одной строке с «Физика · ДЗ» (правка Игоря 2026-07-31).
   Заливка ПЛОТНЕЕ, чем --ev-soft: подсвеченное событие лежит на волне того же
   цвета, и мягкая плашка на ней исчезала (правка Игоря 2026-07-31) */
.ag-tag{ display:inline-block; margin-left:var(--space-2); padding:2px 9px; border-radius:var(--radius-pill);
  background:color-mix(in srgb, var(--ev-text) 22%, var(--bg-card));
  color:var(--ev-text); font-size:11.5px; font-weight:700; }
.ag-ctx{ margin-top:4px; font-size:13.5px; line-height:1.5; color:var(--text-secondary); }
/* раздатка — строкой ВЫШЕ действия; несколько файлов стоят в одну строку */
.ag-mats{ margin-top:var(--space-3); display:flex; flex-wrap:wrap; gap:var(--space-2); }
.ag-mats .mat-btn{ font-size:12px; padding:5px 12px 5px 10px; }
/* действие — у левого края и В ЦВЕТЕ ПРЕДМЕТА: у математики синее, как и всё
   математическое в кабинете (правка Игоря 2026-07-31) */
/* действия идут столбцом: помощь куратора стоит ПОД основной кнопкой */
.ag-cta{ margin-top:var(--space-3); display:flex; flex-direction:column;
  align-items:flex-start; gap:var(--space-3); }
.ag-go{ display:inline-flex; align-items:center; gap:7px; border:0; background:none; padding:0;
  font:inherit; font-size:14.5px; font-weight:700; color:var(--subj-text); cursor:pointer; }
.ag-go .ic{ width:15px; height:15px; transition:transform .18s ease; }
.ag-go:hover .ic{ transform:translateX(3px); }
/* выход к куратору: рядом с действием, но тише его — помощь предлагается, не навязывается */
.ag-help{ display:inline-flex; align-items:center; gap:6px; border:0; background:none; padding:0;
  font:inherit; font-size:13.5px; font-weight:600; color:var(--text-secondary); cursor:pointer; }
.ag-help:hover{ color:var(--text-primary); }
.ag-help .ic{ width:14px; height:14px; }
/* «Этим сейчас» — мягкая волна вместо рамки карточки. Отрицательный margin
   компенсирует верхний паддинг: без него первая строка съезжала вниз и переставала
   стоять на одной линии со временем и точкой (правка Игоря 2026-07-31) */
.ag-ev.is-now .ag-body{ background:linear-gradient(90deg, var(--ev-soft), transparent 72%);
  border-radius:var(--radius-md);
  margin-top:calc(-1 * var(--space-2)); padding-top:var(--space-2);
  padding-bottom:var(--space-4); padding-right:var(--space-3); }
.ag-empty{ margin:0; padding:var(--space-4) 0 var(--space-6); font-size:14px; color:var(--text-secondary); }

/* ---- телефон: месяц компактнее, подпись типа уходит — тип держит иконка ---- */
@media (max-width:860px){
  /* липкая навигация раздела — та же механика, что на «Моём пути»:
     панель едет за уезжающим топбаром через --tb-off */
  .cal-top{ position:sticky; z-index:15;
    top:calc(var(--pbar-h) + var(--topbar-h) - var(--tb-off, 0px));
    background:var(--bg-page); padding:var(--space-2) 0 var(--space-3);
    margin-bottom:var(--space-2); }
  .cal-scope{ width:100%; }
  .cal-toolbar{ gap:var(--space-2); }
  .cal-month-name{ min-width:0; font-size:16px; }
  /* «Сегодня» — та же зелёная капсула, что на десктопе (правка Игоря 2026-07-31) */
  .cal-today{ padding:0 var(--space-4); }
  .cal-grid{ --cal-ev-gap:2px; }
  .cal-day{ min-height:92px; padding:6px 3px 8px; gap:4px; }
  .cal-day .d-num{ font-size:15px; }
  /* ширины дня на слово не хватает — тип держит иконка, и она есть у ВСЕХ типов,
     включая ДЗ. Цвет ни в одном случае не единственный носитель смысла */
  .cal-ev{ font-size:10px; min-height:22px; padding:2px 3px; gap:2px; justify-content:center; }
  .cal-ev .ic{ width:9px; height:9px; }
  .cal-ev .ev-kind{ display:none; }
  .cal-ev.is-more{ font-size:10px; }
  .cal-preview{ display:none !important; }         /* превью — только там, где есть курсор */
  .ag-ev{ grid-template-columns:56px 22px minmax(0,1fr); }
  .ag-head{ font-size:18px; }
}
@media (max-width:520px){
  .cal-day{ min-height:84px; }
  .cal-ev{ font-size:10px; }
  .cs-tab{ font-size:13.5px; }
}

/* ==================================================================
   ЗАГЛУШКИ РАЗДЕЛОВ (Каталог + разделы вне P1) — честно и спокойно
   ================================================================== */
.stub-view{
  max-width:640px; margin:var(--space-7) auto 0; text-align:center;
  background:var(--bg-card); border:1px dashed var(--border-secondary); border-radius:var(--radius-xl);
  padding:var(--space-6); display:flex; flex-direction:column; align-items:center; gap:var(--space-3);
}
.stub-view .ic{ width:34px; height:34px; color:var(--text-secondary); }
.stub-view h1{ margin:0; font-size:24px; font-weight:700; }
.stub-view p{ margin:0; color:var(--text-secondary); font-size:15px; line-height:1.6; max-width:48ch; }
.stub-view code{ font-family:var(--font-mono); font-size:13px; background:var(--bg-subtle); border-radius:var(--radius-sm); padding:2px 6px; }

/* ==================================================================
   КАТАЛОГ (адаптация catalog-wireframe-v1: карточки + фильтры + окно курса)
   ================================================================== */
.cat-toolbar{ display:flex; flex-direction:column; gap:var(--space-3); margin:var(--space-4) 0 var(--space-5); }
.cat-chiprow{ display:flex; align-items:center; gap:var(--space-2); flex-wrap:wrap; }
.cat-chip{ border:1px solid var(--border-default); background:var(--bg-card); color:var(--text-primary);
  border-radius:var(--radius-pill); padding:var(--space-2) var(--space-4); font-size:14px; cursor:pointer;
  font-family:var(--font-head); font-weight:600; transition:border-color .15s, background-color .15s, color .15s; }
.cat-chip:hover{ border-color:var(--border-interactive); }
.cat-chip[aria-pressed="true"]{ background:var(--action-primary); color:var(--action-on-primary); border-color:var(--action-primary); }
.cat-empty{ color:var(--text-secondary); font-size:15px; padding:var(--space-6) 0; text-align:center; }

/* сетка: auto-fill — сама даёт 3/2/1 колонки без отдельных брейкпойнтов */
.cat-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(272px,1fr)); gap:var(--space-5); }

.cat-card{ display:flex; flex-direction:column; background:var(--bg-card); border:1px solid var(--border-default);
  border-radius:var(--radius-lg); overflow:hidden; box-shadow:var(--shadow-card); cursor:pointer;
  transition:transform .15s, box-shadow .2s; }
/* тень при наведении усилена (правка Игоря 2026-08-06): карточка заметно «встаёт».
   Обводки при наведении нет (правка Игоря 2026-08-10): подъёма и тени достаточно. */
.cat-card:hover{ transform:translateY(-3px);
  box-shadow:0 14px 34px rgba(23,17,10,.16), 0 4px 12px rgba(23,17,10,.10); }
.cat-card:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
/* обложка — плейсхолдер (реальное фото преподавателя на брендовом фоне — в финале) */
.cat-cover{ position:relative; aspect-ratio:16/10; display:flex; align-items:center; justify-content:center;
  background:
    radial-gradient(circle at 78% 22%, color-mix(in srgb,var(--cover-c) 22%,transparent) 0 30%, transparent 31%),
    linear-gradient(135deg, color-mix(in srgb,var(--cover-c) 88%,#000 0%), color-mix(in srgb,var(--cover-c) 60%,#000 8%));
  color:#fff; }
.cat-cover .silh{ width:64px; height:64px; border-radius:50%; background:rgba(255,255,255,.28);
  display:flex; align-items:center; justify-content:center; }
.cat-cover .silh .ic{ width:34px; height:34px; color:#fff; }
.cat-cover .ph-note{ position:absolute; bottom:8px; left:10px; font-family:var(--font-mono); font-size:10px; color:rgba(255,255,255,.72); }
.cat-badge{ position:absolute; top:10px; left:10px; background:rgba(255,255,255,.92); color:#1a1a1a;
  border-radius:var(--radius-pill); padding:4px 12px; font-family:var(--font-head); font-weight:700; font-size:12px; }
.cat-body{ display:flex; flex-direction:column; gap:var(--space-2); padding:var(--space-4); flex:1; }
.cat-category{ color:var(--text-secondary); font-size:12.5px; }
.cat-title{ font-family:var(--font-head); font-weight:700; font-size:18px; color:var(--text-strong); }
.cat-tags{ display:flex; flex-wrap:wrap; gap:6px; margin-top:2px; }
.cat-tag{ background:var(--bg-subtle); color:var(--text-secondary); border-radius:var(--radius-sm); padding:3px 9px; font-size:12px; font-weight:600; }
.cat-meta{ display:grid; gap:6px; margin-top:var(--space-2); }
.cat-meta div{ display:flex; align-items:center; gap:8px; color:var(--text-secondary); font-size:13px; }
.cat-meta .ic{ width:15px; height:15px; flex:none; }
.cat-price{ margin-top:auto; padding-top:var(--space-3); font-family:var(--font-head); }
.cat-price .num{ font-size:20px; font-weight:700; color:var(--text-strong); }
.cat-price .unit{ color:var(--text-secondary); font-size:13px; }
.cat-price .hint{ display:block; color:var(--text-secondary); font-size:11.5px; margin-top:2px; font-family:var(--font-body); }
.cat-actions{ display:flex; gap:var(--space-2); padding:0 var(--space-4) var(--space-4); }
.cat-actions .btn{ flex:1; }

/* окно курса — тот же каркас, что платёжная модалка (body.course-open), но шире и без паддинга.
   Скролл живёт на ПОДЛОЖКЕ, не внутри модалки: бегунок у края экрана, скруглённые
   углы окна не режутся треком (правка Игоря 2026-08-06) */
body.course-open .modal-bg.course{ display:flex; align-items:flex-start; justify-content:center; overflow-y:auto; }
.modal.course{ max-width:56rem; padding:0; gap:0; margin:auto; }
.crs-hero{ position:relative; min-height:180px; border-radius:var(--radius-xl) var(--radius-xl) 0 0;
  display:flex; align-items:flex-end; padding:var(--space-6); color:#fff;
  background:linear-gradient(135deg, color-mix(in srgb,var(--cover-c) 88%,#000 0%), color-mix(in srgb,var(--cover-c) 55%,#000 10%)); }
.crs-hero .cat-badge{ top:var(--space-5); left:var(--space-6); }
.crs-hero h2{ margin:0; font-family:var(--font-head); font-size:28px; font-weight:700; color:#fff; }
.crs-hero .teacher{ margin-top:6px; font-size:15px; color:rgba(255,255,255,.9); }
.crs-close{ position:absolute; top:var(--space-4); right:var(--space-4); z-index:2; background:rgba(255,255,255,.92); color:#1a1a1a; }
.crs-close:hover{ background:#fff; }
.crs-body{ padding:var(--space-6); display:grid; grid-template-columns:1.6fr 1fr; gap:var(--space-6); }
.crs-body h3{ margin:0 0 var(--space-3); font-size:14px; text-transform:uppercase; letter-spacing:.04em; color:var(--text-secondary); font-family:var(--font-head); }
.crs-body p{ margin:0 0 var(--space-4); }
.crs-outline{ list-style:none; padding:0; margin:0; display:grid; gap:var(--space-2); }
.crs-outline li{ display:flex; align-items:center; gap:10px; padding:var(--space-3); background:var(--bg-subtle); border-radius:var(--radius-md); font-size:14px; }
.crs-outline .n{ width:24px; height:24px; border-radius:50%; background:var(--action-primary); color:#fff;
  display:inline-flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; flex:none; }
.crs-meta{ display:grid; gap:var(--space-3); margin-bottom:var(--space-5); }
.crs-meta div{ display:flex; align-items:center; gap:10px; font-size:14px; }
.crs-meta .ic{ width:18px; height:18px; flex:none; color:var(--action-primary); }
.crs-pricebox{ background:var(--bg-subtle); border:1px solid var(--border-default); border-radius:var(--radius-lg); padding:var(--space-5); }
.crs-pricebox .big{ font-family:var(--font-head); font-size:26px; font-weight:700; color:var(--text-strong); }
.crs-pricebox .u{ color:var(--text-secondary); font-size:14px; }
.crs-pricebox .k29{ font-size:12.5px; color:var(--text-secondary); margin:var(--space-3) 0 var(--space-4);
  border-left:3px solid var(--subject-border); padding-left:var(--space-3); }
.crs-pricebox .btn{ width:100%; }
.crs-pricebox .btn + .btn{ margin-top:var(--space-2); }
@media (max-width:900px){ .crs-body{ grid-template-columns:1fr; } }
@media (max-width:520px){
  .modal-bg.course{ padding:0; }
  .modal.course{ max-width:100%; min-height:100dvh; border-radius:0; }
  .crs-hero{ border-radius:0; padding:var(--space-5) var(--space-4); }
  .crs-hero h2{ font-size:23px; }
  .crs-body{ padding:var(--space-4); gap:var(--space-5); }
}

/* ==================================================================
   ОПЛАТА (модалка) и «ЖДЁМ ДОСТУП» — сохранено из cabinet-flow-v0.0, не перестраивать
   ================================================================== */
.modal-bg{ display:none; position:fixed; inset:0; z-index:70; background:rgba(23,17,10,.4); place-items:center; padding:var(--space-5); }
body.pay-open .modal-bg{ display:grid; }
.modal{
  width:100%; max-width:440px; background:var(--bg-card); border:1px solid var(--border-default);
  border-radius:var(--radius-xl); box-shadow:0 24px 60px rgba(0,0,0,.28); padding:var(--space-5);
  display:flex; flex-direction:column; gap:var(--space-4);
}
.modal-head{ display:flex; align-items:center; gap:var(--space-3); }
.modal-head h2{ margin:0; font-family:var(--font-head); font-size:19px; font-weight:700; color:var(--text-strong); }
.modal-head .icon-btn{ margin-left:auto; }
.includes{ border:1px solid var(--border-default); border-radius:var(--radius-md); padding:var(--space-3); display:flex; flex-direction:column; gap:8px; }
.includes .it{ display:flex; gap:10px; font-size:14px; align-items:center; }
.includes .ck{ color:var(--action-primary); font-weight:800; }
.stub-box{
  border:2px dashed color-mix(in srgb,var(--state-warning) 50%,transparent); border-radius:var(--radius-lg);
  padding:var(--space-5) var(--space-4); text-align:center; background:var(--state-warning-bg);
  display:flex; flex-direction:column; gap:8px; align-items:center;
}
.stub-box .st{ font-family:var(--font-head); font-weight:700; font-size:16px; color:var(--state-warning); }
.stub-box .sp{ font-size:13px; color:var(--text-secondary); line-height:1.5; }
.demo-hint{ font-size:11.5px; color:var(--text-secondary); text-align:center; }
.wait-wrap{ max-width:520px; margin:8vh auto 0; text-align:center; display:flex; flex-direction:column; align-items:center; gap:var(--space-4); }
.wait-wrap h1{ margin:0; font-size:26px; font-weight:700; }
.wait-wrap p{ margin:0; color:var(--text-secondary); max-width:44ch; }
.wait-note{
  width:100%; text-align:left; background:var(--state-warning-bg); border-radius:var(--radius-lg);
  padding:var(--space-4); border:1px solid color-mix(in srgb,var(--state-warning) 30%,transparent);
}
.wait-note .bt{ font-family:var(--font-head); font-weight:600; font-size:15px; color:var(--text-strong); }
.wait-note .bp{ font-size:14px; line-height:1.55; color:var(--text-secondary); }
/* ==================================================================
   ОГЛАВЛЕНИЕ (эталон; дизайн временный — см. план 07-07 §11)
   ================================================================== */
.toc{
  position:fixed; z-index:44; right:var(--space-5);
  top:var(--chrome-top); bottom:var(--space-4);
  width:var(--toc-w); padding:0; overflow:hidden;
  display:none; flex-direction:column;
  background:var(--neo-bg); border:0; border-radius:var(--neo-r); box-shadow:var(--neo-shadow);
  transform-origin:top right;
  transition:transform .28s ease, opacity .28s ease, box-shadow .28s ease;
}
body[data-screen="lesson"] .toc{ display:flex; }
.toc-head{ flex:none; display:flex; align-items:center; gap:var(--space-2); padding:var(--space-4) var(--space-4) var(--space-3); }
.toc-head > .ic{ width:22px; height:22px; color:var(--text-primary); }
.toc-head h2{ margin:0; font-family:var(--font-head); font-weight:700; font-size:17px; color:var(--text-strong); }
.toc-collapse{ margin-left:auto; }
.toc-collapse .ic{ transform:rotate(-90deg); }
.toc-close{ display:none; margin-left:auto; }
.toc-grip{ display:none; }
.toc-body{ position:relative; flex:1; min-height:0; margin:0 var(--space-1) var(--space-5) 0; }
.toc-body::after{ content:''; position:absolute; left:0; right:12px; bottom:0; height:12px; z-index:2; pointer-events:none;
  background:linear-gradient(to top, var(--neo-bg), rgba(247,246,242,0)); }
.toc-scroll{ height:100%; overflow-y:auto; overscroll-behavior:contain; padding:2px var(--space-3) var(--space-2) var(--space-4); }
/* ------------------------------------------------------------------
   МАРШРУТ УРОКА — вертикальный путь «модуль → блоки». Переписан 2026-07-29
   после двух итераций стыковки линий из CSS-кусочков.

   АРХИТЕКТУРНОЕ РЕШЕНИЕ: линия НЕ собирается из псевдоэлементов. Весь путь —
   один absolute-слой <svg class="rt-lines"> ПОД строками; path'ы строит скрипт
   по фактическим координатам маркеров, измеренным после рендера
   (layoutRouteLines + ResizeObserver). Что это даёт:
     · дуги и вертикали стыкуются математикой path, а не подгонкой полупикселей;
     · линия касается окружности всегда — при любой высоте строки и переносах;
     · универсально: меняется только DATA.toc, код не трогается.
   DOM — простой список строк; маркеры несут data-nid, по которым скрипт
   находит точки пути.
     --rt-shift  сдвиг колонки блоков относительно колонки модулей
     --rt-col    ширина жёлоба маркеров (≥ shift + размер маркера блока)
   ------------------------------------------------------------------ */
.rt-wrap{
  position:relative;
  /* ЕДИНЫЙ цвет всего закрытого (правка Игоря): кольцо закрытого блока, пунктир
     линии и пунктирная окружность закрытого модуля — один и тот же цвет.
     Плотный (через смесь с фоном панели), не полупрозрачный: иначе на
     пересечениях со слоями появляются пятна разной насыщенности */
  --rt-locked:color-mix(in srgb, var(--border-interactive) 55%, var(--neo-bg));
}
/* ПОРЯДОК СЛОЁВ (правка Игоря: подложка активного блока резала линию сверху и
   снизу): подложка (z:-1) → линия маршрута (z:1) → маркеры и текст (z:2).
   Линия идёт ПО подложке, но под кольцами и текстом. */
.rt-lines{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; z-index:1; }
.rt{
  /* размеры маркеров ЕДИНЫ на всех экранах (44 попадает и в десктопную вилку
     44–48, и в мобильную 40–44): SVG кольца всегда 1:1 с viewBox, поэтому штрих
     везде ровно --rt-lw — никаких масштабных расхождений толщины с линией */
  --rt-mod:44px; --rt-blk:31px; --rt-shift:22px; --rt-col:54px; --rt-gap:18px;
  --rt-lw:2.5px;                     /* ОДНА толщина: кольца и линии */
  list-style:none; margin:0; padding:0;
}
.rt-mod{ list-style:none; }
/* пролёт между модулями — место для перехода линии (S-дуги или вертикали) */
.rt-mod + .rt-mod{ margin-top:28px; }
.rt-blocks{ list-style:none; margin:0; padding:0; }
.rt-mod:not(.open) .rt-blocks{ display:none; }

/* ---- строка (общая для модуля и блока): цель нажатия ≥44px ---- */
.rt-row{
  position:relative; display:flex; align-items:center; gap:var(--space-3);
  width:100%; min-height:44px; padding:0;
  background:none; border:0; font:inherit; color:inherit; text-align:left;
}
button.rt-row{ cursor:pointer; }
.rt-gut{ flex:none; width:var(--rt-col); display:flex; align-items:center; }
.rt-brow .rt-gut{ padding-left:var(--rt-shift); }
.rt-txt{ min-width:0; display:flex; flex-direction:column; gap:1px; position:relative; z-index:2; }
.rt-mt{ font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--text-primary); }
.rt-bt{ font-size:15px; font-weight:600; line-height:1.35; color:var(--text-primary); display:flex; align-items:center; gap:6px; }
.rt-bt .ic{ width:14px; height:14px; flex:none; color:var(--text-secondary); }
.rt-sub{ font-size:13px; line-height:1.4; color:var(--text-secondary); }
.rt-chev{ width:18px; height:18px; flex:none; margin-left:auto; color:var(--text-secondary); transform:rotate(180deg); transition:transform .18s; }
.rt-mod:not(.open) .rt-chev{ transform:rotate(-90deg); }
/* подложка активного блока: z-index:-1 уводит её ЗА слой линий (.rt-lines стоит
   под .rt, а подложка — под всем стеком .rt) — линия идёт по подложке, текст выше */
.rt-blk.is-active .rt-row::before{
  content:''; position:absolute; z-index:-1; inset:2px 0 2px var(--rt-shift);
  background:var(--subject-bg-soft); border-radius:var(--radius-lg);
}
button.rt-row:hover .rt-bt{ color:var(--text-strong); }
.rt-blk.is-locked .rt-bt{ color:var(--text-secondary); font-weight:500; }
.rt-mod.is-locked .rt-mt{ color:var(--text-secondary); }
.rt-blk{ margin-top:var(--rt-gap); }
/* первый блок чуть ниже: пролёт вмещает две S-дуги радиуса (shift+blk/2−mod/2)/2 */
.rt-blk:first-child{ margin-top:10px; }

/* ---- кольцо-прогресс: один SVG-компонент, две размерности.
   Внутренняя заливка — <circle class="rg-bg"> ТЕМ ЖЕ радиусом, что и штрих:
   она кончается на осевой линии кольца и снаружи не выступает — никакого
   белого ободка вокруг цифры (правка Игоря) ---- */
.rg{ position:relative; display:inline-flex; flex:none; z-index:2; }   /* маркер над линией */
.rg svg{ display:block; width:100%; height:100%; overflow:visible; }
.rg-module{ width:var(--rt-mod); height:var(--rt-mod); }
.rg-block { width:var(--rt-blk); height:var(--rt-blk); }
.rg b{ position:absolute; inset:0; display:grid; place-items:center;
  font-family:var(--font-head); font-weight:700; color:var(--text-strong); }
.rg-module b{ font-size:17px; letter-spacing:.02em; }
.rg-block  b{ font-size:14px; }
.rg-bg   { fill:var(--bg-card); }
.rg-track{ stroke:var(--border-default); }
.rg-fill { stroke:var(--subject-primary); }
/* пройден на 100%: залита и окружность, и внутренность; число белое, не галочка */
.rg.is-done  .rg-bg{ fill:var(--subject-primary); }
.rg.is-done  .rg-track{ stroke:var(--subject-primary); }
.rg.is-done  b{ color:var(--action-on-primary); }
/* всё закрытое — ОДНИМ цветом --rt-locked И ОДНОЙ толщиной 2px, как у пунктирной
   линии (правка Игоря): кольцо блока-замка, окружность модуля, пунктир пути */
.rg.is-locked .rg-bg{ fill:var(--bg-subtle); }
.rg.is-locked .rg-track{ stroke:var(--rt-locked); stroke-width:2; }
.rg.is-locked b{ color:var(--text-secondary); }
/* у закрытого МОДУЛЯ окружность ещё и пунктирная — шаг штриха тот же, что у линии */
.rg-module.is-locked .rg-track{ stroke-dasharray:3.5 5; }

/* ---- линия маршрута: классы path'ов, которые ставит layoutRouteLines ---- */
.rl-done{ stroke:var(--subject-primary); }
.rl-line{ stroke:var(--border-default); }
.rl-dash{ stroke:var(--rt-locked); }
.toc-cta{
  margin-top:var(--space-3); width:100%; display:flex; align-items:center; gap:var(--space-2);
  padding:var(--space-3) var(--space-4); background:var(--subject-bg-soft); color:var(--subject-primary);
  border:1px solid transparent; border-radius:var(--radius-lg);
  font-family:inherit; font-size:15px; font-weight:600; text-decoration:none; transition:border-color .15s; cursor:pointer;
}
.toc-cta:hover{ border-color:var(--subject-border); }
.toc-cta .ic{ width:18px; height:18px; }
.toc-cta .cta-arr{ margin-left:auto; }
.toc-tab{
  display:none; position:fixed; z-index:44; right:var(--space-5); top:var(--chrome-top);
  width:88px; padding:14px 8px 12px; flex-direction:column; align-items:center; gap:6px;
  background:var(--neo-bg); border:0; border-radius:var(--radius-lg);
  box-shadow:6px 6px 16px var(--neo-dark), -6px -6px 16px var(--neo-light);
  font:inherit; font-size:12px; color:var(--text-primary); cursor:pointer;
  transition:box-shadow .3s ease, background-color .3s ease, transform .3s ease;
}
.toc-tab > .ic{ width:22px; height:22px; }
.toc-tab:hover{ background:var(--neo-bg); box-shadow:9px 9px 22px var(--neo-dark), -9px -9px 22px var(--neo-light); }
.toc-tab:active{ background:var(--neo-bg); box-shadow:6px 6px 16px var(--neo-dark), -6px -6px 16px var(--neo-light); }
.ring-badge{ position:relative; flex:none; width:44px; height:44px; display:flex; align-items:center; justify-content:center; }
.ring-badge svg{ position:absolute; inset:0; width:100%; height:100%; }
.ring-badge b{ font-family:var(--font-mono); font-size:12px; font-weight:500; color:var(--text-primary); }

/* ==================================================================
   ЧАТ — два слоя: список чатов ↔ диалог
   Перенесено со стенда _sandbox/chat-prototype/chat-lab-v1.html;
   решения и их причины — cubi/plans/2026-08-07-chat-prototype.md (Р1-Р28).
   ВНИМАНИЕ к именам: у кабинета уже заняты .day (календарь) и .task
   (карточка практики), поэтому в ленте они идут как .c-day и .c-task.
   Остальные классы чата уникальны, но все правила всё равно писаны
   от .chat — чтобы лента не красила кабинет и наоборот.
   ================================================================== */
.chat{
  /* каркас чата одной связкой: высота поля ввода входит в нижний край ленты,
     длительность — одна на слои, шторку и сужение рабочей области */
  --chat-anim:.40s;
  --input-h:48px;              /* 5 + 36 (кнопка) + 5 + 2 (рамка) */
  --input-gap:var(--space-4);
  /* предел колонки разговора: в полноэкранном режиме (до 1150px) лента без
     него растягивается на всю ширину планшета — строка уезжает за канон
     measure (foundations/grid-and-spacing §4). Столбец центрируется, фон
     остаётся по бокам. На панели 360 и на телефоне не срабатывает. */
  --feed-max:560px;
  --chat-fs:13px;              /* кегль ленты; роль Caption, решение Игоря */
  display:none; position:fixed; z-index:55; right:var(--space-4);
  top:var(--chrome-top); bottom:var(--space-4);
  width:var(--chat-w); padding:0;
  background:var(--neo-bg); border:0; border-radius:var(--neo-r); box-shadow:var(--neo-shadow);
  flex-direction:column; overflow:hidden;
  transition:transform var(--chat-anim) ease;
}
body.chat-open .chat{ display:flex; }
.chat-grip{ display:none; }

/* --- сцена двух слоёв (Р5: одна модель на десктопе и на телефоне) --- */
.chat .stage{ position:relative; flex:1; min-height:0; }
.chat .layer{
  position:absolute; inset:0; display:flex; flex-direction:column;
  background:var(--neo-bg);
  transition:transform var(--chat-anim) cubic-bezier(.22,.61,.36,1);
  will-change:transform;
}
.chat .layer-dialog{ transform:translateX(100%); }
body.dlg-open .chat .layer-list{ transform:translateX(-26%); }   /* лёгкий параллакс, как в iOS/TG */
body.dlg-open .chat .layer-dialog{ transform:translateX(0); }
.chat .layer[aria-hidden="true"]{ pointer-events:none; }

/* --- шапка слоя: общая геометрия у списка и у диалога --- */
.chat .lhead{
  flex:none; display:flex; align-items:center; gap:var(--space-3);
  padding:var(--space-4); border-bottom:1px solid var(--border-default);
  background:var(--neo-bg);
}
.chat .lhead h2{ margin:0; font-family:var(--font-head); font-size:17px; font-weight:700;
  color:var(--text-strong); line-height:1.25; }
.chat .sp{ flex:1; }
.chat .hbtn{
  width:36px; height:36px; flex:none; display:grid; place-items:center;
  border:0; background:none; border-radius:var(--radius-pill); cursor:pointer;
  color:var(--text-secondary); transition:background .12s ease;
}
.chat .hbtn:hover{ background:var(--bg-subtle); }
.chat .hbtn .ic{ width:20px; height:20px; }

/* Р26: бегунок ленты скрыт, проявляется только при наведении на панель.
   Место под него зарезервировано gutter'ом — строки не смещаются.
   :focus-within сюда не годится: при открытии фокус уходит на «назад»,
   и бегунок висел бы постоянно. Chromium не анимирует ::-webkit-scrollbar-*,
   появление резкое — принято осознанно. */
.chat .scrollbox{ scrollbar-gutter:stable; }
.chat .scrollbox::-webkit-scrollbar-thumb{ background:transparent; }
.chat:hover .scrollbox::-webkit-scrollbar-thumb{ background:var(--scroll-thumb); background-clip:padding-box; }
.chat:hover .scrollbox::-webkit-scrollbar-thumb:hover{ background:var(--scroll-thumb-hover); background-clip:padding-box; }
@supports (-moz-appearance:none){
  .chat .scrollbox{ scrollbar-color:transparent transparent; }
  .chat:hover .scrollbox{ scrollbar-color:var(--scroll-thumb) transparent; }
}

/* ==================================================================
   СЛОЙ 1 — СПИСОК ЧАТОВ
   ================================================================== */
.chat .list{ flex:1; min-height:0; overflow-y:auto; padding:var(--space-2) 0; }
.chat .row{
  display:grid; grid-template-columns:44px 1fr auto; gap:var(--space-3);
  align-items:center; width:100%; text-align:left;
  padding:var(--space-3) var(--space-4); border:0; background:none; cursor:pointer;
  font:inherit; color:inherit; transition:background .12s ease;
}
.chat .row:hover{ background:var(--bg-subtle); }
/* оба span'а обязаны быть блочными: строчными они слипаются в одну строку,
   наследуют межстрочник тела и распирают контейнер до горизонтального скролла */
.chat .row-main{ display:block; min-width:0; }
.chat .row-name{
  display:block; font-family:var(--font-head); font-weight:600;
  font-size:calc(var(--chat-fs) + 1px); color:var(--text-strong); line-height:1.3;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.chat .row-prev{
  display:block; margin-top:1px; font-size:var(--chat-fs); line-height:1.35;
  color:var(--text-secondary);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.chat .row-meta{ display:flex; flex-direction:column; align-items:flex-end; gap:4px; flex:none; }
.chat .row-time{ font-size:12px; color:var(--text-secondary); font-variant-numeric:tabular-nums; }

/* аватар — инициалы до реальных фото */
.chat .av{
  width:44px; height:44px; flex:none; border-radius:var(--radius-pill);
  display:grid; place-items:center;
  font-family:var(--font-head); font-weight:600; font-size:15px;
  background:var(--bg-subtle); color:var(--text-secondary);
}
.chat .av.s32{ width:32px; height:32px; font-size:12px; }
.chat .av.s28{ width:28px; height:28px; font-size:11px; }
.chat .av-stack{ display:flex; }
.chat .av-stack .av + .av{ margin-left:-11px; box-shadow:0 0 0 2px var(--neo-bg); }
/* предметный аватар: цвет приходит из --subject-*, их переключает data-subject */
.chat .av-subject{ background:var(--subject-bg-soft); color:var(--subject-primary); }
/* поддержка — не предмет: кросс-предметные сущности идут на нейтралях
   (foundations/surfaces.md). Синий здесь занят математикой, в списке они соседи. */
.chat .av-neutral{ background:var(--bg-subtle); color:var(--text-secondary); }

/* ==================================================================
   СЛОЙ 2 — ДИАЛОГ
   ================================================================== */
.chat .dhead-av{ display:flex; flex:none; }
.chat .dhead-id{ min-width:0; display:flex; flex-direction:column; justify-content:center; }
.chat .dhead-name{
  display:block; font-family:var(--font-head); font-weight:700; font-size:16px;
  color:var(--text-strong); line-height:1.2;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* Р25: присутствие — «в сети» / «был(а) N назад»; у поддержки вместо него режим работы */
.chat .dhead-sub{
  display:block; font-size:12px; line-height:1.25; color:var(--text-secondary);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.chat .dhead-sub.online{ color:var(--subject-primary); }
/* Р22: строка контекста — чем занят разговор */
.chat .dctx{
  flex:none; margin:var(--space-3) var(--space-4) 0;
  font-size:12px; line-height:1.4; color:var(--text-secondary);
  background:var(--bg-subtle); border-radius:var(--radius-sm);
  padding:var(--space-2) var(--space-3);
}

/* --- лента --- */
/* overflow-x:hidden — страховка: при overflow-y:auto горизонталь встаёт в auto,
   и любой перелив содержимого даёт полосу прокрутки под лентой */
.chat .dbody{ flex:1; min-height:0; overflow-y:auto; overflow-x:hidden;
  /* контейнер ленты заканчивается на верхней границе поля ввода — иначе
     бегунок тянется до самого низа панели, мимо поля. Поле выведено из
     потока, само оно контейнер не укорачивает. */
  margin-bottom:calc(var(--input-h) + var(--input-gap));
  padding:var(--space-3) var(--space-4) var(--space-2);
  /* фон «Выход есть» — канон business/assets/design-system/patterns/chat-exit-path.svg,
     встроен data-URI, чтобы прототип остался одним файлом; масштаб 640px по плану паттерна */
  background-image:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 640' fill='none'><g stroke-linecap='round' stroke-linejoin='round'><path d='M32 112H112C139 112 154 96 154 70V42' stroke='%23A39C8B' stroke-opacity='.2' stroke-width='2.25'/><path d='M212 42V74C212 102 228 118 256 118H326' stroke='%23A39C8B' stroke-opacity='.2' stroke-width='2.25'/><circle cx='154' cy='42' r='4.5' fill='%23B9DCC5' fill-opacity='.72'/><circle cx='212' cy='42' r='3' fill='%23B7791F' fill-opacity='.54'/><path d='M62 272H176C203 272 220 289 220 316V346' stroke='%23B9DCC5' stroke-opacity='.5' stroke-width='2.5'/><rect x='215' y='364' width='10' height='48' rx='5' fill='%23E1DDD1' fill-opacity='.78'/><path d='M220 430V466C220 493 237 510 264 510H352' stroke='%23A39C8B' stroke-opacity='.18' stroke-width='2.25'/><path d='M392 178H472C499 178 516 195 516 222V260' stroke='%23A39C8B' stroke-opacity='.18' stroke-width='2.25'/><path d='M516 314V344C516 371 533 388 560 388H608' stroke='%23A39C8B' stroke-opacity='.18' stroke-width='2.25'/><rect x='510' y='276' width='12' height='22' rx='2' fill='%230F7A3D' fill-opacity='.2'/><path d='M350 574H414C442 574 458 558 458 530V486C458 459 475 442 502 442H578' stroke='%23E1DDD1' stroke-opacity='.86' stroke-width='2.5'/><path d='M74 574H124' stroke='%23B7791F' stroke-opacity='.45' stroke-width='3'/><path d='M26 476A132 132 0 0 1 158 344' stroke='%23B9DCC5' stroke-opacity='.24' stroke-width='26'/><path d='M506 76A94 94 0 0 1 600 170' stroke='%23E1DDD1' stroke-opacity='.68' stroke-width='24'/><rect x='352' y='298' width='58' height='4' rx='2' fill='%23B7791F' fill-opacity='.5'/><rect x='118' y='182' width='26' height='7' rx='3.5' fill='%230F7A3D' fill-opacity='.18'/><circle cx='438' cy='86' r='5' fill='%23B9DCC5' fill-opacity='.68'/></g></svg>");
  background-repeat:repeat; background-size:640px 640px;
}
/* тёмная тема: у паттерна нет тёмного варианта (палитра под светлую поверхность) — до отдельного пасса отключён */
:root[data-theme="dark"] .chat .dbody{ background-image:none; }
.chat .feed{ display:flex; flex-direction:column; gap:2px; min-width:0;
  max-width:var(--feed-max); width:100%; margin-inline:auto; }

/* --- разделители --- */
.chat .c-day{
  align-self:center; margin:var(--space-4) 0 var(--space-3);
  font-size:12px; font-weight:500; color:var(--text-secondary);
  background:var(--bg-subtle); border-radius:var(--radius-pill); padding:2px 12px;
}
.chat .feed > .c-day:first-child{ margin-top:0; }
/* Р18: линия «непрочитанные» — она же якорь входа в чат */
.chat .unread-sep{
  display:flex; align-items:center; gap:var(--space-3);
  margin:var(--space-4) 0 var(--space-3);
  font-size:11px; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--state-warning);
}
.chat .unread-sep::before, .chat .unread-sep::after{
  content:''; flex:1; height:1px; background:var(--state-warning); opacity:.35;
}

/* --- колонка автора (Р10) ---
   Есть у всех сообщений серии, но аватар рисуется только у последнего —
   остальные держат пустое место, иначе серия «ступенькой» гуляет влево-вправо. */
.chat .who{ position:relative; flex:none; width:32px; height:32px; align-self:flex-end; }
.chat .who .av{ width:32px; height:32px; font-size:12px; }
/* Р11: подпись роли — только у гостей разговора (эксперт, глава кураторов).
   Выведена из потока: иначе тянет колонку вниз и низ пузыря перестаёт
   совпадать с низом аватара. */
.chat .who-label{
  position:absolute; bottom:100%; left:50%; transform:translateX(-50%);
  margin-bottom:3px; white-space:nowrap;
  font-size:9px; line-height:1.15; text-align:center; color:var(--text-secondary);
}
.chat .c-m.last.has-label{ margin-top:6px; }   /* подписи нужен воздух сверху */

/* --- сообщение --- */
.chat .c-m{ display:flex; align-items:flex-end; gap:6px; max-width:88%; min-width:0; }
.chat .c-m.in{ align-self:flex-start; }
.chat .c-m.out{ align-self:flex-end; flex-direction:row-reverse; }
/* зазор ставится ПОСЛЕ последнего в серии: внутри серии 2px (gap ленты),
   между сериями — 10px. Самое хрупкое место вёрстки (pre-mortem п.2). */
.chat .c-m.last{ margin-bottom:10px; }
.chat .feed > .c-m:last-child{ margin-bottom:0; }

.chat .bub{
  position:relative; min-width:0; max-width:100%;
  padding:7px 11px; border-radius:var(--radius-md);   /* 12px — ступень вниз от lg 18px */
  font-size:var(--chat-fs); line-height:1.5;
  overflow-wrap:anywhere;   /* длинная ссылка не распирает пузырь */
}
/* без рамки и тени: с 1px-бордюром хвост не сшить бесшовно, а закрасить стык
   плашкой фона нельзя — под пузырём паттерн */
.chat .c-m.in .bub{ --bub-bg:var(--bg-card); background:var(--bub-bg); }
.chat .c-m.out .bub{ --bub-bg:var(--subject-bg-soft); background:var(--bub-bg); }
/* ХВОСТ — только у входящих: он тянется к аватару, а у своих сообщений
   аватара нет, там хвосту не к чему идти. Форма — вырез окружностью
   радиуса 16px (= радиус аватара 32px), изгиб читается заодно с ним.
   Угол с хвостом строго 0: любое скругление отрывает хвост от стенки. */
.chat .c-m.in.last .bub{ border-bottom-left-radius:0; }
.chat .c-m.in.last .bub::after{
  content:''; position:absolute; bottom:0; left:-10px;
  width:10px; height:18px; background:var(--bub-bg); pointer-events:none;
  -webkit-mask:radial-gradient(circle 16px at 0 0, transparent 99%, #000 100%);
          mask:radial-gradient(circle 16px at 0 0, transparent 99%, #000 100%);
}
.chat .bub p{ margin:0; }
.chat .bub p + p{ margin-top:var(--space-2); }

/* Время занимает ЧАСТЬ последней строки, а не строку целиком (как в TG).
   Приём: в конец текста встаёт невидимая распорка шириной со время — она
   участвует в переносе строк, а само время лежит абсолютом в этом месте.
   Не влезло в строку — распорка переносится, и время оказывается ниже. */
.chat .c-m.in{ --meta-w:36px; }
.chat .c-m.out{ --meta-w:58px; }
.chat .meta-gap{ display:inline-block; width:var(--meta-w); height:1px; }
.chat .meta{
  display:inline-flex; align-items:center; gap:3px;
  font-size:11px; line-height:1; color:var(--text-secondary);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.chat .meta.abs{ position:absolute; right:12px; bottom:7px; }
/* при медиа время встаёт своей строкой. Модификатор НЕ называть row: .row в
   чате — строка списка чатов, и время подхватывало её grid, паддинги и
   подсветку на наведении (замечено Игорем 2026-08-07 на карточке урока). */
.chat .meta.line{ display:flex; justify-content:flex-end; margin-top:3px; }
/* Ширину задаём явно под каждый viewBox: при width:auto inline-SVG берёт
   дефолт заменяемого элемента (300px) — время уезжает за пузырь.
   margin-bottom — компенсация: flex центрирует по line-box, а чернила цифр
   лежат выше его центра. */
.chat .meta .ic{ height:8px; width:auto; stroke-width:1.8; margin-bottom:1.5px; }
.chat .meta .ck1{ width:9px; }     /* одинарная, viewBox 13×12 */
.chat .meta .ck2{ width:15px; }    /* двойная,   viewBox 22×12 */
.chat .meta .ck0{ width:8px; }     /* часики,    viewBox 24×24 */
.chat .meta .st-read{ color:var(--subject-primary); }

/* --- тип: формула (Р14) --- */
.chat .f-block{
  display:block; margin:6px 0 2px; padding:6px 10px;
  background:var(--bg-subtle); border-radius:var(--radius-sm);
  overflow-x:auto; text-align:center;
}
.chat .c-m.out .f-block{ background:rgba(255,255,255,.55); }
:root[data-theme="dark"] .chat .c-m.out .f-block{ background:rgba(255,255,255,.07); }
.chat .f-fallback{ font-family:var(--font-formula); font-style:italic; }

/* --- тип: фото тетради пачкой (Р16) --- */
.chat .photos{
  display:grid; gap:3px; margin:2px 0 4px;
  grid-template-columns:repeat(2, minmax(0,1fr));
}
.chat .photos.n1{ grid-template-columns:minmax(0,1fr); }
.chat .photos.n3 > :first-child{ grid-column:1 / -1; }
.chat .shot{
  aspect-ratio:4/3; border-radius:var(--radius-sm); border:1px solid var(--border-default);
  background:
    repeating-linear-gradient(to bottom, transparent 0 12px, rgba(36,88,211,.13) 12px 13px),
    linear-gradient(180deg,#FCFBF7,#F6F4EE);
  position:relative; overflow:hidden;
}
:root[data-theme="dark"] .chat .shot{
  background:
    repeating-linear-gradient(to bottom, transparent 0 12px, rgba(110,160,245,.16) 12px 13px),
    linear-gradient(180deg,#20242B,#1A1D22);
}
.chat .shot::after{
  content:''; position:absolute; left:12%; right:22%; top:26%; height:2px;
  background:var(--text-secondary); opacity:.35; border-radius:2px;
  box-shadow:0 13px 0 rgba(107,99,83,.30), 0 26px 0 rgba(107,99,83,.22),
             -6px 39px 0 rgba(107,99,83,.16);
}
.chat .photos .more{
  position:absolute; inset:0; display:grid; place-items:center;
  background:rgba(23,17,10,.42); color:#fff;
  font-family:var(--font-head); font-weight:600; font-size:19px;
}

/* --- тип: карточка задачи/урока (Р14) ---
   Вложение БЕЗ рамки и подложки: строка внутри пузыря, как в мессенджере.
   minmax(0,1fr) обязателен — 1fr не сжимается ниже содержимого, и строка
   вылезает за пузырь, а от неё идёт горизонтальный скролл всей ленты. */
.chat .c-task{
  display:grid; grid-template-columns:auto minmax(0,1fr); gap:10px;
  align-items:center; width:100%; text-align:left;
  margin:3px 0 2px; padding:2px 0;
  background:none; border:0; cursor:pointer; font:inherit; color:inherit;
}
.chat .c-task .tic{
  width:34px; height:34px; border-radius:var(--radius-pill); flex:none;
  display:grid; place-items:center;
  background:var(--subject-primary); color:#fff;
  transition:transform .12s ease;
}
.chat .c-task:hover .tic{ transform:scale(1.06); }
.chat .c-task .tic .ic{ width:18px; height:18px; }
.chat .c-task .c-tt{ min-width:0; }
/* оба — блочные: строчными они склеиваются в одну строку и распирают карточку */
.chat .c-task .t-name{
  display:block; font-family:var(--font-head); font-weight:600;
  font-size:calc(var(--chat-fs) + 1px); line-height:1.3; color:var(--text-strong);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.chat .c-task .t-kind{
  display:block; font-size:calc(var(--chat-fs) - 2px); line-height:1.3;
  color:var(--text-secondary);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

/* --- меню действий на сообщении (Р17) --- */
.chat .mact{
  flex:none; width:26px; height:26px; display:grid; place-items:center;
  border:0; background:none; border-radius:var(--radius-pill); cursor:pointer;
  color:var(--text-secondary); opacity:0; transition:opacity .12s ease, background .12s ease;
}
.chat .mact .ic{ width:17px; height:17px; }
.chat .c-m:hover .mact{ opacity:1; }
.chat .mact:hover{ background:var(--bg-subtle); }
.chat .mact:focus-visible{ opacity:1; }
@media (hover:none){ .chat .mact{ display:none; } }   /* на телефоне — долгий тап */
.chat .c-m.act-open .bub{ box-shadow:0 0 0 2px var(--subject-border); }

/* меню живёт вне панели: иначе его режет overflow:hidden сцены слоёв */
.chat-menu{
  position:fixed; z-index:90; min-width:210px; padding:var(--space-1);
  background:var(--bg-card); border:1px solid var(--border-default);
  border-radius:var(--radius-md); box-shadow:var(--shadow-card);
  display:none;
}
.chat-menu[data-open="1"]{ display:block; }
.chat-menu button{
  display:flex; align-items:center; gap:var(--space-3); width:100%;
  padding:var(--space-2) var(--space-3); border:0; background:none; cursor:pointer;
  border-radius:var(--radius-sm); font:inherit; font-size:15px; text-align:left; color:var(--text-primary);
}
.chat-menu button:hover{ background:var(--bg-subtle); }
.chat-menu button .ic{ width:18px; height:18px; color:var(--text-secondary); }

/* --- поле ввода ---
   Плотное, лежит на панели. Ни блюра, ни градиента над ним нет (решение
   Игоря 2026-08-07): лента заканчивается на его верхней границе, контент
   под поле не уходит и растворять нечего. */
.chat .dinput{
  position:absolute; left:var(--space-4); right:var(--space-4); bottom:var(--input-gap);
  max-width:var(--feed-max); margin-inline:auto;   /* тот же предел, что у ленты */
  display:flex; align-items:center; gap:var(--space-2);
  background:var(--bg-card);
  border:1px solid var(--border-interactive); border-radius:var(--radius-pill);
  padding:5px 5px 5px var(--space-4);
  font-size:calc(var(--chat-fs) + 1px);
}
.chat .dinput input{
  flex:1; min-width:0; border:0; outline:0; background:none;
  font:inherit; color:var(--text-primary);
}
.chat .dinput .send{
  width:36px; height:36px; flex:none; display:grid; place-items:center; border:0;
  background:var(--subject-bg-soft); color:var(--subject-primary);
  border-radius:var(--radius-pill); cursor:pointer;
}

/* --- бейдж непрочитанных (Р7): список + топбар + капсула, всегда числом ---
   Размер идёт от места: в строке списка он сосед времени и аватара 44px,
   на иконке — метка поверх кнопки 40px. Один размер на оба делал метку
   на кнопке тяжелее самой иконки.
   Геометрия одной связкой: min-width = height даёт круг на одну цифру,
   боковой паддинг растягивает в капсулу на две-три. line-height не задаём —
   центруем флексом, иначе при смене кегля цифра уползает. */
.badge{
  --badge-h:18px;
  display:inline-flex; align-items:center; justify-content:center;
  min-width:var(--badge-h); height:var(--badge-h); padding:0 5px;
  border-radius:var(--radius-pill);
  background:var(--action-primary); color:var(--action-on-primary);
  font-size:11px; font-weight:600; line-height:1;
  font-variant-numeric:tabular-nums;
}
.icon-btn .badge, .ctab .badge{ --badge-h:16px; font-size:10px; padding:0 4px; }
/* .tb-actions .icon-btn уже position:relative (там же живёт .notif-dot) */
.icon-btn .badge{ position:absolute; top:0; right:0; box-shadow:0 0 0 2px var(--bg-page); }
.badge[hidden]{ display:none; }

/* ==================================================================
   МОБИЛЬНАЯ КАПСУЛА v3а (эталон)
   ================================================================== */
.capsule-wrap{ display:none; }
/* фон за раскрытием — затемнение (решение Игоря 2026-07-27); слой всегда есть, ловит клик «мимо меню» */
.cube-dim{ position:fixed; inset:0; z-index:58; background:rgba(20,24,28,.45); opacity:0; pointer-events:none; transition:opacity .25s ease; }
body.cube-open .cube-dim{ opacity:1; pointer-events:auto; }
/* точка отсчёта сетки = ЦЕНТР куба (JS ставит left/top): меню растёт из кнопки, стоит низко */
.cube-cloud{ position:fixed; left:50%; top:50%; width:0; height:0; z-index:60; pointer-events:none; }
.cbub{
  position:absolute; left:0; top:0; width:max-content;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  transform:translate(-50%,-50%) scale(.25); opacity:0; border:0; background:none; font:inherit;
  cursor:pointer; padding:0; pointer-events:none;
  transition:transform .34s cubic-bezier(.34,1.3,.64,1), opacity .18s ease;
}
body.cube-open .cbub{
  opacity:1; pointer-events:auto;
  transform:translate(calc(-50% + var(--tx,0px)), calc(-50% + var(--ty,0px))) scale(var(--s,1));
}
/* ПЛОСКО: нео-тень и свечение сняты, осталась волосяная рамка (решение Игоря 2026-07-27) */
.cbub .c{
  width:56px; height:56px; border-radius:50%; color:var(--text-primary);
  background:var(--bg-card); border:1px solid var(--border-default);
  display:flex; align-items:center; justify-content:center; transition:background-color .15s ease;
}
.cbub .c .ic{ width:23px; height:23px; }
/* подпись — второй <span>; селектор обязан исключать .c, иначе стиль летит и на кружок */
.cbub > span:not(.c){
  font-size:11px; line-height:1.35; font-weight:600; color:var(--text-primary);
  background:var(--bg-card); border:1px solid var(--border-default);
  border-radius:var(--radius-pill); padding:1px 8px; white-space:nowrap;
}
.cbub:active .c{ background:var(--bg-subtle); }
/* высота ужата (2026-07-27): поля 5px, пункт 44px (минимальная пальцевая цель) → капсула 56px */
/* ПЛОСКО (правка Игоря 2026-07-29): тени сняты полностью, держит волосяная рамка.
   Сверху 4px воздуха — иконки больше не прижаты к кромке капсулы */
.capsule{
  --cap-pad-y:5px; --cap-pad-x:14px;
  position:fixed; left:50%; transform:translateX(-50%);
  bottom:var(--nav-safe);
  z-index:62; display:flex; align-items:center; gap:2px;
  /* держится ЦВЕТОМ, а не тенью: белее листа + внятная рамка, поэтому читается
     и над бежевым фоном страницы, и над белой карточкой (правка Игоря 2026-07-29) */
  background:#fff; border:1.5px solid var(--border-secondary);
  border-radius:var(--radius-pill);
  padding:calc(var(--cap-pad-y) + 4px) var(--cap-pad-x) var(--cap-pad-y);
  box-shadow:none;
}
.ctab{
  width:60px; display:flex; flex-direction:column; align-items:center; gap:2px; border:0;
  background:none; color:var(--text-secondary); font:inherit; font-size:9.5px; cursor:pointer;
  padding:3px 0 2px; min-height:44px; position:relative; border-radius:14px;
}
.ctab .ic{ width:22px; height:22px; }
/* выбранный = цвет + насыщенность; подчёркивание снято (спорило с кромкой капсулы) */
.ctab.on{ color:var(--menu-selected); font-weight:600; }
.ctab .b{ position:absolute; top:2px; right:12px; width:8px; height:8px; border-radius:50%; background:var(--action-bright); border:1.5px solid var(--bg-card); }
/* счётчик непрочитанных на вкладке чата (Р7). Отсчёт от ЦЕНТРА кнопки, а не
   от её края: иконка стоит по центру, а ширину кнопки задаёт подпись под ней —
   от края метка у каждой вкладки оказывалась на своём расстоянии от иконки. */
.ctab .badge{ position:absolute; top:0; left:calc(50% + 4px); right:auto;
  box-shadow:0 0 0 2px var(--neo-bg); }
.cube{
  width:60px; height:60px; margin:-26px 3px 0; border-radius:50%; border:0; cursor:pointer;
  background:linear-gradient(135deg,var(--action-bright),var(--action-primary) 70%);
  color:var(--action-on-primary); display:flex; align-items:center; justify-content:center; flex:none;
  box-shadow:0 8px 18px color-mix(in srgb,var(--action-primary) 45%,transparent), inset 0 1px 0 rgba(255,255,255,.35);
  transition:transform .25s ease; position:relative;
}
body.cube-open .cube{ transform:rotate(45deg); }
.cube .ic{ width:27px; height:27px; }

/* ==================================================================
   ОВЕРЛЕИ / ТОСТ / ДЕМО-ПАНЕЛЬ ПРОТОТИПА
   ================================================================== */
.backdrop{ position:fixed; inset:0; z-index:48; background:rgba(23,33,43,.34); opacity:0; pointer-events:none; transition:opacity .2s; }
body.notif-open .backdrop, body.profile-open .backdrop, body.toc-open .backdrop{ opacity:1; pointer-events:auto; }
/* профиль: без затемнения на ЛЮБОМ экране (правка Игоря 2026-08-06) —
   бэкдроп остаётся невидимым кликом-ловушкой «мимо = закрыть» */
body.profile-open .backdrop{ opacity:0; }
@media (min-width:861px){
  body.notif-open .backdrop{ opacity:0; }
}
.toast{
  position:fixed; z-index:70; left:calc(var(--space-4) + var(--rail-w) + var(--space-4)); bottom:var(--space-5);
  max-width:340px; padding:var(--space-3) var(--space-4);
  background:#17212B; color:#E7EAF0; font-size:14px; line-height:1.5;
  border-radius:var(--radius-md); box-shadow:0 12px 32px rgba(23,33,43,.25);
  opacity:0; transform:translateY(8px); pointer-events:none; transition:opacity .2s, transform .2s;
}
.toast.is-visible{ opacity:1; transform:translateY(0); }
/* полоса демо-навигации — леса прототипа, НЕ часть продукта */
.pbar{
  position:sticky; top:0; z-index:80; height:var(--pbar-h);
  display:flex; align-items:center; gap:6px; padding:0 var(--space-3); overflow-x:auto;
  background:#17212B; color:#C9D1DA; font-size:12.5px; white-space:nowrap;
}
body.pbar-off .pbar{ display:none; }
.pbar .lab{ font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:#7E8B99; flex:none; }
.pbar button{
  flex:none; border:1px solid #2C3A48; background:#1E2A36; color:#C9D1DA;
  border-radius:var(--radius-pill); padding:5px 11px; font:inherit; font-size:12.5px; cursor:pointer;
}
.pbar button:hover{ background:#27353F; color:#fff; }
.pbar button[aria-current="true"]{ background:var(--action-primary); border-color:var(--action-primary); color:#fff; }
.pbar .sep{ flex:none; width:1px; height:20px; background:#2C3A48; margin:0 4px; }
.pbar .grow{ flex:1 1 auto; }
.pbar .hint{ flex:none; color:#7E8B99; }
.pbar-show{
  display:none; position:fixed; left:var(--space-3); bottom:var(--space-3); z-index:80;
  border:0; border-radius:var(--radius-pill); background:#17212B; color:#C9D1DA;
  padding:8px 14px; font:inherit; font-size:12.5px; cursor:pointer;
}
body.pbar-off .pbar-show{ display:block; }

/* ==================================================================
   ЗОНЫ 2-3 (≥861): десктопная оболочка. Топбар привязан к СЕТКЕ, не к оглавлению.
   ================================================================== */
@media (min-width:861px){
  body[data-screen="lesson"] .toc{ display:flex; }
  body[data-screen="lesson"].toc-collapsed .toc{ transform:scale(.02); opacity:0; pointer-events:none; }
  body[data-screen="lesson"].toc-collapsed .toc-tab{ display:flex; }
  /* крошки на уроке: плоский текст, левый край = левый край текста урока */
  body[data-screen="lesson"] .context{
    position:absolute; top:0; height:var(--topbar-h);
    left:calc((100% - var(--measure)) / 2); right:auto; max-width:none; margin:0; padding:0;
    display:flex; align-items:center; justify-content:flex-start;
    background:none; border-radius:0; overflow:visible; pointer-events:none;
  }
  body[data-screen="lesson"] .context .crumbs{ pointer-events:auto; }
  .tb-actions{ position:absolute; top:0; height:var(--topbar-h); right:var(--space-5); display:flex; align-items:center; }
  /* КАРКАС ДЕСКТОПА — одно правило на все кабинетные экраны (правка Игоря 2026-07-29).
     Рейл стоит поверх страницы и съедает левую полосу, поэтому симметричный жёлоб
     с обеих сторон давал контент, смещённый влево ОТНОСИТЕЛЬНО ВИДИМОЙ области.
     Считаем от рейла: слева жёлоб = рейл + воздух, справа = тот же воздух. Тогда
     центр контента совпадает с центром зоны «после рейла», а не с центром экрана.
     Ширина блока с информацией везде одна: .wrap = min(75rem, доступная ширина),
     поля 24px. Экран урока — исключение: там колонка чтения --measure.
     Прыжки при переключении экранов гасит scrollbar-gutter:stable на html. */
  body:not([data-screen="lesson"]) .page{ padding-left:var(--gutter); padding-right:var(--space-4); }
  /* логотип центрирован по оси рейла (правка Игоря 2026-08-06): сдвиг считается от
     паддинга топбара (24) к центру рейла (16 + rail-w/2), 79px — ширина wordmark;
     следует за шириной рейла (72/224) с той же анимацией, что и сам рейл */
  .brand{ margin-left:calc(var(--space-4) + (var(--rail-w) - 79px)/2 - var(--space-5)); transition:margin-left .2s ease; }
}
/* ==================================================================
   ЗОНА 3 (≥1151): чат = колонка справа, сужает рабочую область (К20)
   ================================================================== */
@media (min-width:1151px){
  body.chat-open[data-screen="lesson"] .page{
    padding-left:calc(var(--space-4) + 72px + var(--space-4));
    padding-right:calc(var(--chat-w) + var(--space-5));
  }
  body.chat-open:not([data-screen="lesson"]) .page{
    padding-left:var(--gutter);
    padding-right:calc(var(--chat-w) + var(--space-5));
  }
  body.chat-open .toc{ transform:scale(.02); opacity:0; pointer-events:none; }
  body.chat-open .toc-tab{ display:none; }
}
/* ==================================================================
   ЗОНА 1 (≤860, телефон): рейл скрыт, капсула, топбар 2 зоны, шторки снизу
   ================================================================== */
@media (max-width:860px){
  .page{ padding:var(--space-3) 0 120px; }
  .wrap{ padding:0 var(--space-5); }
  .topbar{ grid-template-columns:auto 1fr; gap:var(--space-3); padding:0 var(--space-4); }
  .context{ display:none !important; }                /* К37: крошек на мобиле нет */
  .priority{ display:none !important; }               /* пока плашка видна в ленте — в топбаре пусто */
  .priority-mobile{
    display:flex; align-items:center; gap:var(--space-2); margin:0 0 var(--space-4);
    padding:10px var(--space-4); border-radius:var(--radius-lg);
    background:var(--bg-subtle); font-size:14px; line-height:1.45; color:var(--text-primary);
  }
  .priority-mobile b{ color:var(--subject-primary); }
  /* ---- уведомление уезжает в топбар: как только плашка в ленте ушла за верх,
     сообщение появляется в топбаре строкой; не влезло целиком — бежит (правка Игоря 2026-07-27) ---- */
  body.priority-docked .topbar{ grid-template-columns:auto minmax(0,1fr) auto; }
  body.priority-docked[data-center="priority"] .priority{
    display:block !important; justify-self:stretch; min-width:0;
    background:none; padding:0; font-size:13.5px; text-align:left;
  }
  body.focus-mode .priority{ display:none !important; }   /* К19: в фокус-режиме центр пуст */
  .rail{ display:none; }
  body.nav-hidden .topbar{ transform:translateY(-100%); }
  #chatBtn{ display:none; }
  .capsule-wrap{ display:block; }
  body[data-layer="guest"] .capsule-wrap{ display:none; }
  /* МЕНЮ КАБИНЕТА ОСТАЁТСЯ И НА УРОКЕ (правка Игоря 2026-07-29, канон lesson-shell-v2):
     на телефоне капсула — единственная навигация, и прятать её в focus-mode значило
     запирать ученика в экране (выход был только текстовой ссылкой в focus-строке).
     Уступает место она только шторкам оглавления и чата — они занимают тот же низ. */
  body.toc-open .capsule, body.chat-open .capsule{ display:none; }
  /* на уроке низ занимают И капсула, И зелёная FAB оглавления над ней: последний блок
     страницы («Далее» с кнопкой справа) не должен уезжать под FAB */
  body[data-screen="lesson"] .page{ padding-bottom:calc(var(--nav-safe) + 148px); }
  /* FAB стоит у правой кромки капсулы: свободное поле сбоку = (1 − доля)/2 от ширины блока.
     Доля ширины и смещение FAB — ОДНА пара переменных, иначе FAB молча отклеится от края. */
  .toc-fab{
    display:none; align-items:center; justify-content:center;
    position:fixed; z-index:61;
    right:calc(var(--cap-inset) + (100vw - 2*var(--cap-inset)) * (1 - var(--cap-w-factor)) / 2);
    bottom:calc(var(--nav-safe) + 80px);
    width:56px; height:56px; border:0; border-radius:var(--radius-pill);
    background:var(--action-primary); color:var(--action-on-primary); cursor:pointer;
    box-shadow:0 10px 30px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.10);
    transition:transform .25s ease, opacity .25s ease;
  }
  body[data-screen="lesson"] .toc-fab{ display:flex; }
  .toc-fab .ic{ width:26px; height:26px; }
  body.nav-hidden .toc-fab{ transform:translateY(160%); opacity:0; pointer-events:none; }
  body.toc-open .toc-fab, body.chat-open .toc-fab, body.cube-open .toc-fab{ display:none; }
  .capsule{ left:50%; right:auto; transform:translateX(-50%); justify-content:space-around;
    width:calc((100vw - 2*var(--cap-inset)) * var(--cap-w-factor)); }
  /* растворение вернулось коротким (метка Игоря 2026-07-29): полоса от самого низа
     экрана до нижней кромки капсулы — она закрывает щель, в которой мелькал текст,
     и больше не мутит пол-экрана. Тени по-прежнему сняты */
  .nav-fade{
    display:block; position:fixed; left:0; right:0; bottom:0; z-index:47; pointer-events:none;
    height:calc(var(--nav-safe) + 26px);
    background:linear-gradient(to top,
      var(--bg-page) 0%,
      color-mix(in srgb, var(--bg-page) 72%, transparent) 55%,
      color-mix(in srgb, var(--bg-page) 0%, transparent) 100%);
    -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
    -webkit-mask-image:linear-gradient(to top, #000 45%, transparent 100%);
            mask-image:linear-gradient(to top, #000 45%, transparent 100%);
  }
  body[data-layer="guest"] .nav-fade{ display:none; }
  /* оглавление → шторка снизу */
  body[data-screen="lesson"] .toc{
    top:auto; right:0; left:0; bottom:0; width:auto; height:auto;
    max-height:86vh; max-height:86dvh;
    border-radius:var(--neo-r) var(--neo-r) 0 0; z-index:55; box-shadow:none;
    transform:translateY(100%); transform-origin:bottom center;
    padding-bottom:env(safe-area-inset-bottom, 0px);
  }
  body[data-screen="lesson"].toc-open .toc{ transform:translateY(0); }
  /* маршрут на телефоне — тот же DOM, уже только жёлоб (сдвиг 16–20 по ТЗ).
     Размеры маркеров НЕ трогаем: SVG остаётся 1:1, толщины совпадают везде */
  .rt{ --rt-shift:18px; --rt-col:50px; }
  .toc-grip{ display:block; width:44px; height:5px; border-radius:3px; background:var(--border-interactive); opacity:.5; margin:0 auto var(--space-2); flex:none; }
  .toc-collapse{ display:none; }
  .toc-close{ display:flex; }
  .toc-body{ margin-bottom:var(--space-3); }
  .toc-tab{ display:none !important; }
  .lesson{ padding:var(--space-6) var(--space-5) 0; }
  /* тост встаёт НАД капсулой: на телефоне он лежал на кнопках меню (z-70 против z-62) */
  .toast{ left:var(--space-4); right:var(--space-4); max-width:none; bottom:calc(var(--nav-safe) + 96px); }
  /* одноколоночные ленты */
  .tz-lead{ grid-template-columns:1fr; }
  /* ---- ШТАБ на телефоне: лента §12.2, светлый лист (зелёная зона — только разделы) ---- */
  .hq-grid{ grid-template-columns:1fr; grid-template-areas:"now" "events" "practice"; gap:var(--space-6); }
  /* карточка «Событий» остаётся белой и на телефоне: слитая с листом она читалась
     как «ничего нет» (правка Игоря 2026-07-27) */
  .zone-events > .hq-card{ padding:var(--space-5); }   /* планшетная ступень 24; мобильные 16 — ниже, на ≤520 */
  /* ---- ТЕЛЕФОН: те же закладки, но во всю ширину карточки, зоны делятся поровну ---- */
  .zone-now{ grid-template-columns:1fr; grid-template-areas:"label" "tabs" "card"; }
  /* лейбл ↔ его блок — 16 на мобильной, 24 на планшете и десктопе (§9.1, решение Игоря
     2026-07-28): на своей ступени всегда на шаг ближе, чем блоки друг к другу (24/32).
     Минус интерлиньяж под чернилами — считаем от букв, как на десктопе (§9.2а) */
  .section-label{ min-height:0; margin-bottom:calc(var(--space-4) - var(--lab-lead)); }
  .zone-now > .hq-tabs{ justify-self:stretch; }
  .hq-tab{ flex:1 1 0; min-width:0; text-align:center; padding:10px 12px; font-size:15px; font-weight:700; }
  .hq-tab:first-child .f.l{ display:none; }       /* у края карточки внешний уголок не нужен */
  .hq-now.sel-left{ border-top-left-radius:0; }   /* угол выпрямлен под активной крайней */
  .hq-cover{ height:auto; aspect-ratio:16/10; }
  .cover-h{ font-size:24px; }
  .seg .st-lab{ font-size:11px; }
  /* на узкой колонке те же пояснения занимают три строки — резерв растёт, карточка не прыгает */
  .hq-quiet, .overdue-banner{ min-height:calc(3 * 1.5em); }
  /* кнопки столбиком: главное действие сверху, «Обзор урока» под ним */
  .now-cta-row{ flex-direction:column; align-items:stretch; gap:var(--space-3); }
  .now-cta-row .btn, .now-cta-row .btn.v-primary, .now-cta-row .btn.v-link{ flex:none; width:100%; }
  .view-head h1{ font-size:27px; }
}
/* ==================================================================
   ЧАТ = ШТОРКА СНИЗУ в зонах 1-2 (≤1150)
   ================================================================== */
@media (max-width:1150px){
  .chat{
    display:flex; left:0; right:0; top:auto; bottom:0;
    width:auto; height:100dvh; max-height:100dvh;
    border-radius:var(--neo-r) var(--neo-r) 0 0; box-shadow:none; transform:translateY(100%);
    visibility:hidden;
  }
  body.chat-open .chat{ transform:translateY(0); visibility:visible; }
  body.chat-open .backdrop{ opacity:1; pointer-events:auto; }
  .chat-grip{ display:block; width:44px; height:5px; border-radius:3px; background:var(--border-interactive); opacity:.5; margin:var(--space-2) auto var(--space-1); flex:none; }
}
/* ТЕЛЕФОН В АЛЬБОМЕ. При высоте 390 хром съедает столько, что ленте остаётся
   пара реплик. Ужимаем то, что не несёт смысла: ручку, воздух шапки, полоску
   контекста и отступ поля. Сама лента и пузыри не трогаются. */
@media (max-width:1150px) and (max-height:560px){
  .chat{ --input-gap:var(--space-2); }
  .chat-grip{ margin:var(--space-1) auto 0; }
  .chat .lhead{ padding:var(--space-2) var(--space-4); }
  .chat .dctx{ margin-top:var(--space-2); padding:var(--space-1) var(--space-3); }
  .chat .dbody{ padding-top:var(--space-2); }
}
/* узкий десктоп 861-1150: кабинетные сетки в одну колонку, чтобы карточки не сплющивались */
@media (min-width:861px) and (max-width:1150px){
  .tz-lead{ grid-template-columns:1fr; }
  /* колонка «События» тут сплющивалась бы — раскладываем Штаб в один столбец */
  .hq-grid{ grid-template-columns:1fr; grid-template-areas:"now" "events" "practice"; }
  .pdirs{ grid-template-columns:1fr 1fr; }
}
/* открытый чат сужает рабочую область: «Здесь и сейчас» во всю ширину,
   под ним ряд 50/50 — Практика слева, События справа (Igor 2026-07-23) */
@media (min-width:1151px){
  body.chat-open .hq-grid{ grid-template-columns:1fr 1fr; grid-template-areas:"now now" "practice events"; }
  body.chat-open .pdirs{ grid-template-columns:1fr; }
  /* ловушка №6 канона scrollbar.md: в контейнере со скруглением капсула
     бегунка заезжает в дугу. Ход капсулы обрезаем по радиусу панели. */
  .chat .list::-webkit-scrollbar-track{ margin-bottom:var(--neo-r); }
}
/* ==================================================================
   ТЕЛЕФОН (≤520)
   ================================================================== */
@media (max-width:520px){
  .page{ padding:var(--space-4) 0 120px; }
  .wrap{ padding:0 var(--space-4); }
  .lesson{ padding:var(--space-5) var(--space-4) 0; }
  .lesson h1{ font-size:30px; }
  .hero{ margin:var(--space-5) 0; }
  .hero-chip{ display:none; }
  .callout{ flex-direction:column; align-items:flex-start; gap:var(--space-3); margin:var(--space-5) 0; }
  .skl-group{ margin-top:var(--space-6); }
  .ctab{ width:54px; font-size:9px; }
  .pdirs{ grid-template-columns:1fr; }   /* узкий телефон: направления в один столбец */
  /* мобильная ступень паддингов и инсетов включается ТОЛЬКО здесь (карта отступов §6) */
  .zone-events > .hq-card{ padding:var(--space-4); }
  .now-body{ padding:var(--space-4); }
  .cover-title{ left:var(--space-4); right:var(--space-4); bottom:var(--space-3); }
  .date-chip{ top:var(--space-3); left:var(--space-4); }
  .cov-pill{ top:var(--space-3); right:var(--space-4); }
  :root{ --cap-inset:var(--space-4); }   /* инсет капсулы = поле страницы на телефоне */
  .auth-card{ padding:var(--space-5); }
  .otp input{ width:34px; height:46px; font-size:18px; }
  .otp{ gap:6px; }
  .btn.sz-l{ width:100%; }
}
/* ==================================================================
   УЗКИЙ ТЕЛЕФОН (≤340) — 0.80 ширины уже режет подписи капсулы
   («Мой путь» переносится на две строки), поэтому капсулу отпускаем
   ================================================================== */
@media (max-width:340px){
  :root{ --cap-w-factor:0.88; }
  .capsule{ --cap-pad-x:10px; }
}
