﻿/* ============================================================================
   ВИЗУАЛЬНЫЙ ЯЗЫК, 24.07.2026 — «выразительная плотность на тёмной основе».
   Не минимализм: плотная сетка, крупный контрастный акцент на главном действии,
   цвет и размер работают как навигация.
   Три правила, которые здесь зашиты и которые нельзя откатывать поштучно:
   1. Тёмная база НЕ чёрная. #100B18, а не #000: чистый чёрный на OLED мажется
      при скролле (смазывание пикселей на переходе), и весь фиолетовый слой
      продукта на нём выглядит грязным.
   2. Глубина — осветлением поверхности (--bg-0..--bg-4), а НЕ свечением.
      Цветных box-shadow-ореолов в файле больше нет, только честные тени --sh-1/--sh-2.
   3. Акценты приглушённые. Ярко-брендовый --brand допущен максимум на один-два
      элемента экрана; основная «розовая» роль отдана приглушённому --accent.
   Скруглений нет нигде (требование проекта, только 90°) — глубина берётся
   размером блока, заливкой и обводкой.
   ============================================================================ */
:root{
  /* Поверхности: пять ступеней от фона страницы до приподнятого элемента. */
  /* redesign «engine»: ступени приподняты и чуть охлаждены (голубовато-мятный свет),
     чёрным по-прежнему не становятся (OLED), глубина всё так же осветлением. */
  --bg-0:#141220;--bg-1:#1B1730;--bg-2:#241F3C;--bg-3:#2E2A4A;--bg-4:#39345A;
  /* Границы — светом, а не отдельным фиолетовым цветом: одна обводка ложится
     на любую из пяти поверхностей и всегда читается одинаково. */
  --line:rgba(174,222,236,.11);--line-strong:rgba(184,226,236,.18);
  --ink:#F6F1FA;--mut:#C6B7D7;--dim:#A594C0;
  --accent:#F0A8CC;--accent2:#F3D9AC;--good:#7FE8C9;--err:#F0879B;--brand:#FF4D9D;
  /* Слои строки песни. Спетое гасится, но НЕ ниже 50% яркости — ниже уходит
     за норму доступности; неактивная строка 60%. */
  --lyr-active:#FFFFFF;--lyr-idle:rgba(246,241,250,.60);--lyr-past:rgba(246,241,250,.50);
  /* Роли ЧЕТЫРЁХ слоёв строки песни (Сармат 25.07 — ярче и контрастнее, k-pop-сочно).
     База = свой цвет; заливка = ТОТ ЖЕ цвет темнее. Все восемь проверены ≥4.5:1 на #100B18
     и #17101F (scripts contrast: base 9–12:1, fill 5–7.6:1). Четыре различимых тона:
     фиолет / янтарь / циан / мята. Цвет метки-тумблера = цвет яруса в тексте (совпадают). */
  --lyr-k:#C6A5FF;--lyr-k-fill:#9A6BF0;   /* хангыль: фиолет → глубже */
  --lyr-r:#FF93C4;--lyr-r-fill:#D14E93;   /* транскрипция (ведущая, по ней поют): роза → маджента.
                                             Роза темнеет чисто (не в бурый, как янтарь); отрыв
                                             базы от заливки 1.96x (у янтаря был 1.59) — спетое слово
                                             читается явно. База 9.04:1, заливка 4.62:1 на #17101F. */
  --lyr-m:#5CC8F5;--lyr-m-fill:#2E97CC;   /* перевод слов: циан → глубже */
  --lyr-s:#5FE6A4;--lyr-s-fill:#23A874;   /* смысл строки: мята → глубже */
  --s1:4px;--s2:8px;--s3:12px;--s4:16px;--s5:24px;--s6:32px;--s7:48px;--tap:48px;
  --sh-1:0 1px 2px rgba(0,0,0,.55);--sh-2:0 6px 16px rgba(0,0,0,.60);
  --glow-accent:0 0 24px rgba(240,168,204,.22);
  --ease:cubic-bezier(.16,1,.3,1);--d-fast:140ms;--d-base:220ms;--d-slow:380ms;

  /* --- Мост на старые имена. Разметка ссылается на них в 4200 строк app.js,
     переименовывать их поштучно — это диффы, которые нечем проверить.
     Значение теперь ровно одно: токен выше. --muted/--champ/--glass/--line2
     до 24.07 вообще не были объявлены и жили только фолбэками в var(...) —
     поэтому объявляем их здесь, иначе половина файла осталась бы на старой палитре. */
  --bg:var(--bg-0);--bg2:var(--bg-1);--panel:var(--bg-2);--panel2:var(--bg-3);
  --glass:rgba(38,29,51,.66);--line2:var(--line-strong);
  --muted:#A594C0;--champ:#F3D9AC;--gold-soft:#F3D9AC;--txt:var(--ink);
  /* Заливка под белым текстом (свой пузырь в чате, выбранная опция): --brand
     под белым даёт 3.3:1, ниже нормы, поэтому у заливки свой тёмный оттенок 5.2:1. */
  --accent-fill:#B8407A;
  --gold:#D9A441;--silver:#C7CFE0;--bronze:#C98F68;
  --holo1:#F0A8CC;--holo2:#C9A9FF;--holo3:#9FD8FF;--holo4:#F3D9AC;
  --r:0px;
  /* --- redesign «engine», 26-27.07: облицовка «приборной панели». --------------
     Три добавки и ни одной новой сущности сверх них:
     1. --f-mono — ВТОРАЯ гарнитура, но системная: ни одного нового сетевого запроса
        и ни одного стороннего шрифтового домена (правило одной гарнитуры вводилось
        против четырёх ЗАГРУЖАЕМЫХ файлов, см. комментарий в index.html). Живёт только
        на технических микроподписях, числах и переключателях. Текст песни, заголовки
        и любой читаемый абзац остаются Pretendard.
     2. --gold-grad — розовое золото главной кнопки (выбор Сармата 26.07: «золотые
        кнопки оставить»). Тёмные чернила на нём дают 11:1.
     3. --rail/--wave — металлическая грань и осциллограмма, несущий мотив стиля.
        Обе рисуются градиентом и SVG в data:, без картинок и без анимации:
        правило проекта «глубина осветлением, а не свечением» не нарушено,
        цветных ореолов по-прежнему ноль. */
  --f-mono:ui-monospace,"SFMono-Regular","JetBrains Mono","Cascadia Code",Consolas,"Liberation Mono",monospace;
  --gold-grad:linear-gradient(135deg,#FBE6D2,#EDC7A2 46%,#DFA97F);
  --gold-ink:#2A1520;
  --rail:linear-gradient(90deg,transparent,var(--lyr-m) 22%,var(--lyr-k) 62%,transparent);
  --edge-hi:inset 0 1px 0 rgba(255,255,255,.06);
  --edge-hi2:inset 0 1px 0 rgba(255,255,255,.09);
  /* ШРИФТ — одна гарнитура на хангыль, кириллицу и латиницу (см. @font-face ниже
     и комментарий в index.html). Playfair, Orbitron и Unbounded сняты — их роли
     забрал тот же Pretendard весом и трекингом, сторонних шрифтовых доменов
     у продукта больше нет. Три псевдонима ниже оставлены живыми: на них ссылаются
     14 вордмарков групп в app.js и десяток заголовков, схлопывать их поштучно —
     диффы без пользы. */
  --f-ko:"Pretendard Variable","Noto Sans KR";
  --f-ui:"Pretendard Variable","Noto Sans KR",system-ui,-apple-system,"Segoe UI",sans-serif;
  --f-display:var(--f-ui);--f-serif:var(--f-ui);--f-tech:var(--f-ui);
}

/* Swipe-to-go-back: полоса прогресса при свайпе справа налево с левого края */
.swipe-bar{position:fixed;top:0;left:0;height:3px;background:linear-gradient(90deg,var(--lyr-m),var(--accent2));width:0;z-index:999;transition:width 50ms linear}
/* Кириллица и латиница — своим файлом. CDN-сабсет Pretendard содержит 92 диапазона
   и НИ ОДНОГО кириллического (проверено подсчётом), поэтому без этого объявления
   весь русский текст молча уехал бы в системный шрифт. Объявление идёт после
   подключения CDN в <head>, значит на пересечении диапазонов побеждает оно. */
@font-face{
  font-family:"Pretendard Variable";
  font-style:normal;
  font-weight:45 920;
  font-display:swap;
  src:url("/fonts/pretendard-lat-cyr.woff2") format("woff2-variations");
  unicode-range:U+0000-024F,U+0400-04FF;
}
/* Требование: никаких скруглений нигде в интерфейсе — только чёткие 90° углы.
   Круглые бейджи/аватарки/пилюли тоже переведены в квадраты. Иконки-иллюстрации наград
   (диск/комета/бриллиант) — единственное исключение, это графика трофея, а не элемент интерфейса. */
*{box-sizing:border-box;margin:0;padding:0}
html{overflow-x:hidden;-webkit-text-size-adjust:100%;text-size-adjust:100%}
/* Свет сверху, один источник: поверхность у шапки на ступень светлее фона страницы.
   Это и есть «глубина осветлением» — ни одного свечения в макете нет. */
body{background:
  linear-gradient(rgba(120,205,222,.045) 1px,transparent 1px),
  linear-gradient(90deg,rgba(120,205,222,.045) 1px,transparent 1px),
  radial-gradient(58% 42% at 5% 108%, rgba(95,230,224,.07), transparent 60%),
  radial-gradient(130% 70% at 50% -12%,var(--bg-3) 0%,var(--bg-0) 58%);
  background-size:44px 44px,44px 44px,auto,auto;
  background-attachment:fixed;
  background-color:var(--bg-0);
  color:var(--ink);font-family:var(--f-ui);font-optical-sizing:auto;font-synthesis-weight:none;
  min-height:100vh;-webkit-font-smoothing:antialiased;max-width:100vw;overflow-x:hidden;position:relative}
img,iframe,video{max-width:100%}
.wrap{max-width:1120px;margin:0 auto;padding:0 20px}
header{position:sticky;top:0;z-index:40;backdrop-filter:blur(14px);background:rgba(16,11,24,.88);border-bottom:1px solid var(--line)}
/* Снизу воздуха больше, чем сверху (правка Сармата 28.07): кнопки «Вход» и
   «Регистрация» упирались в нижний край металлической плашки — расстояния не было
   вовсе. Теперь низ плашки отстоит от кнопок примерно так же, как её верх от
   верхней точки золотого квадрата в знаке. */
.hbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;min-height:60px;padding:10px 0 16px}
/* ЗНАК БРЕНДА, вариант A, 24.07. Требование основателя: логотип-леттеринг, значок равен
   названию. Две предыдущие попытки отклонены: холо-заливка по контуру букв (AI-tell плюс
   вечная анимация) и кремовая плашка под «ingo» (читалась как текст, случайно выделенный
   маркером, и без плашки не оставалось знака).

   Здесь знак делает сама буква. В имени Idolingo шов «Idol» плюс «lingo» приходится на
   общую «l». В корейском ㄹ (риыль) — это и есть буква l/r, причём в конечной позиции
   слога она читается именно как l, то есть «Idol» = «Ido» плюс ㄹ буквально верно.
   Поэтому шовная «l» получает горизонтальный вылет-подошву, снятый с ㄹ: слово по-прежнему
   читается «Idolingo», но одна буква в нём — кастомная и корейская по происхождению.
   Это ровно механика Duolingo, где хвостик у «g» повторяет бровь маскота
   (design.duolingo.com/identity/logos).

   Иконка вкладки — целая ㄹ, отрисованная прямоугольниками в SVG (см. index.html), поэтому
   не зависит ни от какого шрифта. Замерено: различима в 16 px в цвете, в монохроме и на
   белом. Плашки нет, знак живёт в один цвет и в вывороте.

   Почему описательный, а не абстрактная первая буква: у незнакомых брендов описательный
   знак заметно повышает оценку бренда, и эффект затухает по мере узнаваемости
   [Luffarelli, Mukesh, Mahmood, Journal of Marketing Research 56(5), октябрь 2019,
   шесть исследований и разбор 597 знаков]. Idolingo сейчас не знает никто. */
.logo{font-family:var(--f-display);font-weight:900;letter-spacing:.2em;font-size:15px;
  display:inline-flex;align-items:center;color:var(--ink)}
.logo b{background:var(--accent2);color:#241436;padding:3px 7px 2px 8px;margin-left:3px;
  letter-spacing:.18em;font-weight:900}
/* AI-РАСКРЫТИЕ, правка 24.07. Была бегущая радужная плашка — самый громкий элемент
   гримёрки и вдобавок вечная анимация. Это обязательное раскрытие (КНР, «Interim
   Measures» с 15.07.2026), оно должно быть читаемым, а не праздничным. Стало:
   тихая обводка, 11px, контраст 6.6:1 — норма для нетекстовой подписи с запасом. */
.ai-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;letter-spacing:.12em;
  font-weight:600;padding:3px 7px 2px;color:var(--dim);flex:none;
  background:none;border:1px solid var(--line-strong)}
.brackets{position:relative}
.brackets i{position:absolute;width:16px;height:16px;pointer-events:none;line-height:0}
.brackets i svg{width:100%;height:100%;display:block}
.brackets .tl{top:-7px;left:-7px}
.brackets .tr{top:-7px;right:-7px;transform:scaleX(-1)}
.brackets .bl{bottom:-7px;left:-7px;transform:scaleY(-1)}
.brackets .br{bottom:-7px;right:-7px;transform:scale(-1,-1)}
/* Рама портрета. Была вечно ползущая радуга по контуру — свечение вместо глубины
   и второй бесконечный цикл на экране. Стал статичный двойной кант: тонкая
   светлая обводка плюс воздух, ровно то же «это особенный кадр», но молча. */
.holo-frame{position:relative}
.holo-frame::before{content:"";position:absolute;inset:-3px;
  border:1px solid var(--line-strong);pointer-events:none}
.navtabs{display:flex;gap:6px;margin-left:8px}
.navtab{background:var(--bg-2);border:1px solid var(--line);color:var(--mut);font:inherit;font-size:15px;font-weight:600;letter-spacing:.01em;
  padding:11px 16px;cursor:pointer;transition:color var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease),background-color var(--d-fast) var(--ease)}
.navtab:hover{color:var(--ink);background:var(--bg-4);border-color:var(--line-strong)}
/* Активная вкладка больше не светлая плашка: светлый блок на экране должен быть
   один — главное действие. Здесь состояние показано поверхностью и кантом. */
.navtab.on{background:var(--bg-4);color:var(--ink);border-color:var(--accent)}
.no-idol-btn{margin:18px auto 0;display:block}
.step-ind{margin-left:auto;display:flex;gap:8px;font-size:13px;color:var(--dim)}
.step-ind span{padding:5px 12px;border:1px solid var(--line)}
.step-ind span.on{color:var(--accent);border-color:var(--accent2)}
.auth-area{display:flex;align-items:center;gap:10px;margin-left:auto}
/* Правка Сармата 29.07: знак чуть правее к центру (1-2 мм ≈ 6px), правая группа на
   столько же левее — отступы от краёв экрана до знака и до кнопок одинаковые.
   :last-child это .auth-area; пустой у гостя, он всё равно отжимает группу от края. */
.hbar .logo{margin-left:6px}
.hbar>:last-child{margin-right:6px}
/* На узких экранах вход/регистрация переносятся на вторую строку, и крайним справа
   в первой остаётся язык — ему тот же отступ от края, что у знака слева. */
.hbar .lang-wrap{margin-right:6px}
.auth-user{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--mut)}
.auth-user b{color:var(--ink)}
.auth-form{padding:26px 28px 28px}
.auth-form h3{font-family:var(--f-serif);font-size:22px;margin-bottom:16px}
.auth-form input{width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--ink);font:inherit;font-size:16px;padding:11px 13px;margin-bottom:10px}
.auth-form input:focus{outline:none;border-color:var(--accent2)}
.pass-wrap{position:relative}
.pass-wrap input{margin-bottom:10px}
.pass-eye{position:absolute;right:6px;top:11px;background:none;border:none;font-size:20px;cursor:pointer;padding:4px 6px;line-height:1;opacity:.75}
.pass-eye:hover{opacity:1}
/* iOS не зумит поля с font-size>=16px */
.song-search,.chat-input input,#forgotEmail{font-size:16px}
.spinner.sm{width:14px;height:14px;border-width:2px;display:inline-block;vertical-align:middle}
/* TOPIK был самым громким элементом экрана уроков: золотой баннер на золотом
   фоне над списком, где фанату K-pop продают официальный экзамен.
   Позиционирование сохраняем — оно продающее, — но строкой внизу, не баннером. */
.topik-line{display:flex;gap:8px;align-items:flex-start;font-size:11px;line-height:1.45;
  color:var(--dim,#a394bd);border-top:1px solid var(--line);padding:12px 2px 4px;margin-top:18px;letter-spacing:.01em}
.topik-line b{color:var(--mut,#c7b3da);font-weight:700}
.topik-line span:first-child{opacity:.7;font-size:13px}
.auth-switch{color:var(--dim);font-size:13px;margin-top:12px;text-align:center}
.auth-switch a{color:var(--accent2);cursor:pointer;text-decoration:underline}
main{display:none}main.show{display:block}
.hero{padding:60px 0 30px;text-align:center}
.hero .eyebrow{color:var(--accent);letter-spacing:.4em;font-size:13px;font-weight:700;margin-bottom:18px}
.hero h1{font-size:clamp(34px,6vw,60px);line-height:1;font-weight:800;letter-spacing:-.02em}
.hero h1 .stroke{-webkit-text-stroke:1.3px var(--accent);color:transparent;display:block}
.hero p{max-width:520px;margin:18px auto 0;color:var(--mut);font-size:16px;line-height:1.5}
.sec{padding:34px 0 10px}
.sec-h{display:flex;align-items:baseline;gap:12px;margin-bottom:18px}
.sec-h h2{font-size:22px;font-weight:800}.sec-h .n{color:var(--accent);font-weight:800;font-size:13px;letter-spacing:.1em}
.sec-h .tag{color:var(--dim);font-size:13px;letter-spacing:.14em;text-transform:uppercase;margin-left:auto}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:14px}
.card{background:rgba(30,22,41,.62);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.08);overflow:hidden;cursor:pointer;transition:.18s;position:relative}
.card:hover{transform:translateY(-3px)}
.card.sel{outline:2px solid var(--accent);outline-offset:1px}
.card .ph{position:relative;aspect-ratio:1;overflow:hidden}
.card .ph img{width:100%;height:100%;object-fit:cover;transition:.4s}
.card:hover .ph img{transform:scale(1.05)}
.card .check{position:absolute;top:8px;right:8px;width:24px;height:24px;background:var(--accent-fill);color:#fff;
  display:none;align-items:center;justify-content:center;font-weight:800;font-size:13px}
.card.sel .check{display:flex}
.card .body{padding:10px 12px 12px}
.card .nm{display:flex;align-items:center;gap:7px}.card .nm b{font-size:15px;font-weight:800}
.card .nm .cc{width:8px;height:8px;background:var(--gold)}
.card .concept{color:var(--dim);font-size:11px;margin-top:2px}
/* personalization */
.pz{display:none}.pz.show{display:block}
.opt-h{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--mut);margin:22px 0 10px;font-weight:700}
.opts{display:flex;gap:10px;flex-wrap:wrap}
.gender-tabs{display:flex;gap:6px;margin-bottom:12px}
.gtab{background:transparent;border:1px solid var(--line);color:var(--mut);padding:7px 18px;
  font:inherit;font-size:13px;font-weight:700;cursor:pointer;transition:color .15s,border-color .15s,background-color .15s}
.gtab:hover{border-color:var(--accent2);color:var(--ink)}
.gtab.on{background:var(--accent-fill);color:#fff;border-color:var(--accent-fill)}
.opt{display:flex;align-items:center;gap:11px;text-align:left;background:var(--panel);border:1px solid var(--line);color:var(--ink);padding:9px 16px 9px 9px;cursor:pointer;
  font:inherit;font-size:15px;transition:color .15s,border-color .15s,background-color .15s;min-width:150px}
.opt:hover{border-color:var(--accent2)}
.opt.on{background:var(--accent-fill);color:#fff;font-weight:700;border-color:var(--accent-fill)}
.opt .swatch{width:34px;height:34px;display:flex;align-items:center;justify-content:center;flex:none}
.opt .txt{display:flex;flex-direction:column;line-height:1.3}
.opt small{display:block;color:var(--dim);font-size:11px;margin-top:2px}
.opt.on small{color:rgba(255,255,255,.72)}
.opt.locked{opacity:.32;filter:blur(.4px);cursor:not-allowed;pointer-events:none}
.opt.available{border-color:var(--accent2);box-shadow:0 0 0 1px var(--accent2)}
.opt.recommended{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold)}
.opt.recommended.on{background:var(--accent-fill);border-color:var(--gold);box-shadow:0 0 0 1px var(--gold)}
.rec-badge{display:inline-block;margin-left:6px;font-size:11px;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;color:var(--gold);vertical-align:middle}
.opt.on .rec-badge{color:#ffe9a8}
.empty-genre{color:var(--dim);font-size:13px;background:var(--panel);border:1px dashed var(--line);padding:22px;text-align:center;margin-top:4px}
.lang-lock{color:var(--dim);font-size:13px;background:var(--panel);border:1px dashed var(--line);padding:14px 16px;line-height:1.5}
.lang-lock b{color:var(--ink)}
.bilingual-toggle{display:flex;align-items:center;gap:10px;font-size:15px;color:var(--ink);cursor:pointer;margin-bottom:12px;user-select:none}
.bilingual-toggle input{width:16px;height:16px;accent-color:var(--accent-fill);cursor:pointer}
.lang-progress{color:var(--dim);font-size:13px;margin-top:4px}
.selrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--panel);border:1px solid var(--line);
  padding:14px;margin-bottom:8px}
.selrow .chip{display:flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);padding:6px 8px 6px 6px}
.selrow .chip img{width:38px;height:38px;object-fit:cover}
.selrow .chip b{font-size:13px}
.selrow .empty{color:var(--dim);font-size:13px}
.genbar{position:sticky;bottom:0;background:linear-gradient(transparent,var(--bg) 30%);padding:24px 0 20px;margin-top:20px}
.genbar .inner{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.summary{color:var(--mut);font-size:13px;line-height:1.5}.summary b{color:var(--ink)}
.btn{font:inherit;font-weight:700;letter-spacing:.01em;border:0;padding:15px 30px;cursor:pointer;font-size:16px;min-height:var(--tap);
  transition:transform var(--d-fast) var(--ease),box-shadow var(--d-base) var(--ease),background-color var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease),filter var(--d-fast) var(--ease)}
/* ГЛАВНОЕ ДЕЙСТВИЕ. Единственный крупный светлый блок на тёмном экране — за счёт
   этого он и работает навигацией: глаз находит его раньше, чем читает подпись.
   Тёмные чернила на светлой заливке дают 8.2:1 при норме 4.5. Бегущий блик
   («sheen») снят 24.07: движущаяся подсветка по кнопке — приём 2021 года и один
   из самых узнаваемых признаков сгенерированного интерфейса. */
.btn.accent{position:relative;background:linear-gradient(135deg,var(--accent),var(--accent2));color:#3a1a2c;box-shadow:var(--sh-2);margin-left:auto}
.btn.accent:hover{transform:translateY(-1px);filter:brightness(1.04)}
.btn.accent:active{transform:translateY(0)}
.btn.accent:disabled{opacity:.4;cursor:not-allowed;transform:none;filter:none}
.btn.ghost{background:var(--bg-3);color:var(--ink);border:1px solid var(--line)}
.btn.ghost:hover{background:var(--bg-4);border-color:var(--line-strong)}
.btn.ghost:disabled{opacity:.45;cursor:not-allowed}
.btn.sm{padding:9px 18px;font-size:13px}
.ov{position:fixed;inset:0;z-index:60;background:rgba(9,6,15,.84);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;padding:24px}
.ov.show{display:flex}
.chat-cta{width:100%;margin:10px 0 4px;font-size:16px;font-weight:700;padding:16px;letter-spacing:.01em;
  background:linear-gradient(120deg,var(--accent-fill),#c25e9a);box-shadow:var(--sh-2);}
.chat-cta:hover{filter:brightness(1.06);transform:translateY(-1px)}
.chat-cta-sub{font-size:13px;color:var(--muted,#9a8fb0);margin:0 0 14px;text-align:center}
.pick-h{font-size:clamp(20px,3.4vw,27px);font-weight:800;line-height:1.15;margin-bottom:10px;text-wrap:balance;max-width:20em}

/* ===== HOME (учи корейский с айдолом) — чистый связный экран ===== */
.home{max-width:540px;margin:0 auto;display:flex;flex-direction:column;gap:16px;padding:8px 0 40px}
.idol-hero{display:flex;gap:16px;align-items:center;background:var(--glass,rgba(52,38,78,.42));border:1px solid var(--line);padding:16px;backdrop-filter:blur(8px)}
.idol-hero .idol-ph{flex:0 0 96px;width:96px;height:120px;position:relative}
.idol-hero .idol-ph>img,.idol-hero .ph-inner img{width:100%;height:100%;object-fit:cover}
.idol-hero .ph-inner{width:100%;height:100%;overflow:hidden}
.idol-meta{flex:1;min-width:0}
.idol-name{font-size:20px;font-weight:800;display:flex;align-items:center;gap:8px}
.idol-concept{font-size:13px;color:var(--muted,#a99cc0);margin:2px 0 12px}
.lvl-top{display:flex;justify-content:space-between;align-items:baseline;font-size:13px;color:var(--muted,#a99cc0);margin-bottom:5px}
.lvl-top b{color:var(--champ,#f3d9ac);font-size:13px;font-weight:700}
/* Полоса-покрытие кликабельна: она же и вход обратно в песню, о которой говорит. */
.lvl-song{display:block;width:100%;text-align:left;background:none;border:none;padding:0;margin:0;font:inherit;cursor:pointer}
.lvl-note{font-size:11px;color:var(--mut);margin-top:5px}
.lvl-song:hover .lvl-note{color:var(--muted,#a99cc0)}
.streak-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.streak-chip{display:inline-block;font-size:13px;font-weight:600;padding:5px 11px;background:var(--panel2);border:1px solid var(--gold);color:var(--gold-soft,#f3d9ac)}
.streak-chip.alt{border-color:var(--line);color:var(--mut)}

/* ===== ГРИМЁРКА КАК ЕЁ КОМНАТА =====
   Портрет во всю ширину 4:5 вместо марки 96x100 в углу карточки: продукт называется
   «дружба с айдолом», значит айдол и есть первый экран. Всё, что мерило непройденное
   (уровни, полосы, замки), с экрана убрано. */
/* 40px пустоты между шапкой и портретом — это 5% сгиба ни на что. Сужаем только у себя,
   у гостя и в чужой карточке отступ остаётся прежним. */
.cab:has(.home){padding-top:12px}
.home{padding-top:0}
.home .idol-hero{display:block;position:relative;padding:0;overflow:hidden;background:var(--panel)}
/* Рама 1:1, а не 4:5. Исходники квадратные 640x640 и это плотные кроп-головы: любое 4:5
   срезает пятую часть кадра, и на самых близких портретах (idol4, idol5, idol12) под нож
   идёт подбородок — проверено съёмкой всех 21. При 1:1 кроп нулевой, лицо целиком у всех,
   и сгиб не съеден. Вернуть 4:5 можно только перегенерив портреты сразу в 4:5. */
.home .idol-hero .idol-ph{flex:none;width:100%;height:auto;aspect-ratio:1/1}
.home .idol-hero .ph-inner{position:absolute;inset:0;width:auto;height:auto}
/* Все 21 портрета — плотные кроп-головы 640x640: при 4:5 из кадра уходит нижняя пятая,
   поэтому кадрируем от верхней кромки, тогда лицо целиком остаётся в раме. */
.home .idol-hero img{width:100%;height:100%;object-fit:cover;object-position:50% 0%;display:block}
/* Ни одной буквы поверх лица. Имя и её реплика живут ПОД кадром, на панели карточки:
   любая шторка на такой плотной голове срезает подбородок — проверено на всех 21 портрете. */
.hero-foot{padding:13px 14px 14px;display:flex;flex-direction:column;gap:9px;background:var(--panel);text-align:left}
.hero-foot .idol-name{justify-content:flex-start}
.hero-foot .idol-concept{margin:2px 0 0}
.hero-chips{position:absolute;top:10px;left:10px;z-index:2;display:flex;flex-wrap:wrap;gap:6px;max-width:calc(100% - 74px)}
.hero-chips .streak-chip{font-size:11px;padding:6px 10px;background:rgba(16,11,24,.78);backdrop-filter:blur(6px)}

/* Её сообщение. Пузырь — тот же, что в чате (.chat-msg.idol .chat-b), чтобы это читалось
   как настоящая переписка, а не как рекламный блок. Тап по нему = ответить. */
.dm-teaser{display:block;width:100%;text-align:left;background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer}
.dm-status{display:flex;align-items:center;gap:7px;font-size:11px;font-weight:600;color:var(--mut);margin-bottom:6px}
.dm-teaser.unread .dm-status{color:var(--accent)}
.dm-teaser.unread .dm-status::before{content:"";width:8px;height:8px;flex:none;background:var(--accent);box-shadow:0 0 0 3px rgba(240,168,204,.20)}
.dm-teaser .chat-b{max-width:100%;line-height:1.4;transition:border-color .16s}
/* Обрезка ровно по трём строкам живёт на внутреннем узле без падингов: если резать сам
   пузырь, четвёртая строка подтекает в его нижний отступ (overflow режет по padding-box). */
.dm-teaser .dm-clip{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;line-clamp:3;overflow:hidden;max-height:4.2em}
.dm-teaser.unread .chat-b{border-color:var(--accent);box-shadow:var(--sh-2)}
.dm-teaser:hover .chat-b{border-color:var(--accent)}
.dm-cta{display:block;margin-top:8px;font-size:13px;font-weight:700;color:var(--accent2)}
.dm-cta:empty{display:none}
/* «Печатает…»: анимируются только opacity и transform — ни ширины, ни высоты. */
.dm-typing{display:inline-flex;align-items:center;gap:5px;height:19px}
.dm-typing i{width:6px;height:6px;background:var(--mut);opacity:.3;animation:dmdot 1.3s ease-in-out infinite}
.dm-typing i:nth-child(2){animation-delay:.16s}
.dm-typing i:nth-child(3){animation-delay:.32s}
@keyframes dmdot{0%,62%,100%{opacity:.28;transform:translateY(0)}31%{opacity:1;transform:translateY(-3px)}}

/* Контраст, правка 24.07: белый текст на розовой заливке давал 3.25:1 при норме AA 4.5.
   Взята выворотка кнопки .btn.accent (тёмные чернила на светлой заливке) — она уже
   сделана правильно и служит образцом для главного действия всего продукта. */
.lesson-cta{display:flex;align-items:center;gap:14px;width:100%;text-align:left;cursor:pointer;
  border:none;padding:var(--s5) 18px;min-height:var(--tap);color:#3a1a2c;font:inherit;
  background:linear-gradient(135deg,var(--accent),var(--accent2));box-shadow:var(--sh-2);
  transition:transform var(--d-fast) var(--ease),filter var(--d-fast) var(--ease)}
/* Главное действие стало ссылкой на отдельный экран (/learn.html), а не кнопкой
   внутри приложения. Ссылке нужно снять подчёркивание и наследование цвета — всё
   остальное оформление берётся тем же классом. */
.lesson-cta{text-decoration:none;box-sizing:border-box}
.lesson-cta:hover{filter:brightness(1.04);transform:translateY(-1px)}
.lesson-cta:active{transform:translateY(0)}
.lc-emoji{font-size:26px;flex:0 0 auto}
.lc-text{flex:1;display:flex;flex-direction:column;gap:3px;line-height:1.2}
/* Подпись главного действия — подзаголовочный кегль 20px. Размер здесь работает
   так же, как цвет: он объявляет, что на экране главное. */
.lc-text b{font-size:20px;font-weight:800;letter-spacing:-.01em}
.lc-text small{font-size:13px;font-weight:600;opacity:.82}
.lc-arrow{font-size:20px;opacity:.9}

/* Иерархия: чат — во всю ширину и крупно (единственная механика в нише, за которую
   доказанно платят), алфавит и тетрадь — узкой парой под ним. Трёх одинаковых серых
   строк по 60px больше нет. */
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.tile{display:flex;flex-direction:column;align-items:flex-start;gap:3px;cursor:pointer;font:inherit;text-align:left;
  background:var(--bg-2);border:1px solid var(--line);color:var(--ink);padding:var(--s4) var(--s3);min-height:var(--tap);
  transition:background-color var(--d-fast) var(--ease),border-color var(--d-fast) var(--ease),transform var(--d-fast) var(--ease)}
/* Отклик — осветлением поверхности на ступень, а не свечением рамки. */
.tile:hover{background:var(--bg-4);border-color:var(--line-strong);transform:translateY(-1px)}
/* Правка 24.07: чат был подсвечен ровно как «Понять песню» — тот же градиент, та же
   акцентная рамка, разница в высоте 14px. Два главных действия читались как пара
   равных, и вход в продукт терялся. Акцент снят, размер оставлен: чат остаётся
   вторым по величине, но перестаёт спорить с первым. */
.tile.lead{grid-column:1/-1;display:grid;grid-template-columns:auto 1fr;column-gap:13px;align-items:center;
  padding:17px 16px;background:var(--panel);border-color:var(--line)}
.tile.lead:hover{border-color:var(--accent)}
.tile.lead .t-emoji{grid-row:1/3;font-size:27px;margin:0}
.tile.lead b{font-size:16px;align-self:end}
.tile.lead small{font-size:13px;align-self:start;color:var(--mut)}
.t-emoji{font-size:22px;margin-bottom:4px}
.tile b{font-size:13px;font-weight:700}
.tile small{font-size:11px;color:var(--muted,#a99cc0)}

.coll{background:var(--glass,rgba(52,38,78,.42));border:1px solid var(--line);padding:16px;backdrop-filter:blur(8px)}
.coll-h{font-size:13px;font-weight:700;letter-spacing:.02em;margin-bottom:10px;display:flex;gap:8px}
.coll-h span{color:var(--champ,#f3d9ac)}
.coll-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.coll-grid img{width:100%;aspect-ratio:3/4;object-fit:cover;border:1px solid var(--line);opacity:.9;cursor:pointer;transition:.16s}
.coll-grid img:hover{opacity:1;transform:scale(1.05);border-color:var(--champ,#f3d9ac);box-shadow:var(--sh-2)}
.card-locked{width:100%;aspect-ratio:3/4;border:1px dashed var(--line);display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,rgba(48,36,66,.55),rgba(23,16,31,.80));position:relative;overflow:hidden}
.card-locked::before{content:"";position:absolute;inset:0;z-index:1;background:repeating-linear-gradient(45deg,transparent,transparent 6px,rgba(243,217,172,.05) 6px,rgba(243,217,172,.05) 12px)}
.card-locked .cl-lock{font-size:20px;opacity:.5;filter:grayscale(1)}
/* Закрытая карточка — размытый кадр, а не замок: интрига «что там», а не «тебе нельзя». */
.card-locked img{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;border:none;opacity:.42;
  object-fit:cover;filter:blur(9px) saturate(.55);transform:scale(1.25);cursor:default}
.coll-note{font-size:11px;color:var(--dim,#a394bd);margin-top:10px}

.bio-box{border:1px solid var(--line);background:var(--panel)}
.bio-box summary{cursor:pointer;padding:12px 14px;font-size:13px;font-weight:600;color:var(--muted,#a99cc0);list-style:none}
.bio-box summary::-webkit-details-marker{display:none}
.bio-box summary::after{content:"＋";float:right;color:var(--champ,#f3d9ac)}
.bio-box[open] summary::after{content:"－"}
.bio-box .bio-text{width:100%;min-height:80px;background:var(--panel2);border:none;border-top:1px solid var(--line);color:var(--ink);font:inherit;font-size:13px;padding:12px 14px;resize:vertical}
.bio-box .bio-text:focus{outline:none}
.sub-link{width:100%;cursor:pointer;font:inherit;font-size:13px;color:var(--champ,#f3d9ac);background:transparent;border:1px dashed var(--line2,#54426f);padding:13px}
.sub-link:hover{border-color:var(--champ,#f3d9ac)}
/* Правка 24.07: золотая рамка делала подключение мессенджера самым ярким элементом
   экрана — то есть громче всего кричал наименее важный пункт. Золото на этом экране
   осталось только у серии («N дней подряд»), где оно и значит достижение. */
.connect-link{width:100%;cursor:pointer;font:inherit;font-size:13px;font-weight:600;color:var(--mut,#c7b3da);background:none;border:1px solid var(--line);padding:13px;margin-bottom:9px;transition:border-color .14s,color .14s}
.connect-link:hover{border-color:var(--accent2);color:var(--ink)}
/* PREMIUM. Строка повторяет .connect-link ровно потому, что это тоже настройка аккаунта,
   а не баннер: рядом стоящие строки одного веса не спорят за внимание. Активная подписка
   красится в зелёный статуса (как привязанный канал .connect-link.done) и перестаёт
   выглядеть кнопкой — покупать больше нечего. */
.premium-link{width:100%;cursor:pointer;font:inherit;font-size:13px;font-weight:600;color:var(--mut,#c7b3da);background:none;border:1px solid var(--line);padding:13px;margin-bottom:9px;transition:border-color .14s,color .14s}
.premium-link:hover{border-color:var(--accent2);color:var(--ink)}
.premium-link.on{color:var(--good,#7fe8c9);border-color:rgba(127,232,201,.35);cursor:default}
.prem-perks{list-style:none;padding:0;margin:12px 0 16px;display:flex;flex-direction:column;gap:8px}
.prem-perks li{font-size:14px;line-height:1.4;color:var(--ink);padding-left:22px;position:relative}
.prem-perks li::before{content:"✓";position:absolute;left:0;color:var(--good,#7fe8c9)}
.prem-price{font-size:22px;font-weight:700;color:var(--champ,#f3d9ac);margin-bottom:14px}
.prem-until{font-size:15px;color:var(--good,#7fe8c9);margin:8px 0 2px}
/* Главная кнопка шторки — единственная золотая вещь здесь. 48px по высоте: тап-цель. */
.prem-go{width:100%;min-height:48px;cursor:pointer;font:inherit;font-size:15px;font-weight:700;color:#1a1226;background:var(--champ,#f3d9ac);border:none;padding:14px;transition:opacity .14s}
.prem-go:hover{opacity:.9}
.prem-go:disabled{opacity:.6;cursor:default}
/* Карта — второй вход в ту же кассу, а не второе предложение: тот же размер и та же
   тап-цель, но контуром, чтобы главной осталась одна кнопка. */
.prem-go-card{margin-top:14px;color:var(--ink);background:none;border:1px solid var(--line)}
.prem-go-card:hover{opacity:1;border-color:var(--mut,#c7b3da)}
/* Предупреждение про чужую медленную страницу: заметнее обычной подписи, но не
   тревога — это ожидаемое поведение, а не поломка. */
.prem-slow{color:var(--ink);border-left:2px solid var(--champ,#f3d9ac);padding-left:10px;margin-bottom:12px}
/* Отключение продления — не выход из продукта, поэтому не красное и не главное. */
.prem-cancel{width:100%;min-height:44px;cursor:pointer;font:inherit;font-size:13px;color:var(--muted,#a99cc0);background:none;border:1px solid var(--line);padding:12px;margin-top:16px;transition:border-color .14s,color .14s}
.prem-cancel:hover{border-color:var(--mut,#c7b3da);color:var(--ink)}
.prem-cancel:disabled{opacity:.6;cursor:default}
.prem-note{font-size:12px;line-height:1.45;color:var(--muted,#a99cc0);margin-top:10px}
.prem-wait{font-size:14px;color:var(--muted,#a99cc0);padding:14px 0}
/* Подсказка про цену звезды. Свёрнута, чтобы не удлинять покупку: кто считает деньги —
   раскроет, остальные пройдут мимо. Тап-цель 44px даже в свёрнутом виде. */
.prem-cheap{margin-top:14px;border-top:1px solid var(--line);padding-top:10px}
.prem-cheap summary{cursor:pointer;font-size:13px;color:var(--mut,#c7b3da);padding:9px 0;min-height:44px;display:flex;align-items:center;list-style:none}
.prem-cheap summary::-webkit-details-marker{display:none}
.prem-cheap summary::after{content:"›";margin-left:auto;transition:transform var(--d-fast,.14s)}
.prem-cheap[open] summary::after{transform:rotate(90deg)}
.prem-cheap-b{font-size:12px;line-height:1.5;color:var(--muted,#a99cc0);padding-bottom:6px}
.prem-cheap-b a{color:var(--champ,#f3d9ac)}
.prem-hist-title{font-size:14px;font-weight:700;color:var(--ink);margin-bottom:12px}
.prem-hist-list{display:flex;flex-direction:column;gap:10px}
.prem-hist-row{display:grid;grid-template-columns:70px 1fr 70px 80px;gap:12px;align-items:center;font-size:13px;padding:10px;background:var(--panel2);border-radius:4px}
.prem-hist-date{color:var(--muted,#a99cc0);font-size:12px}
.prem-hist-info{display:flex;flex-direction:column;gap:2px}
.prem-hist-source{color:var(--ink);font-weight:500}
.prem-hist-method{color:var(--muted,#a99cc0);font-size:11px}
.prem-hist-status{font-size:11px;font-weight:600;padding:3px 8px;border-radius:3px;text-align:center}
.prem-hist-completed{background:var(--good,#7fe8c9);color:rgba(0,0,0,.7)}
.prem-hist-failed{background:#e24545;color:white}
.prem-hist-pending{background:var(--champ,#f3d9ac);color:rgba(0,0,0,.7)}
.prem-hist-refunded{background:var(--muted,#a99cc0);color:var(--paper)}
.prem-hist-amount{text-align:right;color:var(--champ,#f3d9ac);font-weight:700;display:flex;flex-direction:column;gap:4px;align-items:flex-end}
.prem-hist-badge{display:inline-block;background:var(--gold);color:#1a1226;font-size:9px;font-weight:700;padding:2px 5px;border-radius:2px}
.prem-hist-empty{font-size:13px;color:var(--muted,#a99cc0);text-align:center;padding:24px 0}
.connect-sub{font-size:13px;line-height:1.45;color:var(--muted,#a99cc0);margin:6px 0 14px}
.connect-rows{display:flex;flex-direction:column;gap:9px}
.connect-row{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;cursor:pointer;font:inherit;background:var(--panel2);border:1px solid var(--line);padding:12px 14px;position:relative}
.connect-row:hover{border-color:var(--gold)}
.connect-row .cr-ic{font-size:20px;position:absolute;right:14px;top:12px}
.connect-row b{font-size:15px;color:var(--ink)}
.connect-row small{font-size:11px;color:var(--muted,#a99cc0)}
.connect-row.sm{padding:9px 12px;opacity:.82}
.connect-row.sm b{font-size:13px}
.connect-row.sm .cr-ic{font-size:16px;top:10px}
.connect-other{margin:12px 0 6px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted,#a99cc0);text-align:center}
.connect-done{margin-top:14px;font-size:13px;color:var(--good);font-weight:600}
.connect-err{margin-top:12px;font-size:13px;color:var(--err)}
.connect-loading{margin-top:12px;font-size:20px;text-align:center;color:var(--gold)}
.connect-code-box{margin-top:16px;text-align:center}
.ccb-step{font-size:13px;color:var(--muted,#a99cc0);line-height:1.4;margin:8px 0}
.ccb-code{font-family:var(--f-tech,monospace);font-size:30px;font-weight:700;letter-spacing:.24em;color:var(--gold);padding:12px;border:1px dashed var(--gold);background:rgba(217,164,65,.06);margin:6px auto;display:inline-block}
/* Telegram: привязка одним тапом — deep-link вместо ручного кода. */
.ccb-link{display:inline-block;margin:8px auto;padding:12px 22px;background:var(--gold);color:#1a1420;font-weight:700;font-size:15px;text-decoration:none}
.ccb-link:hover{filter:brightness(1.08)}
/* ---- Полоса переезда в мессенджер: живёт между шапкой чата и лентой ----
   Стоит здесь, а не в блоке чата: вся привязка каналов — один раздел, один владелец.
   Полоса ВНЕ .chat-log, поэтому новые сообщения её не уносят вверх, а лента (flex:1)
   честно ужимается на её высоту (около 60px из 526 на экране 390x844).
   Тихая по умолчанию: два чипа, рекомендованный канал шире и с champagne-обводкой.
   Скруглений нет — правило проекта, глубина берётся заливкой и обводкой. */
.chat-relay{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:stretch;
  padding:var(--s2) var(--s4);background:var(--bg-1);border-bottom:1px solid var(--line)}
.cr-b{display:flex;align-items:center;gap:9px;min-height:44px;padding:6px 12px;
  background:var(--bg-3);border:1px solid var(--line);color:var(--ink);font:inherit;
  text-align:left;cursor:pointer;
  transition:border-color var(--d-fast) var(--ease),background var(--d-fast) var(--ease)}
/* Главный канал тянется, запасной — по содержимому. На 320px запасной честно
   переносится на вторую строку, а не сжимает текст выгоды до многоточия. */
.cr-b.prim{flex:1 1 190px;border-color:var(--accent2)}
.cr-b.alt{flex:0 0 auto}
.cr-b:hover{background:var(--bg-4);border-color:var(--accent2)}
.cr-b:focus-visible{outline:2px solid var(--accent2);outline-offset:2px}
.cr-e{font-size:17px;line-height:1;flex:0 0 auto}
.cr-t{display:flex;flex-direction:column;gap:1px;min-width:0}
.cr-t b{font-size:13px;font-weight:700;line-height:1.25;color:var(--ink)}
.cr-t small{font-size:11px;line-height:1.2;color:var(--mut);letter-spacing:.02em}
/* .hot — после того, как человек сам написал в чате. Меняется ТОЛЬКО цвет обводки:
   высота та же, лента не дёргается посреди переписки. */
.chat-relay.hot .cr-b.prim{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
/* Ожидание токена — те же живые точки, что и «печатает» в чате: полоса не должна
   на секунду становиться пустой, это читается как поломка. Высота та же, 61px. */
.chat-relay.busy{justify-content:center;align-items:center;min-height:61px}
.cr-wait{display:inline-flex;align-items:center;gap:5px}
.cr-wait i{width:6px;height:6px;background:var(--mut);animation:chatDot 1.3s infinite ease-in-out}
.cr-wait i:nth-child(2){animation-delay:.16s}
.cr-wait i:nth-child(3){animation-delay:.32s}
@media (prefers-reduced-motion:reduce){.cr-wait i{animation:none;opacity:.6}}
/* Ссылка появилась НА МЕСТЕ кнопки: чат остаётся открытым, переписка не теряется. */
.chat-relay.go{flex-direction:column;align-items:stretch;gap:5px}
.cr-go{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;
  padding:9px 14px;background:var(--accent2);color:#241A2E;font-weight:700;font-size:14px;
  text-decoration:none}
.cr-go:hover{filter:brightness(1.06)}
.cr-go:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.cr-go-sub{font-size:11px;line-height:1.3;color:var(--mut);text-align:center}
/* Подключено — статус, а не вторая просьба: звать туда, куда уже сходили, значит
   приучить не замечать полосу. */
.chat-relay.done{padding:9px var(--s4);gap:7px;align-items:center;font-size:12px}
.chat-relay.done .cr-ok{color:var(--good);font-weight:700}
.chat-relay.done .cr-on-nm{color:var(--ink);font-weight:600}
.chat-relay.done .cr-on-sub{color:var(--dim)}
.connect-link.done{color:var(--good);border-color:rgba(127,232,201,.35)}
@media (prefers-reduced-motion:reduce){.cr-b{transition:none}}
.idol-bio-ro{font-size:13px;color:var(--muted,#a99cc0);margin-top:8px}
.closeness{background:var(--glass,rgba(52,38,78,.42));border:1px solid var(--line);padding:16px;backdrop-filter:blur(8px)}
.close-h{font-size:13px;font-weight:700;color:var(--accent,#e8a9c9)}
.close-stage{font-size:16px;font-weight:800;margin:6px 0 9px}
.close-note{font-size:13px;color:var(--muted,#a99cc0);margin-top:9px;line-height:1.45}
.close-note b{color:var(--champ,#f3d9ac)}
.lang-wrap{margin-left:auto;display:flex;flex-direction:column;align-items:flex-end;gap:2px;line-height:1}
.lang-cap{font-family:var(--f-tech);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--gold)}
.lang-sel{background:var(--panel2);color:var(--ink);border:1px solid var(--gold);font:inherit;font-size:13px;padding:6px 9px;cursor:pointer}
.lang-sel:focus{outline:none;border-color:var(--accent2,#f3d9ac)}

@media(max-width:480px){
  /* Было наоборот: на телефоне айдол СЖИМАЛСЯ до 96x120. Теперь растёт — и в своей
     гримёрке (там портрет во всю ширину, правило .home выше), и в чужой карточке. */
  .idol-hero{flex-direction:column;text-align:center;align-items:center}
  .idol-hero .idol-ph{flex:0 0 auto;width:min(64vw,220px);height:auto;aspect-ratio:1/1}
  .idol-name{justify-content:center}
  .lvl-top{justify-content:center;gap:8px}
  .tile{padding:13px 11px}
  .tile.lead{padding:16px 14px}
}
.chat-box{background:var(--bg2);border:1px solid var(--line);max-width:440px;width:100%;height:min(78vh,640px);display:flex;flex-direction:column;overflow:hidden}
.chat-head{display:flex;align-items:center;justify-content:space-between;padding:13px 16px;border-bottom:1px solid var(--line);font-weight:700;color:var(--accent2)}
.chat-x{background:none;border:none;color:var(--ink);font-size:16px;cursor:pointer;opacity:.7}
/* Тап-цель 44 в шапке чата: отрицательные поля гасят прирост, крестик остаётся на месте.
   Правило намеренно ограничено .chat-head — тот же .chat-x живёт в уроке, песне и тетради. */
.chat-head .chat-x{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;margin:-10px -14px -10px 0}
.chat-x:hover{opacity:1}
/* Шапка чата: имя айдола + её состояние. Никакого «урока» — это переписка. */
.chat-ttl{display:flex;flex-direction:column;gap:1px;min-width:0;line-height:1.2}
.chat-ttl-nm{font-size:15px;font-weight:700;color:var(--accent2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-ttl-kr{font-style:normal;font-weight:500;opacity:.65;margin-left:6px;font-size:13px}
.chat-ttl-st{font-size:11px;font-weight:500;letter-spacing:.02em;color:var(--muted,#9a8fb0)}
/* «Печатает» — живые точки вместо неподвижной «…» на все 3+ секунды ожидания. */
.chat-typing{display:inline-flex;align-items:center;gap:5px;padding:12px 14px}
.chat-typing i{width:6px;height:6px;background:var(--muted,#9a8fb0);animation:chatDot 1.3s infinite ease-in-out}
.chat-typing i:nth-child(2){animation-delay:.16s}
.chat-typing i:nth-child(3){animation-delay:.32s}
@keyframes chatDot{0%,65%,100%{opacity:.32;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
@media (prefers-reduced-motion:reduce){.chat-typing i{animation:none;opacity:.6}}
/* Пустой тред: айдол напишет первой, шага от человека не требуем. */
.chat-wait{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 16px}
.chat-wait b{color:var(--ink);font-size:15px;font-weight:700;line-height:1.3}
.chat-wait .chat-typing{background:var(--panel2);border:1px solid var(--line)}
.chat-wait-sub{font-size:13px;line-height:1.5;max-width:270px;color:var(--muted,#9a8fb0)}
.chat-log{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px}
.chat-empty{color:var(--muted,#9a8fb0);font-size:13px;text-align:center;margin:auto;padding:20px}
.chat-msg{display:flex}
.chat-msg.me{justify-content:flex-end}
.chat-msg.idol{justify-content:flex-start}
.chat-b{max-width:78%;padding:9px 13px;font-size:15px;line-height:1.4;white-space:pre-wrap;word-break:break-word}
.chat-msg.me .chat-b{background:var(--accent-fill);color:#fff}
.chat-msg.idol .chat-b{background:var(--panel2);color:var(--ink);border:1px solid var(--line)}
.chat-input{display:flex;gap:8px;padding:12px 14px;border-top:1px solid var(--line)}
.chat-input input{flex:1;background:var(--panel2);border:1px solid var(--line);color:var(--ink);font:inherit;font-size:16px;padding:10px 13px}
.chat-input input:focus{outline:none;border-color:var(--accent2)}
.chat-input .btn{padding:10px 16px;font-size:16px}

/* ===== УРОК-ФУНДАМЕНТ ===== */
.lesson-box{background:var(--bg2);border:1px solid var(--line);max-width:560px;width:100%;height:min(86vh,760px);display:flex;flex-direction:column;overflow:hidden}
/* Список песен короткий — панель фиксированной высоты оставляла под последней карточкой
   около 470px пустоты. В режиме списка панель растёт по содержимому, потолок прежний. */
.lesson-box.fit{height:auto;max-height:min(86vh,760px)}
/* Рабочая тетрадь — во весь экран (26.07, решение Сармата: больше места под строки).
   Только она: чат/песня/уроки остаются центрированной карточкой (.lesson-box). */
#wbOv{padding:0}
#wbBox{max-width:none;width:100vw;height:100vh;height:100dvh;border:0}
.lesson-head{display:flex;align-items:center;gap:10px;padding:13px 16px;border-bottom:1px solid var(--line);font-weight:700;color:var(--accent2)}
.lesson-head span{flex:1;text-align:center}
.lsn-back{background:none;border:none;color:var(--muted,#a99cc0);font-size:20px;cursor:pointer;line-height:1}
.lesson-body{flex:1;overflow-y:auto;padding:18px}
/* ── Разбор песни — полноэкранный экран (Сармат 25.07): не карточка поверх кабинета.
   Список песен остаётся карточкой (.fit); полноэкранный режим = отсутствие .fit.
   :has() уже используется в проекте, поддержка мобильных Safari 15.4+. ── */
#songOv:has(#songBox:not(.fit)){padding:0}
#songBox:not(.fit){max-width:none;width:100%;height:100vh;height:100dvh;border:none}
@media(min-width:640px){
  #songOv:has(#songBox:not(.fit)){padding:24px}
  #songBox:not(.fit){max-width:600px;height:min(94vh,880px);border:1px solid var(--line)}
}
/* Переключатель Текст | Слова — наверху экрана песни, возврат одним тапом без прокрутки.
   В списке песен (.fit) сегмента нет. */
.song-seg{display:flex;background:var(--bg2);border-bottom:1px solid var(--line);flex:0 0 auto}
#songBox.fit .song-seg{display:none}
.song-seg button{flex:1;min-height:46px;background:none;border:none;border-bottom:2px solid transparent;
  color:var(--mut);font:inherit;font-size:14px;font-weight:600;cursor:pointer;transition:color .14s,border-color .14s}
.song-seg button.on{color:var(--ink);border-bottom-color:var(--accent2)}
.song-seg button:active{color:var(--ink)}
/* ── Тумблеры слоёв (Сармат 25.07, вид v4). Регулируют плотность экрана. Два вида контрола,
   переключаются классом на #songBox — логика (localStorage, минимум один, lay-no-*) одна:
     по умолчанию  — ВАРИАНТ 1: тихий ряд цветных меток, каждая в цвете своего слоя;
     .ctrl-popover — ВАРИАНТ 2: иконка ☰ у сегмента, по тапу — поповер с 4 переключателями.
   Не цветом одним: у каждой метки И точка-цвет, И текст (ui-ux-pro-max: color-only = fail). ── */
#songBox{position:relative}   /* якорь для поповера v2 */
.lay-chip{display:inline-flex;align-items:center;gap:6px;background:none;border:none;padding:6px 2px;
  min-height:34px;font:inherit;font-size:11px;font-weight:600;color:var(--dim);opacity:.72;
  cursor:pointer;white-space:nowrap;transition:color .14s,opacity .14s;touch-action:manipulation}
/* Квадрат-галочка: включён — крупная ✓ и подпись в цвете слоя; выключен — пустой квадрат, тихо. */
.lay-chip .dot{width:15px;height:15px;flex:0 0 15px;border:1.5px solid var(--dim);
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;line-height:1;
  color:transparent;transition:border-color .14s,color .14s}
.lay-chip .dot::before{content:'✓'}
.lay-chip.on{opacity:1;color:var(--ink)}
.lay-chip.on[data-lay="k"] .dot{border-color:var(--lyr-k);color:var(--lyr-k)} .lay-chip.on[data-lay="k"] .lbl{color:var(--lyr-k)}
.lay-chip.on[data-lay="r"] .dot{border-color:var(--lyr-r);color:var(--lyr-r)} .lay-chip.on[data-lay="r"] .lbl{color:var(--lyr-r)}
.lay-chip.on[data-lay="m"] .dot{border-color:var(--lyr-m);color:var(--lyr-m)} .lay-chip.on[data-lay="m"] .lbl{color:var(--lyr-m)}
.lay-chip.on[data-lay="s"] .dot{border-color:var(--lyr-s);color:var(--lyr-s)} .lay-chip.on[data-lay="s"] .lbl{color:var(--lyr-s)}
.lay-chip.locked{cursor:default}   /* последний включённый — снять нельзя (логика в JS) */

/* ВАРИАНТ 1 — тихий ряд: один ряд, низкий, без «кнопочной» рамки/заливки */
.song-layers{display:flex;justify-content:space-between;align-items:center;gap:4px;
  padding:6px 14px;background:var(--bg2);border-bottom:1px solid var(--line);flex:0 0 auto}
/* Ряд слоёв — только во вкладке «Текст» (в списке, наборе слов и куплетах его нет) */
#songBox.fit .song-layers,#songBox.sv-words .song-layers,#songBox.sv-verses .song-layers{display:none}

/* Иконка-триггер v2 (в сегменте; в v1 скрыта) */
.song-gear{display:none;flex:0 0 48px;background:none;border:none;border-left:1px solid var(--line);
  color:var(--mut);font-size:17px;line-height:1;cursor:pointer;align-items:center;justify-content:center;touch-action:manipulation}
#songBox.ctrl-popover.sv-text .song-gear{display:flex}
#songBox.fit .song-gear{display:none}

/* ВАРИАНТ 2 — поповер: тот же ряд становится вертикальным листом у иконки, скрыт до тапа */
#songBox.ctrl-popover .song-layers{position:absolute;right:8px;left:auto;z-index:30;display:none;
  flex-direction:column;align-items:stretch;gap:2px;padding:8px;min-width:200px;
  background:var(--bg-3);border:1px solid var(--line-strong);box-shadow:var(--sh-2)}
#songBox.ctrl-popover .song-layers.open{display:flex}
#songBox.ctrl-popover .lay-chip{justify-content:flex-start;min-height:44px;padding:9px 10px;font-size:13px}

/* Скрытие ярусов по тумблерам (стабильный #songBox, строго .kara-lines). */
#songBox.lay-no-k .kara-lines .tok-k{display:none}
#songBox.lay-no-r .kara-lines .tok-r{display:none}
#songBox.lay-no-m .kara-lines .tok-m{display:none}
#songBox.lay-no-s .kara-lines .ksl{display:none}

/* ── Вкладка «Куплеты» (Сармат 25.07) — режим пения. То же караоке (те же тайминги/заливка/скролл),
   но показан ОДИН слой (single-select radio) крупно. Дефолт — транскрипция: включаешь клип и
   подпеваешь по заливке. Радио-переключатель — глобальный режим вкладки, состояние в localStorage. ── */
.song-vmodes{display:none}
#songBox.sv-verses .song-vmodes{display:flex;gap:6px;padding:8px 14px;background:var(--bg2);
  border-bottom:1px solid var(--line);flex:0 0 auto}
.vm-btn{flex:1;min-height:42px;background:none;border:1px solid var(--line);color:var(--mut);
  font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:color .14s,background-color .14s,border-color .14s;touch-action:manipulation}
.vm-btn.on{color:#100B18;border-color:transparent}
.vm-btn.on[data-vm="k"]{background:var(--lyr-k)}
.vm-btn.on[data-vm="r"]{background:var(--lyr-r)}
.vm-btn.on[data-vm="s"]{background:var(--lyr-s)}
/* Прячем всё лишнее: панель куплета, 🔗 и все слои, кроме выбранного */
#songBox.verse-mode .kara-pause,#songBox.verse-mode .ksl-c{display:none}
#songBox.verse-mode .kara-lines .tok-k,#songBox.verse-mode .kara-lines .tok-r,
#songBox.verse-mode .kara-lines .tok-m,#songBox.verse-mode .kara-lines .ksl{display:none}
/* Выбранный слой — крупно, для пения */
#songBox.verse-mode.vm-k .kara-lines .tok-k{display:block;font-size:30px;line-height:1.3}
#songBox.verse-mode.vm-r .kara-lines .tok-r{display:block;font-size:29px;line-height:1.3}
#songBox.verse-mode.vm-s .kara-lines .kline{display:none}
#songBox.verse-mode.vm-s .kara-lines .ksl{display:block}
#songBox.verse-mode.vm-s .kara-lines .ksl-t{font-size:23px;line-height:1.45}
#songBox.verse-mode .kara-lines .kline{gap:10px 20px}
#songBox.verse-mode .kgrp{padding:16px 0}
.lsn-progress{display:flex;align-items:center;gap:10px;margin-bottom:16px;font-size:13px;color:var(--dim,#a394bd)}
.lsn-pbar{flex:1;height:6px;background:var(--panel2);border:1px solid var(--line);overflow:hidden}
.lsn-pbar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent2))}
.lsn-unit{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--champ,#f3d9ac);margin:14px 0 8px}
.lsn-list{display:flex;flex-direction:column;gap:8px}
.lsn-item{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);color:var(--ink);padding:12px 14px;cursor:pointer;transition:.15s}
.lsn-item:hover:not(:disabled){border-color:var(--accent2);transform:translateX(2px)}
.lsn-item.done{border-color:rgba(127,232,201,.38)}
/* Замков в списке уроков нет: открыт весь алфавит, порядок — рекомендация.
   .next — «начни отсюда», единственная подсказка последовательности. */
.lsn-item.next{border-color:var(--accent2);background:rgba(240,168,204,.09)}
/* Метка стоит НАД названием, а не справа от него: справа она отжимала заголовок
   урока в две строки на 360px. */
.lsn-here{align-self:flex-start;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--accent2);border:1px solid rgba(240,168,204,.45);padding:3px 7px;line-height:1.2;margin-bottom:2px}
.lsn-badge{font-size:15px;width:22px;text-align:center;flex-shrink:0;color:var(--dim,#a394bd)}
.lsn-item.next .lsn-badge{color:var(--accent2)}
.lsn-item.done .lsn-badge{color:var(--good)}
.lsn-txt{display:flex;flex-direction:column;gap:2px}
.lsn-txt b{font-size:15px}
.lsn-txt small{font-size:11px;color:var(--dim,#a394bd)}
.lsn-goal{font-size:13px;color:var(--champ,#f3d9ac);margin-bottom:14px}
.lsn-teacher{display:flex;flex-direction:column;gap:12px;margin-bottom:18px}
.lb-text{font-size:15px;line-height:1.55;color:var(--ink)}
/* Карточка буквы: знак слева, справа колонкой две транскрипции, пояснение и
   слово-пример. Раньше это была одна строка flex — с добавлением кириллицы и
   примера она бы разъехалась на узком экране, поэтому правая часть колонка. */
.lb-hangul{display:flex;align-items:flex-start;gap:12px;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:12px 14px}
.lb-char{font-size:34px;font-weight:700;color:var(--accent2);line-height:1;min-width:44px;flex-shrink:0}
.lb-hbody{display:flex;flex-direction:column;gap:5px;flex:1;min-width:0}
.lb-hline{display:flex;align-items:baseline;flex-wrap:wrap;gap:8px}
.lb-cyr{font-size:15px;font-weight:600;color:var(--champ,#f3d9ac);letter-spacing:.01em}
.lb-cyr i{font-style:normal;color:var(--dim,#a394bd);margin-right:6px}
.lb-hex{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 9px;width:100%;text-align:left;
  background:none;border:none;border-top:1px solid var(--line);color:inherit;font:inherit;
  padding:7px 0 0;margin-top:1px;cursor:pointer}
.lb-hex:hover .lb-hex-kr{color:var(--accent2)}
.lb-hex-kr{font-size:16px;font-weight:700;color:var(--ink)}
.lb-hex-rom{font-size:13px;color:var(--champ,#f3d9ac)}
.lb-hex-mean{font-size:13px;color:var(--dim,#a394bd);min-width:0;overflow-wrap:anywhere;order:3}
.lb-hex-say{font-size:13px;margin-left:auto;opacity:.75;order:4}
/* 23.07: боковая полоска слева (замаскированный side-tab, ничего не сообщала) заменена
   на верхнюю линию-разделитель — ровно тем же приёмом, что у соседнего .lb-hex выше. */
.lb-ex{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;border-top:1px solid var(--line);padding:9px 0 8px}
.lb-kr{font-size:20px;font-weight:700;color:var(--ink)}
.lb-rom{font-size:16px;font-weight:700;color:var(--accent2);letter-spacing:.01em}
.say.sm{margin-left:6px;padding:1px 6px;font-size:13px;border:none;vertical-align:middle}
.lsn-toinfo{background:none;border:none;color:var(--muted,#a99cc0);font:inherit;font-size:13px;cursor:pointer;padding:0 0 12px;display:block}
.lsn-toinfo:hover{color:var(--accent2)}
.lb-mean{font-size:15px;color:var(--muted,#a99cc0)}
.lb-tip{font-size:13px;line-height:1.5;background:rgba(243,217,172,.08);border:1px solid rgba(243,217,172,.25);padding:11px 13px;color:var(--muted,#a99cc0)}
.lsn-vocab-note{font-size:13px;color:var(--dim,#a394bd);margin-bottom:16px}
.lsn-quiz-h{font-size:13px;font-weight:700;letter-spacing:.02em;color:var(--accent2);margin-bottom:12px}
.lq{margin-bottom:16px}
.lq-q{font-size:15px;margin-bottom:8px}
.lq-opts{display:flex;flex-direction:column;gap:6px}
.lq-opt{text-align:left;background:var(--panel2);border:1px solid var(--line);color:var(--ink);padding:9px 12px;font:inherit;font-size:13px;cursor:pointer;transition:.12s}
.lq-opt:hover{border-color:var(--accent2)}
.lq-opt.sel{border-color:var(--accent2);background:rgba(240,168,204,.13)}
.lq-opt.correct{border-color:var(--good);background:rgba(127,232,201,.14)}
.lq-opt.wrong{border-color:var(--err);background:rgba(240,135,155,.16)}
.lsn-quiz-msg{font-size:13px;margin:6px 0 12px;min-height:1px}
.lsn-quiz-msg.ok{color:var(--good)}
.lsn-quiz-msg.warn{color:#e0b46a}
.lsn-finish{width:100%;justify-content:center;margin:4px 0 10px}
.lsn-finish.accent{margin-left:0}
.lsn-ask{display:block;width:100%;min-height:44px;text-align:center;background:none;border:1px solid var(--line);color:var(--muted,#a99cc0);padding:11px;font:inherit;font-size:13px;cursor:pointer}
.lsn-ask:hover{border-color:var(--accent2);color:var(--accent2)}

/* ===== МЕХАНИКА УРОКА: серия, распевка, карта хангыля, имя =====
   Тап-цели от 44px, плоские углы (правило проекта), тёмная тема — родная.
   Полосы прогресса меняют width БЕЗ transition: ширину не анимируем. */
/* Счётчиков может быть 1, 2 или 3 — пустые не рисуются вовсе (см. lsnHeader).
   Экран новичка не открывается отчётом о том, чего он ещё не сделал. */
.lsn-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:10px}
/* Один-два счётчика не растягиваем на всю ширину: полоса «가 1/40» во весь
   экран весит как заголовок, хотя это подпись. */
.lsn-stats.n1,.lsn-stats.n2{display:flex;flex-wrap:wrap}
.lsn-stats.n1 .lsn-stat,.lsn-stats.n2 .lsn-stat{flex:0 1 auto;padding:8px 13px;text-align:left}
.lsn-stats.n1 .lsn-stat b,.lsn-stats.n2 .lsn-stat b{font-size:15px}
.lsn-stat{border:1px solid var(--line);background:var(--panel,rgba(52,38,78,.42));padding:10px 8px;text-align:center}
.lsn-stat b{display:block;font-size:16px;color:var(--ink);line-height:1.2;white-space:nowrap}
.lsn-stat small{display:block;font-size:11px;letter-spacing:.04em;color:var(--dim,#a394bd);margin-top:3px}
.lsn-stat.on{border-color:var(--accent2)}
.lsn-stat.on b{color:var(--accent2)}
.lsn-lvl{margin-bottom:10px}
.lsn-lvl-top{display:flex;justify-content:space-between;gap:10px;font-size:11px;color:var(--dim,#a394bd);margin-bottom:5px}
.lsn-lvl-top span:first-child{color:var(--champ,#f3d9ac);font-weight:700;letter-spacing:.04em}
.lsn-freeze{font-size:11px;line-height:1.4;color:var(--dim,#a394bd);border-left:2px solid var(--line);padding-left:9px;margin-bottom:12px}

/* Распевка — ежедневный минимум, стоит выше всего остального.
   Порог входа намеренно низкий: одна карточка в минуту держит серию. */
.lsn-daily,.lsn-name,.lsn-map{display:flex;align-items:center;gap:13px;width:100%;min-height:64px;text-align:left;
  border:1px solid var(--line);background:var(--panel,rgba(52,38,78,.42));color:var(--ink);
  padding:13px 14px;margin-bottom:9px;font:inherit;cursor:pointer;transition:border-color .15s,background-color .15s}
.lsn-daily{border-color:var(--accent2);background:rgba(243,217,172,.09)}
.lsn-daily:hover,.lsn-name:hover,.lsn-map:hover{border-color:var(--accent2);background:rgba(240,168,204,.12)}
.lsn-daily.ok{border-color:rgba(127,232,201,.5);background:rgba(127,232,201,.09)}
.ld-ico,.lm-ico{font-size:26px;line-height:1;flex-shrink:0;width:40px;text-align:center;color:var(--accent2)}
/* Имя может быть длинным (사르마트) — не зажимаем в колонку 40px, иначе рассыпается по вертикали. */
.ln-kr{font-size:20px;font-weight:700;line-height:1.1;color:var(--accent2);flex-shrink:0;
  white-space:nowrap;max-width:44%;overflow:hidden;text-overflow:ellipsis}
.ld-txt,.lm-txt,.ln-txt{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
.ld-txt b,.lm-txt b,.ln-txt b{font-size:15px}
.ld-txt small,.lm-txt small,.ln-txt small{font-size:11px;line-height:1.35;color:var(--mut,#c7b3da)}
.ld-go{margin-left:auto;color:var(--accent2);font-size:16px;flex-shrink:0}
.lsn-name.done .ln-kr{color:var(--good,#7fe8c9)}
/* ===== АЙДОЛ В УРОКЕ =====
   Был серой ссылкой 12px в углу — самым слабым элементом экрана, на котором
   и надо учиться. Стал панелью с лицом, именем и живой репликой, которая
   стоит первой и на списке уроков, и внутри урока. */
.lsn-av{width:44px;height:44px;flex-shrink:0;object-fit:cover;border:1px solid var(--line);background:var(--panel2);display:block}
.lsn-av.ph{display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:700;color:var(--accent2)}
.lsn-coach{display:flex;align-items:center;gap:11px;width:100%;text-align:left;font:inherit;
  border:1px solid var(--line);background:var(--panel,rgba(52,38,78,.42));color:var(--ink);
  padding:10px 12px;margin-bottom:12px}
button.lsn-coach{cursor:pointer;min-height:64px}
button.lsn-coach:hover{border-color:var(--accent2)}
.lsc-b{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.lsc-b b{font-size:13px;letter-spacing:.05em;text-transform:uppercase;color:var(--accent2);font-weight:700}
.lsc-b span{font-size:13px;line-height:1.4;color:var(--ink)}
.lsc-ask{flex-shrink:0;align-self:center;min-width:44px;min-height:44px;background:none;border:1px solid var(--line);
  color:var(--mut,#c7b3da);font:inherit;font-size:13px;padding:6px 11px;white-space:nowrap;cursor:pointer}
.lsc-ask:hover{border-color:var(--accent2);color:var(--accent2)}
/* Тап-цель озвучки внутри урока — не меньше 44px (в списке песен .say меняем не мы). */
.lb-hangul .say,.lb-ex .say,.lb-batchim .say,.dr-big .say,.ln-big .say{min-width:44px;min-height:44px;font-size:16px}
.lsn-secline{display:block;width:100%;min-height:44px;text-align:left;background:none;border:1px solid var(--line);
  color:var(--champ,#f3d9ac);font:inherit;font-size:13px;padding:11px 12px;margin-bottom:14px;cursor:pointer}
.lsn-secline:hover{border-color:var(--accent2)}

/* Карта хангыля: все 40 букв сразу, цвет плитки = уровень владения (SRS). */
.hm-sum{font-size:13px;line-height:1.5;color:var(--champ,#f3d9ac);margin-bottom:10px}
.hm-say{font-size:12px;line-height:1.5;color:var(--dim,#a394bd);margin-bottom:10px}
.hm-empty{font-size:13px;color:var(--dim,#a394bd);border:1px solid var(--line);padding:14px;text-align:center}
.hm-legend{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;font-size:11px;color:var(--dim,#a394bd);margin-bottom:16px}
.hm-dot{display:inline-block;width:11px;height:11px;border:1px solid var(--line);margin-right:1px;vertical-align:-1px}
.hm-dot.t1{background:rgba(240,168,204,.32);border-color:var(--accent)}
.hm-dot.t2{background:rgba(127,232,201,.3);border-color:var(--good,#7fe8c9)}
.hm-dot.t3{background:rgba(217,164,65,.4);border-color:var(--gold)}
.hm-sec{border:1px solid var(--line);padding:12px;margin-bottom:12px}
/* Заголовок сектора переносится на две строки: секторов стало шесть плюс
   правило, и на 320px «Придыхательные + согласные + 0/4» в строку не влезает. */
.hm-h{display:flex;align-items:center;flex-wrap:wrap;gap:5px 9px;margin-bottom:10px}
.hm-h b{font-size:13px;flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.hm-icon{font-size:20px;color:var(--accent2);width:26px;text-align:center;flex-shrink:0}
.hm-kind{font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--dim,#a394bd);
  border:1px solid var(--line);padding:1px 6px;flex-shrink:0;white-space:nowrap}
.hm-kind.k-v{color:var(--accent2);border-color:rgba(240,168,204,.42)}
.hm-kind.k-c{color:var(--good,#7fe8c9);border-color:rgba(127,232,201,.4)}
.hm-count{font-size:13px;color:var(--dim,#a394bd);font-variant-numeric:tabular-nums;flex-shrink:0;margin-left:auto}
.hm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(58px,1fr));gap:6px;margin-bottom:10px}
.hm-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;min-height:64px;
  border:1px solid var(--line);background:var(--panel2);color:var(--dim,#a394bd);font:inherit;cursor:pointer;
  padding:6px 2px;transition:border-color .14s,background-color .14s,color .14s}
.hm-tile:hover{border-color:var(--accent2)}
.hm-ch{font-size:21px;font-weight:700;line-height:1}
.hm-rom{font-size:11px;letter-spacing:.02em;opacity:.9;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.hm-cyr{font-size:11px;line-height:1.1;color:var(--champ,#f3d9ac);opacity:.85;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.hm-tile.t1{color:var(--ink);background:rgba(240,168,204,.14);border-color:rgba(240,168,204,.45)}
.hm-tile.t2{color:var(--ink);background:rgba(127,232,201,.14);border-color:rgba(127,232,201,.5)}
.hm-tile.t3{color:var(--ink);background:rgba(217,164,65,.18);border-color:var(--gold)}
.hm-tile.rule{cursor:default;min-height:56px}
.hm-tile.rule .hm-rom{font-size:11px}
.hm-go{display:block;width:100%;min-height:44px;background:none;border:1px solid var(--line);color:var(--accent2);
  font:inherit;font-size:13px;padding:11px;cursor:pointer}
.hm-go:hover{border-color:var(--accent2);background:rgba(240,168,204,.10)}

/* Первая минута: имя хангылем. Результат виден до любого урока. */
.ln-form input{width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:16px;padding:12px 13px;margin-bottom:16px}
.ln-form input:focus{outline:none;border-color:var(--accent2)}
.ln-big{font-size:38px;font-weight:700;line-height:1.25;color:var(--accent2);text-align:center;
  word-break:break-word;margin-bottom:16px}
.ln-blocks{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-bottom:16px}
.ln-block{border:1px solid var(--line);background:var(--panel,rgba(52,38,78,.42));padding:9px 8px;min-width:56px;text-align:center}
.ln-b-kr{font-size:26px;font-weight:700;line-height:1.1;color:var(--ink)}
.ln-b-parts{display:flex;flex-direction:column;gap:1px;margin-top:5px}
.ln-b-parts span{font-size:13px;color:var(--accent2);line-height:1.2}
.ln-b-parts i{font-size:11px;font-style:normal;color:var(--dim,#a394bd);margin-left:3px}
.ln-note{font-size:11px;line-height:1.45;color:var(--dim,#a394bd);margin-bottom:14px}
.ln-empty{font-size:13px;line-height:1.5;color:var(--dim,#a394bd);padding:16px 0}

/* Распевка и проверочная: один вопрос на экран, мгновенная обратная связь. */
.dr-top{display:flex;align-items:center;gap:10px;margin-bottom:18px;font-size:13px;color:var(--dim,#a394bd);font-variant-numeric:tabular-nums}
.dr-big{font-size:52px;font-weight:700;line-height:1.15;color:var(--accent2);text-align:center;word-break:break-word;margin-bottom:14px}
.dr-q{font-size:15px;line-height:1.4;text-align:center;margin-bottom:16px;color:var(--ink)}
.lq-opt.dr-opt{min-height:48px;font-size:15px;text-align:center;padding:12px}
.lq-opt.dr-opt:disabled{cursor:default}
.dr-react{min-height:52px;margin-top:12px}
/* Новая карточка сначала показывается, потом спрашивается. */
.dr-new{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--accent2);text-align:center;margin-bottom:4px}
.dr-teach{display:flex;flex-direction:column;align-items:center;gap:4px;margin-bottom:16px}
.dr-teach b{font-size:20px;font-weight:700;color:var(--champ,#f3d9ac);letter-spacing:.01em}
.dr-teach+.lsn-idol-line{margin-bottom:16px}
.dr-teach span{font-size:13px;line-height:1.4;color:var(--mut,#c7b3da);text-align:center}
/* Реакция айдола — с лицом. Реагирует он, а не интерфейс. */
.lsn-idol-line{display:flex;align-items:flex-start;gap:10px;text-align:left}
.lsn-idol-line .lsn-av{width:36px;height:36px}
.lil-b{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.lil-who{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--accent2)}
.lil-txt{font-size:13px;line-height:1.4;color:var(--ink)}
.dr-done{text-align:center;padding-top:10px}
.dd-flame{font-size:40px;line-height:1}
.dd-n{font-family:var(--f-display),system-ui,sans-serif;font-size:52px;font-weight:900;line-height:1.05;color:var(--accent2)}
.dd-cap{font-size:15px;color:var(--ink);margin-bottom:14px}
.dd-froze,.dd-seven{font-size:13px;line-height:1.45;color:var(--champ,#f3d9ac);border:1px solid rgba(243,217,172,.3);
  background:rgba(243,217,172,.08);padding:9px 11px;margin-bottom:12px;text-align:left}
.dd-seven{color:var(--gold);border-color:var(--gold);background:rgba(217,164,65,.08)}
.dd-row{display:flex;justify-content:space-between;gap:12px;font-size:13px;color:var(--mut,#c7b3da);
  border-bottom:1px solid var(--line);padding:9px 0}
.dd-row b{color:var(--ink)}
.dr-done .lsn-idol-line{text-align:left;margin:14px 0 16px}

/* Блоки урока: патчхим-группы и «что ты теперь умеешь». */
.lb-batchim{display:flex;align-items:center;gap:12px;border:1px solid var(--line);background:var(--panel2);padding:10px 13px}
.lb-bg{font-size:24px;font-weight:700;color:var(--accent2);line-height:1;min-width:32px}
.lb-bc{font-size:15px;color:var(--mut,#c7b3da);letter-spacing:.06em;min-width:0;word-break:break-word}
.lb-win{display:flex;gap:10px;align-items:flex-start;font-size:13px;line-height:1.5;color:var(--champ,#f3d9ac);
  border:1px solid rgba(243,217,172,.3);background:rgba(243,217,172,.07);padding:12px 13px}
.lb-win span:first-child{color:var(--gold);flex-shrink:0}

@media(max-width:400px){
  .lsn-stat b{font-size:15px}
  .lsn-stat small{font-size:11px}
  .ln-big{font-size:30px}
  .dr-big{font-size:42px}
  .hm-grid{grid-template-columns:repeat(auto-fill,minmax(50px,1fr))}
  .ld-ico,.lm-ico{width:32px;font-size:22px}
  .ln-kr{font-size:16px;max-width:40%}
  /* 320-360px: у буквы пять полей, знак ужимаем, чтобы примеру осталось место */
  .lb-hangul{gap:9px;padding:11px 11px}
  .lb-char{font-size:29px;min-width:34px}
  /* Перевод уезжает на свою строку, динамик остаётся справа в первой */
  .lb-hex-mean{flex-basis:100%;order:4}
  .lb-hex-say{order:3}
  .hm-tile{min-height:60px;padding:5px 1px}
  .hm-ch{font-size:20px}
  .hm-rom,.hm-cyr{font-size:11px}
  .hm-kind{font-size:11px;padding:1px 4px}
}

/* ===== РАБОЧАЯ ТЕТРАДЬ ===== */
.wb-tabs{display:flex;border-bottom:1px solid var(--line)}
.wb-tab{flex:1;background:none;border:none;border-bottom:2px solid transparent;color:var(--dim,#a394bd);font:inherit;font-size:13px;font-weight:600;padding:12px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:7px}
.wb-tab span{font-size:11px;background:var(--panel2);border:1px solid var(--line);padding:1px 7px}
.wb-tab.on{color:var(--accent2);border-bottom-color:var(--accent2)}
.wb-hint{font-size:11px;color:var(--mut);opacity:.75;margin-bottom:14px;line-height:1.45}
.wb-list{display:flex;flex-direction:column;gap:6px}
.wb-row{display:flex;align-items:flex-start;gap:8px;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:8px 10px}
.wb-row.hard .wb-prog .on{color:var(--gold)}
/* Слово занимает основную ширину строки и не даёт себя сжать в полоску: жалоба
   Сармата 24.07 «поле перевода уехало, туда даже буква не вмещается» — это схлопывание
   колонки на узком экране. min-width держит перевод читаемым. */
.wb-word{flex:1 1 auto;min-width:58%;display:flex;flex-direction:column;gap:3px;padding-top:3px}
.wb-word b{font-size:16px;color:var(--ink);line-height:1.3;word-break:break-word}
.wb-word i{font-size:12px;color:var(--mut);font-style:normal;letter-spacing:.02em}
/* Подстрочник под транскрипцией — только у китайского интерфейса (см. trFor2 в
   app.js). Иероглиф не различает 학 и 하, латиница снизу различает. Она мельче и
   тише: ведущая строка всё равно иероглиф, подстрочник дочитывает. */
.wb-tr2{display:block;font-size:10.5px;opacity:.75;letter-spacing:.01em;line-height:1.25}
/* Иероглифам нужен свой размер: в 12px они читаются хуже латиницы. Класс
   ставится разметкой, а не селектором по языку: атрибут lang у страницы
   захардкожен «ru» и языком интерфейса не управляет. */
.wb-tr1{font-size:15px;line-height:1.3}
/* Перевод — это то, ради чего человек открыл строку. Раньше 13px приглушённым: читался
   как сноска. Крупнее и полноцветно, во всю ширину колонки. */
.wb-mean{font-size:15px;color:var(--ink);line-height:1.4;width:100%;word-break:break-word}
/* Обратное направление: ответ скрыт, тап — проверил себя. Список сам работает проверкой. */
.wb-hide{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;cursor:pointer;min-height:26px;padding:2px 0}
.wb-hide em,.wb-hide i{filter:blur(5px);transition:filter .18s ease;font-style:normal}
.wb-hide.on em,.wb-hide.on i{filter:none}
.wb-hide em{font-size:15px;color:var(--ink)}
.wb-hide i{font-size:11px;color:var(--mut)}
.wb-meta{display:flex;flex-direction:column;align-items:flex-end;gap:3px;padding-top:4px;flex:none}
.wb-prog{font-size:11px;letter-spacing:1px;color:var(--line)}
.wb-prog .on{color:var(--accent2)}
/* Статус слова словом, а не точками: «узнаю» человеку понятно, «●●○○○○» — нет.
   Кнопка, потому что статус можно понизить вручную, если слово выветрилось. */
.wb-stat{background:none;border:1px solid var(--line);color:var(--mut);font:inherit;font-size:11px;
  letter-spacing:.02em;padding:3px 7px;cursor:pointer;white-space:nowrap;transition:border-color .14s,color .14s}
.wb-stat:hover{border-color:var(--accent2);color:var(--accent2)}
.wb-stat.s1{color:var(--muted,#a99cc0);border-color:rgba(240,168,204,.32)}
.wb-stat.s2{color:var(--champ,#f3d9ac);border-color:rgba(243,217,172,.4)}
.wb-stat.s3{color:var(--good,var(--good));border-color:rgba(127,232,201,.45)}
/* Строка-источник: слово без своей строки — карточка без контекста. */
.wb-line{font-size:11px;color:var(--mut);opacity:.75;line-height:1.35;word-break:break-word}
.wb-rev-line{display:flex;align-items:center;gap:8px;margin-top:10px;border:1px solid var(--line);padding:8px 10px;text-align:left}
.wb-rev-lt{flex:1;min-width:0}
.wb-rev-lt b{display:block;font-size:15px;color:var(--ink);font-weight:600;line-height:1.35;word-break:break-word}
.wb-rev-lt i{display:block;font-size:13px;color:var(--mut);font-style:normal;margin-top:2px}
.wb-say.sm{min-width:38px;min-height:38px;font-size:15px}
/* Пустая тетрадь больше не тупик: три способа положить в неё первое слово. */
.wb-empty-t{margin-bottom:14px}
.wb-seeds{display:flex;flex-direction:column;gap:8px;max-width:22em;margin:0 auto}
.wb-seed{min-height:48px;background:var(--panel2,rgba(52,38,78,.6));border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:13px;padding:12px;cursor:pointer;transition:border-color .14s,color .14s}
.wb-seed:hover{border-color:var(--accent2);color:var(--accent2)}
/* «Собери строку»: третий формат на том же материале. Тренирует чанк целиком —
   то, что реально поётся, — а не изолированное слово. */
.wb-build{gap:12px}
.wb-b-sense{font-size:15px;line-height:1.45;color:var(--ink);text-align:center;padding:0 4px}
.wb-b-slots{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;align-items:center;min-height:56px;
  border:1px dashed var(--line);padding:10px;transition:border-color .2s}
.wb-b-slots.good{border-color:rgba(127,232,201,.55);border-style:solid}
.wb-b-slots.bad{border-color:rgba(240,135,155,.55);border-style:solid}
.wb-b-ph{font-size:13px;color:var(--mut);opacity:.8}
.wb-b-pool{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;min-height:48px}
.wb-chip-w{min-height:44px;background:var(--panel2,rgba(52,38,78,.6));border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:16px;padding:8px 12px;cursor:pointer;transition:border-color .14s}
.wb-chip-w:hover:not([disabled]){border-color:var(--accent2)}
.wb-chip-w[disabled]{opacity:.75;cursor:default}
.wb-b-right{font-size:15px;color:var(--good,var(--good));text-align:center;word-break:break-word}
.wb-src{font-size:13px;opacity:.8}
.wb-del{background:none;border:none;color:var(--mut);cursor:pointer;font-size:15px;line-height:1;flex:none;
  min-width:34px;min-height:34px;opacity:.55}
.wb-del:hover{color:var(--err);opacity:1}
.wb-say{background:none;border:1px solid transparent;color:var(--accent2);font-size:16px;cursor:pointer;line-height:1;
  flex:none;min-width:44px;min-height:44px;display:flex;align-items:center;justify-content:center;transition:opacity .15s}
.wb-say:hover{border-color:var(--line)}
.wb-say.busy{opacity:.45}
.wb-say.mute{opacity:.3}
.wb-say.big{min-width:60px;min-height:60px;font-size:24px;border-color:var(--line);margin:2px 0}
/* Сегодняшняя порция. Число на кнопке ограничено — растущего долга пользователь не видит никогда. */
.wb-go{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;width:100%;min-height:60px;
  padding:11px 14px;margin-bottom:12px;border:none;cursor:pointer;font:inherit;text-align:center;
  background:linear-gradient(135deg,var(--accent),var(--accent2));color:#3a1a2c}
.wb-go b{font-size:16px;font-weight:800;letter-spacing:.01em}
.wb-go small{font-size:11px;opacity:.78}
.wb-go:hover{filter:brightness(1.06)}
.wb-alldone{border:1px solid var(--line);background:var(--panel);padding:11px 13px;margin-bottom:12px;text-align:center}
.wb-alldone b{display:block;font-size:15px;color:var(--good)}
.wb-alldone small{font-size:11px;color:var(--mut)}
.wb-chip{display:inline-flex;align-items:center;min-height:36px;padding:6px 11px;margin-bottom:10px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--accent2);color:var(--accent2);font:inherit;font-size:13px}
.wb-dir{display:flex;gap:0;margin-bottom:10px;border:1px solid var(--line)}
.wb-dir button{flex:1;min-height:44px;background:none;border:none;color:var(--mut);font:inherit;font-size:13px;
  font-weight:600;cursor:pointer;padding:6px 4px}
.wb-dir button.on{background:var(--panel2);color:var(--accent2)}
.wb-empty-btn{display:block;margin:16px auto 0;min-height:44px}
/* Повторение */
.wb-bar{height:4px;background:var(--panel2);overflow:hidden}
.wb-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent2));
  transform-origin:left center;transition:transform .3s ease}
.wb-bar.sm{height:3px}
.wb-rev{display:flex;flex-direction:column;align-items:center;gap:12px;padding:4px 0 10px}
.wb-rev .wb-bar{width:100%;margin-bottom:10px}
.wb-rev-back{flex:0 0 auto!important;padding:12px 14px!important;color:var(--mut)!important;min-height:44px}
.wb-rev-count{margin-left:auto;align-self:center;padding-right:14px;font-size:13px;color:var(--mut)}
.wb-rev-mode{font-size:11px;letter-spacing:.06em;text-transform:lowercase;color:var(--mut)}
.wb-hardtag{color:var(--gold)}
.wb-rev-q{font-size:29px;font-weight:700;line-height:1.25;text-align:center;color:var(--ink);word-break:break-word}
.wb-rev-tr{font-size:13px;color:var(--mut);margin-top:-6px}
.wb-rev-a{min-height:54px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font-size:20px;color:var(--accent2);text-align:center;line-height:1.3;word-break:break-word}
.wb-rev-a span{font-size:13px;color:var(--mut)}
.wb-rev-a.ghost{visibility:hidden}
.wb-rev-from{font-size:11px;color:var(--mut);margin-top:-6px}
.wb-rev-btns{display:flex;gap:9px;width:100%}
.wb-rev-btns button{flex:1;min-height:52px;font:inherit;font-size:15px;font-weight:600;cursor:pointer;
  background:var(--panel2);border:1px solid var(--line);color:var(--ink);padding:10px}
.wb-rev-btns .wb-no{color:var(--mut)}
.wb-rev-btns .wb-no:hover{border-color:var(--err);color:var(--err)}
.wb-rev-btns .wb-yes,.wb-rev-btns .wb-show{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#3a1a2c;border-color:transparent}
.wb-rev-btns .wb-yes:hover,.wb-rev-btns .wb-show:hover{filter:brightness(1.06)}
.wb-fin{text-align:center;padding:26px 8px}
.wb-fin-n{font-family:var(--f-display,inherit);font-size:34px;font-weight:800;color:var(--accent2)}
.wb-fin-h{font-size:15px;color:var(--ink);margin-top:6px}
.wb-fin-sub{font-size:13px;color:var(--mut);margin-top:6px;line-height:1.5}
.wb-fin-btn{margin:18px auto 0;min-height:48px;min-width:140px}
/* Разобранные песни */
.wb-song{display:flex;flex-direction:column;gap:8px;background:var(--panel);border:1px solid var(--line);padding:11px 12px}
.wb-song-t b{display:block;font-size:15px;color:var(--ink);line-height:1.3}
.wb-song-t small{font-size:11px;color:var(--mut)}
.wb-song-n{font-size:11px;color:var(--mut)}
.wb-song-btns{display:flex;gap:8px}
.wb-song-btns button{flex:1;min-height:44px;background:var(--panel2);border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:13px;cursor:pointer;padding:8px}
.wb-song-btns button:hover:not([disabled]){border-color:var(--accent2);color:var(--accent2)}
.wb-song-btns button[disabled]{opacity:.4;cursor:default}
.wb-song-btns button.on{border-color:var(--accent2);color:var(--accent2)}
/* ===== «Залатай строку»: песня как задание ===== */
.rcp-quiz{width:100%;justify-content:center;margin:0}
.sq{display:flex;flex-direction:column;gap:12px}
.sq-h{font-size:15px;font-weight:700;color:var(--ink);display:flex;align-items:center;gap:8px}
.sq-say{flex:0 0 auto}
.sq-line{border-left-color:var(--accent2)}
.sq-gap .tok-k{color:var(--accent2);letter-spacing:.05em}
.sq-gap .tok-r{color:var(--champ,#f3d9ac)}
.sq-was .tok-k{color:var(--accent2)}
.sq-s{font-size:15px;line-height:1.5;color:var(--muted,#a99cc0);margin:0}
.sq-opt{display:flex;flex-direction:column;align-items:center;gap:2px;line-height:1.2}
.sq-opt b{font-size:16px;font-weight:700}
.sq-opt i{font-size:13px;font-style:normal;color:var(--mut);opacity:.9}
.sq-opt.correct i,.sq-opt.wrong i{color:inherit}
.sq-fix{margin-bottom:10px}
.sq-mean{font-size:13px;color:var(--muted,#a99cc0);margin:8px 0 0}
.sq-mean b{color:var(--ink)}
/* Разбор песни в тетради: то же объяснение «слова порознь ≠ фраза вместе», но без
   спешки — песня уже отзвучала, читать можно сколько угодно. */
.wb-an{display:flex;flex-direction:column;gap:10px;margin-top:4px}
.wb-anv{border-left:2px solid var(--line);padding-left:10px}
.wb-anv-h{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--champ,#f3d9ac);margin-bottom:5px}
.wb-an-tr{font-size:13px;line-height:1.5;color:var(--ink);margin:0 0 8px}
.wb-an-c{margin-bottom:8px}
.wb-an-cs{font-size:13px;color:var(--mut);margin-bottom:3px}
.wb-an-cb{font-size:13px;line-height:1.55;color:var(--muted,#a99cc0);margin:0;background:rgba(243,217,172,.07);
  border:1px solid rgba(243,217,172,.2);padding:8px 10px}
.wb-an-lit,.wb-an-why{font-size:13px;line-height:1.5;color:var(--muted,#a99cc0);margin:8px 0 0}
.wb-an-none{font-size:13px;color:var(--mut);margin:0}
/* Подвкладки открытой песни: «Смысл» / «Слушать слова» (Вариант 2, 25.07) */
.wb-subtabs{display:flex;gap:0;border:1px solid var(--line);margin:2px 0 12px}
.wb-subtabs button{flex:1;min-height:42px;background:none;border:0;color:var(--mut);font:inherit;font-size:13px;font-weight:600;cursor:pointer;border-bottom:2px solid transparent}
.wb-subtabs button+button{border-left:1px solid var(--line)}
.wb-subtabs button.on{background:var(--panel2);color:var(--accent2);border-bottom-color:var(--accent2)}
.wb-sw-list{display:flex;flex-direction:column;gap:6px}
.wb-sw{display:flex;align-items:center;gap:10px;background:var(--panel2);border:1px solid var(--line);padding:8px 10px}
.wb-sw-t{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px}
.wb-sw-t b{color:var(--ink);font-size:17px;font-weight:600}
.wb-sw-t i{color:var(--champ,#f3d9ac);font-size:12px;font-style:normal}
.wb-sw-t span{color:var(--mut);font-size:13px;flex-basis:100%}
.wb-sw-add{flex:0 0 auto;width:42px;min-height:42px;background:var(--panel);border:1px solid var(--line);color:var(--accent2);font:inherit;font-size:18px;cursor:pointer}
.wb-sw-add:hover:not([disabled]){border-color:var(--accent2)}
.wb-sw-add.in{color:var(--good,#7fe8c9);border-color:var(--good,#7fe8c9);opacity:.7;cursor:default}
@media(max-width:400px){
  .wb-rev-q{font-size:25px}
  .wb-dir button{font-size:11px}
  .wb-tab{padding:12px 6px;font-size:13px}
  .wb-go b{font-size:15px}
}
/* Тап-цель озвучки — 44x44 везде, где она встречается (было 39x22, и таких
   кнопок на экране урока восемь подряд). Ряд не ломается: кнопка остаётся
   inline-flex по центру строки и не растягивается. */
.say{margin-left:auto;align-self:center;display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;background:none;border:1px solid var(--line);color:var(--accent2);
  font-size:15px;cursor:pointer;padding:3px 9px;line-height:1;flex-shrink:0}
.say:hover{border-color:var(--accent2)}
.wb-empty{text-align:center;color:var(--dim,#a394bd);font-size:13px;padding:28px 12px;line-height:1.5}

/* ===== РАЗБОР ПЕСНИ ===== */
.song-intro{font-size:13px;line-height:1.5;color:var(--muted,#a99cc0);margin-bottom:12px}
.song-search{width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--ink);font:inherit;font-size:16px;padding:11px 13px;margin-bottom:14px}
.song-search:focus{outline:none;border-color:var(--accent2)}
.song-search-hint{font-size:11px;color:var(--dim,#a394bd);margin:-8px 0 14px;line-height:1.35}
.song-search-wrap{position:relative;z-index:6;margin-bottom:14px}
.song-search-wrap .song-search{margin-bottom:0}
.song-dropdown{position:absolute;left:0;right:0;top:100%;background:rgba(23,16,31,.98);border:1px solid var(--accent2);border-top:none;max-height:56vh;overflow-y:auto;z-index:30;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);padding:6px}
.song-dropdown:empty{display:none}
.song-dropdown .song-item{margin-bottom:4px}
.song-none{text-align:center;color:var(--dim,#a394bd);font-size:13px;padding:22px 12px;line-height:1.5}
.song-online-h{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--champ,#f3d9ac);margin:16px 0 8px}
.song-none.warn{color:#e0b46a}
.song-item.add .lsn-badge{color:var(--accent2)}
.song-item.add:disabled{opacity:.5}
.song-vfoot{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:8px}
.song-botnote{font-size:11px;color:var(--dim,#a394bd);line-height:1.35}
.song-reload,.song-vfoot .song-yt{flex:1;text-align:center;justify-content:center;white-space:nowrap;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);color:var(--mut,#c7b3da);font:inherit;font-size:13px;font-weight:600;padding:9px 10px;cursor:pointer;text-decoration:none;display:flex;align-items:center;justify-content:center;gap:5px}
.song-reload:hover,.song-vfoot .song-yt:hover{border-color:var(--accent2);color:var(--accent2)}
/* .song-sync удалён 25.07 вместе с ручной подгонкой заливки (forced alignment). */
.song-fail{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:18px;font-size:13px;line-height:1.5;color:var(--mut,#c7b3da);background:var(--panel,#1E1629)}
.song-item{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);color:var(--ink);padding:12px 14px;cursor:pointer;transition:border-color .15s,color .15s,transform .15s;margin-bottom:8px}
.song-item:hover{border-color:var(--accent2);transform:translateX(2px)}
.song-item.done{border-color:rgba(127,232,201,.38)}
.song-item.done .lsn-badge{color:var(--good)}
.song-top{position:sticky;top:0;z-index:3;background:var(--bg2);padding-bottom:10px;margin:-2px 0 4px}
#ytStage{padding:12px 18px 8px;border-bottom:1px solid var(--line);background:var(--bg2);transition:padding .25s}
.song-video{position:relative;width:100%;padding-bottom:56.25%;background:#000;border:1px solid var(--line);transition:width .25s,height .25s}
/* Клип НЕ сворачивается в маленький прямоугольник. Раньше при старте он скакал с
   полной ширины на 170x96 — Сармат видел это как «открывается нормально, потом
   становится маленьким», и официальное видео в таком окне не посмотреть. Теперь
   размер один и тот же всё время: полная ширина, 16:9, без прыжка. Строки идут под
   клипом и скроллятся. При игре убираем только подсказку «тапни, чтобы включить» —
   она больше не нужна; кнопка подгонки заливки (song-vfoot) остаётся доступной. */
#ytStage.compact{padding:8px 18px 6px}
#ytStage.compact .yt-hint{display:none!important}
.song-video iframe,.song-video>#ytPlayer{position:absolute;inset:0;width:100%;height:100%;border:0}
.yt-err{position:absolute;inset:0;z-index:2;background:rgba(16,11,24,.94);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;text-align:center;padding:16px}
.yt-err-msg{font-size:15px;color:var(--txt);max-width:280px;line-height:1.4}
.yt-hint{text-align:center;font-size:13px;color:var(--accent,#e8a9c9);padding:8px 10px;font-weight:600}
.song-yt{display:inline-block;font-size:13px;color:var(--accent2);text-decoration:none;margin:-8px 0 12px}
.song-yt:hover{text-decoration:underline}
.song-teacher-note{font-size:13px;color:var(--dim,#a394bd);margin-bottom:14px}
.song-lines{display:flex;flex-direction:column;gap:12px;margin-bottom:14px}
.song-line{background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:12px 14px}
.sl-kr{font-size:20px;font-weight:700;color:var(--ink);line-height:1.4}
.sl-rom{font-size:13px;color:var(--dim,#a394bd);font-style:italic;margin-top:2px}
.sl-tr{font-size:15px;color:var(--muted,#a99cc0);margin-top:6px}
.sl-note{font-size:13px;line-height:1.5;color:var(--muted,#a99cc0);margin-top:8px;background:rgba(243,217,172,.07);border:1px solid rgba(243,217,172,.2);padding:9px 11px}
.sl-save{margin-top:10px;background:none;border:1px solid var(--accent2);color:var(--accent2);font:inherit;font-size:13px;padding:6px 12px;cursor:pointer;transition:.12s}
.sl-save:hover{background:rgba(240,168,204,.13)}
.sl-save.on{border-color:var(--good);color:var(--good);cursor:default}
.song-ctrl{margin-top:4px}
.song-next{width:100%;justify-content:center;margin-left:0}

/* ===== КАРАОКЕ-РАЗБОР ===== */
.kara-hint{font-size:11px;color:var(--dim,#a394bd);margin:10px 0 14px;line-height:1.4}
.kara-lines{display:flex;flex-direction:column;gap:0;margin-bottom:14px}
/* Группа «строка + её смысл». Скролл ведёт СЮДА, поэтому оба слоя всегда в кадре
   одновременно — ради этого обещания продукт и существует.
   КАЖДАЯ СТРОКА ПЕСНИ — ОТДЕЛЬНАЯ КАРТОЧКА (правка 25.07): три яруса слова плюс смысл
   сливались со следующей строкой. Теперь между строками разделительная полоса и отступ,
   чтобы блок читался как единое целое и не путался с соседним. */
.kgrp{display:flex;flex-direction:column;gap:var(--s2);padding:14px 0;border-bottom:1px solid var(--line)}
.kgrp:last-child{border-bottom:none}
.kline{display:flex;flex-wrap:wrap;gap:8px 22px;justify-content:flex-start;padding-left:11px;border-left:2px solid var(--line);transition:border-color var(--d-slow) var(--ease),opacity var(--d-slow) var(--ease)}
/* «готовящаяся» строка в проигрыше: показана заранее, подсвечен край — но слова НЕ закрашены */
.kline.upcoming{border-left-color:var(--accent)}
.tok{display:flex;flex-direction:column;align-items:flex-start;gap:2px;transition:transform var(--d-base) var(--ease);line-height:1.15}
.tok.on{transform:scale(1.04)}
/* ИЕРАРХИЯ СЛОЁВ. Хангыль — главный слой экрана и самый крупный кегль продукта
   (26px/1.35): человек пришёл прочитать корейскую строчку, а не транскрипцию.
   Транскрипция и значение — подпорки на 13 и 11px.
   ЦВЕТ РАБОТАЕТ КАК НАВИГАЦИЯ, а не как украшение:
     не спетое  — --lyr-idle, 60% яркости;
     поётся     — --lyr-active, чистый белый, единственное максимально контрастное
                  пятно на экране, глаз ведётся ровно по нему;
     спетое     — --lyr-past, 50%; ниже 50% опускаться нельзя, это уже за нормой.
   Раньше заливка шла --accent2 (шампань) и по яркости почти совпадала с не спетым
   текстом, поэтому фронт пения читался хуже, чем должен. */
.tok-k{font-size:26px;font-weight:600;color:var(--lyr-idle);line-height:1.35;letter-spacing:-.005em}
.tok-r{font-size:13px;font-weight:450;color:var(--dim)}
.tok-m{font-size:11px;color:var(--dim);opacity:.9}
/* Заливка слова по мере пропевания. Поверх приглушённого текста лежит его же копия
   (::after + data-txt), обрезанная по --fill через clip-path.
   Ни width, ни height не анимируются — лейаут не дёргается, кадр остаётся плавным. */
/* pre-wrap (не pre): длинный токен/фраза переносится, а не уходит за правый край и обрезается.
   overflow-wrap:anywhere ломает и цельное длинное слово (транскрипция на «·») как крайний случай.
   ::after-клон несёт тот же текст, ту же ширину и тот же перенос — оверлей заливки совпадает построчно. */
.tok-k,.tok-r{position:relative;display:block;white-space:pre-wrap;overflow-wrap:anywhere;max-width:100%}
.tok-k::after,.tok-r::after{content:attr(data-txt);position:absolute;left:0;top:0;width:100%;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--lyr-active);-webkit-clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);pointer-events:none}
.tok-r::after{color:var(--mut)}
.tok.done{--fill:100%}
/* Спетое слово гаснет до 50% — но только когда фронт пения ушёл со строки целиком,
   иначе только что спетое слово темнело бы прямо под текущим и рвало строку. */
.kgrp:not(:has(.tok.on)) .tok.done .tok-k::after{color:var(--lyr-past)}
.tok.on .tok-m{color:var(--mut);opacity:1}
/* Строка, которая поётся не по-корейски. В k-pop таких половина, и раньше их просто
   не показывали — экран уверенно врал, что сейчас звучит корейская строка, а заливка
   тянулась через выброшенный кусок. Теперь строка на месте и держит ритм, но кегль
   вдвое меньше и цвет тише: учить в ней нечего, глазу не за что цепляться. */
.kgrp.foreign .kline{border-left-color:transparent}
.kgrp.foreign .tok-k{font-size:15px;font-weight:450;color:var(--dim)}
.kgrp.foreign .tok-k::after{color:var(--mut)}
/* ─── ТРИ РАВНЫХ ЯРУСА (Сармат, 25.07): каждое слово = хангыль / транскрипция / дословный
   глосс, ОДНОГО размера, по центру, каждый своим цветом; заливка = тот же цвет темнее.
   Под рядом слов остаётся смысловой перевод всей строки (.ksl). Область строго .kara-lines —
   квиз (.sq-line) и демо на лендинге (.lp-card) делят те же классы .tok/.ksl и НЕ меняются. ─── */
.kara-lines .tok{align-items:center;text-align:center;gap:3px;max-width:100%;flex-shrink:0}   /* flex-shrink:0 + max-width:100% — токен целиком переносится между словами (flex-wrap), а если ОДИН шире всей строки — упирается в 100% и ломается внутри, не вылезая за экран */
.kara-lines .tok-k{font-size:20px;font-weight:600;color:var(--lyr-k);line-height:1.28}   /* оригинал (хангыль) */
.kara-lines .tok-r{font-size:20px;font-weight:600;color:var(--lyr-r);line-height:1.28}   /* транскрипция — вровень с хангылем, её и читают, чтобы петь */
.kara-lines .tok-m{position:relative;display:block;white-space:pre-wrap;overflow-wrap:anywhere;max-width:100%;font-size:16px;font-weight:450;color:var(--lyr-m);line-height:1.28;opacity:1}  /* дословный глосс — третий ярус, чуть меньше */
.kara-lines .tok-k::after{color:var(--lyr-k-fill)}
.kara-lines .tok-r::after{color:var(--lyr-r-fill)}
/* Третий ярус тоже заливается: копия текста поверх (data-txt), обрезка по --fill. */
.kara-lines .tok-m::after{content:attr(data-txt);position:absolute;left:0;top:0;width:100%;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--lyr-m-fill);-webkit-clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);pointer-events:none}
/* Спетое слово = свой цвет темнее и в активной строке, и в прошедшей (в серое не гасим). */
.kara-lines .kgrp:not(:has(.tok.on)) .tok.done .tok-k::after{color:var(--lyr-k-fill)}
/* Смысл всей строки — СВОЙ слой (мята --lyr-s), отдельный от пословного глосса (циан --lyr-m);
   заливка тем же цветом темнее (розовый акцент боевого правила заглушён). */
.kara-lines .ksl-t{color:var(--lyr-s)}
.kara-lines .ksw::after{color:var(--lyr-s-fill)}
.kara-lines .ksl.on .ksw::after{color:var(--lyr-s-fill)}
.kara-lines .ksl.done .ksw::after{color:var(--lyr-s-fill)}
.kara-lines .ksl.on{border-left-color:var(--lyr-s)}
/* Foreign-строка (поётся не по-корейски): все три яруса мельче и тише — учить нечего. */
.kara-lines .kgrp.foreign .tok-k,.kara-lines .kgrp.foreign .tok-r,.kara-lines .kgrp.foreign .tok-m{font-size:14px;font-weight:450;color:var(--dim)}
.kara-lines .kgrp.foreign .tok-k::after,.kara-lines .kgrp.foreign .tok-r::after,.kara-lines .kgrp.foreign .tok-m::after{color:var(--mut)}
/* Панель куплета больше не несёт построчный смысл (он под строками) — она уехала под
   сгиб и стала тихой: рамка по --line, а не акцентная, иначе пустая коробка внизу
   кричит громче самого текста песни. */
.kara-pause{background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:14px;margin-bottom:12px}
.kp-h{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--champ,#f3d9ac);margin-bottom:8px}
.kp-tr{font-size:15px;line-height:1.5;color:var(--ink);margin-bottom:10px}
.kp-note{font-size:13px;line-height:1.5;color:var(--muted,#a99cc0);background:rgba(243,217,172,.07);border:1px solid rgba(243,217,172,.2);padding:9px 11px;margin-bottom:10px}
.kp-tr.kp-dim{color:var(--mut,#c7b3da);font-style:italic}
/* Смысловой перевод, заливаемый по ходу песни. Заливка идёт ПОСЛОВНО (каждое слово —
   свой clip-path), поэтому длинная фраза корректно переносится на несколько строк:
   у цельного абзаца обрезка по правому краю дала бы вертикальную полосу вместо чтения. */
.kp-slines{display:flex;flex-direction:column;gap:9px;margin-bottom:10px}
/* Смысл строки стоит ПОД своей строкой, с тем же левым отступом — визуально это
   продолжение строки, а не отдельный блок. */
.kgrp .ksl{margin-left:11px;padding-left:11px;border-left:2px solid transparent}
/* Перевод — 15px/1.45: заметно мельче строки песни (26px), но это всё ещё текст
   для чтения, а не подпись. Разрыв в кегле и есть иерархия: сперва читается
   корейская строка, следом её смысл. */
.kgrp .ksl-t{font-size:15px;line-height:1.45}
.ksl{padding-left:10px;border-left:2px solid var(--line);transition:border-color var(--d-slow) var(--ease)}
.ksl.on{border-left-color:var(--accent)}
.ksl.done{border-left-color:var(--line-strong)}
.ksl-row{display:flex;align-items:flex-start;gap:8px}
.ksl-t{flex:1;font-size:15px;line-height:1.45;color:var(--lyr-idle)}
.ksw{position:relative;display:inline-block;white-space:pre}
.ksw::after{content:attr(data-txt);position:absolute;left:0;top:0;white-space:pre;color:var(--ink);
  -webkit-clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);pointer-events:none}
/* Единственное место экрана песни, где вообще появляется цветной акцент —
   смысл ТОЙ САМОЙ строки, которая звучит прямо сейчас. */
.ksl.on .ksw::after{color:var(--accent)}
.ksl.done .ksw::after{color:var(--lyr-past)}
.ksl-c{flex:0 0 32px;width:32px;height:32px;background:none;border:1px solid var(--line);color:var(--champ,#f3d9ac);
  font-size:13px;line-height:1;padding:0;cursor:pointer;transition:border-color .14s,background-color .14s}
.ksl-c:hover,.ksl-c.on{border-color:var(--accent2);background:rgba(240,168,204,.13)}
.ksl-cb{font-size:13px;line-height:1.55;color:var(--muted,#a99cc0);margin:8px 0 0;background:rgba(243,217,172,.07);
  border:1px solid rgba(243,217,172,.2);padding:9px 11px}
/* «Дословно ≠ по смыслу» — свёрнуто по умолчанию: во время проигрывания читать некогда,
   но именно здесь объясняется, почему сумма слов не равна смыслу фразы. */
.kp-sense{margin-bottom:10px}
.kp-sense-t{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;background:none;border:1px solid var(--line);color:var(--champ,#f3d9ac);font:inherit;font-size:13px;font-weight:600;text-align:left;padding:10px 12px;cursor:pointer;transition:border-color .14s,color .14s}
.kp-sense-t:hover{border-color:var(--accent2);color:var(--accent2)}
.kp-caret{font-size:11px;opacity:.85}
.kp-sense-b{border:1px solid var(--line);border-top:none;padding:12px}
.kp-lit,.kp-why{font-size:13px;line-height:1.55;color:var(--muted,#a99cc0);margin:0}
.kp-why{margin-top:12px;color:var(--ink)}
.kp-tag{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--mut,#c7b3da);margin-bottom:3px}
.kp-allwords{display:block;width:100%;min-height:44px;background:none;border:1px solid var(--accent2);color:var(--accent2);font:inherit;font-size:13px;font-weight:600;padding:11px;cursor:pointer;transition:background-color .14s}
.kp-allwords:hover{background:rgba(240,168,204,.13)}

/* ===== Конец песни: набор всех слов по куплетам ===== */
.rcp{display:flex;flex-direction:column;gap:16px}
.rcp-head{border-bottom:1px solid var(--line);padding-bottom:12px}
.rcp-h{font-size:16px;font-weight:700;color:var(--ink);line-height:1.3}
.rcp-sub{font-size:13px;color:var(--muted,#a99cc0);margin-top:4px}
.rcp-v{background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:12px}
.rcp-vh{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.rcp-vn{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--champ,#f3d9ac)}
.rcp-all{min-height:44px;background:none;border:1px solid var(--accent2);color:var(--accent2);font:inherit;font-size:13px;font-weight:600;padding:8px 12px;cursor:pointer;white-space:nowrap;transition:background-color .14s}
.rcp-all:hover{background:rgba(240,168,204,.13)}
.rcp-all:disabled{border-color:rgba(127,232,201,.5);color:var(--good);cursor:default;background:none}
.rcp-tr{font-size:13px;line-height:1.5;color:var(--muted,#a99cc0);margin:0 0 10px}
.rcp-words{display:flex;flex-direction:column}
.rcp-w{display:flex;align-items:center;gap:10px;min-height:48px;padding:4px 0;border-top:1px solid var(--line)}
.rcp-w:first-child{border-top:none}
.rcp-add{width:44px;height:44px;flex:0 0 44px;background:none;border:1px solid var(--accent2);color:var(--accent2);font:inherit;font-size:20px;line-height:1;padding:0;cursor:pointer;transition:background-color .14s}
.rcp-add:hover{background:rgba(240,168,204,.13)}
.rcp-add:disabled{border-color:rgba(127,232,201,.5);color:var(--good);cursor:default;background:none}
.rcp-txt{flex:1 1 auto;min-width:0}
.rcp-k{display:block;font-size:16px;font-weight:700;color:var(--ink);overflow-wrap:anywhere}
.rcp-r{display:block;font-size:13px;font-style:normal;color:var(--muted,#a99cc0);overflow-wrap:anywhere}
.rcp-m{flex:0 1 42%;font-size:13px;color:var(--muted,#a99cc0);text-align:right;overflow-wrap:anywhere}
.rcp-w.on .rcp-k{color:var(--muted,#a99cc0)}
.rcp-none{font-size:13px;color:var(--muted,#a99cc0);padding:14px 0}
.rcp-foot{display:flex;flex-direction:column;gap:8px;padding-bottom:10px}
.rcp-back{min-height:44px;background:none;border:1px solid var(--line);color:var(--muted,#a99cc0);font:inherit;font-size:13px;padding:11px;cursor:pointer;transition:border-color .14s,color .14s}
.rcp-back:hover{border-color:var(--accent2);color:var(--accent2)}
/* «Готово» стало второстепенным: главное действие после набора слов — залатать строки. */
.rcp-done{min-height:44px;background:none;border:1px solid var(--line);color:var(--muted,#a99cc0);font:inherit;
  font-size:13px;padding:11px;cursor:pointer;justify-content:center;margin-left:0;text-align:center;
  transition:border-color .14s,color .14s}
.rcp-done:hover{border-color:var(--accent2);color:var(--accent2)}
@media (max-width:380px){
  .rcp-m{flex-basis:38%;font-size:13px}
  .rcp-k{font-size:15px}
}
.kp-ctrl{display:flex;gap:8px}
.kp-btn{flex:1;justify-content:center;margin-left:0;padding:11px;font-size:15px;text-align:center}
.kp-btn.ghost{background:none;border:1px solid var(--line);color:var(--muted,#a99cc0);cursor:pointer}
.kp-btn.ghost:hover{border-color:var(--accent2);color:var(--accent2)}
.kara-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:14px;margin-top:4px}
.kara-syncbtn{display:flex;align-items:center;gap:7px;background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);color:var(--muted,#a99cc0);font:inherit;font-size:13px;font-weight:600;padding:9px 14px;cursor:pointer;transition:.14s}
.kara-syncbtn:hover{border-color:var(--accent2);color:var(--accent2)}
.kara-toggle{display:flex;align-items:center;gap:9px;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;user-select:none}
.tgl{position:relative;width:44px;height:26px;flex-shrink:0}
.tgl input{opacity:0;width:0;height:0;position:absolute}
/* Тумблер квадратный, как всё в интерфейсе (правило 90°): дорожка и бегунок без
   скругления. Состояние читается заливкой дорожки и положением бегунка, форма
   ту же роль не несёт. */
.tgl i{position:absolute;inset:0;background:var(--bg-3);border:1px solid var(--line);transition:background-color var(--d-base) var(--ease),border-color var(--d-base) var(--ease)}
.tgl i::before{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;background:var(--mut);transition:transform var(--d-base) var(--ease),background-color var(--d-base) var(--ease)}
.tgl input:checked + i{background:linear-gradient(135deg,var(--accent),var(--accent2));border-color:transparent}
.tgl input:checked + i::before{transform:translateX(18px);background:#3a1a2c}

/* ===== ОНБОРДИНГ ===== */
.onb-card{position:relative;background:var(--bg2);border:1px solid var(--accent2);width:min(88vw,420px);max-height:86vh;overflow-y:auto;padding:24px 20px 20px;box-shadow:var(--sh-2)}
.onb-x{position:absolute;top:10px;right:12px}
.onb-title{font-family:var(--f-ui);font-size:20px;font-weight:800;letter-spacing:-.01em;color:var(--accent2);margin-bottom:16px;padding-right:24px}
.onb-rows{display:flex;flex-direction:column;gap:13px;margin-bottom:20px}
/* ПАМЯТКА ПЕРЕРОСЛА ЭКРАН (29.07, после переписывания текста: строк стало семь,
   и две из них в три-четыре ряда). Прокрутка у карточки была и раньше, но
   уезжали в неё именно КНОПКИ — человек видел список без единого действия и
   без намёка, что ниже что-то есть. Теперь прокручивается только список, а
   «Показать по экрану» и «Понятно» приколоты ко дну карточки.
   :has() нужен, потому что класс .onb-card носит и модалка мессенджеров —
   у неё своих .onb-actions нет, и ей прокрутка нужна по-старому, целиком. */
.onb-card:has(.onb-actions){display:flex;flex-direction:column;overflow:hidden}
.onb-card:has(.onb-actions) .onb-body{display:flex;flex-direction:column;min-height:0;flex:1 1 auto}
.onb-card:has(.onb-actions) .onb-rows{flex:1 1 auto;min-height:0;overflow-y:auto;
  margin-bottom:0;padding-bottom:16px;-webkit-overflow-scrolling:touch}
.onb-card:has(.onb-actions) .onb-actions{flex:none;padding-top:14px;
  border-top:1px solid var(--line)}
.onb-row{display:flex;gap:12px;align-items:flex-start;font-size:15px;line-height:1.45;color:var(--ink)}
.onb-ic{font-size:20px;flex-shrink:0;line-height:1.2}
.onb-actions{display:flex;flex-direction:column;gap:8px}
.onb-tour{width:100%;justify-content:center;margin-left:0}
.onb-ok{width:100%;background:none;border:1px solid var(--line);color:var(--muted,#a99cc0);font:inherit;font-size:15px;padding:11px;cursor:pointer}
.onb-ok:hover{border-color:var(--accent2);color:var(--accent2)}
.onb-help{align-self:flex-end;display:inline-flex;align-items:center;gap:6px;margin-bottom:-6px;
  padding:6px 11px;background:transparent;border:1px solid var(--gold);color:var(--gold);
  font-family:var(--f-display);font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  cursor:pointer;line-height:1;transition:color .15s,border-color .15s,background-color .15s}
.onb-help::before{content:"?";display:inline-flex;align-items:center;justify-content:center;
  width:16px;height:16px;border:1px solid var(--gold);font-family:var(--f-serif);font-style:italic;font-size:11px;font-weight:700}
.onb-help:hover{background:var(--gold);color:#241436;border-color:var(--gold)}
.onb-help:hover::before{border-color:#241436}
/* В гримёрке справка была громче имени айдола: золотая рамка, капс, Unbounded, 199x32 над
   всем экраном. Стала тихой кнопкой «?» в углу портрета — 44x44, без золота.
   --gold в этом продукте значит «награда», а не «справка». */
/* Правка 24.07: серый квадрат 44x44 с «?» поверх портрета читался как незагрузившийся
   элемент, а не как справка. Тап-цель осталась 44x44 (она обязательна), но видимой
   стала мягкая круглая накладка 28px — понятный жест «подсказка», а не дырка в макете. */
.home .onb-help{position:absolute;top:10px;right:10px;z-index:2;width:44px;height:44px;padding:0;margin:0;
  align-self:auto;justify-content:center;gap:0;background:none;border:none;color:var(--ink);font-size:0}
.home .onb-help::before{width:28px;height:28px;border-radius:50%;font-size:15px;line-height:1;color:inherit;
  border:1px solid rgba(246,241,250,.42);background:rgba(16,11,24,.62);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background-color .15s,border-color .15s}
.home .onb-help:hover{background:none}
.home .onb-help:hover::before{background:rgba(16,11,24,.94);border-color:var(--ink)}
.home{position:relative}

/* гид-подсветка */
.tour-layer{position:fixed;inset:0;z-index:80;display:none}
.tour-layer.on{display:block}
/* 23.07: раньше здесь ехали четыре геометрических свойства сразу (позиция и размеры)
   на элементе с box-shadow радиусом 9999px — перерисовка затемнения всего экрана каждый кадр.
   Геометрию ставит positionTour() в app.js, переписать её на transform отсюда нельзя,
   поэтому анимируется только opacity: подсветка гасится и зажигается на новом месте. */
.tour-hole{position:absolute;border-radius:10px;box-shadow:0 0 0 9999px rgba(9,6,15,.80);transition:opacity .2s ease;pointer-events:none}
.tour-tip{position:absolute;max-width:min(84vw,300px);background:var(--bg2);border:1px solid var(--accent2);padding:14px 16px;box-shadow:var(--sh-2)}
.tt-text{font-size:15px;line-height:1.45;color:var(--ink);margin-bottom:12px}
.tt-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
.tt-row span{font-size:13px;color:var(--dim,#a394bd)}
.tt-next{margin-left:0;padding:8px 18px;font-size:15px}
.result{background:var(--bg2);border:1px solid var(--line);max-width:460px;width:100%;overflow:hidden}
.result .rv{aspect-ratio:9/16;background:#000;position:relative;max-height:70vh}
.result video{width:100%;height:100%;object-fit:contain;background:#000}
.result .load{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:30px;text-align:center}
.spinner{width:44px;height:44px;border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.load p{color:var(--mut);font-size:15px;line-height:1.5}.load .big{color:var(--ink);font-weight:700;font-size:16px}
.load .steps{display:flex;gap:8px;margin-top:4px}
.load .steps span{padding:4px 10px;font-size:11px;border:1px solid var(--line);color:var(--dim)}
.load .steps span.done{color:var(--good);border-color:var(--good)}
.load .steps span.active{color:var(--accent);border-color:var(--accent2)}
.result .rb{padding:18px 20px}
.result .rb h3{font-size:20px;font-weight:800}
.result .rb p{color:var(--mut);font-size:13px;margin-top:4px;line-height:1.5}
.result .racts{display:flex;gap:10px;margin-top:16px}.result .racts .btn{flex:1;padding:12px;font-size:15px}
.err{background:rgba(255,84,112,.1);border:1px solid rgba(255,84,112,.35);color:#ffb0c1;padding:14px;font-size:13px;line-height:1.5}
.note{background:rgba(63,224,197,.07);border:1px solid rgba(63,224,197,.25);color:#9deee0;padding:12px 15px;font-size:13px;line-height:1.5;margin-top:14px}
footer{border-top:1px solid var(--line);margin-top:50px;padding:26px 0;text-align:center;color:var(--dim);font-size:13px;line-height:1.6}
footer b{color:var(--accent)}
@media(max-width:900px){.step-ind{display:none}}
@media(max-width:640px){
  .hbar{gap:7px 8px}
  .navtabs{gap:5px;margin-left:0}
  .navtab{padding:8px 11px;font-size:13px}
  .lang-sel{margin-left:0;font-size:13px;padding:6px 8px}
  .auth-area{gap:6px;margin-left:auto}
  .btn.sm{padding:8px 12px;font-size:13px}
}
@media(max-width:420px){
  .logo{font-size:13px;letter-spacing:.12em}
  .navtab{padding:7px 9px;font-size:13px}
  .lang-sel{font-size:11px;padding:5px 7px}
  .btn.sm{padding:7px 9px;font-size:11px}
  .hbar{gap:6px 6px}
}
.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(20px);background:var(--panel2);border:1px solid var(--gold);
  color:var(--ink);padding:12px 22px;font-size:13px;font-weight:700;opacity:0;pointer-events:none;transition:.25s;z-index:80;box-shadow:var(--sh-2)}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

/* ===== ЧАРТ (Зал славы) ===== */
.chart-hero{text-align:center;padding:44px 0 8px}
/* 23.07: заливка по контуру букв убрана (AI-tell, правило gradient-text детектора).
   Сплошной --accent2 даёт 13.70:1 на --bg против плавающих 4-9:1 у трёх точек градиента. */
.chart-hero .eyebrow{display:inline-block;font-family:var(--f-tech);font-size:16px;font-weight:700;letter-spacing:.32em;
  color:var(--accent2)}
.chart-hero h1{font-family:var(--f-serif);font-weight:800;font-size:clamp(30px,5vw,46px);margin-top:16px}
.chart-hero p{color:var(--mut);font-size:15px;margin-top:10px}
.podium-wrap{max-width:900px;margin:40px auto 0}
.podium-label{text-align:center;font-family:var(--f-tech);font-size:11px;letter-spacing:.3em;color:var(--gold);margin-bottom:20px}
.podium{display:grid;grid-template-columns:1fr 1.18fr 1fr;gap:16px;align-items:end}
.p-col{display:flex;flex-direction:column}
.p-card{background:linear-gradient(180deg,rgba(38,29,51,.66),rgba(30,22,41,.66));backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.08);padding:18px 14px 20px;text-align:center;
  position:relative;cursor:pointer;transition:.2s}
.p-card:hover{transform:translateY(-4px)}
.p-card[data-rank="1"]{padding-top:30px;border-color:var(--gold);box-shadow:0 0 0 1px rgba(217,164,65,.3),0 25px 60px -20px rgba(217,164,65,.35)}
.p-card[data-rank="2"]{border-color:var(--silver)}
.p-card[data-rank="3"]{border-color:var(--bronze)}
.p-card .laurel{width:30px;height:30px;margin:0 auto 6px}
/* Настоящие ступени подиума — разной высоты, вместо плоской рамки-таблички вокруг всего блока */
.step{text-align:center;font-family:var(--f-serif);font-weight:800;letter-spacing:.15em;
  background:linear-gradient(180deg,rgba(255,255,255,.05),transparent);border:1px solid var(--line);border-top-width:3px;
  display:flex;align-items:flex-start;justify-content:center;padding-top:10px}
.step[data-rank="1"]{height:66px;border-top-color:var(--gold);color:var(--gold);font-size:22px}
.step[data-rank="2"]{height:46px;border-top-color:var(--silver);color:var(--silver);font-size:16px}
.step[data-rank="3"]{height:32px;border-top-color:var(--bronze);color:var(--bronze);font-size:15px}
.p-card .ph{width:100%;aspect-ratio:1;margin-bottom:12px;position:relative}
.p-card .ph .ph-inner{width:100%;height:100%;overflow:hidden}
.p-card[data-rank="1"] .ph .ph-inner{outline:3px solid var(--gold);outline-offset:3px}
.p-card[data-rank="2"] .ph .ph-inner{outline:2px solid var(--silver);outline-offset:2px}
.p-card[data-rank="3"] .ph .ph-inner{outline:2px solid var(--bronze);outline-offset:2px}
.p-card img{width:100%;height:100%;object-fit:cover}
.p-card .num{position:absolute;top:8px;left:8px;font-family:var(--f-serif);font-weight:800;font-size:20px;
  width:32px;height:32px;display:flex;align-items:center;justify-content:center;color:#2a1608}
.p-card[data-rank="1"] .num{background:linear-gradient(135deg,#ffe9b0,var(--gold));font-size:24px;width:38px;height:38px}
.p-card[data-rank="2"] .num{background:linear-gradient(135deg,#e7ecef,var(--silver))}
.p-card[data-rank="3"] .num{background:linear-gradient(135deg,#e8b489,var(--bronze))}
.p-card .nm{font-weight:800;font-size:15px}
.p-card .owner{color:var(--dim);font-size:11px;margin-top:2px}
.p-card .votes{margin-top:10px;font-family:var(--f-serif);font-weight:800;color:var(--gold);font-size:15px}
.p-card .votes span{color:var(--dim);font-family:"Segoe UI",sans-serif;font-weight:400;font-size:11px}
.tier-div{display:flex;align-items:center;gap:14px;margin:34px 0 14px;color:var(--gold);font-size:13px;font-weight:700;letter-spacing:.2em;text-transform:uppercase}
.tier-div::before,.tier-div::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,transparent,var(--line),transparent)}
.tier-sub{color:var(--dim);font-size:11px;text-transform:none;letter-spacing:0;font-weight:400;margin:-10px 0 14px}
.row{display:flex;align-items:center;gap:16px;background:rgba(30,22,41,.60);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.07);padding:12px 16px;margin-bottom:8px;cursor:pointer;transition:border-color .15s,background-color .15s}
.row:hover{border-color:var(--accent2)}
.row .rnum{font-family:var(--f-serif);font-weight:800;font-size:20px;color:var(--mut);width:30px;text-align:center;flex:none}
.row .rph{width:48px;height:48px;object-fit:cover;flex:none}
.row .rinfo{flex:1;min-width:0}
.row .rinfo b{font-size:15px}
.row .rinfo .sub{color:var(--dim);font-size:11px;margin-top:1px}
.row .rvotes{font-weight:800;color:var(--gold);font-size:15px;flex:none;text-align:right}
.row .rvotes small{display:block;color:var(--dim);font-weight:400;font-size:11px;text-transform:uppercase;letter-spacing:.08em}
.row.hot .rvotes{color:var(--holo2)}
.chart-cta{text-align:center;border:1px dashed var(--line);padding:30px 20px;margin:40px 0 10px}
.chart-cta p{color:var(--mut);font-size:15px;margin-bottom:14px}

/* ===== ЛИЧНЫЙ КАБИНЕТ / ПРОДАКШН ===== */
.cab{max-width:1080px;margin:0 auto;padding:40px 20px}
.cab-back{color:var(--dim);font-size:13px;background:none;border:0;font:inherit;cursor:pointer;margin-bottom:18px;display:inline-flex;align-items:center;gap:6px}
.cab-back:hover{color:var(--ink)}
.cab-top{display:flex;gap:26px;align-items:stretch;flex-wrap:wrap}
.cab-ph{width:180px;height:180px;flex:none;position:relative}
.cab-ph .ph-inner{width:100%;height:100%;overflow:hidden;outline:1px solid var(--line);outline-offset:8px}
.cab-ph img{width:100%;height:100%;object-fit:cover}
.cab-info{flex:1 1 380px;min-width:280px;max-width:420px}
.cab-bio{flex:1 1 260px;min-width:240px;background:var(--panel);border:1px solid var(--line);padding:16px 18px;display:flex;flex-direction:column}
.bio-h{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--mut);font-weight:700;margin-bottom:10px}
.bio-text{flex:1;background:transparent;border:0;color:var(--ink);font:inherit;font-size:13px;line-height:1.65;resize:none;width:100%;min-height:180px}
textarea.bio-text{outline:none}
textarea.bio-text::placeholder{color:var(--dim)}
div.bio-text{color:var(--mut)}
.train-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.rest-note{color:var(--dim);font-size:11px}
.cab-info .h2row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.cab-info h2{font-family:var(--f-serif);font-size:28px;font-weight:800}
.cab-owner{color:var(--dim);font-size:13px;margin-top:4px}
.cab-badges{display:flex;gap:10px;margin-top:12px;flex-wrap:wrap}
.badge{display:flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line);padding:6px 13px;font-size:13px;font-weight:700}
.badge.streak{color:var(--accent2);border-color:rgba(255,179,71,.4)}
.badge.league{color:var(--gold);border-color:rgba(217,164,65,.4)}
.badge.support{color:#e8d16a;border-color:rgba(232,209,106,.4)}
/* Мгновенный публичный отклик на голос — большая, но короткая вспышка, не спамим ей других зрителей */
.vote-blast{position:fixed;inset:0;z-index:90;display:none;align-items:center;justify-content:center;
  background:rgba(9,6,15,.80);backdrop-filter:blur(4px);cursor:pointer}
.vote-blast.show{display:flex}
.vote-blast .vb-card{text-align:center;padding:40px 34px;background:linear-gradient(180deg,rgba(38,29,51,.94),rgba(21,15,30,.96));
  border:1px solid var(--gold);max-width:380px;animation:vbPop .35s ease}
@keyframes vbPop{0%{transform:scale(.85);opacity:0}100%{transform:scale(1);opacity:1}}
.vote-blast .vb-fire{font-size:44px;margin-bottom:14px}
.vote-blast h3{font-family:var(--f-serif);font-size:22px;margin-bottom:10px}
.vote-blast p{color:var(--mut);font-size:15px;line-height:1.5}
.vote-blast b{color:var(--gold)}
.fan-path{margin-top:18px;max-width:420px;background:var(--panel);border:1px solid var(--line);padding:12px 15px}
.fp-h{display:flex;justify-content:space-between;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--mut);font-weight:700;margin-bottom:7px}
.fp-h b{color:#e8d16a;text-transform:none;letter-spacing:0;font-size:13px}
.fp-note{color:var(--dim);font-size:11px;margin-top:6px}
.top-supporter{margin-top:10px;max-width:420px;font-size:13px;color:var(--mut);background:var(--panel);border:1px solid var(--line);padding:10px 14px}
.top-supporter b{color:var(--gold)}
.vote-pulse{margin-top:10px;color:var(--dim);font-size:13px}
.live-card{display:flex;gap:14px;background:var(--panel);border:1px solid var(--line);padding:14px;margin-bottom:10px}
.live-card img{width:80px;height:80px;object-fit:cover;flex:none}
.live-body{flex:1}
.live-kind{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);font-weight:700;margin-bottom:6px}
.live-body p{font-size:13px;font-style:italic;color:var(--ink);margin-bottom:10px;line-height:1.5}
.awards{margin-top:16px;display:flex;gap:10px;flex-wrap:wrap;max-width:460px}
.award-tile{width:108px;text-align:center;background:linear-gradient(180deg,rgba(217,164,65,.1),transparent);
  border:1px solid rgba(217,164,65,.45);padding:12px 8px 10px}
.award-tile .award-ic{display:block;margin:0 auto 8px}
.award-tile b{display:block;color:var(--gold);font-size:13px;font-family:var(--f-serif)}
.award-tile .lbl{color:var(--mut);font-size:11px;line-height:1.35;margin-top:3px}
.award-tile.comet{border-color:rgba(201,169,255,.45);background:linear-gradient(180deg,rgba(201,169,255,.1),transparent)}
.award-tile.comet b{color:var(--holo2)}
.award-tile.diamond{border-color:rgba(159,216,255,.45);background:linear-gradient(180deg,rgba(159,216,255,.1),transparent)}
.award-tile.diamond b{color:var(--holo3)}
.stat{margin-top:20px;max-width:420px}
.stat-h{display:flex;justify-content:space-between;font-size:13px;color:var(--mut);margin-bottom:6px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.stat-h b{color:var(--ink)}
.bar{height:9px;background:var(--panel2);border:1px solid var(--line);overflow:hidden}
/* 23.07: анимация ширины полосы снята. Ширину ставит supportTierHtml() один раз, в момент
   вставки узла в DOM, с нуля она никогда не едет — переход не успевал сработать ни разу,
   но заставлял браузер пересчитывать layout полосы. */
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent2))}
.cab-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}
.train-note{color:var(--dim);font-size:11px;margin-top:8px;max-width:420px;line-height:1.5}
.cab-empty{padding:20px 0 0}
.cab-empty p{color:var(--mut);font-size:15px;margin-bottom:18px}
/* ===== Первый экран: живое демо разбора ===== */
.hd-eyebrow{font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--champ,#f3d9ac);margin-bottom:8px}
.hd-sub{max-width:34em}
.hd{background:var(--panel,rgba(52,38,78,.42));border:1px solid var(--line);padding:14px;margin-bottom:4px;min-height:150px}
.hd-src{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--mut);margin-bottom:10px}
.hd-line{margin-bottom:12px;border-left-color:var(--accent2)}
.hd .ksl{border-left-color:var(--line)}
.hd .ksl.on{border-left-color:var(--accent2)}
.hd-c{font-size:13px;line-height:1.55;color:var(--muted,#a99cc0);margin:12px 0 0;background:rgba(243,217,172,.07);
  border:1px solid rgba(243,217,172,.2);padding:9px 11px;opacity:0;transform:translateY(4px);
  transition:opacity .35s ease,transform .35s ease}
.hd-c.on{opacity:1;transform:none}
.hd-foot{font-size:13px;color:var(--mut);text-align:center;margin-top:12px}
@media(prefers-reduced-motion:reduce){.hd-c{transition:none}}
.port-h{font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--mut);margin:30px 0 12px;font-weight:700;display:flex;align-items:center;gap:10px}
.port-h .cnt{color:var(--dim);font-weight:400;text-transform:none;letter-spacing:0;font-size:11px}
.port-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:10px}
.port-grid img{width:100%;aspect-ratio:1;object-fit:cover;border:1px solid var(--line)}
.port-empty{border:1px dashed var(--line);color:var(--dim);font-size:13px;padding:22px;text-align:center;line-height:1.6}
.dbnote{margin-top:26px;color:var(--dim);font-size:11px;border-top:1px dashed var(--line);padding-top:14px;line-height:1.6}

/* ===== ЛЕНТА ПОДПИСОК — вертикальные карточки-посты, как в Instagram, не строчки ===== */
.lenta-hero{text-align:center;padding:44px 0 20px}
.lenta-hero h1{font-family:var(--f-serif);font-weight:800;font-size:clamp(28px,5vw,42px)}
.lenta-hero p{color:var(--mut);font-size:15px;margin-top:10px}
.lenta-col{max-width:460px;margin:0 auto}
.lenta-item{background:rgba(30,22,41,.60);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.07);margin-bottom:22px}
.lenta-item .li-owner{display:flex;align-items:center;gap:10px;padding:12px 14px}
.lenta-item .li-owner img{width:34px;height:34px;object-fit:cover;flex:none}
.lenta-item .li-owner b{font-size:13px}
.lenta-item .li-owner .who{color:var(--dim);font-size:11px}
.lenta-item .li-photo{width:100%;aspect-ratio:4/5;overflow:hidden}
.lenta-item .li-photo img{width:100%;height:100%;object-fit:cover}
.lenta-item .li-body{padding:12px 14px 16px}
.lenta-item .li-body .kind{color:var(--gold);font-size:11px;text-transform:uppercase;letter-spacing:.12em;font-weight:700;margin-bottom:4px}
.lenta-item .li-body .sub{color:var(--mut);font-size:13px;margin-top:2px}
.lenta-empty{border:1px dashed var(--line);color:var(--dim);padding:40px 20px;text-align:center;font-size:13px;line-height:1.7}
.lenta-teaser{position:relative;max-height:75vh;min-height:420px;overflow:hidden}
.lenta-blur{filter:blur(7px);opacity:.5;pointer-events:none;user-select:none}
.lenta-lock{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:20px}
.lenta-lock-box{background:rgba(16,11,24,.94);border:1px solid var(--line);padding:30px 34px;text-align:center;max-width:360px;backdrop-filter:blur(4px)}
.lenta-lock-box .ll-h{font-family:var(--f-serif);font-size:20px;margin-bottom:10px}
.lenta-lock-box p{color:var(--mut);font-size:13px;line-height:1.6;margin-bottom:18px}

/* ===== ЛЕНДИНГ ГОСТЯ: демо-куплет до регистрации =====
   Гость видит товар раньше, чем у него что-то просят: три слоя строки
   (хангыль / как звучит / что значит) и заливка по мере пропевания.
   Компоненты переиспользованы из разбора песни (.kline/.tok/.ksl) — новых
   караоке-примитивов не заводим, иначе демо разойдётся с продуктом. */
.lp{padding:var(--s4) 20px 40px;max-width:640px}
.lp-eyebrow{font-size:11px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-bottom:var(--s2)}
/* Заголовок 28px: та же ступень шкалы, что и «Гримёрка». Playfair снят — серифный
   заголовок рядом с хангылем читался как чужая гарнитура. */
.lp-h{font-size:clamp(28px,7.2vw,34px);line-height:1.12;font-weight:800;letter-spacing:-.02em}
.lp-sub{color:var(--mut);font-size:16px;line-height:1.45;margin-top:var(--s2)}
.lp-card{margin-top:var(--s4);background:var(--bg-2);border:1px solid var(--line);padding:var(--s4) 14px}
.lp-src{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--accent2);margin-bottom:10px}
.lp-vid{position:relative;width:100%;padding-bottom:56.25%;background:#000;border:1px solid var(--line);margin-bottom:12px}
.lp-vid>div,.lp-vid iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
/* Куплет целиком, как на экране песни. min-height держит высоту до старта:
   без него карточка прыгает, когда строки получают подсветку. */
/* Значения на светлую тему — копия инлайновых из learn.html: витрина обязана
   выглядеть как экран песни в ОБЕИХ темах. Для тёмной их перебивает theme-dark.css. */
:root{
  --ls-kr:#A8703A;   --ls-kr-sung:#5A2E00;
  --ls-tr:#566076;   --ls-tr-sung:#0A0E16;
  --ls-mean:#1E6E96; --ls-mean-sung:#05303F;
}
.lp-lines{min-height:128px}
/* Дорожка видна ДО старта: пустая полоса цветом --line на панели сливалась с фоном,
   и человек не понимал, что у куплета вообще есть длина и конец. */
.lp-prog{height:4px;background:rgba(246,241,250,.14);border:1px solid var(--line);margin-top:12px;overflow:hidden}
.lp-prog i{display:block;height:100%;background:var(--accent2);transform-origin:left;transform:scaleX(0)}
.lp-ctrl{margin-top:12px}
.lp-play{width:100%;justify-content:center;min-height:52px;font-size:15px;margin-left:0}
.lp-note{color:var(--mut);font-size:13px;margin-top:8px;text-align:center;line-height:1.4}
.lp-wait{color:var(--mut);font-size:13px;text-align:center;padding:12px 0 2px}
/* Итог куплета: сперва ценность («ты прочитал N слов»), и только потом просьба */
/* ТИЗЕР ДО ПЕРВОГО ТАПА, 02.08.2026. Своего markup не заводит: hd, kline,
   tok, ksl, hd-c — классы героического демо гримёрки (см. app.js
   startHeroDemo, lpTeaser), тизер гостя переиспользует их как есть. */
.lp-done{text-align:center}
.lp-done-n{font-family:var(--f-display);font-size:38px;font-weight:800;color:var(--accent2);line-height:1}
.lp-done-h{font-size:15px;color:var(--ink);margin-top:7px;line-height:1.4}
.lp-words{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin:13px 0 2px}
.lp-w{display:flex;flex-direction:column;align-items:center;gap:1px;background:var(--panel2);border:1px solid var(--line);padding:6px 9px;line-height:1.2;min-width:44px}
.lp-w b{font-size:15px;font-weight:700;color:var(--ink)}
.lp-w i{font-size:11px;font-style:normal;color:var(--mut)}
/* Раскрытие плитки по тапу (правка Сармата 29.07) — та же механика, что подвкладка
   «Слова» на экране песни. Классы свои (lp-), а не ls-: инлайн-стили learn.html
   с теми же именами не должны пересекаться с витриной. Разбор встаёт отдельной
   строкой под рядом плиток за счёт flex-basis:100%. */
.lp-w[data-wi]{cursor:pointer}
.lp-w[data-wi]:focus-visible{outline:2px solid var(--accent2);outline-offset:2px}
.lp-w.open{background:var(--bg-4);border-color:var(--ls-kr)}
/* Круглая сноска с пальцем слева от раскрытого образца: правило одно на всех,
   плюс на каждой плитке раздувал квадратики (правка Сармата 30.07). */
.lp-hint{display:inline-flex;align-items:center;gap:4px;align-self:center;max-width:180px;
  border:1px dashed var(--line);border-radius:999px;background:var(--panel2);
  color:var(--mut);font-size:11px;line-height:1.3;padding:6px 12px;text-align:left}
.lp-hint i{font-style:normal;font-size:15px;line-height:1}
.lp-brk{flex-basis:100%;background:var(--panel2);border:1px solid var(--line);padding:var(--s3);margin-top:2px}
.lp-brk-row{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s4);align-items:flex-end;justify-content:center}
.lp-sy{display:inline-flex;align-items:flex-end;gap:2px}
.lp-sy b{color:var(--ls-kr);font-size:19px;font-weight:700;line-height:1}
.lp-sy u,.lp-brk-row u{color:var(--dim);text-decoration:none;font-size:12px;padding:0 1px;line-height:1.4}
.lp-j{display:inline-flex;flex-direction:column;align-items:center;font-style:normal;color:var(--ls-tr);font-size:17px;font-weight:600;cursor:pointer;padding:2px 3px}
.lp-j em{font-style:normal;font-size:10.5px;font-weight:600;color:var(--ls-mean);margin-top:2px}
.lp-j.mute{opacity:.38}
.lp-j.on{background:var(--bg-4)}
.lp-brk-tip{color:var(--mut);font-size:12px;line-height:1.45;margin-top:var(--s2);min-height:1px;text-align:center}
.lp-brk-tip b{color:var(--ls-tr);font-size:14px}
.lp-save{width:100%;justify-content:center;min-height:52px;margin:14px 0 0;font-size:15px}
.lp-more{display:flex;gap:8px;margin-top:10px}
/* «Ещё раз» и «Выбрать песню» (правка Сармата 29.07: были «сильно пресно»).
   Тот же металл, что у шапки и главной кнопки, но приглушённый — второй план:
   пилюля, тёмный металл с бликом сверху, главная золотая кнопка остаётся главной. */
.lp-ghost{flex:1;min-height:48px;font:inherit;font-size:13.5px;font-weight:700;letter-spacing:.02em;
  color:var(--ink);cursor:pointer;border-radius:999px;padding:10px 12px;
  border:1px solid rgba(255,255,255,.28);
  background:linear-gradient(180deg,rgba(255,255,255,.16) 0%,rgba(255,255,255,.05) 45%,rgba(255,255,255,.11) 55%,rgba(255,255,255,.03) 100%);
  box-shadow:0 1px 0 rgba(255,255,255,.25) inset,0 -1px 0 rgba(0,0,0,.25) inset,0 4px 14px rgba(23,32,56,.20);
  transition:filter .14s,transform .1s,border-color .14s}
.lp-ghost:hover{filter:brightness(1.12);border-color:var(--accent2)}
.lp-ghost:active{transform:translateY(1px)}
/* Надпись кнопки — тот же ребристый металл, что у «Выбрать своего айдола», с бликом
   по шрифту (правка Сармата 30.07: кнопки после перекраски оставались незаметными). */
@supports(-webkit-background-clip:text){
  .lp-ghost-t{background:linear-gradient(180deg,#FFFFFF 0%,#D7DEEA 36%,#FFFFFF 50%,#B7C1D2 62%,#8F9AB0 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.4))}
}
/* Под демо — следующий шаг, а не настройка (язык живёт в шапке иконкой). Кнопка
   нарочно тише, чем «Слушать первый куплет»: сперва человек должен услышать товар,
   и две одинаково яркие кнопки подряд гасили бы главную. */
/* Колонкой: под кнопкой стоит закрытая витрина айдолов, в строку они не встают. */
.lp-lang{display:flex;flex-direction:column;margin-top:16px}
/* КНОПКА АЙДОЛА — ИЗ ТОГО ЖЕ МЕТАЛЛА, ЧТО ШАПКА (правка Сармата 28.07: «кнопка
   некрасивая, сделай хромом, как верхняя плашка»). Раньше это была тонкая рамка
   на пустом месте — рядом с металлической кнопкой «Открыть всю песню» она
   читалась как черновик. Форма, рост и блик — те же, что у главных кнопок;
   цвет — холодный хром, поэтому две главные кнопки не спорят: тёплая ведёт в
   песню, холодная — к айдолу. */
.lp-getidol{width:100%;min-height:52px;font:inherit;font-size:15px;font-weight:700;letter-spacing:.02em;
  display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:999px;
  color:#1B2233;border:1px solid rgba(255,255,255,.35);
  background:linear-gradient(180deg,#F4F6FA 0%,#D7DEEA 42%,#FFFFFF 50%,#C9D2E0 58%,#AAB4C6 100%);
  box-shadow:0 1px 0 rgba(255,255,255,.75) inset,0 -1px 0 rgba(0,0,0,.18) inset,0 8px 22px rgba(23,32,56,.28);
  transition:filter var(--d-fast,140ms) var(--ease,ease),transform var(--d-fast,140ms) var(--ease,ease)}
.lp-getidol:hover{filter:brightness(1.06)}
.lp-getidol:active{transform:translateY(1px)}
/* Закрытая витрина: лица настоящие, но размыты. Замок — поверх сетки. */
.lp-faces{position:relative;display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:10px}
.lp-face{display:block;aspect-ratio:1/1;background-size:cover;background-position:center;
  filter:blur(7px) saturate(1.15) brightness(.82);border:1px solid var(--line);border-radius:10px}
.lp-face.empty{background:var(--bg-3);filter:none}
.lp-faces-lock{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  text-align:center;padding:0 14px;font-size:13px;font-weight:600;line-height:1.35;
  color:#F6F1FA;text-shadow:0 1px 6px rgba(0,0,0,.75);
  background:radial-gradient(120% 80% at 50% 50%,rgba(16,11,24,.20),rgba(16,11,24,.62));border-radius:10px}
@media(max-width:400px){.lp-faces{grid-template-columns:repeat(4,1fr);gap:5px}}
.lp-foot{color:var(--mut);font-size:13px;line-height:1.5;margin-top:16px;text-align:center}
@media(max-width:400px){
  .lp{padding:16px 14px 32px}
  .lp-card{padding:11px}
  .lp-lines{min-height:116px}
  .lp-done-n{font-size:34px}
}

/* ===== ШАПКА: минус лишнее, тап-цели 44px =====
   Было: 5 управляющих элементов, ни один не ведёт к продукту, самый заметный —
   селектор языка в золотой рамке. Гостю вкладки вести некуда (гримёрки у него
   ещё нет), поэтому у гостя их нет вовсе — заодно исчезает врущее «активно». */
/* Боковые поля 12px на ВСЕХ ширинах (правка Сармата 29.07): раньше ноль стоял везде,
   кроме экранов до 420px, и на 430px (его телефон) знак прижимался к левому краю,
   а кнопки — к правому. Эти 12px плюс 6px у знака и у правой группы дают
   одинаковые отступы с обеих сторон. */
.hbar{gap:4px 8px;min-height:52px;padding:4px 12px 10px}
body.guest .navtabs{display:none}
.navtab{min-height:44px;display:inline-flex;align-items:center}
.hbar .btn.sm{min-height:44px;display:inline-flex;align-items:center}
/* Два margin-left:auto в одной flex-строке (у .lang-wrap и .auth-area) съедали
   всё свободное место и ломали шапку на две строки даже там, где всё влезало.
   Автоотступ оставлен ровно один — правая группа едет вправо целиком. */
.logo{flex:none;display:inline-flex;align-items:center;min-height:44px}
.auth-area{margin-left:0}
/* Подпись селектора остаётся для скринридера, но перестаёт быть самым громким
   элементом первого экрана. Сам селектор — нейтральная рамка, не золотая. */
/* ЯЗЫК — ИКОНКА 44x44, правка 24.07.
   Развёрнутый селектор (текст «🇷🇺 Русский» в рамке) съедал полстроки, шапка вставала
   в две строки высотой 100px, и из-за этого главная кнопка «Понять песню» упиралась
   в сгиб, а на узком экране уходила за него. Свёрнут в одну тап-цель 44x44: сам
   <select> лежит поверх прозрачным (родной список ОС открывается как обычно и
   рисуется системой, прозрачность на него не влияет), видим только глобус. */
.lang-wrap{gap:0;margin-left:auto;position:relative;flex:0 0 44px;width:44px;height:44px}
.lang-cap{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.lang-sel{position:absolute;inset:0;width:100%;height:100%;min-height:44px;opacity:0;padding:0;border:0;cursor:pointer;-webkit-appearance:none;appearance:none}
/* «文A» вместо глобуса-эмодзи: эмодзи рисуется системным цветным шрифтом и на тёмной
   шапке становится самым ярким пятном — ровно то, от чего уходили. Знак монохромный,
   узнаваемый как переключатель языка и живёт в той же типографике, что и логотип. */
.lang-ico{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:700;line-height:1;letter-spacing:.02em;border:1px solid var(--line);color:var(--mut);pointer-events:none;transition:border-color .14s,color .14s}
.lang-wrap:hover .lang-ico,.lang-sel:focus-visible+.lang-ico{border-color:var(--accent2)}
/* Шапка встаёт в одну строку на телефоне: логотип + вкладки + язык + «Выйти».
   Кнопки ужимаем по горизонтали, но не по высоте — 44px остаются.
   @username убран: на первом экране имя аккаунта ничего не решает, а занимало
   столько же, сколько сама кнопка выхода, и утаскивало шапку на вторую строку. */
@media(max-width:480px){
  .hbar .btn.sm{padding:9px 11px;font-size:13px}
  .auth-user b{display:none}
}
@media(max-width:420px){
  /* Шапке отдаём поля страницы: 40px горизонтального воздуха — это ровно та разница,
     из-за которой «Выйти» не помещалось и уезжало на вторую строку. */
  header .wrap.hbar{padding-inline:12px;gap:4px 6px}
  .logo{font-size:13px;letter-spacing:.12em}
  .logo b{padding:3px 5px 2px 6px;letter-spacing:.1em}
  .navtab{padding:7px 7px;font-size:13px}
  .hbar .btn.sm{padding:9px 8px;font-size:13px}
}
/* 320px: логотип + две вкладки + язык + «Выйти» в одну строку не помещаются даже
   после сжатия — не хватает около 10px, и добирать их пришлось бы кеглем 11px или
   снятием рамок с вкладок. Читаемость дороже: на 320 шапка честно встаёт в две
   строки (101px), но главная кнопка при этом всё равно выше сгиба — замер
   на 320x760: «Понять песню» в 596..685. Одна строка гарантирована с 390px. */
@media(max-width:360px){
  header .wrap.hbar{padding-inline:10px}
}

/* ============================================================================
   СЛОЙ ВИЗУАЛЬНОГО ЯЗЫКА — добавлено 24.07.2026.
   Стоит в конце файла намеренно: собирает разрозненные компоненты выше к трём
   общим правилам, не переписывая каждое правило поштучно.
   ============================================================================ */

/* --- 1. Размытие только над однородным фоном, НИКОГДА под текстом песни ------
   Стекло красиво на панели поверх портрета и поверх затемнения, но под строкой
   на хангыле оно съедает тонкие штрихи чамо — а именно их человек и учит
   различать. Поэтому у контейнеров разбора песни и демо гостя стекло снимаем
   явно: любая будущая правка выше по файлу не сможет вернуть его молча. */
.lesson-body,.kara-lines,.kgrp,.kline,.ksl,.lp-lines,.lp-card,.song-line,.kara-pause{
  -webkit-backdrop-filter:none;backdrop-filter:none}

/* --- 2. Глубина осветлением, а не свечением --------------------------------
   Пять ступеней поверхности (--bg-0..--bg-4) плюс честная тень. Цветных ореолов
   в файле не осталось; --glow-accent объявлен в :root, но применяется только
   там, где элемент обязан «звучать» (сейчас — нигде, это резерв). */
.card,.coll,.closeness,.idol-hero,.lesson-box,.chat-box,.onb-card,.tour-tip{box-shadow:var(--sh-2)}
.lsn-item,.song-item,.wb-row,.wb-song,.lsn-stat,.hm-sec,.connect-row{box-shadow:var(--sh-1)}
/* Наведение и активное состояние — ступень вверх по поверхности. */
.lsn-item:hover:not(:disabled),.song-item:hover,.lq-opt:hover,.hm-tile:hover,
.wb-seed:hover,.connect-row:hover,.wb-chip-w:hover:not([disabled]){background:var(--bg-4)}

/* --- 3. Движение: одна кривая и три длительности ----------------------------
   --ease — быстрый выход, мягкое приземление. Всё, что осталось на безымянных
   .15s/.18s, приводим к шкале, чтобы интерфейс двигался как одно целое. */
.opt,.gtab,.navtab,.tile,.btn,.lsn-item,.song-item,.lq-opt,.hm-tile,.wb-stat,
.connect-link,.connect-row,.wb-seed,.lsn-ask,.kp-sense-t,.ksl-c,.say,.sub-link,
.premium-link,.prem-go,.prem-cancel{
  transition-duration:var(--d-fast);transition-timing-function:var(--ease)}
.card,.p-card,.coll-grid img{transition-duration:var(--d-base);transition-timing-function:var(--ease)}

/* --- 4. Ритм текста ---------------------------------------------------------
   Кегли ниже 11px в файле не встречаются (проверено скриптом): 11 — подпись,
   13 — вторичная подпись, 15 — вторичный текст и перевод строки, 16 — основной,
   20 — подзаголовок, 26 — строка песни, 28 — заголовок экрана. */
h1,h2,h3,.pick-h,.lp-h,.cab-info h2{letter-spacing:-.02em;text-wrap:balance}
.cab-info h2{font-size:28px}
.idol-name{font-size:20px;letter-spacing:-.01em}
.chat-b{font-size:16px;line-height:1.45}

/* ============================================================================
   ГЛОБАЛЬНЫЙ СЛОЙ ДОСТУПНОСТИ — добавлено 23.07.2026.
   Блок держится в конце файла намеренно: он должен перебивать любые точечные
   outline:none в компонентах выше. Компонентные классы отсюда не переопределяются,
   кроме .tgl — там фокусируемый input имеет нулевой размер и кольцо рисовать не на чем.
   ============================================================================ */

/* --- 1. Видимый фокус с клавиатуры ---------------------------------------
   До 23.07 в файле не было ни одного :focus-visible, зато было восемь
   объявлений outline:none — навигация с клавиатуры шла вслепую.
   Кольцо двойное: тёмный контур вплотную к элементу отделяет его от заливки
   (иначе на светлых кнопках .btn.accent и .navtab.on золотое кольцо пропадает),
   поверх — светлое кольцо 3px. Контраст кольца к тёмному фону 15.6:1,
   тёмного разделителя к кольцу — тоже 15.6:1. Порог для нетекстовых
   элементов 3:1, запас четырёхкратный.
   !important нужен: outline:none в компонентах имеет специфичность 0,2,1,
   а :focus-visible — 0,1,0, без него правило не срабатывает. */
:root{--focus-ring:#ffe9a8;--focus-halo:var(--bg-0)}
:focus-visible{
  outline:3px solid var(--focus-ring)!important;
  outline-offset:2px!important;
  box-shadow:0 0 0 2px var(--focus-halo)!important;
}
/* Мышь и тач не должны видеть кольцо — только клавиатура. */
:focus:not(:focus-visible){outline:none}
/* Скрытый чекбокс тумблера: сам input имеет нулевой размер, кольцо рисуем на подложке. */
.tgl input:focus-visible{outline:none!important;box-shadow:none!important}
.tgl input:focus-visible + i{
  outline:3px solid var(--focus-ring);outline-offset:2px;box-shadow:0 0 0 2px var(--focus-halo)}

/* --- 2. Уважение к prefers-reduced-motion --------------------------------
   24.07: бесконечных холо-заливок (AI-бейдж, рамка портрета) в файле больше нет —
   они сняты вместе с радужным градиентом, а не просто заглушены. Осталось три
   цикла: точки «печатает…» в чате и в тизере и спиннер загрузки. Они гасятся
   здесь до неподвижного состояния, а не просто ускоряются: мигающая точка при
   1ms — это стробоскоп, ровно то, от чего человек и включал режим.
   Ниже — общий предохранитель на всё остальное: любые будущие анимации
   и переходы схлопываются, скролл перестаёт быть плавным. */
@media (prefers-reduced-motion:reduce){
  .dm-typing i,.chat-typing i,.spinner{animation:none!important;opacity:.6!important;transform:none!important}
  .tok,.tok.on{transform:none!important}
  *,*::before,*::after{
    animation-duration:1ms!important;
    animation-iteration-count:1!important;
    transition-duration:1ms!important;
    scroll-behavior:auto!important;
  }
  html{scroll-behavior:auto!important}
}

/* Голосовое от айдола. Плеер узкий: пузырь не должен распирать ленту на телефоне,
   поэтому ширина ограничена и внутри чата, и в тизере на главной. */
.chat-voice{display:flex;flex-direction:column;gap:6px;max-width:min(78vw,320px)}
.chat-voice audio{width:100%;height:34px;display:block}
.chat-voice-t{font-size:.92em;opacity:.85;line-height:1.4}

/* ============================ ПОДДЕРЖКА, 26.07 ============================
   Вход в поддержку и окно переписки. Скруглений нет (правило проекта — только 90°),
   свечения нет, поверхности — ступени --bg-*.

   ПИЛЮЛЯ ВНИЗУ, а не «пузырь чата». Отличие принципиальное: пузырь висит поверх
   продукта всегда и на мобиле перекрывает то, по чему человек пытается тапнуть —
   именно за это его забраковали юзабилити-тесты [Baymard, 15.10.2019]. Наша пилюля
   лежит НИЖЕ оверлеев (z-index 50 против 60 у .ov), поэтому на плотных экранах —
   разбор песни, урок, тетрадь, чат — её физически нет, и перекрыть она там ничего
   не может. Там работают свои входы: «?» в шапке разбора и ссылка в подвале.
   На узком экране остаётся один знак вопроса: подпись съедала бы место у контента. */
.help-fab{
  position:fixed;z-index:50;
  right:calc(14px + env(safe-area-inset-right,0px));
  bottom:calc(14px + env(safe-area-inset-bottom,0px));
  display:inline-flex;align-items:center;gap:8px;
  min-height:44px;padding:0 14px;
  background:var(--bg-3);border:1px solid var(--line-strong);color:var(--mut);
  font:inherit;font-size:13px;font-weight:600;cursor:pointer;
  box-shadow:var(--sh-1);transition:color .15s,border-color .15s,background .15s;
}
.help-fab:hover,.help-fab:focus-visible{background:var(--bg-4);border-color:var(--accent2);color:var(--accent2)}
.help-fab .hf-ic{
  display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;flex:0 0 20px;
  border:1px solid currentColor;font-size:12px;font-weight:800;line-height:1;
}
/* Есть непрочитанный ответ. Точка, а не число: обращений у одного человека одно,
   считать нечего, а цифра «1» на кнопке читается как непрочитанная реклама. */
.help-fab .hf-dot{
  position:absolute;top:-4px;right:-4px;width:10px;height:10px;
  background:var(--brand);border:1px solid var(--bg-0);
}
.help-fab[data-unread="1"]{border-color:var(--accent);color:var(--ink)}
/* Пилюля не должна перекрывать плашку про неполный перевод языка (#langNote, bottom 12px)
   и тост. Тост уходит по центру, плашка — на всю ширину, поэтому поднимаем пилюлю,
   пока плашка на экране. */
body:has(#langNote) .help-fab{bottom:calc(96px + env(safe-area-inset-bottom,0px))}

/* «?» в шапке разбора песни и других оверлеев. 44x44 — минимальная цель тапа. */
.help-mini{
  min-width:44px;min-height:44px;flex:0 0 44px;
  display:inline-flex;align-items:center;justify-content:center;
  background:none;border:1px solid var(--line);color:var(--dim);
  font:inherit;font-size:14px;font-weight:800;cursor:pointer;margin-left:auto;
}
.help-mini:hover,.help-mini:focus-visible{border-color:var(--accent2);color:var(--accent2)}

/* Окно переписки. Наследует .chat-box (размер, колонка, скролл), меняет только своё. */
.help-box{max-width:480px}
.help-box .chat-head{color:var(--accent2)}
/* Пустое состояние: заголовок + чипсы тем. Тема нужна ОДИН раз, дальше это переписка,
   а не анкета: повторно спрашивать «выберите категорию» у человека, который уже
   написал, — способ потерять второе сообщение. */
.help-empty{color:var(--mut);font-size:14px;line-height:1.55}
.help-empty b{color:var(--ink);display:block;margin-bottom:6px;font-size:15px}
.help-topics{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.hchip{
  min-height:40px;padding:0 12px;display:inline-flex;align-items:center;
  background:var(--bg-2);border:1px solid var(--line);color:var(--mut);
  font:inherit;font-size:13px;cursor:pointer;
}
.hchip:hover,.hchip:focus-visible{border-color:var(--accent2);color:var(--accent2)}
.hchip.on{background:var(--bg-4);border-color:var(--accent);color:var(--ink)}

/* Реплики. Человек справа, поддержка слева — как в любом мессенджере, чтобы не
   пришлось разбираться, кто здесь кто. Подпись автора есть только у нашей стороны:
   человеку важно отличить автоответ первой линии от живого разбора. */
.hmsg{max-width:86%;padding:9px 12px;font-size:14px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.hmsg.user{align-self:flex-end;background:var(--bg-4);border:1px solid var(--line-strong);color:var(--ink)}
.hmsg.them{align-self:flex-start;background:var(--bg-2);border:1px solid var(--line);color:var(--mut)}
.hmsg-who{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--dim);margin-bottom:4px}
.hmsg.them.by-agent{border-color:rgba(240,168,204,.34)}
.hmsg.them.by-agent .hmsg-who{color:var(--accent)}

/* Ввод. textarea, а не input: обращение — это несколько строк, и однострочное поле
   заставляет человека укорачивать именно то описание, ради которого мы всё это делаем.
   Растёт до пяти строк, дальше скроллится сама. */
.help-in{align-items:flex-end}
.help-in textarea{
  flex:1;background:var(--bg-2);border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:16px;padding:10px 13px;resize:none;
  min-height:44px;max-height:132px;line-height:1.45;
}
.help-in textarea:focus{outline:none;border-color:var(--accent2)}
.help-in .btn{padding:10px 16px;font-size:16px;min-height:44px}
.help-foot{padding:0 14px 12px;font-size:12px;color:var(--dim);line-height:1.5}
.help-foot label{display:block;margin-bottom:6px}
.help-foot input{
  width:100%;background:var(--bg-2);border:1px solid var(--line);color:var(--ink);
  font:inherit;font-size:16px;padding:9px 11px;min-height:44px;
}
.help-foot input:focus{outline:none;border-color:var(--accent2)}
.help-wait{color:var(--dim);font-size:13px;align-self:flex-start;padding:4px 2px}

@media(max-width:560px){
  /* Подпись уходит, знак вопроса остаётся: 44x44 у самого края, ничего не перекрывает. */
  .help-fab .hf-lbl{display:none}
  .help-fab{padding:0;width:44px;justify-content:center}
  .help-box{height:min(88vh,720px);max-width:none}
  .ov#helpOv{padding:0}
}
/* Поддержка открывается ИЗ другого экрана (например, «?» в шапке разбора песни),
   поэтому она единственный оверлей ВЫШЕ остальных и вне правила взаимного исключения:
   иначе жалоба на строку закрывала бы саму песню. */
.ov#helpOv{z-index:70}
/* Ссылка в подвале — третий вход, тот самый «user-initiated из футера», который
   в юзабилити-тестах единственный не мешал [Baymard, 15.10.2019]. */
/* Была рамка-прямоугольник в 13px приглушённым цветом — «неказистая» (Сармат,
   29.07): по весу это подпись, а не кнопка, нажать её не хотелось. Стала
   полированная таблетка того же металла, что и плашка шапки: фаска сверху,
   тень снизу, значок реплики. Металл тут не украшение — это единственный
   материал продукта, и вход в поддержку логично сделан из него же. */
.foot-help{
  margin-top:16px;min-height:46px;padding:0 22px;border-radius:999px;
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font:inherit;font-size:14px;font-weight:700;letter-spacing:.01em;
  color:#242B39;cursor:pointer;border:1px solid rgba(23,27,38,.20);
  background:linear-gradient(180deg,#FFFFFF 0%,#F1F4F9 44%,#E1E6F0 52%,#F7F9FD 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(23,27,38,.10),
             0 6px 18px rgba(23,32,56,.16);
  transition:transform .14s,box-shadow .14s,border-color .14s,color .14s;
}
/* Значок маской, а не эмодзи: эмодзи рисуется системным цветным шрифтом и не
   красится вместе с кнопкой (та же причина, по которой глобус в шапке набран
   знаком, а не 🌐). */
.foot-help::before{
  content:"";width:17px;height:17px;flex:none;background:currentColor;
  -webkit-mask:var(--ic-bubble) center/contain no-repeat;
  mask:var(--ic-bubble) center/contain no-repeat;
}
.foot-help:hover,.foot-help:focus-visible{
  transform:translateY(-1px);border-color:var(--iris);color:var(--iris);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(23,27,38,.10),
             0 10px 24px rgba(23,32,56,.20)}
.foot-help:active{transform:translateY(0);
  box-shadow:inset 0 2px 5px rgba(23,32,56,.18)}
/* Пилюля НЕ прячется у подвала — вместо этого подвал не даёт себя перекрыть.
   Первая попытка была через IntersectionObserver: пилюля гасла, как только подвал
   попадал в кадр. Замер на 390x844 показал, почему это плохо: лендинг целиком короче
   экрана, подвал виден сразу, и вход в поддержку исчезал ровно там, где чаще всего
   и нужен — на первом экране у нового человека. Отступ снизу решает исходную задачу
   (ничего не перекрыто) и оставляет вход на месте всегда. */
footer{padding-bottom:calc(26px + 62px + env(safe-area-inset-bottom,0px))}
/* Пустая переписка: окно по содержимому. Замерено скриншотом на 390px — при
   height:min(88vh,720px) между чипсами тем и полем ввода зияло около 600 пикселей
   пустоты, и это читалось как незагрузившийся экран, а не как «начни писать». */
.help-box.lean{height:auto;max-height:88vh}
.help-box.lean .chat-log{flex:0 0 auto;padding-bottom:6px}
.help-hint{margin-top:12px;font-size:13px;color:var(--accent2);line-height:1.5}
/* Реплики прижаты к низу, к полю ввода, как в любом мессенджере: короткая переписка,
   висящая под заголовком с пустотой внизу, читается как обрезанная.
   margin-top:auto на первом элементе, а не justify-content:flex-end на контейнере:
   второе в переполненном flex-контейнере со скроллом делает верхние сообщения
   недостижимыми. */
.help-box .chat-log>:first-child{margin-top:auto}
.help-box.lean .chat-log>:first-child{margin-top:0}


/* ============================================================================
   ВИЗУАЛЬНАЯ СИСТЕМА «ХРОМ» — 27.07.2026. Выбор Сармата со стенда направлений.
   Слой «Неон» заменён целиком: он был тёмно-синим, здесь основа СВЕТЛАЯ.

   ЧТО ЭТО ЗА СИСТЕМА
     • корпус — холодное серебро #EDEFF4, поверхности белые: нейтральная база,
       на которой цвет работает как сигнал, а не как настроение;
     • розовое золото остаётся брендом и главным действием. НО на светлом металл
       не живёт: золото #EDC7A2 на серебре даёт APCA 17, знака там просто нет.
       Поэтому шапка получила ТЁМНУЮ хромовую планку #1B2233 — знак стоит на
       своей пластине, как шильдик на корпусе прибора (на планке: золото 74,
       сирень знака 49);
     • второй цвет — иридесцент #6C46D8: состояние, данные, активное. На серебре
       70, на белом 79. Это единственный фиолет из семейства нашего знака,
       который держит норму на светлом: утверждённая сирень #C888E6 даёт 41 и
       годится только на тёмной планке.

   ПАЛИТРА РАЗБОРА ПЕСНИ ПЕРЕСЧИТАНА ПОД СВЕТЛОЕ (старая считалась под тёмное и
   на серебре умирает: золото хангыля APCA 10).
     хангыль      бронза   #8A5620 — 80 на белом, 71 на серебре; спетое #5E3202 (95)
     транскрипция сталь    #2B3242 — 99 / 89;                    спетое #000000 (106)
     перевод слов синь     #1E6E96 — 78 / 68;                    спетое #0A4D6E (91)
     смысл строки нейтраль #646E7E — 76 / 66;                    спетое #3A424F
   Четвёртый ЦВЕТНОЙ слой на светлом с дальтонизмом не уживается: любой
   четвёртый тон сходится с одним из трёх (Viénot 1999 + ΔE2000 — зелёный против
   бронзы даёт 13.9 у протанопа при пороге 20). Поэтому «смысл» ушёл в нейтраль:
   его роль держится местом и кеглем, а не цветом. Остальные пары при любом
   зрении: 30-49 у бронзы, 20+ у стали и сини.

   СПЕТОЕ НА СВЕТЛОМ НЕ СВЕТИТСЯ, А ТЕМНЕЕТ. Ореол — приём тёмной темы, на белом
   он превращается в грязное пятно вокруг букв. Сигнал даёт глубина тона и вес.

   Радиус живёт в одном токене --r. Хром — острые 90 градусов.
   ============================================================================ */
:root{
  /* Пять ступеней от бумаги до вдавленного поля. Сплошной белый на весь экран
     не берём: он режет глаз бликом, серебро спокойнее. */
  --bg-0:#EDEFF4;--bg-1:#F5F7FA;--bg-2:#FFFFFF;--bg-3:#E7EBF2;--bg-4:#DCE2EC;
  --line:rgba(23,27,38,.13);--line-strong:rgba(23,27,38,.22);
  --ink:#171B26;--mut:#4E5766;--dim:#646E7E;
  --m-gold:linear-gradient(160deg,#FDF2E6 0%,#EDC7A2 38%,#D9A07C 68%,#F6DEC8 100%);
  --m-gold-ink:#2A1710;
  --iris:#6C46D8;--iris-deep:#4A2AA8;--iris-soft:rgba(108,70,216,.10);
  --plate:#1B2233;--plate-ink:#EAEEF7;
  --accent:#6C46D8;--accent2:#8A5620;--brand:#6C46D8;--accent-fill:#4A2AA8;
  /* Бегунок переключателя состава (.rs-sw) — свой синий-неон, не фирменный
     малиново-сиреневый (правка Сармата 01.08). Светлый конец здесь — тот же
     --ls-mean, которым в этой теме уже красится перевод строки на витрине:
     не выдумываем новый синий, а называем существующий. */
  --rs-a:#0D3552;--rs-b:#1E6E96;
  --good:#1E7A5A;--err:#B3253F;--champ:#8A5620;--gold-soft:#8A5620;--gold:#8A5620;
  --txt:var(--ink);--muted:#4E5766;--line2:var(--line-strong);
  --glass:rgba(255,255,255,.78);--panel:var(--bg-2);--panel2:var(--bg-3);
  --bg:var(--bg-0);--bg2:var(--bg-1);
  --lyr-k:#8A5620;--lyr-k-fill:#5E3202;
  --lyr-r:#2B3242;--lyr-r-fill:#000000;
  --lyr-m:#1E6E96;--lyr-m-fill:#0A4D6E;
  --lyr-s:#646E7E;--lyr-s-fill:#3A424F;
  --lyr-active:#171B26;--lyr-idle:rgba(23,27,38,.62);--lyr-past:rgba(23,27,38,.5);
  /* Тени холодные и мягкие: чёрная тень на серебре читается как грязь. */
  --sh-1:0 1px 2px rgba(23,32,56,.10);
  --sh-2:0 8px 22px rgba(23,32,56,.13);
  --sh-3:0 18px 44px rgba(23,32,56,.16);
  --bevel:inset 0 1px 0 rgba(255,255,255,.85),inset 0 -1px 0 rgba(23,27,38,.10);
  --bevel-soft:inset 0 1px 0 rgba(255,255,255,.7);
  --glow-mint:none;--glow-rose:none;--glow-accent:none;
  --r:0px;--r-sm:0px;
  --f-mono:ui-monospace,"SFMono-Regular","JetBrains Mono","Cascadia Code",Consolas,monospace;
  /* Значки-маски. Инлайном в url(), поэтому ни одного лишнего запроса, а цвет
     берётся из currentColor хоста — красятся вместе с темой. */
  --ic-bubble:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 3C6.75 3 2.5 6.36 2.5 10.5c0 2.35 1.37 4.44 3.52 5.81-.15 1.04-.6 2.3-1.5 3.44 1.93-.3 3.42-1.06 4.45-1.79.95.22 1.97.34 3.03.34 5.25 0 9.5-3.36 9.5-7.8S17.25 3 12 3z'/%3E%3C/svg%3E");
}
/* Фон: волосяная координатная сетка 48px и два холодных источника света по углам.
   Сетку почти не видно — она даёт ощущение размеченной поверхности, а не узора. */
body{background:
  linear-gradient(rgba(23,27,38,.045) 1px,transparent 1px),
  linear-gradient(90deg,rgba(23,27,38,.045) 1px,transparent 1px),
  radial-gradient(60% 40% at 98% 0%, rgba(108,70,216,.10), transparent 64%),
  radial-gradient(54% 42% at 0% 100%, rgba(23,32,56,.07), transparent 62%),
  linear-gradient(180deg,#F5F7FA 0%,#EDEFF4 46%,#E6EAF1 100%);
  background-size:48px 48px,48px 48px,auto,auto,auto;
  background-attachment:fixed;background-color:var(--bg-0);color:var(--ink)}

/* ------------------------------ 1. КНОПКА -------------------------------- */
/* Золото — единственная заливка-металл на экране. Тёмные чернила на нём дают
   больше 10:1, поэтому главное действие видно и на светлом. */
.btn.accent,.btn.primary{background:var(--m-gold);color:var(--m-gold-ink);
  box-shadow:var(--bevel),var(--sh-2);border:0;font-weight:750}
.btn.accent:hover,.btn.primary:hover{filter:brightness(1.04);box-shadow:var(--bevel),var(--sh-3)}
.btn.accent:disabled{filter:grayscale(.45) brightness(.98);box-shadow:var(--bevel-soft);transform:none}
.btn.ghost{background:linear-gradient(180deg,#FFFFFF,var(--bg-3));
  color:var(--ink);border:1px solid var(--line-strong);box-shadow:var(--bevel-soft),var(--sh-1)}
.btn.ghost:hover{border-color:var(--iris);color:var(--iris)}

/* ------------------------------ 2. ПОЛЯ ---------------------------------- */
.song-search,.auth-form input,.chat-input input,.help-in textarea{
  background:#FFFFFF;border:1px solid var(--line-strong);color:var(--ink);
  box-shadow:inset 0 1px 3px rgba(23,32,56,.07)}
.song-search::placeholder,.auth-form input::placeholder,.chat-input input::placeholder,.help-in textarea::placeholder{color:var(--dim)}
.song-search:focus,.auth-form input:focus{border-color:var(--iris);
  box-shadow:inset 0 1px 3px rgba(23,32,56,.06),0 0 0 3px var(--iris-soft)}
.ov{background:rgba(23,27,38,.52);backdrop-filter:blur(7px)}

/* ------------------------------- 3. ШАПКА --------------------------------- */
/* Тёмная пластина во всю ширину. Она нужна не ради красоты: розовое золото знака
   на светлом выцветает (APCA 17), а на этой планке даёт 74. */
header{background:linear-gradient(180deg,#232B40,#1B2233);
  border-bottom:1px solid rgba(255,255,255,.10);
  box-shadow:0 1px 0 rgba(255,255,255,.06),0 10px 26px rgba(23,32,56,.18)}
header,header .wrap,header a,header button{color:var(--plate-ink)}
.logo{letter-spacing:0}
/* Знак крупнее (правка Сармата 02.08: рядом со строкой «Вход» + двустрочная
   «Создать своего айдола» смотрелся мелко) — 44→55/38→48/32→40, та же кривая
   масштабирования по ширинам, что была. --wm ниже по файлу обязана зеркалить
   эти же три числа — это единственная связь, которая держит верстку шапки
   без миллиметровых расхождений (см. комментарий у --wm). */
.logo svg{height:55px;width:auto;display:block}
@media(max-width:420px){.logo svg{height:48px}}
@media(max-width:360px){.logo svg{height:40px}}
.navtab{background:rgba(255,255,255,.06);color:#C3CBDC;border:1px solid rgba(255,255,255,.14);
  box-shadow:none}
.navtab:hover{background:rgba(255,255,255,.12);color:#fff}
.navtab.on{background:linear-gradient(180deg,#7C58E4,#6C46D8);border-color:transparent;color:#fff}
header .btn.ghost,.lang-btn{background:rgba(255,255,255,.08);color:#D7DDEA;
  border-color:rgba(255,255,255,.18);box-shadow:none}
header .btn.ghost:hover,.lang-btn:hover{background:rgba(255,255,255,.16);color:#fff;border-color:rgba(255,255,255,.3)}
@media(max-width:560px){
  /* padding-bottom:0 здесь и съедал тот самый миллиметр: кнопки «Вход» и
     «Регистрация» ложились ровно на нижнюю кромку металлической плашки.

     ЗАЗОРЫ ВОКРУГ ЗОЛОТОЙ ПЛИТКИ ЗНАКА — СЧИТАЮТСЯ, А НЕ ПОДБИРАЮТСЯ (29.07).
     Первая правка ставила padding-top:24px «на глаз по замеру на 390px», и на
     390 действительно вышло 29.5 против 29.3. Но замер по семи ширинам показал,
     что подобранное число живёт только на одной из них:
         320-360  сверху 32.07  снизу 31.44
         390-412  сверху 29.46  снизу 29.28
         430+     сверху 26.85  снизу 23.11   ← 3.7px, это и видно глазом
     Причин расхождения две, и обе постоянные:
       1. знак — не прямоугольник во всю высоту svg. Плитка с «L» занимает
          14..186 из 216 единиц viewBox, то есть сверху над ней 14/216 высоты,
          снизу под ней 30/216. Снизу пустоты вдвое больше;
       2. svg меняет высоту по ширине экрана (44 / 38 / 32), и обе пустоты
          меняются вместе с ним.
     Плюс третья, плавающая: высоту первой строки задаёт самая высокая кнопка
     справа, а её поля меняются на своих контрольных точках — строка была то 48,
     то 44, и нижний зазор ездил вслед за ней.

     Поэтому: строка знака фиксируется по высоте самим знаком (min-height у
     .logo — растёт только пустое поле вокруг svg, ничего не двигается), а оба
     отступа считаются из --wm по одной формуле. --gap — то самое расстояние,
     которое Сармат утвердил снизу; теперь оно ровно такое же и сверху, на
     любой ширине. Меняется --gap — оба зазора едут вместе. */
  .hbar{row-gap:0;padding-bottom:12px;
    --wm:55px;                       /* высота знака, зеркалит .logo svg{height} */
    --gap:29.3px;                    /* утверждённый зазор, один на обе стороны */
    --row:48px;                      /* высота строки знака, задаётся .logo ниже */
    padding-top:calc(var(--gap) - (var(--row) - var(--wm))/2 - var(--wm)*14/216)}
  .hbar>.logo{min-height:var(--row)}
  /* row-gap обнуляется ДВАЖДЫ намеренно. Выше в файле стоит
     `header .wrap.hbar{gap:4px 6px}` для экранов до 420px — сокращённая запись
     возвращает межстрочный зазор в 4px, и весит она больше, чем `.hbar`.
     Ровно эти 4px и разъезжались: на 430px нижний зазор выходил ровно 29.3,
     а на 390px — 33.3. Формула тут ни при чём, ей просто врали исходные числа. */
  header .wrap.hbar{row-gap:0}
  .logo{order:0}
  .lang-wrap{order:1;margin-left:auto}
  .auth-area{order:2}
  /* Верхнее поле вкладок — вторая половина той же формулы. 9px в ней это
     собственная рамка .navtabs (1) плюс её верхнее поле (8): именно на них
     кнопка «Гримёрка» отстоит от начала блока вкладок. */
  .navtabs{order:3;flex:1 0 100%;gap:6px;padding:8px 0;
    border-top:1px solid rgba(255,255,255,.12);
    margin:calc(var(--gap) - var(--row) - 9px
      + (var(--row) - var(--wm))/2 + var(--wm)*186/216) 0 0}
  .navtabs .navtab{flex:1 1 0;justify-content:center;font-size:14px;padding:11px 8px}
  body.guest .navtabs{display:none}
}
/* --wm обязан зеркалить .logo svg{height} — иначе формула считает по одной
   высоте, а знак нарисован в другой. Точки те же, что у самого знака выше. */
@media(max-width:420px){.hbar{--wm:48px}}
@media(max-width:360px){.hbar{--wm:40px}}

/* ---------------------- 4. ПРИБОРНЫЕ ПОДПИСИ ------------------------------ */
.eyebrow,.lp-eyebrow,.hd-eyebrow,.hd-src,.lp-src,.song-online-h,.kp-h,.kp-tag,
.opt-h,.port-h,.sec-h .tag,.sec-h .n,.step-ind,.ai-badge,.lsn-badge,.streak-chip,
.wb-tab span,.lenta-item .li-body .kind,.song-seg button,.wb-tab,.vm-btn,.lay-chip .lbl,
.gtab,.lp-done-n,.help-fab{font-family:var(--f-mono);font-feature-settings:"tnum"}
.eyebrow,.lp-eyebrow,.hd-eyebrow,.opt-h,.port-h,.song-online-h,.kp-h,.kp-tag,.sec-h .tag{
  letter-spacing:.2em;text-transform:uppercase;color:var(--iris)}
.song-seg button,.wb-tab,.vm-btn,.gtab{letter-spacing:.08em}
.hd-src,.lp-src{color:var(--iris)}
.lp-h{font-size:clamp(32px,8.4vw,44px);line-height:1.02;letter-spacing:-.045em}
.lp-sub{font-size:16.5px;margin-top:14px;color:var(--mut)}
.lp{padding-top:26px}
.lp-card{margin-top:22px;padding:18px 16px}

/* ---------------- 5. ПОВЕРХНОСТИ: БУМАГА, А НЕ СВЕЧЕНИЕ -------------------- */
.lp-card,.hd,.result,.lesson-box,.chat-box,.onb-card,.help-box{
  background:#FFFFFF;border:1px solid var(--line);box-shadow:var(--sh-2);position:relative}
.card,.panel,.opt,.lenta-item{background:#FFFFFF;border-color:var(--line)}
/* Верхняя грань карточки — тонкая иридесцентная нить: единственный след хрома
   на белом. */
.lp-card::before,.hd::before,.result::before,.lesson-box::before,.chat-box::before,.onb-card::before{
  content:"";position:absolute;left:0;right:0;top:0;height:2px;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--iris) 26%,#D9A07C 68%,transparent)}
.ai-badge{color:var(--iris);border-color:var(--line-strong)}
.ai-badge::before{content:"";width:5px;height:5px;background:var(--iris);flex:none;border-radius:50%}
.song-seg button.on{border-bottom-color:var(--iris);color:var(--iris)}
.wb-tab.on{color:var(--iris);border-bottom-color:var(--iris)}
.gtab.on,.opt.on{background:linear-gradient(180deg,#7C58E4,#6C46D8);border-color:transparent;color:#fff}
.card.sel{outline-color:var(--iris)}
.lp-prog{background:var(--bg-3);border-color:var(--line)}
.lp-prog i{background:linear-gradient(90deg,var(--iris),#9A7BEE)}
.lp-done-n{color:var(--iris)}
.lp-ghost{border-color:rgba(23,27,38,.22);color:#1B2233;
  background:linear-gradient(180deg,#F4F6FA 0%,#E3E8F1 45%,#FFFFFF 55%,#D9E0EB 100%);
  box-shadow:0 1px 0 #fff inset,0 -1px 0 rgba(0,0,0,.12) inset,0 3px 10px rgba(23,32,56,.12)}
.lp-ghost:hover{border-color:var(--iris);color:var(--iris);filter:none}
/* На светлой пилюле серебро нечитаемо — надпись из тёмной стали с тем же бликом. */
@supports(-webkit-background-clip:text){
  .lp-ghost .lp-ghost-t{background:linear-gradient(180deg,#57637B 0%,#232B40 40%,#6E7C97 52%,#1B2233 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
    filter:drop-shadow(0 1px 0 rgba(255,255,255,.55))}
}
.streak-chip,.hero-chips .streak-chip{border-color:var(--line-strong);color:var(--champ);background:#FFFFFF}
.card-locked{background:linear-gradient(135deg,var(--bg-3),var(--bg-4))}
.vm-btn.on{color:#fff}
.vm-btn.on[data-vm="k"]{background:var(--lyr-k)}
.vm-btn.on[data-vm="r"]{background:var(--lyr-r)}
.vm-btn.on[data-vm="s"]{background:var(--lyr-s)}
.yt-hint{color:var(--iris)}
.sl-note,.kp-note,.ksl-cb,.hd-c{background:var(--iris-soft);border-color:rgba(108,70,216,.22);color:var(--mut)}
/* Всплывающая подсказка остаётся тёмной: на светлой странице она читается как
   сообщение системы, а не как ещё одна карточка. */
.toast{background:#1B2233;border-color:#1B2233;color:var(--plate-ink);box-shadow:var(--sh-3)}
.help-fab{background:#FFFFFF;color:var(--mut);border-color:var(--line-strong);box-shadow:var(--sh-2)}
.help-fab:hover,.help-fab:focus-visible{border-color:var(--iris);color:var(--iris)}
footer{border-top:1px solid var(--line);margin-top:36px;padding-top:22px;padding-bottom:72px;
  font-size:13px;line-height:1.5;color:var(--dim)}
footer b{font-family:var(--f-mono);letter-spacing:.12em;color:var(--mut)}
/* ПОДВАЛ ПРИЖИМАЛСЯ К САМОМУ НИЗУ ДОКУМЕНТА (правка Сармата 29.07: «не влезает
   в экран»). Причина не в числах выше, а в специфичности: подвал это
   <footer class="wrap">, а `.wrap{padding:0 20px}` весит больше, чем `footer`,
   и обнулял оба вертикальных поля — замер показывал padding 0 при объявленных
   22/72, нижняя кромка кнопки поддержки совпадала с концом документа до пикселя.
   Селектор с классом возвращает объявленное и добавляет запас под плавающую
   пилюлю помощи (она фиксирована в 14px от низа, высота 44). */
footer.wrap{margin:36px auto 0;
  padding:26px 20px calc(30px + 44px + 14px + env(safe-area-inset-bottom,0px))}

/* ------- 6. ДЕМО ГОСТЯ: ТОТ ЖЕ ФОРМАТ, ЧТО НА ЭКРАНЕ ПЕСНИ (28.07) ---------
   Было: одна строка за раз, три яруса НА СЛОВО (хангыль/транскрипция/глосс) —
   формат разбора, снятый 26.07. Сармат: «интерфейс взят старый». Стало: весь
   куплет на экране, у строки два корейских яруса и смысл под ними, поющаяся
   строка подсвечена и увеличена, остальные приглушены, тап по строке играет её
   заново. Один в один learn.html, только цвета берём из тёмной темы сайта
   (--lyr-*), а не из своей палитры того экрана.
   Копия слова (<i>) лежит поверх оригинала и открывается по --fill обрезкой:
   ширину анимировать нельзя, она переверстывает строку каждый кадр. */
.lp-lines{display:flex;flex-direction:column}
.lp-ln{padding:11px 10px;cursor:pointer;border-bottom:1px solid var(--line);
  transform-origin:center;transition:transform var(--d-base,220ms) var(--ease,ease),
  opacity var(--d-base,220ms) var(--ease,ease),background var(--d-base,220ms) var(--ease,ease)}
.lp-ln:last-child{border-bottom:0}
.lp-ln:hover{background:var(--bg-3)}
.lp-ln.on{background:var(--bg-3);transform:scale(1.03);box-shadow:var(--sh-1)}
.lp-ln.dim{opacity:.5}
/* ЦВЕТА — ТЕ ЖЕ, ЧТО НА ЭКРАНЕ ПЕСНИ (правка Сармата 28.07: «залитый текст не
   видно, заливка слабо отличается»). Там спетое слово ЗАГОРАЕТСЯ: золото яркого
   тона, транскрипция в чистый белый, смысл в кислотный циан, и у горящего края
   есть ореол. На витрине заливка была наоборот темнее базы — на тёмном фоне это
   читается как «ничего не произошло». Токены --ls-* объявлены ниже своими
   значениями на случай светлой темы: theme-dark.css перебьёт их для тёмной. */
.lp-kr{color:var(--ls-kr);font-size:17px;font-weight:600;line-height:1.35;text-wrap:balance}
.lp-tr{color:var(--ls-tr);font-size:18px;font-weight:600;line-height:1.4;margin-top:5px;text-wrap:balance;
  /* Тот же пробел между словами, что в разборе песни (.ls-tr в learn.html, правка
     Сармата 29-30.07): слоги внутри слова плотные через точку, зазор между
     словами втрое шире обычного пробела — иначе слова сливаются в ленту. */
  word-spacing:.55em}
.lp-mean{color:var(--ls-mean);font-size:13px;line-height:1.4;margin-top:6px;overflow-wrap:break-word}
.lp-tw{position:relative;display:inline-block;white-space:pre-wrap;overflow-wrap:anywhere;max-width:100%}
.lp-tw > i{position:absolute;left:0;top:0;width:100%;font:inherit;font-style:normal;
  white-space:pre-wrap;overflow-wrap:anywhere;pointer-events:none;
  -webkit-clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0);clip-path:inset(0 calc(100% - var(--fill,0%)) 0 0)}
.lp-kr .lp-tw > i{color:var(--ls-kr-sung)}
.lp-tr .lp-tw > i{color:var(--ls-tr-sung)}
.lp-mean .lp-tw > i{color:var(--ls-mean-sung)}
/* Ореол у залитой части — тот же приём, что на экране песни: белому и золоту
   цветом добавить нечего, поэтому силу берём свечением. Ореол обрезан тем же
   clip-path, значит светится ровно пройденная часть, и граница видна. */
html[data-theme="dark"] .lp-kr .lp-tw > i{text-shadow:0 0 10px rgba(255,208,0,.55)}
html[data-theme="dark"] .lp-tr .lp-tw > i{text-shadow:0 0 8px rgba(255,255,255,.35)}
html[data-theme="dark"] .lp-mean .lp-tw > i{text-shadow:0 0 8px rgba(0,234,255,.45)}

/* Подсказка про тап — под куплетом, а не в каждой строке: повторённая у четырёх
   строк, она читается как часть песни. */
.lp-tune-inf{margin-top:6px;font-family:var(--f-mono);font-size:11px;line-height:1.4;color:var(--mut);text-align:center;word-break:break-all}
.lp-rec{text-align:center;padding:8px 0}
.lp-rec-h{font-size:13px;color:var(--mut)}
.lp-rec-now{font-size:24px;font-weight:700;color:var(--ls-kr);margin:10px 0 4px;min-height:32px}
.lp-rec-cnt{font-family:var(--f-mono);font-size:13px;color:var(--accent2)}
.lp-rec-btn{width:100%;min-height:96px;margin-top:12px;font:inherit;font-size:22px;font-weight:800;letter-spacing:.08em;
  color:#1B2233;border:1px solid rgba(255,255,255,.35);border-radius:18px;cursor:pointer;
  background:linear-gradient(180deg,#F4F6FA,#C9D2E0);box-shadow:0 8px 22px rgba(23,32,56,.3)}
.lp-rec-btn:active{transform:translateY(1px)}
.lp-tune{display:flex;align-items:center;justify-content:center;gap:10px;margin-top:10px}
.lp-tune button{min-height:44px;padding:0 14px;background:var(--bg-3);color:var(--ink);
  border:1px solid var(--line-strong);border-radius:999px;font:inherit;font-size:13px;cursor:pointer}
.lp-tune span{font-family:var(--f-mono);font-size:14px;color:var(--accent2);min-width:74px;text-align:center}
.lp-tap{color:var(--mut);font-size:12px;text-align:center;padding:9px 0 2px}
/* ПОЛОСКУ НЕ АНИМИРУЕМ ПЕРЕХОДОМ (правка Сармата 28.07: «дёргается»). Значение
   ставится каждый кадр из сглаженных часов, а поверх этого стоял переход на 140мс:
   браузер каждый кадр начинал новый переход к новой цели и не успевал его
   доиграть — получалась дрожь вместо движения. Убрали переход — осталось ровное
   движение на частоте экрана. */
@media(prefers-reduced-motion:reduce){.lp-ln{transition:none}}

/* ------------- 7. СПЕТОЕ ТЕМНЕЕТ, А НЕ СВЕТИТСЯ ---------------------------
   На тёмной теме спетое слово загоралось ореолом. На белом ореол даёт грязное
   пятно вокруг букв, поэтому сигнал берётся ГЛУБИНОЙ ТОНА — и только ею.

   ВЕС ЗАЛИТОЙ КОПИИ МЕНЯТЬ НЕЛЬЗЯ. Я поднял его до 750 как «второй канал», и
   пришла жалоба: текст размылся, строка двоится. Копия лежит поверх оригинала
   и обрезается по clip-path; у переменного шрифта другой вес это другая ширина
   глифов, копия расползается относительно низа и к концу строки уходит на
   заметную долю буквы. Копия обязана совпадать с оригиналом метрически до
   пикселя — отличаться может только цвет. */
.kara-lines .tok.on .tok-k::after,
.kara-lines .tok.on .tok-r::after,
.kara-lines .tok.on .tok-m::after{text-shadow:none}
.kline.upcoming{border-left-color:var(--iris)}
.ksl.on{border-left-color:var(--lyr-s)}
.ksl.on .ksw::after{color:var(--lyr-s-fill)}
@media(max-width:400px){
  .eyebrow,.lp-eyebrow,.hd-eyebrow,.opt-h,.port-h,.song-online-h,.kp-h{letter-spacing:.12em}
  .song-seg button,.wb-tab,.vm-btn{letter-spacing:.02em}
  .btn{padding:15px 22px}
}

/* ============================================================================
   ХРОМ, СЛОЙ «МАТЕРИАЛ» — 27.07.2026. Правка Сармата: «квадратные кнопки, всё
   грубое, клетчатая подложка, несовременно».

   ЧТО ГОВОРЯТ ДАННЫЕ
     • Michal Malewicz, «UI Design Direction 2026-2027» (27.05.2026) — автор
       терминов neumorphism и glassmorphism: направление 2026 это МАТЕРИАЛ,
       который ведёт себя как настоящий. Металлическая кнопка отбрасывает блик
       на стекло над собой и на оправу под собой, и блики эти РАЗНЫЕ.
     • Pixelmatters, «7 UI design trends to watch in 2026» (06.01.2026) —
       Liquid Glass: развитие glassmorphism с преломлением, полупрозрачностью
       и глубиной; применять сдержанно, ради иерархии, а не ради красивости.
     • ui-ux-pro-max, стиль Y2K Aesthetic: хром, металлик, ГЛЯНЦЕВЫЕ кнопки,
       иридесцент. В базе он помечен как лучший для музыкальных платформ,
       развлечений и аудитории Gen Z — то есть ровно для нас.
     • ui-ux-pro-max, раздел Interaction: у нажатия обязана быть немедленная
       отдача (active-состояние), цель не меньше 44px.

   ЧТО ИЗ ЭТОГО СДЕЛАНО
     1. Прямых углов нет. Кнопки — таблетка (999px), поверхности 14px.
        Квадрат при остром угле читается как элемент таблицы, а не как вещь,
        которую хочется нажать.
     2. Кнопка собрана как ЛИТОЙ МЕТАЛЛ, а не как заливка: свет сверху, тень
        снизу, светлая кромка по краю, зеркальный блик на верхней трети и
        мягкая цветная тень под корпусом.
     3. Блик ДВИЖЕТСЯ при наведении — 600мс. Именно движение блика отличает
        металл от картинки металла.
     4. Вторичная кнопка — стекло: полупрозрачный корпус, размытие фона,
        кромка. Стекло и металл рядом дают иерархию без единого нового цвета.
     5. Клетчатая подложка убрана. Клетка это язык таблицы и миллиметровки.
   ============================================================================ */

/* ---- 0. Подложка: свет вместо клетки -------------------------------------- */
body{background:
  radial-gradient(64% 44% at 96% 0%, rgba(108,70,216,.13), transparent 66%),
  radial-gradient(58% 46% at 0% 100%, rgba(217,160,124,.14), transparent 64%),
  linear-gradient(180deg,#F7F9FC 0%,#EDEFF4 48%,#E4E9F1 100%);
  background-attachment:fixed;background-color:var(--bg-0);color:var(--ink)}

/* ---- 1. Скругления --------------------------------------------------------- */
:root{--r:14px;--r-sm:10px;--pill:999px}
.btn,.lang-btn,.navtab,.gtab,.opt,.help-fab,.streak-chip,.ai-badge{border-radius:var(--pill)}
.lp-card,.hd,.result,.lesson-box,.chat-box,.onb-card,.help-box,.card,.panel,
.song-search,.auth-form input,.chat-input input,.help-in textarea,.lenta-item{border-radius:var(--r)}
/* Нить по верхнему ребру карточки должна повторять её скругление, иначе
   торчит прямым отрезком поверх круглого угла. */
.lp-card::before,.hd::before,.result::before,.lesson-box::before,.chat-box::before,.onb-card::before{
  border-radius:var(--r) var(--r) 0 0;left:1px;right:1px}

/* ---- 2. Главная кнопка: литое розовое золото ------------------------------ */
/* Слои снизу вверх: тень корпуса → цветной отсвет на подложке → сам металл →
   кромка → зеркальный блик. Каждый слой отвечает за одно, поэтому их видно
   по отдельности и можно править по одному.
   ГЛУБИНА МЕТАЛЛА. Первая версия шла от #FDF2E6 к #F6DEC8 — на белой карточке
   она читалась как кремовая заливка, а не как золото: между самой светлой и
   самой тёмной точкой было меньше 12% яркости, и корпус выглядел плоским.
   Здесь размах втрое больше (#F7DEC3 → #C2865A), и это ровно то, что делает
   поверхность металлической: резкий перепад от блика к тени. */
.btn.accent,.btn.primary{
  position:relative;overflow:hidden;border:0;color:var(--m-gold-ink);font-weight:750;
  background:
    linear-gradient(180deg,rgba(255,255,255,.42),rgba(255,255,255,0) 44%),
    linear-gradient(160deg,#F7DEC3 0%,#E9BE94 30%,#D19A6C 58%,#C2865A 78%,#EFCFAE 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(120,70,40,.25),
    inset 0 0 0 1px rgba(255,255,255,.45),
    0 1px 2px rgba(23,32,56,.14),
    0 10px 24px rgba(190,130,95,.34);
  transition:transform var(--d-fast) var(--ease),box-shadow var(--d-base) var(--ease),
             background-position 600ms var(--ease),filter var(--d-fast) var(--ease)}
/* Зеркальный блик — узкая светлая полоса поперёк корпуса. При наведении она
   проезжает слева направо: неподвижный блик выглядит наклейкой, движущийся —
   отражением. */
.btn.accent::after,.btn.primary::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 34%,rgba(255,255,255,.72) 46%,transparent 58%);
  background-size:280% 100%;background-position:120% 0;
  transition:background-position 620ms var(--ease)}
.btn.accent:hover::after,.btn.primary:hover::after{background-position:-40% 0}
.btn.accent:hover,.btn.primary:hover{transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -1px 0 rgba(120,70,40,.25),
    inset 0 0 0 1px rgba(255,255,255,.5),
    0 2px 4px rgba(23,32,56,.14),
    0 16px 32px rgba(190,130,95,.42)}
/* Нажатие: корпус садится и подбирает под себя тень. Отдача обязана быть
   мгновенной — это прямое требование из раздела Interaction. */
.btn.accent:active,.btn.primary:active{transform:translateY(1px) scale(.985);
  box-shadow:
    inset 0 2px 6px rgba(120,70,40,.4),
    inset 0 0 0 1px rgba(255,255,255,.35),
    0 1px 2px rgba(23,32,56,.16)}
.btn.accent:disabled{filter:grayscale(.5) brightness(1.02);transform:none;
  box-shadow:inset 0 0 0 1px rgba(23,27,38,.12)}

/* ---- 3. Вторичная кнопка: стекло ------------------------------------------ */
/* Liquid Glass в сдержанной дозе: полупрозрачный корпус, размытие того, что под
   ним, светлая кромка. Рядом с металлом стекло само собой уходит на второй план,
   и иерархия не требует ни второго цвета, ни рамки потолще. */
.btn.ghost,.lang-btn{
  background:linear-gradient(180deg,rgba(255,255,255,.92),rgba(255,255,255,.62));
  -webkit-backdrop-filter:blur(10px) saturate(1.4);backdrop-filter:blur(10px) saturate(1.4);
  color:var(--ink);border:1px solid rgba(23,27,38,.14);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),0 2px 8px rgba(23,32,56,.10)}
.btn.ghost:hover,.lang-btn:hover{border-color:rgba(108,70,216,.45);color:var(--iris);
  box-shadow:inset 0 1px 0 #fff,0 6px 16px rgba(23,32,56,.14)}
.btn.ghost:active,.lang-btn:active{transform:translateY(1px) scale(.985);
  box-shadow:inset 0 2px 5px rgba(23,32,56,.14)}

/* ---- 4. Шапка: стекло на тёмной пластине ---------------------------------- */
/* На пластине те же два материала, только вывернутые: корпус тёмный, поэтому
   стекло здесь светится изнутри, а не отражает. */
header .btn.ghost,header .lang-btn{
  background:linear-gradient(180deg,rgba(255,255,255,.16),rgba(255,255,255,.07));
  border-color:rgba(255,255,255,.22);color:#E7ECF6;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.24)}
header .btn.ghost:hover,header .lang-btn:hover{background:rgba(255,255,255,.24);color:#fff;
  border-color:rgba(255,255,255,.4)}
.navtab{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14)}
.navtab.on{position:relative;overflow:hidden;
  background:linear-gradient(180deg,#8A67EC,#6C46D8);border-color:transparent;color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45),0 6px 16px rgba(108,70,216,.45)}

/* ---- 5. Мелочи, которые выдают «грубость» --------------------------------- */
/* Поля ввода — тоже вещь: свет сверху, вдавленность внутрь. */
.song-search,.auth-form input,.chat-input input,.help-in textarea{
  box-shadow:inset 0 2px 4px rgba(23,32,56,.07),inset 0 0 0 1px rgba(255,255,255,.7)}
/* Кнопка помощи — стеклянная таблетка, а не квадрат в углу. */
.help-fab{background:rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  box-shadow:inset 0 1px 0 #fff,0 8px 22px rgba(23,32,56,.18)}
@media(prefers-reduced-motion:reduce){
  .btn.accent::after,.btn.primary::after{transition:none}
  .btn.accent,.btn.primary,.btn.ghost,.lang-btn{transition:none}
}

/* ============================================================================
   ХРОМ, СЛОЙ «ЖИВОЙ МЕТАЛЛ» — 27.07.2026, вторая доводка.
   Сармат: «уже интереснее, но можно лучше».

   Четыре добавки, каждая отвечает на конкретную слабость прошлого захода:
     1. блик стоял в одном месте — теперь он идёт за курсором (material.js);
     2. заголовки были плоской краской — стали полированной сталью с гравировкой;
     3. тёмная планка шапки была ровной заливкой — стала металлом со световой
        полосой поперёк, как ребро корпуса;
     4. карточки лежали мёртво — получили фотокартный перелив, который смещается
        при наведении. Фотокарта — главный предмет фандома, и голограмма на ней
        это то, ради чего её наклоняют к свету.
   ============================================================================ */

/* ---- 1. Блик, который идёт за рукой --------------------------------------
   --mx/--my ставит material.js. Пока их нет (телефон, отключённая анимация,
   мышь ещё не заходила) работают значения по умолчанию, и блик стоит там же,
   где стоял раньше. Ни одного состояния, где кнопка осталась бы без света. */
.btn.accent,.btn.primary{--mx:50%;--my:0%}
.btn.accent::before,.btn.primary::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:radial-gradient(120px 80px at var(--mx) var(--my),
    rgba(255,255,255,.55),rgba(255,255,255,0) 70%);
  opacity:0;transition:opacity var(--d-base) var(--ease)}
.btn.accent:hover::before,.btn.primary:hover::before{opacity:1}
/* Текст кнопки обязан лежать ВЫШЕ обоих бликов, иначе они его забеливают. */
.btn.accent > *,.btn.primary > *{position:relative;z-index:2}

.btn.ghost,.lang-btn,.navtab{--mx:50%;--my:50%}
.btn.ghost:hover,.lang-btn:hover{
  background:
    radial-gradient(160px 100px at var(--mx) var(--my),rgba(108,70,216,.14),transparent 70%),
    linear-gradient(180deg,rgba(255,255,255,.96),rgba(255,255,255,.72))}

/* ---- 2. Заголовок как полированная сталь ---------------------------------
   Градиент сверху вниз от почти чёрного к стали плюс светлая грань снизу —
   так выглядит буква, вырезанная в металле, а не напечатанная на бумаге.
   Оба конца градиента тёмные, поэтому читаемость не падает: APCA к серебру
   88 у верхнего конца и 71 у нижнего при норме 60 для крупного жирного. */
@supports (background-clip:text) or (-webkit-background-clip:text){
  .lp-h,.sec-h h2,.hd h2,.onb-card h2{
    background:linear-gradient(176deg,#0E121C 0%,#1E2536 46%,#3A4459 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
    text-shadow:0 1px 0 rgba(255,255,255,.55)}
}
/* Приборный ярлык над заголовком получил металлическую риску слева: короткая
   линия золотом, как насечка на шкале. */
.lp-eyebrow,.eyebrow{display:inline-flex;align-items:center;gap:9px}
.lp-eyebrow::before,.eyebrow::before{content:"";width:18px;height:2px;flex:none;
  background:linear-gradient(90deg,#C2865A,#EDC7A2)}

/* ---- 3. Шапка: не заливка, а ребро корпуса -------------------------------- */
header{
  background:
    linear-gradient(180deg,rgba(255,255,255,.10) 0%,rgba(255,255,255,0) 18%),
    linear-gradient(100deg,#1B2233 0%,#28324A 38%,#39456485 52%,#232B40 66%,#171D2C 100%);
  border-bottom:1px solid rgba(255,255,255,.12);
  box-shadow:inset 0 -1px 0 rgba(255,255,255,.06),0 10px 30px rgba(23,32,56,.22)}
/* Нижняя кромка планки — тонкая золотая нить. Она же связывает шапку со знаком:
   один и тот же металл сверху и в логотипе. */
header::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(237,199,162,.55) 30%,rgba(108,70,216,.5) 70%,transparent);
  pointer-events:none}
/* ОБРЕЗКИ У ШАПКИ БЫТЬ НЕ ДОЛЖНО. Первым делом я поставил сюда overflow:hidden
   под золотую нить — и это подрезало бы всё, что вылезает за планку: выпадающий
   список языка, кольцо фокуса, любую всплывашку. Нить прижата к нижнему краю
   абсолютом, а шапка и так позиционирована (sticky), так что обрезка не нужна. */
header{position:sticky}

/* ---- 4. Карточка как фотокарта -------------------------------------------- */
/* Перелив идёт по диагонали и смещается при наведении. Альфа держится низкой
   специально: голограмма должна угадываться под углом, а не лежать поверх
   текста цветной плёнкой — под ней читают корейский. */
.lp-card,.card,.hd{position:relative;overflow:hidden;
  transition:transform var(--d-base) var(--ease),box-shadow var(--d-base) var(--ease)}
.lp-card::after,.card::after,.hd::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:linear-gradient(115deg,
    transparent 30%,
    rgba(108,70,216,.10) 42%,
    rgba(95,216,240,.10) 50%,
    rgba(237,199,162,.12) 58%,
    transparent 70%);
  background-size:260% 100%;background-position:100% 0;
  opacity:.75;transition:background-position 700ms var(--ease),opacity var(--d-base) var(--ease)}
.lp-card:hover::after,.card:hover::after,.hd:hover::after{background-position:0 0;opacity:1}
.lp-card:hover,.card:hover,.hd:hover{transform:translateY(-2px);box-shadow:var(--sh-3)}
/* Содержимое карточки — над переливом, иначе плёнка ляжет на буквы. */
.lp-card > *,.card > *,.hd > *{position:relative;z-index:2}

@media(prefers-reduced-motion:reduce){
  .lp-card,.card,.hd,.lp-card::after,.card::after,.hd::after{transition:none}
  .lp-card:hover,.card:hover,.hd:hover{transform:none}
}

/* Переключатель языка — та же стеклянная таблетка, что и кнопки шапки. Раньше он
   был единственным элементом планки с прямыми углами и голой рамкой: мелочь,
   но именно из таких мелочей собирается ощущение недоделанности. */
.lang-ico{border-radius:var(--pill);border-color:rgba(255,255,255,.22);color:#D7DDEA;
  background:linear-gradient(180deg,rgba(255,255,255,.16),rgba(255,255,255,.06));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22)}
.lang-wrap:hover .lang-ico,.lang-sel:focus-visible+.lang-ico{
  border-color:rgba(237,199,162,.65);color:#fff;background:rgba(255,255,255,.22)}

/* ============================================================================
   ОТДАЧА НА КАСАНИЕ — 27.07.2026. Правка Сармата, и она по делу: продукт живёт
   на телефоне, а вся предыдущая работа с бликом и переливом висела на :hover,
   которого на телефоне НЕТ. Наведение там либо не срабатывает вовсе, либо
   залипает после тапа и остаётся гореть на уехавшем элементе.

   Поэтому всё, что раньше показывалось при наведении, здесь показывается при
   НАЖАТИИ, и правило одно на весь продукт: палец коснулся — вещь ответила.
   Требование из ui-ux-pro-max, раздел Interaction: отдача должна быть
   немедленной, иначе человек жмёт второй раз.
   ============================================================================ */
.lp-card:active,.card:active,.hd:active,.lenta-item:active,.ls-item:active,.opt:active{
  transform:scale(.99);box-shadow:var(--sh-1)}
/* Перелив проезжает по тапу — единственный момент, когда на телефоне видно,
   что поверхность непростая. */
.lp-card:active::after,.card:active::after,.hd:active::after{background-position:0 0;opacity:1}
@media (hover:none){
  .btn.accent::before,.btn.primary::before{display:none}
  .lp-card:hover,.card:hover,.hd:hover{transform:none;box-shadow:var(--sh-2)}
  .lp-card::after,.card::after,.hd::after{transition:background-position 420ms var(--ease)}
}


/* ============================================================================
   ЗОЛОТО ВМЕСТО ПУРПУРА — 27.07.2026, правка Сармата: «этот непонятный
   фиолетовый бесит, главное действие должно быть розовым золотом».
   Он прав и по сути: розовое золото — цвет знака, а главное действие обязано
   быть одного цвета с брендом, иначе продукт выглядит собранным из чужих
   частей. Иридесцент остаётся, но уходит на свою настоящую работу — отмечать
   состояние и данные, а не звать нажать.
   ============================================================================ */
/* Вход в продукт: «Разучить песню». Тот же литой металл, что у главной кнопки. */
.lesson-cta{position:relative;overflow:hidden;border-radius:var(--r);color:var(--m-gold-ink);
  background:
    linear-gradient(180deg,rgba(255,255,255,.42),rgba(255,255,255,0) 44%),
    linear-gradient(160deg,#F7DEC3 0%,#E9BE94 30%,#D19A6C 58%,#C2865A 78%,#EFCFAE 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(120,70,40,.25),
    inset 0 0 0 1px rgba(255,255,255,.45),
    0 10px 24px rgba(190,130,95,.34)}
.lesson-cta:active{transform:translateY(1px) scale(.99);
  box-shadow:inset 0 2px 6px rgba(120,70,40,.38)}
.lesson-cta *{position:relative;z-index:2}
/* Подпись под заголовком кнопки была рассчитана на фиолетовый фон. */
.lesson-cta small,.lc-sub{color:rgba(42,23,16,.72)}

/* Выбранная вкладка в шапке — тоже золото. На тёмной планке металл читается
   лучше всего, а фиолет там спорил со знаком. */
.navtab.on{background:
    linear-gradient(180deg,rgba(255,255,255,.4),rgba(255,255,255,0) 46%),
    linear-gradient(160deg,#F7DEC3,#E3B183 46%,#C2865A);
  border-color:transparent;color:#2A1710;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85),0 6px 16px rgba(190,130,95,.34)}

/* Круглая справка в строке под фотографией: слева имя айдола, справа «i».
   Прежние правила (капс, золотая рамка-плашка, ::before с вопросом) сняты —
   от них оставалась только рамка вокруг пустоты.

   ДВА СЛОМА, КОТОРЫЕ Я СЮДА ЖЕ И ПРИНЁС (снимок Сармата, 27.07):
   1. Я развернул .hero-foot из колонки в РЯД и не разрешил перенос. Тизер
      переписки объявлен во всю ширину (width:100%) — в ряду без flex-wrap он
      не может уехать на новую строку и ложится поверх имени айдола. Отсюда
      «сообщение наложилось на заставку». Лечится одним flex-wrap:wrap.
   2. Кнопка справки осталась НА ФОТО, хотя разметка переехала под него: выше
      в этом же файле стоит .home .onb-help{position:absolute;top:10px;right:10px},
      и это правило специфичнее моего. Возвращаем её в поток явно. */
.hero-foot{flex-direction:row;align-items:center;gap:12px;flex-wrap:wrap}
.hero-foot .idol-meta{flex:1 1 auto;min-width:0}
/* И САМ ЗНАК «i» ВИДЕН. Выше в файле у .home .onb-help стоит font-size:0 — там
   символ рисовался псевдоэлементом, а текста в кнопке не было вовсе. Я перенёс
   букву в саму кнопку и не вернул кегль: получился белый кружок с пустотой
   внутри (снимок Сармата, 27.07). Возвращаем размер и цвет явно. */
.home .hero-foot .onb-help{position:static;top:auto;right:auto;width:40px;height:40px;
  font-size:18px;line-height:1;font-style:italic;font-weight:700;color:#8A5620;
  background:linear-gradient(180deg,#fff,#F3F5F9);border:1px solid rgba(194,134,90,.55)}
.onb-help{align-self:center;margin:0;flex:0 0 auto;width:40px;height:40px;padding:0;
  display:grid;place-items:center;border-radius:999px;
  border:1px solid rgba(194,134,90,.55);color:#8A5620;background:linear-gradient(180deg,#fff,#F3F5F9);
  font-family:inherit;font-size:17px;font-weight:700;font-style:italic;letter-spacing:0;text-transform:none;
  box-shadow:inset 0 1px 0 #fff,0 1px 4px rgba(23,32,56,.1)}
.onb-help::before{content:none}
.onb-help:hover{background:linear-gradient(180deg,#FFF6EC,#F7E7D6);color:#5E3202;border-color:#C2865A}
.onb-help:active{transform:scale(.96)}
/* Тизер переписки стоял третьим в колонке; в строке ему место под метаданными. */
.hero-foot .dm-teaser{flex:1 0 100%;order:3}

/* ================= НАШИВКА ПОД ФОТОГРАФИЕЙ (29.07) ==========================
   Правка Сармата: «где написано имя и AI IDOL — оформить покрасивее». Полоса
   была набором из трёх кеглей одной гарнитуры: имя 20/800, фиолетовая пилюля
   бейджа и серая подпись концепта. Все три спорили за внимание, и ни одна
   не выглядела частью фотокарточки.

   Что сделано и почему именно так:
   • полоса получает шов — розово-золотую нить по верхней кромке. Тот же приём
     уже держит верх карточек (.lp-card::before), здесь он превращает подпись
     в НАШИВКУ фотокарточки, а не в отдельный блок под фото;
   • имя набирается крупнее и плотнее (25px, -.03em) — на фотокарточке имя
     артиста и есть главный элемент подписи;
   • бейдж «AI IDOL» перестаёт быть цветной пилюлей: он обязателен (раскрытие
     ИИ, см. §9 CLAUDE.md и китайские правила от 15.07.2026), но его работа —
     быть прочитанным, а не первым бросаться в глаза. Приборный кегль, рамка
     волосяная, точка остаётся;
   • концепт уходит в приборную подпись капслоком с разрядкой — тот же язык,
     которым в продукте набраны все служебные строки (.eyebrow, .hd-eyebrow).
     Раньше это была просто мелкая серая строка ни в одном из стилей системы.
   Кегли и разрядка целиком из существующей шкалы — новых величин не заведено. */
/* Раскладка сеткой, а не переносом строки. Ряд из трёх с flex-wrap:wrap уже
   ломался дважды (27.07 тизер лёг поверх имени), и повторился в третий раз:
   концепт стал набираться с разрядкой, строка выросла — и кружок «i» уехал
   под подпись отдельным рядом. Сетка описывает то, что нужно, прямо: слева
   метаданные, справа «i», тизер во всю ширину под ними. Переносить нечего. */
.hero-foot{position:relative;display:grid;grid-template-columns:1fr auto;
  align-items:center;column-gap:12px;row-gap:10px;padding:15px}
.hero-foot .idol-meta{grid-column:1;grid-row:1;min-width:0}
.home .hero-foot .onb-help{grid-column:2;grid-row:1}
.hero-foot .dm-teaser{grid-column:1/-1}
.hero-foot::before{content:"";position:absolute;left:0;right:0;top:0;height:2px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,#D9A07C 24%,#F3E1CE 50%,#C888E6 78%,transparent)}
.hero-foot .idol-name{font-size:25px;font-weight:800;letter-spacing:-.03em;
  line-height:1.05;gap:9px;align-items:center;flex-wrap:wrap}
.hero-foot .ai-badge{font-size:9.5px;letter-spacing:.18em;padding:3px 8px;
  font-weight:600;opacity:.9;align-self:center}
/* Разрядка .16em (как у .eyebrow) уносила строку на второй ряд и рвала её по
   дефису — «АЙДОЛ-/УЧИТЕЛЬ». Замер на 390px: доступно 292px, строке нужно было
   около 355. .09em при 10px укладывает её в один ряд с запасом. */
.hero-foot .idol-concept{margin:5px 0 0;font-family:var(--f-mono);
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--dim);line-height:1.5}
/* Кружок справки садится на ту же ось, что и имя, и перестаёт быть вторым
   белым пятном рядом с бейджем: тот же металл, но приглушённый. */
.home .hero-foot .onb-help{align-self:center;opacity:.85}
.home .hero-foot .onb-help:hover{opacity:1}

/* ============================================================================
   НОВЫЙ СОСТАВ, 31.07.2026 — квадрат 3x3 на витрине.
   Только новые имена классов, ни одно существующее правило не переопределяется:
   снимаешь блок — витрина ровно такая, как была.
   Зачем отдельная сетка: у общей .grid авто-раскладка (auto-fill minmax), число
   карточек в строке пляшет от ширины окна. Здесь нужно ровно три в ряд, чтобы
   девять человек складывались в квадрат — это и есть «состав», а не полка.
   Фото 1:1 и заранее нарезаны квадратом (ffmpeg, кроп смещён к верху на 10%),
   поэтому браузер ничего не режет по центру и подбородки на месте.
   ============================================================================ */
.cast-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:var(--s5) 0 var(--s3)}
.cast-h b{font-size:15px;letter-spacing:-.01em}
.cast-h span{font-size:12px;color:var(--dim)}
.cast-h i{margin-left:auto;font-style:normal;font-size:11px;color:var(--dim);
  letter-spacing:.08em;text-transform:uppercase}

/* Три в ряд ВСЕГДА (правка Сармата 01.08): девять человек обязаны складываться
   в квадрат на любом экране. Двухколоночная оговорка ниже 520px убрана — она и
   давала «два столбика» вместо трёх. Чтобы подпись не превращалась в кашу на
   узком экране, она там прячется, а не ломает сетку (см. .cast-bio ниже). */
.grid.sq3{grid-template-columns:repeat(3,1fr);gap:var(--s2)}

.grid.sq3 .card .ph{aspect-ratio:1/1}
.grid.sq3 .card .ph img{width:100%;height:100%;object-fit:cover;object-position:center 22%}
.grid.sq3 .card .body{padding:var(--s2) 10px 10px}
.grid.sq3 .card .nm b{font-size:13px}
/* Характер вместо концепта. Две строки максимум и обрезка многоточием: длинная
   реплика иначе растягивает одну карточку и ломает ряд квадрата. */
.cast-bio{font-size:11.5px;line-height:1.35;color:var(--mut);margin-top:3px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
@media(max-width:380px){.cast-bio{display:none}}

/* ============================================================================
   ВИТРИНА ГОСТЯ ОТКРЫТА, 31.07.2026 (правка Сармата: «они должны быть видны»).
   До этого лица были размыты (blur 7px, правка 28.07): гость видел, что их много
   и что они красивые, но не кто именно. Теперь показываем состав как есть —
   за регистрацию по-прежнему уходит ВЫБОР, а не просмотр.
   Блок дописан ниже исходного и только переопределяет три свойства: снять его —
   и размытая витрина вернётся ровно такой, какой была.
   Сетка 3 в ряд под девять человек: тот же квадрат, что и в «Айдолах».
   ============================================================================ */
.lp-faces{grid-template-columns:repeat(3,1fr)}
.lp-face{filter:none;border-color:var(--line-strong)}
/* Замок больше не глушит лица: вместо заливки поверх сетки — подпись снизу,
   на градиенте только у нижнего края. Иначе открытые портреты не читаются. */
.lp-faces-lock{inset:auto 0 0 0;height:auto;padding:18px 12px 9px;font-size:12px;
  background:linear-gradient(to top,rgba(16,11,24,.88),rgba(16,11,24,0));
  border-radius:0 0 10px 10px}
@media(max-width:400px){.lp-faces{grid-template-columns:repeat(3,1fr)}}

/* ============================================================================
   ЕДИНИЦА «ПРОЧИТАНО», 31.07.2026. Приём KakaoTalk: у своего сообщения слева
   стоит «1», и она гаснет, когда айдол начала печатать. Разбор NN/g по bubble
   называет именно исчезновение единицы моментом, ради которого фанат смотрит
   в экран: это единственный видимый признак, что на той стороне кто-то есть.
   Цвет — золото знака, не акцент: это состояние, а не призыв нажать.
   ============================================================================ */
.chat-msg.me{position:relative}
.chat-unread{position:absolute;left:-16px;bottom:6px;font-style:normal;font-size:11px;
  font-weight:700;color:var(--accent2);line-height:1;opacity:.9;transition:opacity .24s}
.chat-unread.gone{opacity:0}
/* На узком экране места слева нет — уводим метку под пузырь. */
@media(max-width:420px){
  .chat-msg.me{padding-bottom:12px}
  .chat-unread{left:auto;right:2px;bottom:0}
}

/* ============================================================================
   ВИТРИНА СОСТАВА НА ГЛАВНОЙ, 01.08.2026 — по утверждённому макету.
   Заменяет размытую сетку лиц с замком (28.07). Причина замены: лицо — главный
   довод при выборе биаса, размытое лицо заставляет выбирать вслепую. Смотреть
   теперь можно всем, за аккаунт уходит выбор.
   Геометрия карточки взята у .lp-face (квадрат, радиус 10), золотая кромка —
   у .lp-w.open. Ни один существующий класс не переопределён: снять этот блок,
   и .lp-faces вернётся ровно таким, каким был.
   ============================================================================ */
.rs-sw{margin-top:12px}
.rs-sw .lp-ghost{transition:filter 260ms cubic-bezier(.16,1,.3,1),
  border-color 260ms cubic-bezier(.16,1,.3,1),transform 120ms ease}
.rs-sw .lp-ghost.on{border-color:var(--accent2);filter:brightness(1.2)}

.rs-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:10px}
.rs-c{position:relative;font:inherit;text-align:left;padding:0;cursor:pointer;color:var(--ink);
  background:var(--panel2);border:1px solid var(--line);border-radius:10px;overflow:hidden;
  display:flex;flex-direction:column;
  animation:rsUp 360ms cubic-bezier(.16,1,.3,1) both;
  transition:border-color .16s,transform .12s}
.rs-c:hover{border-color:var(--accent2);transform:translateY(-2px)}
.rs-c:focus-visible{outline:2px solid var(--accent2);outline-offset:2px}
.rs-c .ph{position:relative;aspect-ratio:1/1;background:var(--bg-3)}
.rs-c .ph img{width:100%;height:100%;object-fit:cover;object-position:center 18%;display:block}
/* Нить цвета персонажа — метка, а не украшение: тот же цвет стоит в .cc витрины. */
.rs-c .ph::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--c)}
.rs-c .tx{padding:6px 8px 8px;line-height:1.25}
.rs-c .tx b{display:block;font-size:12px;font-weight:700;color:var(--ink);letter-spacing:.02em}
.rs-c .tx i{display:block;font-style:normal;font-size:10px;color:var(--mut);margin-top:2px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
@keyframes rsUp{from{opacity:0;transform:translateY(16px) scale(.94)}to{opacity:1;transform:none}}
/* Тот же каскад для сеток ЗА входом (гримёрка, «Айдолы»): до 02.08 лица там
   появлялись разом, а на витрине набегали по одному — одно и то же действие
   выглядело двумя разными продуктами. Задержку ставит app.js по номеру
   карточки, шаг 55мс. Класс отдельный, потому что .card живёт и в тех сетках,
   которые не пересоздаются и мигали бы на каждой мелкой перерисовке. */
.card.rise{animation:rsUp 360ms cubic-bezier(.16,1,.3,1) both}

/* Окно карточки. Прячется видимостью, а не display:none — иначе браузеру не от
   чего отсчитывать прозрачность и карточка появлялась бы рывком. */
.rs-ov{position:fixed;inset:0;background:rgba(8,5,12,.78);backdrop-filter:blur(4px);
  display:flex;align-items:center;justify-content:center;padding:18px;z-index:95;
  visibility:hidden;pointer-events:none;opacity:0}
.rs-ov.on{visibility:visible;pointer-events:auto;opacity:1;animation:rsOvIn 260ms ease both}
.rs-card{position:relative;width:100%;max-width:560px;max-height:88vh;overflow:auto;
  background:var(--bg-2);border:1px solid var(--accent2);border-radius:16px;box-shadow:var(--sh-2)}
.rs-ov.on .rs-card{animation:rsCardIn 420ms cubic-bezier(.16,1,.3,1) both}
@keyframes rsOvIn{from{opacity:0}to{opacity:1}}
@keyframes rsCardIn{from{opacity:0;transform:translateY(40px) scale(.90)}60%{opacity:1}to{opacity:1;transform:none}}
.rs-card .big{width:100%;aspect-ratio:1/1;object-fit:cover;object-position:center 16%;display:block}
.rs-card .in{padding:16px 18px 20px;display:flex;flex-direction:column;gap:10px}
.rs-card .nm{font-size:24px;font-weight:900;letter-spacing:-.02em;color:var(--accent2)}
.rs-card .ty{font-size:12px;color:var(--iris,#C888E6)}
.rs-card .bd{font-size:14px;line-height:1.5;color:var(--ink)}
.rs-card .cr{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:10px 12px}
.rs-card .cr u{display:block;text-decoration:none;font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent2);margin-bottom:3px}
.rs-card .cr span{font-size:13px;line-height:1.45;color:var(--mut)}
.rs-x{position:absolute;top:8px;right:10px;font:inherit;font-size:22px;background:rgba(0,0,0,.45);
  border:none;color:#fff;cursor:pointer;width:34px;height:34px;border-radius:999px;line-height:1;z-index:2}
/* Подвал карточки липкий: текст характера длиннее экрана, и обе кнопки обязаны
   оставаться под пальцем без скролла. Подложка непрозрачная — под кнопками
   проезжает текст. */
.rs-act{position:sticky;bottom:0;display:flex;flex-direction:column;gap:6px;
  margin:0 -18px -20px;padding:12px 18px 16px;background:var(--bg-2);
  box-shadow:0 -8px 16px -8px rgba(0,0,0,.5)}
/* Отказ не спорит с выбором: без заливки и обводки, тап-цель полная (44px). */
.rs-back{width:100%;min-height:44px;font:inherit;font-size:14px;font-weight:600;
  background:none;border:none;color:var(--mut);cursor:pointer;border-radius:999px;
  transition:color var(--d-fast) var(--ease)}
.rs-back:hover{color:var(--ink)}

@media(prefers-reduced-motion:reduce){
  .rs-c,.rs-ov.on,.rs-ov.on .rs-card,.card.rise{animation:none}
}

/* ============================================================================
   «ТВОЙ» НА КАРТОЧКЕ, 01.08.2026. Свой айдол больше не исчезает из витрины
   (см. renderCabGrid) — он остаётся на месте под лёгкой плёнкой с подписью.
   Плёнка намеренно слабая: карточку надо УЗНАВАТЬ, а не разгадывать. Сильное
   размытие тут читалось бы как «закрыто», а смысл обратный — это твой.
   Исключительности между людьми нет: одного и того же персонажа может выбрать
   сколько угодно человек, метка говорит только про тебя.
   ============================================================================ */
.card.taken,.rs-c.taken{cursor:default;opacity:.72}
.card.taken:hover,.rs-c.taken:hover{transform:none;border-color:var(--accent2)}
.card.taken .ph,.rs-c.taken .ph{position:relative}
.card.taken .ph img,.rs-c.taken .ph img{filter:blur(1.5px) saturate(.85) brightness(.82)}
/* Подпись поверх плёнки — золото знака, как у всех состояний, а не призывов. */
.taken-b{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent2);background:rgba(16,11,24,.62);border:1px solid rgba(243,217,172,.45);
  border-radius:999px;padding:4px 11px;white-space:nowrap;pointer-events:none}


/* ============================================================================
   ПЛАВНОЕ РАСКРЫТИЕ СЛОВА. Плитка .lp-w и разбор .lp-brk на витрине
   раскрывались мгновенно. Тайминги на ключевых кадрах, а не на переходах:
   переход, объявленный на классе-состоянии, при снятии класса возвращает
   элемент рывком — именно так первая попытка и не сработала.

   ОТКРЫТИЕ 680мс (плитка сама — 540мс). ЗАКРЫТИЕ 300мс (правка Сармата
   02.08: первая версия закрытия была 460мс — «сильно плавно», короче раза в
   полтора). Несимметрично нарочно: открытие даёт время прочитать, что
   появилось, закрытие — просто убирает то, что уже видели, и не должно
   тянуться так же долго. Класс .closing ставит lpToggleWord в app.js, он же
   ждёт animationend и только тогда убирает узел из DOM. */
.lp-brk{animation:lpBrkIn 680ms cubic-bezier(.22,1,.26,1) both;overflow:hidden}
.lp-brk.closing{animation:lpBrkOut 200ms cubic-bezier(.4,0,.2,1) both;pointer-events:none}
@keyframes lpBrkIn{
  from{opacity:0;max-height:0;padding-top:0;padding-bottom:0;transform:translateY(-8px)}
  to  {opacity:1;max-height:340px;transform:none}
}
@keyframes lpBrkOut{
  from{opacity:1;max-height:340px;transform:none}
  to  {opacity:0;max-height:0;padding-top:0;padding-bottom:0;transform:translateY(-8px)}
}
.lp-w.open{animation:lpWOpen 540ms cubic-bezier(.22,1,.26,1) both}
@keyframes lpWOpen{from{transform:scale(.94)}to{transform:none}}
.lp-w[data-wi]{transition:background 260ms cubic-bezier(.22,1,.26,1),border-color 260ms cubic-bezier(.22,1,.26,1)}

/* Три в ряд и на витрине лендинга — там оговорок и не было, фиксируем явно. */
.rs-grid{grid-template-columns:repeat(3,1fr)}
@media(max-width:380px){.rs-c .tx i{display:none}}

@media(prefers-reduced-motion:reduce){.lp-brk,.lp-brk.closing,.lp-w.open{animation:none}}

/* ============================================================================
   КНОПКА «ПРОСЛУШАТЬ ПЕСНЮ». Стоит ПОД плашкой (правка Сармата 02.08: плашка
   теперь тизером крутится сама с первого кадра, поэтому кнопка идёт следом —
   «сначала ожившая картинка, потом действие», а не наоборот). Занимает место
   бывшей «Выбрать своего айдола»: ту кнопку сняли, сетка лиц ниже сама себе
   приглашение.
   ============================================================================ */
.lp-listen{width:100%;display:flex;align-items:center;gap:12px;text-align:left;
  margin:16px 0 14px;padding:14px 18px;min-height:60px;cursor:pointer;
  font:inherit;color:#2A1B12;border-radius:999px;
  border:1px solid rgba(255,255,255,.42);
  background:linear-gradient(180deg,#FBE7D2 0%,#EEC5A4 42%,#FFF6EC 50%,#E6B694 58%,#D29A7C 100%);
  box-shadow:0 1px 0 rgba(255,255,255,.7) inset,0 -1px 0 rgba(0,0,0,.18) inset,
             0 8px 22px rgba(56,28,12,.30);
  transition:filter 160ms cubic-bezier(.16,1,.3,1),transform 110ms ease}
.lp-listen:hover{filter:brightness(1.06)}
.lp-listen:active{transform:translateY(1px)}
.lp-listen:focus-visible{outline:2px solid var(--accent2);outline-offset:3px}
.lp-listen-i{font-size:17px;line-height:1;flex:none;opacity:.8}
.lp-listen-t{flex:1;display:flex;flex-direction:column;gap:1px;line-height:1.25}
.lp-listen-t b{font-size:16px;font-weight:800;letter-spacing:-.01em}
.lp-listen-t i{font-style:normal;font-size:12px;opacity:.72}
.lp-listen-a{font-size:18px;flex:none;opacity:.65}

/* ============================================================================
   ПЕРЕКЛЮЧАТЕЛЬ СОСТАВА — во всю ширину, две равные половины.
   Прежняя пара .lp-ghost выглядела как две случайные пилюли посреди экрана.
   Здесь одна деталь: цельная полоса, внутри бегунок из фирменного градиента
   золото → сирень, тот же, что на полосе проигрывания .lp-prog.
   ============================================================================ */
.rs-sw{position:relative;display:grid;grid-template-columns:1fr 1fr;width:100%;
  margin:18px 0 12px;padding:4px;border-radius:999px;
  background:var(--bg-2);border:1px solid var(--line-strong);
  box-shadow:0 1px 0 rgba(255,255,255,.06) inset,0 6px 18px rgba(0,0,0,.35)}
/* Бегунок ТЁМНЫЙ, а не золотой. Причина не эстетическая: он псевдоэлемент, и
   если по любой причине не отрисуется, надпись активной половины останется на
   фоне полосы. Со светлым бегунком туда просился тёмный текст — и он сливался
   с фоном (поймал охранник: rgb(23,16,31) на rgb(30,22,41)). Тёмный бегунок
   держит БЕЛЫЙ текст, а белый читается и на бегунке, и на самой полосе.

   ЦВЕТ — тёмно-синий неон (правка Сармата 01.08, был малиново-сиреневый: тот
   повторял фирменный градиент кнопок и здесь читался лишним). --rs-a/--rs-b
   — своя пара переменных на тему (см. :root и theme-dark.css), а не два
   хардкода: светлый конец темы это тот же --ls-mean, которым уже красится
   перевод строки на витрине, тёмный вариант — темнее --ls-mean той темы,
   чтобы белый текст держал контраст (расчёт при правке: ≈3.9-5.6:1 на
   светлом конце в обеих темах — тот же запас, что был у прежнего градиента). */
.rs-sw::before{content:"";position:absolute;top:4px;bottom:4px;left:4px;width:calc(50% - 4px);
  border-radius:999px;background:linear-gradient(135deg,var(--rs-a,#0B3B66),var(--rs-b,#0E86D9));
  box-shadow:0 2px 14px rgba(14,134,217,.5);
  transition:transform 320ms cubic-bezier(.16,1,.3,1)}
.rs-sw[data-g="girl"]::before{transform:translateX(100%)}
.rs-sw button{position:relative;z-index:1;font:inherit;font-size:14px;font-weight:800;
  letter-spacing:.08em;text-transform:uppercase;background:none;border:none;
  color:var(--dim);padding:13px 8px;cursor:pointer;border-radius:999px;
  transition:color 260ms cubic-bezier(.16,1,.3,1)}
.rs-sw button.on{color:#FFFFFF;text-shadow:0 1px 2px rgba(0,0,0,.35)}
.rs-sw button:focus-visible{outline:2px solid var(--accent2);outline-offset:3px}
