/*
 * tokens.css — единственный источник правды по оформлению «Ясны Вижу».
 * Направление «Полночный архив», бриф — /DESIGN.md. Здесь только токены,
 * ни одного селектора кроме :root.
 *
 * ┌──────────────────────────────────────────────────────────────────┐
 * │  НОВАЯ СТРАНИЦА? Подключай общий CSS в <head> в этом порядке:      │
 * │                                                                    │
 * │    <link rel="preconnect" href="https://fonts.googleapis.com">     │
 * │    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> │
 * │    <link href="https://fonts.googleapis.com/css2?family=Fira+Sans+Extra+Condensed:wght@800&family=Lora:ital@0;1&family=Marck+Script&family=Nunito:wght@300;400;500;600;700&display=swap" rel="stylesheet"> │
 * │    <link rel="stylesheet" href="/assets/css/tokens.css?v=3">       │
 * │    <link rel="stylesheet" href="/assets/css/components.css?v=1">   │
 * │    <link rel="stylesheet" href="/assets/css/common.css?v=9">       │
 * │    <link rel="stylesheet" href="/assets/css/<страница>.css?v=N">   │
 * │                                                                    │
 * │  Порядок слоёв: tokens.css → components.css → common.css → страница│
 * │  Пользуйся var(--*) и .btn/.container/.card — :root не объявлять.  │
 * │  Поменял общий CSS — подними ?v= (сброс кэша).                     │
 * └──────────────────────────────────────────────────────────────────┘
 */

:root {
    /* ── Цвет: роль — часть значения (DESIGN.md §2) ──
     * Четыре слоя темноты, и они ЗНАЧАТ. Глубина делается тоном и рамкой,
     * теней нет нигде: box-shadow во всём приложении запрещён.
     * Честное ограничение: витрина к холсту даёт контраст 1.19, чистый чёрный — 1.41.
     * Тоном границу объекта показать физически нельзя, поэтому тон — атмосфера,
     * а не информация. Границу несёт экспонат, заголовок или золотое действие. */
    --hall:   #000000;   /* зал: ТОЛЬКО экран гадания и шапка результата */
    --case:   #0d0d10;  /* витрина: карточки, плитки услуг, поверхность с экспонатом */
    --canvas: #131316;  /* холст: фон всех остальных экранов */
    --edge:   #08080a;  /* структурная граница: стык крупных зон */

    /* Рамки. Обе строго 1 px — толще не бывает, цветных не бывает. */
    --hair:   #343538;   /* волосяная: край витрины с экспонатом, разделители. Контраст 1.21 — атмосфера */
    --border: #6a6b71;   /* видимая: ТОЛЬКО нажимаемый объект без экспоната внутри.
                          * Контраст 2.8 — порог куплен глазами Кати 02.08.2026 на экране-пробе.
                          * Вниз не двигать никогда: гейт, горящий зелёным на невидимой линии,
                          * хуже отсутствующего гейта. Вверх (4.4 = #8c8c8d) — можно. */

    --ink:    #ffffff;   /* текст основной: заголовки, названия услуг. Контраст к холсту 14.9 */
    --body:   #a8afb7;   /* текст тела: описания, этикетки, вторичное. 6.7 к холсту, 8.0 к витрине */
    --mark:   #8c8c8d;   /* метка: подписи полей этикетки, даты в архиве. 5.3 к витрине */

    /* Золото — это РОЛЬ ДЕЙСТВИЯ, а не украшение. Одна залитая кнопка на экран
     * и метка «бесплатно». Фоном блока, цветом ссылки, цветом цены и рамкой — нельзя. */
    --gold:    #d4a574;
    --on-gold: #000000; /* подпись внутри золотой кнопки, контраст 9.4 */

    /* СВЕТ — это не второй акцент, а то же тепло в другой роли (выбор Кати 17.08.2026).
     * Золото КРАСИТ (залитая кнопка, метка «бесплатно»), свет СВЕТИТ и больше ничего:
     * свечение вокруг экспоната, первое слово заголовка, цена в этикетке.
     * Заливкой блока, рамкой и фоном кнопки свет быть не может — это роль золота.
     * Оттенок держится в семье золота (проверяется тестом), чтобы «светом» через
     * полгода не оказался синий или зелёный. Компоненты — для прозрачных свечений. */
    --light:     #ffb15e;
    --light-rgb: 255, 177, 94;

    /* Опасное действие (удаление данных). Единственный хроматический цвет кроме золота,
     * и только на подтверждении удаления — не в оформлении. */
    --danger-rgb: 220, 120, 110;
    --danger-border-rgb: 180, 80, 70;

    /* ── Шрифты ──
     * Заголовок собирается из ДВУХ гарнитур сразу (выбор Кати 17.08.2026 на пробе
     * из трёх пар): первое слово рукописным светом, остальное — узким тяжёлым капсом.
     * Приём принесла сама Катя примером Atziluth + Maratype; тех гарнитур взять
     * нельзя — у Bebas Neue и Anton кириллицы нет вообще (проверено запросом
     * к Google Fonts 17.08.2026), поэтому взяты ближайшие с кириллицей.
     * Прежний ход «прямой сериф + курсивный хвост» снят: он стоял во ВСЕХ шести
     * заголовках лендинга подряд и оттого читался не как приём, а как лекало.
     * Lora осталась ровно за тем, ради чего бралась, — за голосом Ясны. */
    --font-script:  'Marck Script', cursive;                    /* первое слово заголовка, светом */
    --font-display: 'Fira Sans Extra Condensed', sans-serif;    /* хвост заголовка и названия — капсом */
    --font-voice:   'Lora', Georgia, serif;                     /* голос Ясны: сериф, всегда курсивом */
    --font-body:    'Nunito', system-ui, sans-serif;

    /* ── Шкала кегля (SSoT размеров) ──
     * Перепад между заголовком и текстом резкий и намеренный: 48 против 16 — втрое.
     * Промежуточных ступеней в макете нет, это приём источника.
     *
     * Пол clamp = реальный размер на телефоне: там clamp почти всегда упирается вниз.
     * Ниже 16 px читаемый текст не опускаем — в июле 2026 Катя сказала «всё мелко»,
     * и занижать его ради «перепада» значит повторить ту же ошибку (DESIGN.md §3).
     * 12–13 px живёт только на этикетках и метках, которые сканируют, а не читают.
     *
     * --ui-scale: компенсация масштаба шрифта, который навязывает оболочка.
     * Замерено на Android: VK рисует 16px как 13.76px, Telegram — как 16px.
     * Значение подставляет ui-scale.js; 1 — если скрипт не отработал. */
    --ui-scale: 1;

    --fs-xs:   calc(clamp(12px, 3.0vw, 13px) * var(--ui-scale));   /* метка, подпись поля этикетки */
    --fs-sm:   calc(clamp(14px, 3.5vw, 15px) * var(--ui-scale));   /* вторичный текст, лейблы */
    --fs-ui:   calc(clamp(15px, 3.8vw, 16px) * var(--ui-scale));   /* кнопки, пункты меню, названия услуг */
    --fs-base: calc(clamp(16px, 4.0vw, 17px) * var(--ui-scale));   /* текст, который ЧИТАЮТ: гадания, Ясна */
    --fs-lg:   calc(clamp(18px, 4.6vw, 20px) * var(--ui-scale));   /* лид-абзац, название экспоната */
    --fs-h3:   calc(clamp(20px, 5.2vw, 23px) * var(--ui-scale));   /* подзаголовок */
    --fs-h2:   calc(clamp(30px, 8.0vw, 36px) * var(--ui-scale));   /* заголовок раздела */
    --fs-h1:   calc(clamp(40px, 12.5vw, 48px) * var(--ui-scale));  /* заголовок экрана — тот самый перепад */

    /* Обложка лендинга — единственной страницы, которую смотрят с монитора, а не с
     * телефона в оболочке. Там 48px читается как подзаголовок: колонка втрое шире
     * экранной (1120 против 520). Внутри приложения этой ступени быть не должно. */
    --fs-display: calc(clamp(44px, 9vw, 84px) * var(--ui-scale));

    /* ── Интерлиньяж ── */
    --lh-tight:   1.05;   /* заголовки серифом: крупный кегль дышит сам */
    --lh-normal:  1.45;   /* компактный UI-текст */
    --lh-body:    1.7;    /* длинные тексты (гадания, Лила) */

    /* ── Отступы ── */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 10px;
    --space-4: 12px;
    --space-5: 16px;
    --space-6: 24px;

    /* ── Радиус (DESIGN.md §4): плитка 20 · витрина 28 · пилюля · мелкое 4 ── */
    --radius-sm:   4px;
    --radius-tile: 20px;
    --radius-case: 28px;
    --radius-pill: 9999px;

    /* ── Движение ──
     * Только цвет и прозрачность за 0.2 с. Никаких transform, пружин, отскоков
     * и изменения размера при нажатии. Исключение — вытягивание карты и бросок
     * кубика в Лиле: это событие, а не интерфейс, и живёт оно в своих файлах. */
    --transition: color .2s ease, background-color .2s ease, border-color .2s ease, opacity .2s ease;

    /* ── Раскладка ── */
    --container: 520px;
    --gutter: clamp(24px, 6vw, 40px);

    /* Блока совместимости со старыми именами («--bg-deep», «--gold-border»,
     * «--shadow-*» и прочей тёмно-золотой эпохой) здесь БОЛЬШЕ НЕТ: 02.08.2026
     * все 327 обращений к ним переписаны на роли, и блок снят в тот же день,
     * а не оставлен «на всякий случай». Тест tests/test_design_tokens.py держит
     * это нулём: вернувшееся старое имя уронит прогон. */
}
