/*
 * Стили банка заданий (/learn/).
 *
 * Правило: на страницах без заданий — ноль байт этих стилей. Файл подключается
 * условием по разделу в partials/head.html, то есть только там, где есть
 * задания.
 *
 * Внешних ресурсов нет ни одного: ни шрифтов, ни фоновых картинок по http.
 * Каждая переменная имеет запасное значение — если токены не доедут, страница
 * останется читаемой, а не белой на белом.
 *
 * ТЕМА БЕРЁТСЯ У ПОРТАЛА, А НЕ У СИСТЕМЫ. Здесь стоял @media
 * (prefers-color-scheme: light) — единственный источник светлой темы, который
 * страница знала, пока жила статикой мимо Hugo. Он отвечает на вопрос «как
 * настроена операционная система», а портал спрашивает другое: что читатель
 * выбрал переключателем в шапке (ключ digitable:theme, скрипт в
 * partials/head.html ставит data-theme до первой отрисовки). У читателя со
 * светлой системой и тёмным порталом задания приезжали светлыми внутри тёмного
 * портала — и наоборот. Своей темы у этого файла больше нет вовсе: цвета —
 * псевдонимы --course-*, и переключает их портал.
 */

:root {
  /* Цвета — псевдонимы палитры портала (--course-*), а не своя семёрка.
     Ровно этим приёмом живёт книга «Инженерия коммуникации»
     (css/communication-book.css), и по той же причине: палитра портала уже
     посчитана и стережётся замером контраста настоящим браузером
     (scripts/check-contrast.mjs), а вторая палитра рядом означает второе
     место, где чинить, и первое, где разойтись. Свои значения тут были
     дважды — тёмные в :root и светлые под @media, — и светлые до переезда в
     Hugo не включались вовсе, если читатель выбрал тему руками.

     ЦВЕТ КАРТОЧКИ КОДА (--course-code-*) сюда не берётся: листинг эталонной
     модели стоит на поверхности СТРАНИЦЫ, а не на карточке кода, и правило
     «на странице только --course-*» записано в шапке courses-v2.css.

     Запасные значения остаются: если courses-v2.css не доехал, страница
     должна остаться читаемой, а не белой на белом. */
  --learn-bg: var(--course-bg, #05080d);
  --learn-panel: var(--course-surface, #071018);
  --learn-text: var(--course-text, #f5f7fa);
  --learn-muted: var(--course-muted, #9baab8);
  --learn-accent: var(--course-cyan, #00e5e5);
  --learn-border: var(--course-line, #15566a);
  --learn-ok: var(--course-green, #7cff6b);
  --learn-fail: var(--course-red, #ff5b5b);
  --learn-warn: var(--course-orange, #ffc247);
  --learn-radius: var(--digitable-radius-md, 14px);
  /* Второй и третий размер скругления — те же токены, а не свои числа. До этой
     строки поля ввода, кнопки, вердикты и листинги стояли на 8px и 999px,
     набранных прямо в правилах: 8px мельче системного --digitable-radius-sm
     (10px), и на странице задания это читалось как «всё стало квадратнее»
     рядом с карточками на 14px. Запасные значения обязательны здесь так же,
     как у цветов: страницы банка заданий открываются и без сети. */
  --learn-radius-sm: var(--digitable-radius-sm, 10px);
  --learn-radius-pill: var(--digitable-radius-pill, 999px);
}

/* ШКАЛА КЕГЛЕЙ ЗДЕСЬ НЕ СВОЯ. Ни одного нового числа: всё, что ниже, снято с
   эталонных страниц портала — читалки статьи (.article-header и .reader-content
   в courses-v2.css) и /fts/practice/ (css/fts.css).

   ЗАМЕР 2026-08-10, ЧТО БЫЛО. Тренажёр печатал собственную лестницу из
   рем-долей: 25,6 / 16,8 / 16 / 15,2 / 14,7 / 14,4 / 13,6 / 12,8 / 12 px —
   девять ступеней в полосе 12…25,6 px с шагом 0,4…0,8 px. Из них на портале
   существуют ровно две: 16 и 12. Портал печатает 30 / 23 / 19 / 16 / 15 / 13 /
   12 / 11 — семь ступеней, шаг от 1 до 7 px. Это и есть «не премиум», сказанное
   числом: не «мелко», а «шага нет».

   Три следствия того же замера, каждое видно глазами:
   • h1 тренажёра был 25,6 px — МЕНЬШЕ, чем h1 статьи (30 px), и вдвое меньше,
     чем h1 /fts/practice/ (48 px). Заголовок раздела был самым мелким h1
     портала;
   • единственный h2 хаба («Ваше состояние») не имел правила вовсе и печатался
     умолчанием браузера — 24 px; на страницах разделов h2 равнялся 16 px, то
     есть размеру основного текста. Иерархии не было ни там, ни там;
   • интерлиньяж 1,6 стоял на ВСЁМ, включая заголовки: h1 25,6/41 px. Портал
     держит 1,18 у h1, 1,3 у h2/h3 и 1,6…1,74 у прозы. Заголовок с интерлиньяжем
     текста — самый заметный признак вёрстки без шкалы.

   Заливку и семейство шрифта по-прежнему держит портал (body.courses-body):
   своя заливка на <main> закрыла бы фоновый слой портала, а своё семейство
   набрало бы задания не тем начертанием, что соседние страницы.

   Отступы — тоже портальные: 24 px сверху и 40 px снизу берутся у .portal-main,
   20 px по бокам — у .portal-shell. До этой правки здесь стояло
   `padding: 0 1rem 4rem`, и нулевой верхний отступ прижимал h1 вплотную к
   липкой шапке. */
.learn {
  padding: 24px 20px 40px;
  color: var(--learn-text);
  font-size: 16px;
  line-height: 1.6;
}

/* 820 px — ширина колонки статьи (.reader-layout в courses-v2.css), а не 54rem,
   набранные здесь когда-то от руки. Мера строки у заданий не может быть шире
   меры строки у материала: читает их один и тот же человек. Хабу ширина
   переопределяется ниже — там две колонки. */
.learn__wrap {
  max-width: 820px;
  margin: 0 auto;
}

/* Лестница заголовков — портальная. h1 повторяет .article-header h1 (30/1.18,
   вес 750), h2 — .reader-content h2 (23/1.3), h3 — .reader-content h3 (19/1.3).
   Правило на h2 появилось впервые: раньше его не было ни одного. */
.learn h1 {
  font-size: 30px;
  font-weight: 750;
  line-height: 1.18;
  margin: 0;
}

/* Только прямой ребёнок обёртки. `.learn h2` здесь стоять не может: шапки
   свёрток и оговорки — тоже h2, селектор `.learn h2` весит (0,1,1) и побеждает
   `.learn-fold__head` (0,1,0). Замер поймал это сразу: каждая свёрнутая свёртка
   получала +48 px чужой отбивки, и страницы разделов стали выше, чем были. */
.learn__wrap > h2 {
  font-size: 23px;
  line-height: 1.3;
  margin: 32px 0 16px;
}

.learn a {
  color: var(--learn-accent);
}

.learn__top {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: baseline;
  padding: 0 0 16px;
  border-bottom: 1px solid var(--learn-border);
}

/* 13 px — размер ссылки-действия портала (.fts-button, подписи читалки). */
.learn__top nav {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 13px;
}

/* Лид повторяет .article-header__lead: 15/1.6, приглушённый. */
.learn__lead {
  color: var(--learn-muted);
  font-size: 15px;
  line-height: 1.6;
  margin: 14px 0 0;
}

/* Число заданий стояло отдельным абзацем на месте описания — то есть занимало
   строку текста ради двух знаков. Теперь это подпись в шапке рядом с
   заголовком, и на первом экране она не стоит ничего. Кегль — .article-meta
   (11 px): это мета, а не текст. */
.learn__count {
  margin: 0;
  color: var(--learn-muted);
  font-size: 11px;
}

/* ----------------------------------------------- раскрывающиеся блоки

   Оговорка живёт под щитом, служебная подпись — под «i». Свёрнутое состояние
   ставит скрипт (js/learn-fold.js), а НЕ эти правила: правило по классу .js
   спрятало бы текст у каждого, до кого скрипт не доехал. Поэтому ниже нет ни
   одного `display: none` для .learn-fold__body — его прячет атрибут hidden,
   выставленный скриптом, и снять его может только он же. */

.learn-fold {
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius);
  background: var(--learn-panel);
  padding: 12px 16px;
  margin: 16px 0;
}

.learn-fold--shield {
  border-left: 4px solid var(--learn-warn);
}

/* Шапка блока — h2 по разметке, но по роли это строка управления, а не
   заголовок раздела. Поэтому кегль здесь не 23 px, а 16 px — ступень
   .reader-content h4, и интерлиньяж заголовочный (1,3), а не текстовый. */
.learn-fold__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 16px;
  line-height: 1.3;
}

.learn-fold__icon {
  flex: none;
  width: 1rem;
  height: 1rem;
}

.learn-fold--shield .learn-fold__icon {
  color: var(--learn-warn);
}

.learn-fold--note .learn-fold__icon,
.learn-fold--inline .learn-fold__icon {
  color: var(--learn-muted);
}

.learn-fold__label {
  min-width: 0;
}

/* Кнопка прижата к правому краю строки, но на узком экране переносится под
   подпись, а не режет её: заголовок обязан читаться целиком и на 390px. */
.learn-fold__toggle {
  margin-left: auto;
  font-size: 12px;
  padding: 4px 12px;
}

.learn-fold__body {
  margin-top: 12px;
}

.learn-fold__body > :first-child {
  margin-top: 0;
}

.learn-fold__body > :last-child {
  margin-bottom: 0;
}

/* Служебная подпись внутри задания: не карточка внутри карточки, а строка. */
.learn-fold--inline {
  border: 0;
  background: none;
  padding: 0;
  margin: 12px 0 0;
}

.learn-fold--inline .learn-fold__head {
  font-size: 13px;
  color: var(--learn-muted);
  gap: 6px;
}

.learn-fold--inline .learn-fold__toggle {
  margin-left: 0;
  font-size: 12px;
  padding: 2px 10px;
}

.learn__notice {
  border: 1px solid var(--learn-border);
  border-left: 4px solid var(--learn-warn);
  border-radius: var(--learn-radius);
  padding: 16px 18px;
  margin: 20px 0;
  background: var(--learn-panel);
}

.learn__notice h2 {
  font-size: 16px;
  line-height: 1.3;
  margin: 0 0 8px;
}

.learn__notice ul {
  margin: 8px 0 0;
  padding-left: 20px;
}

.learn__notice li + li {
  margin-top: 6px;
}

.learn-cards {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  padding: 0;
  list-style: none;
  margin: 20px 0;
}

.learn-card {
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius);
  padding: 18px;
  background: var(--learn-panel);
}

/* 19 px — .reader-content h3 и .fts-case-card h3. Было 1,05rem = 16,8 px, то
   есть на 0,8 px крупнее основного текста: заголовок, неотличимый от абзаца. */
.learn-card h3 {
  margin: 0 0 8px;
  font-size: 19px;
  line-height: 1.3;
}

.learn-card p {
  margin: 0 0 10px;
  color: var(--learn-muted);
  font-size: 15px;
  line-height: 1.6;
}

/* 18/20 — не «на глаз поменьше», а бюджет: карточка задания повторяется 67 раз
   на /learn/fallacies/, и каждые лишние 4 px её полей стоят странице 268 px.
   Внутренний ритм задан отбивкой абзаца читалки (18 px в .reader-content). */
.learn-task {
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius);
  padding: 18px 20px;
  margin: 16px 0;
  background: var(--learn-panel);
}

.learn-task__head {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
}

.learn-task h3 {
  margin: 0;
  font-size: 19px;
  line-height: 1.3;
}

/* Ярлык вида задания — та же подпись, что .fts-kicker: 11 px, моноширинный,
   разрядка 0,06em, прописные. Одно место на портале, где мелкий кегль уместен,
   и потому он взят целиком, а не выдуман заново. */
.learn-task__kind {
  font-size: 11px;
  font-family: var(--digitable-font-mono, ui-monospace, monospace);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius-pill);
  padding: 2px 9px;
  color: var(--learn-muted);
}

.learn-task__prompt {
  white-space: pre-line;
}

.learn-task__brief {
  font-size: 15px;
  line-height: 1.6;
  color: var(--learn-muted);
  border-left: 2px solid var(--learn-border);
  padding-left: 12px;
  margin: 12px 0;
}

/* Компетенция, идентификатор и источник — мета, ступень .article-meta (11 px). */
.learn-task__meta {
  font-size: 11px;
  color: var(--learn-muted);
  margin: 12px 0 0;
}

.learn-options {
  border: 0;
  margin: 12px 0;
  padding: 0;
}

.learn-options legend {
  font-size: 13px;
  color: var(--learn-muted);
  padding: 0;
}

.learn-options label {
  display: block;
  padding: 4px 0;
  cursor: pointer;
}

.learn-answer {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 12px 0;
}

.learn-answer input[type='text'] {
  flex: 1 1 12rem;
  min-width: 8rem;
  padding: 8px 10px;
  border-radius: var(--learn-radius-sm);
  border: 1px solid var(--learn-border);
  background: var(--learn-bg);
  color: var(--learn-text);
  font: inherit;
}

/* Редактор модели набран как редактор моделей портала
   (.fts-playground__editor textarea): моноширинный, интерлиньяж 1,7. Кегль
   13 px — ступень портала; 13/1,5, стоявшие здесь, ступени не имели. */
.learn-task textarea {
  width: 100%;
  min-height: 12rem;
  padding: 12px;
  border-radius: var(--learn-radius-sm);
  border: 1px solid var(--learn-border);
  background: var(--learn-bg);
  color: var(--learn-text);
  font: 13px/1.7 var(--digitable-font-mono, ui-monospace, monospace);
  resize: vertical;
}

/* 12 px и вес 600 — .article-mode-button, кнопка режима читалки. */
.learn button {
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 7px 14px;
  border-radius: var(--learn-radius-pill);
  border: 1px solid var(--learn-accent);
  background: transparent;
  color: var(--learn-accent);
  cursor: pointer;
}

/* Заливка на наведении выводится из акцента, а не набрана как rgba(0,229,229).
   Тот же цвет числом не следовал за светлой темой: там --learn-accent
   становится #0a6d78, а подсветка оставалась ярко-бирюзовой. */
.learn button:hover {
  background: color-mix(in srgb, var(--learn-accent) 12%, transparent);
}

.learn-verdict {
  margin: 12px 0 0;
  padding: 10px 12px;
  border-radius: var(--learn-radius-sm);
  border: 1px solid var(--learn-border);
  font-size: 15px;
  line-height: 1.6;
}

/* ВЕРДИКТА ЕЩЁ НЕ ВЫНОСИЛИ: с экрана убран, из дерева доступности — нет.

   Это `role="status"`, живая область. Диктор объявляет ИЗМЕНЕНИЕ узла, который
   он уже знает, поэтому узел обязан стоять в дереве с загрузки страницы — до
   того, как в него приедет первый вердикт. Отсюда все три запрета разом:
   ни `display: none`, ни `visibility: hidden`, ни атрибут `hidden` — каждый из
   них выносит узел из дерева, и объявление становится делом случая (замерено
   снимком дерева Chromium, см. features/browser/learning-engine.feature).

   Остаётся приём visually-hidden: клип в 1×1 без выхода из потока дерева. Он
   же стоит у .workbench-recovery .workbench-field span — второй способ заводить
   не стали.

   Признак «пусто» — отсутствие data-tone. Атрибут ставит скрипт вместе с
   текстом, сервер не печатает его никогда; правило по :empty держалось бы на
   отсутствии переноса строки внутри тега и от косметической правки генератора
   дало бы пустую рамку под каждым из 113 заданий. */
.learn-verdict:not([data-tone]) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.learn-verdict[data-tone='passed'] {
  border-color: var(--learn-ok);
  color: var(--learn-ok);
}

.learn-verdict[data-tone='failed'] {
  border-color: var(--learn-fail);
  color: var(--learn-fail);
}

.learn-verdict[data-tone='self'],
.learn-verdict[data-tone='empty'] {
  border-color: var(--learn-warn);
  color: var(--learn-warn);
}

/* Разбор — это то, что на страницах разделов читают больше всего: 21 089 знаков
   из 48 806 на /learn/fallacies/. Он стоял на 15,2 px — кегле, которого на
   портале нет нигде. Теперь 15 px, ступень лида статьи. */
.learn-explain {
  margin-top: 12px;
  font-size: 15px;
  line-height: 1.6;
}

.learn-explain h4 {
  margin: 12px 0 4px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--learn-muted);
}

.learn-task details summary {
  cursor: pointer;
  color: var(--learn-accent);
  font-size: 13px;
}

.learn-task pre {
  overflow-x: auto;
  background: var(--learn-bg);
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius-sm);
  padding: 12px;
  font-size: 12px;
  line-height: 1.7;
}

.learn-state {
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius);
  padding: 18px 20px;
  background: var(--learn-panel);
}

.learn-state textarea {
  width: 100%;
  min-height: 5rem;
  font: 12px/1.7 var(--digitable-font-mono, ui-monospace, monospace);
  background: var(--learn-bg);
  color: var(--learn-text);
  border: 1px solid var(--learn-border);
  border-radius: var(--learn-radius-sm);
  padding: 10px;
}

.learn-state__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0;
}

/* Подвал раздела — служебная проза, 13 px: то же, чем на портале набраны
   подписи под материалом. Отбивка 32 px вместо 40: у .reader-content ритм
   абзацев 18 px, и сорок пикселей пустоты перед пятью строками мелкого текста
   были не воздухом, а провалом. */
.learn-foot {
  margin-top: 32px;
  padding-top: 16px;
  border-top: 1px solid var(--learn-border);
  color: var(--learn-muted);
  font-size: 13px;
  line-height: 1.6;
}

/* ------------------------------------------------------- хаб в две колонки

   ЗАЧЕМ. Замер 2026-08-10 на 1440×900: документ хаба 1391 px при экране 900 —
   полтора экрана. При этом колонка занимала 864 px из 1440, то есть по 288 px
   пустоты с каждой стороны. Страница не помещалась по высоте, имея незанятой
   треть ширины: это и есть «занимает высоту выше viewport», сказанное причиной,
   а не жалобой.

   ЧТО СДЕЛАНО. На широком экране «Ваше состояние» уезжает в правую колонку — к
   карточкам разделов, а не под них. Ни одного слова не убрано и ни один блок не
   спрятан: меняется только то, где они стоят.

   ПОЧЕМУ dense. Разметку печатает генератор и её порядок трогать нельзя
   (scripts/build-learning-bank.mjs сверяет байты), а «Ваше состояние» стоит в
   ней ШЕСТЫМ — после карточек. Обычная раскладка сетки ставит элемент с
   заданной колонкой не выше курсора, то есть под карточками, и выигрыша не
   было бы. `grid-auto-flow: row dense` разрешает вернуться к первой свободной
   строке — правому столбцу достаётся высота карточек.

   ПОЧЕМУ 1100 px. Ниже этой ширины правая колонка (340 px) отбирает у карточек
   столько, что три карточки перестают становиться в ряд, и выигрыш по высоте
   съедается вторым рядом карточек. Замер — в отчёте задачи.

   `> h2` без класса — единственный h2, лежащий прямо в обёртке хаба: заголовки
   свёрток вложены в section. Это следствие того же запрета трогать разметку. */
@media (min-width: 1100px) {
  .learn-page--hub .learn__wrap {
    max-width: 1200px;
    display: grid;
    grid-auto-flow: row dense;
    grid-template-columns: minmax(0, 1fr) minmax(0, 400px);
    column-gap: 32px;
    align-content: start;
    /* Без этого элемент растягивается на высоту строки, а строку задаёт
       соседняя панель состояния: карточки разделов раздувались с 157 px до
       536 px и хаб становился ВЫШЕ, чем был до раскладки. */
    align-items: start;
  }

  .learn-page--hub .learn__top,
  .learn-page--hub .learn__lead,
  .learn-page--hub .learn-foot {
    grid-column: 1 / -1;
  }

  .learn-page--hub .learn-cards,
  .learn-page--hub .learn-fold {
    grid-column: 1;
  }

  .learn-page--hub .learn__wrap > h2,
  .learn-page--hub .learn-state {
    grid-column: 2;
  }

  /* В сетке вертикальный ритм задаёт строка, а не поля соседей: свои margin
     блоки отдают, иначе первая строка правой колонки уезжает вниз на 32 px
     заголовочной отбивки и обе колонки перестают начинаться с одного уровня. */
  .learn-page--hub .learn__wrap > h2 {
    margin: 16px 0 8px;
  }

  .learn-page--hub .learn-cards {
    margin: 16px 0;
  }

  .learn-page--hub .learn-fold {
    margin: 0 0 16px;
  }
}

/* Светлой темы здесь больше нет ни одной строкой, и это не пропажа: все девять
   цветов выше — псевдонимы --course-*, а те портал переопределяет под
   html[data-theme="light"] сам. Тема, выбранная читателем в шапке, доезжает до
   заданий тем же путём, что до остального портала, и до первой отрисовки. */
