/* ═══════════════════════════════════════════════════════════════════════════
   КОМПОНЕНТЫ ЯСНЫ — библиотека на ролях из core/tokeny.css.

   ЗАЧЕМ. Четырёх вещей в приложении не было вовсе: подтверждения (Dialog),
   короткого сообщения о сделанном (Snackbar), полосы-сообщения на экране
   (Banner) и оправы для пустого списка (EmptyState). Каждый экран решал это
   по-своему или не решал: тост существовал ровно один и только в Книге,
   «Скопировано» в Профиле было строкой внутри карточки, а на вопрос «выйти
   из партии?» отвечал системный confirm с английскими «OK / Cancel».
   Полоса-сообщение на Играх на ширине 360 обрезала свой же текст.

   ПРАВИЛА ФАЙЛА (из ds.md — самого файла в репозитории нет, см. шапку
   core/tokeny.css; ниже они выписаны целиком, искать больше негде):
     · ни одного #hex — только роли из tokeny.css;
     · ни одного !important — файл подключается после tokeny.css и до
       файла экрана, и ничего чужого не перекрашивает: он объявляет только
       свои классы с префиксом .ya-;
     · нажимаемое — не меньше 48×48, видимая высота может быть меньше;
     · высота передаётся подложкой из лестницы surface-container, тень
       только у диалога и тоста (уровни 5 и 5);
     · длительности и кривые — токенами; при «убрать анимации» их гасит
       утилита в tokeny.css.

   ПОДКЛЮЧЕНИЕ. Файл нужен всюду, где встречаются .ya-* классы. Пока строка
   подключения не проставлена на страницах, JS-помощник window.YasnaOkna
   (core/dialogs.js) дописывает <link> сам — по адресу уже подключённого
   core/tokeny.css, чтобы путь сходился и на вложенных страницах.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ ИКОНКИ · один набор на всё ══════════════════════════════════════════
   Раньше значков было три языка сразу: SVG-линии, эмодзи и юникод-глифы
   («✕», «›», «·», «✓», «★», «🔍»). Юникод рисуется системным шрифтом: своя
   толщина, своя базовая линия, и цветом роли он не красится.

   Здесь один набор: сетка 24, обводка 2, скруглённые концы, цвет —
   currentColor. Сделан масками, а не спрайтом <use href="файл.svg#имя">:
   ссылка в чужой файл в WebView без сети срабатывает не всегда, а маска —
   часть таблицы стилей и живёт там же, где цвет. Значок ставится одним
   пустым узлом: <span class="ya-ik ya-ik--zakryt"></span>.
   Эмодзи остаётся ровно один — зверь-аватар: это осознанно. */

.ya-ik{
  display:inline-block; flex:none; width:24px; height:24px;
  background-color:currentColor; vertical-align:-.25em;
  -webkit-mask:var(--ya-ik) center/contain no-repeat;
          mask:var(--ya-ik) center/contain no-repeat;
}
.ya-ik--18{ width:18px; height:18px; }   /* значок в подписи кнопки */
.ya-ik--48{ width:48px; height:48px; }   /* значок пустого состояния */

/* ═══ КНОПКА ══════════════════════════════════════════════════════════════
   Четыре вида одной кнопки вместо одиннадцати спецификаций залитой.
   Высота 48 (в карточке 40, во всю ширину 56), радиус 12, подпись Label L
   в одну строку. Нажатие — слой из собственного цвета текста, а не второй
   hex: «вторых синих» в системе больше нет. */

.ya-btn{
  position:relative; box-sizing:border-box;
  display:inline-flex; align-items:center; justify-content:center;
  gap:var(--sp-2);
  min-height:var(--h-btn); padding:0 var(--sp-6);
  border:none; border-radius:var(--shape-m);
  font:var(--type-label-l);
  white-space:nowrap; text-decoration:none; cursor:pointer;
  /* Подпись без заливки — это ТЕКСТ, и мера у него текстовая: сам --primary
     на подложке диалога давал 3.86, а «Оставить» и «Удалить» — это ответ на
     вопрос, и читаться он обязан лучше всего. Заливка ниже остаётся на
     --primary: белому на ней хватает 4.70. */
  background:transparent; color:var(--ya-primary-ink);
  transition:background-color var(--dur-short) var(--ease-standard);
}
.ya-btn--filled  { background:var(--ya-cta,var(--primary)); color:var(--ya-cta-on,var(--on-primary)); }
.ya-btn--tonal   { background:var(--secondary-container); color:var(--on-secondary-container); }
.ya-btn--outlined{ box-shadow:inset 0 0 0 1px var(--outline); color:var(--ya-primary-ink); }
.ya-btn--text    { padding:0 var(--sp-3); }
.ya-btn--compact { min-height:var(--h-btn-compact); }
.ya-btn--hero    { min-height:var(--h-btn-hero); width:100%; }

/* Слой нажатия одинаков для всех четырёх видов: доля берётся из токена,
   цвет — из собственной подписи кнопки. */
.ya-btn::after{
  content:''; position:absolute; inset:0; border-radius:inherit;
  background:currentColor; opacity:0; pointer-events:none;
  transition:opacity var(--dur-short) var(--ease-standard);
}
.ya-btn:active::after     { opacity:var(--state-pressed); }
.ya-btn:focus-visible     { outline:2px solid var(--primary); outline-offset:2px; }
.ya-btn:disabled{
  cursor:default;
  color:color-mix(in srgb, var(--on-surface) calc(var(--state-disabled-content) * 100%), transparent);
}
.ya-btn:disabled::after{ opacity:0; }
.ya-btn--filled:disabled, .ya-btn--tonal:disabled{
  background:color-mix(in srgb, var(--on-surface) calc(var(--state-disabled-fon) * 100%), transparent);
}

/* Кнопка только со значком: видимые 40, нажимаемые 48 добираются паддингом. */
.ya-ib{
  box-sizing:content-box;
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--h-ib); height:var(--h-ib);
  padding:calc((var(--cel-min) - var(--h-ib)) / 2);
  margin:calc((var(--h-ib) - var(--cel-min)) / 2);
  border:none; border-radius:var(--shape-full);
  background:transparent; color:var(--on-surface-variant); cursor:pointer;
}
.ya-ib:active{ background:color-mix(in srgb, currentColor calc(var(--state-pressed) * 100%), transparent); }
.ya-ib:focus-visible{ outline:2px solid var(--primary); outline-offset:-2px; }

/* ═══ ДИАЛОГ ══════════════════════════════════════════════════════════════
   Вопрос с глаголами на кнопках вместо системного confirm. Отказ стоит
   слева и держит фокус; закрытие без ответа — это отказ.
   Разметка: .ya-dialog > .ya-dialog__karta > (h2 + p + .ya-dialog__ryad). */

.ya-dialog{
  position:fixed; inset:0; z-index:9600;
  display:flex; align-items:center; justify-content:center;
  padding:var(--sp-6);
  background:var(--scrim);
  animation:ya-proyavit var(--dur-long) var(--ease-emphasized-decel);
}
/* СВОЯ ПРОКРУТКА У КАРТОЧКИ. Вопрос стоит в неподвижном слое: что вылезло за
   край экрана, страница не принесёт (проба 10.09.2026: scrollTop=200 карточку
   не сдвинул). При экране 390×420 и системном кегле ×2 длинный вопрос давал
   карточку 950 — обе кнопки-ответа оказывались за нижним краем, и ответить на
   вопрос было нечем. Процент считается от содержимого .ya-dialog, у которого
   уже вычтено поле sp-6; пока текст помещается — свойства молчат. */
.ya-dialog__karta{
  box-sizing:border-box; width:100%; max-width:340px;
  max-height:100%; overflow:auto; overscroll-behavior:contain;
  padding:var(--sp-6) var(--sp-6) var(--sp-2);
  border-radius:var(--shape-xl);
  background:var(--surface-container-high); color:var(--on-surface);
  box-shadow:var(--elev-5);
  animation:ya-vsplyt var(--dur-long) var(--ease-emphasized-decel);
}
.ya-dialog__znak{ display:block; margin:0 auto var(--sp-3); color:var(--secondary); }
.ya-dialog__zag{ margin:0 0 var(--sp-2); font:var(--type-headline-s); }
.ya-dialog__txt{ margin:0; font:var(--type-body-m); color:var(--on-surface-variant); }
/* Кнопки прижаты вправо и переносятся на вторую строку, если подписи-глаголы
   длинные: обрезать глагол нельзя — он и есть ответ на вопрос. */
.ya-dialog__ryad{
  display:flex; flex-wrap:wrap; justify-content:flex-end;
  gap:var(--sp-1); margin-top:var(--sp-4);
}
.ya-dialog__karta .ya-btn--opasno{ color:var(--error); }

@keyframes ya-proyavit{ from{ opacity:0 } to{ opacity:1 } }
@keyframes ya-vsplyt{ from{ opacity:0; transform:translateY(12px) scale(.96) } to{ opacity:1; transform:none } }

/* ═══ ТОСТ ════════════════════════════════════════════════════════════════
   Короткое сообщение о том, что уже сделано. Встаёт над наббаром: его
   высоту оболочка держит в --yk-nav, на сайте наббара нет — там 16.
   Инверсная подложка, 11.4:1 к подписи. */

.ya-snack{
  position:fixed; z-index:9500;
  left:var(--sp-4); right:var(--sp-4);
  bottom:calc(var(--yk-nav, 16px) + var(--sp-2));
  box-sizing:border-box;
  display:flex; align-items:center; gap:var(--sp-2);
  min-height:var(--cel-min);
  max-width:560px; margin:0 auto;
  padding:var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  border-radius:var(--shape-s);
  background:var(--inverse-surface); color:var(--inverse-on-surface);
  box-shadow:var(--elev-5);
  animation:ya-vsplyt var(--dur-medium) var(--ease-emphasized-decel);
}
.ya-snack__txt{ flex:1; min-width:0; font:var(--type-body-m); }
/* Действие тоста красится инверсной подписью, а не primary: на тёмной
   подложке светлой темы синий даёт меньше трёх. */
.ya-snack .ya-btn{ color:inherit; min-height:var(--h-btn-compact); }
.ya-snack--uhodit{ animation:ya-uyti var(--dur-medium) var(--ease-emphasized-accel) forwards; }

@keyframes ya-uyti{ to{ opacity:0; transform:translateY(8px) } }

/* ═══ ПОЛОСА-СООБЩЕНИЕ ════════════════════════════════════════════════════
   То, что раньше рисовал каждый экран сам: обновление на Главной, «уроки на
   сервере» на Играх, бежевая заметка Рейтинга, пунктирная строка Уроков.
   На Играх такая полоса на ширине 360 обрезала собственный текст, поэтому
   здесь: текстовая колонка min-width:0, заголовок без nowrap, ряд действий
   без flex-shrink:0 и с переносом. */

.ya-banner{
  box-sizing:border-box;
  display:flex; align-items:flex-start; gap:var(--sp-3);
  padding:var(--sp-4);
  border-radius:var(--shape-l);
  background:var(--surface-container); color:var(--on-surface);
}
.ya-banner__znak{ color:var(--secondary); margin-top:2px; }
.ya-banner__telo{ flex:1 1 auto; min-width:0; }
.ya-banner__zag{ margin:0 0 var(--sp-1); font:var(--type-title-s); overflow-wrap:anywhere; }
.ya-banner__txt{ margin:0; font:var(--type-body-m); color:var(--on-surface-variant); overflow-wrap:anywhere; }
.ya-banner__ryad{
  display:flex; flex-wrap:wrap; justify-content:flex-end;
  gap:var(--sp-1); margin-top:var(--sp-2);
}
.ya-banner--vnimanie{ background:var(--tertiary-container); color:var(--on-tertiary-container); }
.ya-banner--vnimanie .ya-banner__znak,
.ya-banner--vnimanie .ya-banner__txt{ color:inherit; }

/* ═══ ПУСТОЕ СОСТОЯНИЕ ════════════════════════════════════════════════════
   Раньше это был просто абзац посреди экрана. Слова остаются те же —
   меняется только оправа: значок, заголовок, объяснение и, если есть что
   предложить, одна кнопка. */

.ya-empty{
  display:flex; flex-direction:column; align-items:center; text-align:center;
  gap:var(--sp-2); padding:var(--sp-8) var(--sp-4);
}
.ya-empty__znak{ color:var(--on-surface-variant); margin-bottom:var(--sp-1); }
.ya-empty__zag{ margin:0; font:var(--type-title-m); color:var(--on-surface); }
.ya-empty__txt{ margin:0; max-width:34ch; font:var(--type-body-m); color:var(--on-surface-variant); }
.ya-empty .ya-btn{ margin-top:var(--sp-2); }

/* ═══ ПОДСКАЗКА · .ya-podskazka ════════════════════════════════════════
   ЗАЧЕМ. Пояснение к полю жило абзацем под полем и съедало экран: в форме
   правки профиля такие абзацы занимали пятую часть высоты. Пояснение нужно
   не всем и не всегда — тем, кому непонятно, и в тот миг, когда непонятно.
   Значит его место — за знаком «?» у метки, а внутри поля серым стоит
   пример того, что вписывать.

   РАЗМЕТКА. Кнопка, а не иконка: до неё доходит клавиатура, и тултип
   открывается и по наведению, и по фокусу. Текст лежит в самой разметке, а
   не в title (title на телефоне не показывается вовсе). Тот же текст
   связывают с полем через aria-describedby — диктор слышит его как
   описание поля, тултип ему не нужен.

     <label class="ya-pole__metka" for="tel">Телефон
       <button class="ya-podskazka" type="button" aria-label="Пояснение"
               aria-describedby="tel-pod">
         <span class="ya-podskazka__tekst" id="tel-pod" role="tooltip">
           Видишь только ты. Пригодится, когда попросишь посчитать имя.
         </span>
       </button>
     </label>
     <input class="ya-pole__vvod" id="tel" aria-describedby="tel-pod">

   Нажимаемая цель у знака — --h-btn-compact (40): он стоит внутри строки
   метки, и 48 раздвинули бы строку; 40 — минимум, который система допускает
   для вспомогательного. На телефоне тултип открывает/закрывает касание
   (класс .ya-podskazka--otkryta + core/podskazka.js): второй тап по тому же
   «?» снимает класс и blur — иначе :focus оставлял бы пузырь открытым
   навсегда. На столе — :hover; с клавиатуры — :focus-visible.

   ЯКОРЬ. По умолчанию тултип прижат к ПРАВОМУ краю кнопки (right:0) и растёт
   влево: «?» у правого края полной строки (шаги «Свои люди») иначе уезжал
   за экран и раздувал документ вбок. У меток поля (.ya-pole__metka) «?»
   стоит у левого края после короткого слова — там оставляем рост вправо,
   как раньше. max-width + overflow-wrap + box-sizing не дают пузырю стать
   шире экрана; html:not(.yk-shire){overflow-x:clip} ниже — страховка, чтобы
   даже ошибочный абсолют не паннул страницу (карусели со своим
   overflow-x:auto не страдают). */
.ya-podskazka{
  box-sizing:border-box;position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:var(--h-btn-compact);height:var(--h-btn-compact);margin:calc(var(--sp-2)*-1) 0;
  padding:0;border:0;background:transparent;cursor:help;vertical-align:middle;
  color:var(--on-surface-variant)}
.ya-podskazka::before{
  content:'?';display:inline-grid;place-content:center;width:18px;height:18px;
  border:1.5px solid currentColor;border-radius:var(--shape-full);
  font:var(--type-label-s);font-weight:700;line-height:1}
.ya-podskazka:hover,.ya-podskazka:focus-visible,.ya-podskazka--otkryta{color:var(--primary);outline:none}
.ya-podskazka:focus-visible::before{outline:2px solid var(--primary);outline-offset:2px}
.ya-podskazka__tekst{
  position:absolute;right:0;left:auto;bottom:calc(100% + 4px);
  box-sizing:border-box;width:max-content;max-width:min(280px,calc(100vw - 24px));
  padding:var(--sp-2) var(--sp-3);overflow-wrap:anywhere;
  font:var(--type-body-s);line-height:1.45;text-align:left;text-transform:none;letter-spacing:0;
  color:var(--on-surface);background:var(--surface-container-highest);
  border:1px solid var(--outline-variant);border-radius:var(--shape-s);box-shadow:var(--elev-2);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s;z-index:5}
/* Метка поля: «?» у левого края — расти вправо, иначе обрежется слева. */
.ya-pole__metka .ya-podskazka__tekst,
.metka .ya-podskazka__tekst{
  left:calc(var(--sp-2)*-1);right:auto}
/* Открытие: класс (тап/клик, core/podskazka.js), :hover на мыши, :focus-visible
   с клавиатуры. Голый :focus не держим — на телефоне второй тап по уже
   сфокусированной кнопке не снимает фокус, и пузырь оставался бы открытым. */
.ya-podskazka:hover .ya-podskazka__tekst,
.ya-podskazka--otkryta .ya-podskazka__tekst,
.ya-podskazka:focus-visible .ya-podskazka__tekst{opacity:1;visibility:visible}
@media (prefers-reduced-motion: reduce){ .ya-podskazka__tekst{transition-duration:.001s} }

/* Страховка ширины документа (сайт и страницы с komponenty.css). clip, не
   hidden: не создаёт скроллпорт и не ломает sticky; намеренные ленты со
   своим overflow-x:auto остаются. Opt-out: html.yk-shire / data-yk-shire
   на body (см. app/navigatsiya.js). */
@supports (overflow-x:clip){
  html:not(.yk-shire){overflow-x:clip}
}

/* ═══ ПОЛЕ ВВОДА ══════════════════════════════════════════════════════════
   ЗАЧЕМ. Поля в продукте нарисованы шестью разными высотами и пятью кеглями:
   24 при кегле 10 и 30 при 12 в Разборе (core/dialogs.js:410,417), 29 при
   12.5 в подписи места (app.js:2064 — полупиксельных кеглей шкала не знает),
   38 при 14 в админке, 39 при 17 в имени ясны, 56 при 17 во входе и ключе.
   Три из шести вдвое ниже порога нажатия 48, который система объявляет
   обязательным. Здесь одно поле на всё: высота --h-pole, кегль Body L.

   КЕГЛЬ НЕ НИЖЕ 16 — не про красоту. Телефон приближает страницу при фокусе
   в поле мельче 16, а отдалить её человек уже не может: приложение открыто
   без адресной строки. Body L это 17.

   РАЗМЕТКА. Оборачивать всё в <label> нельзя: имя поля собирается из ВСЕГО
   текста метки, и диктор читает «Имя Одно дело, а не тема целиком 15 из 80».
   Метка отдельным узлом и связана через for/id; подсказка, счётчик и ошибка
   приходят описанием:

     <div class="ya-pole">
       <label class="ya-pole__metka" for="imya">Имя</label>
       <input class="ya-pole__vvod" id="imya" aria-describedby="imya-pod imya-schet">
       <div class="ya-pole__niz">
         <p class="ya-pole__pod" id="imya-pod">
           <span class="ya-ik ya-ik--18 ya-pole__znak ya-ik--vnimanie"></span>
           Одно дело, а не тема целиком
         </p>
         <span class="ya-pole__schet" id="imya-schet">15 из 80</span>
       </div>
     </div>

   ОШИБКА — класс .ya-pole--beda на обёртку И aria-invalid="true" на поле.
   Цвет не единственный признак: в беде проступает значок, а слово подсказки
   меняется на слово ошибки. Место под строку подсказки держится всегда
   (min-height 18 — высота строки Body S), иначе появление ошибки раздвигает
   экран и уводит кнопку из-под уже занесённого пальца: эту грабельку вход
   уже проходил (app/vhod.js:238-241).

   МНОГОСТРОЧНОЕ растёт за текстом скриптом экрана: на каждый ввод
   style.height='auto'; style.height=(scrollHeight+2)+'px' (двойка — рамка:
   scrollHeight её не считает, а высота при border-box считает, и без неё поле
   каждый раз ниже нужного на два пикселя и заводит себе прокрутку). Тот же
   счёт надо повторить по document.fonts.ready и по resize: до прихода
   гарнитуры строки меряются запасным шрифтом, выходят короче, и на первом же
   показе последняя строка уходит за нижнюю кромку (замерено: поле в 180
   встало 104), а крупный системный шрифт и поворот телефона перекладывают
   строки уже после разметки (замерено при ×1.3: нужно 398, стоит 208).
   field-sizing:content сделало бы это без скрипта, но для WebView оболочки оно
   слишком новое.
   maxlength не ставим: обрезать написанное молча нельзя — счётчик считает и
   за пределом, а поле уходит в .ya-pole--beda.

   ЗАМЕРЕНО при 375 (в каталоге, внутри оправы опыта): поле 309×56; на экране
   с полем 16 то же поле даёт 343×56. При 320 и системном шрифте ×1.3 поле
   растёт до 60 и вбок не выходит. Контраст (свет/тьма): метка
   16.79/14.74, подсказка и счётчик 6.07/6.90, слово ошибки 5.93/10.35,
   кайма поля 4.48/6.17 (норма графики 3), обводка фокуса 4.26/10.38. */

 /* РАСКЛАДКА — СЕТКА, И СЧЁТЧИК СТОИТ НАВЕРХУ, У МЕТКИ. Стоял он внизу, в одной
   строке с подсказкой, и они дрались за одну ширину: подсказка на два-три слова
   длиннее строки разворачивалась на две-три строки, а счётчик висел справа на
   первой — и читался как число про эту первую строку, а не про поле. Развели:
   счётчик к метке (число о поле — рядом с именем поля), подсказка под поле во
   всю ширину. Замерено при 375: подсказка получила 311 px вместо 254.
   Разметка при этом прежняя — __schet остаётся внутри __niz, а сам __niz отдаёт
   своих детей сетке поля (display:contents). Иначе пришлось бы переписывать
   разметку всюду, где поле уже стоит, и старая разметка сломалась бы молча. */
.ya-pole{
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  column-gap:var(--sp-3);
}
.ya-pole + .ya-pole{ margin-top:var(--sp-4); }

.ya-pole__metka{
  grid-column:1; align-self:baseline; margin:0 0 var(--sp-2);
  font:var(--type-title-s); color:var(--on-surface);
}
.ya-pole__vvod{
  grid-column:1 / -1;
  box-sizing:border-box; display:block; width:100%;
  min-height:var(--h-pole); padding:var(--sp-3) var(--sp-4);
  border:1px solid var(--outline); border-radius:var(--shape-s);
  background:var(--surface-container-lowest); color:var(--on-surface);
  font:var(--type-body-l);
  appearance:none; -webkit-appearance:none;
  transition:border-color var(--dur-short) var(--ease-standard);
}
/* Своя прокрутка, а не обрезка: пока скрипт экрана не вырастил поле, человек
   всё равно доберётся до написанного. resize оставлен вертикальный — на
   мониторе он даёт управу руками, на телефоне не мешает. */
textarea.ya-pole__vvod{ resize:vertical; overflow-y:auto; }
.ya-pole__vvod::placeholder{ color:var(--on-surface-variant); opacity:1; }
/* У поля — :focus, а не :focus-visible, как у кнопки. Кнопке кольцо под мышью
   не нужно, полю нужно всегда: в него пишут, и человек обязан видеть, куда
   попадёт буква. К тому же :focus-visible на поле срабатывает не при всяком
   способе входа (проверено: фокус скриптом его не даёт), и вместо нашего
   кольца проступало системное — 3px чёрным без отступа. */
.ya-pole__vvod:focus{
  outline:2px solid var(--primary); outline-offset:2px;
  border-color:var(--primary);
}
.ya-pole__vvod:disabled{
  cursor:default;
  color:color-mix(in srgb, var(--on-surface) calc(var(--state-disabled-content) * 100%), transparent);
  border-color:color-mix(in srgb, var(--on-surface) calc(var(--state-disabled-fon) * 100%), transparent);
  background:transparent;
}

/* Обёртка низа сама по себе больше ничего не занимает: она отдаёт подсказку и
   счётчик сетке поля, а те встают каждый на своё место. */
.ya-pole__niz{ display:contents; }
/* Место под строку подсказки занято всегда — даже когда сказать нечего: иначе
   появление ошибки раздвигает экран и уводит кнопку из-под пальца. */
.ya-pole__pod{
  grid-column:1 / -1; min-width:0; min-height:18px; margin:var(--sp-2) 0 0;
  display:flex; align-items:flex-start; gap:var(--sp-1);
  font:var(--type-body-s); color:var(--on-surface-variant);
  overflow-wrap:anywhere;
}
.ya-pole__schet{
  grid-column:2; grid-row:1; align-self:baseline; justify-self:end;
  font:var(--type-label-s); line-height:18px; color:var(--on-surface-variant);
  font-variant-numeric:tabular-nums;
}
/* Значок ошибки лежит в разметке всегда и молчит, пока беды нет: так экран
   переключает состояние одним классом, а не перестройкой узлов. */
.ya-pole__znak{ display:none; }

.ya-pole--beda .ya-pole__vvod{ border-color:var(--error); }
.ya-pole--beda .ya-pole__vvod:focus{ border-color:var(--error); }
.ya-pole--beda .ya-pole__pod{ color:var(--error); }
.ya-pole--beda .ya-pole__schet{ color:var(--error); }
.ya-pole--beda .ya-pole__znak{ display:inline-block; }

/* ═══ ПАРА ПОЛЕЙ ══════════════════════════════════════════════════════════
   Два поля под одной мыслью: «Одна сторона / Другая сторона», «Что прибывает
   / Что убывает». На телефоне столбиком, от 600 — рядом. Порог 600, а не 360:
   при 375 два поля дают по 139 внутренних пикселей, и «Первый признак
   перемены» кеглем 17 ложится в четыре строки.

   Общая мысль — не заголовок, а имя группы. Обёртке ставят role="group" и
   aria-labelledby на эту мысль, иначе диктор прочитает два поля подряд,
   ничем не связанные:

     <div class="ya-para" role="group" aria-labelledby="storony-mysl">
       <span class="ya-para__mysl" id="storony-mysl">Две стороны</span>
       <div class="ya-para__ryad"> …два .ya-pole… </div>
     </div> */

.ya-para{ display:block; }
.ya-para__mysl{
  display:block; margin:0 0 var(--sp-3);
  font:var(--type-title-s); color:var(--on-surface);
}
.ya-para__ryad{ display:grid; grid-template-columns:1fr; gap:var(--sp-4); }
/* Зазор даёт сетка — соседский отступ поля здесь только сложился бы с ним. */
.ya-para__ryad > .ya-pole + .ya-pole{ margin-top:0; }
@media (min-width:600px){
  .ya-para__ryad{ grid-template-columns:1fr 1fr; gap:var(--sp-3); align-items:start; }
}
/* РАМКИ ДВУХ ПОЛЕЙ ВСТАЮТ НА ОДНОЙ ВЫСОТЕ. Когда поля стоят рядом, подпись
   левого может занять две строки, а правого одну — и рамка левого уезжает
   вниз на строку (замерено при 720: 20 px разницы, «Что прибывает по дороге к
   стороне «Разговор»» против «Что убывает по дороге назад»). Два поля — две
   отдельные сетки, и сами по себе их строки не сходятся.
   Ровняет подписи скрипт экрана: он берёт высоту самой высокой подписи в ряду
   и ставит её остальным (min-height), а при переходе на телефон снимает.
   Подсказка ниже не в счёт — она стоит уже под рамкой.
   Почему не subgrid: у поля бывает и четвёртый ряд (у мастера «Своя ясна» под
   полем стоит своя тихая строка), а subgrid жёстко считает ряды и лишний
   ребёнок ложится поверх последнего. К тому же subgrid слишком нов для
   WebView оболочки — по той же причине здесь скриптом растят и многострочное
   поле. */

/* ═══ ШАГОМЕР ═════════════════════════════════════════════════════════════
   Где человек в маршруте. Сперва слова, потом полоса — и слова главные:
   «шаг 4 из 10» читается и глазами, и вслух, а полоса добавляет к ним меру.

   ПОЧЕМУ НЕ ТОЧКИ. Шаги уроков нарисованы точками 6×6 и спрятаны от диктора
   (aria-hidden) — то есть человеку с диктором о шагах не говорят вовсе, а
   человеку с глазами предлагают считать точки. Десять точек на 320 не
   считаются. Здесь наоборот: строка словами — единственное, что слышит
   диктор, а жёлобу ставят aria-hidden="true", потому что он повторяет её.
   Второй раз то же число вслух — это не доступность, а помеха.

   Долю ставит экран: style.setProperty('--ya-dolya', '40%').
   ЗАМЕРЕНО: заливка на жёлобе 3.86/8.95, заливка на фоне экрана 4.42/11.05 и
   на карточке 4.26/10.38 (норма графики 3); номер шага 17.41/15.69, имя шага
   6.29/7.34. Сам жёлоб на фоне тихий (1.10) — он и должен быть тихим: меру
   несёт заливка, а правду несут слова. Высота 6 — единственное число здесь,
   под которое в шкале формы роли нет; взято с полосы урока, где оно уже
   проверено (docs/learn.html:244-251). */

.ya-shagi{ display:block; }
.ya-shagi__stroka{
  display:flex; flex-wrap:wrap; align-items:baseline;
  gap:var(--sp-1) var(--sp-3); margin:0 0 var(--sp-2);
}
/* Число шага не обрезаем никогда: ради него строку и читают. */
.ya-shagi__nomer{
  flex:0 0 auto;
  font:var(--type-label-l); color:var(--on-surface);
  font-variant-numeric:tabular-nums;
}
.ya-shagi__imya{
  flex:1 1 10em; min-width:0; text-align:right;
  font:var(--type-body-s); color:var(--on-surface-variant);
  overflow-wrap:anywhere;
}
.ya-shagi__zhelob{
  height:6px; border-radius:var(--shape-full);
  background:var(--surface-container-high); overflow:hidden;
}
.ya-shagi__zaliv{
  display:block; height:100%; width:var(--ya-dolya, 0%);
  border-radius:inherit; background:var(--primary);
  transition:width var(--dur-medium) var(--ease-standard);
}

/* ═══ СКЛАДКА ═════════════════════════════════════════════════════════════
   Справка, которая не мешает: закрыта, пока её не спросили. Собрана на
   родном <details> — он сам даёт клавиатуру, aria-expanded и связь заголовка
   с телом; своих кнопок с aria-expanded в наборе не заводим.

   Разметка: <details class="ya-skladka"><summary>…</summary>
             <div class="ya-skladka__telo">…</div></details>

   Стрелка своя: системный треугольник рисуется шрифтом, у него своя толщина
   и своя базовая линия, и цветом роли он не красится. Разворот стрелки гасит
   утилита «убрать анимации» из tokeny.css. Строка нажатия — 48 сама по себе,
   добирать паддингом ничего не нужно; длинная справка переносится и строка
   растёт. ЗАМЕРЕНО: подпись складки 5.62/10.38. */

.ya-skladka{ display:block; }
.ya-skladka > summary{
  display:flex; align-items:center; gap:var(--sp-2);
  min-height:var(--cel-min); padding:var(--sp-2) 0;
  border-radius:var(--shape-s);
  font:var(--type-label-l); color:var(--ya-primary-ink);
  cursor:pointer; list-style:none;
}
.ya-skladka > summary::-webkit-details-marker{ display:none; }
.ya-skladka > summary::marker{ content:''; }
.ya-skladka > summary:focus-visible{ outline:2px solid var(--primary); outline-offset:2px; }
.ya-skladka__strelka{
  flex:none;
  transition:transform var(--dur-short) var(--ease-standard);
}
.ya-skladka[open] > summary .ya-skladka__strelka{ transform:rotate(180deg); }
.ya-skladka__telo{
  margin:0 0 var(--sp-2) var(--sp-1);
  padding-left:var(--sp-3); border-left:2px solid var(--outline-variant);
  font:var(--type-body-m); color:var(--on-surface-variant);
  overflow-wrap:anywhere;
}
.ya-skladka__telo > :first-child{ margin-top:0; }
.ya-skladka__telo > :last-child{ margin-bottom:0; }

/* ═══ СТРОКА СПИСКА ═══════════════════════════════════════════════════════
   Имя, тихая приписка справа, стрелка. Вся строка — одна цель нажатия: не
   имя, не стрелка, а весь ряд. Ставится и ссылкой <a>, и кнопкой <button>.

   БЕЗ СВОЕЙ ПОДЛОЖКИ, НАРОЧНО. Карточка --surface-container-low на фоне
   экрана --surface даёт 1.04 — край такой карточки не виден вовсе, и список
   из трёх строк читался бы одной плитой. Поэтому строка прозрачная, а между
   строками идёт волосок --outline-variant (роль так и объявлена: только
   декоративные разделители). Строку опознаёт не край, а имя и стрелка —
   6.07/6.90. Хвостового волоска нет: линия стоит только МЕЖДУ строками, и
   список не заканчивается висящей чертой.

   Разметка:
     <button class="ya-stroka" type="button">
       <span class="ya-stroka__telo">
         <span class="ya-stroka__imya">Утро понедельника</span>
         <span class="ya-stroka__pripiska">12 из 12 мест · 8 сентября</span>
       </span>
       <span class="ya-ik ya-stroka__strelka ya-ik--vpered"></span>
     </button>

   ИМЯ И ПРИПИСКА — ОДИН ПЕРЕНОСЯЩИЙСЯ РЯД, а не две колонки сетки. Сетку
   «имя | приписка | стрелка» я сперва и поставил, и вот что она дала при 375:
   обычная строка «Утро понедельника · 12 из 12 мест · 8 сентября» выросла до
   84 вместо 48, а нарочно длинная — до 1084, потому что колонка приписки
   ужалась до одной буквы в строке. Здесь имя и приписка стоят в одном ряду с
   переносом: пока они помещаются рядом, приписка прижата вправо; не помещаются
   — она уходит строкой ниже и остаётся прижатой вправо. Стрелка вне ряда и
   потому не двигается никогда.
   ЗАМЕРЕНО при 375 и ширине строки 343: «Дорога · 1 из 12 мест» встаёт в одну
   строку и даёт 49; «Утро понедельника · 12 из 12 мест · 8 сентября» — 66,
   приписка ушла под имя и осталась справа; нарочно длинная — 104. Ни в одном
   случае вбок не выходит, цель нажатия ниже 48 не падает. При 320 и системном
   шрифте ×1.3 самая длинная даёт 201, и это по-прежнему одна строка списка, а
   не сломанная вёрстка. Контраст: имя 16.79/14.74, приписка и стрелка
   6.07/6.90, волосок 1.55/1.90 (он декоративный, строку опознают слова). */

.ya-stroka{
  position:relative; box-sizing:border-box;
  display:flex; align-items:center; gap:var(--sp-3);
  width:100%; min-height:var(--cel-min);
  padding:var(--sp-3) var(--sp-4);
  border:none; border-radius:var(--shape-m);
  background:transparent; color:var(--on-surface);
  font:inherit; text-align:left; text-decoration:none; cursor:pointer;
}
.ya-stroka + .ya-stroka{ border-top:1px solid var(--outline-variant); }
.ya-stroka__telo{
  flex:1 1 auto; min-width:0;
  display:flex; flex-wrap:wrap; align-items:baseline;
  column-gap:var(--sp-3); row-gap:var(--sp-1);
}
.ya-stroka__imya{
  flex:0 1 auto; min-width:0;
  font:var(--type-title-s); color:var(--on-surface);
  overflow-wrap:anywhere;
}
/* margin-left:auto держит приписку справа на любой строке ряда — и когда она
   стоит рядом с именем, и когда съехала под него. */
.ya-stroka__pripiska{
  flex:0 1 auto; min-width:0; margin-left:auto; text-align:right;
  font:var(--type-body-s); color:var(--on-surface-variant);
  overflow-wrap:anywhere;
}
.ya-stroka__strelka{ flex:none; color:var(--on-surface-variant); }
/* Слой нажатия из собственного цвета текста — тот же приём, что у кнопки. */
.ya-stroka::after{
  content:''; position:absolute; inset:0; border-radius:inherit;
  background:currentColor; opacity:0; pointer-events:none;
  transition:opacity var(--dur-short) var(--ease-standard);
}
.ya-stroka:active::after{ opacity:var(--state-pressed); }
/* Обводка внутрь: строка идёт во всю ширину, и наружное кольцо вылезло бы
   за край экрана и налезло на соседнюю строку. */
.ya-stroka:focus-visible{ outline:2px solid var(--primary); outline-offset:-2px; }

/* ═══ НАБОР ЗНАЧКОВ ═══════════════════════════════════════════════════════
   Сгенерирован из одних и тех же путей: сетка 24, обводка 2, концы круглые.
   Добавлять значок — только сюда. */
.ya-ik--nazad{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 5 8 12 15 19'/%3E%3C/svg%3E")}
.ya-ik--vpered{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5 16 12 9 19'/%3E%3C/svg%3E")}
.ya-ik--vverh{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 15 12 8 19 15'/%3E%3C/svg%3E")}
.ya-ik--vniz{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 9 12 16 19 9'/%3E%3C/svg%3E")}
.ya-ik--zakryt{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6 18 18M18 6 6 18'/%3E%3C/svg%3E")}
.ya-ik--galochka{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13 10 18 19 7'/%3E%3C/svg%3E")}
.ya-ik--plus{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E")}
.ya-ik--poisk{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='6'/%3E%3Cpath d='M15.6 15.6 20 20'/%3E%3C/svg%3E")}
.ya-ik--karandash{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20h4L20 8l-4-4L4 16Z'/%3E%3Cpath d='M14 6l4 4'/%3E%3C/svg%3E")}
.ya-ik--tochki{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='5' cy='12' r='1.6' fill='black' stroke='none'/%3E%3Ccircle cx='12' cy='12' r='1.6' fill='black' stroke='none'/%3E%3Ccircle cx='19' cy='12' r='1.6' fill='black' stroke='none'/%3E%3C/svg%3E")}
.ya-ik--korzina{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E")}
.ya-ik--bulavka{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21v-7M8 4h8l-2 5 4 3H6l4-3Z'/%3E%3C/svg%3E")}
.ya-ik--zvezda{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l2.6 6.2 6.4.6-5 4.2 1.6 6.5L12 17l-5.6 3.5L8 14 3 9.8l6.4-.6Z'/%3E%3C/svg%3E")}
.ya-ik--info{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 11v6'/%3E%3Ccircle cx='12' cy='7.5' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E")}
.ya-ik--vnimanie{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 22 20H2Z'/%3E%3Cpath d='M12 9v5'/%3E%3Ccircle cx='12' cy='17.2' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E")}
.ya-ik--pusto{--ya-ik:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8 12 4l8 4v9l-8 4-8-4Z'/%3E%3Cpath d='M4 8l8 4 8-4M12 12v9'/%3E%3C/svg%3E")}


/* ═══ ПЕРЕКЛЮЧАТЕЛЬ · .ya-perekl ═══════════════════════════════════════
   ЗАЧЕМ. Выбор одного из нескольких видов одной и той же вещи — не кнопки
   и не вкладки. Кнопки обещают действие («сохранить»), вкладки уводят на
   другой экран; здесь же экран остаётся тот же, меняется только ракурс.
   До 11.09.2026 такой ряд рисовали врукопашную прямо в движке уроков,
   инлайновыми стилями, и он не умел ничего, кроме как выглядеть.

   РАЗМЕТКА. Обёртка объявляет группу, кнопки держат своё состояние сами —
   aria-pressed, а не класс: чтец обязан услышать, какой вид выбран.

     <div class="ya-perekl" role="group" aria-label="Вид модели">
       <button class="ya-perekl__knop" type="button" aria-pressed="true">Схема</button>
       <button class="ya-perekl__knop" type="button" aria-pressed="false">Сбоку</button>
     </div>

   ВЫБРАННОЕ ОТЛИЧАЕТСЯ НЕ ТОЛЬКО ЦВЕТОМ: у выбранной кнопки другая
   жирность и сплошная рамка. Человеку, который не различает эти два цвета,
   ряд должен читаться так же однозначно.
   Высота --h-btn: ряд стоит рядом с обычными кнопками, и разнобой высот в
   одном столбце виден сразу. */
.ya-perekl{display:flex;gap:var(--sp-2)}
.ya-perekl__knop{
  box-sizing:border-box;flex:1;min-height:var(--h-btn);padding:var(--sp-3) var(--sp-2);
  font:var(--type-label-l);
  color:var(--on-surface);background:var(--surface-container);
  /* Кайма из --outline, а не --outline-variant: вариант объявлен для
     декоративных границ и даёт к подложке 1,7:1 — контур нажимаемого
     органа так не рисуют. */
  border:1.5px solid var(--outline);border-radius:var(--shape-s);cursor:pointer;
  transition:background .15s,color .15s,border-color .15s}
/* Наведение обязано знать про выбранное: без :not() оно перебивало его по
   весу и гасило слово на выбранной кнопке. */
.ya-perekl__knop:hover:not([aria-pressed="true"]){background:var(--surface-container-high)}
.ya-perekl__knop[aria-pressed="true"]{
  color:var(--on-primary);background:var(--primary);border-color:var(--primary);font-weight:700}
.ya-perekl__knop[aria-pressed="true"]:hover{background:var(--primary)}
.ya-perekl__knop:focus-visible{outline:2px solid var(--primary);outline-offset:2px}

/* ═══ ФИШКА · .ya-fishka ═══════════════════════════════════════════════
   ЗАЧЕМ. Выбор нескольких из многих: части модели, признаки, метки. От
   кнопки отличается тем, что остаётся нажатой, от галочки — тем, что
   стоит в ряду и переносится по строкам.

     <button class="ya-fishka" type="button" aria-pressed="false">
       Вера<span class="ya-fishka__rod">· отрезок</span>
     </button>

   ЗАПЕРТАЯ ФИШКА — aria-disabled БЕЗ disabled: после проверки ответ менять
   нельзя, но прочесть выбранное надо, а настоящий disabled выкидывает кнопку
   из обхода клавишей. Нажатие гасит сам движок. Запертая выбранная остаётся
   в полную силу, запертая невыбранная гаснет, и наведение на запертую ничего
   не обещает: видно, что выбрали, и видно, что выбор закончен.
   Высота --h-btn, а не --h-chip: по фишке ЦЕЛЯТСЯ пальцем в ряду других,
   и сорок восемь тут не роскошь. */
.ya-fishka{
  box-sizing:border-box;display:inline-flex;align-items:center;gap:var(--sp-1);
  min-height:var(--h-btn);padding:var(--sp-2) var(--sp-4);
  font:var(--type-body-s);
  color:var(--on-surface);background:var(--surface-container);
  /* Та же причина, что у переключателя: контур нажимаемого — --outline. */
  border:1.5px solid var(--outline);border-radius:var(--shape-full);cursor:pointer;
  transition:background .15s,color .15s,border-color .15s}
/* То же про вес: наведение не должно перебивать выбранное. */
.ya-fishka:hover:not(:disabled):not([aria-disabled="true"]):not([aria-pressed="true"]){background:var(--surface-container-high)}
.ya-fishka[aria-pressed="true"]{
  color:var(--on-primary);background:var(--primary);border-color:var(--primary);font-weight:700}
.ya-fishka[aria-pressed="true"]:hover{background:var(--primary)}
.ya-fishka:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
/* Запертая фишка остаётся в обходе клавишей (в разметке — aria-disabled без
   disabled): ответ менять нельзя, а перечесть выбранное надо. */
.ya-fishka[aria-disabled="true"]{cursor:default}
.ya-fishka[aria-disabled="true"]:not([aria-pressed="true"]){opacity:.72}
.ya-fishka:disabled{cursor:default}
.ya-fishka:disabled:not([aria-pressed="true"]){opacity:.72}
.ya-fishka__rod{opacity:.7;font-weight:400}

/* ═══ ВЕРДИКТ · .ya-verdikt ════════════════════════════════════════════
   ЗАЧЕМ. Ответ на проверку в уроках печатался шестью разными способами.
   Здесь один: цветная плашка, у которой ПЕРВОЕ СЛОВО — приговор. Правило
   базового курса: «Так.» или «Не так.» стоит первым, до объяснения, иначе
   человек читает разбор, ещё не зная, угадал он или нет.

     <p class="ya-verdikt ya-verdikt--tak" role="status">
       <b class="ya-verdikt__slovo">Так.</b> Воля — отрезок от Кона до Предела.
     </p>

   ЦВЕТ НЕ ЕДИНСТВЕННЫЙ ПРИЗНАК: приговор стоит словом и жирным. Плашка
   живёт в области role="status" — чтец объявляет её сам, без перевода
   фокуса, потому что фокус в этот миг на кнопке «Проверить». */
.ya-verdikt{
  margin:12px 0 0;padding:12px 14px;border-radius:12px;
  font:var(--type-body-s);line-height:1.55}
.ya-verdikt__slovo{font-weight:700}
.ya-verdikt--tak{background:var(--ok-container);color:var(--on-ok-container)}
.ya-verdikt--ne-tak{background:var(--error-container);color:var(--on-error-container)}

/* ═══ ЗАГРУЗКА · .ya-loader ═══════════════════════════════════════════
   ЗАЧЕМ. Ожидание урока, главы книги и прочих полных экранов ждало
   голым текстом «Открываю…» / «Загружаю…». Дуэль уже имела кольцо
   (.dp-loader), но на своих переменных. Здесь одно кольцо на продукт:
   дорожка --outline-variant, акцент --primary, подпись — роли текста.

   РАЗМЕРЫ. Базовый 40 (полноэкранное ожидание), --sm 24 (в строке),
   --lg 56 (крупный сплэш). Блок .ya-loader-block — колонка спиннер +
   подпись с role="status" aria-live="polite" aria-busy.

   ДВИЖЕНИЕ. Вращение + лёгкий brand-pulse тенью primary. Системное
   «убрать анимации» гасит всё утилитой в tokeny.css (1ms / 1 раз) —
   кольцо остаётся статичным маркером ожидания. */

.ya-loader{
  box-sizing:border-box;
  display:inline-block; flex:none;
  width:40px; height:40px;
  border-radius:50%;
  border:3px solid var(--outline-variant);
  border-top-color:var(--primary);
  animation:
    ya-loader-spin .85s linear infinite,
    ya-loader-pulse 1.6s var(--ease-standard) infinite;
  will-change:transform, box-shadow;
}
.ya-loader--sm{ width:24px; height:24px; border-width:2px; }
.ya-loader--lg{ width:56px; height:56px; border-width:3.5px; }

@keyframes ya-loader-spin{ to{ transform:rotate(360deg); } }
@keyframes ya-loader-pulse{
  0%, 100%{ box-shadow:0 0 0 0 color-mix(in srgb, var(--primary) 0%, transparent); }
  50%{ box-shadow:0 0 0 6px color-mix(in srgb, var(--primary) 14%, transparent); }
}

/* Локальная страховка, если утилита tokeny.css ещё не подключилась. */
@media (prefers-reduced-motion: reduce){
  .ya-loader{
    animation:none;
    border-color:var(--outline-variant);
    border-top-color:var(--primary);
  }
}

.ya-loader-block{
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  gap:var(--sp-4);
  max-width:420px; text-align:center;
  color:var(--on-surface);
  font:var(--type-body-m);
  font-family:var(--ya-font-text, system-ui, sans-serif);
}
.ya-loader-block__caption{
  margin:0;
  color:var(--on-surface-variant);
  font:var(--type-body-s);
  line-height:1.55;
}

/* ═══ ЛОГОТИП ЯСНЫ В АВАТАРЕ (наставник в уроках) ════════════════════════
   PNG тёмно-сланцевый на прозрачном (lum ≈ 25): на --surface-container-lowest
   (#070809) в тёмной теме пропадает. Светлая пластина --inverse-surface;
   светлая тема без фильтра — логотип и так читается на белом круге. */
.ya-logo-plate{
  box-sizing:border-box;
  flex-shrink:0;
  border-radius:var(--shape-full);
  overflow:hidden;
  background:var(--surface-container-lowest);
  border:1px solid var(--outline-variant);
  display:flex;
  align-items:center;
  justify-content:center;
  box-shadow:var(--ya-card-elev, none);
}
.ya-logo-yasna{
  display:block;
  object-fit:contain;
}
html[data-theme="dark"] .ya-logo-plate{
  background:var(--inverse-surface);
  border-color:color-mix(in srgb, var(--outline-variant) 65%, transparent);
  box-shadow:0 1px 3px rgba(0,0,0,.28);
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .ya-logo-plate{
    background:var(--inverse-surface);
    border-color:color-mix(in srgb, var(--outline-variant) 65%, transparent);
    box-shadow:0 1px 3px rgba(0,0,0,.28);
  }
}

/* ═══ PREMIUM FILLED CTA НА ТЁМНОМ ═══════════════════════════════════════
   Как hero на Главной / Play: градиент #1A8CFF→#0071E3, белый текст,
   мягкое синее свечение. Чипы (.ya-fishka / .ya-perekl) остаются на
   бледном M3 --primary — их это правило не трогает. */
html[data-theme="dark"] .ya-btn--filled:not(:disabled){
  background:linear-gradient(135deg,#1A8CFF 0%,#0071E3 100%);
  color:#fff;
  box-shadow:var(--ya-selected-glow),
    0 8px 24px color-mix(in srgb,#0071E3 36%,transparent);
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .ya-btn--filled:not(:disabled){
    background:linear-gradient(135deg,#1A8CFF 0%,#0071E3 100%);
    color:#fff;
    box-shadow:var(--ya-selected-glow),
      0 8px 24px color-mix(in srgb,#0071E3 36%,transparent);
  }
}


/* ═══ YS1 · крем-карточки тетради и дневника ═══════════════════════════ */
.ur-cream-card{
  box-shadow:var(--ya-card-elev, none);
}
.ur-workbook-examples .ur-download-btn:hover,
.ur-dnevnik-week .ur-download-btn:hover{
  border-color:var(--book-sutki);
  color:var(--book-sutki);
}
.ur-dnevnik-moments{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:10px;
}
.ur-dnevnik-extra-row{
  display:grid;
  grid-template-columns:minmax(120px,0.9fr) 1.4fr;
  gap:10px;
  align-items:start;
}
@media (max-width:520px){
  .ur-dnevnik-moments,
  .ur-dnevnik-extra-row{
    grid-template-columns:1fr;
  }
}
