/* =============================================================================
   ТОКЕНЫ — ЕДИНСТВЕННЫЙ ИСТОЧНИК ПРАВДЫ pavlova.dance.
   Правим здесь → меняется во всём сайте. В компонентах и страницах хардкод
   цветов, отступов, кеглей, радиусов, длительностей и z-index запрещён —
   только var(--…). Правила: DESIGN_RULES.md, проверка: bin/lint-tokens.sh.

   Файл подключён ДО site.css: легаси-тема продолжает работать на своих именах
   (--color-black, --space-s…), новый код пишется только на этих. Легаси-имена
   не переопределяем и не удаляем — их читает 33 КБ старого CSS.

   Слои: примитивы (шкалы --gray-* / --pink-*) → семантика (роль: --text,
   --surface, --brand) → компонентные значения задаются в самом компоненте от
   семантики. Примитив читается ТОЛЬКО здесь: var(--gray-400) в компоненте —
   такое же нарушение, как голый hex (ловит bin/lint-tokens.sh). Тёмная
   тема — блок .dark-theme-ui внизу: переопределяет только цвета, геометрия
   общая. Любой цвет литералом в компоненте выпадет из тёмной темы.

   Состав консолидирован по решению заказчика: дубли сведены в алиасы
   (--border, --ink / --on-ink, --on-photo, --whatsapp), неиспользованные
   ступени и цвета удалены, полушагов отступов нет — только 8pt-шкала.
   Новый токен заводим, когда он реально нужен на странице, а не «на всякий».
   ========================================================================== */

:root {
    /* ---------------------------------------------------------------------
       Текучая величина сайта: 0 на 414px, 1 на 1920px. От неё считаются
       кегли и секционные отступы — так было в легаси-теме, шкала проверена
       годами на реальных страницах. Объявлена в site.css; здесь только
       используется.
       -------------------------------------------------------------------- */

    /* Гарнитура. У Navigo остались два начертания (@font-face — в site.css):
       Medium 500 и Bold 700. 900 не подключено — H1 на всём сайте набран 700;
       600 браузер синтезирует и текст «мылится». */
    /* эксперимент: тело на системном */
    --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-heading: Navigo, var(--font-ui);   /* заголовки — на Navigo */
    /* Сериф. Раздел сексологии набирает им заголовки: обёртка
       src/routes/sexology/+layout.svelte подменяет --font-heading на этот токен
       (решение заказчика 2026-09-16). Начертание одно, 700 прямое и курсивное:
       @font-face — в том же layout, чтобы файлы грузились только в разделе. */
    --font-serif: 'PT Serif', Georgia, serif;

    /* Начертания. Насыщенность ниже 500 запрещена (решение заказчика
       2026-09-14): системный гротеск в 400 на светлом фоне выглядит тонко;
       body наследует --weight-medium. */
    --weight-medium: 500;   /* тело текста, подписи, ссылки */
    --weight-semibold: 600; /* подписи кнопок кита (Button): плотнее тела, легче заголовка — решение заказчика 2026-09-14 */
    --weight-bold: 700;     /* заголовки */

    /* Кегли. Пара «кегль + межстрочный» на каждую ступень: line-height
       тоже текучий, иначе на широком экране строки слипаются. Ступени
       ближе 6px друг к другу не держим — разницу не видно. Мельче --font-sm
       ступени нет и не будет: минимальный кегль на сайте — 16px (решение
       заказчика 2026-09-14, DESIGN_RULES.md): ступень 12 → 20 удалена.
       --font-caption не мельче: это те же 16px, только без роста. */
    /* Мелкая служебная строка: подвал. Не растёт с экраном — служебная
       строка на широком экране не должна догонять мету контента, а мельче 16
       не бывает (правило 1). Единственная нетекучая ступень в шкале, поэтому
       и имя у неё не по размеру, а по роли. Решение заказчика 2026-09-16. */
    --font-caption: 16px;
    --font-sm:      calc(16px + 8 * var(--responsive));   /* 16 → 24: мета-подписи, карточки, списки */
    --font-base:    calc(18px + 8 * var(--responsive));   /* 18 → 26: тело текста (было 18 → 28, ужато 2026-09-14) */
    --font-md:      calc(20px + 12 * var(--responsive));  /* 20 → 32: лид, крупный абзац (было 20 → 35, ужато 2026-09-14) */
    --font-lg:      calc(24px + 14 * var(--responsive));  /* 24 → 38: заголовок секции (H2) */
    --font-xl:      calc(30px + 34 * var(--responsive));  /* 30 → 64: заголовок блока */
    --font-display: calc(54px + 24 * var(--responsive));  /* 54 → 78: H1 — один на весь сайт (было 54 → 88, верх ужат 2026-09-18) */

    --leading-caption: 24px;  /* пара к --font-caption: тоже без текучести, 1.5 кегля */
    --font-caption-lg: 18px;    /* служебные ссылки платформы («← Все курсы», выбор качества): на 2px крупнее подписи, без текучести */
    --leading-caption-lg: 26px; /* пара к --font-caption-lg */
    --leading-xs:      calc(18px + 8 * var(--responsive));   /* плотная строка под --font-sm в один ряд (быстрая строка меню) */
    --leading-sm:      calc(24px + 12 * var(--responsive));
    --leading-base:    calc(26px + 12 * var(--responsive));  /* 26 → 38, ~1.45 кегля */
    --leading-md:      calc(28px + 14 * var(--responsive));  /* 28 → 42, ~1.3 кегля */
    --leading-prose:   1.68;   /* длинные статьи: спокойный ритм чтения */
    --leading-heading: 1.1;   /* заголовки: плотно, без текучести */
    --leading-tight:   1.02;  /* H1 в две строки */

    /* Трекинг: чем крупнее заголовок, тем туже. Ступени по роли, не по кеглю. */
    --tracking-tight-1: -0.01em;  /* подзаголовок блока */
    --tracking-tight-2: -0.02em;  /* заголовок секции */
    --tracking-display: -0.052em; /* H1 (h1 / .h1_like / .header__xxl): в em, а не в px — кегль текучий,
                                     54→78px, и фиксированный −4px на малом кегле слипает жирные
                                     начертания. Само значение не менялось с тех пор, как верх кегля
                                     ужали с 88 до 78 (2026-09-18): на 1440 это теперь 70.3px и −3.66px
                                     вместо прежних 77.16px и −4px. Трекинг съехал вслед за кеглем
                                     намеренно — он и задан в em ровно для этого. */
    --tracking-wide:     0.06em;  /* мелкие подписи-метки, если без капса не читаются */

    /* ---------------------------------------------------------------------
       Отступы. Одна 8pt-шкала для внутренних зазоров + два текучих для
       секций (те же формулы, что легаси --space-xs: секции сайта уже стоят
       на них, новые страницы должны дышать в том же ритме). Полушагов нет:
       зазор округляем к ближайшей ступени, второй шкалы в системе не будет.
       -------------------------------------------------------------------- */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-7: 32px;
    --space-8: 40px;
    --space-9: 64px;

    --space-block:   calc(15px + 45 * var(--responsive));  /* 15 → 60: зазор между блоками, боковое поле страницы */
    --space-section: calc(var(--space-block) * 1.5);        /* 22.5 → 90: секция = полтора блока, ритм читается */
    --space-inset:   calc(var(--space-block) * 1.25); /* 19 → 75: внутренний отступ крупных плиток и карточек (легаси .card__inner 25 → 70) */
    --space-frame:   90px;   /* боковое поле героя главной на десктопе; фиксированное по решению заказчика, не текучее */

    /* ---------------------------------------------------------------------
       Раскладка
       -------------------------------------------------------------------- */
    --page-width: 1400px;     /* мера контентных секций; full-bleed выходят за неё через calc(50% - 50vw).
                                 Это внешняя ширина блока: box-sizing border-box, боковые поля
                                 (--space-block) лежат внутри меры, поэтому текстовая колонка уже —
                                 1400 - 2 * --space-block (1308.8 на 1440, 1280 на 1920) */
    --page-width-wide: 1600px;  /* мера шапки и сеток плиток: шире — центрируются, по бокам линии */
    --topbar-h: 100px;        /* высота шапки; читают full-bleed секции и якоря (scroll-margin) */
    /* Высота сцены героя (<Hero>): столько занимает первый экран с фотографией.
       Перенесена из легаси-переменной site.css --hero-img-height, которую
       главная держала тремя значениями (900 / 700 / 900). Одно значение на все
       ширины и все страницы: на главной по ней идёт пилон под нижний край
       (bleed), на остальных — верхняя граница высоты снимка в кадре. */
    --hero-h: 700px;
    --measure: 62ch;          /* мера строки абзаца */
    --measure-narrow: 48ch;

    /* ---------------------------------------------------------------------
       Радиусы. Сайт почти без скруглений: базовая пластика — прямые углы
       и волосяные линии. Pill допустим только там, где разрешено в
       DESIGN_RULES.md (витринная CTA-кнопка, бейджи).
       -------------------------------------------------------------------- */
    --radius-xs: 4px;
    --radius-md: 12px;
    --radius-card: 24px;      /* крупные контейнеры: бенто-карточка каталога */
    --radius-pill: 999px;
    --radius-control: var(--radius-md); /* прямоугольные кнопки и поля: 12px как у Apple */
    /* Пузырь сообщения (Bubble): реплика от первого лица набирается формой,
       которую узнают по iMessage и Телеграму, а там скругление 18–20px. На
       --radius-md (12) пузырь читается карточкой, на --radius-pill — таблеткой,
       поэтому ступень своя и названа по месту, а не по размеру: другого
       крупного радиуса в системе нет и не нужно. */
    --radius-bubble: 20px;

    /* Высоты контролов: кнопка и поле одного размера — одной высоты. */
    --control-h-md: 48px;
    --control-h-lg: 56px;
    /* Floating fields перенесены из campus-cors без округления геометрии.
       Компонентные токены отдельны от типографики контента Pavlova: её
       текучая шкала крупнее и меняла бы исходные 13.5/18px на desktop. */
    --field-font: clamp(18px, 0.405vw + 16.313px, 18.5px);
    /* Поднявшаяся подпись — та же мета-подпись, что везде: --font-sm (16 → 24),
       исключений из минимального кегля не бывает (правило 1). Она текучая, а
       --field-font почти нет, поэтому геометрия ниже тоже считается от неё:
       подпись стоит на --space-1 от верха, а строка значения начинается ровно
       под ней. Числами эти отступы держать нельзя — на 1440 подпись выросла бы
       на значение. */
    --field-label-float-font: var(--font-sm);
    --field-label-top: var(--space-1);
    --field-padding-top: calc(var(--space-1) + var(--font-sm));
    --field-padding-bottom: 10px;
    --field-textarea-label-top: var(--space-2);
    --field-textarea-padding-top: calc(var(--space-2) + var(--font-sm) + var(--space-2));
    /* Минимальная тач-цель — правило доступности (44×44, зазор между соседними
       не меньше --space-2). Контролам хватает своей высоты (48/56), но у
       текстовой ссылки её нет: строка --font-sm даёт 24–32px, и цель нужно
       дотянуть min-height. Ниже 44 не опускать и как отступ не использовать —
       это порог, а не ступень шкалы. */
    --touch-target: 44px;
    --icon-size: 20px;
    --icon-size-sm: 16px;
    --icon-size-lg: 24px;     /* = --space-6: иконки живут на той же 8pt-шкале */
    /* Две верхние ступени — уже не интерфейсные иконки. xl (48 = --control-h-md,
       та же 8pt-шкала) — крупный глиф внутри кнопки: марка WhatsApp на
       CTA-кнопке. 2xl (96 = --space-9 * 1.5) — брендовая марка в плитке
       соцсетей (SocialCard), размер из макета. Обе заведены токенами, а не
       числами в компонентах, чтобы правиться в одном месте. */
    --icon-size-xl:  48px;                         /* крупный глиф в кнопке */
    --icon-size-2xl: calc(var(--space-9) * 1.5);   /* 96: марка соцсети */
    --bar-h: 2px;             /* толщина подчёркивания, полосок-индикаторов */
    /* Волосяной шов и рамки: сетки плиток, inset-input. Ровно 1px и под
       zoom страницы: getComputedStyle внутри зума показывает 0.769px, но это
       локальные координаты — на экране всё равно один CSS-пиксель. Поправку на
       зум не вводить, см. DESIGN_RULES.md, «Грабли». */
    --hairline: 1px;

    /* ---------------------------------------------------------------------
       Движение. Голый ease и сырые cubic-bezier в компонентах запрещены.
       -------------------------------------------------------------------- */
    --dur-instant: 0.06s;
    --dur-fast:    0.15s;
    --dur-base:    0.3s;      /* рисование кольца у ArrowLink */
    --ease-std:    cubic-bezier(0.4, 0, 0.2, 1);
    /* Пара кривых бургера, взята с campusagro вместе с иконкой: разгон на
       уходе из состояния (in) и торможение на приходе в него (out). Голый
       ease-in / ease-out в компонентах запрещён — вот их замена. */
    --ease-in-cubic:  cubic-bezier(0.55, 0.055, 0.675, 0.19);
    --ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);

    /* ---------------------------------------------------------------------
       Слои. Ступени редкие; «своё число побольше» не назначать. Осталось
       только то, что реально стоит на странице: подложки под шапкой.
       -------------------------------------------------------------------- */
    --z-below-2: -2;
    --z-below:   -1;
    --z-under-topbar: 100;  /* слой размытия под мобильным меню: выше контента, но ниже шапки (200 в site.css) — она остаётся резкой и кликабельной */
    --z-modal:   300;  /* модалка отзыва: выше фиксированной шапки, у которой в site.css z-index 200 */

    /* ---------------------------------------------------------------------
       ЦВЕТ — ПРИМИТИВЫ. Две шкалы 50–950 из Figma-кита заказчика. Это сырьё:
       у примитива нет роли, он не знает про тему и про контраст. Роль ему
       даёт семантика ниже.

       Правило жёсткое: var(--gray-*) и var(--pink-*) читаются ТОЛЬКО внутри
       этого файла. В компоненте примитив — ошибка (ловит bin/lint-tokens.sh):
       примитив в обеих темах один и тот же, переворачивается только
       семантика, поэтому --gray-600 в компоненте выпадет из тёмной темы так
       же, как голый hex.

       Про шкалы, по решению заказчика: ступень 50 у серого в макете
       пропущена — #fafafa подобран под ряд; тёмный конец серого плотный
       (600–950 идут почти вплотную) — это поверхности тёмной темы, им нужны
       мелкие шаги, а не ровная шкала.

       Чистый чёрный и чистый белый в шкалы не входят: это полюса
       (--text / --bg / --surface), см. семантику.
       -------------------------------------------------------------------- */
    --gray-50:  #fafafa;
    --gray-100: #f5f5f5;
    --gray-200: #d8d8d8;
    --gray-300: #b2b2b2;
    --gray-400: #8b8b8b;
    --gray-500: #646464;
    --gray-600: #3e3e3e;
    --gray-700: #373737;
    --gray-800: #2b2b2b;
    --gray-900: #252525;
    --gray-950: #191919;

    --pink-50:  #fff2fc;
    --pink-100: #ffccf2;
    --pink-200: #ff99e6;
    --pink-300: #ff66d9;
    --pink-400: #ff33cd;
    --pink-500: #ff00c0;
    --pink-600: #e500ad;
    --pink-700: #cc009a;
    --pink-800: #b20086;
    --pink-900: #990073;
    --pink-950: #66004d;

    /* ---------------------------------------------------------------------
       ЦВЕТ — светлая тема. Всё ниже переопределяется в .dark-theme-ui.
       -------------------------------------------------------------------- */

    /* Поверхности. --bg и --surface — полюс шкалы: чистый белый в --gray-*
       не входит, gray-50 (#fafafa) — уже подложка, а не бумага. */
    --bg:        #ffffff;
    --surface:   #ffffff;   /* карточки, поля */
    --surface-2: var(--gray-100);   /* мягкая подложка: сравнение, ховер строки */
    --surface-3: var(--gray-200);   /* заглушки под фото */
    /* Волосяная линия внутри блока: разделители программы, FAQ, линия под
       интро. Считается от текста, поэтому в тёмной теме переворачивается сама. */
    --divider:   color-mix(in srgb, var(--text) 16%, transparent);
    --divider-strong: color-mix(in srgb, var(--text) 24%, transparent);
    --border:    var(--divider);  /* граница объекта от фона: та же волосяная линия */

    /* Текст. --text-3 ≥ 4.5:1 на белом — иначе Lighthouse режет контраст
       (старый --color-gray_500 #a3a3a3 давал 2.5:1 и стоял на предупреждении
       о здоровье). Текст на тёмной заливке — --on-ink.
       --text — второй полюс: ближайшая ступень шкалы (gray-950 #191919)
       заметно светлее чёрного текста, поэтому остаётся литералом. */
    --text:       #0a0a0a;
    --text-2:     var(--gray-800);   /* 14.2:1 — второстепенный текст карточек */
    --text-3:     var(--gray-500);   /* 5.9:1 — подписи, надзаголовки */

    /* Бренд. Розовый #ff00c0 на белом даёт 3.5:1 — для текста мало, поэтому
       у него два лица: --brand для заливок, акцентов и крупного текста
       (≥ 24px: порог 3:1 проходит), --brand-fg — тёмнее, 5.2:1, для ссылок
       и мелких подписей розовым. */
    --brand:       var(--pink-500);
    --brand-hover: var(--pink-600);
    --brand-fg:    var(--brand);    /* розовый текст и ссылки — всегда основной бренд, тёмного варианта нет (решение заказчика 2026-09-16); токен оставлен алиасом */
    /* Текст поверх брендовой заливки. Белый на розовом — 3.5:1: годится
       только для крупного текста (≥ 24px; кнопки кита набраны 500). Мелкий
       текст на розовом не набирать. */
    --on-brand:    #ffffff;
    --brand-soft:  var(--pink-50);  /* розовая подложка: плашка CTA */
    /* Маркер под словом: розовая полоса, как фломастером (первая ссылка героя).
       Полупрозрачный розовый, а не ступень шкалы: полоса лежит ПОД глифами, и
       сквозь неё обязан читаться текст. Считается от --brand, поэтому в тёмной
       теме переворачивается вместе с ним. */
    --brand-marker: color-mix(in srgb, var(--brand) 20%, transparent);

    /* Инверсная пара: чёрная кнопка, тёмная колонка сравнения. Это тот же
       текст и та же поверхность, поменянные местами, поэтому алиасы —
       в тёмной теме пара переворачивается сама. */
    --ink:     var(--text);
    --on-ink:  var(--surface);

    /* Пастель тарифных карточек. Из шкал не берётся: розовая пастель кита
       холоднее pink-50, а лиловой, кремовой и мятной в шкалах нет вообще —
       это отдельные акцентные цвета, а не ступени. Живёт одинаково в обеих
       темах — это акцентные блоки, а не фон интерфейса; текст на них всегда
       --on-tint.
       --on-tint литералом, а не var(--text): в тёмной теме --text белый, а
       пастель остаётся светлой — текст на ней обязан остаться тёмным. */
    --tint-lilac: #eceffb;
    --tint-rose:  #fdeef1;
    --tint-cream: #fdfbe8;
    /* Ещё две ступени пастели — для плиток «кому подойдёт» (Tile variant="tint"):
       пять цветов, чтобы соседние плитки в сетке 3×2 не совпадали. */
    --tint-mint:  #e0f3ee;
    --tint-pink:  #fbe8f5;
    --on-tint:    #0a0a0a;   /* ≥ 16:1 на любой из пяти */
    /* Насыщенные основы адаптивной палитры плиток. Компонентные фоны ниже
       смешивают их только с текущей surface: прозрачность относится к фону,
       поэтому текст и фото не теряют насыщенность. Палитра opt-in и не
       меняет прежние --tint-* у тарифов и остальных секций. */
    --tint-base-lilac: #6673ff;
    --tint-base-rose:  #ff5277;
    --tint-base-cream: #e8b800;
    --tint-base-mint:  #14b88a;
    --tint-base-pink:  var(--pink-500);
    --tile-tint-adaptive-lilac: color-mix(in srgb, var(--tint-base-lilac) 12%, var(--surface));
    --tile-tint-adaptive-rose:  color-mix(in srgb, var(--tint-base-rose) 12%, var(--surface));
    --tile-tint-adaptive-cream: color-mix(in srgb, var(--tint-base-cream) 11%, var(--surface));
    --tile-tint-adaptive-mint:  color-mix(in srgb, var(--tint-base-mint) 13%, var(--surface));
    --tile-tint-adaptive-pink:  color-mix(in srgb, var(--tint-base-pink) 10%, var(--surface));
    --on-photo:   var(--on-brand);  /* подпись поверх фото: снимок тёмный в обеих темах, тень --text-shadow-photo */

    /* Статус. Зелёный один на всю систему: --ok = фирменный зелёный
       WhatsApp, от него же живёт --whatsapp. Второго зелёного в токенах
       быть не должно. Цвет светлый — белый на нём даёт 1.98:1, текст поверх
       заливки только тёмный (--ink, 10:1). */
    --ok: #25d366;

    /* Статусы форм платформы (/study: вход, регистрация, профиль, оплата).
       Заведены вместе с формами, ради которых их держали в бэклоге («жёлтого и
       красного статусов в токенах нет — заведём вместе с формой, которой они
       понадобятся, сразу с посчитанным контрастом», DESIGN_RULES.md).
       Роли разведены так же, как у бренда: заливка и рамка отдельно от текста.
         --danger      — рамка поля с ошибкой и полоса сообщения; белый на нём
                         5.1:1, на белом 5.1:1 — виден и как линия, и как заливка;
         --danger-fg   — текст ошибки: 7.2:1 на белом, 6.3:1 на --danger-soft;
         --danger-soft — подложка сообщения об ошибке (плашка Notice);
         --ok-fg       — текст успеха: 5.4:1 на белом, 5:1 на --ok-soft. Это не
                         второй зелёный системы, а текстовая роль того же
                         статуса: сам --ok светлый (белый на нём 1.98:1) и
                         мелким текстом не набирается;
         --ok-soft     — подложка сообщения об успехе.
       В шкалах --gray-*/--pink-* красного и зелёного нет и не будет: это
       статусы, а не ступени бренда. */
    --danger:      #d81b2f;
    --danger-fg:   #b3001b;
    --danger-soft: #fdecee;
    --ok-fg:       #0b7a3b;
    --ok-soft:     #eafaf0;

    /* Свой цвет лендинга челленджа «Тайна роскошной женщины»: бордо с обложки
       практикума (static/study/challenge/*). Это не ступень розового и не
       статус — отдельный акцент одной страницы, поэтому живёт токеном, а не
       хардкодом в разметке. Только заливка (кнопка, полоса цитаты, маркер):
       белый на нём 9.4:1, поэтому подпись кнопки — --on-brand. */
    --challenge: #8e0b25;

    /* Фирменный цвет WhatsApp: иконка на кнопке и ховер ссылки в шапке.
       Алиас --ok: по решению заказчика зелёный статуса и зелёный WhatsApp —
       один цвет. Поэтому --ok не переопределяется в тёмной теме: чужой
       бренд не перекрашивается. */
    --whatsapp: var(--ok);

    /* Чужие бренды: цвета марок соцсетей в плитках SocialCard. Значения — те,
       что стояли литералами в легаси-svg (src/lib/social-original.html), не
       «настоящие» из брендбуков: блок принят в этом виде, перекрашивать его
       нельзя. В тёмной теме не переопределяются — чужой бренд не
       перекрашивается, как и --whatsapp. Мелким текстом эти цвета не набирать:
       они только заливка марки. */
    --youtube:   #f61c0d;
    --instagram: var(--brand);   /* в легаси-svg марка перекрашена в розовый сайта: #ff00c0 — это ровно --brand (pink-500) */
    --vk:        #2787f5;
    --telegram:  #2787f5;        /* в легаси-svg телеграм залит той же синей, что ВКонтакте */

    /* Тени и подложки */
    --text-shadow-photo: 0 1px 12px rgba(0, 0, 0, 0.5);  /* подпись поверх фото */
    /* Тень карточки: четыре слоя с растущим размытием, как у iOS
       (progressive blur), тон от --on-tint, чтобы не серела на тонированных
       фонах. Ховер — широкая полупрозрачная рамка из бренда. */
    --shadow-card:
      0 1px 2px color-mix(in srgb, var(--on-tint) 4%, transparent),
      0 4px 8px color-mix(in srgb, var(--on-tint) 4%, transparent),
      0 12px 24px color-mix(in srgb, var(--on-tint) 6%, transparent),
      0 28px 56px color-mix(in srgb, var(--on-tint) 8%, transparent);
    --ring-card-hover: 0 0 0 var(--space-2) color-mix(in srgb, var(--brand) 22%, transparent);
    --scrim: color-mix(in srgb, var(--surface) 92%, transparent);        /* подложка шапки, начало */
    --scrim-2: color-mix(in srgb, var(--surface) 78%, transparent);
    --scrim-3: color-mix(in srgb, var(--surface) 42%, transparent);
    /* Подложка модалки. Считается от --on-tint — единственного тёмного токена,
       который не переворачивается в тёмной теме (он же держит текст на пастели):
       от --ink подложка в тёмной теме стала бы белой и слепила вокруг кадра. */
    --scrim-dark: color-mix(in srgb, var(--on-tint) 80%, transparent);
    --inset-input: inset 0 0 0 var(--hairline) var(--border);
    /* Размытие под открытым мобильным меню. Затемнения нет: слой
       .menu-backdrop (Header.svelte) полностью прозрачен и только размывает
       свой backdrop. Не filter на самом контенте: filter считается для всего
       элемента, а не для видимой части, и на длинной странице (5600px на
       /online) браузер растрирует и размывает её целиком — открытие дёргалось.
       backdrop-filter работает по площади вьюпорта и стоит копейки. Радиус —
       с campusagro, где подложка меню размыта так же. Отдельного токена под
       блюр шапки в системе нет: её три ступени (16 / 7 / 2) — не величина
       системы, а внутренняя раскладка одного эффекта, они живут в
       Header.svelte. */
    --blur-menu: 14px;
}

/* Тёмная тема: класс ставит скрипт в app.html на <html> и <body>. Только
   цвета — геометрия общая. Новый цветовой токен добавлять сразу сюда; алиасы
   (--border, --ink, --on-ink, --on-photo, --whatsapp) здесь не повторяются —
   они переворачиваются вместе со своими источниками. */
.dark-theme-ui {
    /* Полюса тёмной темы — чистый чёрный и чистый белый, в шкалы они не
       входят (gray-950 #191919 — уже поверхность). Остальное — примитивы. */
    --bg:        #000000;
    --surface:   #000000;
    --surface-2: var(--gray-950);
    --surface-3: var(--gray-900);

    --text:       #ffffff;
    --text-2:     var(--gray-200);   /* 14.7:1 на чёрном */
    --text-3:     var(--gray-300);   /* 9.9:1 на чёрном */
    /* Тени на чёрном не видны: карточку держит светлый ободок в 1px. */
    --shadow-card: 0 0 0 var(--hairline) color-mix(in srgb, #ffffff 12%, transparent);

    --brand-hover: var(--pink-400);
    --brand-fg:    var(--brand);     /* в тёмной теме тоже сам бренд: 6:1 на чёрном */
    /* Тёмная плашка CTA. Литерала #2a0a22 в шкалах нет и быть не может — это
       не ступень розового, а розовый, подмешанный в поверхность; так он и
       записан, и в тёмной теме считается от --surface. */
    --brand-soft:  color-mix(in srgb, var(--pink-500) 16%, var(--surface));

    /* Та же насыщенная основа глубже смешивается с чёрной surface: плитки
       остаются цветными, но текст наследует светлый --text тёмной темы. */
    --tile-tint-adaptive-lilac: color-mix(in srgb, var(--tint-base-lilac) 30%, var(--surface));
    --tile-tint-adaptive-rose:  color-mix(in srgb, var(--tint-base-rose) 28%, var(--surface));
    --tile-tint-adaptive-cream: color-mix(in srgb, var(--tint-base-cream) 25%, var(--surface));
    --tile-tint-adaptive-mint:  color-mix(in srgb, var(--tint-base-mint) 29%, var(--surface));
    --tile-tint-adaptive-pink:  color-mix(in srgb, var(--tint-base-pink) 27%, var(--surface));

    /* Статусы форм: на чёрном светлая половина шкалы. Красный и зелёный
       светлеют (7.6:1 и 12:1 на чёрном), подложки считаются от поверхности —
       литеральная пастель #fdecee на чёрном слепила бы. --danger-soft и
       --ok-soft остаются подложкой под текст --danger-fg / --ok-fg: пара на
       них даёт 7.7:1 и 9.3:1. */
    --danger:      #ff6b7a;
    --danger-fg:   #ff8f9b;
    --danger-soft: color-mix(in srgb, var(--danger) 20%, var(--surface));
    --ok-fg:       #4ade80;
    --ok-soft:     color-mix(in srgb, var(--ok) 18%, var(--surface));

    /* Бордо челленджа на чёрном фоне не читается заливкой (2.2:1), поэтому
       ступень светлее: 3.4:1 к фону — кнопка видна как объект, белая подпись
       на ней 6.3:1. */
    --challenge: #c0102f;
}

/* =============================================================================
   Базовые правила, которым нужен глобальный охват с первого дня.
   ========================================================================== */

/* Тач: без этого двойной тап по кнопке или ссылке приближает страницу, а
   первый тап идёт с задержкой ~300 мс, пока браузер ждёт второго.
   Именно точечно на контролах, а не touch-action: none на html — глобальный
   запрет масштабирования уже нарушение доступности. */
button, a, input, select, textarea, label, [role="button"] {
    touch-action: manipulation;
}

/* Минимальная насыщенность 500 (DESIGN_RULES.md, правило 1) — страховка от
   легаси-правил и браузерных UA styles. Форм-контролы по умолчанию не обязаны
   наследовать font-weight от body, поэтому перечислены явно; компонентные
   600/700 ниже по каскаду сохраняются. */
body, button, input, select, textarea { font-weight: var(--weight-medium); }

/* H1 — ЕДИНСТВЕННЫЙ стиль на весь сайт: новые страницы (h1), легаси-тема
   (.h1_like) и герои легаси-страниц (.header__xxl) набраны одинаково.
   Конфликтующие font-size / line-height / font-weight из site.css сняты,
   в компонентах эти три свойства у H1 не задаются — только margin. */
h1, .h1_like, .header__xxl {
    font-size: var(--font-display);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    font-weight: var(--weight-bold);
}

/* Гарнитура заголовков. Тело и контролы — системные (--font-ui), Navigo живёт
   только здесь. Список закрытый и полный: кроме h1–h6 в него входят легаси-
   классы-заголовки из site.css, которые раньше получали Navigo наследованием
   от html. Контейнеры в список не берём (.article_header — только padding,
   .article__header__desc — лид-абзац, это тело). Новый заголовочный класс
   заводить не нужно: набирать заголовки тегами h1–h6. */
h1, h2, h3, h4, h5, h6,
.h1_like, .h3_like,
.header__xxl,
.hero__links,                      /* мёртвый легаси-класс: витринное меню героя переехало в <Hero>, гарнитуру задаёт компонент */
.card__header, .card__title,
.article_preview__title, .article_preview__title_description,
.article_group_item__header,
.get_access__title,
.menu__overlay__title,
.soc_icon_title {
    font-family: var(--font-heading);
}

/* Якорные переходы не должны прятать цель под фиксированной шапкой. */
[id] { scroll-margin-top: calc(var(--topbar-h) + var(--space-5)); }
