/* Функциональные стили прежнего облика (формы, загрузка, импорт, ход проверки,
   внутренности сверки) на токенах макета. Конфликтующие с макетом правила
   (шапка, кнопки, сетка, меню, заголовки) убраны генератором переноса. */
*{ box-sizing: border-box; }
.narrow{ max-width: 26rem; margin: 0 auto; }
/* шкала заголовков страниц кабинета: страница → раздел → карточка */
p{ margin: 0; }
a{ color: var(--accent); text-decoration: none; }
a:hover{ text-decoration: underline; }
.center{ text-align: center; }
.accent{ color: var(--accent); }
/* ── шапка и подвал ── */
/* Знак — силуэт цветом текста, а не медь на тёмном квадрате: в светлой теме
   тёмный по светлому, в тёмной — светлый по тёмному. Через <img> так не выйдет
   (currentColor во внешнем файле не наследуется), поэтому фигура берётся
   маской из mark-ink.svg, а цвет даёт сам элемент. */
/* Кнопки шапки (.btn, «Войти») своё оформление держат сами: правило ссылок
   весомее .btn и красило их текст в цвет ссылки — 1.77:1 на синей заливке */
/* Баланс в шапке — тихая капсула с цифрой; цифра моноширинная, ссылка ведёт к пополнению */
/* Телефон: шапка не выше прежней — иначе карточка места в сверке не влезает в
   экран (страж test_phone_shows_one_place_with_its_decisions_on_one_screen).
   «Помощь» остаётся в подвале («Как это работает»), баланс — строкой в кабинете
   (.balance-phone). Заголовок Unbounded широк — на 320 px длинное слово в нём
   не вмещалось. */
/* ряд ссылок подвала — не предложение, а навигация: цель нажатия от 24 px */
form.inline{ display: inline; }
button.link{ background: none; border: 0; font: inherit; cursor: pointer; }
/* ── кнопки и формы ── */
/* Наведение на призрачную кнопку не снимает цвет опасного действия */
label{ display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 0.35rem; color: var(--ink-2); }
input[type=text],input[type=email],input[type=number],input[type=search],input[type=tel],input[type=url],input[type=password],textarea,select{
  font: inherit; width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--rule-control); border-radius: var(--r-ctl);
  background: var(--surface); color: var(--ink); transition: border-color var(--m-micro) var(--e-out), box-shadow var(--m-micro) var(--e-out);
}
/* поля формы — 44 px, как в макете D-new; многострочное поле — своей высоты */
textarea{ height: auto; padding: 0.7rem 0.85rem; }
/* Рамка фокуса — сплошные 2 px цвета --accent (5.9:1 к подложке); прежний ореол
   --accent-soft давал 1.14:1 и был не виден */
input:focus-visible,textarea:focus-visible,select:focus-visible{
  outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent);
}
input[type=file]{ font: inherit; font-size: 0.9rem; color: var(--ink-2); width: 100%; }
input[type=file]::file-selector-button{
  font: inherit; font-weight: 600; font-size: 0.85rem; color: var(--ink); background: var(--surface); border: 1px solid var(--rule-2);
  border-radius: 8px; padding: 0.45rem 0.8rem; margin-right: 0.7rem; cursor: pointer;
}
.field{ margin-bottom: 1rem; }
.hint{ font-size: 0.85rem; color: var(--muted); margin-top: 0.35rem; }
.check{ display: flex; gap: 0.6rem; align-items: flex-start; font-weight: 400; font-size: 0.9rem; color: var(--ink-2); margin: 0.9rem 0; }
.check input{ margin-top: 0.25rem; accent-color: var(--accent); }
.hp{ position: absolute; inset-inline-start: -9999px; }
/* ── поверхности ── */
.card{ background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); padding: 1.35rem; box-shadow: var(--shadow); }
.card-flat{ box-shadow: none; }
.section{ padding: 4rem 0 0; }
.section-head{ text-align: center; max-width: 36rem; margin: 0 auto 2rem; display: flex; flex-direction: column; gap: 0.6rem; }
.section-head p{ color: var(--muted); font-size: 1.05rem; text-wrap: pretty; }
.alert{ border-radius: 10px; padding: 0.75rem 1rem; font-size: 0.9rem; }
.alert-error{ color: var(--crit); background: var(--crit-soft); }
.alert-ok{ color: var(--ok); background: var(--ok-soft); }
.alert-warn{ color: var(--warn); background: var(--warn-soft); }
/* Ссылка на плашке — цветом плашки и подчёркиванием: синяя на тёмно-жёлтом
   в тёмной теме давала 4.37:1 */
.alert-warn a{ color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }
.alert-ok a{ color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }
/* Действие формой на плашке (удалить импорт) — выглядит как соседняя ссылка */
.alert-act{ display: inline; }
.alert-act button{ font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 0.15em; }
.pill{ display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.78rem; font-weight: 600; border-radius: 999px; padding: 0.2rem 0.6rem; white-space: nowrap; }
.pill-ok{ color: var(--ok); background: var(--ok-soft); }
.pill-warn{ color: var(--warn); background: var(--warn-soft); }
.pill-crit{ color: var(--crit); background: var(--crit-soft); }
.pill-note{ color: var(--ink-2); background: var(--surface-2); }
.pill-accent{ color: var(--accent); background: var(--accent-soft); }
.badge{ display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; font-weight: 500; color: var(--ink-2); background: var(--surface); border: 1px solid var(--rule); border-radius: 999px; padding: 0.35rem 0.85rem; box-shadow: var(--shadow); }
.dot{ width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.progress{ height: 6px; background: var(--surface-3); border-radius: 999px; overflow: hidden; }
/* Длина полосы меняется только transform (scaleX от левого края, m-slow e-out);
   ширина, заданная сервером при отрисовке, не анимируется */
.progress i{ display: block; height: 100%; background: var(--accent); border-radius: 999px; transform-origin: 0 50%; transition: transform var(--m-slow) var(--e-out); }
/* Проверка идёт, доли не называем: клиенту этапы не показываются. Без движения —
   ровная треть полосы: полоса всё равно читается как «идёт» рядом с подписью */
.progress-busy i{ width: 33%; }
/* Отчёт клиента у оператора: действия не показываются — метки только у владельца */
@media (prefers-reduced-motion: no-preference){
.progress-busy i{ animation: busy calc(2 * var(--m-loop-pulse)) var(--e-out) infinite; }
}
/* «Занятость» — туда и обратно одним циклом, только transform (33 % × 200 % = край);
   кривая e-out действует на каждый отрезок между кадрами. Одно определение на сервис */
@keyframes busy{ 0%, 100% { transform: translateX(0); } 50% { transform: translateX(200%); } }
.spinner{ width: 18px; height: 18px; border: 2px solid var(--rule-2); border-top-color: var(--accent); border-radius: 50%; display: inline-block; vertical-align: middle; }
@media (prefers-reduced-motion: no-preference){
.spinner{ animation: spin var(--m-loop-spin) var(--e-loop) infinite; }
}
@keyframes spin{ to { transform: rotate(360deg); } }
.icon{ width: 40px; height: 40px; border-radius: 10px; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; flex-shrink: 0; }
.icon svg{ width: 20px; height: 20px; }
.rows{ display: flex; flex-direction: column; }
.row{ display: flex; align-items: center; gap: 0.6rem 1rem; padding: 0.9rem 0; border-top: 1px solid var(--rule); flex-wrap: wrap; }
/* Одно объявление вместо двух: прежде второе перебивало первое и оставляло
   основу 0, из-за чего на 320 px колонка ужималась до 48 px, длинное название
   вылезало на 21 px и налезало на метку состояния (замер на панели оператора).
   Основа 12rem возвращает ряду перенос, min-width — право ужиматься до неё. */
.row .grow{ flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; }
.row-acts{ display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin-inline-start: auto; }
.row:first-child{ border-top: 0; }
.row .title{ font-weight: 600; }
/* Ссылка в ряду — цель нажатия от 24 px (замер ловил 310×20 на панели) */
.row .title a,.row .grow > a{ display: inline-flex; align-items: center; min-height: 24px; }
.row .sub{ color: var(--muted); font-size: 0.85rem; }
kbd{ font-family: var(--mono); font-size: 0.75rem; border: 1px solid var(--rule-2); border-radius: 4px; padding: 0 0.3rem; background: var(--surface-2); color: var(--ink-2); }
/* ── первое окно ── */
.hero{ text-align: center; padding: 4.5rem 0 2.5rem; display: flex; flex-direction: column; align-items: center; gap: 1.25rem; position: relative; }
.hero::before{ content: ""; position: absolute; inset: -6rem 0 auto; height: 26rem; background: radial-gradient(ellipse at 50% 0%, var(--accent-soft), transparent 65%); z-index: -1; pointer-events: none; }
.hero .lede{ color: var(--muted); font-size: 1.15rem; max-width: 36rem; text-wrap: pretty; }
/* Переход по якорю с кнопок «Проверить главу» не должен прятать заголовок под липкой шапкой */
.upload{ max-width: 40rem; margin: 0 auto; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); padding: 1.5rem; text-align: left; scroll-margin-top: calc(var(--top-h, 3.75rem) + 1rem); }
.upload-head{ display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-bottom: 1rem; }
.slots{ display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.slot{ position: relative; border: 1.5px dashed var(--rule-control); border-radius: var(--r); padding: 1.1rem 1rem; text-align: center; cursor: pointer; background: var(--ground); }
/* Подсветка слота при наведении и перетаскивании — сразу, без перехода: цвет рамки
   и фона не анимируются (договор движения: только transform и opacity) */
@media (hover: hover){
.slot:hover{ border-color: var(--accent); background: var(--accent-soft); }
}
.slot.over{ border-color: var(--accent); background: var(--accent-soft); }
.slot:focus-within{ border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }
.slot.filled{ border-style: solid; border-color: var(--ok); background: var(--ok-soft); }
.slot input{ position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.slot .icon{ margin: 0 auto 0.5rem; }
.slot b{ display: block; font-size: 0.95rem; }
.slot .sub{ display: block; font-size: 0.8rem; color: var(--muted); margin-top: 0.15rem; min-height: 4.65em; }
/* Подсказка и имя файла занимают одинаковые три строки: выбор файла не
   сдвигает кнопку загрузки. Более длинное имя переносится без обрезки. */
.slot .picked{ display: block; font-size: 0.8rem; color: var(--ok); margin-top: 0.15rem; min-height: 4.65em; font-weight: 500; overflow-wrap: anywhere; }
.slot .picked:empty{ display: none; }
.slot.filled .sub{ display: none; }
.upload-foot{ display: flex; align-items: center; gap: 1rem; margin-top: 1rem; flex-wrap: wrap; }
.upload-recovery{ margin: 0 0 1rem; padding: 0.9rem 1rem; border: 1px solid var(--rule); border-inline-start: 4px solid var(--accent); border-radius: var(--r); background: var(--surface); }
.upload-recovery__hint{ margin: 0.35rem 0 0.75rem; color: var(--muted); font-size: 0.85rem; }
.upload-recovery__groups{ display: grid; gap: 0.65rem; }
.upload-recovery__group{ min-width: 0; padding: 0.75rem; border: 1px solid var(--rule); border-radius: var(--r); background: var(--ground); }
.upload-recovery__summary{ margin: 0 0 0.45rem; font-weight: 600; font-size: 0.9rem; }
.upload-recovery__files{ display: grid; gap: 0.4rem; margin: 0 0 0.65rem; padding: 0; list-style: none; }
.upload-recovery__files li{ display: grid; gap: 0.1rem; min-width: 0; }
.upload-recovery__name{ overflow-wrap: anywhere; font-size: 0.88rem; }
.upload-recovery__meta{ color: var(--muted); font-size: 0.78rem; }
.upload-recovery__resume{ margin-top: 0.1rem; }
.upload-recovery[hidden]{ display: none; }
/* плитка, которую осталось выбрать (её же называет главная кнопка формы) */
.slot.is-next{ border-style: solid; border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft); }
.slot.is-next .sub{ color: var(--accent); font-weight: 650; }
.captcha{ display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; color: var(--ink-2); }
/* Поле ответа наследовало 0.9rem от подписи: на iOS страница прыгала при
   фокусе (порог 16 px). Размер поля держим явно, подпись остаётся мелкой. */
.captcha input{ width: 4.5rem; padding: 0.45rem 0.6rem; text-align: center; font-size: 1rem; }
.upload-note{ font-size: 0.8rem; color: var(--muted); margin-top: 0.8rem; }
.pricing{ display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1rem; max-width: 40rem; margin: 0 auto; }
.price{ font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; margin: 0.5rem 0 0.2rem; }
.price small{ font-size: 0.9rem; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.plan ul{ margin: 0.8rem 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.4rem; font-size: 0.9rem; color: var(--ink-2); }
.plan li::before{ content: "✓ "; color: var(--ok); font-weight: 700; }
.cta{ text-align: center; padding: 4rem 1.5rem; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg); margin-top: 4rem; display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.faq details{ border-top: 1px solid var(--rule); padding: 0.9rem 0; }
.faq details:last-child{ border-bottom: 1px solid var(--rule); }
/* Safari списковый маркер у summary снимает только этим псевдоэлементом */
summary::-webkit-details-marker{ display: none; }
.faq summary{ cursor: pointer; font-weight: 600; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.faq summary::after{ content: "+"; color: var(--muted); font-weight: 400; font-size: 1.2rem; }
.faq details[open] summary::after{ content: "−"; }
.faq p{ color: var(--muted); margin-top: 0.5rem; max-width: 60ch; font-size: 0.95rem; text-wrap: pretty; }
/* 38rem ≈ 70 знаков в строке: на 42rem выходило 78, длинную строку глаз теряет */
.prose{ max-width: 38rem; margin: 3rem auto 0; display: flex; flex-direction: column; gap: 0.9rem; color: var(--ink-2); }
.prose ol,.prose ul{ margin: 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: 0.35rem; }
.prose table{ font-size: 0.88rem; }
.prose th,.prose td{ text-align: start; padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.prose th{ font-weight: 600; color: var(--ink); }
.prose ol ol{ margin-top: 0.3rem; }
/* Прокручиваемая область получает фокус (иначе с клавиатуры её не сдвинуть),
   а вместе с ним — видимую рамку */
.scroll{ overflow-x: auto; }
.scroll:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
.prose .draft{ border-left: 3px solid var(--warn); padding: 0.5rem 0.8rem; color: var(--warn); background: var(--warn-soft); border-radius: 0 8px 8px 0; font-size: 0.9rem; }
/* ── кабинет ── */
.page-head{ display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; padding: 2.5rem 0 1.5rem; }
/* Ссылка-крошка — навигация, а не предложение: цель нажатия от 24 px
   (замер интерфейса ловил 70×17 и 191×17). */
/* Бейджи глав — ровной сеткой, а не «ёлочкой»: пилюли разной ширины при
   переносе ложились 2 + 2 + 1 со сдвинутыми краями. Колонки равной ширины —
   края совпадают в каждом ряду, сколько бы бейджей ни было. */
.empty{ text-align: center; padding: 3rem 1rem; color: var(--muted); display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.upload-card .slots{ grid-template-columns: 1fr 1fr; }
/* Общая ячейка резервирует высоту большей вкладки без фиксированной высоты
   текста. Скрытая форма недоступна для фокуса и указателя. */
.upload-panes{ display: grid; align-items: start; }
.upload-panes > [data-pane]{ grid-area: 1 / 1; min-width: 0; }
.upload-panes > [data-pane][hidden]{ display: block; visibility: hidden; pointer-events: none; }
.job-card{ text-align: center; display: flex; flex-direction: column; align-items: center; gap: 0.9rem; padding: 2rem 1.5rem; }
.job-card .big{ font-size: 1.15rem; font-weight: 600; }
/* ── отчёт ── */
.report-head{ display: flex; justify-content: space-between; align-items: flex-end; gap: 1rem; flex-wrap: wrap; padding: 2rem 0 1rem; }
.filters{ display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; margin: 1rem 0 0.75rem; }
.filters label{ display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; font-weight: 500; font-size: 0.85rem; background: var(--surface); border: 1px solid var(--rule); border-radius: 999px; padding: 0.3rem 0.75rem; cursor: pointer; color: var(--ink-2); }
.filters label:has(input:checked){ background: var(--accent-soft); border-color: transparent; color: var(--accent); }
.filters input{ accent-color: var(--accent); margin: 0; }
/* Порог паузы — своё поле со своей подписью (обёртка на два поля связывала оба
   с первым, и число оставалось без имени). Ширина та же, что была встроенной. */
/* 1rem, а не 0.85: поле мельче 16 px заставляет iOS увеличивать страницу
   при фокусе. Компактность держим шириной и отступами. */
.pause-min-box input{ width: 4.2rem; font: inherit; font-size: 1rem; padding: 0.1rem 0.3rem;
  border: 1px solid var(--rule-control); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); }
/* Общий ход загрузки всех выбранных файлов: передача байтов, текущий файл и
   отдельные стадии подготовки/проверки. Отказ сервера — у самой формы. */
@media (prefers-reduced-motion: reduce){
.err,.progress i,.slot,input,textarea,select{ transition: none; }
}
.upload-progress{ display: grid; gap: 0.7rem; width: 100%; min-width: 0; margin-top: 1rem;
  padding: 1rem 1.1rem; border: 1px solid var(--rule); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--shadow); }
.upload-progress__head,.upload-progress__summary{ display: flex; align-items: center; justify-content: space-between; gap: 0.6rem 1rem; min-width: 0; }
.upload-progress__heading{ font-size: 1rem; line-height: 1.25; }
.upload-progress__percent{ flex: 0 0 auto; min-width: 4ch; text-align: end; color: var(--accent); font-size: 1.4rem; font-weight: 750; line-height: 1; font-variant-numeric: tabular-nums; }
.upload-progress__bar{ display: block; width: 100%; height: 0.75rem; margin: 0; overflow: hidden; border: 0;
  border-radius: 999px; background: var(--surface-3); accent-color: var(--accent); }
.upload-progress__bar::-webkit-progress-bar{ background: var(--surface-3); border-radius: 999px; }
.upload-progress__bar::-webkit-progress-value{ background: var(--accent); border-radius: 999px; }
.upload-progress__bar::-moz-progress-bar{ background: var(--accent); border-radius: 999px; }
.upload-progress__summary{ color: var(--ink-2); font-size: 0.82rem; font-variant-numeric: tabular-nums; }
/* место крутилки — всегда (волна 2 договора движения): включение и выключение
   «неизвестной длины» не двигает подписи на ширину колонки */
.upload-progress__detail{ display: grid; grid-template-columns: 1.4rem minmax(0, 1fr); align-items: start; gap: 0.6rem; min-width: 0; }
.upload-progress__detail-copy{ display: grid; gap: 0.12rem; min-width: 0; }
.upload-progress__spinner{ display: inline-block; visibility: hidden; flex: 0 0 auto; margin-top: 0.1rem; }
.upload-progress.is-busy.is-indeterminate .upload-progress__spinner{ visibility: visible; }
.upload-progress__text{ color: var(--ink); font-size: 0.9rem; font-weight: 650; }
.upload-progress__current-file,.upload-progress__file-status{ min-width: 0; color: var(--ink-2); font-size: 0.82rem; overflow-wrap: anywhere; }
.upload-progress__file-count{ flex: 0 0 auto; text-align: end; }
.upload-progress__actions{ display: flex; flex-wrap: wrap; gap: 0.5rem; padding-top: 0.15rem; }
.cost-note .spinner{ margin-inline-end: 0.4rem; }
.upload-error{ margin: 0.8rem 0 0; overflow-wrap: anywhere; }
.upload-progress[hidden],.upload-error[hidden]{ display: none; }
/* окно хода не меняет высоту от шага к шагу: полоса прячется без потери места,
   строки файла и ряд кнопок держат свою высоту и пустыми (замечание владельца к 0.9.24) */
.upload-progress__bar[hidden]{ display: block; visibility: hidden; }
.upload-progress__current-file,.upload-progress__file-status{ min-height: 1lh; }
.upload-progress__actions{ min-height: 2.25rem; }
/* панель, добранная до высоты полей (upload.js), не растягивает строки:
   запас — внизу, строки хода стоят на своих местах (E6) */
.upload-progress{ align-content: start; }
/* кнопка формы держит ширину самой длинной надписи шага («Выбрать текст книги»,
   «Продолжить», «Загрузить материалы») — подпись рядом не сдвигается */
#import-form .upload-foot > .btn[type=submit]{ min-width: 13.5rem; justify-content: center; }
/* то же у формы части: «Загрузить и проверить» → «Выбрать текст главы» после
   выбора звука не двигает кнопку (прижата вправо — росла влево, E6) */
#chapter-form .upload-foot > .btn[type=submit]{ min-width: 15rem; justify-content: center; }
@media (max-width: 40rem){
.upload-progress{ padding: 0.9rem; gap: 0.65rem; }
.upload-progress__summary{ align-items: flex-start; flex-direction: column; gap: 0.12rem; }
.upload-progress__file-count{ text-align: start; }
/* строка состояния файла («Подготовка…») на узком экране — в две строки:
   место под них постоянное, кнопки хода под ней не прыгают (E6) */
.upload-progress__file-status{ min-height: 2lh; }
}
.cost-note:empty{ display: none; }
/* в форме части строка цены стоит с первого кадра (пустая — невидима): цена
   приходит после выбора файла и замера длины звука и не сдвигает то, что
   ниже (волна 2 договора движения) */
.upload-card .cost-note{ min-height: 1lh; }
.upload-card .cost-note:empty{ display: block; visibility: hidden; }
/* на узком экране «Спишем … — на балансе останется …» — две строки: место
   под них стоит заранее, кнопка ниже не съезжает после выбора звука (E6) */
@media (max-width: 40rem){ .upload-card .cost-note{ min-height: 2lh; } }
/* Ход загрузки в форме части или книги — панелью НА МЕСТЕ полей выбора, а не
   поверх них: на время передачи заголовок формы, плитки «аудио + текст» и строка
   цены скрыты, панель стоит в потоке перед кнопкой. Наложение поверх формы
   оставляло края плиток торчать из-под панели и выглядело как сбой. Вне
   передачи (пауза, отказ, повторный выбор) поля возвращаются, панель — под ними */
.upload-card > .upload-progress{ margin: 0 0 1rem; box-shadow: none; }
.upload-card.is-transferring > .upload-head,
.upload-card.is-transferring > .slots,
.upload-card.is-transferring > .cost-note{ display: none; }
/* «Продолжить разметку» в «Моих книгах» — следующее дело одной ссылкой */
.job-card .eta{ margin: 0.2rem 0 0; font-weight: 600; color: var(--ink); }
.cost-note{ margin: 0.6rem 0 0; }
.cost-note.cost-short{ color: var(--crit); }
.toast{ position: fixed; bottom: 1.25rem; left: 50%; transform: translateX(-50%) translateY(8px); background: var(--ink); color: var(--ground); padding: 0.6rem 1.1rem; border-radius: 10px; font-size: 0.9rem; opacity: 0; transition: opacity var(--m-fast) var(--e-in), transform var(--m-fast) var(--e-in); pointer-events: none; box-shadow: var(--shadow-lg); }
.toast.show{ opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; transition: opacity var(--m-base) var(--e-out), transform var(--m-base) var(--e-out); }
.toast.error{ background: var(--crit); color: var(--crit-ink); display: inline-flex; gap: 0.8rem; align-items: center; width: max-content; max-width: calc(100% - 2rem); overflow-wrap: anywhere; }
.toast button{ min-width: 24px; min-height: 24px; flex-shrink: 0; font: inherit; background: none; border: 0; color: inherit; cursor: pointer; padding: 0 0.2rem; font-size: 1.1rem; line-height: 1; }
/* сообщение при «меньше движения» — только проявление за m-micro, без сдвига */
@media (prefers-reduced-motion: reduce){
.toast,.toast.show{ transform: translateX(-50%); transition: opacity var(--m-micro) var(--e-out); }
}
@media (max-width: 40rem){
.hero{ padding-top: 3rem; }
.slots,.upload-card .slots{ grid-template-columns: 1fr; }
.menu-form{ flex-wrap: wrap; }
.page-head{ padding-top: 1.5rem; }
}
/* ── циклы, вкладки, раунды, импорт ── */
.series{ margin-top: 2rem; }
.series-menu{ position: relative; }
.series-menu summary{ list-style: none; }
.series-menu .menu{ position: absolute; inset-inline-end: 0; top: 2.2rem; z-index: 5; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); box-shadow: var(--shadow-lg); padding: 0.6rem; display: flex; flex-direction: column; gap: 0.4rem; min-width: min(18rem, calc(100vw - 3rem)); }
/* В паре «поле + кнопка» ужимается поле, а не кнопка: иначе короткая надпись
   разрывается на две строки (поле растёт на 100 %, кнопка сжимаема по умолчанию) */
.menu-form{ display: flex; gap: 0.4rem; }
.menu-form input{ padding: 0.4rem 0.6rem; min-width: 6rem; }
.tabs{ display: flex; gap: 0.25rem; margin-bottom: 0.75rem; border-bottom: 1px solid var(--rule); }
.tab{ font: inherit; font-weight: 600; font-size: 0.92rem; color: var(--muted); background: none; border: 0; border-bottom: 2px solid transparent; padding: 0.55rem 0.9rem; margin-bottom: -1px; cursor: pointer; }
.tab.active{ color: var(--accent); border-bottom-color: var(--accent); }
.round-box{ position: relative; }
.round-box summary{ list-style: none; }
/* min() вместо жёстких 20rem: на 320 px форма вылезала за левый край и её срезал overflow-x: clip */
.round-form{ position: absolute; inset-inline-end: 0; top: 2.2rem; z-index: 5; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); box-shadow: var(--shadow-lg); padding: 0.9rem; display: flex; flex-direction: column; gap: 0.6rem; min-width: min(20rem, calc(100vw - 3rem)); }
.round-form label{ display: flex; flex-direction: column; gap: 0.25rem; }
.rounds{ display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 0.4rem; }
.rounds a{ text-decoration: none; }
.diff{ display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.8rem; padding: 0.8rem 1rem; }
.pair-row select{ flex-shrink: 0; }
.pair-select.dup{ border-color: var(--crit); }
@media (max-width: 40rem){
.pair-row{ flex-wrap: wrap; }
.pair-row select{ width: 100% !important; }
}
/* ── первое окно: цифры, живые шаги, калькулятор ── */
.stats-row{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--rule); border: 1px solid var(--rule); border-radius: var(--r); overflow: hidden; margin-top: 0.5rem; width: 100%; max-width: 44rem; }
.stats-row div{ background: var(--surface); padding: 0.75rem 0.5rem; display: flex; flex-direction: column; gap: 0.1rem; }
.stats-row b{ font-size: 1.15rem; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stats-row span{ font-size: 0.78rem; color: var(--muted); }
.calc label{ margin-bottom: 0.6rem; }
.calc-row{ display: flex; gap: 1rem; align-items: center; }
.calc-row input[type=range]{ flex: 1; accent-color: var(--accent); }
.calc-row output{ font-variant-numeric: tabular-nums; white-space: nowrap; min-width: 9rem; text-align: end; }
@media (max-width: 40rem){
.stats-row{ grid-template-columns: 1fr 1fr; }
.calc-row{ flex-direction: column; align-items: stretch; }
.calc-row output{ text-align: start; }
}
/* Тумблеры порядка, списка и кандидатов */
/* 14rem, а не 15.5: тумблеров четыре, и при 15.5 в полосу 984 px влезали
   только три — четвёртый уезжал на свою строку в одиночку. */
.toggles{ display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 0.6rem; margin: 1rem 0 0.5rem; }
/* Каждый тумблер в своей карточке с лёгкой подсветкой по смыслу: порядок —
   цвет яруса, список — он же, кандидаты — янтарный, как их метка «❓». */
.toggle-box{ display: flex; flex-direction: column; gap: 0.35rem; padding: 0.6rem 0.8rem;
  border: 1px solid var(--rule); border-radius: var(--r-sm); background: var(--surface);
  transition: background var(--m-micro) var(--e-out), border-color var(--m-micro) var(--e-out); }
.toggle-box:has(input:checked){ border-color: transparent; }
.toggle-order:has(input:checked){ background: var(--accent-soft); }
/* Выключенные клавиши — не «хорошее» состояние, поэтому подсветка нейтральная */
.toggle-keys:has(input:checked){ background: var(--surface-2); border-color: var(--rule-2); }
.toggle-cand:has(input:checked){ background: var(--warn-soft); }
.toggle-cand:has(input:checked) .slider{ background: var(--warn); border-color: var(--warn); }
@media (prefers-reduced-motion: reduce){
.toggle-box{ transition: none; }
}
/* 0.75rem = 12 px — нижняя граница проекта; ниже подпись перестаёт читаться */
/* На цветной подложке включённого тумблера приглушённый цвет давал 4.46:1
   при норме 4.5 для мелкого прописного текста (замер: #626F84 на #EAF0FF).
   Во включённом состоянии подпись берёт цвет потемнее. */
.toggle-box:has(input:checked) .toggle-title{ color: var(--ink-2); }
.toggle-title{ font-size: 0.75rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.switch{ display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 0.5rem; cursor: pointer; font-size: 0.85rem; }
.switch b{ text-align: end; }
.switch .off{ text-align: start; }
.switch b{ color: var(--ink); font-weight: 600; }
.switch .off{ color: var(--muted); }
.switch input{ position: absolute; opacity: 0; width: 0; height: 0; }
.switch .slider{ width: 2.4rem; height: 1.3rem; border-radius: 999px; background: var(--surface-3);
  border: 1px solid var(--rule-2); position: relative; transition: background var(--m-micro) var(--e-out); flex: none; }
.switch .slider::after{ content: ""; position: absolute; inset-block-start: 2px; inset-inline-start: 2px;
  width: 1rem; height: 1rem; border-radius: 50%; background: var(--surface); box-shadow: var(--shadow);
  transition: transform var(--m-micro) var(--e-out); }
.switch input:checked + .slider{ background: var(--accent); border-color: var(--accent); }
.switch input:checked + .slider::after{ transform: translateX(1.05rem); }
.switch input:focus-visible + .slider{ outline: 2px solid var(--accent); outline-offset: 2px; }
.switch input:checked ~ .off{ color: var(--ink); font-weight: 600; }
.switch input:checked ~ b{ color: var(--muted); font-weight: 400; }
.switch input:disabled ~ *{ opacity: 0.5; }
/* Подпись к тумблерам — во всю ширину, тремя строками: по строке на тумблер */
.toggles-note{ display: grid; gap: 0.2rem; margin: 0 0 1.1rem; padding: 0.7rem 0.9rem;
  border-inline-start: 3px solid var(--rule-2); color: var(--muted); font-size: 0.85rem; }
.toggles-note p{ margin: 0; text-wrap: pretty; }
.toggles-note b{ color: var(--ink-2); font-weight: 600; }
@media (prefers-reduced-motion: reduce){
.switch .slider,.switch .slider::after{ transition: none; }
}
/* Паузы — находки для монтажа, отдельным блоком, с ошибками не смешиваются */
.pauses{ border: 1px dashed var(--rule-2); border-radius: var(--r-sm); padding: 0.7rem 0.9rem;
  margin-bottom: 0.8rem; display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.pauses-title{ width: 100%; font-size: 0.85rem; color: var(--muted); }
@media (forced-colors: active){
.err.candidate{ border-inline-start-color: Highlight; }
.switch .slider{ border: 1px solid CanvasText; }
.switch input:checked + .slider{ background: Highlight; forced-color-adjust: none; }
}
/* ── экран сверки 2.0 ──
   Правила владельца (2026-09-27/28): две колонки — список мест и карточка;
   окно чтения — жёсткий прямоугольник, место в средней строке посередине;
   плеер прямо над кнопками решения; текущее место — в середине списка, список
   постоянной высоты (по карточке справа) и движется сам. */
.report-head{ padding: 1.5rem 0 0.75rem; }
.rv-progress{ display: flex; align-items: center; gap: 0.5rem 0.9rem; flex-wrap: wrap; font-size: 0.9rem; margin: 0.25rem 0 0.75rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.rv-progress .bar{ flex: 1 1 12rem; max-width: 26rem; height: 6px; border-radius: 999px; background: var(--surface-3); display: flex; overflow: hidden; }
.rv-progress .bar i{ display: block; height: 100%; }
.b-crit{ background: var(--crit); }
.b-fp{ background: var(--muted); }
#work-count b{ color: var(--ink); }
.rv-filters{ display: flex; gap: 0.5rem 0.9rem; flex-wrap: wrap; align-items: center; margin-bottom: 0.75rem; }
.seg{ display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--surface-2); padding: 3px; border-radius: 9px; }
.seg button{ font: inherit; font-size: 0.8125rem; font-weight: 600; border: 0; background: transparent; color: var(--ink-2); padding: 0.35rem 0.7rem; min-height: 32px; border-radius: 7px; cursor: pointer; white-space: nowrap; }
.seg button[aria-pressed="true"]{ background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(0,0,0,0.08); }
.seg button:focus-visible{ outline: 2px solid var(--accent); outline-offset: 1px; }
.seg .c{ font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 500; margin-inline-start: 0.3rem; }
.viewbox{ position: relative; }
.viewbox > summary{ list-style: none; cursor: pointer; }
.viewbox > summary::-webkit-details-marker{ display: none; }
.viewbox > summary::after{ content: " ▾"; }
/* Свёрнутый <details> в Chrome держит содержимое в раскладке (content-visibility):
   закрытое меню убираем явно, иначе оно «уезжает» за край узкого экрана */
.viewbox:not([open]) .viewpop{ display: none; }
/* «Вид» раскрывается во всю ширину под строкой фильтров: не накрывает список и
   не уезжает за край ни на узком экране, ни при увеличении 200 %. Панель —
   сосед <details>, поэтому сама кнопка остаётся в строке (2026-10-05) */
.viewbox:not([open]) + .viewpop{ display: none; }
.viewbox + .viewpop{ flex-basis: 100%; box-sizing: border-box; }
.viewpop{ margin-top: 0.5rem; padding: 0.9rem 1rem; display: grid; gap: 0.6rem; }
.viewpop .filters{ margin: 0; }
.viewpop .toggles{ margin: 0; }
.filters label b{ font-variant-numeric: tabular-nums; }
.tl-wrap{ margin-bottom: 0.75rem; }
.tl-wrap .tl{ position: relative; height: 28px; background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-sm); cursor: pointer; }
.tl-wrap .tl i{ position: absolute; top: 8px; bottom: 8px; width: 4px; margin-inline-start: -2px; border-radius: 2px; background: transparent; box-shadow: inset 0 0 0 1.5px var(--rule-control); pointer-events: none; }
.tl-wrap .tl i.err{ background: var(--crit); box-shadow: none; top: 3px; bottom: 3px; }
.tl-wrap .tl i.fp{ background: var(--gone); box-shadow: none; top: 10px; bottom: 10px; }
.tl-wrap .tl i.added{ top: 9px; bottom: 9px; width: 9px; margin-inline-start: -4.5px; border-radius: 50%; }
.tl-wrap .tl i.cur{ top: 1px; bottom: 1px; box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }
/* Волна записи под метками шкалы (макет): громкость главы, без смысла цвета */
.tl-wave{ position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.tl-wave path{ fill: none; stroke: var(--rule-2); stroke-width: 0.6; }
.tl-wrap .tl .head{ position: absolute; top: 0; bottom: 0; width: 2px; background: var(--accent); margin-inline-start: -1px; pointer-events: none; }
.tl-axis{ position: relative; height: 16px; font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }
.tl-axis span{ position: absolute; transform: translateX(-50%); }
.tl-axis span:first-child{ transform: none; }
.rv{ display: grid; grid-template-columns: minmax(15rem, 0.8fr) minmax(0, 1.4fr); gap: 14px; align-items: stretch; margin-bottom: 2rem; }
.rv > .card{ padding: 0; }
/* Список — окно постоянной высоты (по карточке справа): его содержимое не
   растит строку сетки (contain: size), решения не меняют его размер */
.rv > .lbox{ display: flex; flex-direction: column; contain: size; min-height: 22rem; }
.list-h{ display: flex; justify-content: space-between; padding: 0.5rem 0.75rem 0.4rem; font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.err-list{ flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 6px; }
/* поля сверху и снизу — чтобы и первое, и последнее место вставали посередине */
.pl-pad{ display: flex; justify-content: center; font-size: 0.75rem; color: var(--muted); }
.pl-pad-top{ align-items: flex-end; padding-bottom: 10px; }
.pl-pad-bot{ align-items: flex-start; padding-top: 10px; }
.err{ display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px; border-radius: var(--r-sm); border-inline-start: 3px solid transparent; }
.err.current{ background: var(--accent-soft); }
.err.reader{ border-inline-start-color: var(--crit); }
.err.candidate:not(.reader){ border-inline-start-color: var(--warn); }
.err .pl-sel{ font: inherit; text-align: start; border: 0; background: transparent; color: var(--ink); display: grid; grid-template-columns: 3.4rem minmax(0, 1fr); gap: 0.6rem; align-items: center; padding: 0.55rem 0.4rem 0.55rem 0.5rem; border-radius: var(--r-sm); cursor: pointer; min-width: 0; }
@media (hover: hover){
.err:not(.current):hover{ background: var(--surface-2); }
}
.err .tc{ font-family: var(--mono); font-size: 0.8rem; color: var(--accent); }
.err .w{ font-size: 0.9rem; min-width: 0; overflow-wrap: anywhere; }
.err .w small{ display: block; font-size: 0.75rem; color: var(--muted); }
.err .wrong{ color: var(--crit); font-weight: 600; }
.err .arrow{ color: var(--muted); margin: 0 0.25rem; }
.err.false .w b,.err.false .w .wrong{ text-decoration: line-through; text-decoration-color: var(--rule-2); }
.err .acts{ display: flex; gap: 2px; padding-inline-end: 4px; }
.err .vd,.list-f .vd{ display: inline-grid; place-items: center; line-height: 1; font-weight: 700; border-radius: 50%; }
.err .vd{ width: 28px; height: 28px; font: inherit; font-size: 0.85rem; font-weight: 700; border: 1.5px solid var(--rule-control); background: transparent; color: var(--muted); cursor: pointer; padding: 0; }
.err .vd.is-err{ background: var(--crit); border-color: var(--crit); color: var(--crit-ink); }
.err .vd.is-fp{ background: var(--surface-3); border-color: var(--rule-control); color: var(--ink-2); }
.err .vd.del{ border-style: dashed; }
.err .vd:focus-visible,.err .pl-sel:focus-visible{ outline: 2px solid var(--accent); outline-offset: 1px; }
/* подпись под списком — одна строка постоянной высоты: список не укорачивается */
.list-f{ margin: 0; padding: 0 0.75rem; height: 2.5rem; display: flex; align-items: center; gap: 5px; flex: none; border-top: 1px solid var(--rule); font-size: 0.75rem; color: var(--muted); white-space: nowrap; overflow: hidden; }
.list-f .vd{ width: 16px; height: 16px; border: 1.5px solid var(--rule-control); font-size: 0.75rem; flex: none; }
.list-f .vd.is-err{ background: var(--crit); border-color: var(--crit); color: var(--crit-ink); }
.list-f .vd.is-fp{ background: var(--surface-3); color: var(--ink-2); }
.list-f .gap{ width: 4px; flex: none; }
.list-f button{ font: inherit; color: var(--accent); background: none; border: 0; padding: 0; text-decoration: underline; cursor: pointer; }
.focus{ padding: 0.9rem 1.25rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.6rem; align-content: start; }
.focus-h{ display: flex; gap: 8px 12px; align-items: center; min-height: 32px; }
.fh-tags{ display: flex; gap: 8px; align-items: center; flex: 1 1 auto; min-width: 0; flex-wrap: wrap; font-weight: 600; color: var(--ink); }
.fh-tags .tc{ font-family: var(--mono); font-weight: 500; color: var(--accent); }
.reader-empty{ padding: 3rem 1rem; }
/* Окно чтения — книжная страница с местом в одной точке (решения владельца
   07–08.10.2026): reader.js набирает строки сам — абзацы с красной строки,
   полные строки по ширине без переносов слов, последняя строка абзаца влево.
   Строка места — линза посередине окна (без прокрутки), над ней —
   полоса пометки чтеца; место — в середине своей строки. Окно — жёсткий
   прямоугольник; предложение с местом — полным цветом, прочий текст приглушён */
.reader{ --lh: 1.6; --above: 2; --chip: 2.2rem; font-family: var(--book); font-size: 1.15rem; line-height: var(--lh); color: var(--ink-2); }
.rd-win{ position: relative; height: calc((var(--above) * 2 + 1) * var(--lh) * 1em + var(--chip)); overflow: hidden; }
.rd-lines{ position: absolute; inset: 0; overflow: hidden; padding-inline: 12px; color: var(--muted); -webkit-hyphens: none; hyphens: none; font-kerning: normal; }
.rd-p1,.rd-p3{ position: absolute; }
.rl{ margin: 0; white-space: nowrap; text-align: left; text-indent: 0; -webkit-hyphens: none; hyphens: none; }
/* линза (вариант «Е», 08.10.2026): фраза вокруг места крупнее, середина места —
   в центре окна; слева текст прижат к центру, справа — от центра, края гаснут.
   Появление — наплывом (scale + opacity, токены движения) */
.rd-lens{ position: absolute; left: 12px; right: 12px; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: end; padding: 26px 0 2px; line-height: 1.4; white-space: nowrap; color: var(--ink);
  border-radius: var(--r-panel, 14px); background: var(--raised, #fff); box-shadow: 0 0 0 1px var(--line, rgba(0,0,0,.08)), var(--shadow, 0 8px 24px -16px rgba(0,0,0,.3)); }
.rd-lens .ln-l, .rd-lens .ln-r{ display: flex; min-width: 0; overflow: hidden; }
.rd-lens .ln-l{ justify-content: flex-end; -webkit-mask-image: linear-gradient(to right, transparent, #000 40%); mask-image: linear-gradient(to right, transparent, #000 40%); }
.rd-lens .ln-r{ justify-content: flex-start; -webkit-mask-image: linear-gradient(to left, transparent, #000 40%); mask-image: linear-gradient(to left, transparent, #000 40%); }
.rd-lens .ln-in{ white-space: pre; }
.rd-lens .ln-m{ position: relative; }
.rd-lens .pm .note{ bottom: calc(100% + 1px); padding: 0 8px; line-height: 22px; }
.rd-p1 .rl-off, .rd-p3 .rl-off{ visibility: hidden; }
.rd-lens .wd{ color: var(--ink-2, var(--ink)); }
.rd-lens .snt, .rd-lens .rl-m{ color: var(--ink); }
@keyframes nv-lens-in{ from{ opacity: 0; transform: scale(0.96); } to{ opacity: 1; transform: none; } }
@media (prefers-reduced-motion: no-preference){ .rd-lens.rd-in{ animation: nv-lens-in var(--m-base, 220ms) var(--e-out, ease-out) both; } }
.rl-m.rl-wrap{ display: inline-block; white-space: normal; text-align: center; vertical-align: middle; line-height: var(--lh); }
.rl-note{ text-align: center; font-family: var(--sans); font-size: 0.85rem; color: var(--muted); }
.rl-m,.rd-lines .snt{ color: var(--ink); }
.rd-measure{ position: absolute; left: 0; top: 0; visibility: hidden; white-space: pre; pointer-events: none; }
/* бегущее слово: янтарный цвет и тонкая черта под ним; черта одна на окно и
   переезжает от слова к слову сдвигом (reader.js), без движения — только цвет */
.wd.now{ color: var(--sig-t); }
.rd-cur{ position: absolute; left: 0; top: 0; width: 1px; height: 2px; border-radius: 1px; background: var(--sig-g); transform-origin: 0 0; opacity: 0; pointer-events: none; }
.rd-cur.on{ opacity: 1; }
/* место — одна единица: сплошное янтарное подчёркивание по всей группе слов
   (пробелы и знаки внутри — тоже), при переносе — по каждой строке */
.pm{ position: relative; text-indent: 0; }
.pm .note{ position: absolute; left: 50%; bottom: calc(100% + 0.35em); transform: translateX(calc(-50% + var(--nx, 0px))); text-indent: 0; font-family: var(--sans); font-size: 1rem; font-weight: 600; line-height: 1.35; color: var(--crit); background: var(--crit-soft); padding: 3px 11px; border-radius: 7px; white-space: nowrap; pointer-events: none; letter-spacing: 0; word-spacing: 0; -webkit-hyphens: none; hyphens: none; }
.pm .note i{ font-style: normal; font-weight: 500; opacity: 0.85; }
.pm .w,.pm .wg{ font-weight: 600; color: var(--ink); text-decoration: underline solid var(--sig-g); text-decoration-thickness: 2px; text-underline-offset: 0.24em; text-decoration-skip-ink: none; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.pm-ins{ display: inline-block; width: 0.9em; height: 1em; vertical-align: -0.1em; }
.pm-ins svg{ position: absolute; left: 0; bottom: -0.1em; width: 0.9em; height: 0.7em; color: var(--sig-g); }
@media (prefers-reduced-motion: no-preference){
.wd{ transition: color var(--m-micro) var(--e-out); }
.rd-cur{ transition: transform var(--m-fast) var(--e-out), opacity var(--m-fast) var(--e-out); }
}
@media (prefers-reduced-motion: reduce){ .rd-cur{ transition: none !important; } }
/* Панель решений: плеер прямо над кнопками решения */
.deck{ display: grid; gap: 8px; }
.deck audio{ display: none; }
.deck-play{ display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.deck-play .sp{ flex: 1 1 0; min-width: 0; }
#listen{ min-width: 7rem; }
.verdicts{ display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: 10px; }
.vbtn{ min-width: 0; min-height: 3rem; font: inherit; font-weight: 600; font-size: 1rem; border-radius: 10px; padding: 0.6rem 0.9rem; border: 1.5px solid var(--rule-2); background: var(--surface); color: var(--ink); cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; }
.vbtn kbd{ font-family: var(--mono); font-size: 0.75rem; font-weight: 500; border: 1px solid var(--rule-2); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; color: var(--ink-2); background: var(--surface); }
.vbtn.v-err{ border-color: var(--crit); color: var(--crit); }
.vbtn.v-err[aria-pressed="true"]{ background: var(--crit); color: var(--crit-ink); }
.vbtn.v-fp[aria-pressed="true"]{ background: var(--ink-2); border-color: var(--ink-2); color: var(--surface); }
.vbtn.v-skip{ border-style: dashed; color: var(--muted); font-size: 0.9rem; }
.vbtn:disabled{ border-style: dashed; border-color: var(--rule-2); color: var(--muted); background: transparent; cursor: not-allowed; }
.vbtn:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
.keys{ margin: 0; color: var(--muted); font-size: 0.78rem; }
.keys kbd{ font-family: var(--mono); }
.pauses{ margin: 0.5rem 0; }
/* кнопки пауз одеты как строки списка (страж test_report_pause_buttons_are_dressed_like_the_list) */
.pauses .t{ font: inherit; border: 0; background: transparent; color: var(--ink); cursor: pointer; padding: 0.35rem 0.5rem; border-radius: var(--r-sm); }
@media (hover: hover){
.pauses .t:hover{ background: var(--surface-2); }
}
@media (forced-colors: active){
.vbtn,.err .vd,.seg button[aria-pressed="true"]{ border: 1px solid CanvasText; }
.vbtn[aria-pressed="true"],.err .vd[aria-pressed="true"]{ outline: 2px solid Highlight; }
.tl-wrap .tl i{ forced-color-adjust: none; }
}
/* Узкий экран: карточка места сверху, список под ней своим окном; клавиши —
   подсказкой не нужны (телефон), цели пальца — не меньше 44 px */
@media (max-width: 56rem){
.rv{ grid-template-columns: minmax(0, 1fr); }
.rv > .lbox{ order: 2; contain: none; min-height: 0; }
.err-list{ max-height: 16rem; }
}
@media (max-width: 40rem){
.keys{ display: none; }
.focus{ padding: 0.75rem; }
.reader{ font-size: 1rem; --lh: 1.6; --chip: 2.1rem; }
.verdicts{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.verdicts .v-skip{ grid-column: span 2; min-height: 44px; }
.vbtn{ min-height: 3.25rem; }
.deck-play [data-skip="-2"],.deck-play [data-skip="2"]{ display: none; }
.err .vd{ width: 44px; height: 44px; }
.filters{ display: grid; grid-template-columns: 1fr 1fr; gap: 0.35rem; }
}
/* ─── экраны автора 2.0 (макет v18): таблицы материалов и частей, полосы
   состояний, ход проверки, импорт. Цвет полосы — второй канал: числа
   всегда стоят подписью рядом. ─── */
.box{ background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r); }
.box.empty{ padding: 2rem 1.25rem; }
.scroll-x{ overflow-x: auto; -webkit-overflow-scrolling: touch; }
.eyebrow{ font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.bar{ display: flex; height: 8px; border-radius: 99px; overflow: hidden; background: var(--surface-3); }
.bar i{ display: block; height: 100%; }
.bar .b-ok{ background: var(--ok); }
.bar .b-acc{ background: var(--accent); }
.bar .b-warn{ background: var(--warn); }
.bar .b-crit{ background: var(--crit); }
/* «Не ошибка» — цветом второстепенного текста: --gone на дорожке давал
   2.55:1 в светлой теме при норме 3:1 для значимой графики */
.bar .b-fp{ background: var(--muted); }
.bar .b-gone{ background: var(--gone); opacity: 0.55; }
.pill-gone{ background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1px var(--rule-control); }
.tbl{ width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.tbl th{ text-align: start; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--rule); white-space: nowrap; }
.tbl td{ padding: 0.7rem 0.75rem; border-bottom: 1px solid var(--rule); vertical-align: middle; }
.tbl tr:last-child td{ border-bottom: 0; }
.tbl .num{ font-variant-numeric: tabular-nums; }
.tbl .t{ font-weight: 600; color: var(--ink); display: inline-flex; align-items: center; min-height: 24px; overflow-wrap: anywhere; }
.tbl .t:hover{ color: var(--accent); }
.tbl td.act{ text-align: end; }
.tbl td.act > *{ vertical-align: middle; }
.tbl td.act form{ display: inline; }
.row-actions{ display: flex; align-items: flex-start; justify-content: flex-end; flex-wrap: wrap; gap: 0.4rem; }
.live-note{ display: inline-flex; align-items: center; gap: 0.35rem; color: var(--accent); font-size: 0.8rem; font-weight: 600; }
.live-note .spinner{ width: 13px; height: 13px; border-width: 1.5px; flex: 0 0 auto; }
.live-note--waiting{ color: var(--warn); }
.live-note--queued{ color: var(--muted); }
.inline-form{ display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }
.inline-form label{ margin: 0; }
.inline-form select{ width: auto; padding: 0.4rem 0.6rem; }
.pager{ display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 0.8rem; }
.steps{ display: flex; gap: 0.4rem; flex-wrap: wrap; margin: 0 0 1rem; list-style: none; padding: 0; }
.steps li{ font-size: 0.8125rem; font-weight: 600; color: var(--muted); display: flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.65rem 0.25rem 0.25rem; border-radius: 99px; background: var(--surface-2); }
.steps li span{ width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-3); font-size: 0.75rem; }
.steps li.done{ color: var(--ok); }
.steps li.done span{ background: var(--ok-soft); }
.steps li.now{ color: var(--accent); background: var(--accent-soft); }
.steps li.now span{ background: var(--accent); color: var(--accent-ink); }
/* итог отправки книги на проверку — шаг 4 на странице книги */
.sent-done{ margin: 0 0 1rem; padding: 0.9rem 1.1rem; border: 1px solid var(--rule); border-left: 4px solid var(--ok); border-radius: var(--r); background: var(--surface); }
.sent-done .steps{ margin-bottom: 0.6rem; }
.sent-done p{ margin: 0; }
.sent-done-t{ margin-bottom: 0.25rem !important; }
.upload-how{ margin: 0 0 0.8rem; max-width: 70ch; }
.upload-next{ margin: 0; }
/* пункты окна подтверждения у клиента (склейка глав, отмена импорта) — списком,
   как у оператора (nv-studio.css), а не продолжением вопроса */
.nv-confirm-points:not([hidden]){ display: flex; flex-direction: column; gap: 6px; margin: 12px 0 0; padding: 0; list-style: none; color: var(--ink-2); }
.nv-confirm-points li{ display: flex; gap: 8px; overflow-wrap: anywhere; }
.nv-confirm-points li::before{ content: "·"; color: var(--muted); flex: none; }
.pairs select{ width: auto; max-width: 100%; min-width: 12rem; padding: 0.4rem 0.6rem; font-size: 0.875rem; }
.pairs .title{ font-weight: 600; }
.pairs .sub{ font-size: 0.8125rem; color: var(--muted); }
/* первое предложение главы и кнопка «послушать» — сопоставить пару на слух */
.pairs .pair-open{ margin: 0.3rem 0 0; max-width: 46ch; font-size: 0.8125rem; color: var(--ink-2); font-style: italic;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.pair-audio{ display: flex; align-items: center; gap: 0.5rem; }
/* глава может идти несколькими файлами — каждый своей строкой */
.pair-files{ display: grid; gap: 0.4rem; justify-items: start; }
.pair-file{ display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; max-width: 100%; }
.pair-file .ib,.pair-more{ min-width: 44px; min-height: 44px; }
.pair-more{ padding: 0 0.6rem; font-size: 0.875rem; }
.pairs .pair-doubt{ margin: 0.35rem 0 0; max-width: 46ch; font-size: 0.8125rem; font-weight: 600; color: var(--warn); }
.pair-row:focus{ outline: 2px solid var(--accent); outline-offset: -2px; }
.pair-loose{ padding: 1rem 1.1rem; border-top: 1px solid var(--rule); display: grid; gap: 0.5rem; }
.pair-loose h2{ margin: 0; }
.pair-loose-list{ list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.pair-loose-item{ display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.pair-loose-name{ font-weight: 600; min-width: 10rem; }
.pair-loose-item select{ width: auto; max-width: 100%; padding: 0.4rem 0.6rem; font-size: 0.875rem; }
/* правка глав: меню строки, окна «Разрезать» и «Добавить главу» */
.pair-intro{ display: flex; justify-content: space-between; align-items: center; gap: 0.5rem 1rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.pair-intro p{ margin: 0; }
/* слова главы и её правки — одной строкой: «Разрезать» и «Склеить» видны сразу */
.pair-meta{ display: flex; align-items: center; flex-wrap: wrap; gap: 0 0.25rem; }
.pair-meta .sub{ margin-right: 0.35rem; }
.pairs .pair-tool{ min-height: 44px; padding: 0 0.55rem; font-size: 0.8125rem; color: var(--ink-2); }
.pairs .pair-tool:hover{ color: var(--ink); }
.pair-gap{ margin-bottom: 0.6rem; }
.pair-acts{ display: inline-block; }
.pair-acts[open]{ display: block; width: 100%; }
.pair-acts summary{ list-style: none; display: inline-flex; align-items: center; justify-content: center; min-width: 44px; cursor: pointer; }
.pair-acts summary::-webkit-details-marker{ display: none; }
.pair-acts-menu{ display: flex; flex-wrap: wrap; gap: 0 0.25rem; padding: 0.1rem 0 0.2rem; }
.last-sent{ margin: -0.4rem 0 1rem; }
/* «Отменить импорт» на телефоне — коротко «Отменить» (полное имя — для диктора) */
.pair-cancel-s{ display: none; }
.sum-bal{ color: var(--ink-2); white-space: nowrap; }
.pair-add-row{ padding: 0.8rem 1.1rem; border-top: 1px solid var(--rule); }
.pair-dlg{ width: min(40rem, calc(100vw - 2rem)); max-height: calc(100dvh - 2rem); padding: 0; border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface); color: var(--ink); }
.pair-dlg::backdrop{ background: rgb(0 0 0 / 0.45); }
.pair-dlg-form{ display: grid; gap: 0.55rem; padding: 1.2rem; }
.pair-dlg-form h2{ margin: 0; }
.pair-dlg-form p{ margin: 0; }
.pair-dlg-form textarea{ width: 100%; min-height: 8rem; }
.pair-dlg-acts{ display: flex; justify-content: flex-end; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.3rem; }
.cut-box{ max-height: min(50dvh, 26rem); overflow-y: auto; border: 1px solid var(--rule); border-radius: var(--r-sm); }
.cut-lines{ list-style: none; margin: 0; padding: 0; }
.cut-line{ display: grid; grid-template-columns: 3.6rem minmax(0, 1fr); gap: 0.5rem; padding: 0.45rem 0.7rem; border-bottom: 1px solid var(--rule); font-size: 0.875rem; cursor: pointer; }
.cut-line:last-child{ border-bottom: 0; }
.cut-line[aria-disabled]{ cursor: default; color: var(--muted); }
.cut-line.hit{ background: var(--warn-soft); box-shadow: inset 4px 0 0 var(--warn); }
.cut-line[aria-checked=true]{ background: var(--accent-soft); box-shadow: inset 0 3px 0 var(--accent); }
.cut-line:focus{ outline: 2px solid var(--accent); outline-offset: -2px; }
.cut-at{ font-variant-numeric: tabular-nums; }
.add-files{ border: 1px solid var(--rule); border-radius: var(--r-sm); padding: 0.5rem 0.75rem; display: grid; gap: 0.3rem; max-height: 12rem; overflow-y: auto; }
.add-file-opt{ display: flex; gap: 0.5rem; align-items: center; min-height: 44px; cursor: pointer; }
.add-file-opt input{ width: 1.1rem; height: 1.1rem; }
.add-file-opt[hidden],.add-files-none[hidden]{ display: none; }
/* display: grid/flex выше перебивает [hidden] */
.pair-loose[hidden],.pair-loose-item[hidden],.pairs .pair-doubt[hidden],.pair-file .pair-drop[hidden]{ display: none; }
.pair-play .i-pause,.pair-play[aria-pressed=true] .i-play{ display: none; }
.pair-play[aria-pressed=true] .i-pause{ display: inline; }
/* главное действие страницы пар — шире соседнего «Отменить импорт» */
.pair-go{ min-width: 16rem; justify-content: center; }
@media (max-width: 40rem){ .pair-go{ min-width: 0; flex: 1 1 auto; } }
.sumbar{ display: flex; justify-content: space-between; align-items: center; gap: 0.75rem 1.25rem; flex-wrap: wrap; padding: 1rem 1.1rem; border-top: 1px solid var(--rule); background: var(--surface-2); border-radius: 0 0 var(--r) var(--r); }
/* сводка пар с кнопкой отправки держится у нижнего края, пока видна таблица:
   у книги на 40 глав итог и «Начать поиск ошибок» не уезжают за десяток экранов */
#pairs .sumbar{ position: sticky; bottom: 0; z-index: 2; box-shadow: 0 -10px 24px -18px rgb(0 0 0 / 0.55); }
/* элемент в фокусе не уходит под закреплённую сводку (WCAG 2.4.11); прокручивается
   окно, поэтому отступ — у корня, и только на странице пар */
:root:has(#pairs .sumbar){ scroll-padding-bottom: var(--sum-h, 11rem); }
.prog{ display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.prog > *{ min-width: 0; }
.state{ padding: 1.4rem; display: flex; flex-direction: column; align-items: flex-start; gap: 0.6rem; }
.state .spinner{ width: 12px; height: 12px; border-width: 1.5px; }
.state-title{ font-size: 1.35rem; margin-top: 0.3rem; }
.state p{ color: var(--ink-2); max-width: 36em; }
.state .eta{ font-weight: 600; color: var(--ink); margin: 0; }
.state-acts{ display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.5rem; }
.prog-next{ padding: 1rem 1.1rem; display: grid; gap: 0.5rem; }
.prog-next #job-note{ margin: 0; text-align: start; font-size: 0.875rem; color: var(--ink-2); }
.prog-next #job-note:empty{ display: none; }
@media (max-width: 48rem){
.prog{ grid-template-columns: minmax(0, 1fr); }
.tbl td.act{ text-align: start; }
.row-actions{ justify-content: flex-start; }
}
/* Телефон: строка таблицы — карточка. Заголовки колонок остаются для чтеца
   экрана, глазу их роль играют подписи в ячейках. */
@media (max-width: 40rem){
.tbl thead{ position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.tbl,.tbl tbody,.tbl tr{ display: block; width: 100%; }
.tbl tr{ display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.35rem; padding: 0.75rem 0.9rem; border-bottom: 1px solid var(--rule); }
.tbl tr:last-child{ border-bottom: 0; }
.tbl td{ display: block; padding: 0; border: 0; min-width: 0; }
.tbl td.act{ display: flex; flex-wrap: wrap; gap: 0.4rem; }
.pairs tr{ grid-template-columns: 2rem minmax(0, 1fr); }
.pairs td:nth-child(3){ grid-column: 2; }
.pairs select{ min-width: 0; width: 100%; min-height: 44px; }
.pair-loose-item select{ min-height: 44px; }
#pairs .sumbar{ padding: 0.6rem 0.9rem; gap: 0.4rem; }
/* телефон: закреплённая сводка — итог и кнопки; обычная подсказка уходит,
   предупреждение (дубль, длинная глава, нехватка минут) остаётся */
#pairs .sumbar p{ font-size: 0.875rem; }
#pairs .sumbar > div:first-child{ min-width: 0; flex: 1 1 100%; }
.sum-bal{ white-space: normal; }
.form-acts .btn{ max-width: 100%; white-space: normal; height: auto; min-height: 44px; }
/* скрыта только глазу: живая область остаётся в дереве и объявит появившееся предупреждение */
#pairs .sumbar #sum-note:not(.is-problem){ position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
#pairs .sumbar .head-acts{ display: flex; width: 100%; gap: 0.4rem; flex-wrap: nowrap; }
#pairs .sumbar .head-acts .btn-ghost{ flex: 0 0 auto; padding: 0 0.6rem; }
.pair-cancel-x{ position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.pair-cancel-s{ display: inline !important; }
#pairs .sumbar .pair-go{ white-space: normal; height: auto; min-height: 44px; line-height: 1.2; text-align: center; }
.pair-audio select{ flex: 1 1 auto; }
.pair-file{ width: 100%; flex-wrap: nowrap; }
.pair-file select{ flex: 1 1 auto; }
.pair-loose-item{ display: grid; grid-template-columns: minmax(0, 1fr) auto; }
.pair-loose-item select{ grid-column: 1 / -1; width: 100%; }
}
.new-material{ max-width: 36rem; padding: 1.35rem; }
.short-audio{ margin: 1rem 0; padding: 1rem 1.1rem; border: 1px solid var(--rule); border-radius: var(--r-sm); background: var(--surface-2); }
.short-audio legend{ font-weight: 600; padding: 0 0.3rem; }
.extend-form{ display: inline-flex; gap: 0.35rem; align-items: center; }
.extend-form select{ width: auto; padding: 0.3rem 0.5rem; font-size: 0.85rem; min-height: 32px; }
.error-box{ max-width: 34rem; margin: 5rem auto 0; padding: 1.6rem 1.5rem; display: grid; gap: 0.6rem; justify-items: start; }
/* Строка таблицы на телефоне — сетка, а правило автора перебивает [hidden]
   браузера: фильтр частей ничего не прятал (ревью 2026-09-28) */
.tbl tr[hidden]{ display: none; }
/* Телефон: цели экрана сверки не меньше 44 px (правило владельца) */
@media (max-width: 40rem){
#status-filter button,#list-settings > summary,#goto-first{ min-height: 44px; display: inline-flex; align-items: center; }
}
/* Режим высокой контрастности: полоса места и слово под звуком — фоном,
   который система снимает; вместо него рамка */
@media (forced-colors: active){
.wd.now,.pm.now{ outline: 2px solid Highlight; }
}
/* ─── новый облик 2026-10-04: образ книги, карточки материалов, плитки частей ───
   Решение владельца: компактно, одна главная кнопка на карточку, остальное в «⋯»,
   обложки не нужны — образ собирает сервис (медальон). */
/* Круговая волна записи (макет): тонкий круг и 56 штрихов цветом подборки */
/* Карточки материалов: 4 в ряд, на планшете 2, на телефоне 1 */
/* остаток табличной вёрстки (.books .bar: 8–14rem) карточке не нужен */
/* Подборка-карточка на главной кабинета */
/* Плитки частей книги */
/* «Загрузить перезапись чтеца» раскрывается внутри плитки, а не всплывает: плитка
   у левого края, и всплывающая форма уходила за экран */
/* правило раскладки не перебивает [hidden] (страж test_phone_part_filter_really_hides_rows) */
/* Меню «⋯» книги в шапке: история, перенос, удаление (было подвалом страницы) */
/* Телефон: заголовки Unbounded мельче — шрифт широкий, на 320 px длинное слово
   не вмещалось. В конце файла: правила страниц (.prose h1 и т. п.) объявлены выше
   и при равной весомости иначе перебили бы эти. */
/* приёмка 2026-10-04: номер шага мастера импорта — контраст 4.5:1 */
.steps li span{color:var(--ink-2)}
.bar .b-fp{background:var(--muted)}
