/* Инструмент проверяющего: плотная типографика, никаких украшений.
   Отчёт должны читать с экрана и печатать на бумагу — отсюда светлая тема
   по умолчанию и отдельные правила для печати в конце файла. */
:root {
  /* Зелёный ведущим, а не синий: сервис говорит «сошлось» или «не сошлось»,
     и цвет согласия — тот же, каким помечены пройденные проверки. Синий не
     значил здесь ничего, кроме «это ссылка». */
  --bg: #fbfbfa; --fg: #16181d; --muted: #626873; --line: #dcdfe4;
  --card: #ffffff; --accent: #146b45; --high: #b3261e; --medium: #8a5a00;
  --low: #4a5568; --info: #2c6e49; --ok: #2c6e49;
  /* Подложка под кадрами талисмана. На тёмной теме это лист бумаги: кадр
     несёт мягкую тень под ногами, вырезать её нельзя — она той же светлоты,
     что белый корпус, и связана с фигурой; без подложки под роботом остаётся
     белая клякса. На светлой теме подложке быть нечего, и она сливается с
     карточкой. Пока здесь стоя́л беж `#faf8f3` при любой теме, на светлой он
     лежал тёплым пятном с закруглёнными углами на белой карточке — ровно то,
     чего в комментарии к `.verdict .mood` обещано не было. */
  --paper: var(--card); --d-paper: #faf8f3;
  /* Тёмные полосы на светлой странице: своим цветом, а не темой. Ими
     разделены разделы, и они должны быть тёмными при любой теме */
  --ink: #14161a; --ink-fg: #e6e8ec; --ink-muted: #9aa1ad; --ink-line: #2b3038;
  --ink-card: #1b1e24;

  /* Тёмные значения названы один раз и включаются двумя правилами ниже:
     системной настройкой и выбором в шапке. Дублировать сами цвета нельзя —
     разъедутся при первой же правке. */
  --d-bg: #14161a; --d-fg: #e6e8ec; --d-muted: #9aa1ad; --d-line: #2b3038;
  --d-card: #1b1e24; --d-accent: #5fc48d; --d-high: #ff8a80; --d-medium: #f0b429;
  --d-low: #b6bdc9; --d-info: #7fd1a3; --d-ok: #7fd1a3;
}
/* Системная настройка — по умолчанию, но выбор человека её перебивает: тот,
   кто нажал «светлая» при тёмной системе, хотел именно светлую. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: var(--d-bg); --fg: var(--d-fg); --muted: var(--d-muted);
    --line: var(--d-line); --card: var(--d-card); --accent: var(--d-accent);
    --high: var(--d-high); --medium: var(--d-medium); --low: var(--d-low);
    --info: var(--d-info); --ok: var(--d-ok);
    --paper: var(--d-paper);
  }
}
:root[data-theme="dark"] {
  --bg: var(--d-bg); --fg: var(--d-fg); --muted: var(--d-muted);
  --line: var(--d-line); --card: var(--d-card); --accent: var(--d-accent);
  --high: var(--d-high); --medium: var(--d-medium); --low: var(--d-low);
  --info: var(--d-info); --ok: var(--d-ok);
  --paper: var(--d-paper);
}
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 16px/1.55 -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}
/* По середине, а не по базовой линии: со знаком в шапке базовая линия имени
   уехала вниз на высоту картинки, и меню срывалось на вторую строку. */
header {
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
  padding: 12px 24px; border-bottom: 1px solid var(--line); background: var(--card);
}
/* Знак и имя стоят рядом, а подпись — под именем, а не под всем блоком:
   иначе она уезжает под картинку и висит сама по себе. */
.logo {
  font-weight: 700; font-size: 20px; text-decoration: none; color: var(--fg);
  display: inline-flex; align-items: center; gap: 12px;
}
.logo b { font-weight: inherit; }
.logo span { color: var(--accent); }
/* подпись под знаком: ссылку кидают в чат людям, которые про сервис не
   слышали, и одно название им ничего не говорит */
.logo small {
  display: block; font-size: 10px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted); margin-top: 1px;
}
/* Меню переносится по строкам. Без переноса пять пунктов не помещались в
   телефон: сама полоса меню оказывалась шире экрана, а вместе с ней и вся
   страница — «Вход» уезжал за правый край, и появлялась горизонтальная
   прокрутка на всех разделах сразу. */
nav { display: flex; gap: 8px 18px; margin-left: auto; flex-wrap: wrap; }
nav a, a { color: var(--accent); }
main { max-width: 1080px; margin: 0 auto; padding: 28px 24px 60px; }
footer {
  max-width: 1080px; margin: 0 auto; padding: 20px 24px 40px;
  color: var(--muted); font-size: 14px; border-top: 1px solid var(--line);
}
h1 { font-size: 28px; margin: 0 0 8px; }
h2 { font-size: 21px; margin: 32px 0 10px; }
h3 { font-size: 17px; margin: 22px 0 6px; }
p.lead { color: var(--muted); margin-top: 0; }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 20px 22px; margin: 18px 0;
}
/* Разбор не удался — это не мелкая пометка: без структуры проверка пуста,
   и пустой отчёт легко принять за «замечаний нет». */
.card.alarm { border-left: 4px solid var(--high); }
.card.warn { border-left: 4px solid var(--medium); }
.diag {
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 12px 14px; margin: 12px 0; font-size: 13px; white-space: pre-wrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-x: auto;
}
/* Рамка альбома рядом с формой: спрашивать «как подписана графа», не показав
   графу, — значит получить в ответ то, что написано внутри клетки. */
.frame-shot { margin: 14px 0; }
.frame-shot img {
  display: block; max-width: 100%; height: auto; background: #fff;
  border: 1px solid var(--line); border-radius: 6px;
}
.frame-shot figcaption { margin-top: 6px; }

/* слова из рамки: нажал — попало в поле. Перепечатывая вручную, человек и
   заменяет подпись графы на то, что стоит в клетке */
button.word {
  background: var(--bg); border: 1px solid var(--line); border-radius: 999px;
  padding: 2px 10px; margin: 0 4px 4px 0; font: inherit; font-size: 13px;
  color: inherit; cursor: pointer;
}
button.word:hover { border-color: var(--accent); }

.row { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; }
/* Плашки в ряду тянутся на одну высоту. По середине они плавают: текста в
   них разное количество, и не совпадает ни верх, ни низ — заголовки встают
   лесенкой, а ряд читается как несколько отдельных кусков вместо одного.
   Правило узкое, на плашки: в прочих рядах по середине стоят кнопки и
   подписи, и там центрирование верно. */
.row > .card { align-self: stretch; }
/* Ряд плашек — сетка, а не строка. Строкой последняя плашка при переносе
   растягивается во всю ширину: четыре по 260 пунктов требуют 1100, а полоса
   набора 1032, и «3 + 1 во всю строку» выходило само собой. Сетка кладёт их
   поровну и переносит парами. */
.cards {
  display: grid; gap: 20px; margin: 18px 0;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.cards > .card { margin: 0; }
/* Форма загрузки: поля разной высоты, и подсказки под ними тоже разные.
   По середине они разъезжаются — подписи встают на разной высоте, а глаз
   ищет одну линию. Поэтому здесь выравнивание по верху. */
.row.aligned { align-items: flex-start; }
.row.aligned > div > input[type="file"],
.row.aligned > div > select,
.row.aligned > div > button { margin-top: 2px; }
.label-gap { display: inline-block; }
/* `min-width: 0` обязательно: у flex-элемента наименьшая ширина по умолчанию
   равна ширине содержимого, и он не сжимается. Поле выбора файла показывает
   имя целиком, поэтому альбом с длинным именем распирал колонку и вылезал за
   край карточки — заказчик прислал снимок. */
.grow { flex: 1 1 260px; min-width: 0; }
/* То же и для соседей по ряду. Ширину выпадающего списка задаёт самый длинный
   пункт — «Автоматизация технологических процессов (АТХ)», — и без этого
   блок с ним не сжимался: на телефоне карточка формы вылезала за правый край
   вместе с подписью под ней. Дефект того же рода, что у поля файла, только
   вылез позже: у списка длинный пункт есть всегда, а длинное имя файла —
   не у каждого. */
.row.aligned > div { min-width: 0; }
/* …и сами поля не шире колонки: содержимое внутри обрезается, а не тянет поле. */
.row.aligned > div > input[type="file"],
.row.aligned > div > select { width: 100%; box-sizing: border-box; }
/* Тарифы: плашки сравнивают глазами, поэтому колонки строго равные и одной
   высоты. На flex-обёртке лишняя плашка переносилась на свою строку и
   растягивалась во всю ширину — рядом с тремя узкими читалась как главная. */
.tiers {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px; margin: 18px 0;
}
.tiers .card { display: flex; flex-direction: column; margin: 0; }
.tiers .card h3 { margin-top: 0; }
.tiers .price { margin: 0 0 4px; }
.tiers .hint { margin-bottom: 0; padding-top: 10px; }
.tiers .card > .hint:last-child { margin-top: auto; }
/* Подвал плашки: ровно одна кнопка, прижатая к низу. Кнопки стояли сразу за
   описанием, а описания разной длины — ряд получался лесенкой. Кнопка именно
   одна: от двух подвалы выходят разной высоты, и уровень снова расходится,
   а выбор между двумя одинаково громкими кнопками ещё и задерживает
   решение. Помесячная оплата уведена в ссылку выше. */
.tiers .tier-foot { margin-top: auto; padding-top: 14px; }
.tiers .tier-foot form { margin: 0; }
.tiers .tier-foot button, .tiers .tier-foot .button {
  width: 100%; text-align: center;
}
/* выгода названа числом, а не словом «выгодно» */
.save { margin: 0 0 10px; font-size: 14px; line-height: 1.6; }
.save .badge { color: var(--ok); }
.was { color: var(--muted); text-decoration: line-through; font-weight: 400; }
/* оплата помесячно — ссылка в тексте, но за ней форма: цена уходит POST'ом,
   как и у главной кнопки, а не адресом, который можно подсунуть по ссылке */
.as-text { display: inline; }
button.link {
  background: none; border: none; padding: 0; font: inherit;
  color: var(--accent); text-decoration: underline; cursor: pointer;
  display: inline; width: auto;
}
@media (max-width: 900px) { .tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .tiers { grid-template-columns: 1fr; } }
/* развилка из двух равных дорог: прочитать как есть или прочитать точно.
   Колонки ровно две — auto-fit втискивал бы третью и ломал пару */
.split {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px; margin: 16px 0;
}
.split > * { border-top: 2px solid var(--line); padding-top: 12px; }
.split h3 { margin-top: 0; }
@media (max-width: 720px) { .split { grid-template-columns: 1fr; } }
button, .button {
  font: inherit; padding: 9px 18px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
  text-decoration: none; display: inline-block;
}
button.ghost, .button.ghost { background: transparent; color: var(--accent); }
button:disabled { opacity: .5; cursor: default; }
.inline-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.inline-form select, .inline-form input[type=date] { font-size: 14px; padding: 4px 6px; }
button.small { padding: 4px 12px; font-size: 14px; }
/* Переключатель темы. Кнопку ставит скрипт — без него она не делала бы
   ничего, а мёртвая кнопка в шапке хуже её отсутствия. */
button.theme {
  align-self: center; padding: 2px 6px; font-size: 17px; line-height: 1;
  border: none; background: transparent; color: var(--muted);
}
button.theme:hover { color: var(--fg); }
input[type=file], input[type=date], select, input[type=text] {
  font: inherit; padding: 7px 9px; border: 1px solid var(--line);
  border-radius: 6px; background: var(--bg); color: var(--fg); max-width: 100%;
}
table { border-collapse: collapse; width: 100%; font-size: 15px; }
th, td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; }
td.num, th.num { text-align: right; }
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 92%; }
.muted { color: var(--muted); }
.err { color: var(--high); }
/* извещение об исходе, за которым стоят деньги: цветного текста тут мало —
   человек возвращается из банка и ищет глазами, прошло или нет */
.good, .warn {
  margin: 0 0 18px; padding: 12px 16px; border-radius: 8px;
  border: 1px solid currentColor; background: var(--card); font-size: 15px;
}
.good { color: var(--ok); }
.warn { color: var(--medium); }
.progress { height: 8px; background: var(--line); border-radius: 4px; overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--accent); width: 0; transition: width .4s; }
/* разбор оборвался: полоса заполнена, но цветом «не получилось», а не рабочим —
   иначе полная полоса читается как «готово» */
.progress > i.lost { background: var(--high); }
.badge {
  display: inline-block; padding: 1px 8px; border-radius: 20px; font-size: 12px;
  border: 1px solid currentColor;
}
.sev-high { color: var(--high); }
.sev-medium { color: var(--medium); }
.sev-low { color: var(--low); }
.sev-info { color: var(--info); }
/* Замечание — плашка того же вида, что образец на главной. Человек видит
   образец до загрузки и свой отчёт после; разный вид одного и того же читался
   бы как разные вещи. Левый край цветом важности остался: по нему отчёт
   пролистывают, ища серьёзное. */
.finding {
  border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: 8px; background: var(--card);
  padding: 12px 16px; margin: 16px 0;
  /* Текст замечания — обычного цвета, важность несут метка и левый край.
     Класс важности стоит на всей плашке, и её цвет доставался заодно
     описанию: серьёзное замечание выходило красным целиком, вместе с
     объяснением и нормой. Читать это тяжело, а главное — красным становилось
     всё подряд, и указывать оказывалось нечем. */
  color: var(--fg);
}
.finding.sev-high { border-left-color: var(--high); }
.finding.sev-medium { border-left-color: var(--medium); }
.finding .head {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin: 0 0 6px; font-size: 13px;
}
.finding .head .muted { font-size: 13px; }
.finding p { margin: 0 0 6px; }
.finding p:last-child { margin-bottom: 0; }
.finding .where { color: var(--muted); font-size: 14px; }
.finding .change { font-family: ui-monospace, Menlo, monospace; font-size: 14px; }
.finding .norm { color: var(--muted); font-size: 13px; font-style: italic; }
/* откуда взято: страницы, на которых движок это увидел */
.finding .from { color: var(--muted); font-size: 13px; }

/* ------------------------------------------------------------ разбор находок

   Три решения по каждому замечанию: принято, не ошибка, отложено. Кнопками в
   строку, а не списком выбора с «сохранить»: решение принимается одним
   движением, и видно оно без раскрытия. Сто замечаний при списке выбора — это
   двести щелчков, и разбор на этом кончается.

   Разобранное замечание глохнет фоном, а не цветом текста: по отчёту
   пролистывают, ища неразобранное, и глаз должен цеплять именно его. Цветом
   важности при этом ничего не теряется — левый край остаётся. */
.triage { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap;
  margin-top: 10px; }
.triage .hint { font-size: 13px; }
.pill {
  display: inline-block; background: var(--bg); border: 1px solid var(--line);
  border-radius: 999px; padding: 2px 10px; font: inherit; font-size: 13px;
  color: inherit; cursor: pointer; text-decoration: none;
}
.pill:hover { border-color: var(--accent); }
.pill.on { border-color: var(--accent); color: var(--accent); font-weight: 600; }
/* Пустое состояние в фильтре остаётся на месте, но гаснет: исчезающие ссылки
   переставляют ряд под рукой, и человек щёлкает не туда, куда вёл глаз. */
.pill.nil { color: var(--muted); }
.chips { display: flex; gap: 6px; flex-wrap: wrap; align-items: baseline; }
.finding.done { background: var(--bg); }
.finding.done .head .badge:not(.onlyprint) { opacity: .7; }
/* Видно только на бумаге. Распечатанный отчёт несут на приёмку, и там решение
   по пункту важнее кнопок, которых на бумаге всё равно нет. */
.onlyprint { display: none; }
.summary td.num { font-variant-numeric: tabular-nums; }
.scroll { overflow-x: auto; }
.sheets td { padding: 3px 8px; font-size: 14px; }
.sheets select { padding: 2px 4px; font-size: 13px; }
.hint { font-size: 14px; color: var(--muted); }

/* Страница «Что проверяем». Правил четыре десятка, и у каждого объяснение на
   несколько абзацев — полотном это не читают. Снаружи остаётся строка: что
   сверяется. Всё остальное — чем расхождение грозит, когда это не ошибка, по
   какой норме — под «Подробнее», и раскрывается только у того правила, ради
   которого человек сюда пришёл. `scroll-margin-top` нужен, чтобы после
   перехода по якорю из отчёта заголовок не прилипал к кромке окна. */
.rule { scroll-margin-top: 16px; border-left: 3px solid var(--line);
  padding: 4px 0 4px 14px; margin: 10px 0; }
.rule-high { border-left-color: var(--high); }
.rule-medium { border-left-color: var(--medium); }
.rule > summary { color: var(--fg); font-size: inherit; }
.rule-lead { display: block; color: var(--muted); margin-top: 2px; }
.rule p { margin: 8px 0; }
.rule .norm { color: var(--muted); font-size: 13px; font-style: italic; }
details > summary { cursor: pointer; color: var(--accent); font-size: 14px; }
details[open] > summary { margin-bottom: 6px; }
/* Свёрнутая справка: основание находки и перечни правил. Набирается тише
   самого замечания — это ответ на вопрос «почему», а не сам ответ. */
.why > summary { font-size: 13px; color: var(--muted); }
.why > summary:hover { color: var(--accent); }
.why.wide > summary { font-size: 14px; }
.why p { margin: 6px 0; }
@media print {
  /* На бумаге сворачивать нечего: основание находки нужно целиком — по нему
     спорят с проектировщиком. Раскрывается разметкой, а не стилем: скрытое
     содержимое `details` браузер прячет сам, и `display` его не возвращает. */
  .why > summary { display: none; }
}
/* Разбор структуры сворачивается, когда проверка пошла: он длинный, а ответа
   в этот момент ждут от отчёта. Заголовок при этом остаётся заголовком — по
   нему страницу и находят глазами. */
#structure > summary { color: inherit; }
#structure > summary > h2 { display: inline-block; margin: 0; }
h2[id] { scroll-margin-top: 16px; }
/* Ссылка, которая не хочет выглядеть ссылкой: заголовок правила и заголовок
   замечания в отчёте. Подчёркивание появляется под курсором — тот, кто ищет
   объяснение, его найдёт, а тот, кто читает подряд, не спотыкается о синеву. */
.anchor { color: inherit; text-decoration: none; }
.anchor:hover { text-decoration: underline; }

/* Вход и регистрация. Страница узкая и центрированная: здесь всего одна
   задача, и всё, что не поле ввода, только мешает её выполнить. Слева от
   формы — короткое напоминание, что аккаунт ничего не открывает и не
   закрывает: иначе регистрация читается как платный барьер. */
.auth { max-width: 880px; margin: 0 auto; }
.auth-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  gap: 34px; align-items: start; }
@media (max-width: 760px) { .auth-grid { grid-template-columns: 1fr; gap: 18px; } }

.auth-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 26px 28px 22px; box-shadow: 0 1px 2px rgba(16, 24, 40, .04),
                                       0 8px 24px rgba(16, 24, 40, .06);
}
@media (prefers-color-scheme: dark) { .auth-card { box-shadow: none; } }
.auth-card h1 { font-size: 24px; margin-bottom: 4px; }
.auth-side { font-size: 14px; color: var(--muted); }
.auth-side h2 { font-size: 15px; margin: 0 0 8px; color: var(--fg); }
.auth-side ul { margin: 0 0 18px; padding-left: 18px; }
.auth-side li { margin: 5px 0; }

.field { margin: 0 0 16px; }
.field > label { display: block; font-size: 14px; font-weight: 600; margin-bottom: 5px; }
.field input[type=email], .field input[type=password], .field input[type=text] {
  font: inherit; width: 100%; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg); color: var(--fg);
}
.field input:focus-visible, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.field .note { display: block; font-size: 13px; color: var(--muted); margin-top: 5px; }
.field .note.err { color: var(--high); }
.field .note.ok { color: var(--ok); }
.field.bad input { border-color: var(--high); }

/* Полоса надёжности: не оценка «сложности», а честный ответ на вопрос
   «этот пароль легко подобрать?» — длина решает больше, чем спецсимволы. */
.meter { height: 5px; border-radius: 3px; background: var(--line); margin-top: 8px;
  overflow: hidden; opacity: 0; transition: opacity .2s; }
.meter.weak, .meter.fair, .meter.good { opacity: 1; }   /* пока не набрали — не мозолит глаз */
.meter > i { display: block; height: 100%; width: 0; transition: width .25s, background .25s; }
.meter.weak > i { width: 33%; background: var(--high); }
.meter.fair > i { width: 66%; background: var(--medium); }
.meter.good > i { width: 100%; background: var(--ok); }

.auth-card button[type=submit] { width: 100%; padding: 11px 18px; font-weight: 600; }
.auth-foot { margin: 14px 0 0; font-size: 14px; text-align: center; color: var(--muted); }
.auth-legal { margin: 16px 0 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
.show { font-size: 14px; color: var(--muted); user-select: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; }
ul.plain { list-style: none; padding-left: 0; }
ul.plain li { margin: 6px 0; }

@media print {
  /* На бумагу отчёт уходит светлым, какая бы тема ни стояла на экране: серый
     по белому в тёмной палитре печатается почти невидимым. Селектор с
     атрибутом нужен, чтобы перебить выбор темы, а не только системный. */
  :root, :root[data-theme] {
    --bg: #fff; --fg: #16181d; --muted: #626873; --line: #dcdfe4;
    --card: #ffffff; --accent: #146b45; --high: #b3261e; --medium: #8a5a00;
    --low: #4a5568; --info: #2c6e49; --ok: #2c6e49;
  }
  header, footer, nav, form, .noprint { display: none !important; }
  .onlyprint { display: inline-block !important; }
  body { background: #fff; color: #000; font-size: 12pt; }
  .card { border: none; padding: 0; }
  main { max-width: none; padding: 0; }
}

/* ------------------------------------------------ главная: полосы во всю ширину

   Разделы разделены цветом фона, а не отступом: страница длинная, и на
   расстоянии видно, где кончилось одно и началось другое. Внутри полосы
   содержимое держит ту же ширину, что и на остальных страницах, — читать
   строку в 1500 пикселей невозможно. */
main.wide { max-width: none; padding: 0; }
.band { border-bottom: 1px solid var(--line); }
.band > .wrap { max-width: 1080px; margin: 0 auto; padding: 44px 24px; }
.band.tint { background: var(--card); }
.band.ink {
  background: var(--ink); color: var(--ink-fg); border-bottom-color: var(--ink);
}
.band.ink h2, .band.ink h3, .band.ink strong { color: var(--ink-fg); }
.band.ink .muted, .band.ink .hint { color: var(--ink-muted); }
.band.ink .card {
  background: var(--ink-card); border-color: var(--ink-line); color: var(--ink-fg);
}
.band.ink a { color: #7fd1a3; }

/* Заголовок раздела слева, содержимое справа: колонка с названием и одной
   фразой объясняет, что сейчас будет, и не отнимает ширину у самого важного */
.band .aside {
  display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 36px;
  align-items: start;
}
.band .aside > .said { margin: 0; }
.band .aside h2 { margin: 0 0 10px; }
@media (max-width: 800px) { .band .aside { grid-template-columns: 1fr; gap: 16px; } }

.eyebrow {
  display: inline-block; font-size: 12px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 14px;
  border: 1px solid var(--line); border-radius: 20px; padding: 3px 12px;
}
h2.section {
  font-size: 13px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin: 0 0 10px;
}

/* Первый экран: слева обещание и сама форма, справа — что получится. Не
   рисунок «как бы отчёта», а числа с демонстрационного альбома: их сверяет
   `tests/demo_album.py` с тем, что движок находит на самом деле */
.hero-top { padding-bottom: 0; }
.hero-top h1 { font-size: 42px; line-height: 1.1; margin: 0 0 16px; letter-spacing: -.02em; }
.hero-top h1 em { font-style: normal; color: var(--accent); }
.hero-top .lead { font-size: 17px; max-width: 46em; margin-bottom: 0; }
/* Форма и пример — ряд из двух ячеек, выровненных по верху. Пока пример лежал
   в одной колонке с заголовком, его верх равнялся на заголовок и с формой не
   совпадал ничем: высота текста над формой меняется от длины строки, от
   ширины окна и от того, вошёл ли человек. */
.band > .wrap.hero { padding-top: 20px; }
.hero {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 40px; align-items: start;
}
.hero > div > .card:first-child, .hero .panel { margin-top: 0; }
@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; }
  .hero-top h1 { font-size: 32px; }
}

/* Панель «что получится»: сводка слева, одно настоящее замечание справа */
.panel { border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
.panel > .top {
  font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); padding: 10px 16px; border-bottom: 1px solid var(--line);
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
}
/* «пример» набирается заметнее прочего в шапке: панель стоит вплотную к форме
   загрузки и выглядит как готовый отчёт — принять её за свой результат проще,
   чем кажется */
.panel > .top .badge {
  letter-spacing: .06em; font-weight: 700; background: var(--card);
}
.panel > .body { display: grid; grid-template-columns: 150px minmax(0, 1fr); }
.panel .sum { padding: 16px; border-right: 1px solid var(--line); }
.panel .sum .big { font-size: 30px; font-weight: 700; line-height: 1.1; }
.panel .sum .big.good { color: var(--ok); }
.panel .sum .big.bad { color: var(--high); }
.panel .sum p { margin: 0 0 12px; font-size: 13px; color: var(--muted); }
.panel .pick { padding: 16px; }
@media (max-width: 560px) {
  .panel > .body { grid-template-columns: 1fr; }
  .panel .sum { border-right: 0; border-bottom: 1px solid var(--line); }
}

/* Сличение: слева одно, справа другое. На витрине между ними «≠» — там
   названы два документа, и знак говорит «не сошлись». В отчёте его нет:
   вопрос у читателя другой — какое число откуда, — и на него отвечают
   подписи, а символ между ними только просит истолкования. */
/* Карточки тянутся на всю высоту ряда, а слово между ними стои́т по центру.
   При выравнивании по центру каждая карточка была своей высоты — подпись
   «модулей ввода-вывода» в две строки против «базовых блоков» в одну, — и
   рядом оказывались две рамки разного размера со сдвинутыми краями. Читается
   это как небрежность ровно там, где показывают аккуратность. */
.versus {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 10px; align-items: stretch; margin: 14px 0;
}
.versus .ne { align-self: center; }
.versus.plain { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 30em; }
/* Между документами стоит слово, а не знак «≠». Знак читают математики и
   программисты; проектировщику он не говорит ни что случилось, ни что делать.
   Слово говорит хотя бы первое, а второе досказывает подпись «должно быть». */
.versus .ne {
  font-size: 12px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--high); font-weight: 700; text-align: center; white-space: nowrap;
}
.versus .doc {
  border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px;
  background: var(--bg);
  /* Подпись под числом — «модулей ввода-вывода» — в узкой колонке ломалась по
     дефису на три строки. Ломать по дефису тут нечего: обе части слова нужны
     вместе, а места хватает, если не переносить внутри слова. */
  overflow-wrap: normal; word-break: keep-all;
}
.band.ink .versus .doc { background: var(--ink); border-color: var(--ink-line); }
.versus .doc .what {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 6px;
}
.versus .doc .num { font-size: 22px; font-weight: 700; font-family: ui-monospace, Menlo, monospace; }
@media (max-width: 560px) {
  .versus { grid-template-columns: 1fr; }
  .versus .ne { justify-self: center; }
}
/* То же, но по ширине места, отведённого блоку, а не окна. В карточке примера
   на документ остаётся полтораста точек: «модулей ввода-вывода» ломается по
   дефису на три строки, и рядом с однострочными «базовых блоков» это выглядит
   сломанным. Окно при этом широкое, и медиазапрос не помогает.

   Контейнером объявлен родитель: на ширину собственного размера элемент
   отзываться не может — запрос читает размер предка. */
.pick { container-type: inline-size; }
@container (max-width: 400px) {
  .versus { grid-template-columns: 1fr; gap: 8px; }
  .versus .ne { justify-self: center; }
}

/* Шаги работы: подряд, с номерами. Их шесть, и в ряд они помещаются только
   узкими — потому и без картинок: номер и два слова читаются, значок нет */
.steps {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 20px; margin: 8px 0 0;
}
.steps .step .no {
  font-family: ui-monospace, Menlo, monospace; font-size: 12px; color: var(--accent);
  font-weight: 700; letter-spacing: .06em;
}
.steps .step h3 {
  font-size: 14px; letter-spacing: .04em; text-transform: uppercase; margin: 6px 0 4px;
}
.steps .step p { margin: 0; font-size: 14px; color: var(--muted); }

/* Строки состава: номер, название, значок исхода */
.rows { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.rows .r {
  display: grid; grid-template-columns: 46px minmax(0, 1fr) auto;
  gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--line);
  align-items: center; font-size: 15px;
}
.rows .r:last-child { border-bottom: 0; }
.rows .r .no { font-family: ui-monospace, Menlo, monospace; color: var(--muted); font-size: 13px; }
.rows .r .mark { font-weight: 700; }

.legend { display: flex; gap: 10px; flex-wrap: wrap; margin: 16px 0 0; }
.legend > span {
  border: 1px solid currentColor; border-radius: 6px; padding: 6px 12px;
  font-size: 13px;
}

/* Полоса с призывом: одна строка, одна кнопка, ничего кроме */
.cta { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; }
.cta > div { flex: 1 1 320px; }
.cta h2 { margin: 0 0 4px; font-size: 24px; }

@media print {
  /* Полосы главной и рамки замечаний — экранные приёмы. На бумаге тёмная
     полоса съедает картридж и делает текст нечитаемым, а рамка вокруг
     каждого замечания дробит отчёт на клетки. Правило стоит последним:
     оно обязано перебивать и тему, и разметку главной. */
  .band, .band.ink, .band.tint {
    background: #fff !important; color: #000 !important; border: none;
  }
  .band > .wrap { padding: 0; max-width: none; }
  .band.ink a, .band.ink h2, .band.ink h3, .band.ink .muted { color: #000; }
  .finding {
    border: none; border-left: 3px solid var(--line);
    border-radius: 0; padding: 2px 0 2px 14px; background: transparent;
  }
  .versus { display: block; }
  .versus .doc { border: none; padding: 0; background: transparent; }
}

/* Ожидание разбора: талисман, который читает документ.

   Полоса на большом альбоме подолгу стоит на месте — работа идёт постранично,
   и процент меняется раз в несколько секунд. Неподвижная страница при этом
   читается как зависшая, и человек жмёт «обновить», теряя задание. Движение
   здесь и отвечает на единственный вопрос ожидающего: «оно вообще живо?».

   Картинки лежат рядом, в `static/`. Наружу страница не ходит ни за чем — ни
   за шрифтом, ни за анимацией: на ней открыт чужой альбом. */
.waiting {
  margin: 4px auto 14px;
  width: min(376px, 80%);
  /* Лист бумаги под фигурой. Сами кадры прозрачные — анимация идёт
     анимированным WebP, у которого полупрозрачность настоящая, а не в один
     бит, как у гифа, и рваной каймы по мягкому краю нет. Подложка нужна не
     ради кромки, а ради тени: талисман отбрасывает её под ноги, вырезать
     тень нечем, и на тёмной теме она читалась бы белой кляксой. Лист её
     объясняет — персонаж стои́т на бумаге. */
  background: var(--paper);
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
}
.waiting img { display: block; width: 100%; height: auto; }
.waiting img[hidden] { display: none; }
/* Анимацию не остановить ни стилем, ни скриптом — поэтому у каждой позы
   есть отдельная неподвижная картинка, и показывается ровно одна из двух.
   Отметку `hidden` ставит этап, и она сильнее: у `.waiting img[hidden]`
   вес выше, чем у правил ниже, так что спрятанную этапом картинку
   настройка движения не вытащит. */
.waiting .still { display: none; }
@media (prefers-reduced-motion: reduce) {
  .waiting .alive { display: none; }
  .waiting .still { display: block; }
}
@media print { .waiting { display: none; } }

/* Знак в шапке. Стоит перед именем и не мешает ему: имя — то, что читают и
   ищут, а знак лишь помогает узнать вкладку среди десятка открытых. */
.logo img { width: 64px; height: 64px; flex: none; }
@media (max-width: 640px) {
  .logo { gap: 8px; font-size: 18px; }
  .logo img { width: 44px; height: 44px; }
}

/* Настроение отчёта. Сводку читают бегло, и один взгляд должен говорить, чем
   кончилось; слова при этом остаются нашими — «ошибок нет» сервис обещать не
   вправе, он сверяет документ сам с собой, а не подтверждает решения. */
.verdict { position: relative; }
.verdict .mood {
  float: right;
  width: 150px;
  height: auto;
  margin: -8px -4px 4px 16px;
  /* Та же бумажная подложка, что у картинки ожидания, и по той же причине.
     Кадр талисмана несёт мягкую тень под ногами — её не вырезать: она той же
     светлоты, что белый корпус, и связана с фигурой, а на тёмной теме под
     роботом оставалась белая клякса. Подложка тень не прячет, а объясняет:
     персонаж стои́т на листе бумаги.

     Здесь раньше стоя́л беж прямым цветом, и к нему была приписка «на светлой
     теме её не видно». Видно: карточка белая, беж тёплый, и подложка лежала
     на ней пятном с закруглёнными углами. Теперь цвет идёт из `--paper`,
     который на светлой теме равен цвету карточки. */
  background: var(--paper);
  border-radius: 10px;
  padding: 4px;
  box-sizing: border-box;
}
@media (max-width: 640px) { .verdict .mood { width: 104px; margin-left: 10px; } }
@media print { .verdict .mood { display: none; } }

/* Блок, к которому человека привела ссылка из замечания. Подсветка держится
   до перезагрузки страницы, а не гаснет по таймеру: читают не сразу, и мигнув
   однажды, подсказка исчезнет ровно у того, кто отвлёкся. */
details.lit {
  border-left: 4px solid var(--accent);
  padding-left: 12px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
details.lit > summary { font-size: inherit; }
.lit-note {
  margin: 6px 0 10px;
  padding: 8px 10px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
