/* Тест на уровень китайского.
 *
 * Свой файл и свой префикс `ltest-`: у старого теста (`?v=2`) один вид
 * задания и выбор уровня перед началом, у этого четыре вида и проходка
 * насквозь. Общие классы означали бы, что правка одного теста молча
 * меняет другой.
 *
 * Всё на токенах марки. Верный ответ — нефритовый, неверный — красный;
 * это единственное место на сайте, где красный значит «ошибка», а не
 * «главное действие», поэтому главная кнопка внизу карточки намеренно
 * отделена от вариантов ответа воздухом.
 */

.ltest__shell {
    max-width: 720px;
    margin: 0 auto;
}

/* --- ход теста ------------------------------------------------------ */

.ltest__progress {
    display: flex;
    gap: 3px;
    margin-bottom: var(--sp-3);
}

.ltest__seg {
    flex: 1 1 0;
    height: 6px;
    border-radius: 999px;
    background: var(--border-subtle);
    transition: background-color .2s ease, transform .2s ease;
}

.ltest__seg.is-right { background: var(--jade-500); }
.ltest__seg.is-wrong { background: var(--red-400); }

/* Текущее задание — приподнятым отрезком, а не цветом: цвет здесь уже
   занят результатом ответа, и третий оттенок читался бы как третий
   исход. */
.ltest__seg.is-current { transform: scaleY(1.8); background: var(--ink-400); }

.ltest__meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
    font-size: var(--fs-2xs);
    color: var(--text-muted);
}

.ltest__counter b { color: var(--text-body); font-variant-numeric: tabular-nums; }

/* --- карточка задания ----------------------------------------------- */

.ltest__card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.ltest__kind {
    align-self: flex-start;
    font-size: var(--fs-3xs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--text-subtle);
}

.ltest__kind--audio { color: var(--jade-500); }
.ltest__kind--tone { color: var(--red-500); }
.ltest__kind--order { color: var(--gold-300); }

.ltest__stage {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-5) 0 var(--sp-2);
}

.ltest__stage[hidden] { display: none; }

/* Иероглиф — крупно и брусковым: на него смотрят, а не читают его.
   Тот же шрифт, что у прописей и словаря, иначе один знак выглядит на
   трёх страницах сайта тремя разными. */
.ltest__hanzi {
    font-family: var(--font-hanzi), "Noto Sans SC", serif;
    font-size: 92px;
    line-height: 1;
    color: var(--ink-900);
}

.ltest__audio { display: flex; align-items: center; gap: var(--sp-3); }

.ltest__play {
    width: 72px;
    height: 72px;
    border: 0;
    border-radius: 50%;
    background: var(--jade-500);
    color: #fff;
    cursor: pointer;
    display: grid;
    place-items: center;
    box-shadow: var(--sh-sm);
    transition: transform .15s ease, background-color .15s ease;
}

.ltest__play:hover { background: var(--jade-600); }
.ltest__play:active { transform: scale(.94); }

/* Пульсация во время звучания: у кнопки «послушать» нет другого способа
   показать, что она сработала, — звук идёт в наушники, а не на экран. */
.ltest__play.is-playing { animation: ltest-pulse 1s ease-out infinite; }

@keyframes ltest-pulse {
    0% { box-shadow: 0 0 0 0 rgba(47, 122, 103, .45); }
    100% { box-shadow: 0 0 0 18px rgba(47, 122, 103, 0); }
}

/* Инлайновый SVG приходит нулевого размера, если размер не задан
   правилом под имя класса-контейнера — грабли, на которых проект уже
   стоял в шапке и в легенде расписания. */
.ltest__play svg { width: 30px; height: 30px; fill: currentColor; stroke: currentColor; }

.ltest__audio-note { font-size: var(--fs-2xs); color: var(--text-muted); }

.ltest__prompt {
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-snug);
    color: var(--text-body);
}

.ltest__prompt [lang="zh"] { font-family: var(--font-hanzi), "Noto Sans SC", serif; }

.ltest__pinyin {
    display: block;
    margin-top: var(--sp-2);
    font-size: var(--fs-site-small);
    font-weight: var(--fw-regular);
    color: var(--text-muted);
}

.ltest__hint {
    margin: var(--sp-3) 0 0;
    font-size: var(--fs-2xs);
    font-weight: var(--fw-regular);
    line-height: var(--lh-normal);
    color: var(--text-muted);
}

/* --- варианты ответа ------------------------------------------------- */

.ltest__answers { display: flex; flex-direction: column; gap: var(--sp-3); }

.ltest__option {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-3) var(--sp-4);
    text-align: left;
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--r-control);
    font: inherit;
    font-size: var(--fs-site-small);
    color: var(--text-body);
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, transform .1s ease;
}

.ltest__option:hover:not(:disabled) { border-color: var(--border-strong); }
.ltest__option:active:not(:disabled) { transform: scale(.995); }
.ltest__option:disabled { cursor: default; }

.ltest__option-mark {
    flex: none;
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--surface-sunken);
    font-size: var(--fs-3xs);
    font-weight: var(--fw-bold);
    color: var(--text-muted);
}

.ltest__option-text { min-width: 0; }

.ltest__option.is-right {
    border-color: var(--jade-500);
    background: var(--jade-50);
}

.ltest__option.is-right .ltest__option-mark { background: var(--jade-500); color: #fff; }

.ltest__option.is-wrong {
    border-color: var(--red-400);
    background: var(--red-50);
}

.ltest__option.is-wrong .ltest__option-mark { background: var(--red-400); color: #fff; }

/* Тоны в два столбца: пять подписей в колонку — это экран прокрутки
   ради одного выбора. */
.ltest__answers--tone { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ltest__answers--tone .ltest__option:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* --- сборка фразы ---------------------------------------------------- */

.ltest__line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    min-height: 64px;
    padding: var(--sp-3);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-control);
    background: var(--surface-sunken);
}

.ltest__line.is-right { border-style: solid; border-color: var(--jade-500); background: var(--jade-50); }
.ltest__line.is-wrong { border-style: solid; border-color: var(--red-400); background: var(--red-50); }
.ltest__line--answer { margin-top: var(--sp-2); }
.ltest__line-empty { font-size: var(--fs-2xs); color: var(--text-subtle); }

.ltest__pool { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.ltest__chunk {
    padding: var(--sp-2) var(--sp-4);
    border: 1px solid var(--border-default);
    border-radius: var(--r-chip);
    background: var(--surface-card);
    font-family: var(--font-hanzi), "Noto Sans SC", serif;
    font-size: 26px;
    line-height: 1.3;
    color: var(--text-body);
    cursor: pointer;
    transition: border-color .15s ease, transform .1s ease;
}

.ltest__chunk:hover:not(:disabled) { border-color: var(--border-strong); }
.ltest__chunk:active:not(:disabled) { transform: scale(.96); }
.ltest__chunk.is-picked { border-color: var(--border-strong); background: var(--surface-card); }
.ltest__chunk:disabled { cursor: default; }

/* --- разбор ---------------------------------------------------------- */

.ltest__feedback {
    padding: var(--sp-4);
    border-radius: var(--r-control);
    font-size: var(--fs-2xs);
    line-height: var(--lh-normal);
}

.ltest__feedback[hidden] { display: none; }
.ltest__feedback.is-right { background: var(--jade-50); color: var(--jade-700); }
.ltest__feedback.is-wrong { background: var(--red-50); color: var(--red-700); }
.ltest__feedback.is-neutral { background: var(--surface-sunken); color: var(--text-muted); }

.ltest__feedback-title { display: block; margin-bottom: var(--sp-1); font-size: var(--fs-site-small); }
.ltest__feedback-text { margin: 0; }

.ltest__actions { margin-top: var(--sp-5); display: flex; justify-content: center; }
.ltest__actions .eddy-btn { min-width: 220px; }

/* --- итог ------------------------------------------------------------ */

.ltest__result[hidden] { display: none; }

.ltest-result { text-align: center; }

.ltest-result__seal { margin: 0 auto var(--sp-5); }

.ltest-result__title { margin: 0 0 var(--sp-2); }

.ltest-result__score {
    margin: 0 0 var(--sp-4);
    font-size: var(--fs-site-small);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.ltest-result__text {
    max-width: 52ch;
    margin: 0 auto var(--sp-6);
    line-height: var(--lh-relaxed);
    color: var(--text-body);
}

.ltest-result__levels {
    max-width: 420px;
    margin: 0 auto var(--sp-7);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.ltest-result__level {
    display: grid;
    grid-template-columns: 64px minmax(0, 1fr) 44px;
    align-items: center;
    gap: var(--sp-3);
}

.ltest-result__level-name { font-size: var(--fs-2xs); color: var(--text-muted); text-align: left; }
.ltest-result__level-num {
    font-size: var(--fs-2xs);
    color: var(--text-muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ltest-result__bar {
    display: block;
    height: 8px;
    border-radius: 999px;
    background: var(--border-subtle);
    overflow: hidden;
}

/* Полоса набирается сжатием по горизонтали, а не ростом ширины: ширина
   — свойство раскладки, и её переход заставляет браузер пересчитывать
   геометрию на каждом кадре у всех шести полос разом. `transform`
   считает видеокарта.

   Истина живёт в `--fill` и в значении покоя; `is-empty` — временная
   подмена, которую снимает таймер. Тут проходит граница между
   украшением и ложью: полоса с подписью «2/4» обязана быть заполнена
   наполовину, даже если движения не случилось, — пустая рядом с «2/4»
   это неверный результат, а не отсутствие эффекта.

   Поэтому именно переход, а не `animation`: анимация ВЛАДЕЕТ свойством,
   пока считается идущей, и в скрытой вкладке, где она не двигается,
   намертво держит полосу пустой (проверено — держала). Переход же вне
   своего проигрывания свойство не трогает. По той же причине снимает
   подмену `setTimeout`, а не `requestAnimationFrame`: кадров в скрытой
   вкладке не выдают вовсе, а таймеры срабатывают. */
.ltest-result__bar-fill {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 999px;
    background: var(--red-400);
    transform: scaleX(var(--fill, 1));
    transform-origin: left center;
    transition: transform .55s cubic-bezier(.22, .61, .36, 1);
}

.ltest-result__bar-fill.is-empty { transform: scaleX(0); }

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

.ltest-result__bar-fill.is-strong { background: var(--jade-500); }

.ltest-result__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-5);
}

.ltest-result__cta {
    max-width: 46ch;
    margin: 0 auto;
    font-size: var(--fs-2xs);
    line-height: var(--lh-normal);
    color: var(--text-muted);
}

@media (max-width: 560px) {
    .ltest__hanzi { font-size: 68px; }
    .ltest__answers--tone { grid-template-columns: minmax(0, 1fr); }
    .ltest__actions .eddy-btn { width: 100%; }
    .ltest-result__level { grid-template-columns: 52px minmax(0, 1fr) 40px; }
}
