/* Lorevo app mockup — restyle revision.
 * IT-tool aesthetic: dense grid, thin 1px borders, low radii, JetBrains Mono for
 * all numbers/technical data, code-review diff. Draws entirely from
 * shared/tokens.css — no hardcoded brand hex. Severity reuses correction tokens
 * (--error/--hint/--success), defined for both themes. --surface-elevated is
 * dark-only in tokens → fall back to --surface in light.
 */

:root { --line: var(--border); --hair: 1px;
  /* M3 (Сессия 20e): рамка поля ввода в ПОКОЕ — отдельный токен ≥3:1 к surface/bg
     (WCAG 1.4.11). НЕ глобальный --border/--line (иначе жирнеют все разделители).
     Замерено: #7E8A99 на surface 3.51 / на bg 3.20; на hover/focus рамка уходит в
     --primary. Тёмный эквивалент — ниже. Совпадает с --btn-edge лендинга. */
  --input-border: #7E8A99; }
[data-theme="dark"] { --input-border: #66707E; }  /* на surface 3.53 / на bg 3.56 */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
  font-family: var(--font-primary);
  background: var(--bg); color: var(--text);
  font-size: 16px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.mono { font-family: var(--font-mono); font-feature-settings: "tnum" 1; letter-spacing: -.02em; }
.muted { color: var(--text-secondary); }
.sm { font-size: 14px; }
a { color: inherit; text-decoration: none; }
/* Buttons don't inherit color by default → on dark theme native-styled buttons
   (.scn, .cfg-toggle) rendered near-black text on a dark surface. Inherit fixes
   the whole class; explicit .btn--cta/.btn--danger colors still win by specificity. */
button { font: inherit; cursor: pointer; color: inherit; }
h1, h2 { margin: 0; }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 12px; top: 12px; z-index: 50; background: var(--cta); color: var(--cta-text); padding: 8px 14px; border-radius: 6px; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }

.ic { display: inline-flex; width: 18px; height: 18px; flex: none; }
.ic svg { width: 100%; height: 100%; }

/* severity helpers */
.sev--error { color: var(--error-text); }
.sev--hint { color: var(--hint-text); }
.sev--success { color: var(--success-text); }
.sev--primary { color: var(--primary); }
.sev--cta { color: var(--cta); }
.sevbg--error { background: var(--error-text); }
.sevbg--hint { background: var(--hint-text); }
.sevbg--success { background: var(--success-text); }
/* Backend severity is 'error' | 'improvement'; UI palette is error/hint/success.
   Map 'improvement' onto the hint (amber) palette so improvement findings render
   instead of falling through to an undefined class (transparent bg / no colour). */
.sev--improvement { color: var(--hint-text); }
.sevbg--improvement { background: var(--hint-text); }

/* ---------- brand (identical to landing wordmark) ---------- */
.brand { display: inline-flex; align-items: baseline; }
.brand-logo { display: inline-flex; align-items: baseline; font-family: var(--font-primary); letter-spacing: -.5px; line-height: 1; }
.brand-lor { font-size: 24px; font-weight: 700; color: var(--primary); }
.brand-evo { font-size: 19px; font-weight: 700; color: var(--cta); }

/* ---------- app bar ---------- */
.appbar { display: flex; align-items: center; gap: 12px; padding: 14px 24px; border-bottom: var(--hair) solid var(--line); position: sticky; top: 0; background: var(--bg); z-index: 10; }
.appbar__sp { flex: 1; }
.appbar--sub { gap: 16px; }
.chip { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--text-secondary); border: var(--hair) solid var(--line); padding: 5px 11px; border-radius: 999px; background: var(--surface); }
.chip b { color: var(--text); }
.chip .ic { width: 15px; height: 15px; color: var(--cta); }
a.chip:hover { border-color: var(--primary); color: var(--text); }
.iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border: var(--hair) solid var(--line); background: var(--surface); color: var(--text); border-radius: 8px; }
.iconbtn:hover { background: var(--bg-alt); }
.backlink { display: inline-flex; align-items: center; gap: 4px; font-size: 14px; color: var(--text-secondary); }
.backlink .ic { width: 16px; height: 16px; }
.backlink:hover { color: var(--primary); }
.timer { font-size: 14px; color: var(--text-secondary); transition: color .3s ease; }
/* Last minute of the session — clear, persistent warning that the lesson is
   about to close (the status line churns too fast to carry it). */
.timer--ending { color: var(--error-text); font-weight: 700; }

/* ---------- section nav (tabbar) — desktop left rail / mobile bottom bar ---------- */
body { padding-left: 76px; }              /* desktop: room for the fixed left rail */
.tabbar { position: fixed; left: 0; top: 0; bottom: 0; width: 76px; display: flex; flex-direction: column; gap: 4px; padding: 16px 8px; border-right: var(--hair) solid var(--line); background: var(--surface); z-index: 20; }
.tab { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 4px; border-radius: 10px; color: var(--text-secondary); font-size: 11px; text-align: center; }
.tab .ic { width: 22px; height: 22px; }
.tab:hover { background: var(--bg-alt); color: var(--text); }
.tab--on { color: var(--primary); background: var(--bg-alt); }

/* ---------- layout ---------- */
.wrap { max-width: 760px; margin: 0 auto; padding: 24px; display: flex; flex-direction: column; gap: 16px; }
.wrap--narrow { max-width: 680px; }
.cols-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.metrics-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.actions-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.hero { padding-top: 4px; }
.h-hero { font-size: 34px; font-weight: 700; letter-spacing: -.5px; }
.h-screen { font-size: 28px; font-weight: 700; letter-spacing: -.4px; display: flex; align-items: center; gap: 10px; }
.h-screen .h-ic { width: 22px; height: 22px; color: var(--success-text); }
.h-center { justify-content: center; }
.h-sec { font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: .8px; color: var(--text-secondary); display: inline-flex; align-items: center; gap: 8px; }
.sub { color: var(--text-muted); font-size: 14px; margin: 2px 0 0; }
.sub--center { text-align: center; }
.head-block { display: flex; flex-direction: column; gap: 4px; }

/* ---------- panel / card ---------- */
.panel { background: var(--surface); border: var(--hair) solid var(--line); border-radius: 10px; padding: 16px; }
.panel--danger { border-color: var(--error-border); }
.panel__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.panel__bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.panel__bar .lbl { font-size: 12px; text-transform: uppercase; letter-spacing: .8px; color: var(--text-secondary); }

.link { color: var(--primary); font-weight: 500; font-size: 13px; display: inline-flex; align-items: center; gap: 4px; background: none; border: none; padding: 0; }
.link .ic { width: 14px; height: 14px; }
.link:hover { text-decoration: underline; }

/* ---------- buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 11px 18px; border: var(--hair) solid transparent; border-radius: 8px; font-weight: 600; font-size: 15px; transition: transform 130ms cubic-bezier(.22,1,.36,1), background 130ms ease; }
.btn:active { transform: scale(.985); }
.btn .ic { width: 18px; height: 18px; }
.btn--cta { background: var(--primary); color: #fff; }
.btn--cta:hover { filter: brightness(.93); }
/* Dark: --primary is the light petrol used for the waveform; white text on it
   fails AA. Use --primary-strong (#1A5F7A) for solid CTAs — white passes AA. */
[data-theme="dark"] .btn--cta { background: var(--primary-strong); }
[data-theme="dark"] .fchip.on { background: var(--primary-strong); border-color: var(--primary-strong); }
.btn--ghost { background: var(--surface); color: var(--text); border-color: var(--line); }
.btn--ghost:hover { background: var(--bg-alt); }
.btn--danger { background: transparent; color: var(--error-text); border-color: var(--error-border); }
.btn--danger:hover { background: var(--error-bg); }
.btn--block { width: 100%; padding: 14px; }
.btn--sm { padding: 8px 14px; font-size: 14px; }

/* ---------- badges / pills ---------- */
.badge { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; background: var(--neutral-bg); color: var(--neutral-text); border: var(--hair) solid var(--neutral-border); }
.badge--soon { color: var(--text-muted); font-weight: 500; text-transform: none; }
.badge--error { background: var(--error-bg); color: var(--error-text); border-color: var(--error-border); }
.badge--hint { background: var(--hint-bg); color: var(--hint-text); border-color: var(--hint-border); }
.badge--success { background: var(--success-bg); color: var(--success-text); border-color: var(--success-border); }
.badge--improvement { background: var(--hint-bg); color: var(--hint-text); border-color: var(--hint-border); }
.pill { font-family: var(--font-mono); font-size: 12px; font-weight: 500; padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.pill--error { background: var(--error-bg); color: var(--error-text); }
.pill--hint { background: var(--hint-bg); color: var(--hint-text); }
.pill--success { background: var(--success-bg); color: var(--success-text); }
.pill--improvement { background: var(--hint-bg); color: var(--hint-text); }

/* ---------- metrics ---------- */
.metric { border: var(--hair) solid var(--line); background: var(--surface); border-radius: 10px; padding: 14px; }
.metric__label { font-size: 12px; text-transform: uppercase; letter-spacing: .6px; color: var(--text-secondary); }
.metric__val { font-size: 30px; font-weight: 600; margin-top: 4px; line-height: 1; }
.metric__suf { font-family: var(--font-primary); font-size: 13px; font-weight: 400; color: var(--text-secondary); }
.metric--rule .metric__label { text-transform: lowercase; letter-spacing: 0; font-size: 13px; }

/* ---------- bars ---------- */
.bar { height: 6px; background: var(--bg-alt); border-radius: 999px; overflow: hidden; }
.bar--lg { height: 8px; }
.bar__fill { display: block; height: 100%; border-radius: inherit; }
.bar__fill--primary { background: var(--primary); }

/* ---------- generic rows (dashboard) ---------- */
.rows, .weaks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.row { display: flex; align-items: center; gap: 10px; padding: 9px 4px; }
.row + .row { border-top: var(--hair) solid var(--line); }
.row:hover { background: var(--bg-alt); }
.row__icon { color: var(--primary); display: inline-flex; }
.row__main { display: flex; flex-direction: column; min-width: 0; }
.row__title { font-weight: 500; }
.row__meta { font-size: 12px; color: var(--text-muted); }
.weaks { gap: 12px; }
.weak__top { display: flex; justify-content: space-between; margin-bottom: 5px; }
/* Сессия 19: ссылка «Отработать» на слабом месте (drilling этой конструкции). */
.weak__drill { display: inline-flex; align-items: center; gap: 5px; margin-top: 6px; min-height: 24px; padding: 3px 0; font-size: 13px; font-weight: 600; color: var(--primary); }
.weak__drill .ic { width: 14px; height: 14px; }
.weak__drill:hover { text-decoration: underline; }
.weak__key { font-size: 14px; }
.weak__n { font-size: 13px; color: var(--text-secondary); }

/* Плашка опроса на дашборде (Сессия 24c). #surveyMsg — live-region: держится
   отрендеренным пустым (min-height вместо display:none), иначе анонс SR
   ненадёжен (LEARNED 17.07). Кнопки-варианты переносятся на узких экранах. */
/* Вопрос обращён к пользователю — обычный регистр и основной цвет, а НЕ ярлык
   секции .h-sec (13px caps, вторичный цвет): иначе вопрос неотличим от подписей
   «Последние уроки» и теряется среди блоков дашборда. */
.survey__q { font-size: 16px; font-weight: 600; color: var(--text); }
.survey__note { margin: 2px 0 0; font-size: 13px; }
.survey__opts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* Восстановить семантику [hidden]: авторское display:flex выше побеждает
   UA-правило [hidden]{display:none}, и после ответа кнопки остались бы видимы
   (тот же приём, что у .shadow-card / .mic-note ниже). */
.survey__opts[hidden] { display: none; }
/* Рамка ghost-кнопки на --line даёт 1.35:1 — вариант в покое почти неотличим от
   карточки (1.4.11). Локально берём тот же токен, что 20e взяла для полей. */
.survey__opt { border-color: var(--input-border); }
/* Отключённое состояние обязано читаться: пока запрос в полёте, кнопка не
   должна выглядеть живой. Контраст отключённых контролов 1.4.3 не нормирует. */
.survey__opt:disabled { opacity: .55; cursor: default; }
.survey__opt:disabled:hover { background: var(--surface); }
/* Отказ — приглушённая ссылка-кнопка под вариантами. .link — inline-flex, поэтому
   ей тоже нужно вернуть семантику [hidden]; padding добирает тач-цель до 24px. */
.survey__skip { margin-top: 10px; padding: 5px 0; min-height: 24px; color: var(--text-secondary); }
.survey__skip[hidden] { display: none; }
.survey__skip:disabled { opacity: .55; cursor: default; }
.survey__msg { min-height: 1.2em; margin: 8px 0 0; font-size: 13px; }

/* ---------- lesson ---------- */
.lesson { display: grid; grid-template-columns: 280px 1fr; gap: 16px; padding: 16px 24px; align-items: stretch; max-width: 1100px; margin: 0 auto; }
/* Lock the lesson screen to the viewport (desktop two-column layout only) so
   ONLY the transcript (#feed / .stage__body) scrolls — otherwise a long
   transcript grows .stage past the viewport and the whole page (left config
   panel included) scrolls. The data-route hook is set by the router (app.js).
   On narrow screens the panel collapses behind a toggle, so normal page scroll
   is fine and the lock is skipped (it would fight the stacked grid). */
@media (min-width: 881px) {
  body[data-route="lesson"] #view { height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
  /* width:100% + max-width:none — as a flex item the `margin:0 auto` on .lesson
     otherwise disables cross-axis stretch and the grid shrinks to its content,
     so the dialog column was narrow when empty and grew with long replies.
     Pin it to the full screen width so it never reflows between states. */
  body[data-route="lesson"] .lesson { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr); width: 100%; max-width: none; }
  body[data-route="lesson"] .lesson__cfg { overflow-y: auto; }
}
.cfg-toggle { display: none; }
.lesson__cfg { border: var(--hair) solid var(--line); background: var(--surface); border-radius: 10px; padding: 16px; display: flex; flex-direction: column; gap: 18px; }
/* dimmed + non-interactive while a lesson is live (controls are read at Start) */
.lesson__cfg.cfg--locked { opacity: .45; pointer-events: none; }
/* level is read-only on the panel — shown, edited in the profile */
.lvl-info { display: flex; align-items: baseline; gap: 10px; }
.lvl-info__val { font-size: 16px; font-weight: 600; color: var(--text); }
.lvl-info__edit { font-size: 12px; }
.g { display: flex; flex-direction: column; gap: 8px; }
.g__l { font-size: 12px; text-transform: uppercase; letter-spacing: .7px; color: var(--text-secondary); }
.seg { display: flex; gap: 3px; background: var(--bg-alt); padding: 3px; border-radius: 8px; }
.seg--wrap { flex-wrap: wrap; }
.seg__b { flex: 1; border: none; background: transparent; color: var(--text-secondary); padding: 7px 8px; border-radius: 6px; font-size: 13px; font-weight: 500; }
.seg__b.on { background: var(--surface); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
/* Dark theme: track is a recessed dark (--bg-alt), so the active segment must be
   an ELEVATED fill with high-contrast text — otherwise surface≈track and the
   selected mode label merges into the panel. */
[data-theme="dark"] .seg__b.on { background: var(--surface-elevated); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.4); }
.scn-list { display: flex; flex-direction: column; gap: 6px; }
.scn { display: flex; align-items: center; gap: 9px; text-align: left; color: var(--text); border: var(--hair) solid var(--line); background: var(--surface); border-radius: 8px; padding: 9px 11px; font-size: 14px; }
.scn .ic { width: 16px; height: 16px; color: var(--text-muted); }
.scn:hover { border-color: var(--primary); }
.scn.on { border-color: var(--primary); background: var(--bg-alt); }
.scn.on .ic { color: var(--primary); }
.scn__l { font-weight: 500; }
.scn__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.scn__d { font-size: 12px; font-weight: 400; color: var(--text-muted); line-height: 1.3; }
.seg__desc { margin: 6px 0 0; font-size: 12px; color: var(--text-muted); line-height: 1.35; }
/* Пустое состояние сценариев — сфера не выбрана (Сессия 20d, вариант A). */
.scn-empty { margin-top: 8px; border: var(--hair) solid var(--line); border-radius: 8px; padding: 12px; background: var(--bg-alt); }
.scn-empty__t { margin: 0 0 10px; font-size: 13px; color: var(--text-secondary); line-height: 1.4; }
.scn-empty__grid { display: flex; flex-wrap: wrap; gap: 8px; }
.scn-sphere { flex: 1 1 auto; min-height: 44px; padding: 10px 14px; border: var(--hair) solid var(--line); border-radius: 8px; background: var(--surface); color: var(--text); font-size: 14px; font-weight: 500; cursor: pointer; }
.scn-sphere:hover { border-color: var(--primary); }
.scn-sphere:disabled { opacity: .55; cursor: default; }
.scn-empty .auth-err.sm { margin: 8px 0 0; font-size: 12px; }
/* Раскрывашка «сценарий из другой сферы (только этот урок)». */
.scn-more { margin-top: 8px; }
.scn-more__sum { list-style: none; min-height: 24px; display: inline-flex; align-items: center; padding: 5px 0; font-size: 13px; font-weight: 500; color: var(--primary); cursor: pointer; }
.scn-more__sum::-webkit-details-marker { display: none; }
.scn-more__sum::before { content: '▸'; margin-right: 6px; font-size: 11px; transition: transform 120ms ease; }
.scn-more[open] .scn-more__sum::before { transform: rotate(90deg); }
.scn-list--more { margin-top: 8px; }
@media (prefers-reduced-motion: reduce) { .scn-more__sum::before { transition: none; } }
.range { width: 100%; accent-color: var(--primary); }
.range__sc { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-muted); }

.stage { border: var(--hair) solid var(--line); background: var(--surface); border-radius: 10px; padding: 18px; display: flex; flex-direction: column; min-height: 0; }
/* live transcript area: scrollable column of .turn cards during a lesson */
/* scrollbar-gutter: keep the text width identical whether the scrollbar is
   shown (long lesson) or not (before start / short lesson) — otherwise the
   column visibly narrows once it starts scrolling. */
.stage__body { flex: 1; min-height: 0; overflow-y: auto; scrollbar-gutter: stable; display: flex; flex-direction: column; gap: 8px; }
.stage__hint { color: var(--text-muted); font-size: 15px; text-align: center; margin: 0 0 12px; }
/* Карточки-цели над сценой: Shadowing (Сессия 15) + Drilling (Сессия 16) — общий стиль. */
.shadow-card, .drill-card { border: var(--hair) solid var(--primary); background: var(--bg-alt); border-radius: 8px; padding: 12px 14px; margin-bottom: 12px; flex: none; }
.shadow-card[hidden], .drill-card[hidden] { display: none; }
.shadow-card__top, .drill-card__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.shadow-card__badge, .drill-card__badge { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--primary); }
.shadow-card__cnt, .drill-card__cnt { font-size: 12px; color: var(--text-muted); }
.shadow-card__phrase, .drill-card__focus { margin: 0; font-size: 16px; font-weight: 600; color: var(--text); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.stage__bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: var(--hair) solid var(--line); padding-top: 14px; }
.ctrls { display: flex; gap: 10px; }
.ctrls .btn { min-width: 120px; }

@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
}

/* ---------- loading / error state ---------- */
.loading { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 56px 0; text-align: center; }
.loading p { margin: 0; }
.loading__pulse { width: 14px; height: 14px; border-radius: 50%; background: var(--primary); animation: pulse 1100ms ease-in-out infinite; }
@keyframes pulse { 0%, 100% { transform: scale(.7); opacity: .45; } 50% { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .loading__pulse { animation: none; opacity: .8; } }

/* ---------- summary (test-report) ---------- */
.trows { display: flex; flex-direction: column; }
.trow { display: flex; align-items: center; justify-content: space-between; padding: 11px 0; }
.trow + .trow { border-top: var(--hair) solid var(--line); }
.trow__t { font-size: 14px; }
.pill--neutral { background: var(--neutral-bg); color: var(--neutral-text); }

/* ---------- lesson progress block (Сессия 18) ---------- */
/* Темп замечаний урока против прошлых. Цвет числа/стрелки — подкрепление к словам
   (меньше/больше/чисто), не единственный носитель смысла (WCAG 1.4.1). */
.prog { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.prog__rate { font-size: 30px; font-weight: 600; line-height: 1; color: var(--text); }
.prog__unit { font-family: var(--font-primary); font-size: 13px; font-weight: 400; color: var(--text-secondary); }
.prog__cmp { display: flex; align-items: center; gap: 6px; font-size: 14px; color: var(--text-secondary); }
.prog__arr { font-weight: 700; }
.prog.is-better .prog__rate, .prog.is-better .prog__arr { color: var(--success-text); }
.prog.is-worse .prog__rate, .prog.is-worse .prog__arr { color: var(--hint-text); }
.prog.is-flat .prog__arr { color: var(--text-muted); }

/* ---------- new-words chips (Сессия 18-B) ---------- */
.vchips { display: flex; flex-wrap: wrap; gap: 8px; }
.vchip { font-family: var(--font-mono); font-size: 13px; padding: 5px 12px; border-radius: 999px; background: var(--bg-alt); color: var(--text); border: var(--hair) solid var(--line); }
.vocab__total { margin-top: 10px; }

/* ---------- review (code-review diff) ---------- */
.diff { border: var(--hair) solid var(--line); border-radius: 10px; overflow: hidden; background: var(--surface); }
.diff + .diff { margin-top: 2px; }
.diff--good { border-color: var(--success-border); }
.diff__head { display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border-bottom: var(--hair) solid var(--line); background: var(--bg-alt); }
.diff__rep { font-size: 12px; color: var(--text-secondary); }
.rule { font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: #fff; padding: 2px 9px; border-radius: 5px; }
/* Dark: severity fills (--error-text etc) are light → white text fails AA.
   Use the dark surface colour for the label text instead. */
[data-theme="dark"] .rule { color: var(--surface); }
.diff__l { display: flex; gap: 10px; padding: 8px 12px; align-items: baseline; }
.diff__l code { font-size: 13px; white-space: pre-wrap; word-break: break-word; }
.diff__s { font-weight: 700; opacity: .7; }
.diff__l--minus { background: var(--error-bg); color: var(--error-text); }
.diff__l--plus { background: var(--success-bg); color: var(--success-text); }
.diff__note { display: flex; gap: 10px; padding: 11px 12px; border-top: var(--hair) solid var(--line); }
.diff__note p { margin: 0; font-size: 14px; color: var(--text-secondary); }
.lora { color: var(--primary); }

/* avatars */
.ava { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; flex: none; border-radius: 50%; font-size: 12px; font-weight: 600; }
.ava--lora { background: var(--bg-alt); color: var(--primary); border: var(--hair) solid var(--line); }
.ava--user { background: var(--bg-alt); color: var(--cta); border: var(--hair) solid var(--line); }
.ava--big { width: 44px; height: 44px; font-size: 16px; background: var(--bg-alt); color: var(--primary); }

/* ---------- history ---------- */
.fchips { display: flex; flex-wrap: wrap; gap: 8px; }
.fchip { border: var(--hair) solid var(--line); background: var(--surface); color: var(--text-secondary); border-radius: 999px; padding: 6px 14px; font-size: 13px; }
.fchip.on { background: var(--primary); color: #fff; border-color: var(--primary); }
.fchip:hover:not(.on) { border-color: var(--primary); }
.hrows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.hrow { display: flex; align-items: center; justify-content: space-between; gap: 12px; border: var(--hair) solid var(--line); background: var(--surface); border-radius: 10px; padding: 13px 16px; }
.hrow:hover { border-color: var(--primary); }
.hrow__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hrow__title { font-weight: 500; }
.hrow__lv { color: var(--text-muted); font-size: 12px; }
.hrow__meta { font-size: 12px; color: var(--text-muted); }
.more { text-align: center; font-size: 13px; }

/* ---------- errors ---------- */
.ecards { display: flex; flex-direction: column; gap: 12px; }
.ecard { border: var(--hair) solid var(--line); background: var(--surface); border-radius: 10px; padding: 14px; }
.ecard__top { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; }
.ecard__key { font-size: 15px; font-weight: 600; }
.ecard__sp { flex: 1; }
.ecard__n { font-size: 13px; color: var(--text-secondary); }
.d--good { color: var(--success-text); }
.d--bad { color: var(--error-text); }
.ecard__exp { margin: 9px 0 0; font-size: 14px; color: var(--text-secondary); }
.ecard__act { margin-top: 12px; }

/* ---------- transcript (IT-like, same language as the review diff) ---------- */
.chatlog { display: flex; flex-direction: column; gap: 8px; }
/* flex-shrink:0 — inside the live transcript (.stage__body is a flex column)
   cards must keep their natural height and let the column scroll; without this
   they compress and .turn's overflow:hidden clips the text. */
.turn { border: var(--hair) solid var(--line); border-radius: 8px; background: var(--surface); overflow: hidden; flex-shrink: 0; }
.turn__head { padding: 7px 12px; border-bottom: var(--hair) solid var(--line); background: var(--bg-alt); }
.turn__who { font-size: 11px; font-weight: 600; }
.turn--lora .turn__who { color: var(--primary); }
.turn--user .turn__who { color: var(--cta); }
.turn__text { margin: 0; padding: 10px 12px; font-size: 14px; }

/* ---------- profile ---------- */
.acc { display: flex; align-items: center; gap: 14px; }
.acc__id { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.acc__id b { font-size: 17px; }
.acc__id span { font-size: 13px; }
/* flex-wrap: на узких экранах (≤~360px) длинный select переносится под подпись,
   а не вылезает за край (1.4.10 Reflow) — поймано reflow_audit 18.07. */
.frow { display: flex; align-items: center; justify-content: space-between; gap: 8px 16px; padding: 11px 0; flex-wrap: wrap; }
.frow + .frow { border-top: var(--hair) solid var(--line); }
.frow__v { color: var(--primary); font-size: 14px; }
.sel { font: inherit; font-size: 14px; padding: 6px 34px 6px 10px; border: var(--hair) solid var(--input-border); border-radius: 8px; background: var(--surface); color: var(--text);
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; }
.sel:hover { border-color: var(--primary); }

/* ---------- auth screens (Phase 5.2) ---------- */
/* no-nav layout: auth screens have no left rail / bottom bar, full width */
body.no-nav { padding-left: 0; padding-bottom: 0; }
.auth { min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.auth-card { width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: 16px; }
.auth-card--center { text-align: center; align-items: center; }
.auth-head { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
.auth-head--center { align-items: center; text-align: center; }
.auth-head .brand-logo { margin-bottom: 10px; }
.auth-h { font-size: 26px; font-weight: 700; letter-spacing: -.4px; }
.auth-form { display: flex; flex-direction: column; gap: 12px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field__l { font-size: 13px; font-weight: 500; color: var(--text-secondary); }
.input {
  font: inherit; font-size: 15px; width: 100%; padding: 11px 13px;
  border: var(--hair) solid var(--input-border); border-radius: 8px;
  background: var(--surface); color: var(--text);
}
.input::placeholder { color: var(--text-muted); }
/* Поле ввода кода (Сессия 20e): крупные моно-цифры, разрядка, по центру. */
.code-input { text-align: center; font-size: 24px; letter-spacing: .4em; padding-right: 13px; font-variant-numeric: tabular-nums; }
/* Опциональная подпись поля («по желанию»). */
.field__l .opt { color: var(--text-muted); font-weight: 400; }
/* Honeypot против ботов — вне экрана и вне таб-порядка (см. #ctHp). */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
textarea.input { resize: vertical; min-height: 88px; line-height: 1.5; }
.input:hover { border-color: var(--primary); }
.input:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; border-color: var(--primary); }
.auth-err { color: var(--error-text); font-size: 13px; min-height: 18px; }
.auth-alt { align-self: center; }
.auth-foot { font-size: 14px; text-align: center; margin: 0; }
.auth-foot .link { font-size: 14px; }
.auth-consent { font-size: 13px; text-align: center; line-height: 1.5; margin: 0; }
.auth-consent .link { font-size: 13px; }
.auth-svc-toggle { align-self: center; color: var(--text-muted); font-weight: 400; margin-top: 8px; }
.auth-svc { border-top: var(--hair) solid var(--line); padding-top: 14px; margin-top: 2px; }
.auth-icon { display: inline-flex; width: 44px; height: 44px; align-items: center; justify-content: center; border-radius: 50%; background: var(--bg-alt); color: var(--primary); }
.auth-icon .ic { width: 24px; height: 24px; }
.auth-icon--warn { color: var(--error-text); background: var(--error-bg); }

/* ---------- onboarding: «как это работает» strip (dashboard, 0 lessons) ---------- */
.how { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.how__s { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; text-align: center; }
.how__ic { display: inline-flex; width: 36px; height: 36px; align-items: center; justify-content: center; border-radius: 9px; background: var(--bg-alt); color: var(--primary); }
.how__ic .ic { width: 20px; height: 20px; }
.how__t { font-size: 13px; font-weight: 500; }
.how__arr { color: var(--text-muted); flex: none; font-size: 16px; }

/* ---------- onboarding: mic-permission note (lesson, first start) ---------- */
.mic-note { display: flex; align-items: center; gap: 8px; justify-content: center; font-size: 13px; color: var(--text-secondary); background: var(--bg-alt); border: var(--hair) solid var(--line); border-radius: 8px; padding: 9px 12px; margin-bottom: 12px; }
/* The `hidden` attribute (set in JS once the lesson starts) was overridden by the
   author `display:flex` above, so the hint stayed visible over the transcript.
   Restore [hidden] semantics so it disappears once the mic is on. */
.mic-note[hidden] { display: none; }
.mic-note .ic { width: 16px; height: 16px; flex: none; color: var(--cta); }

/* ---------- live mic/voice level meter (Сессия 17c, H1) ---------- */
/* Живой индикатор уровня: 5 полос, высоту задаёт JS (viz) из analyser, цвет — по
   состоянию (слушаю = petrol, Лора говорит = amber, пауза = muted). Декоративен
   (aria-hidden), статус озвучивает #lessonStatus. */
.mic-meter { display: flex; align-items: flex-end; justify-content: center; gap: 4px; height: 26px; margin: 0 0 10px; }
.mic-meter[hidden] { display: none; }
.mic-meter__bar { width: 4px; height: 100%; border-radius: 2px; background: var(--primary); transform: scaleY(0.12); transform-origin: center bottom; transition: transform 90ms linear, background-color 220ms ease; }
.mic-meter.is-lora .mic-meter__bar { background: var(--cta); }
.mic-meter.is-pause .mic-meter__bar { background: var(--text-muted); }
@media (prefers-reduced-motion: reduce) { .mic-meter__bar { transition: background-color 220ms ease; } }

/* ---------- help screen ---------- */
.help-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
.help-step { display: flex; gap: 12px; align-items: flex-start; }
.help-step__n { display: inline-flex; width: 26px; height: 26px; flex: none; align-items: center; justify-content: center; border-radius: 50%; background: var(--bg-alt); color: var(--primary); font-size: 13px; font-weight: 600; }
.help-step__b b { font-size: 15px; }
.help-step__b p { margin: 3px 0 0; }

/* ---------- password field with show/hide eye ---------- */
.pw-wrap { position: relative; display: flex; }
.pw-wrap .input { flex: 1; padding-right: 44px; }
.pw-eye { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border: none; background: transparent; color: var(--text-muted); border-radius: 6px; }
.pw-eye:hover { color: var(--text); }
.pw-eye .ic { width: 18px; height: 18px; }

/* ---------- гид первого урока (Сессия 20e) ---------- */
/* Оверлей ловит клики (модально), затемнение рисует box-shadow подсветки. */
.guide { position: fixed; inset: 0; z-index: 1000; }
/* Лок скролла фона на время гида: подсветка .guide__spot — position:fixed и не
   слушает scroll, поэтому прокрутка увела бы её от цели. */
body.guide-open { overflow: hidden; }
.guide__spot { position: fixed; border-radius: 10px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(15, 23, 42, .62); transition: top .2s ease, left .2s ease, width .2s ease, height .2s ease; }
.guide__card { position: fixed; width: min(320px, calc(100vw - 24px));
  background: var(--surface); border: var(--hair) solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-lg); padding: 16px 18px; z-index: 1001; }
.guide__step { font-size: 12px; color: var(--text-muted); margin: 0 0 4px; }
.guide__t { font-size: 17px; font-weight: 700; margin: 0 0 6px; }
.guide__b { font-size: 14px; color: var(--text-secondary); line-height: 1.5; margin: 0 0 14px; }
.guide__nav { display: flex; align-items: center; gap: 8px; }
.guide__sp { flex: 1; }
.guide__skip { color: var(--text-muted); font-size: 13px; }
@media (prefers-reduced-motion: reduce) { .guide__spot, .cfg-toggle__chev { transition: none; } }
/* set-password (profile): stacked new + confirm fields */
.pw-fields { display: flex; flex-direction: column; gap: 10px; margin-bottom: 4px; }

/* ---------- responsive ---------- */
@media (max-width: 880px) {
  .lesson { grid-template-columns: 1fr; }
  /* Тоггл настроек (Сессия 20e-fix): disclosure-affordance — слева подпись + строка
     текущего выбора, справа шеврон (▾ закрыт / ▴ открыт). Раньше центрированный текст
     без сигнала читался как заголовок; шеврон-вверх при открытом = «сверни для Start». */
  .cfg-toggle { display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 14px; border: var(--hair) solid var(--line); background: var(--surface); border-radius: 8px; text-align: left; box-shadow: var(--shadow-sm); }
  .cfg-toggle:hover { border-color: var(--primary); }
  .cfg-toggle__l { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
  .cfg-toggle__ttl { font-weight: 700; font-size: 14.5px; color: var(--text); }
  .cfg-toggle__sum { font-size: 12.5px; font-weight: 500; color: var(--text-muted); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cfg-toggle__chev { display: inline-flex; width: 20px; height: 20px; color: var(--text-secondary); transition: transform .2s ease; flex: none; }
  .cfg-toggle__chev .ic { width: 20px; height: 20px; }
  .cfg-toggle[aria-expanded="true"] .cfg-toggle__chev { transform: rotate(180deg); color: var(--primary); }
  .lesson__cfg { display: none; position: static; }
  .lesson__cfg.open { display: flex; }
  /* Открытая панель скроллится ВНУТРИ себя (длинный список сценариев), а не выталкивает
     Start за запертый вьюпорт. Панель действий закреплена снизу (fixed) — Start виден
     ВСЕГДА, открыты настройки или нет; критично, т.к. гид первого урока сам раскрывает панель. */
  body[data-route="lesson"] .lesson__cfg.open { max-height: calc(100dvh - 140px); overflow-y: auto; }
  body[data-route="lesson"] .stage { padding-bottom: 84px; }
  body[data-route="lesson"] .stage__bar {
    position: fixed; left: 0; right: 0; bottom: 0; margin: 0;
    flex-direction: row; flex-wrap: wrap; gap: 8px;
    border-top: var(--hair) solid var(--line);
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom)); z-index: 20;
  }
  body[data-route="lesson"] .stage__bar .ctrls { flex: 1 1 auto; }
  body[data-route="lesson"] #hintBtn { flex: 0 0 auto; }
  /* #4 — на мобильном тоже запираем урок во вьюпорт: скроллится только лента
     (#feed / .stage__body), поэтому панель действий (управление + «Подсказка»)
     закреплена снизу и не уезжает за экран при длинном разговоре. Урок —
     фокус-режим, нижние табы прячем ради места (на дашборд ведёт ссылка в шапке). */
  body[data-route="lesson"] { padding-bottom: 0; }
  body[data-route="lesson"] #tabbar { display: none; }
  body[data-route="lesson"] #view { height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
  body[data-route="lesson"] .lesson { flex: 1; min-height: 0; grid-template-rows: auto auto minmax(0, 1fr); }
  body[data-route="lesson"] .stage { min-height: 0; }
}
@media (max-width: 680px) {
  .cols-2, .metrics-3, .actions-2 { grid-template-columns: 1fr; }
  .appbar { padding: 12px 16px; gap: 8px; }
  /* Разгрузка шапки на мобиле: чип имени (ссылка на профиль) убран — Профиль уже
     в нижнем таб-баре, а на 360–390 он сплющивался в пустую пилюлю. Streak-чип остаётся. */
  .appbar a.chip { display: none; }
  .wrap, .lesson { padding: 16px; }
  .h-hero { font-size: 27px; }
  .h-screen { font-size: 23px; }
  .ctrls { flex: 1; }
  .ctrls .btn { flex: 1; min-width: 0; }
  .stage__bar { flex-direction: column-reverse; align-items: stretch; }
  /* nav → bottom tab bar */
  body { padding-left: 0; padding-bottom: 66px; }
  .tabbar { flex-direction: row; top: auto; right: 0; width: auto; gap: 0; border-right: none; border-top: var(--hair) solid var(--line); padding: 6px 4px; padding-bottom: calc(6px + env(safe-area-inset-bottom)); }
  .tab { flex: 1; }
}

/* ── Тарифы / оплата (pricing, pay-success, pay-fail) ──────────────────── */
.tcards { display: grid; gap: 12px; margin: 14px 0; }
@media (min-width: 560px) { .tcards { grid-template-columns: 1fr 1fr; } }
.tcard { background: var(--surface); border: var(--hair) solid var(--line); border-radius: 12px; padding: 18px; display: flex; flex-direction: column; gap: 10px; }
.tcard--on { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary) inset; }
.tcard__name { margin: 0; font-size: 16px; }
.tcard__price { font-size: 26px; font-weight: 700; }
.tcard__feats { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; }
.tcard__feats li { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.tcard__feats .ic { color: var(--primary); }
.quota__plan { margin: 8px 0 0; font-size: 12px; }
.quota__plan .ic { width: 14px; height: 14px; vertical-align: -2px; }
.pay-result { display: flex; flex-direction: column; gap: 14px; padding-top: 28px; text-align: center; }
.pay-result .ic { width: 44px; height: 44px; margin: 0 auto; }
.pay-result .ic--ok { color: var(--success-text); }
.pay-result .ic--warn { color: var(--error-text); }
