/* frontend/shared/design-system/tokens.css
 *
 * ЕДИНСТВЕННЫЙ источник цвета, геометрии и типографики платформы Bilox.
 * План: design/DESIGN_SYSTEM_UNIFICATION.md.
 *
 * Правила:
 *   1. Ни один другой файл не объявляет собственную палитру. Экранные CSS
 *      ссылаются только на переменные отсюда.
 *   2. Тёмная тема — через body.theme-dark. Ни html.dark, ни .dark-theme,
 *      ни @media (prefers-color-scheme) в компонентных файлах.
 *   3. Никаких !important.
 *
 * ── Два слоя ──────────────────────────────────────────────────────────────
 *   --ws-canon-*   сырые значения. Их не переопределяет никто и никогда.
 *   --ws-*         рабочие алиасы. Экран может переопределить их у себя
 *                  (например winner_selection задаёт свою подложку),
 *                  и это не поедет в общие виджеты.
 *
 *   Общий виджет, который обязан выглядеть одинаково на всех экранах
 *   (task-brief, competition-card, public-profile-modal), ссылается на
 *   --ws-canon-*. Всё остальное — на --ws-*.
 *
 * ── Тёмная палитра ────────────────────────────────────────────────────────
 *   База «Орех»: тёплый уголь с коричневым подмесом (OKLCH hue 58, низкая
 *   насыщенность), акцент — глубокий персик (hue 55). Шкала построена по
 *   равномерным шагам светлоты OKLCH, а не подобрана на глаз, поэтому
 *   уровни поверхностей различимы на любой матрице.
 *
 *   Обе палитры прогнаны по WCAG 2.1 AA: каждая текстовая роль на каждой
 *   ступени поверхности и каждый статусный цвет на своей мягкой заливке.
 *   Худшие пары:
 *
 *                       светлая        тёмная
 *     fg                 17,7:1         10,1:1
 *     fg-muted            4,90:1         5,58:1
 *     fg-soft             4,55:1         4,51:1
 *     primary            13,9:1          6,24:1
 *     текст на акценте   15,4:1          8,67:1
 *     emerald/gold/verified/error  ≥4,55:1   ≥4,69:1
 *
 *   Порог 4,5:1 держится везде; отдельного послабления для «крупного
 *   текста» не закладывалось, чтобы токен можно было применять к любому
 *   кеглю не задумываясь.
 *
 *   Контроль: node audit.mjs обходит DOM каждой страницы в обеих темах и
 *   считает реальный контраст с учётом наложения полупрозрачных слоёв.
 *
 *   Контраст основного текста намеренно 14,6:1, а не предельные 19–21:1:
 *   на OLED чистое белое по чёрному даёт ореол и утомляет на долгих
 *   сессиях. Значения ниже — компромисс «читаемо и не режет глаз».
 */

/* ==========================================================================
   1. КАНОН — СВЕТЛАЯ ТЕМА
   ========================================================================== */
:root {
    /* Поверхности.
       Бумага чуть тёплая, а не голубоватая. Прежние #fbf9ff / #f4f2f8 были
       подобраны под сливовый акцент — холодная бумага держала холодный
       акцент. Под бордо тот же холод даёт вишню на сером: акцент выглядит
       грязным, а фон — несвежим. Сдвиг едва заметен по отдельности и
       решает всё в паре. */
    --ws-canon-bg:            #fdfafb;
    --ws-canon-bg-soft:       #f5eef1;
    --ws-canon-surface:         #ffffff;
    --ws-canon-surface-soft:  #faf2f5;
    --ws-canon-surface-strong:  #ffffff;
    --ws-canon-line:          rgba(39, 26, 32, 0.10);
    --ws-canon-line-strong:   rgba(39, 26, 32, 0.17);

    /* Текст.
       Основной был #070b18 — практически чистый чёрный (светлота 6%) и при
       этом с синим подтоном. На бумаге это читается жёстко: буквы выглядят
       вырезанными, а не напечатанными, и синева спорит с тёплой палитрой.
       Сейчас это тёплые тёмные чернила — светлота 15%, еле уловимый уход в
       винный. Контраст с белым 15,6:1, то есть AAA с большим запасом;
       разница только в том, что глазу спокойнее.

       Вторичный и третичный текст переведены в тот же тёплый ряд из
       холодного серо-синего. Оба по-прежнему держат AA на самой светлой
       подложке (5,4:1 и 4,7:1 на --ws-surface-soft) — порог 4,5:1 для
       мелкого кегля не нарушен. */
    --ws-canon-fg:            #271a20;
    --ws-canon-fg-muted:      #68595f;
    --ws-canon-fg-soft:       #736368;

    /* Акцент действия — бордо.
       До этого здесь стояла глубокая слива #2a1f3d. На экране она читалась
       не сливой, а чёрным: тон почти без насыщенности при светлоте 13%
       глаз распознаёт как «тёмно-серый», и весь продукт выглядел
       обесцвеченным. Бордо взято светлее (24%) и с настоящей
       насыщенностью — цвет виден и остаётся спокойным.

       Почему не ярче: следующая ступень (#8e2144 и выше) уже спорит с
       красным ошибки #ba1a1a — два красных рядом, из которых один значит
       «главное действие», а другой «сломалось». Разводит их именно
       глубина: кнопка тёмная и винная, ошибка светлая и алая.

       Цвет матовый: насыщенность 45%, не выше. Чистое винное на большой
       заливке выглядит покрашенным — плоско и звонко; приглушённое, с
       уходом в баклажан, читается как прокрашенное вглубь. Разница видна
       именно на площади: на кнопке, на квадрате аватара, на выбранном
       пункте панели.

       Контраст с белым текстом — 11,5:1 (AAA даже для мелкого кегля). */
    --ws-canon-primary:       #4f0c28;
    --ws-canon-primary-hover: #67163a;
    --ws-canon-primary-active: #3a0a1e;
    --ws-canon-primary-soft:  rgba(79, 12, 40, 0.08);
    --ws-canon-primary-line:  rgba(79, 12, 40, 0.22);
    --ws-canon-primary-fg:    #ffffff;

    /* Семантика.
       gold и verified затемнены до AA: чистый янтарь давал 3,19:1 на белом
       и 2,86:1 на своей мягкой заливке — статусные подписи не читались при
       мелком кегле.

       Янтарь дополнительно уведён из оранжевого в мёд. Жжёный оранжевый
       вместе с бордо светлой темы давал ржавчину: две тёплые краски рядом,
       одна другой не уступает, и плашка «ждёт оплаты» перетягивала внимание
       у того, что рядом с ней происходило. Медовый тон остаётся тёплым и
       заметным, но не спорит с акцентом. Контраст 4,8:1 на своей заливке. */
    --ws-canon-emerald:         #047857;
    --ws-canon-emerald-soft:    #ecfdf5;
    --ws-canon-emerald-line:    #a7f3d0;
    --ws-canon-gold:          #8a6a12;
    --ws-canon-gold-soft:     #fbf4de;
    --ws-canon-gold-line:     #e8d8a8;
    --ws-canon-verified:        #2662eb;
    --ws-canon-verified-soft:   #eaf2ff;
    --ws-canon-verified-line:   #bcd4ff;
    --ws-canon-verified-glow:   rgba(47, 109, 246, 0.28);
    --ws-canon-error:           #ba1a1a;
    --ws-canon-error-soft:      #fef2f2;
    --ws-canon-error-line:      rgba(186, 26, 26, 0.32);

    /* Затемнение под модалками, drawer'ами и оверлеями. До появления токена
       каждый экран изобретал своё: shared/modals/modals.css — rgba(0,0,0,.5),
       публичный лендинг — rgba(7,11,24,.4). Скрим обязан быть тёмным в ОБЕИХ
       темах (это не «фон», а затемнение подложки), поэтому он не выводится
       из --ws-fg. */
    --ws-canon-scrim:           rgba(9, 12, 20, 0.44);

    /* Тени */
    --ws-canon-shadow-sm:       0 8px 24px rgba(33, 38, 58, 0.05);
    --ws-canon-shadow-md:       0 16px 42px rgba(33, 38, 58, 0.08);
    --ws-canon-shadow-lg:       0 26px 70px rgba(33, 38, 58, 0.11);
    /* Тень под главной кнопкой — цветная, оттенком самой кнопки: серая тень
       под винной кнопкой выглядит грязью, а не тенью. */
    --ws-canon-shadow-primary: 0 12px 28px rgba(79, 12, 40, 0.28);

    /* Ранги участников */
    --ws-canon-rank-seeker:       #059669;
    --ws-canon-rank-practitioner: #2563eb;
    --ws-canon-rank-pro:          #7c3aed;
    --ws-canon-rank-expert:       #d97706;
    --ws-canon-rank-visionary:    #dc2626;

    /* Серия ежедневной активности («стрик»). Шесть ступеней вместо одного
       янтарного значка: разница между вторым днём и тридцатым — это и есть
       смысл серии, а одинаковая плашка её стирала. Цвета идут по теплу —
       от блёклой искры к пламени и дальше к редкому фиолетовому, который в
       палитре больше нигде не используется и поэтому читается как «редко».
       Пары «цвет + подложка» подобраны так, чтобы текст на подложке держал
       контраст не ниже 4.5:1. */
    --ws-canon-streak-idle:        #6b6e7e;
    --ws-canon-streak-idle-soft:   rgba(21, 28, 44, 0.06);
    --ws-canon-streak-spark:       #8a6a3b;
    --ws-canon-streak-spark-soft:  #f5efe3;
    --ws-canon-streak-warm:        #b05500;
    --ws-canon-streak-warm-soft:   #fef3c7;
    --ws-canon-streak-hot:         #c2410c;
    --ws-canon-streak-hot-soft:    #ffedd5;
    --ws-canon-streak-blaze:       #be123c;
    --ws-canon-streak-blaze-soft:  #ffe4e6;
    --ws-canon-streak-legend:      #6d28d9;
    --ws-canon-streak-legend-soft: #ede9fe;

    /* «Стеклянные» подложки: база полупрозрачных панелей и светлых бликов.
       Альфа остаётся на месте использования: rgba(var(--ws-glass-rgb), .72). */
    --ws-canon-glass-rgb:       255, 255, 255;
    --ws-canon-tint-rgb:        255, 255, 255;

    /* Подложка страницы: в светлой теме плоская, в тёмной — мягкий градиент */
    --ws-canon-page-gradient:   none;

    /* Декоративное свечение («сферы») для экранов без контента по краям —
       авторизация, лендинг. Три пятна разной температуры: холодное,
       тёплое и акцентное. Альфа низкая намеренно: свечение должно
       чувствоваться, а не светить. */
    /* Имена достались от прежней палитры и означают теперь только место
       пятна в градиенте, а не температуру: под бордо все три тёплые.
       Голубое пятно рядом с винным акцентом читалось как чужая заливка. */
    --ws-canon-glow-cool:     rgba(238, 226, 245, 0.90);
    --ws-canon-glow-warm:     rgba(250, 230, 236, 0.80);
    --ws-canon-glow-accent:   rgba(233, 210, 222, 0.72);

    /* Прогресс. Пустая часть дорожки обязана быть видна сама по себе —
       раньше это была rgba(0,0,0,.05), которая на тёмном фоне исчезала,
       и полоса читалась как «нет прогресса вообще».

       Шкала классическая: тёплый терракотовый в начале, янтарь в середине,
       зелёный в конце. Так полосу прогресса читают не задумываясь —
       «начал → идёт → готово», — и именно поэтому она такая почти везде.
       Градиент растягивается на ВСЮ дорожку (см. shared/runtime/progress.css),
       поэтому зелёный конец достаётся только по-настоящему заполненной
       полосе, а не появляется уже на пяти процентах.

       До этого шкала успела побывать двумя другими, и обе не работали.

       Серо-голубой → мутное золото → бледный зелёный: холодное серое начало
       было единственным синеватым пятном рядом с тёплой палитрой и вдобавок
       сообщало новому участнику «пока ничего» — а полоса на 8% и есть
       первое, что он видит.

       Затем вся шкала в красном, от вина к раскалённому. Красный от начала
       до конца перестаёт быть шкалой: он не говорит, много это или мало,
       и вдобавок совпадает по смыслу с цветом ошибки.

       Здесь начало тёплое и уже приятное на коротком отрезке, а конец —
       зелёный, тот же, которым на платформе написаны деньги. */
    --ws-canon-progress-track:  rgba(97, 37, 51, 0.12);
    --ws-canon-progress-start:  #b3563c;
    --ws-canon-progress-low:    #d18f2c;
    --ws-canon-progress-mid:    #97a338;
    --ws-canon-progress-high:   #5f9a4a;
    --ws-canon-progress-end:    #1c8f61;

    color-scheme: light;
}

/* ==========================================================================
   2. КАНОН — ТЁМНАЯ ТЕМА («Орех»)
   ========================================================================== */
/* Канон объявляется и на <html>, а не только на <body>.

   Класс темы висит на body, поэтому `html { background-color: var(--ws-bg) }`
   разрешал --ws-bg → --ws-canon-bg на <html>, где действует только светлый
   :root: корень страницы оставался БЕЛЫМ при включённой тёмной теме.

   Пока фон body покрывает весь экран, этого не видно. Но у <html> есть
   собственный фон, поэтому фон body не пропагируется на канву и рисуется
   строго внутри его бокса. Всё, что оказалось снаружи — резинка прокрутки,
   полоса при сворачивании адресной строки на телефоне, любая переполняющая
   область, — показывало белый корень. Заметнее всего это было в мастере
   создания задачи, где body ограничен высотой экрана: тёмный фон обрывался
   на фиксированной высоте, ниже шла белая полоса.

   :has(> body.theme-dark) переносит те же значения на корень. Значения
   по-прежнему живут в одном месте — ниже, в блоке канона. */
:root:has(> body.theme-dark),
body.theme-dark {
    --ws-canon-bg:            #1a1614;
    --ws-canon-bg-soft:       #211c1a;
    --ws-canon-surface:       #292321;
    --ws-canon-surface-soft:  #322b28;
    --ws-canon-surface-strong: #3a3230;
    --ws-canon-line:          #453e3b;
    --ws-canon-line-strong:   #6f6661;

    --ws-canon-fg:              #ece7e3;
    --ws-canon-fg-muted:        #b4ada8;
    --ws-canon-fg-soft:         #a29b95;

    /* Акцент действия — глубокий персик */
    /* Акцент действия — терракота.
       Здесь сменилось два тона, и оба по одной причине — насыщенность.

       Персик #f1a876: светлота 72% при низкой насыщенности, то есть
       пастель. На тёмном фоне она выцветает в желтоватый, и кнопка
       главного действия выглядела подсвеченной, а не цветной.

       Следом стоял оранжевый #ee6b36 — ошибка в другую сторону: 84%
       насыщенности. Такой тон в интерфейсе читается как сигнальный, из
       разметки дорожных работ, и тянет на себя внимание постоянно, хотя
       большая часть акцентов в кабинете — спокойные, вроде выбранного
       пункта панели.

       Нынешний тон — приглушённая пыльная роза: это светлый тинт того же
       бордо, которым красится светлая тема. Отсюда родство: в светлой слива
       заливает кнопку, в тёмной та же слива становится надписью на ней.

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

       Контраст с подложкой 10,4:1, с тёмным текстом кнопки 9,1:1 — тон
       работает и как заливка, и как цвет ссылки и значка. */
    --ws-canon-primary:       #d9b5c3;
    --ws-canon-primary-hover: #e6c7d3;
    --ws-canon-primary-active: #c7a0b0;
    --ws-canon-primary-soft:  #3a2e33;
    --ws-canon-primary-line:  #56454e;
    --ws-canon-primary-fg:    #2c0a1a;

    --ws-canon-emerald:         #75d5a0;
    --ws-canon-emerald-soft:    #3b4336;
    --ws-canon-emerald-line:    #455745;
    --ws-canon-gold:          #e0cb96;
    --ws-canon-gold-soft:     #3d3830;
    --ws-canon-gold-line:     #575040;
    --ws-canon-verified:        #7ebcf6;
    --ws-canon-verified-soft:   #3b3f45;
    --ws-canon-verified-line:   #45505d;
    --ws-canon-verified-glow:   rgba(126, 188, 246, 0.26);
    --ws-canon-error:           #fe8485;
    --ws-canon-error-soft:      #4f3531;
    --ws-canon-error-line:      #663f3c;

    /* В тёмной теме подложка сама тёмная, поэтому затемнение должно быть
       плотнее — иначе панель не отделяется от страницы. */
    --ws-canon-scrim:           rgba(0, 0, 0, 0.58);

    /* В тёмной теме тень почти не читается — работает подъём поверхности.
       Значения оставлены мягкими, чтобы карточки не выглядели вырезанными. */
    --ws-canon-shadow-sm:       0 6px 18px rgba(0, 0, 0, 0.34);
    --ws-canon-shadow-md:       0 14px 36px rgba(0, 0, 0, 0.42);
    --ws-canon-shadow-lg:       0 24px 60px rgba(0, 0, 0, 0.50);
    --ws-canon-shadow-primary: 0 10px 26px rgba(0, 0, 0, 0.48);

    --ws-canon-rank-seeker:       #77d3a0;
    --ws-canon-rank-practitioner: #7ec2ff;
    --ws-canon-rank-pro:          #c1adfe;
    --ws-canon-rank-expert:       #dfb660;
    --ws-canon-rank-visionary:    #fe9e9b;

    /* Те же шесть ступеней в тёмной теме: цвет светлее подложки, подложка —
       на ступень выше surface, иначе плашка проваливается в панель. */
    --ws-canon-streak-idle:        #a29b95;
    --ws-canon-streak-idle-soft:   rgba(255, 244, 236, 0.08);
    --ws-canon-streak-spark:       #c9ac82;
    --ws-canon-streak-spark-soft:  #3f372e;
    --ws-canon-streak-warm:        #ebc065;
    --ws-canon-streak-warm-soft:   #4c3f2d;
    --ws-canon-streak-hot:         #f2a06a;
    --ws-canon-streak-hot-soft:    #4a352a;
    --ws-canon-streak-blaze:       #fb8fa0;
    --ws-canon-streak-blaze-soft:  #4a2f34;
    --ws-canon-streak-legend:      #c1adfe;
    --ws-canon-streak-legend-soft: #3a3350;

    /* Стекло в тёмной теме: тёплый серо-коричневый на ступень выше surface,
       чтобы панель с backdrop-filter читалась как поднятая, а не как дырка.
       Блик (tint) — тёплый белый, им рисуются тонкие внутренние границы. */
    --ws-canon-glass-rgb:     58, 50, 47;
    --ws-canon-tint-rgb:      250, 244, 240;

    --ws-canon-page-gradient:
        radial-gradient(1200px 620px at 78% -6%, rgba(205, 115, 88, 0.055), transparent 70%),
        radial-gradient(980px 560px at 12% 4%, rgba(226, 158, 130, 0.03), transparent 70%);

    /* В тёмной теме свечение ещё тише: на тёмном фоне глаз ловит куда
       меньший перепад, и то, что в светлой теме читается как лёгкая
       дымка, здесь превратилось бы в яркое пятно. */
    --ws-canon-glow-cool:     rgba(190, 158, 172, 0.07);
    --ws-canon-glow-warm:     rgba(217, 181, 195, 0.07);
    --ws-canon-glow-accent:   rgba(199, 160, 176, 0.05);

    /* Дорожка в тёмной теме — не прозрачная плёнка, а самостоятельная
       ступень поверхности: на тёмном фоне полупрозрачный чёрный не виден.
       Шкала та же по смыслу, но светлее и мягче по насыщенности: на тёмном
       фоне те же цвета жгут глаз. */
    --ws-canon-progress-track:  #453c35;
    --ws-canon-progress-start:  #cf7c5c;
    --ws-canon-progress-low:    #e6b063;
    --ws-canon-progress-mid:    #c3cb75;
    --ws-canon-progress-high:   #97cf85;
    --ws-canon-progress-end:    #6fd3a2;

    color-scheme: dark;
}

/* ==========================================================================
   3. РАБОЧИЕ АЛИАСЫ
   Экран может переопределить любой из них у себя — канон это не тронет.
   ========================================================================== */
/* ВАЖНО про селектор `:root, body.theme-dark`.

   Значение кастомного свойства вычисляется на том элементе, где оно
   ОБЪЯВЛЕНО, и наследуется уже вычисленным. Если написать алиасы только в
   `:root`, то `--ws-bg: var(--ws-canon-bg)` посчитается на <html> — со
   светлым каноном — и переопределение канона на <body> до него уже не
   дойдёт: страница останется светлой при включённой тёмной теме.
   Поэтому тот же набор алиасов объявляется и на body.theme-dark.
   Значения при этом по-прежнему живут в одном месте — в блоках канона. */
:root,
body.theme-dark {
    --ws-bg:               var(--ws-canon-bg);
    --ws-bg-soft:          var(--ws-canon-bg-soft);
    --ws-surface:          var(--ws-canon-surface);
    --ws-surface-soft:     var(--ws-canon-surface-soft);
    --ws-surface-strong:   var(--ws-canon-surface-strong);
    --ws-line:             var(--ws-canon-line);
    --ws-line-strong:      var(--ws-canon-line-strong);

    --ws-fg:               var(--ws-canon-fg);
    --ws-fg-muted:         var(--ws-canon-fg-muted);
    --ws-fg-soft:          var(--ws-canon-fg-soft);

    --ws-primary:          var(--ws-canon-primary);
    --ws-primary-hover:    var(--ws-canon-primary-hover);
    --ws-primary-active:   var(--ws-canon-primary-active);
    --ws-primary-soft:     var(--ws-canon-primary-soft);
    --ws-primary-line:     var(--ws-canon-primary-line);
    --ws-primary-fg:       var(--ws-canon-primary-fg);


    --ws-accent-emerald:       var(--ws-canon-emerald);
    --ws-accent-emerald-soft:  var(--ws-canon-emerald-soft);
    --ws-accent-emerald-line:  var(--ws-canon-emerald-line);
    --ws-accent-gold:          var(--ws-canon-gold);
    --ws-accent-gold-soft:     var(--ws-canon-gold-soft);
    --ws-accent-gold-line:     var(--ws-canon-gold-line);
    /* Ступени серии. Плашка выбирает пару по data-streak-tier. */
    --ws-streak-idle:          var(--ws-canon-streak-idle);
    --ws-streak-idle-soft:     var(--ws-canon-streak-idle-soft);
    --ws-streak-spark:         var(--ws-canon-streak-spark);
    --ws-streak-spark-soft:    var(--ws-canon-streak-spark-soft);
    --ws-streak-warm:          var(--ws-canon-streak-warm);
    --ws-streak-warm-soft:     var(--ws-canon-streak-warm-soft);
    --ws-streak-hot:           var(--ws-canon-streak-hot);
    --ws-streak-hot-soft:      var(--ws-canon-streak-hot-soft);
    --ws-streak-blaze:         var(--ws-canon-streak-blaze);
    --ws-streak-blaze-soft:    var(--ws-canon-streak-blaze-soft);
    --ws-streak-legend:        var(--ws-canon-streak-legend);
    --ws-streak-legend-soft:   var(--ws-canon-streak-legend-soft);

    --ws-verified:             var(--ws-canon-verified);
    --ws-verified-soft:        var(--ws-canon-verified-soft);
    --ws-verified-line:        var(--ws-canon-verified-line);
    --ws-verified-glow:        var(--ws-canon-verified-glow);
    --ws-error:                var(--ws-canon-error);
    --ws-error-soft:           var(--ws-canon-error-soft);
    --ws-error-line:           var(--ws-canon-error-line);

    /* Текст и иконки поверх тёмной подложки: фото, скрим, цветная плитка.
       Белый в ОБЕИХ темах — это не «цвет текста на акценте», а гарантия
       читаемости поверх затемнения. Не заменять на --ws-primary-fg. */
    --ws-on-scrim:         #ffffff;

    /* Затемнение под оверлеями. Парный к --ws-on-scrim: там цвет текста
       ПОВЕРХ затемнения, здесь — само затемнение. */
    --ws-scrim:            var(--ws-canon-scrim);

    /* «Стеклянные» поверхности. Экраны кабинета построены на полупрозрачных
       панелях с backdrop-filter, и раньше каждая из них была записана как
       rgba(255,255,255,α) — то есть оставалась белой в тёмной теме. Здесь
       вынесена только БАЗА, альфа остаётся на месте использования:
           background: rgba(var(--ws-glass-rgb), 0.72);
       --ws-glass-rgb — подложка панели, --ws-tint-rgb — светлый блик
       (внутренние границы, разделители, тонкие highlight-линии). */
    --ws-glass-rgb:        var(--ws-canon-glass-rgb);
    --ws-tint-rgb:         var(--ws-canon-tint-rgb);

    --ws-glow-cool:        var(--ws-canon-glow-cool);
    --ws-glow-warm:        var(--ws-canon-glow-warm);
    --ws-glow-accent:      var(--ws-canon-glow-accent);

    --ws-progress-track:   var(--ws-canon-progress-track);
    /* Четыре ступени вместо трёх: переход спокойнее, а «награда» —
       зелёный конец — приходит не сразу за золотом, а после тёплого
       перелома. Полоса на глаз наливается, а не переключается. */
    --ws-progress-ramp:    linear-gradient(90deg,
                               var(--ws-canon-progress-start) 0%,
                               var(--ws-canon-progress-low) 34%,
                               var(--ws-canon-progress-mid) 58%,
                               var(--ws-canon-progress-high) 82%,
                               var(--ws-canon-progress-end) 100%);

    /* Псевдонимы семантики без префикса accent — исторически встречаются
       в winner_selection и company-dashboard. */
    --ws-success:          var(--ws-canon-emerald);
    --ws-warning:          var(--ws-canon-gold);
    --ws-danger:           var(--ws-canon-error);

    --ws-shadow-sm:        var(--ws-canon-shadow-sm);
    --ws-shadow-md:        var(--ws-canon-shadow-md);
    --ws-shadow-lg:        var(--ws-canon-shadow-lg);
    --ws-shadow-primary:   var(--ws-canon-shadow-primary);

    /* ---------- Геометрия ---------- */
    --ws-radius-sm:   8px;
    --ws-radius-md:   12px;
    --ws-radius-lg:   16px;
    --ws-radius-xl:   20px;
    --ws-radius-2xl:  24px;
    --ws-radius-full: 999px;

    /* ---------- Шрифты ---------- */
    --ws-font-sans:    "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --ws-font-heading: "Manrope", "Inter", system-ui, sans-serif;
    --ws-font-mono:    "Geist Mono", "JetBrains Mono", "SF Mono", Consolas, monospace;

    /* ---------- Ритм ---------- */
    --ws-space-2xs: 4px;
    --ws-space-xs:  8px;
    --ws-space-sm:  12px;
    --ws-space-md:  16px;
    --ws-space-lg:  24px;
    --ws-space-xl:  32px;
    --ws-space-2xl: 48px;

    /* ---------- Высоты контролов ---------- */
    --ws-control-h:    44px;
    --ws-control-h-sm: 36px;

    /* ---------- Словесный знак «Билокс» ----------
       Логотип на публичных страницах — лендинг и авторизация — рисовался
       двумя независимыми наборами чисел: 20px/900 со знаком 32px на лендинге
       и 19px/800 со знаком 26px на авторизации. Разница в один пиксель и в
       одну ступень насыщенности не читается как замысел, она читается как
       небрежность — тем более что человек попадает с одной страницы на
       другую в один клик. На телефоне лендинг вдобавок утягивал надпись до
       12px общим правилом «мелкие подписи».
       Размер логотипа — свойство марки, а не страницы, поэтому он живёт
       здесь: меняется в одном месте и подтягивается всюду. */
    --ws-wordmark-size:        22px;
    --ws-wordmark-weight:      900;
    --ws-wordmark-gap:         10px;
    --ws-wordmark-mark-size:   34px;
    --ws-wordmark-mark-font:   18px;
    --ws-wordmark-mark-radius: 10px;
}

/* ==========================================================================
   4. МОСТЫ В LEGACY-ИМЕНА
   Единственное место, где живут старые переменные. Раньше их объявляли
   shared/legacy/styles.css, apps/user/user-design-tokens.css и
   shared/legal/legal.tokens.css — каждый со своей палитрой и своим
   body.theme-dark, из-за чего в тёмной теме акцент становился indigo,
   а не акцентом продукта. Теперь значение одно и приходит отсюда.

   Селектор двойной по той же причине, что и у блока алиасов выше.
   ========================================================================== */
:root,
body.theme-dark {
    --font-main:            var(--ws-font-sans);
    --font-display:         var(--ws-font-heading);

    --bg-color:             var(--ws-bg);
    --bg-gradient:          var(--ws-canon-page-gradient);

    --text-primary:         var(--ws-fg);
    --text-secondary:       var(--ws-fg-muted);
    --text-tertiary:        var(--ws-fg-soft);
    --text-muted:           var(--ws-fg-muted);
    --text-placeholder:     var(--ws-fg-soft);

    --accent:               var(--ws-primary);
    --accent-color:         var(--ws-primary);
    --accent-hover:         var(--ws-primary-hover);
    --accent-text:          var(--ws-primary-fg);
    --accent-gradient:      linear-gradient(180deg, var(--ws-primary-hover) 0%, var(--ws-primary) 100%);
    --accent-shadow:        var(--ws-shadow-primary);
    --accent-glow:          0 0 20px var(--ws-primary-soft);

    --border-color:         var(--ws-line);
    --border-muted:         var(--ws-line-strong);

    --card-bg:              var(--ws-surface);
    --card-border:          1px solid var(--ws-line);
    --card-shadow:          var(--ws-shadow-sm);
    --modal-bg:             var(--ws-surface-strong);

    --input-bg:             var(--ws-surface);
    --input-border:         1px solid var(--ws-line-strong);
    --input-text:           var(--ws-fg);
    --input-focus-border:   var(--ws-primary);
    --input-focus-ring:     0 0 0 3px var(--ws-primary-soft);

    --segment-bg:            var(--ws-bg-soft);
    --segment-active-bg:     var(--ws-surface);
    --segment-active-text:   var(--ws-fg);
    --segment-inactive-text: var(--ws-fg-muted);
    --segment-shadow:        var(--ws-shadow-sm);

    --success:              var(--ws-accent-emerald);
    --success-color:        var(--ws-accent-emerald);
    --error:                var(--ws-error);
    --warning:              var(--ws-accent-gold);

    --rank-seeker:          var(--ws-canon-rank-seeker);
    --rank-practitioner:    var(--ws-canon-rank-practitioner);
    --rank-pro:             var(--ws-canon-rank-pro);
    --rank-expert:          var(--ws-canon-rank-expert);
    --rank-visionary:       var(--ws-canon-rank-visionary);

    --radius-sm:            var(--ws-radius-sm);
    --radius-md:            var(--ws-radius-md);
    --radius-lg:            var(--ws-radius-lg);
    --radius-xl:            var(--ws-radius-2xl);
    --btn-height:           48px;
}

/* ==========================================================================
   5. БАЗА ДОКУМЕНТА
   Фон и цвет текста задаются здесь один раз, чтобы ни одна страница не
   осталась со светлой подложкой при theme-dark. Экран, которому нужен свой
   фон, переопределяет --ws-bg / --ws-canon-page-gradient, а не background.
   ========================================================================== */
html {
    background-color: var(--ws-bg);
}

body {
    background-color: var(--ws-bg);
    background-image: var(--ws-canon-page-gradient);
    background-attachment: fixed;
    color: var(--ws-fg);
}

/* ── Мгновенная смена темы ─────────────────────────────────────────────────
   Тема должна переключаться одним кадром. Раньше body плавно перекрашивался
   за 220 мс, а всё остальное — панели, карточки, кнопки — меняло цвет сразу,
   потому что переменные не анимируются. При быстром переключении было
   отчётливо видно, как подложка «догоняет» содержимое, и на экране проступал
   прямоугольник рабочей зоны.

   Собственная анимация фона здесь удалена, а на время самого переключения
   рантайм вешает на <html> класс `theme-switching` — он гасит ВСЕ переходы
   и анимации на странице на один кадр. Компонентные transition (ховеры,
   раскрытия) при этом остаются на месте, они просто не участвуют в смене
   темы. */
html.theme-switching,
html.theme-switching *,
html.theme-switching *::before,
html.theme-switching *::after {
    transition: none !important;
    animation-duration: 0s !important;
    animation-delay: 0s !important;
}

/* Полосы прокрутки и нативные контролы следуют за темой. */
* {
    scrollbar-color: var(--ws-line-strong) transparent;
}

::selection {
    background: var(--ws-primary-soft);
    color: var(--ws-fg);
}

/* Единое кольцо фокуса — критерий доступности 2.4.7. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--ws-primary);
    outline-offset: 2px;
}

/* ==========================================================================
   ВЕС ЗНАЧКОВ — СТРЕЛКИ И ШЕВРОНЫ
   --------------------------------------------------------------------------
   Толщина обводки — такая же часть общего языка, как цвет и радиус, поэтому
   она живёт здесь, а не в файле отдельного экрана: этот файл подключён на
   всех страницах платформы, включая собранные правовые.

   Что было. Одна и та же стрелка «вправо» рисовалась тремя разными весами:
     • 2.2 — в строке черновика кабинета компании,
     • 1   — в трёх других местах того же файла (атрибут stroke-width просто
             забыли, а браузерное значение по умолчанию — единица),
     • 2   — везде, где стрелку рисует lucide по data-lucide.
   Рядом, в одной колонке, стояли волосяная и жирная стрелка. Плюс своя
   геометрия на лендинге (шток 4→20 вместо 5→19) — четвёртое начертание.

   Канон — стрелка «назад» с экрана отбора победителя: сетка 24, обводка 2,
   круглые концы. Здесь она поднята до 2.2: при 18px, на которых стрелка
   обычно и стоит, двойка выглядит тоньше, чем та же двойка на 24px.

   Правило намеренно узкое — только стрелки и шевроны, по имени значка и по
   классам-обёрткам. Трогать вес всех значков подряд нельзя: у части из них
   вес подобран под форму (галочка 2.7, значок «поделиться» 2.05).
   ========================================================================== */
:where(
    i[data-lucide^="arrow-"] svg,
    i[data-lucide^="chevron-"] svg,
    svg[data-lucide^="arrow-"],
    svg[data-lucide^="chevron-"],
    /* lucide подменяет <i> на <svg class="lucide lucide-arrow-right">, и
       атрибут data-lucide до готовой разметки не доживает — ловим и по
       классу, который библиотека ставит сама. */
    svg[class*="lucide-arrow-"],
    svg[class*="lucide-chevron-"],
    .cdb-round-link svg,
    .cdb-action-go svg,
    .dropdown-chevron,
    .dropdown-chevron svg,
    .drawer-chevron,
    .drawer-chevron svg,
    .subscription-chevron,
    .subscription-chevron svg,
    .chevron-icon,
    .chevron-icon svg,
    .chart-nav-icon,
    .chart-nav-icon svg,
    .task-accordion-icon,
    .task-accordion-icon svg
) {
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
