/* ============================================================
   ВОПРОС / ВАРИАНТЫ ОТВЕТА
   ============================================================ */
.question {
    font-size: 1.375rem;
    line-height: 1.75rem;
    font-weight: 400;
    color: var(--md-sys-color-on-surface);
    margin-bottom: 16px;
}
.question b, .question .script { font-weight: 600; }
/* Вставка изучаемого языка в строке вопроса — тот же случай, что
   .md-prompt-strong, только фраза здесь одна, а языков в ней два. Обёртку
   ставит sc() (js/core.js) там, где вопрос склеен с русской подводкой
   («Определите падеж и число для формы: λύεις»). 1em — кегль самой строки
   вопроса (1.375rem), поэтому у иврита вставка получает те же 42px, что
   и строка условия ниже. */
.question .script {
    font-size: calc(1em * var(--md-ref-script-size) * var(--md-ref-script-scale));
    line-height: 1.3;
}
/* Шрифт и направление вставке даёт .script (styles/base.css) — здесь только вес. */
.md-prompt-strong {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    /* Кегль условия задан в долях от русского текста на экране: 1.375rem —
       это строка вопроса (.question) прямо над ним, а не тело интерфейса.
       Оба множителя на месте: шаг письма (свой у каждого языка) и ползунок
       размера текста. */
    font-size: calc(1.375rem * var(--md-ref-script-size) * var(--md-ref-script-scale));
    line-height: 1.3;
    text-align: center;
    margin: 16px 0;
    color: var(--md-sys-color-on-surface);
}
.md-prompt-ru {
    font-size: 1.25rem;
    line-height: 1.75rem;
    text-align: center;
    margin: 16px 0;
    color: var(--md-sys-color-on-surface);
}
/* Выбор начертания перед первой буквой: обычная карточка со списком, как меню
   урока. Отдельной внешности у карточки нет; своего требует только образец
   буквы в пункте — он стоит прямо в строке названия, и без своего кегля
   начертания по нему не различить (строка названия — 1rem). Нижняя граница —
   как у мелкого текста на изучаемом языке (см. --md-ref-script-min-size). */
.letter-write-choice .lesson-item__headline .script {
    font-size: calc(max(1.5rem, var(--md-ref-script-min-size)) * var(--md-ref-script-scale));
}
/* Буква и слово «Печатные» / «Курсив» — одна строка, и слово стоит по центру
   буквы, а не по её базовой линии. Буква набрана кеглем 1.5rem и выше, строка
   названия — 1rem, поэтому на общей базовой линии слово уезжало под букву.
   Flex-строка это чинит: оба элемента — flex-элементы (слово становится
   анонимным), и align-items: center центрует их по вертикали. gap заменяет
   пробел из разметки: в flex-контейнере пробельный текстовый узел не рисуется
   отдельным элементом, поэтому расстояние задаёт только gap. */
.letter-write-choice .lesson-item__headline {
    display: flex;
    align-items: center;
    gap: 8px;
}
.writing-practice {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin: 16px 0;
    /* Шаг письма забирает остаток высоты упражнения, а карточка холста — внутри
       него. Так поле растёт вместе с окном до самого низа, а не живёт своей
       долей окна (40vh), оставляя пустоту под собой. min-height: 0 обязателен:
       без него flex-элемент не даёт содержимому ужаться ниже своего размера, и
       на низком окне карточка вылезала бы за экран. */
    flex: 1 1 auto;
    min-height: 0;
}
.writing-practice .writing-canvas-card {
    flex: 1 1 auto;
    /* Пол: поле не сжимается в полоску на низком окне. Карточка тянется
       флексом, но ниже этого размера писать пальцем уже негде — тогда шаг
       письма просто уезжает под нижний край и страница прокручивается.
       (min-height: 0 здесь был бы не нужен: он всё равно перебит этим же
       правилом, а нужен он родителю — .writing-practice — чтобы флекс-цепочка
       вообще могла ужиматься.) */
    min-height: clamp(180px, 34vh, 340px);
}
/* Оборот занимает ту же высоту, что и холст: .flashcard-flip растягивается на
   остаток шага, а карточка внутри — на весь .flashcard-flip. Без этого показ
   буквы был бы своей высоты по содержимому (его min-height), и при перевороте
   карточка прыгала бы на десятки пикселей — ровно то, от чего избавляет общий
   тон и ширина у холста и оборота. */
.writing-practice .flashcard-flip {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
}
.writing-practice .flashcard-flip > .md-flashcard--writing {
    flex: 1 1 auto;
}
/* Экран упражнения — колонка во всю высоту окна, чтобы шаг письма мог занять
   остаток. Цепочка: #drillSection → .card → #exerciseQuestion → .writing-practice
   → карточка с холстом. Высота считается от окна, а не от содержимого: иначе
   «остаток» было бы не от чего отсчитывать.
   Вычитаем ровно то, что .md-content добавляет сам (styles/base.css): верхний
   padding (app bar + safe-top) и нижний (nav bar + safe-bottom + 88px под FAB).
   dvh, а не vh: на телефоне адресная строка браузера уезжает и обратно, и vh
   остаётся по самому высокому положению — низ поля оказывался бы под ней. */
#drillSection {
    min-height: calc(100dvh - var(--app-bar-height) - var(--safe-top)
        - var(--nav-bar-height) - var(--safe-bottom) - 88px);
    flex-direction: column;
}
/* display — только у активного экрана. Селектор по id (1,0,0) сильнее
   `.section { display: none }` (0,1,0) из styles/layout.css, поэтому flex,
   объявленный без .active, оставлял экран упражнения висеть после ухода с
   него: любой следующий экран («Настройки», словарь) открывался ниже
   брошенной карточки с упражнением. */
#drillSection.active { display: flex; }
#drillSection > .card {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
#exerciseQuestion {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
/* Карточка холста тянется вместе с окном и упирается в свой потолок, а не
   переключается скачком на контрольной точке: до потолка её ширину задаёт
   контейнер (100%), после — max. Предпочтение задано процентом, а не vw:
   сама колонка приложения уже текучая (.app, max-width 840px), и на телефоне
   60vw оказалось бы меньше доступного места — карточка стала бы у́же, чем
   была. Пол 280px срабатывает только на экране у́же 320px, где 100% и так
   меньше, — то есть никогда не тянет карточку за пределы контейнера.
   Потолки разные: греческому нужно место под две формы буквы (Σ σ), ивриту —
   под одну. Потолок в любом случае ниже контейнера: у экрана упражнения
   .card внутри .app это 752px (840 − 24×2 − 20×2).
   Правила ниже перечисляют оба селектора сразу — холст и оборот карточки, —
   потому что это одна и та же карточка до и после «Готово»: у неё обязаны
   совпадать и ширина, и тон поверхности, иначе переворот читается как мигание.
   Селектор оборота составной: правило стоит раньше .md-flashcard и без этого
   проиграл бы ему по специфичности. Тон взят как у врезки (таблицы, сборка
   предложения), а не как у обычной карточки внутри карточки.
   Широкий потолок у курса — отдельная пара: грек берёт 720px, иврит остаётся
   на общем правиле. */
.writing-canvas-card {
    position: relative;
    padding: 12px;
    border-radius: var(--md-sys-shape-corner-medium);
    border: 1px solid var(--md-sys-color-outline);
    box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.04);
    /* Поле письма — не прокручиваемая и не выделяемая поверхность: жест,
       начатый хоть на холсте, хоть на его рамке в 12px, не должен тянуть
       страницу (иначе поле уезжает вниз под рукой) и не должен поднимать
       на iOS меню выделения по долгому нажатию. touchmove-предохранитель
       живёт в initLetterWriteCanvas, тут — тот же запрет на уровне CSS. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}
/* Высота карточки — от окна, а не от содержимого: холст внутри неё лежит
   абсолютно и своей коробкой не задаёт её высоту, поэтому процент на холсте
   разрешался бы против высоты, которую сам же и определяет (круговая
   зависимость) — браузер падал на нижнюю границу clamp, и на телефоне
   карточка оставалась маленькой, а под ней зияла пустота до низа экрана.
   clamp: пол — рабочий размер для узкого экрана, потолок — чтобы на большом
   поле не вытянулось на весь монитор. Единицы окна (vh), а не проценты: 100%
   от родителя, у которого высота auto, тоже не даёт определённой высоты. */
/* Оборот карточки берёт те же высоты: холст и показ — одна и та же карточка
   до и после «Готово», и разная высота читалась бы как прыжок при перевороте.
   Это min-height, а не height: на шаге письма карточка растягивается флексом
   (.writing-practice .writing-canvas-card), а на показе буквы у неё высоты
   задаёт содержимое, и минимум держит её от схлопывания. */
.writing-canvas-card--hebrew,
.md-flashcard.md-flashcard--writing {
    min-height: clamp(200px, 40vh, 340px);
}
.writing-canvas-card--greek,
.md-flashcard.md-flashcard--writing-greek {
    min-height: clamp(240px, 44vh, 380px);
}
.writing-canvas-card,
.md-flashcard.md-flashcard--writing {
    width: 100%;
    max-width: clamp(280px, 100%, 560px);
    background: var(--md-sys-color-surface-container-lowest);
}
.writing-canvas-card--greek,
.md-flashcard.md-flashcard--writing-greek {
    max-width: clamp(280px, 100%, 720px);
}
/* Показ буквы центрируется по карточке. Классы оборота заучивания
   (.md-flashcard--back, --has-flip) прижимают содержимое к верху и держат 76px
   снизу под круглую кнопку переворота, которой у письма нет: буква висела
   в верхней трети карточки, а под ней оставалась пустота. Пара классов
   (0,2,0) перебивает оба одиночных правила, объявленных ниже, а высота
   карточки от полей не зависит — её задаёт флекс-цепочка (.writing-practice). */
.md-flashcard.md-flashcard--writing {
    justify-content: center;
    padding-bottom: 24px;
}
/* Кнопки письма. Это две строки одного упражнения, и они не должны разъезжаться:
   на холсте «Очистить | Готово», на показе «Назад | Далее». Порядок кнопок задаёт
   разметка (showExercise / completeLetterWritingPractice), а row разводит их по
   краям — тогда главное действие («Готово», «Далее») остаётся у правого края на
   обоих шагах, а второе стоит у левого, как «Очистить». Поэтому «Назад» при
   перевороте встаёт ровно на место «Очистить». */
.writing-practice .md-button-row {
    justify-content: space-between;
}
.md-button-row.exercise-actions {
    justify-content: space-between;
}
/* Кнопка «Далее» после ответа — у правого края, а не сразу под текстом слева:
   глаз после чтения обратной связи остаётся на той же строке, а палец на
   телефоне достаёт до неё, не возвращаясь к левому краю. */
.exercise-next-actions {
    justify-content: flex-end;
}
/* Холст один на письмо буквы и на написание огласовки, поэтому и правило одно:
   селектор по общему классу, а не по id, — иначе второй холст оставался бы
   нестилизованным и брал бы свою внутреннюю ширину (300×150), растягивая
   экран. */
.writing-canvas {
    /* Холст занимает всю коробку карточки (её height), а не задаёт её сам:
       так высота зависит от окна, а буфер подгоняется под неё в js. Карточка
       держит padding 12px, и холст лежит в её padding-box вычтенным на эти
       12px — inset: 12px растянул бы его по краям, но у canvas есть своя
       внутренняя ширина/высота (300×150), поэтому width/height заданы явно:
       без них холст остался бы 300×150, а не заполнил карточку. */
    position: absolute;
    top: 12px;
    left: 12px;
    width: calc(100% - 24px);
    height: calc(100% - 24px);
    display: block;
    border-radius: calc(var(--md-sys-shape-corner-medium) - 4px);
    background: transparent;
    touch-action: none;
    cursor: crosshair;
}
.letter-write-reveal {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    text-align: center;
    min-height: 180px;
    /* Сдвиг показа на разницу между серединой строки и серединой чернил:
       величину считает alignLetterReveal в js/exercises.js. Через transform,
       а не отступом, — поток и высота карточки не меняются. У огласовки
       переменной нет, и сдвиг равен нулю. */
    transform: translateY(var(--letter-write-ink-shift, 0px));
}
/* Показ буквы крупно: на карточке только начертание — имя уже было вопросом
   перед рисованием, — поэтому кегль здесь не «подпись под буквой», а сама
   буква. 3.5rem — это +56% к прежним 2.25rem: заметно крупнее, и при этом
   показ влезает в карточку на любом положении ползунков размера текста.
   Форм бывает больше одной: у греческого прописная и строчная, у ивритской
   буквы с конечной формой — обе формы (letterWriteRevealForms в js/exercises.js).
   Коробка держит только раскладку: кегль и высоту строки задаёт сама буква
   (.script) — см. правило ниже. */
.letter-write-reveal__forms {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    width: 100%;
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    color: var(--md-sys-color-on-surface);
}
/* Кегль и высота строки — на самой букве и с одним числом множителей: 3.5rem
   и 4.25rem (прежняя пропорция 1.214). Множителей два — не описка: коробка
   задавала кегль 3.5rem × ползунок, а .script внутри множил его ещё раз, и
   такой показ владелец видел. Ошибка была одна — высота строки оставалась
   с одним множителем (108.8px под буквой в 143px), поэтому выносные хвосты
   (χ, ך ן ץ) вылезали из строки. Теперь строка растёт вместе с кеглем. */
.letter-write-reveal__forms .script {
    font-size: calc(3.5rem * var(--md-ref-script-scale) * var(--md-ref-script-scale));
    line-height: calc(4.25rem * var(--md-ref-script-scale) * var(--md-ref-script-scale));
}
/* Знак огласовки: и образец под холстом, и показ ответа берут один кегль —
   тогда дорисованное сравнивают с верным знаком один в один. Кегль тот же, что
   у знака на карточке огласовки (.flashcard-word): это тот же знак в том же
   размере, и множитель ползунка на месте. */
.vowel-write-form {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    font-size: calc(3.5rem * var(--md-ref-script-scale));
    line-height: calc(4.125rem * var(--md-ref-script-scale));
    color: var(--md-sys-color-on-surface);
}
/* Носитель под холстом: бледный образец буквы, к которой дописывают знак. По
   нему видно, куда ставить точку или чёрточку. Цвет — контур, а не on-surface:
   штрих ученика рисуется primary (js/exercises.js), и образец не должен с ним
   спорить. Холст прозрачен и лежит поверх (он позже в разметке), поэтому
   образец виден сквозь него; pointer-events: none — чтобы не перехватывать
   штрих за пределами холста (карточка держит padding 12px). */
.vowel-write-guide {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--md-sys-color-outline);
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}
/* Подсказка перед рисованием — название знака и его звук. Обе строки русские,
   поэтому множителей изучаемого языка у них нет: это подсказка о знаке, а не
   сам знак, — как и на обороте карточки огласовки. */
.vowel-write-prompt {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 8px;
    margin: 0 0 16px;
}
.vowel-write-prompt__name {
    font-size: 1.25rem;
    line-height: 1.75rem;
    color: var(--md-sys-color-on-surface);
}
.vowel-write-prompt__sound {
    font-size: 1.125rem;
    line-height: 1.5rem;
    color: var(--md-sys-color-on-surface-variant);
}
.options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 8px;
    margin: 16px 0;
}
.option-btn {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    min-height: 56px;
    padding: 12px 20px;
    border: 1px solid var(--md-sys-color-outline);
    border-radius: var(--md-sys-shape-corner-full);
    background: transparent;
    color: var(--md-sys-color-on-surface);
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.5rem;
    letter-spacing: 0.00625rem;
    cursor: pointer;
    text-align: center;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard),
                border-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard),
                color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard),
                border-radius var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-emphasized);
}
.option-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: -1;
}
.option-btn:hover:not(:disabled)::before { opacity: var(--md-sys-state-hover-opacity); }
.option-btn:active:not(:disabled) { border-radius: var(--md-sys-shape-corner-medium); }
/* Варианты ответа — формы изучаемого языка, а не подписи интерфейса. */
.options--script .option-btn {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    /* Ответ — на шаг ниже условия, но не мелким: 1.125rem — это около 0.82
       от 1.375rem, кегля условия, а множители те же, так что соотношение
       держится на любом положении ползунков.
       Предела кегля (--md-ref-script-min-size) здесь нет намеренно: даже на
       самом мелком положении ползунка вариант остаётся около 28px, то есть
       предел в 20px не наступает ни разу, а у иврита он поднял бы ответ
       вплотную к условию вместо шага вниз. Предел остаётся там, где текст
       изучаемого языка действительно мелкий: банк слов, ячейки парадигм,
       разбор ошибок (см. проверку в tests/rtl.test.js). */
    font-size: calc(1.125rem * var(--md-ref-script-size) * var(--md-ref-script-scale));
    line-height: 1.4;
    /* Длинное слово переносится, а не выезжает за кнопку: колонка сетки
       не шире 160px, а «ἀποκρίνομαι» или «יְרוּשָׁלִַם» в неё не влезают. */
    overflow-wrap: break-word;
    letter-spacing: 0;
}
.option-btn:disabled { cursor: default; }
.option-btn:disabled:not(.correct):not(.wrong) { opacity: 0.38; }
.option-btn.correct {
    background: var(--md-extended-color-success-container);
    color: var(--md-extended-color-on-success-container);
    border-color: transparent;
    animation: md-answer-pop var(--md-sys-motion-duration-medium4) var(--md-sys-motion-easing-emphasized);
}
.option-btn.wrong {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
    border-color: transparent;
    animation: md-answer-shake var(--md-sys-motion-duration-medium4) var(--md-sys-motion-easing-standard);
}
@keyframes md-answer-pop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.04); }
    100% { transform: scale(1); }
}
@keyframes md-answer-shake {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-6px); }
    40% { transform: translateX(5px); }
    60% { transform: translateX(-3px); }
    80% { transform: translateX(2px); }
}

/* ============================================================
   ОБРАТНАЯ СВЯЗЬ (результат ответа)
   ============================================================ */
.feedback {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px;
    border-radius: var(--md-sys-shape-corner-medium);
    margin: 16px 0;
    font-size: 0.875rem;
    line-height: 1.25rem;
    letter-spacing: 0.015625rem;
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
@keyframes md-feedback-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* В <strong> обратной связи лежит то русский ответ, то форма изучаемого
   языка — что именно, знает только тот, кто эту строку собрал. Поэтому
   шрифт и направление вешает он же, классом .script, а не это правило. */
.feedback.ok {
    background: var(--md-extended-color-success-container);
    color: var(--md-extended-color-on-success-container);
}
.feedback.fail {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}
.feedback::before {
    font-family: 'Material Symbols Rounded';
    font-size: 20px;
    line-height: 1.25rem;
    font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 20;
    flex-shrink: 0;
}
.feedback.ok::before { content: 'check_circle'; }
.feedback.fail::before { content: 'cancel'; }

/* индикатор прогресса упражнения */
.md-progress-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
}
.progress-text, .md-progress-label {
    font-size: 0.75rem;
    line-height: 1rem;
    font-weight: 500;
    letter-spacing: 0.03125rem;
    color: var(--md-sys-color-on-surface-variant);
    white-space: nowrap;
}
.md-linear-progress {
    flex: 1;
    height: 4px;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-secondary-container);
    overflow: hidden;
}
.md-linear-progress__bar {
    height: 100%;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-primary);
    transition: width var(--md-sys-motion-duration-long2) var(--md-sys-motion-easing-emphasized);
}

/* ============================================================
   СПИСКИ СЛОВ
   ============================================================ */
.word-list { display: flex; flex-direction: column; }
.word-item {
    border-radius: var(--md-sys-shape-corner-medium);
    overflow: hidden;
    transition: background-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
}
.word-item + .word-item { margin-top: 2px; }
.word-item .word-row {
    position: relative;
    isolation: isolate;
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 56px;
    padding: 8px 16px;
    user-select: none;
}
.word-item.clickable .word-row { cursor: pointer; }
.word-item.clickable .word-row::after {
    content: 'expand_more';
    font-family: 'Material Symbols Rounded';
    font-size: 20px;
    color: var(--md-sys-color-on-surface-variant);
    transition: transform var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized);
}
.word-item.clickable.open .word-row::after { transform: rotate(180deg); }
.word-item .word-row::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--md-sys-color-on-surface);
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: -1;
}
.word-item.clickable .word-row:hover::before { opacity: var(--md-sys-state-hover-opacity); }
.word-item .word-row strong {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    font-weight: 600;
    /* Заголовок словарной статьи — единственный кегль изучаемого языка,
       который НЕ слушает ползунки размера текста, и это намеренно (просьба
       владельца): словарь листают десятками строк, а не читают подряд, и
       слово в нём должно стоять на месте при любой настройке. Прежняя
       формула (шаг × ползунок) давала по умолчанию 38.4px у греческого и
       40.96px у иврита — строка вырастала до 66/69px, и список делался
       редким. Закреплённый кегль задан токеном в px со своим значением у
       каждого письма (styles/tokens.css), поэтому ни общий ползунок (он
       живёт в font-size корня, а px от него не зависит), ни языковой сюда
       не доезжают.
       Этим правилом живут оба списка слов — общий словарь (js/vocab.js) и
       словарь урока (js/lesson.js): строка у них одна и та же, и разный
       кегль в одинаковых строках на двух экранах выглядел бы странно. */
    font-size: var(--md-ref-script-headword-size);
    /* Числом, а не в rem: строка не должна расти вместе с кеглем, её держит
       min-height: 56px выше M3-минимумом списка. */
    line-height: 1.3;
    color: var(--md-sys-color-on-surface);
}
.word-item .word-row > span:not(.vocab-chevron) {
    /* В строке словаря и в словаре урока последний <span> — это шеврон
       (.vocab-chevron), и он тоже прямой потомок .word-row. Без :not() правило
       ловило и его: шеврону доставались margin-left: auto и кегль перевода, —
       и он уезжал вправо от перевода, оставляя между ними пустое поле, да ещё
       и рисовался не своим кеглем (0.875rem вместо 20px из styles/components.css:
       правила одной специфичности, а этот файл подключается позже). */
    /* перевод всегда прижат к правому краю, чтобы строка читалась как список */
    margin-left: auto;
    font-size: 0.875rem;
    line-height: 1.25rem;
    letter-spacing: 0.015625rem;
    color: var(--md-sys-color-on-surface-variant);
    text-align: right;
}
.word-details {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    padding: 0 16px;
    background: var(--md-sys-color-surface-container-high);
    transition: max-height var(--md-sys-motion-duration-long1) var(--md-sys-motion-easing-emphasized),
                padding var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized),
                opacity var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-standard);
}
.word-details.open {
    max-height: 720px;
    padding: 12px 16px 16px;
    opacity: 1;
}
.vocab-section { margin-bottom: 8px; }
.vocab-section h4 {
    padding: 16px 16px 8px;
    font-size: 0.875rem;
    line-height: 1.25rem;
    font-weight: 500;
    letter-spacing: 0.00625rem;
    color: var(--md-sys-color-primary);
}

/* ============================================================
   ТАБЛИЦЫ (склонения, грамматика)
   ============================================================ */
/* Таблица шире экрана едет по горизонтали внутри своей полосы, а не тянет
   за собой страницу: overscroll-behavior обрывает цепочку прокрутки на ней. */
.md-table-scroll {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
    margin: 16px 0;
    /* Куда прижимать содержимое ячеек — решает таблица, а не текст в них.
       Значение наследуется внутрь и применяется в правиле ячеек ниже.
       По умолчанию влево: интерфейс левосторонний, <html> направления не
       получает никогда (см. AGENTS.md, «Writing direction»). Развёрнутые
       таблицы переопределяют это ниже.
       Именно left, а не start: при unicode-bidi: plaintext логическое start
       разрешается по тексту САМОЙ ячейки, и в таблице алфавита буква א
       уезжала к правому краю колонки, за 170 пикселей от собственной
       шапки «Буква». */
    --md-table-align: left;
}
.word-details table, .grammar-text table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    line-height: 1.25rem;
    margin: 8px 0;
    background: var(--md-sys-color-surface-container-lowest);
    border-radius: var(--md-sys-shape-corner-medium);
    overflow: hidden;
}
/* Внутри полосы прокрутки таблица занимает всю ширину, но не обязана в неё
   влезать: width:100% сжимал бы колонки до нечитаемого вместо прокрутки. */
.md-table-scroll table { width: auto; min-width: 100%; margin: 0; }
/* Таблица парадигмы — это формы изучаемого языка, и разворачивается она вместе
   с ним: при письме справа налево первая колонка правая. Направление стоит на
   полосе прокрутки, а не на самой таблице: слишком широкая таблица должна
   открываться с первой колонки, а у полосы с direction:ltr «начало» — левый
   край, и она открывалась бы с последней.
   Таблицы из материала урока сюда не входят: они бывают и русскими, и
   разворачиваются только там, где в данных написано <table dir="rtl"> —
   этот атрибут переносит на полосу grammarLiftedHtml() (js/lesson.js). */
.word-details > .md-table-scroll {
    direction: var(--md-ref-script-direction);
    --md-table-align: var(--md-ref-script-align);
}
/* Таблица материала урока разворачивается только по <table dir="rtl"> в данных;
   этот атрибут переносит на полосу grammarLiftedHtml() (js/lesson.js). Здесь же
   и выравнивание: развёрнутая таблица прижимает ВСЕ ячейки вправо, включая
   русские подписи строк и шапку, — иначе шапка расходится со своей колонкой.
   Таблицы без dir не трогаем: у таблицы огласовок главы 2 ось латинская
   (a/e/i/o/u), она читается слева направо и развороту не подлежит. */
.md-table-scroll[dir="rtl"] { --md-table-align: right; }
/* Формы в таблице парадигмы. Шрифт им даёт .script на самой ячейке
   (js/declension.js): подпись строки и колонка «Перевод» русские, и разворачивать
   вместе с формами их нельзя. Кегль остаётся табличным — 14px, — но не ниже
   предела, за которым огласовка перестаёт читаться: для греческого max() ничего
   не меняет, для иврита поднимает. Единственное место, где текст изучаемого
   языка был набран интерфейсным шрифтом: на греческом это было незаметно, на
   огласовке — нет. */
.word-details td.script {
    font-size: calc(max(0.875rem, var(--md-ref-script-min-size)) * var(--md-ref-script-scale));
}
/* Подпись парадигмы. Именно <caption>, а не строка над таблицей: полоса
   прокрутки уезжает вбок вместе с содержимым, и заголовок вне таблицы от неё
   бы отстал. Выравнивание по началу строки, а не по центру: у развёрнутой
   таблицы начало справа. */
.word-details caption {
    padding: 0 12px 8px;
    text-align: start;
    font-size: 0.8125rem;
    line-height: 1.25rem;
    font-weight: 600;
    letter-spacing: 0.00625rem;
    color: var(--md-sys-color-on-surface-variant);
}
.word-details td, .word-details th,
.grammar-text td, .grammar-text th {
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    padding: 10px 12px;
    /* Выравнивание задаёт ТАБЛИЦА, а не содержимое ячейки, — отсюда
       переменная вместо start.
       start здесь не работает: ниже стоит unicode-bidi: plaintext, а при нём
       start/end разрешаются по направлению текста самой ячейки. В еврейской
       таблице русский «Муж. род» уезжал к левому краю, а форма טוֹב под ним
       стояла у правого — заголовок оказывался не над своей колонкой.
       Само значение ставит полоса прокрутки (--md-table-align ниже), и оно
       физическое: любое логическое plaintext переосмыслит заново.
       Запасное start — для обычных русских таблиц урока: они не
       разворачиваются, и там это ровно прежнее поведение. Убрать объявление
       совсем нельзя: у <th> собственный умолчательный center. */
    text-align: var(--md-table-align, start);
    /* Направление каждая ячейка берёт из своего текста: в развёрнутой таблице
       колонка форм еврейская, а «Падеж» и «Перевод» русские, и точка в конце
       «ед. ч.» без этого уезжала бы в левый край ячейки. */
    unicode-bidi: plaintext;
    color: var(--md-sys-color-on-surface);
}
/* Внутри полосы прокрутки ячейки не переносятся. Иначе колонка «Перевод»,
   которой на экране всё равно не видно, сжимается и растит строку до трёх
   строк текста: у самой широкой таблицы строка была 117px вместо 37px.
   Ширины это почти не меняет — лишние пиксели уезжают в прокрутку. */
.md-table-scroll td, .md-table-scroll th { white-space: nowrap; }

/* Опциональная таблица-пул для букв и огласовок: метка и знак стоят в одной
   ячейке, но выстраиваются друг под другом и не теряются при прокрутке. */
.md-table--pool {
    --md-table-align: center;
    --md-table-pool-header-bg: var(--md-sys-color-surface-container-high);
    --md-table-pool-row-label-bg: var(--md-sys-color-surface-container-lowest);
    --md-table-pool-cell-padding-x: 0.75rem;
    --md-table-pool-cell-padding-y: 0.75rem;
}

.md-table--pool .md-table-pool__cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    min-width: 5.5rem;
    text-align: center;
}

.md-table--pool .md-table-pool__label {
    display: block;
    font-size: 0.625rem;
    line-height: 1rem;
    letter-spacing: 0.0125rem;
    color: var(--md-sys-color-on-surface-variant);
    text-transform: none;
    font-weight: 400;
}

/* Знак огласовки — предмет главы 2 иврита, а не подпись к ней, поэтому кегль
   у него свой, крупнее табличного. Он закреплён в px по просьбе владельца:
   алфавит и огласовку листают и узнают знаки, а не читают подряд, и они не
   должны ехать за ползунками размера. Значение — тот кегль, что формула
   давала при ползунке 160% (1.375rem × 1.6): на экране по умолчанию ничего
   не изменилось. Предел огласовки (--md-ref-script-min-size) здесь не нужен:
   35.2px выше его 20px при любом положении ползунков, а сам он не ползунок. */
.md-table--pool .md-table-pool__glyph {
    display: block;
    font-size: 35.2px;
    line-height: 1.25;
    color: var(--md-sys-color-on-surface);
    font-weight: 500;
}

.md-table--pool th,
.md-table--pool td {
    padding: var(--md-table-pool-cell-padding-y) var(--md-table-pool-cell-padding-x);
    text-align: center;
    vertical-align: middle;
}

.md-table--pool > thead th,
.md-table--pool th:first-child,
.md-table--pool > tbody > tr > th {
    background: var(--md-table-pool-header-bg);
    color: var(--md-sys-color-on-surface-variant);
    font-weight: 600;
}

.md-table--pool > tbody > tr > th {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--md-table-pool-row-label-bg);
    border-right: 1px solid var(--md-sys-color-outline-variant);
    box-shadow: 1px 0 0 var(--md-sys-color-outline-variant);
    /* Первая колонка — русские подписи строк («Долгие с matres lectionis»). Без
       ограничения она растягивалась по самой длинной подписи (212px) и
       выдавливала знаки огласовки в узкую полоску. Ограничиваем ширину и
       разрешаем перенос: ячейки полосы прокрутки обычно не переносятся
       (.md-table-scroll td, th выше). 8rem — предел, при котором самое длинное
       слово подписи («Сверхкраткие», 96px) ещё помещается в строку целиком,
       а «Долгие с matres lectionis» спокойно ложится в две. */
    max-width: 8rem;
    white-space: normal;
}

.md-table--pool[dir="rtl"] > tbody > tr > th {
    left: auto;
    right: 0;
    border-right: 0;
    border-left: 1px solid var(--md-sys-color-outline-variant);
    box-shadow: -1px 0 0 var(--md-sys-color-outline-variant);
}

.md-table--pool > tbody > tr:last-child td,
.md-table--pool > tbody > tr:last-child th {
    border-bottom: 0;
}

/* Таблица алфавита (греческий урок 1 и глава 1 иврита). Три колонки видны
   всегда — буква, название и произношение; у иврита четвёртая-шестая
   (конечная форма, курсив, транслитерация) дополнительные, и их раскрывает
   одна кнопка .alphabet-toggle. Состояние живёт в localStorage, а класс
   is-expanded на таблицу ставит renderAlphabetExtras() (js/lesson.js):
   в таблице понятия «колонка» нет, и прятать приходится каждую её ячейку.
   У греческой таблицы дополнительных колонок нет и кнопки тоже — правила
   ниже просто не находят её ячеек, и всё, что есть, видно сразу.
   Кегль крупнее табличного — буквы здесь предмет главы, а не подпись к ней. */
.md-table--alphabet {
    --md-table-align: center;
}
/* Ячейки без буквы (название, произношение, транслитерация) тоже крупнее
   табличного кегля, а не только буквы: глава читается с телефона, и в прежнем
   кегле подписи были вровень с мелкой огласовкой. У иврита это русские
   подписи, у греческого — греческие названия букв. Ячейка названа прямо в
   селекторе: на узком экране layout.css задаёт кегль самим td и th, и
   унаследованный от таблицы размер до ячеек не дошёл бы. Заголовки (th) при
   этом остаются табличными. */
.grammar-text .md-table--alphabet,
.grammar-text .md-table--alphabet td {
    font-size: 1rem;
}
.md-table--alphabet td, .md-table--alphabet th {
    padding: 0.625rem 0.875rem;
    vertical-align: middle;
}
/* Ячейкам без буквы можно переноситься — вопреки общему запрету переноса в
   полосе прокрутки (.md-table-scroll td, th выше). Причина в длинных подписях:
   у греческого произношение идёт с пояснением («[г] (перед γ, κ, ξ, χ – [н])»),
   и с запретом минимальная ширина колонки равна максимальной — таблица
   перестаёт сжиматься и вместе с произношением уезжает за экран телефона.
   Колонка буквы переносу не подлежит: «Σσ» и «בּ / ב» — цельные знаки, а не
   фраза. Остальные ячейки короткие, и перенос срабатывает только там, где
   подпись действительно длинная. */
.md-table--alphabet td:not(:first-child) { white-space: normal; }
.md-table--alphabet .alphabet-col--final,
.md-table--alphabet .alphabet-col--cursive,
.md-table--alphabet .alphabet-col--translit {
    display: none;
}
.md-table--alphabet.is-expanded .alphabet-col--final,
.md-table--alphabet.is-expanded .alphabet-col--cursive,
.md-table--alphabet.is-expanded .alphabet-col--translit {
    display: table-cell;
}
/* Буква, конечная форма и курсив — текст изучаемого языка. Гарнитуру,
   направление и языковой множитель ячейка берёт у lang="he" (иврит) или
   lang="el" (греческий) из styles/base.css, поэтому span задаёт только кегль
   и множитель ползунка. Кегль крупный: в греческом уроке 1 и в главе 1 иврита
   буква — предмет главы, а не подпись, и в греческой таблице прописная со
   строчной стоят в одной ячейке («Αα») — то есть это ещё и самая широкая
   ячейка таблицы. 1.75rem — предел, при котором греческие три колонки ещё
   помещаются в полосу прокрутки телефона (412px) вместе с произношением;
   ивритской таблице буква нужна крупнее (на ячейку одна узкая буква против
   греческой пары), и её таблица на узком экране слегка уезжает вбок — ровно
   то, ради чего у каждой таблицы своя полоса прокрутки (.md-table-scroll),
   страница при этом не едет.
   Кегль закреплён в px по просьбе владельца: алфавит листают и узнают буквы,
   а не читают подряд, и он не должен ехать за ползунками размера. Значение
   берётся токеном, а не пишется здесь: у иврита оно своё и крупнее, и ветку
   выбирает курс через data-script — см. --md-ref-script-alphabet-size в
   styles/tokens.css. Предел огласовки здесь не нужен — кегль выше его
   20px при любом положении ползунков. */
.md-table--alphabet .alphabet-glyph {
    font-size: var(--md-ref-script-alphabet-size);
    line-height: 1.2;
}
/* Рукописное начертание — та же гарнитура Gveret Levin, что и в упражнении
   письма; шрифт уже подключён в index.html и описан в data/licenses.js. */
.md-table--alphabet .alphabet-glyph--cursive {
    font-family: var(--md-ref-typeface-cursive-hebrew);
}
/* Кнопка над таблицей — обычная M3-кнопка .menu-btn.text из components.css;
   здесь только её место в материале урока. */
.alphabet-toggle {
    margin-bottom: 4px;
}

.word-details th, .grammar-text th {
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface-variant);
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.03125rem;
    text-transform: uppercase;
}
/* Таблица «бегадкефат» (глава 1 иврита): две строки по шесть букв. Русские
   подписи строк («смычные», «щелевые») — не шапка, а название вида буквы:
   читать их не надо, смотреть надо на буквы. Поэтому капслок общего правила
   выше им не нужен, и кегль у них ниже табличного — по шкале M3 это label
   small, 11px. Сами буквы, наоборот, крупнее табличного кегля: они и есть
   предмет главы, как буква в таблице алфавита.
   Кегль ячейки объявлен селектором, который перебивает
   .grammar-text table td:lang(he) из base.css: там он равен 1em языкового
   ползунка, а букве здесь нужен ещё и собственный размер. Гарнитуру,
   направление и языковой множитель ячейка по-прежнему берёт у lang="he" в
   данных — здесь только размер. Кегль закреплён в px, как у буквы в таблице
   алфавита и у знака огласовки: буквы алфавита листают и узнают, а не читают
   подряд, и они не должны ехать за ползунками размера. Значение — тот кегль,
   что формула давала при ползунке 160% (1.5rem × 1.6): на экране по умолчанию
   ничего не изменилось. Предел огласовки не нужен — 38.4px выше его 20px. */
.grammar-text .md-table--begadkefat th {
    font-size: 0.6875rem;
    letter-spacing: 0;
    text-transform: none;
}
.grammar-text .md-table--begadkefat td[lang="he"] {
    font-size: 38.4px;
}
.word-details tr:last-child td, .grammar-text tr:last-child td { border-bottom: 0; }

.grammar-text {
    font-size: 1rem;
    line-height: 1.625rem;
    letter-spacing: 0.03125rem;
    color: var(--md-sys-color-on-surface);
    overflow-wrap: break-word;
}
.grammar-text b { color: var(--md-sys-color-on-surface); }
/* Вставка изучаемого языка в прозе материала. Обёртку ставит wrapScriptRuns()
   (js/lesson.js): греческий материал размечен не был, и пометить вставки при
   отрисовке дешевле, чем править тридцать три урока.
   Кегль здесь — не украшение, а цель задачи: то, что изучают, набрано крупнее
   русского вокруг него. 1em — кегль самого абзаца (1rem), а дальше два
   множителя: шаг письма и ползунок размера текста.
   Селектор перечисляет прозаические блоки, а не всё подряд под .grammar-text:
   таблица материала — тоже .grammar-text, и её ячейки со своими правилами
   (.md-table-pool__glyph) перебить нельзя — .grammar-text .script (0,2,0)
   оказался бы сильнее их (0,1,0) и сломал бы таблицу огласовок главы 2. */
.grammar-p .script, .grammar-h .script, .grammar-list .script {
    font-size: calc(1em * var(--md-ref-script-size) * var(--md-ref-script-scale));
    /* Числом, а не в rem: вставка растёт вместе с кеглем, и зажатая высота
       строки на крупном кегле налезла бы на соседнюю. */
    line-height: 1.3;
}
/* Одиночный знак ударения или придыхания (знак без буквы, .script--mark) —
   метка в скобках, а не слово. Языковой шаг кегля раздувал её через два
   множителя и вешал высоко над русской строкой. Кегль здесь — 1.5rem: заметно
   крупнее русского текста вокруг (16px) и всё же меньше греческих слов
   (24px против 38px), чтобы знак было видно, но он не перекрывал строку.
   Множителя ползунка языка тут нет намеренно: это исключение sweeps'а в
   tests/fontscale.test.js, закреплено отдельной проверкой (общий ползунок
   через rem знак всё равно двигает). vertical-align опускает его: глиф знака
   нарисован у самой макушки, и при 24px он без сдвига повис бы над русскими
   буквами. -0.35em возвращает его примерно на прежнюю высоту (~11px над
   базовой линией). Гарнитуру, направление и изоляцию знак по-прежнему берёт
   у .script. */
.grammar-p .script.script--mark,
.grammar-h .script.script--mark,
.grammar-list .script.script--mark {
    font-size: 1.5rem;
    vertical-align: -0.35em;
}

/* Ритм материала. Разметку на блоки собирает renderGrammarHtml() (js/lesson.js);
   отступы задаёт этот блок, а не число <br> подряд в data/lessons.js. */
.grammar-h {
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 600;
    letter-spacing: 0.009375rem;
    color: var(--md-sys-color-on-surface);
    margin: 28px 0 8px;
    /* Переход на самой основе, а не на .is-target: иначе подсветка гасла бы
       мгновенно, когда класс снимается таймером (см. scrollToGrammarHeading). */
    transition: background-color var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-standard),
                color var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-standard),
                box-shadow var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-standard);
}
.grammar-text > .grammar-h:first-child { margin-top: 0; }
/* Заголовок, к которому пришёл прыжок из поиска: короткая подсветка, чтобы
   после прокрутки было видно, какая тема нашлась. Ореол нарисован box-shadow,
   а не padding: указатель не должен сдвигать разметку. */
.grammar-h.is-target {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
    border-radius: var(--md-sys-shape-corner-small);
    box-shadow: 0 0 0 8px var(--md-sys-color-primary-container);
}
.grammar-p { margin: 0 0 12px; }
.grammar-text > :last-child { margin-bottom: 0; }
/* Маркер снаружи: вторая строка пункта встаёт под текст, а не под «•» */
.grammar-list {
    margin: 0 0 12px;
    /* inline-start: списку с dir="rtl" отступ нужен справа */
    padding-inline-start: 24px;
    list-style: disc outside;
}
.grammar-list li { margin-bottom: 4px; }
.grammar-list li:last-child { margin-bottom: 0; }
.grammar-list li::marker { color: var(--md-sys-color-primary); }
/* Заголовок сразу после таблицы или списка не липнет к ним */
.md-table-scroll + .grammar-h, .grammar-list + .grammar-h { margin-top: 24px; }

/* ============================================================
   КАРТОЧКИ ДЛЯ ЗАУЧИВАНИЯ (flashcards)
   ============================================================ */
.flashcard-area { text-align: center; padding: 8px 0; }
/* Обёртка держит перспективу для переворота; поля остаются на самой карточке. */
.flashcard-flip { perspective: 1200px; }
.md-flashcard {
    position: relative;
    background: var(--md-sys-color-surface-container-high);
    border-radius: var(--md-sys-shape-corner-extra-large);
    padding: 40px 24px;
    margin: 8px 0 24px;
    min-height: 200px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    animation: md-card-in var(--md-sys-motion-duration-medium4) var(--md-sys-motion-easing-emphasized-decelerate);
}
@keyframes md-card-in {
    from { opacity: 0; transform: translateY(16px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.flashcard-word {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    /* Кегль карточки задан прямо, а не через шаг письма: карточка — это
       отдельный экран с одним словом, и здесь важен абсолютный размер, а не
       отношение к русскому тексту вокруг (см. --md-ref-script-size в
       styles/tokens.css). Множитель ползунка остаётся: настройка обязана
       работать и здесь. */
    font-size: calc(3.5rem * var(--md-ref-script-scale));
    line-height: 4.125rem;
    font-weight: 400;
    color: var(--md-sys-color-on-surface);
    word-break: break-word;
}
/* Карточка иврита: согласные с огласовкой на греческом кегле читаются
   с трудом — точки под буквой сливаются с ней, и ради этого у иврита свой
   размер. Он не выведен из греческого множителем нарочно: это две разные
   задачи — греческое слово длиннее, и ему хватает меньшего, а иврит мельче
   не читается вовсе. Ветка идёт по письму (data-script), а не по курсу, —
   тем же атрибутом, каким tokens.css выбирает шрифт и предел кегля.
   Множитель ползунка сохранён, иначе настройка перестала бы её слушать. */
:root[data-script="hebrew"] .flashcard-word {
    font-size: calc(3.5rem * var(--md-ref-script-scale));
    /* Высота строки несёт тот же множитель, что и кегль (числа те же, что у
       греческого: 4.125 / 3.5 — это 1.18 строки на кегль). Без множителя
       коробка строки оставалась меньше самих букв: кегль иврита растёт шагом
       письма, а 4.125rem — нет, и чернила вылезали за коробку вниз, к чтению
       под словом. Никкуд сидит внутри буквы и под ней, и от этого запас
       между словом и его чтением сходил почти в ноль. */
    line-height: calc(4.125rem * var(--md-ref-script-scale));
}
.flashcard-translation {
    font-size: 1.5rem;
    line-height: 2rem;
    color: var(--md-sys-color-primary);
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
/* Чтение слова на карточке — под самим словом и над переводом, тем же
   порядком, что и в раскрытой статье словаря (js/vocab.js). Кегль в rem, а не
   через множители письма: это русские буквы и латиница, то есть подсказка
   о слове, а не изучаемый текст. Общий ползунок размера текста её поэтому
   двигает, а языковой — нет, как и полагается подсказке. */
.flashcard-translit {
    font-size: 1.125rem;
    line-height: 1.5rem;
    color: var(--md-sys-color-on-surface-variant);
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
/* Оборот карточки огласовки: название знака и звук, который он обозначает.
   Обе строки русские — «патах», «[а]», — поэтому множители изучаемого языка им
   не нужны и правило не трогает ни .script, ни data-script: как и .flashcard-
   translit, это подсказка о знаке, а не сам знак. */
.flashcard-vowel-name {
    font-size: 1.125rem;
    line-height: 1.5rem;
    color: var(--md-sys-color-on-surface-variant);
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
.flashcard-vowel-sound {
    font-size: 1.5rem;
    line-height: 2rem;
    color: var(--md-sys-color-primary);
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
.flashcard-buttons {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 24px;
}
.flashcard-buttons button {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    min-height: 48px;
    padding: 12px 24px;
    border: 0;
    border-radius: var(--md-sys-shape-corner-full);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0.00625rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    -webkit-tap-highlight-color: transparent;
    transition: border-radius var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-emphasized);
}
.flashcard-buttons button::before {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: -1;
}
.flashcard-buttons button:hover::before { opacity: var(--md-sys-state-hover-opacity); }
.flashcard-buttons button:active { border-radius: var(--md-sys-shape-corner-medium); }
.flashcard-buttons .show { background: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary); }
.flashcard-buttons .know { background: var(--md-extended-color-success-container); color: var(--md-extended-color-on-success-container); }
.flashcard-buttons .dontknow { background: var(--md-sys-color-error-container); color: var(--md-sys-color-on-error-container); }

/* --- Оборот карточки: тренировка форм слова --- */
/* Кнопка-переворот стоит в углу поверх содержимого, поэтому обе стороны
   резервируют под неё место снизу. */
.md-flashcard--has-flip { padding-bottom: 76px; }
.md-flashcard--back {
    padding-top: 24px;
    justify-content: flex-start;
    min-height: 260px;
}
@keyframes md-card-flip {
    from { transform: rotateY(-90deg); opacity: 0; }
    to   { transform: rotateY(0deg); opacity: 1; }
}
.md-flashcard--flip {
    animation: md-card-flip var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
.card-declension { width: 100%; }
.card-declension__word {
    font-family: var(--md-ref-typeface-script);
    direction: var(--md-ref-script-direction);
    unicode-bidi: isolate;
    font-size: calc(1.5rem * var(--md-ref-script-scale));
    line-height: 2rem;
    color: var(--md-sys-color-on-surface);
}
/* Оборот карточки показывает то же слово, поэтому у иврита он крупнее тем же
   множителем, что и лицо карточки. */
:root[data-script="hebrew"] .card-declension__word {
    font-size: calc(1.5rem * 1.5 * var(--md-ref-script-scale));
    line-height: 3rem;
}
.card-declension__progress {
    margin-top: 4px;
    font-size: 0.75rem;
    line-height: 1rem;
    letter-spacing: 0.03125rem;
    text-transform: uppercase;
    color: var(--md-sys-color-on-surface-variant);
}
.card-declension__prompt {
    margin-top: 12px;
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 500;
    color: var(--md-sys-color-primary);
}
.card-declension .options { margin: 16px 0 0; }
.card-declension__done {
    margin-top: 24px;
    font-size: 1.375rem;
    line-height: 1.75rem;
    color: var(--md-sys-color-on-surface);
}
.card-declension .md-button-row { justify-content: center; margin-top: 8px; }

.flashcard-flip-btn {
    position: absolute;
    right: 16px;
    bottom: 16px;
    width: 48px;
    height: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: var(--md-sys-shape-corner-full);
    /* Filled icon button, а не tonal: тональные роли (*-container) почти
       сливаются с surface-container-high карточки — 1.06:1 в светлой теме и
       1.00:1 в «Сепии». primary даёт 5.2–8.4:1 во всех трёх темах. */
    background: var(--md-sys-color-primary);
    color: var(--md-sys-color-on-primary);
    cursor: pointer;
    isolation: isolate;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
    transition: border-radius var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-emphasized);
}
.flashcard-flip-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: -1;
}
.flashcard-flip-btn:hover::before { opacity: var(--md-sys-state-hover-opacity); }
.flashcard-flip-btn:focus-visible::before { opacity: var(--md-sys-state-focus-opacity); }
.flashcard-flip-btn:active { border-radius: var(--md-sys-shape-corner-medium); }
.flashcard-flip-btn .msym { font-size: 24px; }

/* ============================================================
   СТАТИСТИКА / ОШИБКИ
   ============================================================ */
.stat-row {
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 56px;
    padding: 8px 0;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}
.stat-row:last-child { border-bottom: none; }
.stat-row .msym { color: var(--md-sys-color-on-surface-variant); }
.stat-row__label { flex: 1; font-size: 1rem; line-height: 1.5rem; }
.stat-row__value {
    font-size: 1.375rem;
    line-height: 1.75rem;
    color: var(--md-sys-color-primary);
    font-variant-numeric: tabular-nums;
}
.md-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 8px;
    margin-bottom: 8px;
}
.md-stat-tile {
    background: var(--md-sys-color-surface-container-high);
    border-radius: var(--md-sys-shape-corner-large);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.md-stat-tile__value {
    font-size: 2.25rem;
    line-height: 2.75rem;
    color: var(--md-sys-color-on-surface);
    font-variant-numeric: tabular-nums;
}
.md-stat-tile__label {
    font-size: 0.75rem;
    line-height: 1rem;
    font-weight: 500;
    letter-spacing: 0.03125rem;
    color: var(--md-sys-color-on-surface-variant);
}
.md-subhead {
    padding: 16px 0 8px;
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0.00625rem;
    color: var(--md-sys-color-primary);
}
.error-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 16px;
    margin: 4px 0;
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    font-size: 0.875rem;
    line-height: 1.25rem;
}
/* Правильный ответ здесь — то форма изучаемого языка, то русский перевод:
   разбор ошибок сводит в один список все виды упражнений. Шрифт и
   направление формы даёт .script, которым errorText() (js/stats.js) метит
   только строки на изучаемом языке, — русский ответ остаётся шрифтом
   интерфейса. plaintext — запас на строку, в которой смешано то и другое. */
.error-item strong {
    unicode-bidi: plaintext;
    color: var(--md-extended-color-success);
}
/* Строка списка — 14px, а огласовка на таком кегле сливается с буквой.
   Порог тот же, что у прочего мелкого текста изучаемого языка. */
.error-item .script {
    font-size: calc(max(1em, var(--md-ref-script-min-size)) * var(--md-ref-script-scale));
    line-height: 1.5;
}
.error-item .msym { color: var(--md-sys-color-error); }
.clear-btn {
    min-height: 40px;
    padding: 9px 23px;
    border: 1px solid var(--md-sys-color-outline);
    border-radius: var(--md-sys-shape-corner-full);
    background: transparent;
    color: var(--md-sys-color-error);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0.00625rem;
    cursor: pointer;
    margin-top: 16px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    transition: background-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
}
.clear-btn:hover { background: color-mix(in srgb, var(--md-sys-color-error) 8%, transparent); }
.md-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 40px 16px;
    text-align: center;
    color: var(--md-sys-color-on-surface-variant);
}
.md-empty-state .msym {
    font-size: 48px;
    color: var(--md-sys-color-outline);
    margin-bottom: 8px;
}


/* ============================================================
   «ОТЧЕ НАШ»
   ============================================================ */
.prayer-verse {
    padding: 12px 0;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}
.prayer-verse:last-child { border-bottom: 0; }
/* Стих — ряд отдельных слов, поэтому направление письма стоит здесь: иначе
   слова легли бы в порядке слева направо, а каждое читалось бы справа налево.
   Класс .script на этот ряд вешает renderPrayerText() (js/prayer.js). */
.prayer-line {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}
/* Слово молитвы — текст изучаемого языка. */
.prayer-word {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: 4px 10px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    font-family: var(--md-ref-typeface-script);
    font-size: calc(max(1.125rem, var(--md-ref-script-min-size)) * var(--md-ref-script-scale));
    line-height: 1.75rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard),
                color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
}
/* У иврита огласовка живёт под буквой и внутри неё, а .prayer-word обрезает
   содержимое ради ripple: тесная строка срезала бы точки снизу. */
:root[data-script="hebrew"] .prayer-word {
    line-height: 1.5;
}
.prayer-word:hover { background: var(--md-sys-color-primary-container); color: var(--md-sys-color-on-primary-container); }
.prayer-word.selected { background: var(--md-sys-color-primary); color: var(--md-sys-color-on-primary); }
.prayer-russian {
    margin-left: 4px;
    font-size: 0.9375rem;
    line-height: 1.375rem;
    color: var(--md-sys-color-on-surface-variant);
}
.prayer-transcription {
    margin-left: 4px;
    font-size: 0.8125rem;
    line-height: 1.25rem;
    font-style: italic;
    color: var(--md-sys-color-outline);
}
.prayer-analysis {
    display: none;
    margin: 12px 0 4px;
    padding: 16px;
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-tertiary-container);
    color: var(--md-sys-color-on-tertiary-container);
    font-size: 0.875rem;
    line-height: 1.25rem;
    animation: md-feedback-in var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate);
}
.prayer-analysis strong {
    font-family: var(--md-ref-typeface-script);
    unicode-bidi: plaintext;
    font-size: calc(max(1.0625rem, var(--md-ref-script-min-size)) * var(--md-ref-script-scale));
    line-height: 1.5;
}
/* Чтение слова в разборе: русскими буквами и латиницей, поэтому идёт
   интерфейсной гарнитурой, без множителей изучаемого языка. */
.prayer-word-reading {
    display: block;
    margin-top: 2px;
    font-size: 0.8125rem;
    line-height: 1.25rem;
    font-style: italic;
}


/* ============================================================
   СТАРТОВЫЙ ЭКРАН: ВЫБОР КУРСА
   ============================================================
   Перекрытие поверх приложения, а не ещё одна .section: nav bar уже держит
   пять точек — максимум для M3 — а пусковой экран и не точка навигации.
   Видимость ведёт body.start-open (js/course.js), атрибут hidden держится
   с ним в согласии ради программ чтения с экрана. */
.start-screen { display: none; }
body.start-open .start-screen {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 40;
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    background: var(--md-sys-color-surface);
    padding: calc(24px + var(--safe-top)) 16px calc(24px + var(--safe-bottom));
}
/* Пока выбор не сделан, рамки приложения нет: ни app bar, ни навигации, ни FAB.
   Содержимое тоже убрано — так под перекрытием нечему прокручиваться, и не
   приходится вешать overflow: hidden на body: это сделало бы body контейнером
   прокрутки и сломало бы window.scrollY, на который смотрит тень app bar. */
body.start-open .md-top-app-bar,
body.start-open .md-nav-bar,
body.start-open .md-fab,
body.start-open .md-content { display: none; }

.start-screen__inner {
    width: 100%;
    max-width: 480px;
    margin: auto;
}
.start-screen__title {
    font-size: 2rem;
    line-height: 2.5rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--md-sys-color-on-surface);
    margin-bottom: 8px;
}
.start-screen__list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 16px;
}

/* Карточка курса — тот же выразительный контейнер, что .md-feature-card.
   На ней только опознавательные знаки курса: буква, название, источник и
   объём. Описания уроков нет намеренно (см. AGENTS.md, «Courses»), поэтому
   строк меньше и бейдж с шевроном выровнены по центру текста, а не по верху. */
.course-card {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;
    padding: 20px;
    border: 0;
    text-align: left;
    border-radius: var(--md-sys-shape-corner-extra-large);
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    font-family: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.course-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: -1;
}
.course-card:hover::before { opacity: var(--md-sys-state-hover-opacity); }
.course-card:focus-visible::before { opacity: var(--md-sys-state-focus-opacity); }
.course-card:active::before { opacity: var(--md-sys-state-pressed-opacity); }
.course-card__icon {
    width: 48px;
    height: 48px;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.course-card__glyph {
    display: block;
    line-height: 1;
    font-size: 1.75rem;
    letter-spacing: 0;
    transform: translateY(-1px);
}
.course-card__glyph.greek {
    direction: ltr;
    unicode-bidi: isolate;
    /* Буква на бейдже курса — знак, а не текст для чтения: бейдж круглый и
       фиксированный (48px, .course-card__icon). Поэтому кегль задан в px и
       намеренно не несёт ни общего множителя (--app-font-scale приходит через
       rem), ни языкового ползунка — иначе на 160% греческая буква вырастала до
       самого диаметра, а ивритская вылезала за него. Исключение из правила
       «кегль изучаемого языка несёт множитель» закреплено в
       tests/fontscale.test.js. Греческая 30px — ровно то, что было при общем
       100%; ивритская 32px вместо прежних 40.32px: те были основанием ползунка
       иврита (×1.2), а оно существует ради огласовки, которой на бейдже нет. */
    font-size: 30px;
    transform: translateY(-1px);
}
.course-card__glyph.hebrew {
    direction: rtl;
    unicode-bidi: isolate;
    font-size: 32px;
    transform: translateY(1px);
}
.course-card__text { flex: 1; min-width: 0; }
.course-card__title,
.course-card__tagline { display: block; }
.course-card__title {
    font-size: 1.5rem;
    line-height: 2rem;
    font-weight: 400;
    letter-spacing: 0;
}
.course-card__tagline {
    margin-top: 4px;
    font-size: 0.875rem;
    line-height: 1.25rem;
    letter-spacing: 0.015625rem;
    color: var(--md-sys-color-on-surface-variant);
}
/* Объём курса — метка, а не третья строка описания: та же справка «сколько
   уроков», но плашкой, чтобы она не читалась как рассказ о содержании.
   Кегль, высота и скругление — метрики чипа из components.css
   (.filter-chip__body), а secondary-container / on-secondary-container — та же
   тональная пара, которой чип отмечает выбранное состояние. */
.course-card__note {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    margin-top: 12px;
    padding: 0 12px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
    font-size: 0.875rem;
    line-height: 1.25rem;
    letter-spacing: 0.00625rem;
    font-weight: 500;
}
.course-card__note .msym { font-size: 18px; }
.course-card__chevron {
    color: var(--md-sys-color-on-surface-variant);
}
