/* ==========================================================================
   main.css — reset, база, раскладка, компоненты. Общий для всех страниц.

   Стилистика: палитра, скругления и круглые пастельные плашки — с
   bimiboo.com; структура секций (центрированный герой с иллюстрацией,
   карточки-фичи, чередующиеся ряды текст/картинка, цветная CTA-полоса,
   многоколоночный подвал) — с kimikosoft.com.

   ТРИ ИНВАРИАНТА. Из-за их нарушения в референсном сайте паддинги секций
   гасили друг друга, и лечилось это !important'ами.

   1. Ни один компонент не задаёт вертикальный margin. Вертикаль дают только
      .section (padding-block) и .flow (margin-block-start у соседей).
      Схлопывание margin'ов невозможно, если margin всегда с одной стороны.
   2. Ни один компонент не задаёт горизонтальные отступы страницы —
      только .container.
   3. Селекторов по тегу вне reset/base нет. Единственное задокументированное
      исключение — .prose в legal.css: там ~200 абзацев, класс на каждом
      не нужен.

   Пастельные фоны (--past-*) встречаются ниже РОВНО в одном месте:
   блоке .card--*. Это проверяется греплом, см. README.
   ========================================================================== */

@layer reset {
  /* :where() даёт нулевую специфичность — сброс ни с чем не конкурирует. */
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }
  :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, dd, figure, blockquote, fieldset) {
    margin: 0;
  }
  :where(ul, ol) {
    padding: 0;
    list-style: none;
  }
  :where(img, svg) {
    display: block;
    max-width: 100%;
  }
  :where(button, input, select, textarea) {
    font: inherit;
    color: inherit;
  }
  :where(a) {
    color: inherit;
  }

  /* Плавную прокрутку включаем только тем, кто не просил её отключить:
     вестибулярные триггеры — не косметика. */
  @media (prefers-reduced-motion: no-preference) {
    html {
      scroll-behavior: smooth;
    }
  }
  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

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

  body {
    margin: 0;
    background: var(--c-bg);
    color: var(--c-fg);
    font-family: var(--ff-body);
    font-size: var(--fs-0);
    line-height: var(--lh-body);
    text-underline-offset: 0.16em;
  }

  h1,
  h2,
  h3,
  h4 {
    font-family: var(--ff-display);
    font-weight: 800;
    line-height: var(--lh-head);
    color: var(--c-heading);
    text-wrap: balance;
  }

  a {
    color: var(--c-link);
    text-decoration-thickness: 1px;
  }
  a:hover {
    text-decoration-thickness: 2px;
  }

  strong {
    font-weight: 700;
    color: var(--c-heading);
  }

  /* Технические имена (ключи хранилища, имена cookie) — моноширинным.
     Отдельное семейство под это не грузим: системного стека достаточно. */
  code {
    padding: 0.1em 0.35em;
    border-radius: var(--r-1);
    background: var(--c-bg-alt);
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, "DejaVu Sans Mono",
      "Courier New", monospace;
    font-size: 0.92em;
    word-break: break-word;
  }

  /* У Nunito Sans есть настоящий курсив, но в юридическом тексте он читается
     хуже подчёркивания, а <em> там встречается редко. */
  em {
    font-style: italic;
  }

  /* Все id получают отступ под липкую шапку — иначе анкоря в документах
     приземляются под ней. --header-h объявлена один раз в tokens.css. */
  [id] {
    scroll-margin-top: calc(var(--header-h) + var(--s-5));
  }

  :focus-visible {
    outline: 3px solid var(--c-focus);
    outline-offset: 2px;
    border-radius: 4px;
  }
}

@layer layout {
  .container {
    width: min(100% - var(--gutter) * 2, var(--measure-wide));
    margin-inline: auto;
  }

  .section {
    padding-block: var(--section-y);
  }
  .section--alt {
    background: var(--c-bg-alt);
  }

  /* Единственный механизм вертикального ритма внутри потока.
     Контекст переопределяет шаг через --flow, а не через свои margin'ы. */
  .flow > * + * {
    margin-block-start: var(--flow);
  }
}

@layer components {
  /* --- Скип-ссылка: первый Tab на любой странице ------------------------- */
  .skip-link {
    position: absolute;
    left: var(--s-3);
    top: var(--s-3);
    z-index: 100;
    padding: var(--s-3) var(--s-5);
    background: var(--c-heading);
    color: var(--white);
    border-radius: var(--r-pill);
    font-weight: 700;
    text-decoration: none;
    transform: translateY(-200%);
  }
  .skip-link:focus-visible {
    transform: translateY(0);
    outline-color: var(--white);
    outline-offset: -6px;
  }

  /* --- Шапка -------------------------------------------------------------
     Гамбургера и JS-навигации нет: на узком экране навигация уходит в свой
     ряд под логотипом. Липкой шапка была только с 48em — из опасения, что
     на телефоне она съест пол-экрана. На деле она съедала его и без sticky:
     просто уезжала вверх и ссылки становились недоступны (BBA-24496).
     Теперь шапка липкая всегда, а мобильный ряд навигации сжат до одной
     строки (см. ниже) — вместе это 108px из ~600, а не половина. */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--c-bg);
    box-shadow: 0 1px 0 var(--c-rule);
  }
  .site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-3) var(--s-6);
    min-height: var(--header-h);
    padding-block: var(--s-3);
  }
  /* Прижимает кнопку к правому краю. Раньше это делал стоявший перед ней
     переключатель языка; после его удаления auto нужен здесь. */
  .site-header__cta {
    margin-inline-start: auto;
  }
  /* На узком экране навигация уходит во вторую строку целиком, а логотип и
     «Связаться» остаются в первой: order:2 у навигации ставит её после
     кнопки, хотя в разметке она стоит до неё.
     Кнопку здесь раньше просто скрывали (BBA-24460) — на телефоне её не было
     ни в одной ориентации. Три ряда, которых тогда боялись, брались от
     переключателя языков; его давно нет, и в два ряда всё укладывается. */
  @media (max-width: 47.99em) {
    .site-header__inner {
      row-gap: var(--s-2);
      /* Колоночный зазор уменьшен: на 320px логотип и кнопка иначе не
         помещаются в одну строку и кнопка уезжает в третий ряд. */
      column-gap: var(--s-3);
      /* Шапка теперь липкая, поэтому её высота — это отнятый экран.
         Вертикальные отступы сжаты, min-height снят: два ряда задают высоту
         сами, и заданные 4.5rem только мешали бы сжаться. */
      min-height: 0;
      padding-block: var(--s-2);
    }
    .site-nav {
      flex-basis: 100%;
      order: 2;
      /* Страховка для 320px и для более широких шрифтов: если строка всё же
         не поместится, она прокручивается вбок, а не переносится и не рвёт
         вёрстку. Полосу прокрутки не показываем — на телефоне она оверлейная,
         а на широком экране этот блок не применяется. */
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: none;
    }
    /* Навигация — строго одна строка. Три ссылки требовали 327px из 328
       доступных на 360px, и шрифт чуть шире переносил «Документы» во второй
       ряд: шапка становилась трёхэтажной (BBA-24499). nowrap делает перенос
       невозможным в принципе, а сжатый зазор даёт запас 17px вместо 1px.
       Кегль не уменьшаем: на ступень ниже ссылка теряет высоту до 39px, а
       тач-таргет держим ≥44px. Если ширины всё же не хватит (320px), строка
       прокрутится вбок — см. overflow-x у .site-nav выше.
       Селектор из двух классов намеренно: у .site-nav__list ниже в файле
       стоят flex-wrap:wrap и gap, медиазапрос специфичности не добавляет, и
       при равной специфичности победило бы правило, идущее позже. */
    .site-nav .site-nav__list {
      flex-wrap: nowrap;
      column-gap: clamp(var(--s-3), 3vw, var(--s-5));
    }
    /* nowrap у списка запрещает перенос ПУНКТОВ, но не текста внутри них:
       flex-элементы по умолчанию сжимаются, и на 320px «Безопасность»
       ломалась на две строки — ряд навигации становился 72px вместо 44px.
       Запрещаем и сжатие, и перенос: если строка не влезает, она уезжает
       под прокрутку, а высота шапки остаётся постоянной. */
    .site-nav__list > li {
      flex: none;
    }
    .site-nav__list a {
      white-space: nowrap;
    }
    /* На телефоне это единственный способ связаться, не доскроллив до
       подвала, поэтому кнопка добирает до 44px — планка тач-таргета,
       которой держится весь сайт. Селектор из двух классов намеренно:
       у .btn--sm ниже в файле стоит min-height: 2.5rem, и при равной
       специфичности победило бы правило, идущее позже. */
    .site-header .site-header__cta {
      min-height: 2.75rem;
    }
  }
  /* Планка тач-таргета — свойство пальца, а не ширины окна. Телефон лёжа
     даёт 873px и попадает в «десктопные» правила, где кнопка 40px. Ось
     здесь — указатель, поэтому правило дублируется по pointer: coarse. */
  @media (pointer: coarse) {
    .site-header .site-header__cta {
      min-height: 2.75rem;
    }
  }
  /* Ниже 360px три ссылки не влезают даже с минимальным зазором: не хватает
     23px. Прокрутка вбок для навигации — плохой ответ (WCAG 1.4.10 допускает
     её для таблиц и карт, но не для меню), поэтому здесь кегль опускается на
     ступень, а тач-таргет добирается паддингом: 15px × 1.5 + 24px = 46px. */
  @media (max-width: 22.5em) {
    /* Снова два класса: .site-nav__list a ниже в файле задаёт padding-block,
       и при равной специфичности победило бы правило, идущее позже. */
    .site-nav .site-nav__list a {
      padding-block: var(--s-3);
      font-size: var(--fs--1);
    }
  }

  .brand {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
    text-decoration: none;
    color: var(--c-heading);
  }
  .brand__mark {
    width: 2.25rem;
    height: 2.25rem;
    flex: none;
  }
  .brand__name {
    font-family: var(--ff-display);
    font-weight: 800;
    font-size: var(--fs-1);
  }

  .site-nav__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-5);
  }
  .site-nav__list a {
    display: inline-block;
    padding-block: var(--s-2); /* до 44px по вертикали вместе с line-height */
    color: var(--c-fg);
    font-weight: 600;
    text-decoration: none;
  }
  .site-nav__list a:hover,
  .site-nav__list a[aria-current="page"] {
    color: var(--c-accent-deep);
    text-decoration: underline;
  }
  .site-nav__list a[aria-current="page"] {
    text-decoration-thickness: 2px;
  }

  /* --- Кнопки: пилюли, как на обоих референсах -------------------------- */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.875rem; /* 46px */
    padding: var(--s-3) var(--s-6);
    border: 2px solid transparent;
    border-radius: var(--r-pill);
    background: var(--c-btn-bg);
    color: var(--c-btn-fg);
    font-family: var(--ff-display);
    font-weight: 700;
    font-size: var(--fs-0);
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 150ms ease;
  }
  .btn:hover {
    background: var(--c-btn-bg-hover);
    color: var(--c-btn-fg);
    text-decoration: none;
  }
  .btn--sm {
    min-height: 2.5rem;
    padding: var(--s-2) var(--s-5);
    font-size: var(--fs--1);
  }
  /* Обводка: тот же размер и вес, что у залитой. Разница только в заливке —
     на cookie-баннере это обязательное условие, а не вкусовщина. */
  .btn--outline {
    background: transparent;
    border-color: var(--c-accent-deep);
    color: var(--c-accent-deep);
  }
  .btn--outline:hover {
    background: var(--teal-soft);
    color: var(--c-accent-deep);
  }
  /* На бирюзовой полосе белая кнопка с тёмным текстом. */
  .btn--on-accent {
    background: var(--white);
    color: var(--c-accent-deep);
  }
  .btn--on-accent:hover {
    background: var(--grey-100);
    color: var(--c-accent-deep);
  }
  .btn:focus-visible {
    outline: 3px solid var(--c-focus);
    outline-offset: 3px;
    box-shadow: 0 0 0 3px var(--white);
  }
  .cta .btn:focus-visible {
    outline-color: var(--grey-900);
    box-shadow: 0 0 0 3px var(--white);
  }

  .linkish {
    padding: var(--s-2) 0;
    border: 0;
    background: none;
    color: var(--c-link);
    font: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 0.16em;
    cursor: pointer;
  }

  /* --- Мелкие типографские детали --------------------------------------- */
  .eyebrow {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-5);
    border-radius: var(--r-pill);
    background: var(--teal-soft);
    color: var(--c-accent-deep);
    font-weight: 700;
    font-size: var(--fs--1);
  }

  .age-mark {
    display: inline-block;
    padding: 0.05em 0.4em;
    border: 2px solid currentColor;
    border-radius: var(--r-1);
    font-weight: 800;
    font-size: 0.82em;
  }

  /* Центрированная шапка секции с подзаголовком — приём kimikosoft.
     Чередующиеся ряды (.row) её не используют: там текст выключен влево. */
  .section__head {
    max-width: 46rem;
    margin-inline: auto;
    margin-block-end: var(--s-7);
    text-align: center;
  }
  .section__title {
    font-size: var(--fs-3);
  }
  .section__sub {
    margin-block-start: var(--s-3);
    font-size: var(--fs-1);
    color: var(--c-fg);
  }
  /* Заголовок внутри чередующегося ряда сам отбивает свой лид. */
  .row .section__title {
    margin-block-end: var(--s-4);
  }

  /* Маркер незаполненного токена. Подсветка маркером — чтобы отправить
     страницу на модерацию с незаполненным токеном внутри было невозможно
     случайно. Двойные скобки в комментариях не пишем — их поймает
     tools/check-placeholders.mjs. */
  .placeholder {
    padding: 0 0.3em;
    border-radius: var(--r-1);
    background: var(--c-mark);
    color: var(--grey-900);
    font-weight: 700;
    box-decoration-break: clone;
  }

  /* --- Герой ------------------------------------------------------------- */
  /* Первый экран должен помещаться целиком, без обрезанной иллюстрации.
     Поэтому вертикальные размеры героя привязаны не только к ширине, но и к
     ВЫСОТЕ вьюпорта: отступы, кегль заголовка и высота картинки ограничены
     через svh. На низком окне герой сжимается сам, вместо того чтобы
     выталкивать картинку за край.

     Единица svh (small viewport height), а не vh: на мобильных vh считается
     от высоты БЕЗ адресной строки, поэтому по vh контент вылезал бы ровно
     на её высоту. Фолбэк на vh — для браузеров без svh. */
  .hero {
    padding-block: var(--s-6) var(--s-4);
    background: linear-gradient(180deg, var(--teal-soft) 0%, var(--c-bg) 78%);
  }
  .hero__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
  }
  .hero__title {
    max-width: 24ch;
    margin-block-start: var(--s-5);
    font-size: var(--fs-5);
    line-height: var(--lh-tight);
  }
  /* Единственный акцентный жест в заголовке: пунктирная направляющая, как в
     прописях.

     Именно text-decoration, а не border-block-end на inline-block. Разница
     не косметическая: border рисует ОДНУ линию по нижнему краю блока и во
     всю его ширину, поэтому при переносе строки линия оказывается под
     последней строкой и шире текста. text-decoration подчёркивает каждую
     строку ровно по ширине её текста — а так как заголовок центрирован,
     линия остаётся симметричной на любой ширине экрана. */
  .hero__accent {
    text-decoration-line: underline;
    text-decoration-style: dashed;
    text-decoration-color: var(--c-accent);
    text-decoration-thickness: 4px;
    text-underline-offset: 0.16em;
    /* Пунктир не должен разрываться на свисающих элементах букв (у, р, д). */
    text-decoration-skip-ink: none;
  }
  .hero__lead {
    max-width: var(--measure-lead);
    margin-block-start: var(--s-4);
    font-size: var(--fs-1);
  }
  .hero__art {
    width: 100%;
    max-width: 45rem;
    margin-block-start: var(--s-5);
  }
  /* Ограничиваем именно svg, а не контейнер: при заданной max-height и
     width:auto картинка с viewBox сама сохраняет пропорции и сжимается по
     высоте, вместо того чтобы обрезаться. */
  .hero__art svg {
    max-height: 24rem;
    width: auto;
    margin-inline: auto;
  }

  /* Подгонка героя под высоту окна включается только на достаточно высоком
     окне. На телефоне в горизонтальной ориентации (высота ~390px) вписать
     заголовок, лид и картинку в один экран нельзя в принципе, а попытка это
     сделать давала кегль лида 10.6px — нечитаемо (BBA-24483). На низком окне
     герой просто прокручивается, и это нормально: прокрутка дешевле, чем
     нечитаемый текст.
     Порог 34em = 544px по 16px: телефон в горизонтальной ориентации ниже,
     телефон в вертикальной (~870px) и планшет — выше.
     Единица svh (small viewport height), а не vh: на мобильных vh считается
     от высоты БЕЗ адресной строки, поэтому по vh контент вылезал бы ровно
     на её высоту. Фолбэк на vh — для браузеров без svh. */
  @media (min-height: 34em) {
    .hero {
      padding-block: clamp(var(--s-4), 4vh, var(--s-8)) clamp(var(--s-3), 2vh, var(--s-5));
      padding-block: clamp(var(--s-4), 4svh, var(--s-8)) clamp(var(--s-3), 2svh, var(--s-5));
    }
    .hero__inner {
      /* Занять экран целиком на высоком окне; на низком min-height просто
         перестаёт влиять, потому что содержимое уже выше. */
      min-height: calc(100vh - var(--header-h) - var(--s-10));
      min-height: calc(100svh - var(--header-h) - var(--s-10));
    }
    /* Потолок по высоте окна: на невысоком экране заголовок уступает место
       иллюстрации, а не наоборот. max() снизу — обязателен: без него потолок
       по svh опускает кегль сколь угодно низко, и на телефоне 320×568 лид
       уходил под 15px. Подгонка под экран не стоит нечитаемого текста. */
    .hero__title {
      font-size: max(2rem, min(var(--fs-5), 7.4svh));
    }
    .hero__lead {
      margin-block-start: clamp(var(--s-3), 2.4svh, var(--s-5));
      font-size: max(1rem, min(var(--fs-1), 2.7svh));
    }
    .hero__art {
      margin-block-start: clamp(var(--s-4), 3svh, var(--s-7));
    }
    .hero__art svg {
      max-height: min(36svh, 24rem);
    }
  }

  /* --- Бейджи магазинов (заглушки) --------------------------------------
     Официальные «Download on the App Store» и «Get it on Google Play» —
     товарные знаки со строгими гайдлайнами, перерисовывать их нельзя.
     Здесь нейтральные пилюли; заменить официальными файлами перед запуском. */
  .badges {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--s-4);
    margin-block-start: var(--s-6);
  }
  .badge {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
    min-height: 2.875rem;
    padding: var(--s-3) var(--s-6);
    border-radius: var(--r-pill);
    background: var(--c-heading);
    color: var(--white);
    font-family: var(--ff-display);
    font-weight: 700;
    text-decoration: none;
  }
  .badge:hover {
    background: var(--grey-900);
    color: var(--white);
  }
  .badge__glyph {
    width: 1.25rem;
    height: 1.25rem;
    flex: none;
  }

  /* --- Карточки --------------------------------------------------------- */
  /* Число колонок задано явно, а не через auto-fit. Причина: auto-fit считает
     колонки от ширины, ничего не зная о количестве плиток, и на телефоне в
     горизонтальной ориентации (873px) выдавал ровно 3 колонки на 4 плитки —
     четвёртая висела одна с пустотой рядом (BBA-24463). Плиток в разметке
     фиксированное число: 4 в «Чему учит», 3 в документах, — поэтому делители
     ширины выбираем сами: 1 → 2 → 4 и 1 → 3. Одинокой плитки не бывает ни на
     одной ширине. */
  .cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--s-5);
  }
  @media (min-width: 36em) {
    .cards {
      grid-template-columns: repeat(2, 1fr);
    }
  }
  @media (min-width: 62em) {
    .cards {
      grid-template-columns: repeat(4, 1fr);
    }
  }
  .cards--3 {
    grid-template-columns: 1fr;
  }
  @media (min-width: 48em) {
    .cards--3 {
      grid-template-columns: repeat(3, 1fr);
    }
  }
  .card {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    padding: var(--s-6);
    border-radius: var(--r-3);
    background: var(--c-surface);
    box-shadow: var(--shadow-card);
  }
  .card__badge {
    display: grid;
    place-items: center;
    width: 4.5rem;
    height: 4.5rem;
    margin-block-end: var(--s-2);
    border-radius: 50%;
    background: var(--card-tint, var(--teal-soft));
    color: var(--c-heading);
  }
  .card__badge svg {
    width: 2.5rem;
    height: 2.5rem;
  }
  .card__title {
    font-size: var(--fs-2);
  }
  .card__title a {
    color: inherit;
    text-decoration-color: var(--c-accent);
  }

  /* Пастельные оттенки живут ТОЛЬКО здесь. На карточках-фичах они красят
     круглую плашку под иконкой, на карточках документов — весь фон. */
  .card--mint {
    --card-tint: var(--past-mint);
  }
  .card--peach {
    --card-tint: var(--past-peach);
  }
  .card--lilac {
    --card-tint: var(--past-lilac);
  }
  .card--green {
    --card-tint: var(--past-green);
  }
  .card--blue {
    --card-tint: var(--past-blue);
  }
  /* Карточки документов: только заголовок-ссылка, поэтому выравниваем их по
     центру плитки — иначе одно- и двухстрочные названия висят по-разному. */
  .cards--3 .card {
    justify-content: center;
    min-height: 8.5rem;
    background: var(--card-tint);
    box-shadow: none;
  }

  /* --- Чередующийся ряд текст / иллюстрация ------------------------------ */
  .row {
    display: grid;
    gap: var(--s-7);
    align-items: center;
  }
  @media (min-width: 62em) {
    .row {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--s-9);
    }
    /* Порядок меняем только на широком экране: в одну колонку текст
       обязан идти первым, иначе скринридер получит картинку до заголовка. */
    .row--flip .row__text {
      order: 2;
    }
  }
  .row__lead {
    margin-block-end: var(--s-5);
    font-size: var(--fs-1);
  }
  .row__note {
    margin-block-start: var(--s-5);
    font-size: var(--fs--1);
    color: var(--c-fg-faint);
  }
  .row__art {
    justify-self: center;
    width: 100%;
    max-width: 26rem;
  }

  .ticks li {
    position: relative;
    padding-inline-start: var(--s-7);
  }
  .ticks li + li {
    margin-block-start: var(--s-3);
  }
  .ticks li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: 0.3em;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background: var(--past-green) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23599E2E' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7'/%3E%3C/svg%3E")
      center / 0.9rem no-repeat;
  }

  /* --- Цена и реквизиты ------------------------------------------------- */
  .price,
  /* Реквизиты. Колонка терминов задаётся долей от ширины, а не содержимым:
     при `auto` длинный термин («Ответственный за обработку ПДн», 30 знаков)
     берёт max-content и на телефоне забирает 224px из 305, оставляя значению
     72px — там ОГРНИП переносился в три строки, а имя в пять (BBA-24462).
     Потолок 12rem нужен на широком экране: без него термины разъезжаются от
     значений на пол-страницы. */
  .req {
    display: grid;
    grid-template-columns: clamp(6rem, 35%, 12rem) minmax(0, 1fr);
    gap: var(--s-2) var(--s-4);
  }
  .price {
    margin-block-start: var(--s-5);
    padding: var(--s-5);
    border-radius: var(--r-2);
    background: var(--c-bg);
  }
  .section--alt .price {
    background: var(--white);
  }
  .price dt,
  .req dt {
    font-size: var(--fs--1);
    color: var(--c-fg-faint);
  }
  /* break-word, а не anywhere: anywhere обнуляет min-content дорожки, и
     любая авторазмерная колонка рядом с таким значением схлопывается. Ломать
     слово по буквам всё равно приходится — на 320px в 96px не влезает ни
     «НИКОЛАЕВНА», ни 15-значный ОГРНИП, — но только когда иначе никак. */
  .price dd,
  .req dd {
    overflow-wrap: break-word;
  }
  /* Табличные цифры: 15 разрядов ОГРНИП читают и сверяют по колонке.
     Тонких пробелов между разрядами нет намеренно — они ломают вставку
     в форму поиска по ЕГРИП. */
  .req__value {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    letter-spacing: 0.02em;
  }
  .req--compact {
    gap: var(--s-1) var(--s-4);
    font-size: var(--fs--1);
  }

  /* --- «Безопасно для детей» -------------------------------------------- */
  .facts {
    display: grid;
    gap: var(--s-5);
  }
  .facts li {
    padding-inline-start: var(--s-5);
    border-inline-start: 4px solid var(--c-accent);
  }
  .facts h3 {
    font-size: var(--fs-1);
    margin-block-end: var(--s-1);
  }

  /* --- Бирюзовая CTA-полоса --------------------------------------------- */
  .cta {
    padding-block: var(--section-y);
    background: var(--c-accent);
  }
  .cta__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--s-4);
  }
  /* Белый текст на #5AB6CC даёт всего 2.3:1 — не проходит даже порог 3:1
     для крупного текста. Поэтому на бирюзовой плашке текст ТЁМНЫЙ: 8.0:1.
     Это и приём обоих референсов — тёмный текст на цветной подложке. */
  .cta__title {
    font-size: var(--fs-3);
    color: var(--grey-900);
  }
  .cta__text {
    max-width: var(--measure-lead);
    color: var(--grey-900);
  }

  /* --- Контакты --------------------------------------------------------- */
  .contacts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
    gap: var(--s-6) var(--s-7);
    padding: var(--s-6);
    border-radius: var(--r-3);
    background: var(--c-bg-alt);
  }
  .contacts__head {
    font-size: var(--fs-1);
    margin-block-end: var(--s-4);
  }
  .contacts__line + .contacts__line {
    margin-block-start: var(--s-2);
  }
  .contacts__note {
    margin-block-start: var(--s-4);
    font-size: var(--fs--1);
    color: var(--c-fg-faint);
  }

  /* --- Подвал ----------------------------------------------------------- */
  .site-footer {
    padding-block: var(--section-y) var(--s-6);
    background: var(--c-heading);
    color: #c9cacd; /* 7.3:1 на #323235 */
  }
  .site-footer a {
    color: var(--white);
  }
  .site-footer__inner {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--s-7);
  }
  .site-footer__brand {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin-block-end: var(--s-5);
    color: var(--white);
    font-family: var(--ff-display);
    font-weight: 800;
    font-size: var(--fs-1);
  }
  .site-footer__head {
    color: var(--white);
    font-size: var(--fs--1);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-block-end: var(--s-4);
  }
  .site-footer__list li + li {
    margin-block-start: var(--s-2);
  }
  /* --grey-400 на тёмном подвале даёт 4.34:1 — чуть меньше нужных 4.5
     для 14px, поэтому в подвале подписи светлее (6.7:1). */
  .site-footer .req dt {
    color: #b9bbc0;
  }
  .site-footer__cookie {
    margin-block-start: var(--s-4);
  }
  .site-footer .linkish {
    color: var(--white);
  }
  .site-footer :focus-visible {
    outline-color: var(--white);
  }
  .site-footer__legal {
    margin-block-start: var(--s-7);
    padding-block-start: var(--s-5);
    border-block-start: 1px solid rgba(255, 255, 255, 0.16);
    font-size: var(--fs--1);
  }
  /* Маркер на тёмном подвале остаётся жёлтым с тёмным текстом — он и должен
     кричать. */

}

@layer components {
  /* --- Появление при прокрутке ------------------------------------------
     Начальное состояние живёт под классом .reveal-on, который ставит
     assets/js/reveal.js. Без JS селектор не срабатывает и ничего не
     скрыто — для сайта, существующего ради юридических документов, это
     обязательное условие, а не перестраховка.

     Дополнительно всё завёрнуто в prefers-reduced-motion: no-preference,
     чтобы даже при ошибочно поставленном классе движения не было. */
  @media (prefers-reduced-motion: no-preference) {
    .reveal-on [data-reveal] {
      opacity: 0;
      transform: translateY(20px);
      transition: opacity 620ms cubic-bezier(0.22, 0.61, 0.36, 1),
        transform 620ms cubic-bezier(0.22, 0.61, 0.36, 1);
      transition-delay: var(--reveal-delay, 0ms);
      /* Подсказка компоновщику; снимается после появления, чтобы не держать
         слой в памяти без нужды. */
      will-change: opacity, transform;
    }
    /* Наезды сбоку — на чередующихся рядах текст/иллюстрация, как в
       референсе (там это были fade-right и fade-left). */
    .reveal-on [data-reveal="left"] {
      transform: translateX(-28px);
    }
    .reveal-on [data-reveal="right"] {
      transform: translateX(28px);
    }
    .reveal-on [data-reveal="scale"] {
      transform: scale(0.94);
    }

    .reveal-on [data-reveal][data-revealed] {
      opacity: 1;
      transform: none;
      will-change: auto;
    }

    /* Каскад по карточкам: задержка задаётся позицией в сетке, а не
       атрибутом в разметке — иначе при добавлении карточки пришлось бы
       пересчитывать числа руками. */
    .reveal-on .cards > [data-reveal]:nth-child(2) {
      --reveal-delay: 90ms;
    }
    .reveal-on .cards > [data-reveal]:nth-child(3) {
      --reveal-delay: 180ms;
    }
    .reveal-on .cards > [data-reveal]:nth-child(4) {
      --reveal-delay: 270ms;
    }
    .reveal-on .facts > [data-reveal]:nth-child(2) {
      --reveal-delay: 80ms;
    }
    .reveal-on .facts > [data-reveal]:nth-child(3) {
      --reveal-delay: 160ms;
    }

    /* Герой появляется по загрузке, а не по прокрутке: он и так в кадре. */
    .hero__inner > * {
      animation: hero-in 700ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
    }
    .hero__inner > *:nth-child(2) {
      animation-delay: 90ms;
    }
    .hero__inner > *:nth-child(3) {
      animation-delay: 180ms;
    }
    .hero__inner > *:nth-child(4) {
      animation-delay: 270ms;
    }
  }

  @keyframes hero-in {
    from {
      opacity: 0;
      transform: translateY(16px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
}

@layer utilities {
  .u-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
