/* ==========================================================================
   ui-tokens.css — словарь интерфейса: цвета, метрики и материалы.

   Зачем он появился. В шестнадцати с половиной тысячах строк CSS одна и та
   же коричневая панель написана заново в каждом разделе, кремовая плашка
   ресурса — в трёх местах с разными числами, а золотая кнопка встречается
   в пяти написаниях. Из-за этого одинаковые на вид элементы расходятся в
   мелочах: радиус 12px рядом с 13px, тень «парящая» рядом с направленной,
   нажатие то есть, то нет.

   Здесь собран один словарь. Файл ничего не переопределяет: он задаёт
   имена `--ui-*` и классы `.ui-*`. Существующие переменные (`--brown-*`,
   `--gold-*`, `--radius*`, `--space-*`) ссылаются сюда из `common.css`,
   поэтому смена значения здесь меняет всю игру разом.

   28 АВГУСТА ПАЛИТРА ЗАМЕНЕНА ЦЕЛИКОМ.

   До этого дня словарь был тёплым: дерево, земля, золото, крем — он
   собирался по референсам `as/4.png` и `as/5.png`. ТЗ `uif.md` заменило
   визуальный контракт: теперь источник истины — `grok/8.png` и
   `grok/9.png`, глубокий сине-фиолетовый мир с золотом и зеленью.
   Прежние комментарии со ссылками на `as/*` ниже сохранены там, где они
   объясняют ФОРМУ (радиусы, кромки, физику нажатия): форма от смены
   гаммы не изменилась. Всё, что говорит про ЦВЕТ, переписано.
   ========================================================================== */

:root {
    /* ==================================================================
       ПАЛИТРА ПО `grok/8.png` И `grok/9.png`.

       До 28 августа игра была тёплой: дерево, земля, золото, крем. ТЗ
       `uif.md` заменило визуальный контракт целиком — теперь это
       глубокий сине-фиолетовый мир с золотом, как на кадрах «SHOP»,
       «PROFILE», «TOWER» и на всех окнах.

       Значения сняты пипеткой по доминирующему цвету области, а не
       точечно: в кадре есть блики, обводки и текст, и одна точка врёт.
       Метод — Counter по прямоугольнику внутри поверхности.

         фон экрана          #0B0925   (между панелями кадра SHOP)
         панель корпус       #151244   (панель «POWER UPS»)
         панель шапка        #230E58   (её лиловая полоса)
         шапка раздела       #34147A   (полоса «SHOP» с кнопкой назад)
         нижняя навигация    #1A1A3A
         золото кнопки       #D29014 → #CA8004  (кнопка «CLAIM»)
         зелень кнопки       #619C16 → #3F750F  (кнопка «GET COINS»)
         корпус окна         #10111B  (окно «LEVEL UP!»)
         корпус окна-отказа  #241416  (окно «NOT ENOUGH COINS!»)

       ИМЕНА ТОКЕНОВ НЕ МЕНЯЮТСЯ. Их читают сорок с лишним файлов
       разделов; переименование означало бы переписать их все и
       гарантированно что-то сломать. Поэтому `--ui-wood-*` и
       `--ui-earth-*` остались, но ведут теперь на фиолетовый корпус:
       смысл имени («материал панели», «материал подземелья») сохранён,
       материал сменился. Это и есть миграция без остановки игры.
       ================================================================== */

    --ui-bg-deep:      #060617;   /* самый тёмный фон, за всем */
    --ui-bg-dark:      #0b0925;   /* фон разделов */
    --ui-panel-dark:   #100e33;   /* нижняя часть панели */
    --ui-panel-main:   #151244;   /* корпус панели */
    --ui-panel-light:  #251f66;   /* верхняя кромка панели */
    --ui-panel-edge:   #05040f;   /* нижняя грань панели */
    --ui-row-a:        #171346;   /* чётная строка списка */
    --ui-row-b:        #120f3a;   /* нечётная строка списка */

    /*
     * Задник сцены — три ступени одного пятна света: вверху экрана
     * светлее, к низу уходит в ночь. Числа жили в base.css как
     * `--bg-main`, то есть цвет игры задавался мимо словаря, и два
     * раздела (башня, квартал Trumpywood) читали его оттуда — квартал
     * ещё и с запаской прежнего мира. Имена стопов заведены здесь,
     * чтобы источник цвета остался один.
     */
    --ui-bg-glow:      #191045;   /* пятно света вверху сцены */
    --ui-bg-mid:       #110b2e;   /* середина задника */
    --ui-bg-night:     #0a0815;   /* низ задника */
    --ui-bg-main:      radial-gradient(78% 62% at 50% 12%,
                         var(--ui-bg-glow) 0%, var(--ui-bg-mid) 46%,
                         var(--ui-bg-night) 100%);

    /* Лиловая шапка панели и полоса раздела — вторая по важности
       поверхность кадра: ею подписан КАЖДЫЙ экран референса. */
    --ui-head:         #34147a;   /* полоса заголовка раздела */
    --ui-head-dark:    #230e58;   /* шапка панели внутри экрана */
    --ui-head-light:   #4a1fa0;   /* её верхний блик */

    /*
     * «Дерево» — историческое имя материала панелей. Материал теперь
     * фиолетовый; имена оставлены, чтобы разделы не переписывать.
     */
    --ui-wood-dark:    #100e33;
    --ui-wood:         #1c1750;
    --ui-wood-light:   #2b2470;

    /* «Земля» — материал игрового поля и подземных разделов. На кадре
       «BATTLEFIELD» и «ARENA BATTLE» земля осталась землёй: поле боя
       коричневое, и это единственное место, где тепло уцелело. */
    --ui-earth-light:  #c98a4a;
    --ui-earth:        #9a5f2c;
    --ui-earth-dark:   #5d3517;
    --ui-earth-hole:   #180b04;

    /* ------------------------------------------------------------------
       Светлый набор. На кадрах `grok/*` кремовой эмалированной плашки нет
       ни разу: светлое там — это ТЕКСТ (белый капслок заголовков) и блик
       на золоте. Имена оставлены (их читают разделы), но уведены в
       холодный белый: тёплый крем на фиолетовом выглядел пятном чужой
       темы. Плашки, которые были кремовыми, стали тёмно-фиолетовыми.
       ------------------------------------------------------------------ */
    --ui-ivory-light:  #ffffff;   /* белый текст заголовков */
    --ui-ivory:        #f2f0ff;   /* чуть тёплый белый */
    --ui-ivory-dark:   #c9c4e8;   /* приглушённый светлый */
    --ui-ivory-deep:   #6a63a8;   /* контур светлой поверхности */

    /* ---------------------------------------------------------------- */
    /* Золото. Верхний блик и нижняя фаска — из рабочей кнопки            */
    /* mvp.css:263, корпус — --gold-2 и --gold-medium из common.css,      */
    /* самая тёмная грань — из золотого градиента common.css:474.         */
    /* ---------------------------------------------------------------- */
    --ui-gold-hi:      #fff3b0;   /* самый светлый блик */
    --ui-gold-light:   #ffd873;   /* верхний блик, подписи на фиолетовом */
    --ui-gold:         #eeb126;   /* основной корпус */
    --ui-gold-mid:     #d29014;   /* середина градиента */
    --ui-gold-dark:    #ca8004;   /* нижняя фаска */
    --ui-gold-deep:    #7a4a05;   /* тёмная грань под фаской */

    /* ------------------------------------------------------------------
       ЗОЛОТО КНОПКИ — отдельный, более спокойный набор.

       Цвета сняты пипеткой с кнопки «ЗАБРАТЬ» окна ежедневных наград
       (as/5.png, вертикальный срез при x=150). Сверху вниз:

         y+1   #F9D56C  тонкий светлый блик под кромкой
         y+3   #CB8C1B  корпус, верхняя треть
         y+30  #AB6B12  корпус, нижняя треть
         y+45  #1f1455  нижняя грань, ВСЕГО 2-3px
         кромка по периметру #21155a — тёплая тёмно-коричневая

       Чем это отличается от того, что стояло. Наш корпус шёл от #FFD76A
       к #B36F12 — на две ступени ярче и заметно желтее референсного,
       кромка была ЧЁРНОЙ (`rgba(0,0,0,.45)`), а нижняя грань — плитой в
       5px цвета #291a70. Чёрный контур на тёплом золоте выглядит
       наклейкой, а толстая плита под кнопкой — вторым элементом рядом с
       ней: владелец назвал это «нижняя тень или обводка не гармонирует
       с цветом». На кадрах грань тонкая и того же рода, что корпус.
       ------------------------------------------------------------------ */
    /*
     * Значения пересняты с кнопки «CLAIM» окна «LEVEL UP!» (grok/9.png):
     * корпус #D29014 сверху → #CA8004 снизу, светлый кант по периметру,
     * тёмная грань. Прежние сняты с кадра as/5.png и были на ступень
     * бледнее — на фиолетовой панели такая кнопка гасла.
     */
    --ui-gold-btn-hi:   #ffd873;   /* блик под верхней кромкой */
    --ui-gold-btn-top:  #eeb126;   /* корпус, верх */
    --ui-gold-btn:      #d29014;   /* корпус, середина */
    --ui-gold-btn-low:  #ca8004;   /* корпус, низ */
    --ui-gold-btn-edge: #7a4a05;   /* кромка по периметру */
    --ui-gold-btn-deep: #613406;   /* нижняя грань */

    /*
     * ЗЕЛЁНАЯ КНОПКА — «GET COINS», «CONTINUE», «CLAIM» на кадрах.
     *
     * На референсе зелёный — второе главное действие после золотого, и
     * встречается он куда чаще, чем в прежней раскладке: им подписаны и
     * «получить», и «продолжить», и «купить за деньги». Значения сняты с
     * кнопки «CONTINUE» окна «NEW SKIN!».
     */
    --ui-green-btn-hi:  #a8e05a;
    --ui-green-btn-top: #7cba22;
    --ui-green-btn:     #619c16;
    --ui-green-btn-low: #4a8511;
    --ui-green-btn-edge:#2c5408;
    --ui-green-btn-deep:#22440a;

    /* ---------------------------------------------------------------- */
    /* Текст                                                             */
    /* ---------------------------------------------------------------- */
    /* На кадрах основной текст — чистый белый, второстепенный — светлый
       лиловый. Тёплый крем #FFF4D6 на фиолетовом отдавал желтизной.

       Приглушённый светлый сведён к --ui-ivory 30 августа. Замер по
       grok/8.png и 9.png: светлое там почти нейтральное (#e0e0e0,
       #e0e0d8, #d8d8d0), лиловой примеси в нём нет. Прежние
       rgba(214,210,255) и rgba(196,192,240) уводили подписи в сирень,
       а по разделам параллельно жило полсотни написаний
       rgba(238,236,255,α) — это и есть --ui-ivory #f2f0ff с альфой
       (разница четыре единицы из 255, глазом не берётся). Теперь оба
       уровня — доли одного светлого, и владелец меняет их одной
       строкой. */
    --ui-text-main:    #ffffff;                      /* основной */
    --ui-text-muted:   color-mix(in srgb, var(--ui-ivory) 78%, transparent);
    --ui-text-faint:   color-mix(in srgb, var(--ui-ivory) 50%, transparent);
    --ui-text-dark:    #170f3f;                      /* текст на золоте */
    --ui-text-ivory:   #241a3d;                      /* текст на светлом */

    /* Обводка надписи. По разделам жило пять почти одинаковых
       почти-чёрных (#060518, #090618, #09071e, #0a0822, #0b0925) в
       двухстах написаниях text-shadow — на глаз неразличимы, но
       перекрасить обводку разом было нельзя. Один токен на всю игру,
       включая подпись на зелёной кнопке (там был тёмно-зелёный
       #102206: в контуре толщиной 1px оттенок не читается). */
    --ui-text-outline: #060518;

    /* ---------------------------------------------------------------- */
    /* Смысловые цвета. Все четыре уже есть в игре: зелёный и бордовый —  */
    /* из карточек соперников (modal.css:1369, 1374), красный и синий —   */
    /* из --accent-red и --accent в base.css.                             */
    /* ---------------------------------------------------------------- */
    --ui-green:        #619c16;   /* success, «забрать», «продолжить» */
    --ui-green-light:  #7cba22;
    --ui-green-deep:   #2c5408;

    --ui-red:          #b8302a;   /* danger, потеря, отказ */
    --ui-red-light:    #e04a3c;
    --ui-red-deep:     #6e1a16;

    /* Синий — служебный ресурс: энергия, подсказка, редкость «редкий».
       Панели и заголовки им не красят: игра остаётся тёплой. */
    --ui-blue:         #3f8cc9;
    --ui-blue-light:   #6fc0ee;
    --ui-blue-deep:    #1e5a8a;

    /* ------------------------------------------------------------------
       Фиолетовый БОЛЬШЕ НЕ РЕДКИЙ АКЦЕНТ, а основной цвет интерфейса.

       До 28 августа он значил только премиум (VIP, сезон, эпическая
       редкость) и появлялся на трёх экранах. По `uif.md` §8 фиолетовый
       входит в число главных цветов игры, и на кадрах `grok/8-9.png` из
       него сделаны все панели, шапки и карточки. Роль «премиум» за ним
       остаётся, но выделяется теперь не сам цвет, а золотая кромка
       вокруг него — как у панели «SPECIAL OFFER» кадра «SHOP».
       ------------------------------------------------------------------ */
    --ui-purple-deep:  #1a0c3d;
    --ui-purple-dark:  #230e58;
    --ui-purple:       #34147a;
    --ui-purple-light: #6b34c9;

    /*
     * Сиреневый свет — тот же цвет, что уже держала кромка панели
     * (`--ui-border-warm`), но названный и сплошной.
     *
     * Новый оттенок здесь не заводится: #9678FF два десятка файлов пишут
     * сырым `rgba(150, 120, 255, N)` — это верхняя грань панели, свечение
     * над утопленной доской и кант гнезда. Пока у цвета не было имени,
     * каждый раздел писал его числом, и смена палитры его бы не задела.
     */
    --ui-purple-glow:  #9678ff;

    /* ------------------------------------------------------------------
       ФИОЛЕТОВЫЙ ПАНЕЛИ — набор с кадра «НАБОР ПОБЕДИТЕЛЯ» (as/5.png).

       Замер по вертикали при x=530: #4A1E6B сверху, #612A7D в середине,
       #44235A у низа, и светлый рим #74419C толщиной в пиксель. Наш
       `--ui-purple-light` (#B866DB) на этом месте давал сиреневую заливку
       вдвое светлее кадра — панель выглядела не премиальной, а кислотной.
       ------------------------------------------------------------------ */
    --ui-purple-panel-top: #4a1e6b;
    --ui-purple-panel:     #612a7d;
    --ui-purple-panel-low: #44235a;
    --ui-purple-panel-rim: #74419c;

    /* ---------------------------------------------------------------- */
    /* Редкости (§15 tok.txt). Один набор на всю игру: скины, молоты,     */
    /* снаряжение, офисы башни, артефакты, сундуки.                       */
    /* ---------------------------------------------------------------- */
    --ui-rar-common:      #7b7ba8;
    --ui-rar-uncommon:    #5fa83a;
    --ui-rar-rare:        #3f8cc9;
    --ui-rar-epic:        #b455ff;
    --ui-rar-legendary:   #eeb126;
    /*
     * Мифическая — шестая ступень: она есть у артефактов, косметики и
     * снаряжения, а токена не было. Каждый раздел красил её сам и
     * по-своему: музей — `--ui-red-light`, хранилище — `--ui-red`,
     * коллекция — rgba(229,57,53), снаряжение — розовым на глаз. Один
     * предмет в четырёх списках выходил четырёх разных цветов. Новый
     * оттенок не вводится: это светлый красный словаря, на котором уже
     * стояли два из четырёх списков.
     */
    --ui-rar-mythic:      var(--ui-red-light);

    --ui-locked:       #221f52;   /* корпус недоступного элемента */
    --ui-locked-text:  rgba(226, 224, 255, 0.45);

    /* ---------------------------------------------------------------- */
    /* Отступы. Ровно семь значений (§21): случайных 13px и 17px в        */
    /* одинаковых компонентах быть не должно.                             */
    /* ---------------------------------------------------------------- */
    --ui-space-1: 4px;
    --ui-space-2: 8px;
    --ui-space-3: 12px;
    --ui-space-4: 16px;
    --ui-space-5: 20px;
    --ui-space-6: 24px;
    --ui-space-7: 32px;

    /* Поле страницы — единственный отступ, который следует за шириной
       экрана (§108, responsive spacing).

       Внутренние промежутки от ширины не зависят: воздух между строкой и
       её значком на узком телефоне нужен ровно тот же. А вот боковое поле
       раздела зависит: замер по семнадцати маршрутам дал шесть разных
       значений (8, 10, 12, 14, 15, 16px), и ни одно из них не менялось от
       320px к 430px. На узком экране 14px с каждой стороны — это девятая
       часть ширины, отданная пустоте; на широком те же 14px прижимают
       карточки к краю. Теперь поле одно на все разделы и дышит: 10px на
       320, 12.5 на 390, 13.8 на 430, дальше упирается в 16.

       Сцены поля не берут (карта, поле боя): у них картинка идёт в край
       намеренно. */
    --ui-gutter: clamp(10px, 3.2vw, 16px);

    /* ---------------------------------------------------------------- */
    /* Скругления (§22). Шесть шагов — и ни одного числа мимо них.        */
    /*                                                                    */
    /* Значения сняты с референса as/4.png. Кадр там 331px в ширину при   */
    /* телефоне в 390 CSS-пикселей, коэффициент 1.18. Замеры по краю      */
    /* заливки: карточка скина и плашка набора в магазине — 6-7px кадра   */
    /* (≈8 CSS), кнопка «ИГРАТЬ» — 9px кадра (≈11 CSS), панель «лучшие    */
    /* достижения» в профиле — 11-14px кадра (≈13-16 CSS), вывеска        */
    /* заголовка — 9px кадра (≈11 CSS). Отсюда: мелочь 8, карточка и      */
    /* кнопка 12, крупная панель 16. Всё, что было 22-40px, в референсе   */
    /* не встречается вовсе: такие числа стояли на чипах и шкалах, а им   */
    /* положена таблетка.                                                 */
    /* ---------------------------------------------------------------- */
    --ui-radius-xs:   6px;    /* шкалы, тонкие полосы, мелкие метки */
    --ui-radius-sm:   8px;    /* вложенные плашки, строки списка, иконки */
    --ui-radius-md:   12px;   /* карточка, плитка, кнопка — основной шаг */
    --ui-radius-lg:   16px;   /* панель раздела, витрина, вывеска, сцена */
    --ui-radius-xl:   20px;   /* окно поверх экрана */
    --ui-radius-pill: 999px;  /* чип, бейдж, шкала, кнопка-таблетка */

    /* ---------------------------------------------------------------- */
    /* Контуры (§23). Толстый читаемый контур — обязательная часть        */
    /* объёмного интерфейса, тонкая линия в 1px на телефоне пропадает.    */
    /* ---------------------------------------------------------------- */
    --ui-border:       2px;
    --ui-border-thick: 3px;
    /* светлая кромка панели — сиреневый свет словаря в треть силы */
    --ui-border-warm:  color-mix(in srgb, var(--ui-purple-glow) 30%, transparent);
    --ui-border-dark:  rgba(0, 0, 0, 0.55);         /* внешний тёмный контур */
    --ui-border-ivory: #4a4288;                     /* контур светлой панели */

    /* ---------------------------------------------------------------- */
    /* Тени (§24). Тень — часть материала, а не «парящая» тень из         */
    /* интерфейсов деловых приложений: сначала направленная нижняя грань  */
    /* без размытия, затем мягкое пятно под элементом.                    */
    /* ---------------------------------------------------------------- */
    --ui-edge-panel:  0 5px 0 var(--ui-panel-edge);
    --ui-edge-ivory:  0 4px 0 var(--ui-ivory-deep);
    /* Грань золотой кнопки — 3px, а не 5px, и того же тёплого рода, что
       корпус (замер по кадру: под кнопкой «ЗАБРАТЬ» ровно 2-3px). */
    --ui-edge-gold:   0 3px 0 var(--ui-gold-btn-deep);
    --ui-edge-brown:  0 5px 0 #05040f;
    --ui-edge-danger: 0 5px 0 var(--ui-red-deep);
    --ui-edge-green:  0 5px 0 var(--ui-green-deep);
    --ui-edge-purple: 0 5px 0 var(--ui-purple-deep);

    /* ------------------------------------------------------------------
       ЛЕСТНИЦА ТЕНЕЙ (§108 ТЗ: shadows).

       Падающая тень была россыпью: двести объявлений в тридцати девяти
       файлах и сто сорок семь РАЗНЫХ значений. Соседние по смыслу вещи
       падали по-разному — карточка облика на 26px, карточка задания на
       18px, карточка соперника на 22px, — и это читается не богатством,
       а небрежностью: глаз видит, что предметы лежат на разной высоте
       без всякой причины.

       Ступени берут по РАЗМЕРУ отбрасывающего, а плотность идёт за
       высотой по физике: тень у самой поверхности тесная и тёмная
       (контакт), высокая — широкая и светлая (рассеянная).

       --ui-shadow-xs    чип, значок, мелкий контрол — лежит на доске
       --ui-shadow-sm    строка списка, кнопка, вкладка
       --ui-shadow-soft  карточка, плитка — рабочая ступень интерфейса
       --ui-shadow-lg    панель раздела, лист, витрина
       --ui-shadow-deep  окно
       --ui-shadow-scene сцена, оверлей, лист поверх всего

       Значения `-soft` и `-deep` не менялись: их читают сто с лишним
       правил, и они и были нормой — лестница достроена вокруг них.
       ------------------------------------------------------------------ */
    --ui-shadow-xs:    0 2px 5px rgba(0, 0, 0, 0.45);
    --ui-shadow-sm:    0 4px 10px rgba(0, 0, 0, 0.45);
    --ui-shadow-soft:  0 8px 18px rgba(0, 0, 0, 0.35);
    --ui-shadow-lg:    0 12px 26px rgba(0, 0, 0, 0.30);
    --ui-shadow-deep:  0 14px 34px rgba(0, 0, 0, 0.45);
    --ui-shadow-scene: 0 22px 55px rgba(0, 0, 0, 0.50);

    /* ------------------------------------------------------------------
       ТЕНЬ ПОД КАРТИНКОЙ (`filter: drop-shadow`).

       У вырезанного арта тень своя, и она НЕ равна тени корпуса: под
       картинкой нет панели, тень читается сама по себе и потому плотнее.
       Плотность здесь означает подложку, а не высоту:

       --ui-art-shadow-pin   значок поверх картинки или цветной кнопки:
                             тень держит силуэт, а не рисует объём
                             (золотой кружок на золотой кнопке иначе
                             пропадает — `mvp.css`, `.tam-icon--art`)
       --ui-art-shadow-card  картинка ВНУТРИ карточки: под ней светлая
                             доска, плотная тень выглядит грязью
       --ui-art-shadow-sm    мелкий предмет на корпусе
       --ui-art-shadow-md    герой карточки, плитки, строки
       --ui-art-shadow-lg    крупный герой сцены
       --ui-art-shadow-xl    портрет во весь экран, награда окна
       ------------------------------------------------------------------ */
    --ui-art-shadow-pin:  0 2px 4px rgba(0, 0, 0, 0.55);
    --ui-art-shadow-card: 0 10px 15px rgba(0, 0, 0, 0.28);
    --ui-art-shadow-sm:   0 5px 10px rgba(0, 0, 0, 0.50);
    --ui-art-shadow-md:   0 10px 16px rgba(0, 0, 0, 0.50);
    --ui-art-shadow-lg:   0 16px 26px rgba(0, 0, 0, 0.45);
    --ui-art-shadow-xl:   0 22px 40px rgba(0, 0, 0, 0.50);

    /* ------------------------------------------------------------------
       ФАКТУРА ПОВЕРХНОСТЕЙ.

       Прежняя «грязь» рисовала земляную крупу и разводы: она собиралась
       под тёплые деревянные панели `as/4-5.png` и там была обязательной.
       На кадрах `grok/8-9.png` поверхность другая — гладкое окрашенное
       стекло с мягким светом сверху. Замер разброса яркости внутри
       чистого участка панели: std ≈ 12 против 6 у фона, то есть неровность
       есть, но она вчетверо слабее земляной крупы и другого рода — это
       СВЕТ, а не грязь.

       Поэтому крупа ослаблена втрое и переведена в холодный тон, а
       широкие разводы стали мягким лиловым свечением. Имена сохранены:
       их читают шесть десятков объявлений `background:` в `ui-frame.css`,
       и переписывать их все ради смены фактуры незачем.
       ------------------------------------------------------------------ */
    --ui-dirt: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='d' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.55 0 0 0 0 0.50 0 0 0 0 0.95 0.30 0 0 0 -0.12'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23d)'/%3E%3C/svg%3E");

    --ui-dirt-wide: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='d' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.016 0.020' numOctaves='4' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.42 0 0 0 0 0.24 0 0 0 0 0.90 0.55 0 0 0 -0.30'/%3E%3C/filter%3E%3Crect width='420' height='420' filter='url(%23d)'/%3E%3C/svg%3E");

    /* По золоту — след тёплой пыли, вдвое слабее прежнего: на кадре
       золотая кнопка почти гладкая, у неё работает блик, а не зерно. */
    --ui-dirt-lite: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='d' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.6' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.40 0 0 0 0 0.26 0 0 0 0 0.04 0.34 0 0 0 -0.16'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23d)'/%3E%3C/svg%3E");

    /* ------------------------------------------------------------------
       ЗАКЛЁПКА (§108 ТЗ: decorative bolts).

       На кадрах `grok/8.png` у лиловой полосы группы («MOLE SKINS»,
       «POWER UPS») в углу стоит маленький светлый ромб. Замер по кадру:
       поле полосы #34147a, ромб #6a45b0 — то есть это не отдельный цвет,
       а та же поверхность, высветленная примерно на 22 %. Поэтому в
       значке забелён белый с прозрачностью, а не хекс из палитры: одна
       заклёпка одинаково работает и на лиловой полосе, и на тёмной доске.

       Ромб идёт с тёмной подложкой на пиксель ниже — без неё он читается
       наклейкой, а не вдавленной деталью корпуса. Размер 16px при
       рисунке в 11px: поля нужны, иначе тень срежется краем плитки.
       ------------------------------------------------------------------ */
    --ui-bolt: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cdefs%3E%3ClinearGradient id='b' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23ffffff' stop-opacity='0.34'/%3E%3Cstop offset='1' stop-color='%23ffffff' stop-opacity='0.07'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M8 3.6 13.2 8.8 8 14 2.8 8.8Z' fill='%23000000' fill-opacity='0.22'/%3E%3Cpath d='M8 2.6 13.2 7.8 8 13 2.8 7.8Z' fill='url(%23b)'/%3E%3C/svg%3E");

    /* Внутренние блики и утопления — тоже часть материала.

       Третьего значения, `--ui-inner-bottom` (`inset 0 -2px 6px` чёрным
       по 28 %), здесь больше нет. Оно стояло рядом с этими двумя и не
       читалось НИКЕМ; заход 97 поставил его на материал карточек §6
       (тот самый bevel из §108) и замерил кадр: разница на всей карточке
       вышла 12 единиц из 255 и на глаз не видна. Причина простая —
       направленную нижнюю грань карточке уже даёт слой `0 5px 0
       --ui-panel-edge` снаружи, а изнутри её несёт сам градиент корпуса,
       уходящий к `--ui-panel-dark` на 100 %. Второе затемнение поверх
       первого ничего не добавляет, зато вешает лишний слой тени на
       каждую карточку игры. */
    --ui-inner-top:    inset 0 1px 0 rgba(238, 236, 255, 0.18);
    --ui-inner-well:   inset 0 3px 8px rgba(0, 0, 0, 0.45);

    /* ------------------------------------------------------------------
       СВЕЧЕНИЕ (§108 ТЗ: glow).

       Свечение в игре было россыпью: двадцать объявлений в двенадцати
       файлах с радиусами 6, 8, 10, 12, 14, 16, 18, 22, 24 и плотностью
       от 14 % до 90 %. Соседние по смыслу вещи светились по-разному —
       огонёк башни на 6px, искра «три в ряд» на 12px, вспышка сундука
       на 22px, — и «дорого» из этого не складывалось: разнобой читается
       не богатством, а небрежностью.

       Радиусов теперь три, и берут их по РАЗМЕРУ светящегося:
       --ui-glow-sm  точка, огонёк, значок, искра — то, что меньше 24px;
       --ui-glow-md  карточка, кнопка, чип, плитка — обычный элемент;
       --ui-glow-lg  окно, награда, сцена — то, что занимает экран.

       Плотность — три ступени, и они означают РАЗНОЕ:
       -soft  тихая подсветка фона под элементом (шкала сезона, кольцо
              обучения) — её замечают краем глаза;
       обычная — «этот элемент выбран, он ценный» (активная плитка,
              купленный облик, доступный этаж);
       -hot   вспышка события (сундук открылся, ряд собрался) — живёт
              долю секунды и в покое не стоит.

       Цвет берётся из палитры и означает то же, что везде: золото —
       ценность, зелень — успех, красный — отказ, синий — подсказка.
       Свечение цветом ВНЕ этого набора — ошибка, как и любой цвет мимо
       словаря (§85). Исключение одно: искры «три в ряд» светятся цветом
       своей фишки (`--t0`…`--t5`), и радиус они всё равно берут отсюда.
       ------------------------------------------------------------------ */
    --ui-glow-sm: 8px;
    --ui-glow-md: 14px;
    --ui-glow-lg: 22px;

    --ui-glow-gold:      0 0 var(--ui-glow-md) color-mix(in srgb, var(--ui-gold) 55%, transparent);
    --ui-glow-gold-soft: 0 0 var(--ui-glow-md) color-mix(in srgb, var(--ui-gold) 18%, transparent);
    --ui-glow-gold-hot:  0 0 var(--ui-glow-lg) color-mix(in srgb, var(--ui-gold) 90%, transparent);
    --ui-glow-green:     0 0 var(--ui-glow-md) color-mix(in srgb, var(--ui-green) 45%, transparent);
    --ui-glow-red:       0 0 var(--ui-glow-md) color-mix(in srgb, var(--ui-red) 45%, transparent);
    --ui-glow-blue:      0 0 var(--ui-glow-md) color-mix(in srgb, var(--ui-blue) 45%, transparent);

    /* ---------------------------------------------------------------- */
    /* Типографика (§19-20). Семейства — канон проекта; мелкий тонкий     */
    /* текст не используется, минимальный вес интерфейса — 600.           */
    /* ---------------------------------------------------------------- */
    /*
     * Семейства берутся из fonts.css, а не пишутся здесь второй раз.
     *
     * Здесь стояли 'Unbounded' и 'Manrope' — оба убраны из index.html
     * 27 августа, и обе переменной молча уезжали на system-ui. То есть
     * весь словарь (`.ui-body`, `.ui-value`, `.ui-section`) и половина
     * рамы набирались системным гротеском, пока разделы со своими
     * `--font-main` шли Nunito: на одном экране стояли два разных шрифта.
     */
    --ui-font-title:     var(--font-heading);
    --ui-font-main:      var(--font-main);
    --ui-font-condensed: var(--font-condensed);

    --ui-weight-title:   900;
    --ui-weight-section: 800;
    --ui-weight-value:   800;
    --ui-weight-body:    600;

    --ui-size-title:   22px;
    --ui-size-section: 17px;
    --ui-size-value:   16px;
    --ui-size-body:    14px;
    --ui-size-small:   12px;
    /* Нижняя граница кегля. Ниже 10px подпись капслоком с разрядкой на
       телефоне не читается — её видно как серую полоску. Пять мест в игре
       стояли на 9px; три обычных подняты сюда, два оставшихся живут внутри
       @media узкого экрана, где кегль ужат осознанно. */
    --ui-size-micro:   10px;

    /* Обводка допустима только у крупных игровых заголовков. */
    --ui-title-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);

    /* Мягкая тень ПОД НАДПИСЬЮ. Три ступени, и мера у них — КЕГЛЬ, а не
       панель: тень должна отделять букву от пёстрого задника, оставаясь
       внутри её высоты. По разделам жило восемь плотностей от .35 до .85,
       и половина из них была списана с панели — `0 10px 24px` стояло на
       подписях в 11-13px в восьми местах. При кегле 12px смещение в 10px
       уносит тень целиком из-под буквы, а размытие в 24px растирает её в
       грязь: работы никакой, а экран мутнеет.

       Цвет один — обводочный `--ui-text-outline`: чёрный на фиолетовом
       корпусе отдаёт зеленью, тёмно-синий держит тон.                    */
    --ui-text-shadow-sm: 0 1px 2px
        color-mix(in srgb, var(--ui-text-outline) 75%, transparent);
    --ui-text-shadow-md: 0 2px 6px
        color-mix(in srgb, var(--ui-text-outline) 60%, transparent);
    --ui-text-shadow-lg: 0 4px 12px
        color-mix(in srgb, var(--ui-text-outline) 55%, transparent);

    /* ---------------------------------------------------------------- */
    /* Размеры касания. Ниже 48px палец не попадает.                      */
    /* ---------------------------------------------------------------- */
    --ui-tap:        56px;
    --ui-tap-icon:   52px;
    /* Нижняя граница §49 ТЗ: мелкая кнопка раздела («Отметить
       прочитанным», ссылки в соседние разделы) не может быть ниже. До
       появления этого имени такие кнопки писали 38, 40 и 44px числом. */
    --ui-tap-min:    44px;
    --ui-press:      2px;    /* насколько кнопка уходит вниз при нажатии */
    /* Нажатие. Своего числа здесь больше нет: 0.12s жило рядом с лестницей
       движения вторым источником времени и молча решало за неё, как быстро
       отвечает КАЖДАЯ кнопка игры — шестнадцать мест в девяти файлах.
       Ступень «палец нажал» одна на всю игру, и живёт она в `game-ui.css`. */
    --ui-ease:       var(--tam-t-tap) ease;

    /* ---------------------------------------------------------------- */
    /* Толщина шкал (§24 и §71 ТЗ: полоса обязана быть толстой и          */
    /* игровой). Высоты писали числом в файлах разделов, и одна и та же   */
    /* по смыслу шкала выходила то 16px в профиле, то 6px в задании —     */
    /* волосок поверх доски, который на телефоне не читается вовсе.       */
    /* Четыре ступени: волосок HUD, строка списка, доска раздела, витрина.*/
    /* ---------------------------------------------------------------- */
    --ui-bar-h-thin: 8px;    /* внутри чипа и боевого HUD */
    --ui-bar-h-sm:  12px;    /* строка списка, узкий столбец */
    --ui-bar-h:     16px;    /* опыт, сезон, лига, здоровье босса */
    --ui-bar-h-lg:  26px;    /* витрина: шкала во всю ширину панели */
}

/* ==========================================================================
   МАТЕРИАЛЫ

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

/* ----- PANEL_BROWN — шапка, нижняя навигация, крупные окна, секции ------- */
.ui-panel-brown {
    background:
        /* Золотой отсвет сверху: панель выглядит освещённой, а не залитой.
           Числа тут были свои (#f5d65a, #e9b84e) — жёлтая пара прежнего,
           тёплого мира, из-за которой блик на шапке был на полтона зеленее
           золота кнопок. Теперь тот же самый золотой словаря (§103). */
        radial-gradient(120% 90% at 50% -20%,
            color-mix(in srgb, var(--ui-gold-light) 10%, transparent) 0%,
            color-mix(in srgb, var(--ui-gold) 5%, transparent) 38%,
            transparent 62%),
        radial-gradient(140% 120% at 50% -18%,
            var(--ui-panel-light) 0%,
            var(--ui-panel-main) 22%,
            var(--ui-panel-dark) 46%,
            var(--ui-bg-dark) 72%,
            var(--ui-bg-deep) 100%),
        /* Нижний слой видно только по краям, где радиалы уже сошли на нет.
           Он был серо-коричневым (#5a4040) — то есть панель по периметру
           отдавала в тёплое даже после смены палитры. Теперь корпусный
           фиолетовый. */
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-edge) 100%);
    border: var(--ui-border) solid var(--ui-border-warm);
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-edge-panel), var(--ui-shadow-soft), var(--ui-inner-top);
    color: var(--ui-text-main);
}

/* ----- PANEL_IVORY — плашки ресурсов, сводки, вторичные карточки --------- */
.ui-panel-ivory {
    /*
     * Основа — вертикальный градиент, а не радиальный.
     *
     * У плашки ресурса в header.css свет задан радиальным пятном из центра.
     * На маленькой пилюле это выглядит как блик, но стоит растянуть тот же
     * набор на широкую карточку — и края уходят в тёмный #5847af, а
     * середина остаётся светлой: панель читается как прожектор. Материал
     * обязан работать на любой ширине, поэтому свет идёт сверху вниз, а
     * блик остаётся отдельным мягким слоем.
     */
    background:
        radial-gradient(90% 70% at 50% 0%,
            rgba(255, 255, 255, 0.55) 0%,
            rgba(255, 255, 255, 0) 72%),
        linear-gradient(180deg,
            var(--ui-ivory-light) 0%,
            var(--ui-ivory) 45%,
            var(--ui-ivory-dark) 100%);
    border: var(--ui-border) solid var(--ui-border-ivory);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-edge-ivory), var(--ui-shadow-soft),
                inset 0 1px 0 rgba(255, 255, 255, 0.5);
    color: var(--ui-text-ivory);
}

/* ----- INSET_DARK — утопленная область внутри панели --------------------- */
/* Прогресс, статистика, задача, предмет, карточка соперника: всё, что по
   смыслу лежит «внутри» панели, а не поверх неё. */
/* Тёмная заливка тёплая и неглубокая: на референсе выемка внутри доски
   ровно на ступень темнее самой доски (#231660 → #1b124b), а не чёрная. */
.ui-inset-dark {
    background: linear-gradient(180deg, rgba(6, 5, 24, 0.30) 0%, rgba(6, 5, 24, 0.16) 100%);
    border: 1px solid rgba(0, 0, 0, 0.5);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-inner-well), 0 1px 0 rgba(238, 236, 255, 0.06);
    color: var(--ui-text-main);
}

/* ==========================================================================
   КНОПКИ

   Общая часть вынесена в .ui-button, цвет — отдельным материалом. Физика
   нажатия одинаковая у всех: нажал — ушла вниз, нижняя грань уменьшилась.
   ========================================================================== */

.ui-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-space-2);
    min-height: var(--ui-tap);
    padding: 0 var(--ui-space-5);
    border-radius: var(--ui-radius-md);
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-section);
    font-size: var(--ui-size-value);
    line-height: 1.1;
    text-align: center;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    /* Задержки клика в 300 мс быть не должно: игра живёт на касаниях. */
    touch-action: manipulation;
    transition: transform var(--ui-ease), box-shadow var(--ui-ease),
                filter var(--ui-ease);
}

/* Нажатие: кнопка уходит вниз ровно на высоту, которую теряет её грань, —
   поэтому низ остаётся на месте и элемент выглядит вдавленным, а не
   съехавшим. Класс .is-pressed нужен обработчику pointerdown, где касание
   Telegram не всегда доходит до :active. */
.ui-button:active,
.ui-button.is-pressed {
    transform: translateY(var(--ui-press));
    filter: brightness(0.96);
}

/* На настольном экране наведение только чуть осветляет: полагаться на него
   нельзя, на телефоне его не существует. */
@media (hover: hover) {

    .ui-button:hover { filter: brightness(1.05); }
}

.ui-button:disabled,
.ui-button.is-disabled {
    pointer-events: none;
    /*
     * Не «прозрачная кнопка»: выключенный элемент остаётся плотным, просто
     * перестаёт быть золотым. Полупрозрачность на пёстром фоне читается
     * как сбой отрисовки, а не как запрет.
     *
     * И не серая. Здесь стоял холодный #4e4387 → #4a3c3a: «ДОХОД СОБРАН»
     * в башне и «ПОЛУЧЕНО» в заданиях выглядели серыми плашками из чужого
     * интерфейса посреди тёплого дерева. Выключенная кнопка — это тоже
     * дерево, только тёмное и без блика.
     */
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-panel-dark) 100%);
    border-color: rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well), 0 3px 0 rgba(0, 0, 0, 0.4);
    color: var(--ui-locked-text);
    text-shadow: none;
}

/* ----- BUTTON_GOLD — главное действие -----------------------------------
   Корпус собран ровно так, как на кадрах: тёплая тёмно-коричневая кромка,
   ОДИН светлый блик в 1px под ней, спокойный амбровый корпус и тонкая
   грань снизу. Прежний набор давал три светлые линии подряд (кромка 2px
   кремом + белый блик + внутренняя тень), и кнопка выглядела обведённой
   дважды — это и читалось как «несуразно».                              */
.ui-button-gold {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
            var(--ui-gold-btn-hi) 0%,
            var(--ui-gold-btn-top) 6%,
            var(--ui-gold-btn) 46%,
            var(--ui-gold-btn-low) 100%);
    border: var(--ui-border) solid var(--ui-gold-btn-edge);
    box-shadow: var(--ui-edge-gold), var(--ui-shadow-soft),
                inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 55%, transparent),
                inset 0 -2px 4px color-mix(in srgb, var(--ui-gold-deep) 30%, transparent);
    /*
     * Надпись кремовая в тёмной обводке, а не коричневая.
     *
     * На всех шести кадрах референса главная кнопка подписана белой
     * буквой с толстым контуром: «ИГРАТЬ», «ИЗМЕНИТЬ», активная вкладка
     * «СКИНЫ». Коричневый капслок на золоте отличается от корпуса
     * меньше чем на две ступени яркости — под солнцем такая надпись
     * пропадает вместе с кнопкой. Контур же держит её и на светлом
     * блике сверху, и на тёмной фаске снизу.
     *
     * `--ui-text-dark` остаётся текстом на золоте там, где обводка
     * неуместна: мелкие значения в золотых плашках и бейджах.
     */
    color: var(--ui-ivory-light);
    /* Восемь смещений по 1px и ни одной падающей тени: контур в 2px
       смыкается внутри буквы, а тень на 3px даёт под надписью её
       тёмного двойника. Проверено на «ПОДЕЛИТЬСЯ» и «ЗАБРАТЬ». */
    text-shadow:
        -1px -1px 0 rgba(10, 8, 34, 0.92),  0   -1px 0 rgba(10, 8, 34, 0.92),
         1px -1px 0 rgba(10, 8, 34, 0.92),  1px  0   0 rgba(10, 8, 34, 0.92),
         1px  1px 0 rgba(10, 8, 34, 0.92),  0    1px 0 rgba(10, 8, 34, 0.92),
        -1px  1px 0 rgba(10, 8, 34, 0.92), -1px  0   0 rgba(10, 8, 34, 0.92);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.ui-button-gold:active,
.ui-button-gold.is-pressed {
    box-shadow: 0 1px 0 var(--ui-gold-btn-deep), var(--ui-shadow-soft),
                inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 40%, transparent);
}

/* ----- BUTTON_BROWN — второстепенные действия --------------------------- */
/* «Назад», «Позже», фильтры. С золотой кнопкой не соревнуется. */
.ui-button-brown {
    background: linear-gradient(180deg,
            var(--ui-panel-light) 0%,
            var(--ui-panel-main) 45%,
            var(--ui-panel-dark) 100%);
    border: var(--ui-border) solid var(--ui-border-warm);
    box-shadow: var(--ui-edge-brown), var(--ui-shadow-soft), var(--ui-inner-top);
    color: var(--ui-text-main);
}

.ui-button-brown:active,
.ui-button-brown.is-pressed {
    box-shadow: 0 2px 0 var(--ui-bg-deep), var(--ui-shadow-soft);
}

/* ----- DANGER — разрушительное и необратимое ---------------------------- */
/* Распустить клан, удалить, отказаться навсегда. Всё остальное — не danger:
   если красным покрасить обычное действие, красный перестанет значить
   «осторожно». */
.ui-button-danger {
    background: linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 55%, var(--ui-red-deep) 100%);
    border: var(--ui-border) solid var(--ui-border-dark);
    box-shadow: var(--ui-edge-danger), var(--ui-shadow-soft), var(--ui-inner-top);
    color: var(--ui-text-main);
}

.ui-button-danger:active,
.ui-button-danger.is-pressed {
    box-shadow: 0 2px 0 var(--ui-red-deep), var(--ui-shadow-soft);
}

/* ----- BUTTON_SUCCESS — «забрать» и только оно -------------------------- */
/* Зелёная кнопка означает «награда лежит и ждёт». Ею нельзя красить
   «купить», «в бой» и «дальше»: иначе игрок перестанет замечать награду. */
.ui-button-success {
    background: linear-gradient(180deg,
            var(--ui-green-light) 0%, var(--ui-green) 55%, var(--ui-green-deep) 100%);
    border: var(--ui-border) solid var(--ui-border-dark);
    box-shadow: var(--ui-edge-green), var(--ui-shadow-soft),
                inset 0 2px 0 rgba(255, 255, 255, 0.28);
    color: #f4ffe8;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.ui-button-success:active,
.ui-button-success.is-pressed {
    box-shadow: 0 2px 0 var(--ui-green-deep), var(--ui-shadow-soft);
}

/* ----- BUTTON_PREMIUM — VIP, сезонный пропуск, особое предложение ------- */
.ui-button-premium {
    background: linear-gradient(180deg,
            var(--ui-purple-light) 0%, var(--ui-purple) 52%, var(--ui-purple-dark) 100%);
    border: var(--ui-border) solid var(--ui-gold-dark);
    box-shadow: var(--ui-edge-purple), var(--ui-shadow-soft),
                inset 0 2px 0 rgba(255, 255, 255, 0.26);
    color: var(--ui-gold-light);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.ui-button-premium:active,
.ui-button-premium.is-pressed {
    box-shadow: 0 2px 0 var(--ui-purple-deep), var(--ui-shadow-soft);
}

/* ----- Состояние ожидания (§70 ТЗ) --------------------------------------- */
/*
 * Кнопка, отправившая запрос, обязана перестать принимать нажатия и
 * сказать об этом: без этого игрок жмёт «купить» трижды.
 *
 * Класс надевает служба `mvp/services/pending.service.js` — одна на всю
 * игру, — поэтому правило написано на любую кнопку, а не только на
 * `.ui-button`: кнопки разделов носят свои имена (`trumpamole__btn-par`,
 * `tam-lab__btn`, `claim-btn`), и списком их было бы не догнать. Слой
 * окна тоже носит `is-loading` (`modal-framework.js`), но он не кнопка и
 * под этот отбор не попадает.
 */
button.is-loading,
.ui-button.is-loading,
[role="button"].is-loading {
    pointer-events: none;
    color: transparent !important;
    /*
     * Обводка гасится вместе с заливкой.
     *
     * Подпись на золоте набрана кремовым в тёмной обводке (§21 рамы), а
     * обводку там даёт четвёрка `text-shadow`. От прозрачного цвета она
     * не исчезает: на кнопке магазина оставались пустые тёмные контуры
     * букв, и колечко крутилось поверх слова «КУПИТЬ».
     */
    text-shadow: none !important;
    -webkit-text-stroke-color: transparent;
    position: relative;
}

/*
 * Подпись гасится дважды. Прозрачный цвет снимает текст, лежащий в кнопке
 * без обёртки, а `visibility` — вложенную подпись со своим цветом: у
 * половины кнопок игры буквы живут в `<span>` с собственным правилом, и
 * они пережили бы прозрачность родителя, встав рядом с колечком.
 */
button.is-loading > *,
.ui-button.is-loading > *,
[role="button"].is-loading > * {
    visibility: hidden;
}

button.is-loading::after,
.ui-button.is-loading::after,
[role="button"].is-loading::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    /* Размер в `em`: у мелкой кнопки строки колечко не вылезет за корпус. */
    width: 1.4em;
    height: 1.4em;
    margin: -0.7em 0 0 -0.7em;
    border: 3px solid rgba(0, 0, 0, 0.32);
    border-top-color: var(--ui-ivory);
    border-radius: 50%;
    animation: ui-spin 0.7s linear infinite;
    visibility: visible;
}

@keyframes ui-spin { to { transform: rotate(360deg); } }

/*
 * Иконочная кнопка живёт в ui-components.css под именем .ui-icon-button.
 *
 * Здесь она была на этапе 10, пока компонентов ещё не существовало, но
 * размер и форма — свойства компонента, а не материала: словарь отвечает
 * за то, из чего элемент покрашен, а не за то, какой он ширины. Двух имён
 * у одной кнопки быть не должно, поэтому осталось одно.
 */

/* ==========================================================================
   СМЫСЛОВЫЕ СОСТОЯНИЯ
   ========================================================================== */

/* SUCCESS и INFO — оттенки для областей, а не кнопок: получено, засчитано,
   подсказка. Кнопкой остаётся золотая. */
.ui-tone-success {
    background: linear-gradient(180deg, var(--ui-green-light) 0%, var(--ui-green) 60%, var(--ui-green-deep) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.35);
    border-radius: var(--ui-radius-md);
    box-shadow: 0 4px 0 var(--ui-green-deep), var(--ui-shadow-soft), var(--ui-inner-top);
    color: var(--ui-text-main);
}

.ui-tone-info {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--ui-blue) 22%, transparent) 0%,
        color-mix(in srgb, var(--ui-blue) 8%, transparent) 100%);
    border: var(--ui-border) solid color-mix(in srgb, var(--ui-blue) 35%, transparent);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

.ui-tone-danger {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--ui-red-deep) 35%, transparent) 0%,
        color-mix(in srgb, var(--ui-red-deep) 25%, transparent) 100%);
    border: var(--ui-border) solid color-mix(in srgb, var(--ui-red-light) 40%, transparent);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

/* LOCKED — недоступно.
   Не прозрачность: обесцвеченный корпус, тёмный полог сверху и место под
   значок замка с текстом требования. Прозрачный элемент на пёстром фоне
   читается как ошибка отрисовки, а не как «пока рано». */
.ui-locked {
    position: relative;
    filter: grayscale(0.75);
    pointer-events: none;
}

.ui-locked::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: rgba(8, 7, 30, 0.55);
    pointer-events: none;
}

/* Содержимое замка (значок и требование) кладётся сюда — оно обязано
   оставаться читаемым поверх полога. */
.ui-locked > .ui-locked-note {
    position: relative;
    z-index: 1;
    filter: none;
}

.ui-locked-note {
    display: inline-flex;
    align-items: center;
    gap: var(--ui-space-2);
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-body);
    font-size: var(--ui-size-small);
    color: var(--ui-text-main);
    text-shadow: var(--ui-text-shadow-sm);
}

/* ==========================================================================
   ТИПОГРАФИЧЕСКИЕ РОЛИ
   ========================================================================== */

.ui-title {
    font-family: var(--ui-font-title);
    font-weight: var(--ui-weight-title);
    font-size: var(--ui-size-title);
    line-height: 1.15;
    color: var(--ui-text-main);
    text-transform: uppercase;
    letter-spacing: 0.01em;
    text-shadow: var(--ui-title-shadow);
}

.ui-section {
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-section);
    font-size: var(--ui-size-section);
    color: var(--ui-text-main);
}

.ui-value {
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-value);
    font-size: var(--ui-size-value);
    color: var(--ui-text-main);
}

.ui-body {
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-body);
    font-size: var(--ui-size-body);
    line-height: 1.4;
    color: var(--ui-text-main);
}

.ui-muted {
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-body);
    font-size: var(--ui-size-body);
    color: var(--ui-text-muted);
}

/* ==========================================================================
   ДОСТУПНОСТЬ
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

    .ui-button {
        transition: none;
    }

    .ui-button:active,
    .ui-button.is-pressed {
        transform: none;
    }
}
