/*
 * Стили сервиса «Перед поездкой».
 *
 * Главный пользователь — человек 45–70 лет, часто с телефона (Паспорт §2).
 * Отсюда правила, которые здесь нельзя «оптимизировать»:
 *   - базовый шрифт 20px и не меньше;
 *   - кнопка не ниже 56px и во всю ширину экрана на телефоне;
 *   - контраст текста не ниже 7:1;
 *   - никаких сторонних шрифтов (ADR-0009): только системные.
 */

/* ======================================================================
   СЛОЙ ТОКЕНОВ (R11-001)
   ======================================================================

   Одно место, где заданы цвет, отступ, скругление и толщина линии. До R11
   значения были рассыпаны по правилам, и «поправить фон» означало найти его
   в семи местах. Страницы обращаются к токенам и не знают чисел.

   Цвет риска — не украшение (R11-005):

     --red     только точное совпадение с записью официального перечня;
     --orange  только «нужно уточнить» / «возможное совпадение»;
     --accent  обычное действие и навигация;
     --ready   готовность процесса, спокойная, не «всё хорошо»;
     --pending — ждём, не сделано.

   Основное действие красным не бывает никогда. Если однажды красная кнопка
   появится на обычном экране, красный перестанет что-либо значить — и человек
   перестанет замечать его там, где он важен.

   Поверхность тёплая, бумажно-льняная: продукт открывают в тревожную минуту,
   и холодный синий лист этому не помогает. Чернила сдержанные, тёмные.
*/

/* --- Тема ---------------------------------------------------------------
 *
 * Тёплая светлая — единственная тема продукта (R11-010).
 *
 * До R11.2 тёмные значения включались сами, по системной настройке. Владелец
 * открыл стенд на своём телефоне и увидел почти чёрный сайт: продукт читался
 * как панель службы безопасности, а не как общественный сервис. Причина была
 * не в палитре — светлая уже существовала, — а в том, что её никто не видел.
 *
 * Поэтому тёмные значения остались в файле, но включаются только явным
 * `data-theme="dark"` на <html>. Переключателя в продукте пока нет: тёмная
 * тема — отдельная работа, и делать её наспех, торгуя за это первым
 * впечатлением, незачем.
 */

:root {
  color-scheme: light;

  /* --- Поверхности ---
   * Четыре ступени, и разница между ними маленькая. Глубину даёт ступень
   * поверхности и слабая тень, а не рамка: до R11.2 продукт состоял из
   * прямоугольников в рамках, вложенных друг в друга, и выглядел собранным
   * из полей ввода.
   *
   * В R11.3 бумага стала теплее ещё на шаг. Причина не вкусовая: владелец
   * сказал, что вид «аккуратный, но не свой». Холодноватый небелёный лист —
   * это вид любого сервиса; лён с ощутимой желтизной уже чей-то. */
  --paper: #f6f2e9;        /* фон страницы: суровый лён */
  --card: #fffcf6;         /* поверхность карточки */
  --card-raised: #ffffff;  /* поднятая поверхность: главное действие, шапка */
  --card-sunken: #efe9dc;  /* утопленная: вставка, путь внутри чужого меню */

  /* --- Чернила ---
   * Контраст каждой пары «чернила на поверхности» не ниже 7:1 и посчитан, а не
   * прикинут на глаз. Приглушённый текст приглушён цветом, но не читаемостью:
   * оговорки и мелкий шрифт человек 60+ обязан прочитать. */
  --ink: #15181d;          /* основной текст, контраст к бумаге 15.9:1 */
  --ink-soft: #454d59;     /* пояснение, подпись: 7.6:1 к бумаге */

  /* --- Линии ---
   * Волосяные. Линия существует, чтобы разделить, а не чтобы обвести:
   * рамка вокруг каждого блока — главная причина, по которой интерфейс
   * читался механическим. */
  --line: #e3dcce;         /* разделитель */
  --line-strong: #c6bda9;  /* линия, которую надо заметить */

  /* --- Действие ---
   * Глубокая васильковая синь. До R11.3 здесь стоял сине-серый: он был
   * спокойным, но ничьим. Василёк — цвет льняного поля и вышивки по полотну,
   * то есть ремесла и людей, а не государства и не движения. Контраст
   * посчитан: 7.9:1 к бумаге, 8.8:1 для белого текста на заливке. */
  --accent: #2c4a7c;
  --accent-strong: #1d3560; /* наведение и удержание */
  --accent-soft: #e9edf5;   /* очень слабая заливка под действием */
  --accent-ink: #ffffff;

  /* --- Нить ---
   * Тёплый лён-солома. Единственное назначение — украшение: полоса мотива,
   * засечка у заголовка, край карточки. Текстом, состоянием, рамкой поля или
   * подписью он не бывает никогда: смысловые цвета уже заняты, и пятый
   * значащий цвет сделал бы неразличимыми первые четыре.
   * `scripts/test-shell.mjs` падает, если нить уйдёт из украшения в смысл. */
  --thread: #8a6f42;

  /* --- Смысловые цвета: только по назначению --- */
  --red: #8c1d18;          /* точное совпадение */
  --red-bg: #fbeae8;
  --orange: #6f4300;       /* нужно уточнить */
  --orange-bg: #fdf3e2;
  --ready: #1c5335;        /* процесс завершён */
  --ready-bg: #e9f2ec;
  --pending: #4a4640;      /* ждём, не сделано */
  --pending-bg: #efe9dc;
  --neutral: #3b424d;
  --neutral-bg: #f1ece2;

  /* --- Шаг отступов. Один ряд, без промежуточных значений. --- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 80px;
  --gap: var(--space-5);

  /* --- Размеры текста (R11.3) -------------------------------------------
   *
   * Одна лестница вместо чисел, рассыпанных по правилам, и ступени у неё
   * подвижные: `clamp()` выбирает размер по ширине окна. Это не украшение —
   * до R11.3 заголовок был 33px и на телефоне, и на настольном экране, и
   * поэтому на телефоне он давил, а на большом экране терялся.
   *
   * Нижние границы неприкосновенны: основной текст 20px (Паспорт §2), мелкий
   * не мельче 17px. Оговорка, которую нельзя прочитать, — это оговорка,
   * которой нет. */
  --text-note: 17px;
  --text-small: 18px;
  --text-body: 20px;
  --text-lead: clamp(21px, 20px + 0.35vw, 23px);
  --text-h3: clamp(21px, 19.4px + 0.45vw, 24px);
  --text-h2: clamp(25px, 22.4px + 0.75vw, 31px);
  --text-h1: clamp(33px, 28.6px + 1.25vw, 44px);
  --text-display: clamp(36px, 29.5px + 1.85vw, 52px);

  /* --- Скругления. Сдержанные: это не витрина приложений. --- */
  --radius: 12px;
  --radius-sm: 8px;
  --radius-lg: 18px;

  /* --- Кромка: грамматика поверхностей (R11.3, система в R11.4) ---
   *
   * У ткани кромка — это край, по которому полотно узнают. В продукте она
   * заменила рамку вокруг блока: обведённый блок читается как поле ввода,
   * кромка — как край листа.
   *
   * В R11.4 кромка перестала быть украшением и стала грамматикой. Читается
   * она одинаково на любой странице, и значений ровно пять:
   *
   *   акцент, 5px   — это действие, которым можно воспользоваться сейчас;
   *   акцент, 3px   — это требование или условие: прочитать до действия;
   *   нить, 3px     — это пояснение, обещание, оговорка;
   *   кромки нет    — этого здесь пока нет (поверхность утоплена);
   *   красный 5px   — точное совпадение; оранжевый 3px — нужно уточнить.
   *
   * Отсюда правило, которое и делает вид системой: у поверхности с кромкой
   * нет рамки по кругу. Рамка и кромка вместе превращают страницу в набор
   * обведённых прямоугольников — ровно то, из-за чего продукт читался
   * «аккуратным, но ничьим». */
  --edge: 3px;
  --edge-strong: 5px;

  /* --- Тени. Слабые и тёплые: не «приложение», а лист на листе. --- */
  --shadow: 0 1px 2px rgba(60, 50, 35, 0.05);
  --shadow-soft: 0 1px 3px rgba(60, 50, 35, 0.06), 0 6px 16px -10px rgba(60, 50, 35, 0.14);
  --shadow-raised: 0 2px 6px rgba(28, 64, 90, 0.14), 0 12px 28px -16px rgba(28, 64, 90, 0.28);
  --shadow-lift: 0 4px 10px rgba(60, 50, 35, 0.08), 0 18px 34px -20px rgba(60, 50, 35, 0.26);

  /* --- Движение (R11.3) --------------------------------------------------
   *
   * Движение в этом продукте служит одному: показать, что нажатие принято и
   * что появилось новое. Ни одного движения ради красоты — человек открывает
   * сайт в тревожную минуту, и прыгающая страница этому не помогает.
   *
   * Длительности короткие намеренно. Всё, что дольше 0.4s, на телефоне
   * начинает ощущаться как задержка ответа, а не как плавность.
   *
   * Тот, кто попросил меньше движения, получает ноль движения: ниже стоит
   * общее правило, и эти токены там обнуляются. */
  --dur-fast: 0.12s;
  --dur: 0.2s;
  --dur-slow: 0.36s;
  --ease: cubic-bezier(0.2, 0, 0.1, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* --- Ширины ---
   *
   * Две, и у каждой своя работа.
   *
   * `--shell` — общий контейнер шапки, содержания и подвала. Он один, поэтому
   * имя в шапке, заголовок страницы и подвал стоят на ОДНОМ левом крае: пока у
   * оболочки была своя ширина, а у текста своя, на большом экране страница
   * читалась как две склеенные.
   *
   * `--measure` — предел строки текста внутри содержания. Абзац шириной в
   * тысячу пикселей не читается, сколько бы места ни было. Так на большом
   * экране сетка карточек получает всю ширину оболочки, а текст остаётся
   * читаемым, и левый край у них общий.
   */
  --shell: 61rem;
  --measure: 42rem;

  /* --- Область нажатия. Ниже не опускаться. --- */
  --tap: 48px;
  --tap-lg: 60px;

  /* --- Мотив плетения ---------------------------------------------------
   *
   * Один мотив в двух масштабах (R11-002, R11.3).
   *
   *   `--weave`      — плитка 32px: структура полотна. Полоса у края шапки и
   *                    подвала, фон утопленных частей.
   *   `--weave-band` — лента 96×24: тот же мотив, но раскрытый до
   *                    орнаментального ритма. Разделитель частей страницы и
   *                    засечка под заголовком раздела.
   *
   * Прозрачность разная у каждой роли: полоса под текстом навигации обязана
   * быть тише, чем разделитель между частями страницы. */
  --weave: url('/img/weave.svg');
  --weave-band: url('/img/weave-band.svg');
  /*
   * Льняная фактура (R13.1 §17) — поверхность, а не узор.
   *
   * У плетения есть рисунок, и его читают; у фактуры читать нечего. Она
   * работает на больших поверхностях оболочки — шапка, подвал, полоса о
   * данных — и не появляется под длинным текстом ни на одной странице:
   * шум под абзацем это усталость глаз, а не характер.
   *
   * Прозрачность вписана в сам файл: у фоновой картинки отдельной
   * прозрачности нет, а гасить её через ::after значило бы заводить слой
   * ради 5% серого.
   */
  --linen: url('/img/linen.svg');
  --linen-size: 16px;
  --weave-opacity: 0.22;
  --weave-opacity-rule: 0.34;
  --weave-opacity-band: 0.40;
}

/*
 * Тёмные значения. Включаются ТОЛЬКО явным `data-theme="dark"` и сами не
 * включаются никогда: см. примечание о теме выше. Оставлены здесь готовыми,
 * чтобы будущий переключатель не начинался с подбора палитры заново.
 */
:root[data-theme="dark"] {
  color-scheme: dark;

  --paper: #15171b;
  --card: #1d2026;
  --card-raised: #23272e;
  --card-sunken: #101216;

  --ink: #f4f1ea;
  --ink-soft: #c5c9cf;
  --line: #3a3f48;
  --line-strong: #545c66;

  --accent: #a8c6ec;
  --accent-strong: #c9dcf6;
  --accent-soft: #1e2733;
  --accent-ink: #0f141b;

  --thread: #c9a86a;

  --red: #ffb4aa;
  --red-bg: #3a1714;
  --orange: #f7c47a;
  --orange-bg: #33240c;
  --ready: #8fd3a8;
  --ready-bg: #14271c;
  --pending: #b9b3aa;
  --pending-bg: #23262b;
  --neutral: #d4d8de;
  --neutral-bg: #24282f;

  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-soft: 0 1px 3px rgba(0, 0, 0, 0.45);
  --shadow-raised: 0 2px 8px rgba(0, 0, 0, 0.5);
  --shadow-lift: 0 6px 18px rgba(0, 0, 0, 0.5);

  /* На тёмном фоне то же плетение заметнее — приглушаем сильнее. */
  --weave-opacity: 0.14;
  --weave-opacity-rule: 0.22;
  --weave-opacity-band: 0.26;
}

/* ======================================================================
   СЛОЙ ДВИЖЕНИЯ (R11.3)
   ======================================================================

   Правило одно: движение отвечает на действие человека или показывает, что
   появилось новое. Всё остальное — украшение, и его здесь нет.

   Три роли, и больше никаких:

     ОТКЛИК     нажатие, наведение, фокус. 0.12–0.2s, чтобы палец успел
                связать причину со следствием;
     РАСКРЫТИЕ  свёрнутый раздел и меню разделов: содержимое выезжает, а не
                возникает из ниоткуда;
     ПОДТВЕРЖДЕНИЕ  карточка результата и сообщение о состоянии: человек
                должен заметить, что ответ появился.

   Роли ровно три, и у всех трёх общее свойство: ни одна не прячет
   содержание. Выключи здесь весь слой движения — и страница останется
   полностью читаемой, просто без плавности.

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

/*
 * Человек, попросивший меньше движения, получает НОЛЬ движения.
 *
 * Правило стоит выше всего остального и написано через !important
 * намеренно: любое новое правило с переходом окажется под ним, и добавить
 * движение мимо этой настройки нельзя даже по невнимательности.
 *
 * Токены длительности тоже обнуляются: правило `transition: none` снимает
 * переход, но вычисления вида `calc(var(--dur) * 2)` продолжали бы жить.
 */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0s;
    --dur: 0s;
    --dur-slow: 0s;
  }

  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font: 20px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
}

/*
 * Содержание. Ширина — общая с шапкой и подвалом, чтобы левый край был один;
 * строку текста внутри держит `--measure` (см. примечание к ширинам).
 */
/*
 * Нижний отступ содержания намеренно небольшой (R11.4).
 *
 * До R11.4 хвост страницы складывался из четырёх отступов подряд: 64px под
 * содержанием, 16px у последнего абзаца, 24px ленты и 48px сверху в подвале.
 * Полторы сотни пикселей пустоты между последней фразой и первой строкой
 * подвала — это не воздух, а обрыв: страница выглядела законченной дважды.
 *
 * Отделяет содержание от подвала кромка подвала, а не пустота.
 */
.wrap {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-6) var(--space-5) var(--space-6);
}

/*
 * Предел строки текста. Перечислены именно текстовые блоки: сетка карточек и
 * таблица получают всю ширину оболочки и в этот список не входят.
 *
 * Без этого правила на экране 1280px абзац растягивался бы на 976px — глаз
 * теряет начало следующей строки, и человек перечитывает одну и ту же.
 */
.wrap h1, .wrap h2, .wrap h3, .wrap h4,
.wrap p, .wrap ul, .wrap ol, .wrap dl,
.wrap > details, .wrap blockquote, .wrap figure {
  max-width: var(--measure);
}

/* А это — блоки, которым ширина оболочки нужна целиком. Правило идёт после
   предела строки, поэтому его и отменяет. */
.wrap .platforms, .wrap .areas, .wrap .actions, .wrap .cards, .wrap .metrics,
.wrap .table-wrap, .wrap .btn-row, .wrap .trust, .wrap .trust__list,
.wrap .platform-group {
  max-width: none;
}

/* ======================================================================
   ОБЩАЯ ОБОЛОЧКА (R11)
   ======================================================================

   Шапка и подвал одинаковы на всех страницах продукта. До R11 человек,
   перейдя с главной в проверку, терял навигацию: каждая страница носила
   собственную шапку из двух строк без разделов.

   Меню на телефоне здесь нет намеренно. Скрытое меню — это лишнее действие и
   лишний шанс не найти раздел; для человека 60+ это плохая сделка. Поэтому
   разделы видны всегда, переносятся по строкам и нажимаются пальцем. Цена —
   две строки в шапке на узком экране; на телефоне поэтому показываются три
   главных раздела, остальные живут в подвале, где видны целиком. */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--accent-ink);
  padding: var(--space-3) var(--space-4);
  border-radius: 0 0 var(--radius) 0;
  z-index: 10;
  text-decoration: none;
  font-weight: 600;
}

/* Появляется только для того, кто идёт с клавиатуры, — и появляется заметно. */
.skip:focus { left: 0; }

.site-head {
  background: var(--card-raised);
  /* Фактура льна на поверхности шапки: длинного текста здесь нет, а
     характер продукт получает на каждой странице и на каждой ширине. */
  background-image: var(--linen);
  background-repeat: repeat;
  background-size: var(--linen-size) var(--linen-size);
  position: sticky;
  top: 0;
  z-index: 30;
}

/*
 * Почему шапка липкая (R11.3).
 *
 * Страницы продукта длинные: инструкция по выгрузке — это шесть шагов, а
 * раздел «если случилось» читается сверху донизу. Человек, дочитавший до
 * середины, до R11.3 не имел способа перейти в другой раздел, кроме как
 * прокрутить всё обратно вверх. На телефоне это десятки движений пальцем.
 *
 * Цена решения — 72px экрана. Плата принята осознанно: разделы нужны чаще,
 * чем эти 72px, и содержание под ними не прячется, а прокручивается.
 *
 * `scroll-padding-top` обязателен: без него переход по якорю ставит цель ровно
 * под шапку, и человек видит не заголовок, а его нижнюю половину.
 */
html { scroll-padding-top: 92px; scroll-padding-bottom: 104px; }

/* Полоса плетения у нижнего края шапки. Она же и разделитель: отдельной
   границы под шапкой больше нет — две линии подряд читались как рант. */
.site-head::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 10px;
  background-image: var(--weave);
  background-repeat: repeat;
  background-size: 32px 32px;
  background-position: center;
  opacity: var(--weave-opacity);
  pointer-events: none;
}

/* Тонкая линия под полосой плетения: край шапки должен быть определённым. */
.site-head::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--line);
  pointer-events: none;
}

.site-head__inner {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-3) var(--space-5) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.site-head__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

/*
 * Имя, обещание и знак.
 *
 * Знак слева — не логотип компании, а кромка полотна: квадрат с тем же
 * мотивом, что идёт полосой под шапкой. Он нарисован стилями, а не
 * разметкой, — иначе его пришлось бы вставить в двадцать шесть страниц и в
 * двадцати шести местах не разойтись.
 *
 * Сетка, а не колонка: знак стоит слева и занимает обе строки, имя и
 * обещание — справа друг под другом. Строкой из трёх надписей это на узком
 * экране расходилось и читалось как три несвязанные подписи.
 */
.site-head__brand {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-3);
  align-items: center;
  text-decoration: none;
  min-height: var(--tap);
}

/*
 * Знак продукта (R11-020).
 *
 * Это разметка, а не фоновая картинка: знак обязан брать цвет из темы, а
 * фоновая картинка currentColor не наследует и в тёмной теме осталась бы
 * тёмно-синей на тёмном. Ценой стали двадцать семь одинаковых вставок в
 * разметку — их держит посимвольная проверка шапки и подвала в
 * `scripts/test-shell.mjs`, и разойтись они не могут.
 *
 * Подложки под знаком нет. Квадрат с заливкой делал из знака кнопку, которой
 * он не является: знак — это подпись, а не действие.
 */
.site-head__mark {
  grid-row: 1 / 3;
  color: var(--accent);
  transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.site-head__name {
  font-size: 23px;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ink);
  line-height: 1.15;
}

.site-head__claim {
  color: var(--ink-soft);
  font-size: var(--text-note);
  line-height: 1.3;
}

.site-head__brand:hover .site-head__name { color: var(--accent); }
.site-head__brand:hover .site-head__mark { color: var(--accent-strong); }
.site-head__brand:active .site-head__mark { transform: scale(0.94); }

/* ----------------------------------------------------------------------
   РАЗДЕЛЫ САЙТА
   ----------------------------------------------------------------------

   Спокойная текстовая навигация, а не панель кнопок.

   До R11.2 каждый раздел был отдельной кнопкой в рамке, и шапка читалась как
   служебная панель: на телефоне это был плотный ряд мелких кнопок, который
   забирал внимание у первого действия. Рамок больше нет — есть подписи, у
   которых область нажатия человеческая, а текущий раздел отмечен чертой.

   Почему на телефоне меню, хотя в R11.1 его намеренно не было. Тогда выбор
   стоял между скрытым меню и видимым рядом; взят был ряд, и ряд оказался
   плотным. Теперь выбор другой: не «меню против ряда», а «меню с настоящей
   подписью против ряда мелких кнопок». Подпись «Разделы» — обычная кнопка с
   текстом, её видно и понятно; гамбургера без подписи здесь нет.

   Почему без единой строки скрипта. <details> умеет раскрываться сам, и
   <summary> для клавиатуры и экранного диктора уже кнопка с состоянием
   «раскрыто/свёрнуто». Скрипт добавил бы мигание при загрузке и отдельный
   отказ, если он не загрузился.
*/

/* Позиционируется не сама навигация, а шапка: раскрытое меню на телефоне
   встаёт под шапкой во всю её ширину, а не под кнопкой «Разделы». Поэтому
   опорой служит `.site-head`, у которой position: relative уже есть. */
.nav { position: static; margin-left: auto; }

.nav__menu > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: var(--space-2) var(--space-3);
  margin-right: calc(var(--space-3) * -1);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  list-style: none;
  width: max-content;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.nav__menu > summary:hover { background: var(--accent-soft); }
.nav__menu[open] > summary { background: var(--accent-soft); color: var(--accent-strong); }

/* Стрелка UA убирается в обоих семействах движков, иначе рядом с нашей
   появляется вторая. */
.nav__menu > summary::-webkit-details-marker { display: none; }
.nav__menu > summary::marker { content: ""; }

/* Своя стрелка: поворачивается, когда меню раскрыто. Смысл не держится на ней
   одной — состояние объявлено самим <summary> и видно по списку. */
.nav__menu > summary::after {
  content: "";
  width: 10px;
  height: 10px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.nav__menu[open] > summary::after { transform: translateY(2px) rotate(-135deg); }

.nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
 * Свёрнутое меню ничего не показывает; раскрытое — столбец крупных подписей
 * во всю ширину шапки.
 *
 * Никакого `display` у списка по умолчанию нет намеренно: задай его здесь — и
 * <details> перестанет скрывать содержимое вовсе. Это проверено в браузере:
 * со свойством display у списка свёрнутое меню оставалось раскрытым.
 */
.nav__menu[open] > .nav__list {
  display: flex;
  flex-direction: column;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 20;
  background: var(--card-raised);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-lift);
  padding: var(--space-2) var(--space-5) var(--space-4);
  animation: sheet-down var(--dur-slow) var(--ease-out);
}

/*
 * Меню раскатывается из-под шапки сверху вниз — как лист, который развернули.
 *
 * Разворачивается именно обрезка, а не прозрачность. Полупрозрачное меню в
 * движении показывает сквозь себя заголовок страницы: на снимке это выглядело
 * поломкой, а не анимацией. Обрезка оставляет меню плотным с первого кадра.
 *
 * У этого есть и второе следствие, более важное: меню ни в один момент не
 * бывает «наполовину невидимым» для браузера, поэтому нажатие по свежеоткрытому
 * разделу срабатывает сразу, а не после окончания движения.
 */
@keyframes sheet-down {
  from { clip-path: inset(0 0 100% 0); }
  to { clip-path: inset(0 0 0 0); }
}

/* Внутри раскрытого меню подписи крупнее и разделены линиями: это отдельный
   список, и пальцем по нему надо попадать не глядя. */
.nav__menu[open] > .nav__list li + li { border-top: 1px solid var(--line); }
.nav__menu[open] .nav__link { min-height: 56px; font-size: 19px; }

.nav__list li { margin: 0; }

.nav__link {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: var(--space-2) 0;
  color: var(--ink);
  font-size: var(--text-small);
  font-weight: 500;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}

.nav__link:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; }

/* Текущий раздел видно не только по цвету: он полужирный и подчёркнут. */
.nav__link[aria-current="page"] {
  color: var(--accent);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 5px;
}

/* --- Выбор языка ---
 *
 * Место — в подвале, рядом с остальными сведениями о сервисе, а не в шапке.
 * Причина простая: переключать пока нечего, а нерабочий указатель в шапке
 * стоил 48px первого экрана на каждой странице и телефоне. Когда появятся
 * белорусский и английский, сюда встанет настоящий выбор, и разметка страниц
 * от этого не изменится.
 *
 * Флажков здесь не будет: флаг — знак государства, а не языка, и в этом
 * продукте он был бы неуместен дважды. */

.lang {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  font-size: 17px;
  margin: 0;
}

.lang__label { color: var(--ink-soft); }
.lang__current { font-weight: 700; color: var(--ink); }
.lang__soon { font-size: 17px; color: var(--ink-soft); }

/* ----------------------------------------------------------------------
   ПОДВАЛ
   ----------------------------------------------------------------------

   Подвал — край страницы, а не вторая страница.

   До R11.2 здесь стояли пять столбцов по три-четыре ссылки, каждая высотой
   48px. На телефоне столбцы вставали друг под друга, и подвал занимал больше
   экрана, чем содержание: человек, докрутивший до конца, попадал во вторую
   навигацию и терялся в ней.

   Теперь ссылок ровно столько, сколько разделов: те же, что в шапке, плюс
   «Поддержать». Разделы второго уровня — телефон, семейный план, список из
   файла — живут внутри своих разделов, откуда человек к ним и идёт; сюда они
   не дублируются.
*/

.site-foot {
  border-top: 1px solid var(--line);
  background: var(--card);
  /* Та же фактура, что у шапки: страница закрывается тем же полотном, каким
     открылась. Под длинным текстом её нет — в подвале длинного текста нет. */
  background-image: var(--linen);
  background-repeat: repeat;
  background-size: var(--linen-size) var(--linen-size);
  color: var(--ink-soft);
  font-size: var(--text-note);
  position: relative;
}

/*
 * Край страницы (R11.3).
 *
 * У подвала теперь тот же знак, что в шапке, и лента мотива над ним: это
 * закрывающая кромка полотна. Человек, докрутивший до конца, видит, что
 * страница кончилась, а не что она оборвалась.
 */
.site-foot::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 24px;
  background-image: var(--weave-band);
  background-repeat: repeat-x;
  background-size: 96px 24px;
  background-position: center;
  opacity: var(--weave-opacity-band);
  pointer-events: none;
}

.site-foot__inner {
  max-width: var(--shell);
  margin: 0 auto;
  padding: var(--space-5) var(--space-5) var(--space-6);
}

.site-foot__brand {
  margin: 0 0 var(--space-4);
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-3);
  align-items: center;
}

/* Знак выравнивается по ПЕРВОЙ строке, а не по середине обеих: обещание в
   подвале занимает две строки, и знак, центрированный по ним, вставал ниже
   имени продукта и выглядел съехавшим. */
.site-foot__mark {
  grid-row: 1 / 3;
  align-self: start;
  margin-top: 3px;
  color: var(--accent);
}

.site-foot__name { font-weight: 700; color: var(--ink); font-size: 21px; }
.site-foot__line { display: block; font-size: var(--text-note); color: var(--ink-soft); }

/* Ссылки идут строкой и переносятся. Область нажатия остаётся человеческой за
   счёт высоты и боковых отступов, а не за счёт строки на каждую ссылку.
   На телефоне отступ увеличен: строка из шести подписей встаёт в три ряда, и
   между рядами палец обязан попадать не глядя. */
/* Ссылки идут строкой и переносятся. На телефоне это три ряда по 44px —
   ряды без промежутка, иначе подвал вырастает на полэкрана. Область нажатия
   держится высотой ряда и боковым промежутком, а не пустотой между рядами. */
.site-foot__links {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-5);
}

.site-foot__links li { margin: 0; }

.site-foot__links a {
  display: flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  color: var(--accent);
  font-weight: 500;
  font-size: var(--text-small);
  transition: color var(--dur-fast) var(--ease);
}

.site-foot__links a:hover { text-decoration: underline; text-underline-offset: 4px; color: var(--accent-strong); }

.site-foot__legal {
  border-top: 1px solid var(--line);
  padding-top: var(--space-4);
  margin-top: var(--space-4);
  font-size: var(--text-note);
  line-height: 1.55;
}

.site-foot__legal p { margin: 0 0 var(--space-2); max-width: var(--measure); }
.site-foot__legal p:last-child { margin-bottom: 0; }

/* --- Текст --- */

/*
 * Размеры (R11.3).
 *
 * Числа ушли в лестницу `--text-*`, и ступени у неё подвижные: заголовок,
 * который на телефоне не давит, на настольном экране обязан быть крупнее,
 * иначе страница читается как увеличенный телефон.
 *
 * Основной текст остаётся 20px и меньше не становится (Паспорт §2). Мелкий
 * шрифт не мельче 17px: оговорка, которую нельзя прочитать, — это оговорка,
 * которой нет.
 *
 * Вес выделяет главное в своём блоке и больше нигде. Когда выделено всё, не
 * выделено ничто; иерархию держат размер, воздух и — с R11.3 — засечка нити
 * под заголовком раздела.
 */

h1 {
  font-size: var(--text-h1);
  line-height: 1.16;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-4);
  font-weight: 700;
  text-wrap: balance;
}

h2 {
  font-size: var(--text-h2);
  line-height: 1.26;
  letter-spacing: -0.01em;
  margin: var(--space-7) 0 var(--space-3);
  font-weight: 650;
  text-wrap: balance;
}

h3 {
  font-size: var(--text-h3);
  line-height: 1.32;
  margin: var(--space-5) 0 var(--space-2);
  font-weight: 650;
}

p { margin: 0 0 var(--space-4); }
ul, ol { margin: 0 0 var(--space-4); padding-left: 24px; }
li { margin-bottom: var(--space-2); }

.lead { font-size: var(--text-lead); line-height: 1.5; color: var(--ink-soft); }
.muted { color: var(--ink-soft); font-size: var(--text-note); }

/* --- Стежок под заголовком раздела (R11.3) ----------------------------
 *
 * Короткая линия нитью под <h2> внутри содержания. Это не украшение ради
 * украшения: до R11.3 разделы длинной страницы различались только величиной
 * шрифта, и на телефоне при прокрутке человек терял место, где кончился один
 * раздел и начался другой.
 *
 * Лентой мотива здесь пробовали, и на снимках она читалась не ритмом, а
 * сором: на 48 пикселях от узора остаются три ромбика размером с опечатку.
 * Лента осталась там, где ей есть где развернуться, — на разделителях частей
 * страницы, — а под заголовком стоит ровно то, чем она держится: стежок.
 *
 * Экранный диктор его не читает вовсе: это фон, а не текст.
 */
.wrap > h2::after,
.below > h2::after,
.platform-group__title::after {
  content: "";
  display: block;
  width: 56px;
  height: 4px;
  border-radius: 2px;
  margin-top: var(--space-3);
  background: var(--thread);
  opacity: 0.8;
}

/* --- Надзаголовок раздела (R11.3) -------------------------------------
 *
 * Короткая подпись над заголовком: не «эйбрау» из витрины приложений, а
 * подпись на папке — чем этот лист является. Слова обычные, человеческие;
 * слов разработки здесь не бывает, как и везде в обычном интерфейсе.
 *
 * Размер 17px и не ниже, разрядка небольшая: разогнанные прописные буквы
 * человеку 60+ читать тяжело, и заглавных здесь поэтому нет.
 */
.kicker {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  font-size: var(--text-note);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

/* Тот же стежок, что под заголовком раздела. Ленты мотива здесь была и
   убрана: рядом с заголовком получались две разные засечки на два сантиметра
   текста — это шум, а не ритм (R11-021). */
.kicker::before {
  content: "";
  flex: none;
  width: 22px;
  height: 3px;
  border-radius: 2px;
  background: var(--thread);
  opacity: 0.8;
}

/* --- Указатель шага (R11.4) -------------------------------------------
 *
 * На длинном экране проверки подпись «Шаг 2 из 3» — это слова, а человеку
 * нужен ещё и вид: сколько пройдено и сколько осталось. Три отрезка вместо
 * ленты мотива, пройденные закрашены акцентом.
 *
 * Отрезки рисуются фоном, а не разметкой: экранный диктор читает подпись
 * словами, и дублировать её значками незачем. Смысл не держится на цвете —
 * рядом стоит «Шаг N из 3» прописью.
 */
.kicker--step::before {
  width: 46px;
  height: 4px;
  border-radius: 2px;
  opacity: 1;
  background-repeat: no-repeat;
  background-size: 12px 4px, 12px 4px, 12px 4px;
  background-position: 0 0, 17px 0, 34px 0;
}

.kicker--step[data-step="1"]::before {
  background-image:
    linear-gradient(var(--accent) 0 0),
    linear-gradient(var(--line-strong) 0 0),
    linear-gradient(var(--line-strong) 0 0);
}

.kicker--step[data-step="2"]::before {
  background-image:
    linear-gradient(var(--accent) 0 0),
    linear-gradient(var(--accent) 0 0),
    linear-gradient(var(--line-strong) 0 0);
}

.kicker--step[data-step="3"]::before {
  background-image:
    linear-gradient(var(--accent) 0 0),
    linear-gradient(var(--accent) 0 0),
    linear-gradient(var(--accent) 0 0);
}

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

a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- Кнопки --- */

/*
 * Кнопка.
 *
 * Обычная — тонкая линия и очень слабая заливка акцентом: до R11.2 рамка была
 * 2px, и кнопка на карточке выглядела ещё одним полем ввода.
 *
 * Ширина ограничена 30rem. Во всю ширину она по-прежнему на телефоне и внутри
 * карточки — там 30rem больше контейнера; на большом экране кнопка перестала
 * растягиваться на 976px, потому что кнопка длиной в строку текста не читается
 * как кнопка.
 *
 * Отклик на нажатие (R11.3). Кнопка уходит вниз на 1px и теряет часть тени.
 * Это единственное движение, которое человек замечает сознательно, и оно
 * нужно: на телефоне между нажатием и сменой экрана проходит заметное время,
 * и без отклика палец нажимает второй раз.
 */
.btn {
  display: block;
  width: 100%;
  max-width: 30rem;
  min-height: var(--tap-lg);
  padding: 15px 22px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.btn:hover { background: var(--card-raised); border-color: var(--accent-strong); color: var(--accent-strong); }
.btn:active { transform: translateY(1px); }

/* Главное действие: залито акцентом и слегка поднято. Красным основное
   действие не бывает никогда — красный значит точное совпадение (R11-005). */
.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-size: 21px;
  min-height: 64px;
  box-shadow: var(--shadow-raised);
}

.btn--primary:hover {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--accent-ink);
  box-shadow: var(--shadow-lift);
}

.btn--primary:active { transform: translateY(1px); box-shadow: var(--shadow); }

.btn + .btn { margin-top: 12px; }

.btn-list { margin: 28px 0 0; }

/* --- Полка действия под большим пальцем (R11.3) ------------------------
 *
 * Где это нужно. Проверка Telegram — длинный шаг: требование к программе,
 * предупреждение о задержке, объяснение. Кнопка «Начать» стоит в конце, и на
 * телефоне человек проходит до неё почти два экрана. Он читает, соглашается —
 * и не видит, чем дальше.
 *
 * Что сделано. Действие шага прилипает к нижнему краю экрана, пока идёт этот
 * шаг, и садится на своё место, когда шаг кончается. Палец держит телефон
 * снизу — действие оказывается там же.
 *
 * Почему без скрипта. `position: sticky` внутри своего шага: пока шаг виден,
 * полка внизу экрана; кончился шаг — полка ушла вместе с ним. Скрытый шаг
 * уносит и её, и показывать её на чужом шаге невозможно по построению.
 */
.thumb-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  /*
   * Поле над полкой — не отступ, а гарантия (R11.4).
   *
   * Когда шаг дочитан, полка садится на своё место в потоке, и это поле
   * становится зазором между последней строкой текста и кнопкой. Без него
   * последняя строка оставалась прижатой к полке и читалась подрезанной.
   */
  margin: var(--space-6) 0 0;
  padding: var(--space-3) 0 calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  /*
   * Полка непрозрачная. Затухание здесь было и убрано: полупрозрачная кромка
   * превращает строку под ней в половину строки, и владелец справедливо
   * прочитал это как перекрытый текст. Сплошная бумага с волосяной линией
   * читается как полка, а строка над линией остаётся целой.
   *
   * Цвет берётся из токена, поэтому полка не привязана к светлой теме.
   */
  background: var(--paper);
  box-shadow: 0 -1px 0 var(--line), 0 -10px 20px -14px rgba(60, 50, 35, 0.35);
}

.thumb-bar .btn { margin: 0; }

/*
 * Низкий экран — полка не прилипает.
 *
 * Это случай крупного шрифта и увеличенного масштаба страницы: при 200%
 * экран телефона по высоте становится как половина прежнего, и 80 пикселей
 * прилипшей полки забирают у чтения слишком много. Тогда кнопка просто
 * стоит в конце шага.
 */
@media (max-height: 30rem) {
  .thumb-bar {
    position: static;
    background: none;
    box-shadow: none;
    padding-bottom: 0;
  }
}

/* --- Поиск --- */

.search-form { margin: 8px 0 24px; }

.search-form label {
  display: block;
  font-weight: 600;
  margin-bottom: 8px;
}

/* Поле ввода — единственное, у чего рамка осталась заметной и тёмной: поле
   обязано выглядеть полем. Именно поэтому её убрали у карточек: пока рамка
   была у всех, поле ничем не отличалось от сообщения. */
.search-form input {
  width: 100%;
  max-width: 30rem;
  min-height: var(--tap-lg);
  padding: 14px 16px;
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card-raised);
  color: var(--ink);
  font: inherit;
}

.search-form input { transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.search-form input:focus { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.search-form .btn { margin-top: 12px; }

.hint { color: var(--ink-soft); font-size: 17px; margin-top: 8px; }

/* --- Результат --- */

/* Вердикт — единственное место, где рамка остаётся толстой: здесь она несёт
   смысл, а не оформление. Цвет рамки и есть вывод проверки. */
.verdict {
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: var(--space-5) 0;
  background: var(--card);
  box-shadow: var(--shadow-soft);
  max-width: var(--measure);
  /* Вывод проверки обязан быть замечен: он проступает, а не подменяет собой
     страницу молча. Движение короткое и однократное (R11.3). */
  animation: settle var(--dur-slow) var(--ease-out);
}

.verdict__title { font-size: var(--text-h3); font-weight: 700; margin: 0 0 10px; }
.verdict__text { margin: 0; }
.verdict__text + .verdict__text { margin-top: 14px; }

.verdict--red { border-color: var(--red); background: var(--red-bg); }
.verdict--red .verdict__title { color: var(--red); }
.verdict--orange { border-color: var(--orange); background: var(--orange-bg); }
.verdict--orange .verdict__title { color: var(--orange); }
.verdict--white { border-color: var(--line); background: var(--neutral-bg); }
.verdict--white .verdict__title { color: var(--neutral); }

.record {
  border: 0;
  border-left: var(--edge-strong) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card);
  box-shadow: var(--shadow-soft);
  padding: 18px 20px;
  margin: 0 0 16px;
  max-width: var(--measure);
}

.record--official { border-left-color: var(--red); }
.record--attention { border-left-color: var(--orange); }

.record__title { font-size: 21px; font-weight: 700; margin: 0 0 6px; }
.record__status { font-weight: 600; margin: 0 0 12px; }
.record--official .record__status { color: var(--red); }
.record--attention .record__status { color: var(--orange); }

/*
 * Строка «подпись — значение».
 *
 * Значение переносится, даже если точек переноса в нём нет. Версия набора
 * вроде `2026-09-15-40960db30571` — это один токен без пробелов: без явного
 * разрешения переноса он растягивал страницу, и на телефоне панель владельца
 * была шире экрана на 402px. Тот же приём, что у технических строк ниже:
 * переносим, а не прокручиваем, и `overflow-x: hidden` для этого не
 * используем — спрятанный дефект вёрстки остаётся дефектом.
 *
 * `min-width: 0` обязателен обоим: без него элемент гибкой строки отказывается
 * сжиматься ниже своего содержимого, и перенос не срабатывает.
 */
.record__facts { margin: 0; }
.record__facts div { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0; border-top: 1px solid var(--line); }
.record__facts dt { font-weight: 600; min-width: min(11rem, 100%); margin: 0; }

.record__facts dd {
  margin: 0;
  color: var(--ink-soft);
  min-width: 0;
  overflow-wrap: anywhere;
}

.record__note { margin: 14px 0 0; color: var(--ink-soft); font-size: 17px; }

/* Осторожная подсказка: совпал текст, а не адрес, либо разбор неуверенный. */
.record__caution {
  margin: 0 0 12px;
  padding: 10px 14px;
  border-left: var(--edge) solid var(--orange);
  background: var(--orange-bg);
  font-size: var(--text-note);
}

.record__subtitle { font-size: 17px; font-weight: 600; margin: 16px 0 6px; }

/* Дословный текст первичного источника. Показывается как цитата, а не как
   наша формулировка: человек должен видеть разницу. */
.record__official {
  margin: 0;
  padding: 10px 14px;
  border-left: var(--edge) solid var(--line);
  background: var(--card-soft, rgba(0, 0, 0, 0.03));
  color: var(--ink);
  font-size: 17px;
  white-space: pre-line;
}

/* --- Предупреждения --- */

/*
 * Предупреждение. Оранжевое — и поэтому его нельзя ставить под обычную
 * справку: оранжевый в продукте значит «нужно уточнить», и если им окрашено
 * рядовое сообщение, он перестаёт значить это (R11-005).
 *
 * Спокойное напоминание живёт отдельно — см. `.reminder` ниже.
 */
.notice {
  border: 0;
  border-left: var(--edge) solid var(--orange);
  background: var(--orange-bg);
  color: var(--ink);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-5);
  max-width: var(--measure);
}

.notice strong { color: var(--orange); }

/* Сведения о живой базе — не предупреждение, а справка: кромка нитью. */
.notice--data {
  border-left-color: var(--thread);
  background: var(--card);
}

/*
 * Спокойное напоминание (R11.2).
 *
 * «Начните заранее» — это справка о времени, а не риск и не требование
 * уточнения. Оранжевым оно было раньше, и оранжевый на обычном сообщении
 * обесценивает оранжевый на результате проверки. Поэтому здесь нейтральная
 * поверхность и линия акцентом: заметно, но не тревожно.
 */
.reminder {
  border: 0;
  border-left: var(--edge) solid var(--thread);
  background: var(--card);
  color: var(--ink);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-5);
  box-shadow: var(--shadow);
  max-width: var(--measure);
}

.reminder p { margin: 0; }
.reminder strong { color: var(--ink); font-weight: 650; }

.notice--data .record__facts div:first-child { border-top: 0; }

.disclaimer {
  border-top: 1px solid var(--line);
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  color: var(--ink-soft);
  font-size: var(--text-note);
  max-width: var(--measure);
}

/* --- Заглушки будущих разделов --- */

/* Заглушка будущего раздела. Пунктира больше нет: пунктирная рамка читается
   как незавершённый черновик разработчика, а раздел не черновик — его просто
   пока нет. Отличие держится на утопленной поверхности и на словах. */
.stub {
  border: 0;
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: var(--space-5);
  background: var(--card-sunken);
  max-width: var(--measure);
}

.stub__label {
  display: inline-block;
  font-weight: 700;
  color: var(--ink-soft);
  margin-bottom: 8px;
}

/* --- Печать (Emergency и Family Plan должны печататься) --- */

@media print {
  body { background: #fff; color: #000; font-size: 12pt; }
  .site-head, .site-foot, .btn, .no-print { display: none !important; }
  .wrap { max-width: none; padding: 0; }
  a { color: #000; text-decoration: underline; }
}

/* ======================================================================
   Компоненты v0.2
   ====================================================================== */

/* --- Главный экран --- */

.hero { padding: 8px 0 4px; }
.hero h1 { font-size: 34px; margin-bottom: 12px; }
.hero__sub { font-size: 21px; color: var(--ink-soft); margin-bottom: 28px; }

/* --- Карточки сценариев --- */

.cards { display: grid; gap: 14px; margin: 24px 0; }

.card {
  display: block;
  border: 0;
  border-left: var(--edge) solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card-raised);
  box-shadow: var(--shadow-soft);
  padding: var(--space-5);
  text-decoration: none;
  color: inherit;
  transition:
    border-color var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

.card:hover, .card:focus-visible {
  border-left-color: var(--accent-strong);
  background: var(--card-raised);
  box-shadow: var(--shadow-lift);
  transform: translateY(-1px);
}

.card:active { transform: translateY(1px); box-shadow: var(--shadow); }
.card__title { font-size: 22px; font-weight: 650; color: var(--accent); margin: 0 0 8px; }
.card__text { margin: 0; color: var(--ink-soft); }

/* --- Шаги --- */

.steps { counter-reset: step; list-style: none; padding: 0; margin: 24px 0; }

.steps > li {
  counter-increment: step;
  border-left: var(--edge) solid var(--line);
  padding: 0 0 var(--space-5) var(--space-5);
  margin: 0;
  position: relative;
}

.steps > li::before {
  content: counter(step);
  position: absolute;
  left: -16px;
  top: 0;
  width: 29px;
  height: 29px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 16px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 4px var(--paper);
}

.steps > li:last-child { border-left-color: transparent; padding-bottom: 0; }
.steps__title { font-weight: 700; display: block; margin-bottom: 4px; }

/* --- Формы --- */

.field { margin: 0 0 18px; }
.field label { display: block; font-weight: 600; margin-bottom: 6px; }

.field input, .field textarea {
  width: 100%;
  max-width: 30rem;
  min-height: 56px;
  padding: 12px 14px;
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card-raised);
  color: var(--ink);
  font: inherit;
}

.field textarea { min-height: 110px; resize: vertical; }
.field input, .field textarea { transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.field input:focus, .field textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }

/*
 * Ряд кнопок, которые появляются только после проверки (R11.4).
 *
 * «Сохранить результаты» и «Очистить проверку» до первой проверки скрыты, но
 * сам ряд оставался в потоке со своими отступами: 48 пикселей пустоты
 * посреди страницы, за которыми ничего нет. Ровно такую дыру владелец и
 * назвал пустой областью.
 *
 * Отступ теперь принадлежит не ряду, а случаю «в ряду есть видимая кнопка».
 * Там, где `:has` не поддерживается, ряд просто прижимается к тексту выше:
 * тесно — это не дефект, дыра — дефект.
 */
.btn-row { display: grid; gap: var(--space-3); margin: 0; }
.btn-row:has(> .btn:not([hidden])) { margin: var(--space-5) 0; }
.btn--quiet { border-color: var(--line); color: var(--ink); }

/* --- Таблицы --- */

.table-wrap { overflow-x: auto; margin: 20px 0; }

table { border-collapse: collapse; width: 100%; font-size: 17px; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-weight: 700; }
tbody tr:nth-child(odd) { background: var(--neutral-bg); }

/* --- Метки состояния --- */

/* Метка состояния в таблицах. Не мельче 16px: на телефоне 15px в кружке
   превращается в неразборчивую пилюлю. */
.tag {
  display: inline-block;
  font-size: var(--text-note);
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--neutral-bg);
  color: var(--ink-soft);
  white-space: nowrap;
}

.tag--ok { border-color: var(--accent); color: var(--accent); background: transparent; }
.tag--warn { border-color: var(--orange); color: var(--orange); background: var(--orange-bg); }

/* Красной метки здесь нет намеренно. `.tag--blocked` существовала, но ею никто
   не пользовался: единственный красный в продукте живёт в карточке результата,
   где он означает точное совпадение с записью перечня. Неиспользуемое красное
   правило — это заготовка, из которой красный однажды расползётся по таблицам
   как оформление (R11-005). */

/* --- График --- */

.chart { margin: 20px 0; }
.chart svg { width: 100%; height: 180px; display: block; }
.chart__legend { font-size: 16px; color: var(--ink-soft); margin-top: 8px; }

/* --- Панель периодов --- */

.periods { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0; }

.periods button {
  min-height: 48px;
  padding: 10px 16px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.periods button[aria-pressed='true'] { border-color: var(--accent); color: var(--accent); }

/* --- Показатели --- */

/*
 * Плитки показателей.
 *
 * `minmax(150px, …)` без `min()` держит колонку шириной 150px даже тогда, когда
 * всему контейнеру 312px: на экране 360px две такие колонки не помещаются, а
 * длинное значение внутри («15 сентября 2026 г.» крупным шрифтом) не переносится
 * и выпирает наружу. Страница /sources/ оказывалась шире экрана на 95px, и
 * заметил бы это человек на телефоне, а не мы.
 *
 * Поэтому три правила вместе: колонка не шире контейнера, элемент сетки имеет
 * право сжаться (`min-width: 0`), а значение переносится, даже если точек
 * переноса в нём нет. Прятать это через `overflow-x: hidden` нельзя: дефект
 * вёрстки остался бы дефектом, просто невидимым.
 */
.metrics {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  margin: var(--space-5) 0;
}

.metric {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow);
  padding: var(--space-4);
  min-width: 0;
}

.metric__value {
  font-size: 30px;
  font-weight: 700;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
/*
 * Подпись показателя переносится по тем же причинам, что и значение над ней.
 * Значению перенос разрешили ещё в R3.3, а подписи — нет, и одно длинное слово
 * («идентификаторов», «демонстрационные») растягивало плитку: на экране 360px
 * панель владельца оказывалась шире экрана на 9px. Дефект прожил незамеченным,
 * потому что браузерная проверка обходила только страницы продукта; теперь она
 * обходит и служебные (R11.2).
 */
.metric__label {
  color: var(--ink-soft);
  font-size: 16px;
  margin-top: 4px;
  overflow-wrap: anywhere;
}

/* --- Адрес объекта: текст, а не ссылка (v0.2 §20) --- */

.address {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 16px;
  word-break: break-all;
  background: var(--neutral-bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 10px;
  display: inline-block;
}

/* --- Технический текст: имена полей, пути, схема (R3.3) --- */

/*
 * Длинная техническая строка вроде
 * `relationships_following[].string_list_data[].href: string` — это один
 * токен без пробелов. Обычный <pre> такую строку не переносит и растягивает
 * страницу: на телефоне владелец увидел горизонтальную прокрутку и решил,
 * что страница сломана.
 *
 * Поэтому переносим, а не прокручиваем. `anywhere` нужен именно потому, что
 * точек переноса в такой строке нет вовсе: без него не помогает ни один
 * другой перенос.
 */
.code-block {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
  line-height: 1.5;
  margin: 12px 0;
  padding: 10px 12px;
  background: var(--neutral-bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ink-soft);

  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;   /* для браузеров постарше */
  max-width: 100%;
  box-sizing: border-box;
}

/*
 * Сырой отчёт по умолчанию свёрнут: это служебный текст, а не содержание
 * страницы. Разворачивается — остаётся внутри своей рамки и по-прежнему не
 * растягивает страницу.
 */
.raw-report > summary {
  cursor: pointer;
  font-weight: 600;
}

.raw-report .code-block {
  max-height: 60vh;
  overflow-y: auto;
}

/* --- Спокойный информационный блок --- */

.info {
  border-left: var(--edge) solid var(--thread);
  background: var(--card);
  padding: var(--space-4) var(--space-5);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin: var(--space-5) 0;
  max-width: var(--measure);
}

.info p:last-child { margin-bottom: 0; }

@media (min-width: 40rem) {
  .cards { grid-template-columns: 1fr 1fr; }
  .btn-row { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
}

/* Скрытый элемент скрыт всегда. Без этого правила класс .btn с собственным
   display побеждал бы hidden, и кнопки «Сохранить результаты» и «Очистить
   проверку» были бы видны до первой проверки. */
[hidden] {
  display: none !important;
}

/* Область выбора файла выгрузки Telegram. Перетаскивание — дополнение к
   обычной кнопке выбора файла, а не замена ей: клавиатура и экранный диктор
   работают через input. */
/*
 * Область выбора файла.
 *
 * Пунктир здесь остаётся — и это единственное место, где он допустим: он
 * означает «сюда можно положить», а не «здесь что-то сломано». В карточках
 * платформ пунктира нет именно поэтому.
 */
.drop-zone {
  border: 2px dashed var(--line-strong);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: var(--card);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.drop-zone--over {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-soft);
}

/* Панель уточнения кандидата: этап 2 массовой проверки Telegram. */
.confirm {
  margin: var(--gap) 0;
  padding: var(--gap);
  background: var(--neutral-bg);
  border-radius: var(--radius);
}

.confirm__steps {
  margin: 0 0 var(--gap);
  padding-left: 1.2em;
}

.confirm__steps li {
  margin-bottom: 0.4em;
}

/* Свёрнутое объяснение. Открывается только тем, кто захотел подробностей. */
/* Свёрнутое объяснение. Рамки нет — есть линия сверху: обведённый рамкой
   «details» выглядел ещё одной карточкой, хотя это всего лишь строка, которую
   можно открыть. */
.explain {
  margin: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  padding: 0;
  max-width: var(--measure);
}

.explain:last-of-type { border-bottom: 1px solid var(--line); }

/* Заголовок свёрнутого раздела — строка под палец, а не строчка текста.
   Своя стрелка вместо стрелки движка: та рисуется по-разному и в трёх
   браузерах из пяти оказывается в другом месте. */
.explain > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 19px;
  color: var(--accent);
  min-height: var(--tap-lg);
  transition: color var(--dur-fast) var(--ease);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  padding: var(--space-2) 0;
}

.explain > summary::-webkit-details-marker { display: none; }
.explain > summary::marker { content: ""; }

.explain > summary::after {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.explain[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.explain > summary:hover { color: var(--accent-strong); }

/*
 * Раскрытие (R11.3).
 *
 * Содержимое выезжает сверху, а не возникает из ниоткуда: человек должен
 * видеть, что текст пришёл из строки, которую он нажал, — иначе на телефоне
 * страница просто прыгает под пальцем.
 *
 * Движение живёт на содержимом, а не на самом <details>: анимировать высоту
 * элемента, который только что перестал быть нулевым, браузеры умеют
 * по-разному, и на части из них это давало рывок.
 */
.explain__body {
  padding: 0 0 var(--space-4);
}

/*
 * Движение только у РАСКРЫТОГО раздела.
 *
 * Без `[open]` анимация запускалась и у свёрнутого — то есть на каждой
 * загрузке страницы, и первые кадры текст внутри был прозрачным. Поймала
 * это браузерная проверка «содержание невидимо сразу после разметки», и
 * поймала правильно: человек этот текст не видит, но он на странице есть.
 */
.explain[open] > .explain__body {
  animation: unfold var(--dur-slow) var(--ease-out);
}

@keyframes unfold {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

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

/* Предупреждение об устаревшей базе. Заметное намеренно: человек должен
   увидеть его ДО того, как истолкует результат проверки. */
.notice--stale {
  border-left: var(--edge-strong) solid var(--orange);
  background: var(--orange-bg);
  color: var(--orange);
}

.notice--stale strong {
  display: block;
  margin-bottom: 0.3em;
}

/* Требование, без которого дальше идти незачем.
   Живой тест показал: человек открывает Telegram Web, ищет там выгрузку и
   упирается в тупик. Значит, сказать об этом нужно ДО инструкции и заметно,
   а не строчкой внутри неё (R2-017). */
/* Требование: условие, которое надо прочитать до действия. Кромка акцентом
   тонкая — это не само действие. */
.requirement {
  border: 0;
  border-left: var(--edge) solid var(--accent);
  background: var(--card);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: var(--space-5) 0;
  box-shadow: var(--shadow-soft);
  max-width: var(--measure);
}

.requirement__title { font-size: var(--text-h3); font-weight: 650; margin: 0 0 var(--space-3); }

/* Подходит / не подходит. Различие держится на цвете полосы И на слове:
   по одному цвету разницу увидит не каждый. */
.fit { list-style: none; padding: 0; margin: 0 0 16px; }

.fit li {
  border-left: var(--edge) solid var(--line);
  padding: var(--space-2) 0 var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
}

/* Вес селектора не ниже, чем у «.fit li» выше, иначе цвет полосы не сменится. */
.fit .fit--no { border-left-color: var(--red); }
.fit .fit--no strong { color: var(--red); }
.fit .fit--yes { border-left-color: var(--accent); }
.fit .fit--yes strong { color: var(--accent); }

/* ======================================================================
   КОМПОНЕНТЫ R11 — переработаны в R11.3
   ====================================================================== */

/* --- Первый экран главной ---------------------------------------------
 *
 * Отвечает на три вопроса и ни на один больше: что это, что я могу сделать и
 * с чего начать. Манифест приватности, методика источников и юридическая
 * оговорка живут ниже — человек 60+ обязан понять первый экран за секунды, а
 * не прочитать полстраницы, прежде чем найти кнопку.
 *
 * Что изменилось в R11.3. Заголовок стал по-настоящему крупным и подвижным по
 * ширине окна, обещание получило собственную кромку нити слева, а фон первого
 * экрана — очень слабую ленту мотива сверху. Первый экран — единственное
 * место, где мотив работает не разделителем, а воздухом: дальше по странице
 * он снова только отделяет часть от части.
 */

.opening { position: relative; padding: var(--space-2) 0 0; }

.opening h1 {
  font-size: var(--text-display);
  line-height: 1.08;
  letter-spacing: -0.028em;
  margin: 0 0 var(--space-4);
}

/* Главная мысль сервиса. Крупная и спокойная: это обещание, а не кнопка,
   поэтому цвет чернильный, а не акцентный — акцентом окрашено то, что
   нажимается. Кромка нити слева отличает обещание от обычного абзаца, не
   делая его ни предупреждением, ни выводом. */
.opening__claim {
  display: block;
  font-size: var(--text-lead);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  margin: 0 0 var(--space-4);
  padding-left: var(--space-4);
  border-left: var(--edge) solid var(--thread);
  max-width: var(--measure);
}

.opening__sub {
  font-size: 19px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 var(--space-6);
  max-width: 34rem;
}

/* --- Список действий --------------------------------------------------
 *
 * Действия, а не разделы, и не четыре равных прямоугольника.
 *
 * До R11.2 их было четыре одинаковых по весу, и глазу было не за что
 * зацепиться: человек читал все четыре, чтобы выбрать один. Вес разный и
 * задан тремя ступенями:
 *
 *   главное     — залито акцентом, крупнее, с тенью: за этим приходят;
 *   спокойное   — поверхность карточки, кромка нити слева: нужно реже;
 *   экстренное  — строка с линией сбоку, не карточка: нужно редко и не должно
 *                 пугать того, у кого ещё ничего не случилось.
 *
 * R11.3 добавил к ним стрелку и отклик. Стрелка — не украшение: до неё
 * спокойное действие выглядело сообщением в рамке, и владелец на живом
 * просмотре не понял, что по нему надо нажать.
 */

.actions { display: grid; gap: var(--space-3); margin: 0 0 var(--space-6); }

/*
 * Спокойное действие. Рамки по кругу нет: её работу делают поднятая
 * поверхность и кромка. Это и есть «глубина вместо украшения» — до R11.4
 * четыре действия были четырьмя обведёнными прямоугольниками.
 */
.action {
  position: relative;
  display: block;
  border: 0;
  border-left: var(--edge) solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card-raised);
  padding: var(--space-4) 44px var(--space-4) var(--space-5);
  min-height: 84px;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-soft);
  transition:
    border-color var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

/* Стрелка — признак «сюда можно нажать». Рисуется фоном, не текстом:
   экранный диктор её не читает, а человек видит. */
/*
 * Место под стрелку выделено отступом, а не «на глаз»: до R11.3 стрелка
 * стояла на 24px от края при отступе текста 32px, и на телефоне подпись
 * «связь с близкими» заезжала прямо под неё.
 */
.action::after {
  content: "";
  position: absolute;
  right: var(--space-4);
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -6px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
  transition: transform var(--dur) var(--ease);
}

.action:hover, .action:focus-visible {
  border-left-color: var(--accent-strong);
  background: var(--card-raised);
  box-shadow: var(--shadow-lift);
  transform: translateY(-1px);
}

.action:hover::after, .action:focus-visible::after { transform: rotate(-45deg) translate(3px, 3px); }
.action:active { transform: translateY(1px); box-shadow: var(--shadow); }

.action__title {
  display: block;
  font-size: 21px;
  line-height: 1.25;
  font-weight: 650;
  color: var(--accent);
  margin-bottom: var(--space-1);
}

.action__text { display: block; color: var(--ink-soft); font-size: var(--text-small); line-height: 1.45; }

/* Главное действие. Заливка — акцентом, не красным: основная кнопка красной
   не бывает никогда (R11-005). Лента мотива внутри заливки — та же кромка
   полотна, что в шапке: это место, где продукт называет себя. */
.action--main {
  border-left-color: var(--accent-strong);
  border-radius: var(--radius);
  background: var(--accent);
  box-shadow: var(--shadow-raised);
  min-height: 116px;
  padding: var(--space-5) 56px var(--space-5) var(--space-5);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.action--main .action__title { color: var(--accent-ink); font-size: clamp(23px, 20px + 0.9vw, 28px); font-weight: 700; }
.action--main .action__text { color: var(--accent-ink); opacity: 0.92; font-size: 19px; }
.action--main::after { border-color: var(--accent-ink); right: var(--space-5); }

.action--main:hover, .action--main:focus-visible {
  background: var(--accent-strong);
}

/* Экстренное действие. Это строка с линией сбоку, а не карточка: раздел нужен
   редко, и делать из него четвёртый равный прямоугольник — значит каждый день
   напоминать о беде тому, у кого ничего не случилось. Оранжевым он тоже не
   окрашен: оранжевый значит «нужно уточнить» в результате проверки. */
/* Экстренное действие. Кромки акцентом у него нет намеренно: это не то, чем
   пользуются сегодня, и выглядеть равным сегодняшнему действию оно не должно.
   Раздел нужен редко, и делать из него четвёртый равный прямоугольник значит
   каждый день напоминать о беде тому, у кого ничего не случилось. */
.action--urgent {
  border: 0;
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  min-height: 0;
  padding: var(--space-2) 40px var(--space-2) var(--space-4);
}

.action--urgent { max-width: var(--measure); }
.action--urgent .action__title { font-size: 19px; color: var(--accent); }
.action--urgent .action__text { font-size: var(--text-note); }
.action--urgent::after { right: var(--space-2); }

.action--urgent:hover, .action--urgent:focus-visible {
  background: transparent;
  box-shadow: none;
  transform: none;
  border-left-color: var(--accent);
}

/* --- Полоса о данных --------------------------------------------------
 *
 * Четыре коротких обещания вместо манифеста, и не четыре карточки: карточками
 * это была бы ещё одна сетка прямоугольников, которую человек прочитает как
 * четыре действия.
 *
 * Каждое обещание относится к тому, что в продукте действительно сделано:
 * обещать сверх реализованного нельзя. Подробности и честные оговорки — на
 * странице о проекте, и ссылка туда стоит здесь же.
 *
 * Полосу сверху держит лента мотива: это и разделитель первого экрана, и то
 * место, где у продукта появляется характер.
 */

/*
 * Условия, на которых работает проверка (R11.4).
 *
 * Раньше здесь была лента мотива и под ней список. Это была третья полоса
 * орнамента на одном экране — узор начинал работать обоями, а не смыслом.
 *
 * Теперь это утопленная вставка с кромкой нити, пришитая прямо под
 * действиями: не отдельный раздел, а условия того предложения, которое
 * стоит выше. Отличается она от остального не полосой, а ГРУНТОМ — и
 * ровно поэтому ритм страницы перестал быть однородным.
 */
.trust {
  position: relative;
  margin: 0 0 var(--space-6);
  padding: var(--space-5);
  background: var(--card-sunken);
  /* Полоса о данных — короткие обещания в столбик, а не текст для чтения.
     Третья и последняя поверхность с фактурой на весь продукт. */
  background-image: var(--linen);
  background-repeat: repeat;
  background-size: var(--linen-size) var(--linen-size);
  border-left: var(--edge) solid var(--thread);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.trust__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3) var(--space-5);
}

.trust__list li {
  position: relative;
  padding-left: 30px;
  margin: 0;
  font-size: var(--text-small);
  line-height: 1.4;
  font-weight: 500;
}

/* Значок — не галочка «всё хорошо», а узелок нити: вывода «безопасно» сервис
   не делает нигде, и оформление не имеет права намекать на него. */
.trust__list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 8px;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--accent);
  transform: rotate(45deg);
}

.trust__note { margin: var(--space-2) 0 0; font-size: var(--text-note); color: var(--ink-soft); }

/* --- Карточка платформы в хабе подписок -------------------------------
 *
 * Вопрос человека — «что мне делать с Telegram?», а не «в каком состоянии этот
 * сервис». Поэтому карточка построена как ответ: название, одна фраза о том,
 * что будет, и одно действие.
 *
 * Пять карточек не равны между собой намеренно. Человек, увидевший пять
 * одинаковых карточек, разумно решит, что и проверок пять. Различие держится
 * на трёх признаках, и ни один из них не цвет:
 *
 *   СЛОВА     — состояние названо прямо, «Проверка работает» против
 *               «Проверка готовится»;
 *   ГЛУБИНА   — готовая карточка приподнята тенью, неготовая лежит плоско на
 *               утопленной поверхности;
 *   ДЕЙСТВИЕ  — у готовой кнопка залита, у неготовой обведена.
 *
 * Пунктирной рамки здесь нет. Пунктир читается как незаконченный черновик
 * разработчика или как ошибка — а неготовая проверка не ошибка, её просто
 * пока нет, и сказано об этом словами.
 *
 * R11.3 добавил четвёртый признак того же рода — кромку: у готовой карточки
 * она акцентная и толстая, у неготовой её нет вовсе. Цветом это различие не
 * является: у неготовой карточки нет кромки, а не «другая».
 */

.platforms { display: grid; gap: var(--space-4); margin: 0 0 var(--space-6); }

.platform {
  border: 0;
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* Готовая проверка: поднятый белый лист и кромка акцентом. Это действие. */
.platform--ready {
  background: var(--card-raised);
  border-left: var(--edge-strong) solid var(--accent);
  box-shadow: var(--shadow-soft);
}

.platform--ready:hover { box-shadow: var(--shadow-lift); transform: translateY(-1px); }

/* Есть часть пути. */
.platform--partial {
  background: var(--card);
  border-left: var(--edge-strong) solid var(--thread);
  box-shadow: var(--shadow);
}

/*
 * Проверки здесь пока нет.
 *
 * Это ЗАПИСЬ О СЕРВИСЕ, а не выключенный модуль программы. Разница видна
 * по трём вещам, и ни одна из них не цвет: утопленный грунт вместо
 * поднятого листа, отсутствие кромки вместо кромки акцентом, отсутствие
 * тени вместо тени. Текст при этом полноцветный и читаемый — гасить его
 * нельзя: человеку нужно прочитать, что можно сделать сегодня.
 */
.platform--pending {
  background: var(--card-sunken);
  border-left-color: transparent;
  box-shadow: none;
}

.platform__head { display: flex; flex-direction: column; gap: var(--space-2); }

.platform__name { font-size: var(--text-h3); font-weight: 650; margin: 0; color: var(--ink); }

/* Состояние стоит ПЕРЕД названием в порядке чтения и заметно раньше него:
   иначе список читается как список готовых проверок (тот же урок, что в
   R2.6 с кандидатами Telegram). */
.platform__state {
  order: -1;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-note);
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--neutral-bg);
  color: var(--ink-soft);
}

/* Точка перед словом повторяет состояние формой, а не только цветом: у
   готовой она залита, у неготовой — пустая окружность. */
.platform__state::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2px solid currentColor;
  background: currentColor;
}

/* Цвет состояния — спокойный. Красного среди состояний нет: красный значит
   точное совпадение в перечне и больше ничего (R11-005). */
.platform__state--ready { border-color: var(--ready); color: var(--ready); background: var(--ready-bg); }
.platform__state--partial { border-color: var(--orange); color: var(--orange); background: var(--orange-bg); }
.platform__state--pending { border-color: var(--line-strong); color: var(--pending); background: transparent; }
.platform__state--pending::before { background: transparent; }

.platform__what { margin: 0; font-size: 19px; line-height: 1.5; }

.platform__note {
  margin: 0;
  padding: 0 0 0 var(--space-4);
  border-left: var(--edge) solid var(--line-strong);
  background: transparent;
  border-radius: 0;
  font-size: var(--text-note);
  line-height: 1.45;
  color: var(--ink-soft);
}

.platform__action { margin: var(--space-1) 0 0; margin-top: auto; padding-top: var(--space-2); }
.platform__action .btn { margin: 0; min-height: 56px; font-size: 19px; }

/* Группа карточек с заголовком: «можно сейчас» и «ещё готовим» — разные вещи,
   и человек обязан увидеть это до того, как начнёт читать карточки. */
/* Заголовок группы отменяет отступ <h2> сверху, поэтому воздух над группой
   задан самой группе: без этого «Можно проверить сейчас» прилипало к строке
   «Выберите сервис» и читалось её продолжением. */
.platform-group { margin: var(--space-7) 0; }
.platform-group:last-of-type { margin-bottom: var(--space-6); }
.platform-group__title { font-size: var(--text-h2); font-weight: 650; margin: 0 0 var(--space-3); max-width: var(--measure); }
.platform-group__note { margin: 0 0 var(--space-4); color: var(--ink-soft); font-size: var(--text-small); max-width: var(--measure); }
.platform-group .platforms { margin-bottom: 0; }

/*
 * Группа «ещё готовим» читается как одна справка, а не как три отключённых
 * модуля: общий утопленный грунт, записи внутри разделены волосяной линией.
 * На телефоне это особенно важно — три одинаковые плитки подряд человек
 * читает как три одинаковые проверки.
 */
.platform-group--quiet .platforms {
  background: var(--card-sunken);
  border-radius: var(--radius);
  gap: 0;
}

.platform-group--quiet .platform { background: transparent; }
.platform-group--quiet .platform + .platform { border-top: 1px solid var(--line); }

/* --- Будущие области проверки (R11-027) ---------------------------------
 *
 * Символика, музыка, книги. Кода за ними нет вовсе, и карточка обязана
 * читаться как ЗАПИСЬ О ЗАМЫСЛЕ, а не как ещё одна проверка рядом с
 * работающими.
 *
 * Отличие от карточки платформы держится на том же, на чём там держится
 * отличие готового от неготового, и ни один признак не цвет:
 *   - утопленный грунт вместо поднятого листа;
 *   - нет кромки акцентом и нет тени;
 *   - кнопка обведена, а не залита, и ведёт она не в эту проверку, а в ту,
 *     что работает уже сегодня.
 *
 * Пунктира здесь нет и не будет: он читается как поломка, а замысел —
 * не поломка (R11-012).
 *
 * Текст при этом полноцветный: гасить его нельзя, потому что главное в
 * карточке — прочитать, чего мы обещать не будем.
 */
.areas { display: grid; gap: var(--space-4); margin: 0 0 var(--space-6); }

.area {
  border: 0;
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card-sunken);
  box-shadow: none;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.area__head { display: flex; flex-direction: column; gap: var(--space-2); }

.area__name { font-size: var(--text-h3); font-weight: 650; margin: 0; color: var(--ink); }

/* Состояние стоит ПЕРЕД названием в порядке чтения — по той же причине, что
   и у платформы: иначе три карточки читаются как три готовые проверки. */
.area__state {
  order: -1;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* Подпись не мельче мелкого текста продукта: «крошечная плашка состояния»
     — ровно та ошибка, из-за которой человек её не читает. */
  font-size: var(--text-note);
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--pending);
}

/* Пустая окружность повторяет состояние формой, а не только цветом. */
.area__state::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2px solid currentColor;
  background: transparent;
}

.area__what { margin: 0; font-size: 19px; line-height: 1.5; max-width: var(--measure); }

.area__part { display: flex; flex-direction: column; gap: var(--space-2); }

.area__label {
  margin: 0;
  font-size: var(--text-note);
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

.area__list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }

.area__list li {
  position: relative;
  padding-left: var(--space-5);
  font-size: var(--text-small);
  line-height: 1.45;
  max-width: var(--measure);
}

/* Знак перед строкой — нить, а не галочка: галочка читается как «сделано». */
.area__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 12px;
  height: 2px;
  background: var(--thread);
}

/* Строка отказа. Она важнее списка замысла, и поэтому её знак — не нить, а
   прочерк во всю толщину: «этого не будет». Красным он не бывает: отказ — не
   результат проверки. */
.area__list--no li::before { background: var(--line-strong); height: 3px; }

.area__today {
  margin: 0;
  padding: 0 0 0 var(--space-4);
  border-left: var(--edge) solid var(--line-strong);
  font-size: var(--text-note);
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: var(--measure);
}

.area__today strong { color: var(--ink); }

.area__action { margin: var(--space-1) 0 0; margin-top: auto; padding-top: var(--space-2); }
.area__action .btn { margin: 0; min-height: 56px; font-size: 19px; }

/* --- Свежесть сведений ------------------------------------------------
 *
 * Три разные даты, которые нельзя смешивать: когда человек проверил, когда
 * собран наш набор и когда мы последний раз видели первичный источник.
 * Третьей сейчас нет — и блок обязан уметь сказать «мы не знаем». Зелёного
 * «всё свежо» при неизвестной свежести не бывает.
 */

.freshness {
  border: 0;
  border-left: var(--edge) solid var(--thread);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
  font-size: var(--text-note);
  max-width: var(--measure);
}

.freshness__row { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); padding: var(--space-1) 0; }
.freshness__label { color: var(--ink-soft); }
.freshness__value { font-weight: 600; }

/* Неизвестно — значит неизвестно. Не зелёное и не тревожное. */
.freshness__value--unknown { font-weight: 600; color: var(--pending); }

/* --- Состояние без данных и отказ ------------------------------------
 *
 * Отказ не прячется и не маскируется успокаивающим зелёным.
 */

.state-msg {
  border: 0;
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--card-sunken);
  padding: var(--space-4) var(--space-5);
  margin: var(--space-4) 0;
  max-width: var(--measure);
  animation: settle var(--dur-slow) var(--ease-out);
}

.state-msg__title { font-size: 20px; font-weight: 650; margin: 0 0 var(--space-2); }

/* Главная строка ответа формы: «данные никуда не отправлены». Она обязана
   читаться сразу после заголовка сообщения, а не теряться в абзаце под ним
   (R13.1 §8). */
.state-msg__strong { font-weight: 650; margin: 0 0 var(--space-2); }
.state-msg p:last-child { margin-bottom: 0; }

.state-msg--offline { border-color: var(--line-strong); }
.state-msg--unavailable { border-color: var(--orange); }
.state-msg--unavailable .state-msg__title { color: var(--orange); }

/* --- Раздел ниже первого экрана ---------------------------------------
 *
 * Отделён сменой плотности, а не полосой: выше — действия и условия, здесь
 * начинается чтение. Ленты мотива тут больше нет (R11.4): три полосы узора
 * на одном экране читались обоями, а не характером.
 */

.below { position: relative; padding-top: var(--space-6); }
.below > h2:first-of-type { margin-top: 0; }

/* ======================================================================
   ПОЯВЛЕНИЕ СОДЕРЖАНИЯ — УБРАНО (R11.4)
   ======================================================================

   В R11.3 блок, впервые попавший в поле зрения, проступал снизу. Владелец
   пролистал главную на телефоне и увидел большую пустую область.

   Причина измерена, а не угадана: до срабатывания наблюдателя за видимостью
   на главной висело 942 пикселя содержания с нулевой прозрачностью. Место
   блок занимает, текста в нём не видно. Наблюдатель срабатывает не мгновенно,
   страховка стояла на секунду после загрузки, а человек листает раньше.

   Вывод, который дороже самого приёма: появление по прокрутке в этом
   продукте невозможно сделать безопасно. Любая его поломка — не «пропала
   анимация», а «пропал текст», и происходит это на медленном телефоне, то
   есть ровно у того человека, для которого продукт сделан.

   Поэтому движения, которое прячет содержание, здесь больше нет ни в каком
   виде. Движение осталось только там, где оно ОТВЕЧАЕТ на действие человека
   и где его отсутствие ничего не скрывает: отклик кнопки, раскрытие
   свёрнутого раздела, выкатывание меню, появление ответа проверки.

   `scripts/test-shell.mjs` падает, если правило с нулевой прозрачностью на
   содержании вернётся.
*/

/* Появление ответа: карточка результата и сообщение о состоянии. Это не
   украшение — человек должен заметить, что на его действие пришёл ответ.
   Анимируются только прозрачность и сдвиг: layout shift невозможен. */
@keyframes settle {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ======================================================================
   ШИРИНЫ ЭКРАНА
   ======================================================================
   Проверяется на 360, 390, 508, 768 и 1280. Горизонтальной прокрутки не
   должно быть ни на одной из них, и `overflow-x: hidden` для этого не
   используется: спрятанный дефект вёрстки остаётся дефектом.

   Телефон — не сжатый настольный экран, а основная поверхность: владелец
   смотрит продукт с телефона. Поэтому одностолбцовое чтение — исходное
   состояние, а столбцы появляются там, где для них есть место.

   R11.3 добавил к этому правилу телефонную ступень СНИЗУ: до 26rem поля
   уменьшаются, а шапка сжимается. На экране 360px боковые поля по 24px
   съедали 48px из 360 — на такой ширине это шестая часть строки.
*/

/* --- Узкий телефон ----------------------------------------------------
 *
 * Поля уже, шапка ниже, первый экран короче. Ничего не прячется: уменьшается
 * только воздух, потому что на 360px воздух дороже всего.
 */
@media (max-width: 26rem) {
  .wrap { padding-left: var(--space-4); padding-right: var(--space-4); padding-top: var(--space-5); }
  .site-head__inner { padding-left: var(--space-4); padding-right: var(--space-4); }
  .site-foot__inner { padding-left: var(--space-4); padding-right: var(--space-4); }
  .nav__menu[open] > .nav__list { padding-left: var(--space-4); padding-right: var(--space-4); }

  /*
   * Шапка на узком телефоне.
   *
   * Обещание «Проверить заранее» обязано стоять в ОДНУ строку. На 360px оно
   * ломалось пополам, шапка вырастала с 72px до 92px, и липкая шапка съедала
   * лишние 20px первого экрана на каждой странице. Поэтому здесь ужимается
   * всё, что вокруг обещания: знак, промежуток и поля кнопки разделов, — а
   * сам текст остаётся прежнего размера.
   */
  .site-head__mark { width: 32px; height: 32px; }
  .site-head__brand { column-gap: var(--space-2); }
  .site-head__name { font-size: 21px; }
  .nav__menu > summary { padding-left: var(--space-2); padding-right: var(--space-2); margin-right: calc(var(--space-2) * -1); }

  .opening__sub { margin-bottom: var(--space-5); }
  .action { padding-left: var(--space-4); padding-right: var(--space-5); }
  .action--main { padding-left: var(--space-4); padding-right: var(--space-6); }
  .platform { padding: var(--space-4); }
  .area { padding: var(--space-4); }
}

/* --- Самый узкий телефон: обещание уходит из шапки ---------------------
 *
 * До 384px «Проверить заранее» в шапке не помещается в строку и ломается
 * пополам. Шапка вырастает с 72px до 92px, и поскольку она липкая, эти 20px
 * человек теряет на каждом экране и при каждой прокрутке.
 *
 * Обещание из продукта при этом не исчезает: оно остаётся в заголовке
 * вкладки, в подвале КАЖДОЙ страницы и заголовком первого экрана главной.
 * Спрятано оно только от глаза — экранный диктор читает его по-прежнему,
 * поэтому здесь не `display: none`, а обрезка до точки.
 */
@media (max-width: 24rem) {
  .site-head__claim {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Телефон пошире: обещания о данных встают в два столбца — строки короткие,
   и в один столбец они оставляли половину полосы пустой. */
@media (min-width: 30rem) {
  .trust__list { grid-template-columns: 1fr 1fr; }
}

/*
 * На широком экране лента становится строкой.
 *
 * Четырьмя колонками по 230px она была четырьмя узкими колодцами: «Проверка на
 * вашем устройстве» переносилось в три строки, и короткое обещание выглядело
 * длинным. Строка с переносом отдаёт каждому обещанию ровно столько места,
 * сколько ему нужно.
 */
@media (min-width: 52rem) {
  .trust__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
  }
}

/* Планшет: карточки платформ и спокойные действия становятся в два столбца. */
@media (min-width: 46rem) {
  /*
   * Число столбцов задаётся содержанием, а не пересчитывается руками
   * (R11-024). Пока готовых проверок было две, здесь стояло «два столбца», а
   * у неготовых — «три». После переноса YouTube стало три и две, и обе сетки
   * сразу оказались неправильными: готовая карточка осталась одна во второй
   * строке, а у неготовых зияла пустая третья колонка.
   *
   * `auto-fit` схлопывает пустые дорожки сам, поэтому правило переживёт любое
   * следующее изменение состояния платформы.
   */
  .platforms { grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr)); }

  /*
   * Карточки замысла на большом экране идут не рядом, а одна под другой, и
   * раскладываются внутри себя.
   *
   * Рядом их было три на две дорожки: третья оставалась одна во второй
   * строке, и справа от неё зияла дыра величиной с карточку. Уменьшать
   * дорожку до трёх столбцов тоже нельзя — перечень отказов превращается в
   * столбик по слову, а именно его человек обязан прочитать.
   *
   * Широкая строка решает оба: дыры нет вовсе, а два перечня — «что войдёт»
   * и «чего не будет» — встают рядом и читаются вместе.
   */
  .areas { grid-template-columns: 1fr; }

  .area {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-6);
    row-gap: var(--space-3);
    align-items: start;
  }

  /* Через всю строку идёт всё, кроме двух перечней: они и есть столбцы. */
  .area__head,
  .area__what,
  .area__today,
  .area__action { grid-column: 1 / -1; }

  /* В сетке прижимать действие вниз нечем и незачем. */
  .area__action { margin-top: 0; justify-self: start; }

  .actions { grid-template-columns: 1fr 1fr; }
  .action--main { grid-column: 1 / -1; }
  .action--urgent { grid-column: 1 / -1; }

  /* --- Шапка на большом экране ---
   * Меню больше не нужно: разделы встают строкой и видны все сразу. Кнопка
   * «Разделы» скрывается, а список раскрывается независимо от того, открыт
   * <details> или нет.
   *
   * Два способа раскрытия рядом — не перестраховка. Новые движки скрывают
   * содержимое через `::details-content`, старые — через сам список; какой
   * именно у человека в телефоне, мы не знаем. */
  /* Разделы уходят на свою строку под именем: на 768px пять подписей рядом с
     именем в одну строку не помещаются, и строка разъезжалась. */
  .site-head__top { flex-wrap: wrap; }
  .nav { flex-basis: 100%; margin-left: 0; }

  .nav__menu > summary { display: none; }
  .nav__menu::details-content { content-visibility: visible; block-size: auto; }
  .nav__menu > .nav__list,
  .nav__menu[open] > .nav__list {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 var(--space-5);
    position: static;
    background: transparent;
    border-bottom: 0;
    box-shadow: none;
    padding: 0;
    z-index: auto;
    animation: none;
  }

  .nav__menu[open] > .nav__list li + li { border-top: 0; }
  .nav__menu[open] .nav__link { min-height: 44px; font-size: 18px; }

  .nav__link { padding: var(--space-1) 0; min-height: 44px; }

  /* «О проекте» — раздел второго плана: он нужен реже остальных и отделён
     от них промежутком, а не рамкой. */
  .nav__item--secondary { margin-left: auto; }
  .nav__item--secondary .nav__link { color: var(--ink-soft); }
  .nav__item--secondary .nav__link:hover { color: var(--accent); }

  .site-head__inner { padding-top: var(--space-4); padding-bottom: var(--space-4); }
  .site-head__top { align-items: center; }

  .site-foot__inner { padding-top: var(--space-6); }

  /* Полка действия нужна только там, где до действия надо прокручивать. На
     настольном экране шаг помещается целиком, и прилипшая кнопка была бы
     лишней панелью поверх содержания. */
  .thumb-bar { position: static; background: none; padding: 0; }
}

/* Настольный экран: заголовок первого экрана крупнее, воздуха больше. */
@media (min-width: 52rem) {
  .opening { padding-top: var(--space-5); }
  .opening__sub { font-size: 20px; }
  .wrap { padding-top: var(--space-7); }

  /* У неготовых карточек воздуха меньше: это записи о сервисе, а не действия. */
  .platform-group--quiet .platform { padding: var(--space-4) var(--space-5); }
}

/* ----------------------------------------------------------------------
   ШИРОКИЙ ЭКРАН: ЗАСЕЧКА УХОДИТ НА ПОЛЕ (R11.4)
   ----------------------------------------------------------------------

   Владелец сказал про настольный вид: короткие страницы выглядят брошенными
   в левом верхнем углу большого листа. Расширять строку текста нельзя —
   абзац шириной в тысячу пикселей не читается.

   Поэтому пустое поле слева получает работу: засечка раздела выходит из
   колонки на поле, как отметка на полях документа. Страница перестаёт быть
   лентой посреди пустоты и начинает читаться как лист с полями — а это и
   есть тот регистр, в котором продукт работает: архив, выписка, документ.

   Включается только там, где поле действительно есть: от 75rem ширина поля
   не меньше 112px, а засечка уходит на 72px. Ниже — засечка под заголовком,
   как была.
*/
@media (min-width: 75rem) {
  .wrap > h2,
  .below > h2,
  .platform-group__title { position: relative; }

  .wrap > h2::after,
  .below > h2::after,
  .platform-group__title::after {
    position: absolute;
    left: -72px;
    top: 0.62em;
    margin-top: 0;
  }
}

/*
 * Наведение мышью — не то же самое, что палец на стекле.
 *
 * На телефоне `:hover` срабатывает от касания и остаётся висеть после
 * перехода: человек возвращается назад и видит «подсвеченную» карточку,
 * которую он не трогает. Поэтому подъём карточек включается только там, где
 * есть настоящий указатель.
 */
@media (hover: none) {
  .action:hover, .card:hover, .platform--ready:hover { transform: none; box-shadow: var(--shadow-soft); }
  .action--main:hover { box-shadow: var(--shadow-raised); }
}

/* ======================================================================
   ВЗЯТО ИЗ R9 — осознанно и по частям
   ======================================================================
   Из принятой владельцем ветви инструкций по выгрузке перенесены только три
   мелких приёма вёрстки, каждый из которых уже проверен глазами владельца.
   Ни одной страницы, ни одного разбора и ни одной формулировки инструкций
   оттуда не взято — что именно взято, записано в DECISION_LOG (R11-007).
*/

/* Короткий список фактов вместо абзаца: три строки читаются, абзац из тех же
   трёх мыслей — нет. */
.facts { list-style: none; padding: 0; margin: 0 0 var(--space-4); }

.facts li {
  position: relative;
  padding: 0 0 0 26px;
  margin-bottom: var(--space-2);
  line-height: 1.45;
}

.facts li::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 12px;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--accent);
  transform: rotate(45deg);
}

/* Предупреждение в одну мысль: рамка та же, воздуха меньше. */
.notice--tight { margin: 0 0 var(--space-5); padding: var(--space-3) var(--space-4); }
.notice--tight:last-child { margin-bottom: 0; }

/* ======================================================================
   ПОДДЕРЖАТЬ ПРОЕКТ
   ======================================================================
   Страница поддержки — часть продукта, а не отдельный сайт сбора денег.
   Поэтому здесь нет ни одного приёма платёжных площадок: ни ярко-зелёной
   кнопки оплаты, ни шкалы собранного, ни сердец, ни монет. Цвет действия тот
   же синий, что во всём продукте; красный не участвует вовсе — он значит
   точное совпадение с записью перечня и ничего больше (R11-005).

   Знака платёжного сервиса здесь тоже нет: человек встретит его на странице
   оплаты, а до перехода страница обязана выглядеть нашей (R12.1).

   Перенесено из принятой ветви поддержки без изменений (R13.1 §9).
*/

/* Обещание, которое человек обязан прочитать ДО кнопки: поддержка
   добровольная. Выделено тихой заливкой действия, а не восклицанием. */
.pledge {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-left: var(--edge) solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--ink);
  font-size: var(--text-lead);
  font-weight: 650;
  line-height: 1.45;
  max-width: var(--measure);
}

/* Куда ведёт кнопка. Стоит перед ней, а не после: человек обязан узнать про
   чужую страницу и про новую вкладку до нажатия, а не после. */
.support-where {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card-sunken);
  color: var(--ink-soft);
  font-size: var(--text-small);
  max-width: var(--measure);
}

/* Переход к оплате. Во всю ширину на телефоне: это главное действие
   страницы, и промахиваться по нему человек не должен. */
.support-go { margin: 0 0 var(--space-6); max-width: var(--measure); }

.support-go .btn {
  margin: 0;
  width: 100%;
  min-height: 56px;
  font-size: var(--text-h3);
}

@media (min-width: 30rem) {
  .support-go .btn { width: auto; min-width: 16rem; }
}

/* Плотность страницы поддержки (R12.2).
   Компонентов не трогаем: страница просто длинная, и на телефоне читается
   тяжело. Заголовки и лента-разделитель получают чуть меньше воздуха, а
   списки становятся плотнее — только здесь и только на этой странице. */
[data-page="support"] .wrap h2 { margin-top: var(--space-5); }
[data-page="support"] .below { padding-top: var(--space-6); }

/* Плотный перечень: пункты в одну-две строки, между ними меньше воздуха. */
.tight { margin: 0 0 var(--space-4); }
.tight li { margin-bottom: var(--space-1); line-height: 1.45; }

/* ======================================================================
   СЛУЖЕБНЫЕ СТРАНИЦЫ
   ======================================================================
   Панель владельца и страница диагностики носят ту же шапку, но БЕЗ разделов
   сайта: ссылка из них в продукт есть, ссылки из продукта в них нет нигде.
   Так служебную страницу нельзя случайно открыть, не зная адреса, и нельзя
   спутать с продуктом.
*/

.site-head--service { background: var(--card-sunken); }
.site-head--service .site-head__claim { font-weight: 600; }
.site-head--service::after { opacity: 0; }
.site-foot--service::before { opacity: 0; }

/* --- Служебная страница знака (web/dev/mark/) --------------------------
 * Нужна для просмотра владельцем и для снимка: знак обязан быть проверен
 * во всех размерах сразу, а не «на глаз в шапке». В навигации продукта её
 * нет, как и всех остальных служебных страниц. */
.mark-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
  gap: var(--space-4);
  margin: var(--space-5) 0 var(--space-6);
  max-width: none;
}

.mark-tile { margin: 0; min-width: 0; }

.mark-tile__box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 128px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* Подложки заданы классами, а не атрибутом style: строгая политика
   безопасности сайта запрещает встроенные стили, и это правильно. */
.mark-tile__box--card { background: var(--card); color: var(--accent); }
.mark-tile__box--white { background: var(--card-raised); color: var(--accent); }
.mark-tile__box--paper { background: var(--paper); color: var(--accent); }
.mark-tile__box--dark { background: #1d2026; color: #a8c6ec; border-color: #3a3f48; }
.mark-tile__box--ink { background: var(--card-raised); color: var(--ink); }
.mark-tile__box--accent { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

.mark-tile figcaption {
  margin-top: var(--space-2);
  font-size: var(--text-note);
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

/* --- Отметки человека о кандидате YouTube (R4) -------------------------
 * Это его собственный след в этой вкладке, а не результат проверки, поэтому
 * блок нарочно тихий. Отступ задан токеном: ряд кнопок внутри отметки живёт
 * по тем же правилам, что и остальные ряды (R11-022).
 */
.mark .btn-row { margin: var(--space-3) 0 var(--space-2); }
.mark .btn-row:has(> .btn:not([hidden])) { margin: var(--space-3) 0 var(--space-2); }

/* ======================================================================
   R13 — одна проверка на всё, источники, помощь проекту
   ======================================================================
   Ни одного нового цвета и ни одной новой ступени текста: всё ниже собрано
   из токенов, которые уже есть. Красный по-прежнему значит одно — точное
   совпадение с записью официального перечня, — поэтому ни состояние
   источника, ни кнопка вида записи красными не бывают.
*/

/* --- Выбор вида записи -------------------------------------------------
 *
 * Ряд кнопок под полем ввода. Первая — «Все», и она нажата по умолчанию:
 * человек не обязан знать заранее, Telegram это, книга или песня.
 *
 * Область нажатия не опускается ниже --tap: на телефоне по этому ряду
 * промахиваются чаще всего.
 */
.scopes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
}

.scope {
  min-height: var(--tap);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: var(--text-small);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.scope:hover { border-color: var(--accent); color: var(--accent-strong); }

.scope[aria-pressed='true'] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
}

/* --- Карточка ответа ---------------------------------------------------
 *
 * Кромка слева — грамматика: красная 5px у подтверждённого, оранжевая 3px у
 * того, что нужно уточнить, никакой у помощи в поиске. Рамки по кругу нет
 * ни у одной: рамка и кромка вместе превращают ответ в набор полей ввода.
 */
.found {
  background: var(--card);
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: var(--shadow);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-4);
}

.found--confirmed { border-left-width: var(--edge-strong); border-left-color: var(--red); }
.found--clarify { border-left-color: var(--orange); }

/* Похожие названия — не результат. Поверхность утоплена, кромки нет. */
.found--similar {
  background: var(--card-sunken);
  border-left-color: transparent;
  box-shadow: none;
}

.found__state {
  font-weight: 650;
  font-size: var(--text-small);
  margin: 0 0 var(--space-2);
  color: var(--neutral);
}

.found--confirmed .found__state { color: var(--red); }
.found--clarify .found__state { color: var(--orange); }

.found__title {
  font-size: var(--text-h3);
  font-weight: 650;
  margin: 0 0 var(--space-1);
  color: var(--ink);
  overflow-wrap: anywhere;
}

.found__kind { margin: 0 0 var(--space-3); color: var(--ink-soft); font-size: var(--text-note); }
.found__why { margin: 0 0 var(--space-1); font-size: var(--text-small); }
.found__meaning { margin: 0 0 var(--space-3); color: var(--ink-soft); font-size: var(--text-note); }

.found__more { margin: 0; }

.found__more > summary {
  cursor: pointer;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  color: var(--accent);
  list-style: none;
}

.found__more > summary::-webkit-details-marker { display: none; }
.found__more > summary::marker { content: ""; }

.found__more > summary::after {
  content: "";
  width: 9px;
  height: 9px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.found__more[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.found__more > summary:hover { color: var(--accent-strong); }

.found__body { padding-top: var(--space-3); }
.found__body .record__facts { margin-bottom: var(--space-3); }

/* --- Карточка источника ------------------------------------------------
 *
 * Неполадка источника — спокойное сообщение, а не тревога. Оранжевая кромка
 * здесь означает ровно то же, что везде: «нужно уточнить», а не «опасно».
 */
.source {
  background: var(--card);
  border-left: var(--edge) solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: var(--shadow);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-4);
}

.source--working { border-left-color: var(--ready); }
.source--attention { border-left-color: var(--orange); }
.source--pending { border-left-color: var(--line-strong); background: var(--card-sunken); box-shadow: none; }

.source__name { font-size: var(--text-h3); font-weight: 650; margin: 0 0 var(--space-1); }
.source__publisher { margin: 0 0 var(--space-3); color: var(--ink-soft); font-size: var(--text-note); }

.source__state {
  display: inline-block;
  font-weight: 650;
  font-size: var(--text-note);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  margin: 0 0 var(--space-2);
}

.source__state--working { color: var(--ready); border-color: var(--ready); background: var(--ready-bg); }
.source__state--attention { color: var(--orange); border-color: var(--orange); background: var(--orange-bg); }
.source__state--pending { color: var(--pending); border-color: var(--line-strong); background: transparent; }

.source__state-text { margin: 0 0 var(--space-3); font-size: var(--text-small); }
.source__note { margin: var(--space-3) 0 0; color: var(--ink-soft); font-size: var(--text-note); }

/* Честное «этого мы не записываем» выделено словом, а не пунктиром: пунктир
 * читается как поломка. */
.source__unknown { color: var(--pending); font-style: italic; }

/* --- Свёрнутая карточка неподключённого источника (R13.1 §5) ------------
 *
 * Шесть подряд раскрытых карточек с одной и той же длинной фразой честны, но
 * нечитаемы: страница превращается в отчёт о неудачах. Свёрнутый вид ничего
 * не прячет — название, ведомство и состояние видны сразу, а подробности на
 * один жест. Пунктира здесь нет: пунктир читается как поломка.
 */
.source--folded { padding: 0; }

.source__summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-5);
  min-height: var(--tap-lg);
  position: relative;
  padding-right: var(--space-7);
}

.source__summary::-webkit-details-marker { display: none; }
.source__summary::marker { content: ""; }

/* Та же стрелка, что у свёрнутых пояснений: один жест — один знак. */
.source__summary::after {
  content: "";
  position: absolute;
  right: var(--space-5);
  top: calc(var(--space-3) + 0.55em);
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.source--folded[open] > .source__summary::after { transform: translateY(4px) rotate(-135deg); }

/* В свёрнутом виде название набрано основным размером, а не заголовочным:
   названия ведомственных перечней длинные, и на телефоне заголовочный кегль
   растягивал каждую свёрнутую карточку на пять строк. */
.source__summary .source__name { margin: 0; color: var(--accent); font-size: var(--text-body); }
.source__summary .source__publisher { margin: 0; }
.source__summary .source__state { margin: var(--space-1) 0 0; align-self: flex-start; }

.source__body { padding: 0 var(--space-5) var(--space-4); }
.source__body > :last-child { margin-bottom: 0; }

.source--folded[open] > .source__body { animation: unfold var(--dur-slow) var(--ease-out); }

/* Сводная строка страницы источников: сколько источников стоит за ответом
   проверки прямо сейчас. Это главный факт страницы, и он читается первым. */
.sources-count {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lead);
  font-weight: 650;
  color: var(--ink);
  max-width: var(--measure);
}

/* --- Готовое предложение источника ------------------------------------- */
.proposal {
  width: 100%;
  min-height: 190px;
  font: inherit;
  font-size: var(--text-note);
  line-height: 1.5;
  padding: var(--space-3) var(--space-4);
  color: var(--ink);
  background: var(--card-sunken);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  resize: vertical;
}

/* --- Пути помощи проекту ------------------------------------------------ */
.help { display: grid; gap: var(--space-4); margin: 0 0 var(--space-6); }

.help__item {
  background: var(--card);
  border-left: var(--edge) solid var(--thread);
  border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: var(--shadow);
  padding: var(--space-4) var(--space-5);
}

.help__title { font-size: var(--text-h3); font-weight: 650; margin: 0 0 var(--space-2); }
.help__item p { margin: 0 0 var(--space-3); }
.help__item p:last-child { margin-bottom: 0; }

@media (min-width: 46rem) {
  .help { grid-template-columns: 1fr 1fr; }
}

/* ----------------------------------------------------------------------
   ПРОВЕРКА ОДНОЙ СТРОКИ ПРЯМО НА ГЛАВНОЙ (R13.1 §1)
   ----------------------------------------------------------------------

   До R13.1 здесь стояла карточка-ссылка `.action--second`: человек с
   названием в руках нажимал на неё и только на следующей странице видел
   поле. Владелец на живом просмотре назвал это лишним нажатием, и он прав —
   поле теперь стоит прямо здесь.

   Заливки у блока нет намеренно: залито одно действие на первом экране —
   проверка подписок. Второе сильное место держится не цветом, а тем, что это
   единственное на экране настоящее поле ввода.
*/
.home-search {
  grid-column: 1 / -1;
  background: var(--card-raised);
  border-left: var(--edge-strong) solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  box-shadow: var(--shadow);
  padding: var(--space-4) var(--space-5);
}

.home-search__title {
  margin: 0 0 var(--space-1);
  font-size: clamp(21px, 19px + 0.6vw, 25px);
  font-weight: 700;
  color: var(--accent);
  max-width: var(--measure);
}

/* Засечка раздела к этому заголовку не относится: он не разделяет страницу,
   а называет поле под собой. */
.home-search__title::after { content: none; }

.home-search__text {
  margin: 0 0 var(--space-3);
  color: var(--ink-soft);
  font-size: var(--text-note);
  max-width: var(--measure);
}

.home-search__form { margin: 0; }

.home-search__label { display: block; font-weight: 600; margin-bottom: var(--space-2); }

.home-search__form input {
  width: 100%;
  max-width: 30rem;
  min-height: var(--tap-lg);
  padding: 14px 16px;
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.home-search__form input:focus { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }

/* Кнопка во всю ширину на телефоне: промахиваться по главному действию блока
   человек не должен. */
.home-search__form .btn { margin: var(--space-3) 0 0; width: 100%; min-height: var(--tap-lg); }

@media (min-width: 30rem) {
  .home-search__form .btn { width: auto; min-width: 12rem; }
}

.home-search__hint,
.home-search__more {
  margin: var(--space-3) 0 0;
  font-size: var(--text-note);
  color: var(--ink-soft);
  max-width: var(--measure);
}

.home-search__more { margin-bottom: 0; }
.home-search__note { margin: var(--space-3) 0 0; }

/* Пустое сообщение — это не сообщение.
 * Блок ответа формы существует в разметке до нажатия, и без этого правила
 * под кнопкой висела бы серая полоса, в которой человек искал бы текст. */
.state-msg:empty { display: none; }

/* Тихий ряд ссылок: путь для тех, кто уже знает, какой сервис ему нужен.
   Он не соперничает с главным действием рядом — это строка текста, а не
   ряд кнопок (R13.1 §4). */
.quiet-links { font-size: var(--text-note); color: var(--ink-soft); }

/* ======================================================================
   ЕСЛИ ВАС ЗАДЕРЖАЛИ: ПЕРВЫЕ ЧАСЫ (R13.1 §10-§16)
   ======================================================================

   Этот раздел читает человек в самом плохом состоянии, в которое он вообще
   может попасть, — и часто с телефона. Поэтому здесь нет ни одного приёма
   «красиво»: ни двух колонок, ни мелкого текста, ни длинных абзацев.

   Одна карточка — одна мысль. Номер шага стоит отдельным знаком, потому что
   под напряжением человек ищет глазами, где он остановился, а не читает
   подряд. Красного здесь нет: красный в продукте значит точное совпадение с
   записью перечня, и тревожить им тут нельзя.
*/

.emg-block { margin: var(--space-6) 0 0; }
.emg-block:first-child { margin-top: var(--space-4); }

.emg-block__title {
  font-size: var(--text-h3);
  font-weight: 700;
  margin: 0 0 var(--space-2);
  max-width: var(--measure);
}

.emg-block__note {
  margin: 0 0 var(--space-4);
  color: var(--ink-soft);
  font-size: var(--text-note);
  max-width: var(--measure);
}

/* Шаг: номер слева, заголовок рядом. Номер не декоративный — это место в
   последовательности, и оно обязано читаться без усилия. */
.record--step { border-left-color: var(--accent); }

.record--step .record__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.record__step {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
}

.record__title-text { flex: 1 1 auto; }

/* Две карточки, которые держат человека в руках. Заливки действия у них нет:
   это не кнопки. Кромка та же, что у шага, — они из того же разговора. */
.emg-block--keep-calm .record {
  border-left-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: none;
}

.emg-block--keep-calm .record__title { font-size: var(--text-h3); }
.emg-block--keep-calm .record p { font-size: var(--text-lead); line-height: 1.55; }

/* Юридическая часть: спокойное сообщение, а не поломка. Пунктира здесь нет —
   пунктир читается как «сломалось». */
.emg-block--ask-and-record .record { border-left-color: var(--line-strong); background: var(--card-sunken); }

/* Личный опыт стоит отдельно и подписан словами, а не цветом.
   Нитью его красить нельзя: значащих цветов в продукте четыре, и пятый
   обесценил бы первые четыре. Различие здесь держится на подписи под текстом
   и на том, что блок стоит последним. */
.emg-block--owner-experience .record {
  border-left-color: var(--line-strong);
  background: var(--card-sunken);
  box-shadow: none;
}

.record__origin {
  margin: var(--space-3) 0 0;
  font-size: var(--text-note);
  font-weight: 650;
  color: var(--ink-soft);
}

/* Под напряжением строка должна быть просторной. Правило действует только в
   этом разделе — в остальном продукте межстрочный интервал общий. */
[data-page="emergency"] .record p { line-height: 1.65; }

/* ======================================================================
   Предложение источника (R13.2)
   ====================================================================== */

/* Ловушка для рассылок. Прячется так, чтобы её не показала ни одна тема и ни
   один режим: `display: none` часть программ-заполнителей распознаёт и поле
   пропускает. Человеку она не видна, в порядок обхода не попадает и в
   озвучивание не попадает тоже (`aria-hidden` в разметке). */
.trap {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Что произойдёт по нажатию — сказано прямо над кнопкой, обычным текстом.
   Не мелким шрифтом и не серым: это часть решения, а не оговорка. */
.before-send {
  margin: var(--space-4) 0 var(--space-3);
  color: var(--ink-soft);
}

/* Номер предложения: его переписывают с экрана телефона или диктуют вслух. */
.proposal-ref {
  margin: var(--space-3) 0 0;
  font-size: var(--text-note);
}

.proposal-ref strong {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Карточка благодарности и карточка неудачи занимают всю ширину колонки:
   на телефоне ответ не делится на два столбца ни при какой ширине. */
#source-done .btn-row {
  margin-top: var(--space-4);
}

#source-done:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
