/* ==========================================================================
   ui-frame.css — рама интерфейса по главному референсу `as/4.png`.

   Зачем отдельный файл. Словарь (`ui-tokens.css`) и библиотека
   (`ui-components.css`) описывают правильные цвета и правильные
   компоненты, но пятьдесят файлов разделов писались до них и рисуют
   свои поверхности сами: почти чёрная карточка с волосяной рамкой,
   заголовок простым текстом в пустоте, кнопка `.ui-btn--gold`, у которой
   вообще нет описания, — и она выходит белой системной кнопкой.

   Референс требует обратного: тёплое дерево вместо черноты, толстая
   кромка, направленная нижняя грань, заголовок на деревянной табличке,
   щит в навигации, тёмный чип ресурса с золотым ободком у значка.

   Поэтому файл подключается ПОСЛЕДНИМ и переопределяет материал —
   только материал. Размеры, сетки и раскладку разделов он не трогает:
   иначе полсотни живых экранов поедут.

   ПОЧЕМУ СПИСКИ СЕЛЕКТОРОВ ДЛИННЫЕ. Первый заход описывал материал для
   десятка классов — и рама легла на десяток экранов из двадцати шести,
   а остальные остались в старом материале: полупрозрачная чернота поверх
   размытой фотографии. Именно это владелец видел как «совсем не похоже».
   Поэтому здесь перечислены ВСЕ классы поверхностей, найденные по
   разделам (`-hero`, `-card`, `-row`, `-panel`, `-note`, `-chip`,
   `-empty`, `-tabs`). Список точный, а не по подстроке: `[class*=...]`
   зацепил бы `-hero-inner`, `-card-art`, `-row-note` и залил бы
   материалом внутренности, которым нужен другой материал.

   Порядок разделов: фон → таблички → подписи → ленты → панели →
   карточки → строки → утопленные поверхности → кнопки → чипы →
   вкладки → навигация → полосы → профиль → главная → служебное.
   ========================================================================== */

/* ==========================================================================
   1. ФОН

   Референс тёплый: под панелями видно дерево и землю, а не чёрный
   провал. Прежний фон уходил в #05040f — почти чёрный, из-за него любая
   панель выглядела наклейкой на пустоте.
   ========================================================================== */

/*
 * Фон — РОВНОЕ тёмное дерево, а не провал к чёрному.
 *
 * Замер по референсу: во всех шести кадрах поле под панелями держится в
 * узком коридоре #151244…#0d0a2c, то есть ровно на тоне --ui-panel-dark.
 * У нас же фон уезжал вниз к #060617, и нижняя половина любого экрана
 * превращалась в чёрную дыру: карточка сверху выглядела доской, а точно
 * такая же карточка снизу — наклейкой на пустоте. Именно этот провал
 * читался как «совсем не похоже на референс».
 *
 * Перепад с панелями остаётся: панель --ui-panel-main на ступень светлее
 * фона, и её отделяет не разница в яркости фона, а тёмная кромка с
 * направленной нижней гранью — как на всех кадрах.
 */
body {
    /*
     * Фон по кадрам `grok/8-9.png`: почти чёрный сине-фиолетовый, ровный,
     * с одним мягким лиловым свечением сверху. Прежний тёплый градиент по
     * дереву снят вместе со всей коричневой темой.
     */
    background:
        var(--ui-dirt-wide),
        radial-gradient(120% 70% at 50% -10%,
            color-mix(in srgb, var(--ui-purple-light) 30%, transparent) 0%,
            color-mix(in srgb, var(--ui-purple) 12%, transparent) 45%,
            rgba(0, 0, 0, 0) 75%),
        linear-gradient(180deg,
            var(--ui-bg-dark) 0%,
            var(--ui-bg-dark) 45%,
            var(--ui-bg-deep) 100%);
}

/* ==========================================================================
   2. ТАБЛИЧКА ЗАГОЛОВКА

   В референсе у каждого экрана деревянная вывеска с широкими краями, а
   не строка текста. Форма собрана из трёх слоёв: корпус, светлая фаска
   сверху и тёмная грань снизу — тот же приём, что у кнопки.

   Второй заход по кадру 2 («КАРТА УРОВНЕЙ»), замеры при коэффициенте
   1.18. Расхождений было три, и все заметные:

   1. Вывеска там ШИРОКАЯ — 190px кадра из 317, то есть около 60 %
      экрана, и стоит между двумя круглыми кнопками. У нас она была
      `fit-content`: «ШОП» давал табличку в 90px, и она читалась как
      кнопка, а не как вывеска раздела.
   2. Сквозь неё проходит тонкая ПЕРЕКЛАДИНА — доска, уходящая к обоим
      краям экрана. У нас вместо неё стояли два прямоугольных «уха»
      высотой почти во всю табличку: они выглядели обрубками, а не
      продолжением доски.
   3. Надпись набрана плотным капслоком с тёмной обводкой. Unbounded
      здесь широкий и круглый: в вывеску влезает вдвое меньше букв, и
      длинные названия («ЕЖЕДНЕВНЫЕ ЗАДАНИЯ») ужимались до нечитаемого
      кегля.
   ========================================================================== */

.ui-plate,
.trumpamole__page-title,
.trumpamole__ref-hero-title,
.trumpamole__match3-page-title,
.trumpamole__arenapvp-page-title,
.trumpamole__tw-title,
.trumpamole__tasks-page-title,
.trumpamole__skins-hero .trumpamole__page-title,
.trumpamole__title-block .trumpamole__page-title {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 8px var(--ui-space-6);
    border-radius: var(--ui-radius-lg);
    /*
     * ВЫВЕСКА СТАЛА ЛИЛОВОЙ ПОЛОСОЙ ЗАГОЛОВКА.
     *
     * На каждом кадре `grok/8-9.png` экран подписан одинаково: широкая
     * лиловая полоса #34147A во всю ширину, белый капслок по центру,
     * круглая кнопка «назад» слева. Деревянной таблички там нет ни разу.
     */
    /*
     * Заклёпки в углах — прямо с кадра (§108 ТЗ: decorative bolts).
     *
     * У лиловой полосы группы на `grok/8.png` («MOLE SKINS», «POWER UPS»)
     * в верхних углах стоит маленький светлый ромб — единственная деталь,
     * которая отличает нарисованную деталь корпуса от закрашенного
     * прямоугольника. Значок лежит слоями фона, а не псевдоэлементом:
     * `::before` и `::after` вывески заняты — они принудительно погашены
     * ниже, потому что половина разделов рисует ими «уши».
     */
    background:
        var(--ui-bolt) left 12px top 9px / 16px 16px no-repeat,
        var(--ui-bolt) right 12px top 9px / 16px 16px no-repeat,
        var(--ui-dirt-wide),
        linear-gradient(180deg,
            var(--ui-head-light) 0%,
            var(--ui-head) 45%,
            var(--ui-head-dark) 100%);
    border: var(--ui-border) solid color-mix(in srgb, var(--ui-purple-glow) 35%, transparent);
    box-shadow:
        0 4px 0 var(--ui-purple-deep),
        var(--ui-shadow-soft),
        inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 35%, transparent);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: 24px;
    line-height: 1.05;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--ui-ivory-light);
    /* Обводка, а не мягкая тень: на кадрах у надписи вывески чёткий
       тёмный контур, он и держит её на светлеющем к верху дереве. */
    text-shadow:
        -2px -2px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 2px -2px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -2px  2px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 2px  2px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
         0    4px 0 color-mix(in srgb, var(--ui-text-outline) 50%, transparent);
    text-align: center;
    /*
     * ПОЛОСА ЗАГОЛОВКА ВО ВСЮ ШИРИНУ.
     *
     * На кадрах `grok/8-9.png` («SHOP», «PROFILE», «QUESTS», «SKINS»,
     * «TOWER», «MAPS», «EVENT», «LEADERBOARD», «INVENTORY») экран всегда
     * подписан одинаково: лиловая полоса от края до края, белый капслок
     * по центру, круглая кнопка «назад» слева. Табличка `fit-content`
     * шириной в 60 % была из прежнего, деревянного контракта.
     */
    width: 100%;
    max-width: none;
    margin-left: 0;
    margin-right: 0;
    align-self: stretch;
    border-radius: var(--ui-radius-md);
}

/*
 * ПЕРЕКЛАДИНЫ НЕТ.
 *
 * Прошлый заход дорисовал вывеске «уши» — доску, уходящую к обоим краям
 * экрана. Приём взят с кадра «КАРТА УРОВНЕЙ», но там сквозь вывеску
 * проходит полоса шапки между двумя круглыми кнопками, а у нас она
 * оказалась двумя обрубками, прилипшими к табличке по бокам. Владелец
 * назвал их «боковыми ерундовинами» и потребовал вид страницы «ДРУЗЬЯ»,
 * где вывеска стоит одна.
 *
 * Правило `content: none` оставлено явным (а не удалением блока):
 * у половины разделов свои `::before/::after` на этом же селекторе
 * прописаны в файлах разделов, и их тоже нужно снять.
 */
.ui-plate::before,
.ui-plate::after,
.trumpamole__page-title::before,
.trumpamole__page-title::after,
.trumpamole__tasks-page-title::before,
.trumpamole__tasks-page-title::after,
.trumpamole__ref-hero-title::before,
.trumpamole__ref-hero-title::after,
.trumpamole__match3-page-title::before,
.trumpamole__match3-page-title::after,
.trumpamole__arenapvp-page-title::before,
.trumpamole__arenapvp-page-title::after,
.trumpamole__tw-title::before,
.trumpamole__tw-title::after {
    content: none;
}

/* Блок заголовка вместе с подписью тоже собирается по центру. */
.trumpamole__title-block {
    align-items: center;
    text-align: center;
}

/*
 * Полоса заголовка не режет вывеску.
 *
 * «Уши» вывески выходят за её габарит, а верхние ленты разделов почти
 * все закрыты `overflow: hidden` — из-за этого края таблички исчезали и
 * она выглядела обычной тёмной плашкой.
 */
.tam-store__top-body,
.trumpamole__skins-title-box,
.trumpamole__title-block,
.trumpamole__tasks-title-block,
.trumpamole__arenapvp-title-block,
.trumpamole__match3-title-block,
.tam-arena__title-block {
    overflow: visible;
}

/* ==========================================================================
   3. ПОДПИСЬ СЕКЦИИ

   В референсе подпись внутри панели стоит по центру и набрана светлым
   капслоком: «ЛУЧШИЕ ДОСТИЖЕНИЯ», «НОВЫЕ СКИНЫ». Слева от края её там
   нет ни разу.
   ========================================================================== */

/* Колонка, а не строка: у половины заголовков есть подпись вторым
   элементом, и в строке она уезжала вправо от названия. */
.trumpamole__skins-section-header,
.trumpamole__leaderboard-section-header,
.trumpamole__ref-section-header,
.trumpamole__arenapvp-section-header,
.trumpamole__profile-section-header,
.trumpamole__tasks-section-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    margin: var(--ui-space-5) 0 var(--ui-space-3);
    text-align: center;
    /* Колонка увела вниз и кнопки, стоявшие в строке справа от подписи:
       обновление списка друзей висело отдельным кружком под заголовком.
       Такие кнопки уходят в угол абсолютом, а подпись остаётся по центру. */
    position: relative;
}

/* Кнопка при подписи секции — в правом углу строки, а не под ней. */
.trumpamole__ref-header-right {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
}

.trumpamole__skins-section-header > span,
.trumpamole__skins-section-header .trumpamole__hint,
.trumpamole__leaderboard-section-header .trumpamole__hint,
.trumpamole__ref-section-header .trumpamole__hint,
.trumpamole__profile-section-header .trumpamole__hint,
.trumpamole__tasks-section-header .trumpamole__hint,
.trumpamole__arenapvp-section-header .trumpamole__hint,
/* «Найдено 5 из 10 · пыль 270» под вывеской музея — та же вторая строка
   подписи секции, только стоит она не внутри `...-section-header`, а
   прямо в шапке витрины. Раздел держал у себя её копию тремя
   объявлениями. */
.tam-museum__sub {
    color: var(--ui-text-muted);
    font-family: var(--ui-font-main);
    font-size: var(--ui-size-small);
    font-weight: var(--ui-weight-body);
}

.trumpamole__skins-section-header h2,
.trumpamole__skins-section-header h3,
.trumpamole__leaderboard-section-header h2,
.trumpamole__ref-section-header h2,
.trumpamole__arenapvp-section-header h2,
.trumpamole__profile-section-header h2,
.trumpamole__tasks-section-header h2,
.trumpamole__leaderboard-top-title,
.tam-vault__section-title,
.tam-hero__story-title,
/* «МУЗЕЙ АРТЕФАКТОВ» — подпись секции витрины в профиле. Раздел набирал
   её своей копией этих же семи объявлений вместе с пятью тенями
   обводки: при смене кегля подписей музей остался бы один в старом. */
.tam-museum__title {
    position: relative;
    margin: 0;
    padding: 0 var(--ui-space-3);
    /*
     * Подпись секции набрана тем же плотным капслоком с обводкой, что и
     * вывеска: «ЛУЧШИЕ ДОСТИЖЕНИЯ», «НОВЫЕ СКИНЫ», «РЕСУРСЫ» на кадрах
     * — это белая буква в тёмном контуре, а не серый мелкий текст.
     */
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-value);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ui-ivory-light);
    /*
     * Центрирование задаётся самой подписью, а не только контейнером.
     *
     * Половина подписей стоит не внутри `...-section-header`, а прямо в
     * разделе: «ИСТОРИЯ ГЕРОЯ» в снаряжении, «НА СТОЛЕ» в лаборатории,
     * «ЗАПИСИ» в хронике. Они получали набор отсюда, но выравнивание —
     * от своего блока, и оставались у левого края, пока соседние подписи
     * стояли по центру. На кадрах референса подписи секций всегда по
     * центру панели.
     */
    text-align: center;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
         0    3px 0 color-mix(in srgb, var(--ui-text-outline) 45%, transparent);
}

/*
 * Планок по бокам подписи нет.
 *
 * Их поставил первый заход, чтобы заголовок «не висел в воздухе». На
 * референсе таких планок нет ни у одной из шести подписей: держит их
 * та же обводка, что и надпись вывески. Две светлые чёрточки рядом с
 * капслоком читались как обрезанная линейка.
 */
.trumpamole__skins-section-header h2::before,
.trumpamole__skins-section-header h2::after,
.trumpamole__leaderboard-section-header h2::before,
.trumpamole__leaderboard-section-header h2::after,
.trumpamole__ref-section-header h2::before,
.trumpamole__ref-section-header h2::after,
.trumpamole__arenapvp-section-header h2::before,
.trumpamole__arenapvp-section-header h2::after {
    content: none;
}

/* ==========================================================================
   4. ВЕРХНЯЯ ЛЕНТА РАЗДЕЛА

   Главная беда старого интерфейса: лента раздела — это размытая
   фотография интерьера, поверх неё полупрозрачная чернота
   `rgba(0,0,0,.18)`, а на этом стоит содержимое. Получается серо-бурый
   туман, в котором не читается ни арт, ни текст, и ни одна поверхность
   не имеет края.

   В референсе (кадры 3, 4, 5) верх раздела — плотная деревянная доска с
   толстой тёмной кромкой и направленной нижней гранью. Арт остаётся, но
   уходит в фактуру: он подсказывает место, а не спорит с содержимым.

   Ленты игровых экранов (главная, «три в ряд») сюда не входят: там арт —
   это сама игра.
   ========================================================================== */

.trumpamole__profile-hero,
.trumpamole__leaderboard-hero,
.trumpamole__ref-hero,
.trumpamole__ref-card-full,
.trumpamole__skins-hero,
.trumpamole__skins-active-full,
.trumpamole__tasks-hero,
.trumpamole__arenapvp-hero,
.tam-store__top,
.tam-event-hero {
    /*
     * Лента — это ФОН, а не поверхность.
     *
     * Первый заход сделал её светлым деревом, и экран стал плоским:
     * панель того же тона лежала на панели, кромки не читались. На
     * кадрах 3-5 референса верх раздела такой же тёмный, как всё
     * остальное поле, и светлые в нём только вывеска и карточки —
     * именно этот перепад и делает панели объёмными.
     *
     * Но «такой же тёмный» на референсе — это #1c1750, а не чернота.
     * Лента у половины разделов ростом во весь экран (в профиле она
     * 646px), и градиент до #060617 закрашивал низ страницы чёрным.
     * Поэтому тон ровный, как у фона: разницу даёт нижняя грань.
     */
    background:
        var(--ui-dirt-wide),
        linear-gradient(180deg,
        var(--ui-wood) 0%,
        var(--ui-panel-dark) 45%,
        var(--ui-bg-dark) 100%);
    border-bottom: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 6px 0 rgba(0, 0, 0, 0.45), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 18%, transparent);
}

/* Слой фотографии: из главного изображения в фактуру доски. */
.trumpamole__profile-hero::before,
.trumpamole__leaderboard-hero::before,
.trumpamole__leaderboard-league-panel::before,
.trumpamole__leaderboard-podium-wrap-full::before,
/* Полоса побед и поражений дуэли — тот же подиум, что в рейтинге. Своей
   записи здесь не было, и раздел глушил фотографию сам: `saturate(.5)`
   с `brightness(.6)` вместо общих 0.94 — колизей под медалями оставался
   единственной серо-бурой картинкой игры. */
.trumpamole__arenapvp-podium-wrap-full::before,
.trumpamole__ref-hero::before,
.trumpamole__ref-card-full::before,
.trumpamole__skins-hero::before,
.trumpamole__skins-active-full::before,
.trumpamole__tasks-hero::before,
.trumpamole__arenapvp-hero::before {
    /*
     * Картинка раздела ВИДНА, а не угадывается.
     *
     * Стояло 0.24 с размытием в 2px и яркостью 0.6 — рисунок магазина,
     * скинов и рефералов превращался в бурое пятно, и владелец сказал
     * прямо: фоновые изображения нужно сделать заметнее. На кадрах
     * референса верх раздела — читаемая иллюстрация: видно и «TRUMP
     * TOWER», и фонтан на карте, и лестницу в профиле.
     *
     * Порог держит НЕ прозрачность, а тёмная накладка ::after ниже: она
     * тянет низ ленты к --ui-panel-dark, поэтому подпись и вывеска стоят
     * на ровном тоне при любой картинке. Размытие оставлено, но в 1px:
     * оно снимает шум JPEG, не превращая рисунок в кисель.
     */
    /* Второй заход по прямому указанию владельца: «фоновые изображения
       сделай ещё чуть более видимыми на страницах типа скины, магазин,
       рефералы». 0.52 → 0.66, яркость 0.86 → 0.94. Читаемость держит
       накладка ::after ниже, а не приглушение самой картинки. */
    opacity: 0.66;
    filter: blur(1px) saturate(1) brightness(0.94);
}

/*
 * Верх магазина держит фотографию отдельной картинкой, а не фоном
 * псевдоэлемента, поэтому в список выше он не попадал и остался в старом
 * материале: портрет за вывеской «МАГАЗИН» читался как иллюстрация и
 * спорил с надписью. Значения те же — расходиться этим двум слоям нельзя.
 */
.tam-store__top-art img {
    /* Второй заход по прямому указанию владельца: «фоновые изображения
       сделай ещё чуть более видимыми на страницах типа скины, магазин,
       рефералы». 0.52 → 0.66, яркость 0.86 → 0.94. Читаемость держит
       накладка ::after ниже, а не приглушение самой картинки. */
    opacity: 0.66;
    filter: blur(1px) saturate(1) brightness(0.94);
}

/* Затемнение над фотографией: тёплое, а не серо-чёрное. */
.trumpamole__profile-hero::after,
.trumpamole__leaderboard-hero::after,
.trumpamole__leaderboard-league-panel::after,
.trumpamole__leaderboard-podium-wrap-full::after,
.trumpamole__arenapvp-podium-wrap-full::after,
.trumpamole__ref-hero::after,
.trumpamole__ref-card-full::after,
.trumpamole__skins-hero::after,
.trumpamole__skins-active-full::after,
.trumpamole__tasks-hero::after,
.trumpamole__arenapvp-hero::after,
/* Верх магазина держит фотографию отдельным слоем (`__top-art`), и
   затемнение у него своё — на псевдоэлементе этого слоя. Копия
   градиента жила в `store.css` и уже разошлась с общим на сотые доли
   и на оттенок синего. Расходиться этим двум слоям нельзя. */
.tam-store__top-art::after {
    /*
     * Накладка стала верхом ленты, а не вуалью поверх картинки: сверху
     * почти прозрачно (рисунок виден), к низу выходит на тон панели,
     * чтобы вывеска и подпись стояли на ровном фоне. Так картинку можно
     * было отпустить до 0.52, не потеряв читаемость текста.
     */
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--ui-bg-dark) 10%, transparent) 0%,
        color-mix(in srgb, var(--ui-bg-dark) 46%, transparent) 46%,
        color-mix(in srgb, var(--ui-bg-dark) 88%, transparent) 82%,
        color-mix(in srgb, var(--ui-bg-dark) 97%, transparent) 100%);
}

.trumpamole__leaderboard-league-panel,
.trumpamole__leaderboard-podium-wrap-full,
.trumpamole__arenapvp-podium-wrap-full {
    background:
        var(--ui-dirt-wide),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-panel-dark) 100%);
}

/*
 * Реплика лиги — карточка, а не мутный прямоугольник.
 *
 * Стрелки переключения лиг лежали поверх текста и накрывали последнее
 * слово описания: у реплики теперь есть поля под них.
 */
.trumpamole__leaderboard-speech {
    background:
        var(--ui-dirt-wide),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-panel-dark) 100%);
    border: var(--ui-border) solid color-mix(in srgb, var(--ui-purple-glow) 28%, transparent);
    border-radius: var(--ui-radius-lg);
    box-shadow: 0 4px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 25%, transparent);
    padding-right: 42px;
}

.trumpamole__leaderboard-nav-btn {
    width: 40px;
    height: 40px;
    border-radius: var(--ui-radius-md);
    background:
        var(--ui-dirt-wide),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid color-mix(in srgb, var(--ui-purple-glow) 28%, transparent);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.5), var(--ui-inner-top);
    color: var(--ui-gold-light);
}

/*
 * Двойного приглушения у шапки магазина нет.
 *
 * Здесь стояло `opacity: 0.34` НА КОНТЕЙНЕРЕ, а картинка внутри него
 * получала ещё 0.66 своим правилом: в сумме 0.22 — от лавки оставалось
 * бурое пятно. Владелец потребовал вернуть фоновую картинку «как везде»,
 * поэтому приглушает ровно один слой — сама картинка.
 */
.tam-store__top-art {
    opacity: 1;
    filter: none;
}

/*
 * Лента раздела собирается по центру.
 *
 * Прежняя сетка «1fr | 120px» держала место под значок раздела, и
 * вывеска вместе с подписью центровалась не по экрану, а по левой
 * колонке — на глаз это выглядело сдвигом влево. Значок есть у трёх
 * разделов из десяти, поэтому он уходит в правый край поверх ленты, а
 * текст получает всю ширину.
 */
.trumpamole__skins-hero-inner,
.trumpamole__tasks-hero-inner {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
}

.trumpamole__tasks-title-block {
    align-items: center;
    text-align: center;
}

/* Значок раздела в шапке заданий повторял вывеску и отнимал полосу. */
.trumpamole__tasks-top-icon {
    display: none;
}

/*
 * Значок раздела снят: он повторял то, что и так нарисовано фоном
 * ленты, а в один столбец наезжал на кнопку сбора дохода в башне.
 * Раздел узнаётся по фону и вывеске — как на всех кадрах референса.
 */
.trumpamole__skins-hero-icon {
    display: none;
}

/*
 * Строка счётчиков ленты — ВО ВСЮ ШИРИНУ, как в магазине.
 *
 * Здесь стояло `justify-content: center`, и пара чипов собиралась в
 * кучку посреди полосы: «ВЫПОЛНЕНО 4» и «ПОЛУЧЕНО 0» в заданиях,
 * «МОНЕТЫ» и «ЗЕМЛЯ» в скинах занимали половину ширины, а по бокам
 * оставались пустые поля. В магазине те же два чипа расходятся от края
 * до края и держат полосу — владелец потребовал этот вид везде.
 *
 * `flex: 1 1 0` вместо `1 1 auto` намеренно: чипов в ряду два-три, и
 * равные доли выглядят ровнее, чем ширина по длине подписи.
 */
.tam-cos__stats,
.trumpamole__skins-stats-row,
.trumpamole__tasks-stats-row,
.trumpamole__arenapvp-stats-row {
    display: flex;
    align-items: stretch;
    justify-content: stretch;
    gap: var(--ui-space-3);
    width: 100%;
    max-width: none;
}

.tam-cos__stats > *,
.trumpamole__skins-stats-row > *,
.trumpamole__tasks-stats-row > *,
.trumpamole__arenapvp-stats-row > * {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
}

/* ==========================================================================
   5. ПАНЕЛЬ РАЗДЕЛА

   Тело раздела — не поверхность, а место для карточек: своего материала
   у него быть не должно, иначе экран превращается в панель на панели.
   ========================================================================== */

.trumpamole__skins-main-panel,
.trumpamole__profile-main-panel,
.trumpamole__leaderboard-main-panel,
.trumpamole__ref-main-panel,
.trumpamole__tasks-main-panel,
.trumpamole__arenapvp-main-panel {
    background: transparent;
    border: 0;
}

/*
 * Боковое поле раздела — ОДНО на всю игру.
 *
 * Здесь стоял только `skins-main-inner` на 12px, а лента над ним держала
 * свои 14px, задания — 14, магазин — 12, инвентарь — 16, главная — 10.
 * Перескок в 2-6px виден при переходе между вкладками: край столбца
 * содержимого дёргается влево-вправо, хотя карточки одни и те же. Список
 * ниже — все «столбцы содержимого» игры; они берут поле из
 * `--ui-gutter`, который к тому же сужается на узком экране.
 *
 * Новый раздел дописывать сюда, а не заводить своё число.
 */
.trumpamole__skins-hero-inner,
.trumpamole__skins-active-inner,
.trumpamole__profile-hero-inner,
.trumpamole__tasks-hero-inner,
.trumpamole__skins-main-inner,
.trumpamole__profile-main-inner,
.trumpamole__tasks-main-inner,
.tam-store__top-body,
.tam-hero__head,
.tam-inv__bottom,
.tam-challenge,
.trumpamole__home {
    padding-left: var(--ui-gutter);
    padding-right: var(--ui-gutter);
}

/* ==========================================================================
   6. КАРТОЧКИ

   Один материал на всю игру: корпус светлее фона, толстая тёмная кромка,
   светлая фаска сверху, направленная грань снизу. Это и есть главный
   приём референса — каждая поверхность выглядит вырезанной из дерева.
   ========================================================================== */

.ui-card,
.tam-arena__card,
.tam-arena__rival,
.tam-arena__poster,
.tam-arena__defense,
.tam-blocker__card,
/* Цель вызова — главная и единственная панель приземления: без записи
   здесь она держала свой градиент и волосяную кромку в 1px, то есть
   ровно тот плоский card, что запрещает §62. */
.tam-challenge__target,
/* Кланы: карточка клана в шапке вкладки, карточка задачи, три доски
   штаба и карточка облавы. Все шесть красили себя сами полупрозрачной
   чернотой с золотой волосяной рамкой — тем самым плоским card, который
   §62 запрещает поимённо. Класса `.tam-clan__card`, стоявшего здесь
   раньше, в разметке игры нет ни одного: строка была мёртвой. */
.tam-clan__head,
.tam-clan__task,
.tam-hq__project,
.tam-hq__wall,
.tam-hq__perks,
.tam-raid,
.tam-col__card,
/* Сцена стойки молотов, плитка молота в ряду под ней и полка витрины
   профиля. Все три заливали себя сами — градиент по прозрачной черноте
   с золотой линией в 1px, — и вкладки «МОЛОТКИ» и «ТРОФЕИ» оставались
   единственными в коллекции без кромки и направленной грани. */
.tam-col__rack-stage,
.tam-col__rack-item,
.tam-col__showcase,
.tam-cos__card,
.tam-cos__base-card,
/* Сцена предпросмотра гардероба: своей записи у неё не было, и она
   осталась единственной коричневой доской экрана посреди фиолетовых
   карточек — ровно тот «обычный чужой card», что запрещает §62. */
.tam-cos__stage,
.tam-lab__card,
.tam-museum__card,
.tam-rivalry__card,
.tam-share__card,
.tam-store__card,
.tam-store__item,
.tam-item,
.tam-vault__card,
.trumpamole__arenapvp-card,
/* Карточка боя дуэли — самая крупная поверхность своего экрана: во время
   боя она занимает его целиком. Своей записи здесь не было, и она
   заливала себя прозрачной чернотой в 22 % без кромки и грани; поверх
   этого вариант `.has-arena` вешал внутреннюю тень, которая перебивала бы
   и материал, взятый отсюда. */
.trumpamole__arenapvp-match,
.trumpamole__map-card,
/* Шапка карты: название раздела и две плитки сводки. Своей записи не
   было, и она осталась единственной доской экрана, собранной по
   `--brown-*` — на пол-тона мимо карточек остальной игры. */
.trumpamole__map-head,
.trumpamole__profile-pick-card,
.trumpamole__ref-card,
.trumpamole__return-card,
.trumpamole__skins-card,
.trumpamole__tasks-card,
.trumpamole__tasks-info-card,
/* Плитка дня в ленте ежедневных наград и доска важных дел. Первая
   держала свою копию этого материала числами (#26196a → #1a1148), то
   есть на полтона мимо карточек остальной игры; вторая заливала себя
   чернотой в 18 % без единой кромки и вешала поверх содержимого ещё
   один тёмный градиент — ровно тот плоский card, что запрещает §62. */
.trumpamole__tasks-card-mini,
.trumpamole__tasks-important-wrap,
.trumpamole__tw-sheet-card,
.tam-event-card,
.tam-event-goods,
.tam-event-ms,
.tam-event-next,
.tam-event-story,
.tam-event-task,
.tam-season__chapter,
/* История героя (§5) и ступени сета (§6) — такие же панели, как всё
   остальное на экране героя: без записи здесь они остались бы в старом
   материале и выглядели бы дырой посреди раздела. */
.tam-hero__story,
.tam-set,
/* Полоса босса над полем боя: имя, портрет и точки частей. Своей записи
   здесь не было, и полоса держала копию корпуса числами
   (`rgba(37, 31, 100, .92)` → `rgba(11, 9, 37, .94)`) — то есть висела
   над тёмным полем ровно того же тона, что поле, без фактуры и без
   направленной грани. */
.tam-boss,
/* Состав призов колеса: панель держала свой градиент и золотую рамку в
   1px — единственная поверхность мини-игры вне общего материала. */
.trumpamole__fortune-oddsBox,
/* Карточка реплики сюжетной сцены. Она лежит поверх полноэкранного
   кадра, то есть это единственная поверхность на экране, — и держала
   свой градиент по `--brown-*` с волосяной рамкой в 1px. На кадре с
   персонажем такая подложка читается подписью к картинке, а не панелью
   игры: ни кромки, ни направленной грани, ни фактуры. */
.trumpamole__story-card,
/* Сцена кабинета на главной — самая крупная поверхность игры, и своей
   записи у неё не было: коробка держала кромку в 2px чёрным по 45 % и
   заливку `--brown-0`, то есть висела на экране без направленной грани,
   тогда как карточка «что делать» прямо под ней эту грань имеет.
   Заливка тут не видна — кадр закрывает её целиком, — но кромка и грань
   решают, читается сцена вырезанным окном или наклеенной картинкой. */
.trumpamole__home-scene {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-panel-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-lg);
    box-shadow:
        0 5px 0 var(--ui-panel-edge),
        var(--ui-shadow-soft),
        inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
    color: var(--ui-text-main);
}

/*
 * Редкость — кольцо ВНУТРИ кромки, а не сама кромка.
 *
 * Карточки редкости красили свой `border-color`. Пока кромка была
 * волосяной, это читалось как подсветка; с толстой кромкой референса
 * карточка получила ярко-синюю раму во весь периметр — в хранилище
 * шесть таких рам стояли рядом и спорили друг с другом. Кромка остаётся
 * почти чёрной у всех, а редкость даёт кольцо и свечение под ним.
 *
 * Карточки гардероба (`.tam-cos__card.is-<редкость>`) добавлены в те же
 * списки: редкость там была подписана только словом под названием, и
 * §15 ТЗ, требующий рамку, свечение и подпись СРАЗУ, выполнялся на
 * треть. Имя класса у них другое (`is-rare`, а не `--rare`) — вид
 * собирает его сам, и менять разметку ради единообразия имени
 * означало бы трогать рабочий JS без нужды.
 *
 * Плитки снаряжения (`.tam-item--<редкость>`) вошли сюда же. Вид
 * инвентаря писал этот класс с самого начала, а описания у него не было
 * ни одного: сорок вещей в полосе лежали одинаковыми досками, и легендарный
 * молот ничем не отличался от обычной рукавицы. Надетое (`.tam-item.is-on`,
 * вес 0-2-0) кольцо редкости не перебивает — состояние важнее качества.
 *
 * Прилавок магазина (`.tam-store__item--<редкость>`) и карточка
 * подходящего товара (`.tam-store__card--<редкость>`) — последние из
 * ряда. §28 ТЗ требует редкость на карточке товара прямо, а сорок вещей
 * снаряжения и десяток обликов лежали в витрине одинаковыми досками:
 * легендарная тема кабинета за 60 000 выглядела так же, как обычная
 * рукавица за 400. Редкость товару даёт его состав (`ShopProduct::rarity`),
 * у пакетов монет и энергии её нет вовсе — там кольца и не будет.
 */
.tam-vault__card--common,
.tam-col__card--common,
.tam-museum__card--common,
.tam-item--common,
.tam-store__item--common,
.tam-store__card--common,
.tam-cos__card.is-common {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-rar-common) 55%, transparent);
}

.tam-vault__card--uncommon,
.tam-col__card--uncommon,
.tam-museum__card--uncommon,
.tam-item--uncommon,
.tam-store__item--uncommon,
.tam-store__card--uncommon,
.tam-cos__card.is-uncommon {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-rar-uncommon) 62%, transparent),
                inset 0 0 14px color-mix(in srgb, var(--ui-rar-uncommon) 30%, transparent);
}

.tam-vault__card--rare,
.tam-col__card--rare,
.tam-museum__card--rare,
.tam-item--rare,
.tam-store__item--rare,
.tam-store__card--rare,
.tam-cos__card.is-rare {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-rar-rare) 62%, transparent),
                inset 0 0 14px color-mix(in srgb, var(--ui-rar-rare) 30%, transparent);
}

.tam-vault__card--epic,
.tam-col__card--epic,
.tam-museum__card--epic,
.tam-item--epic,
.tam-store__item--epic,
.tam-store__card--epic,
.tam-cos__card.is-epic {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-rar-epic) 62%, transparent),
                inset 0 0 14px color-mix(in srgb, var(--ui-rar-epic) 32%, transparent);
}

.tam-vault__card--legendary,
.tam-col__card--legendary,
.tam-museum__card--legendary,
.tam-item--legendary,
.tam-store__item--legendary,
.tam-store__card--legendary,
.tam-cos__card.is-legendary {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-gold) 68%, transparent),
                inset 0 0 16px color-mix(in srgb, var(--ui-gold) 34%, transparent);
}

.tam-vault__card--mythic,
.tam-col__card--mythic,
.tam-museum__card--mythic,
.tam-item--mythic,
.tam-store__item--mythic,
.tam-store__card--mythic,
.tam-cos__card.is-mythic {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-red-light) 62%, transparent),
                inset 0 0 16px color-mix(in srgb, var(--ui-red-light) 32%, transparent);
}

/*
 * 6.1. ПАНЕЛЬ ПРЕДЛОЖЕНИЯ — «НАБОР ПОБЕДИТЕЛЯ» с кадра as/5.png.
 *
 * Единственная карточка игры, которая не деревянная: особое предложение
 * стоит первым экраном магазина и обязано отличаться от прилавка под
 * ним. Цвета сняты пипеткой по вертикали при x=530 кадра — #4a1e6b
 * сверху, #612a7d в середине, #44235a у низа, светлый рим #74419c в
 * пиксель, тёмная кромка по периметру; в словаре это набор
 * `--ui-purple-panel-*`.
 *
 * Золотого канта на кадре нет: панель держит тот же тёмный контур, что
 * и всё остальное, а «дорого» говорит сам цвет.
 *
 * Материал переехал сюда из `store.css`, где рядом с ним лежал ещё и
 * золотой корпус «на случай обычного предложения» — класс `is-premium`
 * вид ставит всегда, и золотой набор не доходил до экрана ни разу.
 */
.tam-store__hero {
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-lg);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
        var(--ui-purple-panel-top) 0%,
        var(--ui-purple-panel) 34%,
        var(--ui-purple-panel) 62%,
        var(--ui-purple-panel-low) 100%);
    box-shadow:
        0 5px 0 var(--ui-purple-deep),
        var(--ui-shadow-deep),
        inset 0 1px 0 var(--ui-purple-panel-rim);
    color: var(--ui-text-main);
}

/* Картинка набора — та же выемка §8, но в кольце золота: на кадре у
   предмета предложения есть золотая рама, и это единственное золото
   панели помимо кнопки. */
.tam-store__hero-art {
    border: var(--ui-border) solid var(--ui-gold-dark);
    border-radius: var(--ui-radius-md);
    background: color-mix(in srgb, var(--ui-purple-deep) 62%, transparent);
}

/* Чип состава внутри фиолетовой панели — глубже её корпуса: тёмный чип
   §10 читался бы на ней заплаткой из другого набора. */
.tam-store__hero .tam-store__content {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-purple-dark) 0%, var(--ui-purple-deep) 100%);
    box-shadow: var(--ui-inner-well),
                inset 0 1px 0 color-mix(in srgb, var(--ui-purple-panel-rim) 50%, transparent);
}

/* ==========================================================================
   7. СТРОКИ СПИСКОВ

   Строка — та же доска, но тоньше: у списка из двадцати позиций
   направленная грань под каждой строкой превращает экран в лестницу.
   Поэтому кромка есть, а нижней грани нет.
   ========================================================================== */

.ui-row,
.trumpamole__row,
.trumpamole__ref-row,
.trumpamole__tasks-row,
.trumpamole__leaderboard-player-row,
.trumpamole__profile-support-row,
.trumpamole__profile-ach-row,
.tam-arena__ladder-row,
.tam-arena__log-row,
/* Строка дуэли — такой же список, как журнал боёв рядом: до правки она
   красилась парой `--rowA/--rowB` из старого словаря и стояла на пол-тона
   мимо соседей. */
.trumpamole__arenapvp-duel,
.tam-chr__row,
.tam-clan__donate-row,
/* Участник клана, клан в списке поиска и выбор проекта в штабе: те же
   строки списка, что журнал боёв рядом. Держали собственную заливку
   `rgba(20, 14, 12, .6)` — последний коричневый остаток тёплого мира в
   разделе, на фиолетовой доске читавшийся грязным пятном. */
.tam-clan__member,
.tam-clan__row,
.tam-hq__pick,
/* Таблица вклада в облаву стояла в списке карточек §6 и выходила вдвое
   тяжелее вех над ней: толстая кромка и направленная грань под каждой из
   десяти строк превращали таблицу в лестницу — ровно то, из-за чего у
   строки грани нет. */
.tam-raid__row,
.tam-col__dossier-row,
.tam-season__top-row,
/* Вход в сезон на странице заданий: кнопка-строка держала пару
   `var(--rowA, #2a1f1f)` — псевдоним с тёплой запаской прежнего мира.
   Запаска переживает смену палитры и врёт: там, где `--rowA` не
   объявлена, строка выходила бурой посреди фиолетового списка. */
.tam-season-banner,
.tam-tower__list-row,
/* Этаж лифта: строка держала собственную копию этого же градиента,
   написанную числами (#26196a → #1a1148), и стояла на пол-тона мимо
   всех остальных списков игры. */
.trumpamole__map-lift-floor,
/* Строка титула в окне выбора: держала ту же копию градиента числами. */
.tam-title__row,
/* Карточка соперника недели над таблицей лидеров: держала запаску
   `var(--rowA, #2a1f1f)` — псевдоним с бурым прямоугольником прежнего
   мира на случай, которого не бывает. Показывает она то же, что строка
   таблицы под ней, и материал у неё тот же. */
.tam-rivalry__card,
/* Строка рекорда Трампивуда: собственная заливка #2a1f1f → #241a1a была
   последней коричневой поверхностью квартала — две такие строки стояли
   бурыми брусками посреди фиолетового нижнего листа. */
.trumpamole__tw-record,
.tam-box-row {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 18%, transparent),
                var(--ui-shadow-xs);
    color: var(--ui-text-main);
}

/* Чередование строк остаётся, но в пределах одного материала. */
.trumpamole__row.alt,
.trumpamole__ref-row.alt,
.trumpamole__tasks-row.alt,
/* Строка рейтинга приходит из `leaderboard.js` с модификатором `--alt`,
   а не с классом `alt`: селектор `.trumpamole__leaderboard-player-row.alt`
   не совпадал ни разу, и вся таблица шла одним тоном без чередования. */
.trumpamole__leaderboard-player-row--alt,
.tam-arena__ladder-row.alt,
.tam-tower__list-row.alt,
/* Строка достижения чередовалась парой `--rowA/--rowB` из старого словаря:
   пока в раме её не было, полосатость держалась мимо материала списка. */
.trumpamole__profile-ach-row.alt,
/* В журнале боёв чередование считает браузер, а не разметка: строки
   приходят одним списком без класса `alt`. */
.tam-arena__log-row:nth-child(even) {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood) 100%);
}

/*
 * СВОЯ СТРОКА В ТАБЛИЦЕ — ЗОЛОТО ПОВЕРХ МАТЕРИАЛА (§27 ТЗ).
 *
 * `leaderboard.css` красил её в #2f2323 — бурый прямоугольник прежнего
 * мира, последний в разделе. Рецепт тот же, что у текущей лиги в лестнице
 * арены (`arena.css`, `.is-current`): подсветка ЛОЖИТСЯ на материал
 * строки, а не заменяет его, и держит пыль по золоту — ровная заливка
 * одним цветом выпадает из ряда сразу. Кольцо добавлено потому, что своя
 * строка стоит посреди сорока таких же, и одного оттенка ей мало. Кромкой,
 * а не кольцом через `box-shadow`: тень строке задана строкой выше, и
 * сокращённая запись погасила бы её ради одной линии.
 */
.trumpamole__leaderboard-player-row--me {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
            color-mix(in srgb, var(--ui-gold) 26%, var(--ui-panel-light)) 0%,
            color-mix(in srgb, var(--ui-gold) 14%, var(--ui-wood)) 100%);
    border-color: var(--ui-gold-dark);
    color: var(--ui-text-main);
}

/*
 * Итог таблицы взносов — подпись под списком, а не ещё одна строка.
 *
 * `clans.css` красил её в `--brown-2` с золотой цифрой, но `.tam-clan__donate-row`
 * стоит в списке выше, рама грузится последней — и «ВЕСЬ КЛАН» выходила
 * ровно такой же доской, как строка игрока над ней. Итог обязан читаться
 * иначе: корпус на ступень темнее строки, цифра золотая.
 */
.tam-clan__donate-row--sum {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-b) 0%, var(--ui-bg-dark) 100%);
    border-color: rgba(0, 0, 0, 0.55);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-gold-light);
}

/* ==========================================================================
   8. УТОПЛЕННЫЕ ПОВЕРХНОСТИ

   Значение, состав набора, портрет, пустое состояние, примечание — всё,
   что в референсе вырезано внутрь доски: тёмная заливка, внутренняя
   тень, без направленной грани.

   «Тёмная» здесь — тоже дерево. Замер по кадру профиля: доска #201a5e,
   вырезанная в ней плашка со счётчиком #171346 — на ступень темнее, и
   только. Прежняя заливка уходила к #0a0822, и вместо выемки в дереве
   получалась чёрная дыра: этим были заняты обе плашки трофеев в профиле
   и весь состав набора в магазине.
   ========================================================================== */

.ui-card__surface,
.trumpamole__ref-note,
.trumpamole__ref-field-value,
.trumpamole__reward-box,
.trumpamole__profile-showcase-empty,
.trumpamole__profile-tower-empty,
/* Часы дуэли — такое же окно времени, что часы боя: цифры вырезаны В
   доске. Держали прозрачную черноту в 40 % с волосяной лиловой линией,
   то есть висели над полем без края — а это единственное, на что игрок
   смотрит в последние секунды. */
.trumpamole__arenapvp-timer,
/* Состав набора на утопленной подложке — ТОЛЬКО в панели предложения.
   В карточке товара внутри состава лежит один чип («35 энергии»), и
   выемка под ним читалась плашкой в плашке: у карточки VIP она тянулась
   во всю ширину, а чип занимал её половину. */
.tam-store__hero .tam-store__contents,
.tam-store__item-art,
.tam-store__card-art,
.tam-arena__rival-block,
.tam-arena__defense-note,
.tam-arena__poster-note,
/* Суточные попытки арены: строка стоит между заголовком раздела и подиумом
   и до записи здесь заливала себя сама — полупрозрачный прямоугольник с
   волосяной рамкой, то есть ровно тот web-элемент, что запрещает §62. */
.tam-arena__attempts,
.tam-clan__task-note,
.tam-col__rack-note,
.tam-col__track-note,
.tam-cos__card-note,
.tam-hq__pick-note,
.tam-season__chapter-note,
.tam-season__source-note,
.tam-tower__floor-note,
.tam-tower__list-note,
.tam-card__stat,
/* Счёт серии вызовов: табло вырезано В экране, как любое значение. */
.tam-challenge__series,
/* Строка приза колеса: последние коричневые плитки игры (#2a1f1f). */
.trumpamole__fortune-odd,
.tam-chr__chip-icon,
/* Поиск по хронике и гнездо значка записи: обе выемки были выписаны
   руками (#171346 → #100e33) — это ровно `--ui-row-a` и
   `--ui-panel-dark` строкой ниже, то есть копия общего материала мимо
   словаря. Поле поиска — то же, что поиск клана и поиск офиса башни. */
.tam-chr__search-input,
.tam-chr__row-icon,
.tam-clan__apps,
.tam-clan__search,
/* Строка остатка взносов, шапка таблицы взносов и поля окна создания
   клана: значение и ввод вырезаны В доске. Первая заливала себя золотой
   плёнкой `rgba(245, 214, 90, .08)`, вторая — псевдонимом `--brown-2`,
   поля — прозрачной чернотой с волосяной рамкой. */
.tam-clan__donate-line,
.tam-clan__donate-head,
.tam-clanform__field input,
.tam-clanform__field textarea,
/* Кадр стройки штаба, картинка облавы и кружок с уровнем перка — тоже
   вырезы: под ними лежит изображение, а не корпус панели. */
.tam-hq__site,
.tam-hq__perk-level,
.tam-raid__art,
/* Выбор языка — единственный `<select>` игры. Он заливал себя сам
   (`rgba(0,0,0,.18)` с волосяной линией) и в ряду настроек читался
   светлой наклейкой на доске, а не полем. На кадре `grok/8.png`
   выпадающий список лиги тоже вырезан В панели. */
.trumpamole__select,
/* Поиск офиса в башне — то же поле, что поиск клана строкой выше. Своей
   записи здесь не было, и раздел заливал его сам, на полступени темнее
   общей выемки. */
.tam-tower__search-input,
.tam-cos__card-art,
/* Метка редкости и доступности в сцене гардероба: та же выемка, что
   плашка со значением рядом. Держала копию материала числами. */
.tam-cos__tag,
/* Метка редкости на карточке товара — та же выемка, что метка гардероба:
   одна редкость обязана выглядеть одинаково и в витрине, и в шкафу. */
.tam-store__tag,
.tam-discovery__kind,
.tam-discovery__progress,
.tam-event-wallet__item,
/* Кадр события в его собственном разделе: иллюстрация вырезана В доске,
   как картинка облавы и кадр стройки штаба. Своей записи не было, и
   раздел обводил её волосяной лиловой линией в 1px. */
.tam-event-scene,
/* «Сейчас тихо» и «Сезон завершён» переехали на общий блок §56
   (`.ui-empty` ниже по файлу), и материал им теперь приходит оттуда:
   записи здесь и на шаге скругления сняты, чтобы одна поверхность не
   собиралась из двух правил. */
/* Место на полке витрины профиля: слот вырезан В доске, как гнездо
   значка хроники. Заливал себя своим градиентом по прозрачной черноте,
   и пустой слот держался на `opacity: .72` — сквозь него просвечивал
   фон раздела. */
.tam-col__slot,
.tam-hero__level,
.tam-hq__builder,
.tam-hq__perk,
.tam-hq__trophy,
.tam-lab__need,
.tam-museum__hint,
.tam-museum__kind,
.tam-raid__step,
.tam-result__goal,
.tam-rivalry__stat,
.tam-season-banner__art-frame,
.tam-season__cell,
.tam-season__source,
.tam-season__tier,
.trumpamole__arenapvp-reward-item,
/* Доска бонусной игры и лицо открытой карточки: предмет лежит В выемке
   доски, а не на ней. Без записи здесь партия шла на прозрачном фоне. */
.tam-bonusgame__board,
.tam-bonusgame__face--front,
/* Манекен и комната офиса в гардеробе: предпросмотр вырезан В сцене,
   а не лежит на ней — иначе тёмный квадрат читается дырой. */
.tam-cos__dummy,
.tam-cos__room,
/* Поле «три в ряд»: доска вырезана В панели раздела. Своей записи здесь
   не было, и раздел заливал её сам от `--ui-bg-deep` — до начала партии,
   когда на поле ещё нет ни одной фишки, это давало ровно ту чёрную дыру
   во весь экран, про которую сказано в заголовке §8. Геометрию (радиус
   панели, толстая кромка) доска держит у себя. */
.trumpamole__match3-board,
.trumpamole__match3-goal-tag,
.trumpamole__return-card-icon,
.trumpamole__row-icon,
.trumpamole__skins-owned-mini,
.trumpamole__skins-price-row,
/* Холодная серая заливка rgba(11, 9, 37,…) — последнее наследство
   старой палитры: на тёплом дереве она читается дырой, а не выемкой.
   Плашки башни в профиле и подписи узлов карты жили именно в ней. */
.trumpamole__profile-tower,
/* Лучший офис и любимая комната — примечание внутри блока башни. Плитки
   показаний оттуда ушли к общим `.tam-stat` (§10): вырез в вырезе с
   одинаковым материалом объёма не давал. */
.trumpamole__profile-tower-note,
/* Полка витрины: трофеи стоят В вырезе доски. Своей записи у неё не
   было вовсе, и заполненная витрина висела картинками на пустом месте. */
.trumpamole__profile-shelf,
/* Карточка соперника из списка лидеров: полка трофеев, плитки счётчиков
   и гнездо портрета. Все три держали свой материал числами (#181043,
   #1d1351, `--ui-panel-main` до `--ui-bg-deep`) — три варианта одной и
   той же выемки, стоящие мимо таких же плиток профиля. */
.trumpamole__guest-shelf,
.tam-guest__stat,
.tam-guest__avatar,
/* «Твоё место» под таблицей лидеров — подпись к списку, а не строка в
   нём: своя заливка #1f1515 была последней коричневой поверхностью
   раздела. */
.trumpamole__leaderboard-you-separator,
.trumpamole__map-count,
.trumpamole__map-teaser,
/* Значок задания стоит в такой же выемке, что предмет в хранилище, и
   держал её своей копией числами (#1d1351 → #140d38). Запись ожидания
   заданий отсюда снята вместе с их спиннером: список ждёт общим блоком
   §55, а он берёт выемку в конце файла вместе с пустым местом. */
.trumpamole__tasks-left-icon,
/* Лаборатория: гнездо находки в карточке работы, плашка «уже известно»
   и подпись состояния стола на сцене. Гнездо рисовало себя радиальным
   пятном золота по черноте с волосяной линией в 1px; плашка «уже
   известно» стояла в §6 и получала материал ДОСКИ — карточка внутри
   карточки, хотя это примечание, вырезанное в ней; подпись состояния
   держала свою копию выемки числами (#181043 → #0e0927). */
.tam-lab__card-art,
.tam-lab__card-known,
.tam-lab__state,
/* Встреча с боссом: гнездо портрета в карточке узла, сцена кадра в
   кинематике и строка реплики в сцене победы. Все три рисовали себя
   радиальным пятном золота по черноте (`rgba(11, 9, 37, .9)` и
   `rgba(8, 7, 30, .92)`) с волосяной кромкой — то есть три варианта
   одной и той же выемки мимо общего материала, да ещё и без фактуры:
   на кадре встречи портрет висел наклейкой на теле окна. */
.trumpamole__boss-face,
.trumpamole__boss-frame-stage,
.trumpamole__boss-line,
.ui-row__icon {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    border-radius: var(--ui-radius-sm);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

/*
 * Три выемки со своей формой.
 *
 * Общий шаг выемки — `--ui-radius-sm`: она вложена в доску и мельче её.
 * Но кружок с номером уровня перка — круг, а кадр стройки и картинка
 * облавы это не плашка со значением, а изображение во всю ширину
 * карточки, и на шаге в 8px его углы выглядят обрубленными рядом с
 * углами самой карточки. Правило стоит здесь, а не в `clans.css`:
 * рама грузится последней и перебила бы раздел (§86).
 */
.tam-hq__perk-level { border-radius: 50%; }

/* Метка гардероба мельче плашки со значением: это подпись в один ряд с
   такими же, и шаг у неё самый мелкий (§скругления, `-xs`). */
.tam-cos__tag,
.tam-store__tag { border-radius: var(--ui-radius-xs); }

.tam-hq__site,
/* Гнездо портрета босса ростом в 148px — не плашка со значением, а
   ниша во всю ширину окна: на шаге в 8px её углы выглядят обрубленными
   рядом с углами самого окна. */
.trumpamole__boss-face,
.tam-raid__art { border-radius: var(--ui-radius-md); }

/*
 * Реплика сцены победы — выемка с золотым язычком слева.
 *
 * Язычок отделяет прямую речь от текста сцены, и задать его в `boss.css`
 * нельзя: сокращённая `border` общего списка выемок стоит в раме, а рама
 * грузится последней и перебивает раздел при равном весе (§86).
 */
.trumpamole__boss-line {
    border-left: 3px solid var(--ui-gold-dark);
    border-radius: var(--ui-radius-md);
}

/* Кадр события ростом во всю ширину раздела и с заголовком поверх — это
   витрина, а не плашка со значением: на шаге в 8px его углы выглядят
   обрубленными рядом с углами карточек под ним. Сцена кинематика босса —
   такая же витрина во весь экран. */
.tam-event-scene,
.trumpamole__boss-frame-stage { border-radius: var(--ui-radius-lg); }

/*
 * НАГРАДА ПО СЕЗОННОМУ ПРОПУСКУ — ФИОЛЕТОВАЯ.
 *
 * Правило стоит ЗДЕСЬ, а не в `season.css`, и именно после общего списка
 * выемок: `.tam-season__cell` перечислен строкой выше, рама грузится
 * последней и перебивала любой цвет, заданный в файле раздела. Первый
 * заход покрасил ячейку в `season.css` — и не увидел никакой разницы.
 *
 * Фиолетовый в игре означает премиум (§19-20 tok.txt): VIP, сезонный
 * пропуск, особое предложение. До этого колонка «ПО ПРОПУСКУ»
 * подкрашивалась тем же золотом, что и бесплатная, и на глаз они
 * читались одинаковыми — платить было не за что.
 */
.tam-season__cell--premium {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
        var(--ui-purple-panel-top) 0%, var(--ui-purple-panel-low) 100%);
    border-color: rgba(0, 0, 0, 0.55);
    box-shadow: var(--ui-inner-well), inset 0 1px 0 var(--ui-purple-panel-rim);
}

/* Ступень с героем — единственная золотая плитка колонки: она и есть
   причина взять пропуск. */
.tam-season__cell[data-hero] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-head) 0%, var(--ui-panel-light) 100%);
    border-color: var(--ui-gold-dark);
    box-shadow: var(--ui-inner-well), inset 0 0 0 1px color-mix(in srgb, var(--ui-gold) 32%, transparent);
}

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

   `.ui-btn` — наследство: класс живёт в пяти разделах, а описания у него
   нет ни в одном файле. Браузер рисовал системную серо-белую кнопку —
   именно она стоит на карточке соперника в арене и ломает весь экран.
   ========================================================================== */

.ui-btn {
    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;
    touch-action: manipulation;
    transition: transform var(--ui-ease), box-shadow var(--ui-ease);
}

.ui-btn--sm {
    min-height: 40px;
    padding: 0 var(--ui-space-3);
    font-size: var(--ui-size-body);
    border-radius: var(--ui-radius-sm);
}

.ui-btn--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);
    color: var(--ui-text-dark);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.ui-btn--ghost,
/*
 * Общая кнопка `.trumpamole__btn` — второе наследство того же рода.
 *
 * Своего материала у неё в `button.css` не было вовсе: прозрачная
 * чернота в 22 %, `border: 0` и волосяная светлая линия сверху. На
 * тёмном поле это ровно тот «обычный card с серой рамкой», который §62
 * ТЗ запрещает поимённо, — на кадре сообщения об ошибке рейтинга она
 * читалась не кнопкой, а подложкой под надписью. Кнопка эта нейтральная
 * («Dark» из §36 ТЗ), поэтому материал у неё тот же деревянный, что у
 * `.ui-btn--ghost`, а не золото: золотая CTA на экране одна (§59).
 */
.trumpamole__btn {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: var(--ui-edge-brown), var(--ui-inner-top);
    color: var(--ui-text-main);
}

/*
 * Вторичная кнопка — та же доска ступенью светлее, а не стекло.
 *
 * Стояло `rgba(255,255,255,.1)` с рамкой `rgba(150,120,255,.2)` в 1px:
 * два элемента подряд («Попробовать снова» и соседняя кнопка) отличались
 * только прозрачностью и на тёмном поле сливались в одно пятно.
 */
.trumpamole__btn--secondary {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
}

/* Нажатие: кнопка садится на свою нижнюю грань. Правило стоит здесь, а
   не в `button.css`, потому что там `:active` перебил бы материал рамы —
   у псевдокласса вес выше. */
.trumpamole__btn:active {
    box-shadow: 0 1px 0 var(--ui-panel-edge), var(--ui-shadow-soft);
}

/*
 * Выключенная — плотная обесцвеченная плашка, а не прозрачный призрак.
 *
 * Стояло `opacity: .5` с `grayscale(.5)`: сквозь кнопку просвечивала
 * страница, и она читалась сбоем отрисовки. Тот же приём, что у
 * выключенных кнопок заданий и товара события ниже.
 */
.trumpamole__btn:disabled {
    opacity: 1;
    pointer-events: none;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    border-color: rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-locked-text);
    cursor: default;
}

.ui-btn:active { transform: translateY(var(--ui-press)); }

/* --------------------------------------------------------------------------
   9.1. КНОПКИ ЗАДАНИЙ И ССЫЛОК РАЗДЕЛОВ

   «ПОДПИСАТЬСЯ», «СМОТРЕТЬ», «ПЕРЕЙТИ», «ЗАБРАТЬ», «ПОЛУЧЕНО», «В
   ПРОЦЕССЕ», «ПОДЕЛИТЬСЯ». Все они писались до словаря и получали своё
   оформление в каждом разделе: кремовая эмаль в заданиях, лимонная
   плашка в ежедневных наградах, растянутая золотая полоса у рефералов.
   Один смысл — один материал.

   По умолчанию кнопка ЗОЛОТАЯ: это действие, которого от игрока ждут.
   -------------------------------------------------------------------------- */

.trumpamole__tasks-small-btn,
.trumpamole__tasks-mini-btn,
/* «К скинам» на закрытом облике — единственное действие своего экрана,
   а материал у неё был свой: лимонный градиент по диагонали. */
.tam-hero__buy,
/* Пауза боя — единственное золотое пятно кадра, и золото у неё было
   своё: градиент в четыре ступени от #f0c95a к #a86c16. Подписи на ней
   нет (два бруска рисуются `i`), поэтому в §21 она не нужна. */
.tam-battle-hud__pause,
/* «КУПИТЬ» у товара события: держала свой радиальный градиент числами
   (#F5D65A → #C9882F) с коричневой подписью #312121 — золото прежнего
   мира на самой нажимаемой кнопке раздела. «ЗАБРАТЬ» у задания события
   стояла тут же и ушла к зелёным ниже. */
/* «ОТКРЫТЬ» на плашке о новой записи хроники: единственное действие
   плашки, и золото у неё было своё — две ступени от `--ui-gold-light`
   к `--ui-gold-dark` вместо четырёх ступеней корпуса кнопки. */
.tam-chr-hint__btn,
/* «НАДЕТЬ» на стойке молотов и «ПОСТАВИТЬ НА ПОЛКУ» в витрине профиля —
   единственное действие своей вкладки коллекции. Обе держали своё
   золото в две ступени (`--gold-3` → `--gold-4`) с тёмно-синей подписью
   без обводки: на золоте такая надпись почти не видна (§21). */
.tam-col__btn--gold,
/* «НАЙТИ СОПЕРНИКА» на поле боя — главное и единственное действие
   раздела, а кнопка была СИНЕЙ: диагональный градиент #4da3ff → #2a6bb0
   без кромки и без направленной грани. Синего корпуса в игре нет нигде
   больше, и §62 ТЗ запрещает «стандартную синюю кнопку» поимённо. */
.trumpamole__arenapvp-btn-primary {
    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);
    color: var(--ui-ivory-light);
}

.trumpamole__tasks-small-btn:active,
.trumpamole__tasks-mini-btn:active,
.tam-hero__buy:active,
.tam-col__btn--gold:active,
.tam-battle-hud__pause:active,
.tam-chr-hint__btn:active,
.trumpamole__arenapvp-btn-primary:active {
    box-shadow: 0 1px 0 var(--ui-gold-btn-deep), var(--ui-shadow-soft);
}

/*
 * Кончился товар события — кнопка остаётся ПЛОТНОЙ деревянной плашкой.
 *
 * Стояло `opacity: .5` с `saturate(.5)`: сквозь такую кнопку просвечивала
 * карточка под ней, и она читалась сбоем отрисовки, а не запретом. Тот же
 * приём, что у выключенной кнопки заданий выше.
 */
.tam-event-goods__btn.is-off {
    opacity: 1;
    pointer-events: none;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    border-color: rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-locked-text);
    text-shadow: none;
    cursor: default;
}

/* «ЗАБРАТЬ» — награда лежит и ждёт: единственный зелёный в разделе.
   «ЗАБРАТЬ РЕЗУЛЬТАТ» в лаборатории — то же самое: работа закончена,
   и результат лежит на столе. Класс был `--gold`, и на экране выходило
   два золота подряд — «отдать» и «забрать» одним цветом, хотя это
   разные по смыслу шаги (§36 ТЗ требует зелёную «забрать»). */
.trumpamole__tasks-small-btn.claim-btn,
.trumpamole__tasks-mini-btn.claim-btn,
.tam-lab__btn--claim,
/* «ЗАБРАТЬ» у задания и вехи события: то же самое действие, что и в
   заданиях, а корпус был золотой. Клановое «Забрать» покрашено ниже,
   в разделе кланов: там материал мелкой кнопки задаётся позже. */
.tam-event-task__btn {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
        var(--ui-green-light) 0%, var(--ui-green) 55%, var(--ui-green-deep) 100%);
    border-color: rgba(0, 0, 0, 0.45);
    box-shadow: 0 4px 0 var(--ui-green-deep), var(--ui-shadow-soft),
                inset 0 2px 0 rgba(255, 255, 255, 0.3);
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent);
}

/* Нажатие зелёной — на свою же тёмную грань, а не на золотую: правило
   `:active` золотой кнопки выше стоит на том же элементе. */
.tam-lab__btn--claim:active,
.tam-event-task__btn:active {
    box-shadow: 0 1px 0 var(--ui-green-deep), var(--ui-shadow-soft);
}

/* --------------------------------------------------------------------------
   9.1.1. ПОВТОРЯЮЩЕЕСЯ ДЕЙСТВИЕ РЯДА — ВТОРОЙ КОРПУС

   Разбор §36 по всем разделам сразу (он и был отложен): золото значит
   «главное действие этого экрана», и значит оно это ровно до тех пор,
   пока золотая кнопка на экране одна. В заданиях их выходило четыре —
   «ПОДПИСАТЬСЯ» в ряду соцсетей (а сетей в наборе шесть, и при полном
   наборе кнопок было бы шесть) и три «СМОТРЕТЬ» в ленте роликов; в
   витрине магазина — восемь ценовых планок плюс золотая CTA предложения
   сверху. Экран с девятью главными кнопками не имеет главной вовсе, и
   §59 ТЗ («что здесь главное — понятно за секунду») на нём не работает.

   Оба кадра референса решают это одинаково: золото в панели ровно одно.
   `grok/8.png` подписывает цены скинов и усилений тёмными чипами, а
   выделяет только «SPECIAL OFFER»; `grok/9.png` красит повторяющиеся
   цены магазина зелёным, оставляя золото окну подтверждения и «GET
   PASS!». Зелёный в игре уже занят смыслом «забрать» (блок выше),
   поэтому повторяющееся действие берёт ВТОРОЙ корпус — ту же доску
   ступенью светлее, что у `.trumpamole__btn--secondary`.

   Правило целиком: золото — одно действие на экран; зелень — «забрать»,
   сколько бы наград ни лежало; второй корпус — одинаковое действие,
   повторённое в ряду или сетке. Выключенная плашка ниже темнее их всех
   и остаётся утопленной, поэтому «СМОТРЕТЬ» и «ПОЛУЧЕНО» рядом не
   путаются.

   ОКНО — ТОТ ЖЕ ЭКРАН. Разбор выше шёл по разделам, и окна не считались
   ни разу: `window.showModal` открывает поверх страницы отдельную сцену,
   на которой действует ровно то же правило. Счёт по всем двадцати с
   лишним раскладам окна (`/tmp/s81_modal.py`) нашёл три места, и корпус
   им сменили в `modules/ui/modals.js`, а не здесь — эти кнопки собирает
   `Buttons.create`, и второй корпус у него называется темой `dark`:

     · «ВЫБРАТЬ» на каждом из трёх пакетов VIP (вариант 16);
     · «В БОЙ» на каждом друге в сети (вариант 12, живое окно `pvp_modes`);
     · столбик из одних только `buttons` без `buttonText` — золотым красилась
       КАЖДАЯ кнопка списка, теперь только первая.

   Выбранная сумма в окне покупки (`.trumpamole__modal-v4-chip.is-active`)
   золотая и остаётся такой: это не действие, а отметка выбора — та же
   роль, что у открытой вкладки.
   -------------------------------------------------------------------------- */

.trumpamole__tasks-small-btn.social-subscribe-btn,
.trumpamole__tasks-small-btn.social-open-btn,
.trumpamole__tasks-mini-btn.ads-watch-btn,
/* «ОТДАТЬ ДИГГСУ» на карточке работы: кнопок на экране столько же,
   сколько готовых к работе находок. Прежнее объяснение в золотом блоке
   выше так и называло её повторяющимся действием — и оставляло золотой;
   правило §9.1.1 отменяет именно это. «ЗАБРАТЬ РЕЗУЛЬТАТ» на той же
   карточке остаётся зелёной и потому исключена по классу. */
.tam-lab__btn:not(.tam-lab__btn--claim),
/* «КУПИТЬ» у товара события: витрина события — такой же список
   одинаковых покупок, как сетка магазина, и золото в ней стояло на
   каждой строке. */
.tam-event-goods__btn,
/* «ВЫБРАТЬ» на строке купленного облика: второе действие строки (первое
   — «ПРИМЕРИТЬ», оно берёт обычное дерево §12). Строк на полке столько
   же, сколько купленных обликов, и золотыми они шли стеной. */
.trumpamole__skins-owned-mini-btn.gold,
/* «В БОЙ» на карточке соперника: соперников в раскладе арены всегда
   трое. Золото на экране арены одно, и оно переезжает: пока забег не
   записан, оно у «ЗАПИСАТЬ ЗАБЕГ», после записи — у «РЕВАНША» на
   плакате врага (`arena.view.js`, немезис §147). Раньше обе кнопки
   были золотыми разом — на арене выходило две главных. */
.tam-arena__rival-go,
/* «В БОЙ» на строке вызова в дуэль: вызовов сервер не ограничивает
   (`PvpInvitation::incoming` без `LIMIT`), значит золотых кнопок было
   ровно столько, сколько зовущих. Отказ рядом развязан не цветом, а
   формой — блок «Пара „принять — отклонить“» ниже. */
.trumpamole__arenapvp-duel-btn--accept,
/* Варианты выбора в сюжетной сцене. Их всегда несколько, и они равны:
   «заделать пролом» и «посмотреть, куда он ведёт» — одно и то же
   действие сцены, а не главное и второстепенное. Своей записи здесь не
   было, и оба варианта держали золотую линию в 1px поверх старого
   дерева. */
.trumpamole__story-choice {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: var(--ui-edge-brown), var(--ui-shadow-soft), var(--ui-inner-top);
    color: var(--ui-text-main);
}

.trumpamole__tasks-small-btn.social-subscribe-btn:active,
.trumpamole__tasks-small-btn.social-open-btn:active,
.trumpamole__tasks-mini-btn.ads-watch-btn:active,
.tam-lab__btn:not(.tam-lab__btn--claim):active,
.tam-event-goods__btn:active,
.trumpamole__skins-owned-mini-btn.gold:active,
.tam-arena__rival-go:active,
.trumpamole__arenapvp-duel-btn--accept:active,
.trumpamole__story-choice:active {
    box-shadow: 0 1px 0 var(--ui-panel-edge), var(--ui-shadow-soft);
}

/* ----- Пара «принять — отклонить» ----------------------------------------
   Две кнопки одной строки нельзя развязать одним лишь корпусом: второй
   корпус согласия и «дерево» отказа отличаются на ступень яркости, и на
   бегу игрок жмёт не ту. Развязка идёт формой и глубиной — ровно так же,
   как их развязывает игра на кадрах референса: утвердительное действие
   поднято и подписано словом, отрицательное утоплено в гнездо и несёт
   один знак.

   Крест берёт красный только на нажатии: постоянный красный на строке
   вызова кричал бы громче самого вызова, а danger по §36 — цвет
   необратимого, не цвет вежливого отказа. */
.trumpamole__arenapvp-duel-btn--reject {
    width: var(--ui-tap-min);
    min-width: var(--ui-tap-min);
    padding: 0;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-edge) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    /* Утопленное гнездо: тень внутрь сверху, блик по нижней кромке. */
    box-shadow: inset 0 3px 6px rgba(4, 3, 14, 0.75),
                inset 0 -1px 0 rgba(255, 255, 255, 0.08);
    color: var(--ui-text-muted);
}

.trumpamole__arenapvp-duel-btn--reject:active {
    color: var(--ui-red-light);
    box-shadow: inset 0 4px 8px rgba(4, 3, 14, 0.85);
}

@media (hover: hover) {

    .trumpamole__arenapvp-duel-btn--reject:hover { color: var(--ui-ivory); }
}

/*
 * «ПОЛУЧИТЬ» на сегодняшнем дне — ЗЕЛЁНАЯ, как любая «забрать».
 *
 * Награда за день уже лежит и ждёт нажатия — это ровно тот же шаг, что
 * «ЗАБРАТЬ» в строке задания, а корпус у неё оставался золотым. На
 * `grok/9.png` окно «DAILY BONUS» подписано зелёной «CLAIM», и золото
 * там отдано «LEVEL UP» и «VIP PASS».
 */
.trumpamole__tasks-mini-btn.daily-claim-btn {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
        var(--ui-green-light) 0%, var(--ui-green) 55%, var(--ui-green-deep) 100%);
    border-color: rgba(0, 0, 0, 0.45);
    box-shadow: 0 4px 0 var(--ui-green-deep), var(--ui-shadow-soft),
                inset 0 2px 0 rgba(255, 255, 255, 0.3);
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent);
}

.trumpamole__tasks-mini-btn.daily-claim-btn:active {
    box-shadow: 0 1px 0 var(--ui-green-deep), var(--ui-shadow-soft);
}

/*
 * «ПОЛУЧЕНО» и «В ПРОЦЕССЕ» — не выцветшая копия активной кнопки.
 *
 * Стояло `opacity: .52`: сквозь такую кнопку просвечивала строка под
 * ней, и она читалась как сбой отрисовки. Выключенная кнопка остаётся
 * ПЛОТНОЙ деревянной плашкой — она просто перестаёт быть золотой.
 */
.trumpamole__tasks-small-btn[disabled],
.trumpamole__tasks-mini-btn[disabled] {
    opacity: 1;
    pointer-events: none;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    border-color: rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-locked-text);
    text-shadow: none;
    cursor: default;
}

/*
 * Надпись на золоте — КРЕМОВАЯ В ТЁМНОЙ ОБВОДКЕ, а не коричневая.
 *
 * Это проверено по всем шести кадрам: «ИГРАТЬ» и «УРОВЕНЬ 45» на кадре 1,
 * «ИЗМЕНИТЬ» в профиле, активная вкладка «СКИНЫ» в инвентаре — везде
 * белая буква с толстым тёмным контуром. Коричневый капслок на золоте
 * даёт разницу яркости меньше двух ступеней: на телефоне под солнцем
 * такая надпись пропадает, и главная кнопка экрана перестаёт читаться
 * как кнопка. Обводка же держит её на любом золоте — и на светлом
 * блике сверху, и на тёмной фаске снизу.
 *
 * Светлая кромка внутри тёмного контура — вторая половина приёма:
 * без неё кнопка выглядит наклейкой, а не литой клавишей.
 */
/* Собственно надписи на золоте собраны в §21 — в конце файла: разделы
   §11 и §19 красят те же вкладки и кнопки, и правило обязано стоять
   после них, иначе побеждает более поздний тёмный цвет. */

/*
 * Корпус золотой кнопки здесь НЕ переопределяется.
 *
 * Проверено на живых экранах: `background` у `.ui-button-gold` в этом
 * файле перекрывает разделы, которые сознательно перекрашивают ту же
 * кнопку, — коричневую «купить» на золотой панели магазина и зелёный
 * «+» в шапке. Рама отвечает за материал по умолчанию, а не за право
 * последнего слова: светлая кромка живёт в самом материале
 * (ui-tokens.css, `.ui-button-gold`), где раздел её может отменить.
 */

/* --------------------------------------------------------------------------
   9.2. ПРЕМИУМ-КНОПКА (`.trumpamole__btn-par`)

   Ею собрана половина главных действий игры: «Поделиться» у рефералов,
   «Забрать» и «Купить» в окнах, покупка в магазине, выбор скина, сбор
   дохода в башне. Корпус рисовался ВНУТРИ SVG: прямоугольник 420×104 в
   поле 520×140 со `preserveAspectRatio="none"`, растянутый в высоту 56px.

   Что из этого получалось. Скругление `rx=22` при таком растяжении
   давит по вертикали в четыре раза сильнее, чем по горизонтали, — углы
   уезжали в овал; поверх лежала кривая «блик-волна» и два круглых
   пятна-искры по диагонали. Кнопка выходила покатой лепёшкой, ни на
   что на кадрах референса не похожей: там кнопка — прямой скруглённый
   прямоугольник с толстой тёмной кромкой и направленной нижней гранью.
   Владелец потребовал переделать её на странице «Друзья» и во всех
   окнах — это одна и та же кнопка.

   Корпус SVG снимается целиком, материал берётся из словаря по теме
   (`data-btn-theme`, ставит `modules/ui/buttons.js`). Подпись остаётся
   в своём `span`, поэтому ни один вызывающий модуль менять не нужно.
   -------------------------------------------------------------------------- */

.trumpamole__btn-par {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--ui-tap);
    height: auto;
    padding: 0;
    border-radius: var(--ui-radius-md);
    /* Золото — умолчание: тема `gold` у большинства вызовов. Корпус тот
       же, что у `.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);
    /* Свечение вокруг кнопки снято: `drop-shadow` в 80px радиуса на
       каждую кнопку экрана — это перерисовка целого кадра при прокрутке. */
    filter: none;
    transition: transform var(--ui-ease), box-shadow var(--ui-ease);
}

.trumpamole__btn-par.fire { filter: none; }

.trumpamole__btn-par:active,
.trumpamole__btn-par.fire:active {
    transform: translateY(var(--ui-press));
    filter: none;
    box-shadow: 0 1px 0 var(--ui-gold-btn-deep), var(--ui-shadow-soft);
}

/* Корпус жил в SVG — теперь он материал, и рисунок больше не нужен. */
.trumpamole__btn-par__svg { display: none; }

.trumpamole__btn-par__text {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-space-2);
    width: 100%;
    height: auto;
    min-height: var(--ui-tap);
    padding: 8px var(--ui-space-4);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-value);
    line-height: 1.15;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-align: center;
}

/* ----- Темы ----- */

/* Зелёная — «забрать», «вступить», «продолжить» (§36 заказа). Корпус тот
   же, что у `.ui-button-success`: зелёная кнопка в игре одна. */
.trumpamole__btn-par[data-btn-theme="green"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
            var(--ui-green-btn-hi) 0%,
            var(--ui-green-btn-top) 6%,
            var(--ui-green-btn) 46%,
            var(--ui-green-btn-low) 100%);
    border-color: var(--ui-green-btn-edge);
    box-shadow: var(--ui-edge-green), var(--ui-shadow-soft), var(--ui-inner-top);
}

.trumpamole__btn-par[data-btn-theme="green"]:active {
    box-shadow: 0 2px 0 var(--ui-green-btn-deep), var(--ui-shadow-soft);
}

.trumpamole__btn-par[data-btn-theme="red"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 55%, var(--ui-red-deep) 100%);
    box-shadow: var(--ui-edge-danger), var(--ui-shadow-soft), var(--ui-inner-top);
}

.trumpamole__btn-par[data-btn-theme="red"]:active {
    box-shadow: 0 2px 0 var(--ui-red-deep), var(--ui-shadow-soft);
}

/* Синей темы здесь больше нет. Ею были покрашены обмен в окне варианта 4,
   приглашение друга и вступление в клан, а набор кнопок §36 заказа знает
   пять корпусов — золото, зелень, красный, фиолетовый и тёмный. Синий
   остаётся цветом энергии и подсказки, но не кнопки. */

/* Кремовая — единственная тема с тёмной подписью (см. §21). */
.trumpamole__btn-par[data-btn-theme="ivoryCream"],
.trumpamole__btn-par--ivory {
    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-color: var(--ui-border-ivory);
    box-shadow: var(--ui-edge-ivory), var(--ui-shadow-soft),
                inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

/* Тёмная — второстепенное действие: «Позже», «Остаться», «Отмена». */
.trumpamole__btn-par[data-btn-theme="dark"],
.trumpamole__btn-par[data-btn-theme="secondary"],
.trumpamole__btn-par.is-dark,
.trumpamole__btn-par.secondary {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
            var(--ui-panel-light) 0%, var(--ui-panel-main) 45%, var(--ui-panel-dark) 100%);
    border-color: var(--ui-border-warm);
    box-shadow: var(--ui-edge-brown), var(--ui-shadow-soft), var(--ui-inner-top);
}

.trumpamole__btn-par.is-dark:active,
.trumpamole__btn-par.secondary:active {
    box-shadow: 0 2px 0 var(--ui-bg-deep), var(--ui-shadow-soft);
}

/*
 * Недоступная кнопка не выцветает до призрака.
 *
 * Стояло `grayscale(.55) brightness(.72)` плюс `opacity: .75` — на пёстром
 * фоне такая кнопка читалась как ошибка отрисовки. Плотный глухой корпус
 * говорит то же самое честнее.
 *
 * Низ корпуса был серо-коричневым (#4a3c3a) — числом прежнего, тёплого
 * мира: рядом с фиолетовыми панелями недоступная кнопка отдавала бурым.
 * Теперь низ — `--ui-locked`, тот же тон, которым словарь красит закрытое
 * везде. Верх — `--ui-border-ivory`: единственный в словаре приглушённый
 * фиолетовый средней светлоты. Светлее (`--ui-ivory-deep`) корпус
 * оживает и спорит с золотой кнопкой рядом, темнее — тонет в карточке.
 */
.trumpamole__btn-par.is-disabled,
.trumpamole__btn-par:disabled {
    filter: none;
    opacity: 1;
    pointer-events: none;
    background: linear-gradient(180deg, var(--ui-border-ivory) 0%, var(--ui-locked) 100%);
    border-color: rgba(0, 0, 0, 0.4);
    box-shadow: 0 4px 0 var(--ui-panel-dark), var(--ui-shadow-soft);
}

.trumpamole__btn-par.is-disabled .trumpamole__btn-par__text,
.trumpamole__btn-par:disabled .trumpamole__btn-par__text {
    color: var(--ui-locked-text);
    text-shadow: none;
}

/* ==========================================================================
   10. ЧИПЫ РЕСУРСОВ

   Референс: тёмная утопленная плашка, значок в золотом ободке, значение
   светлым жирным. Кремовая эмалированная плашка §11 в этой раме читается
   как чужая деталь — на всех шести кадрах референса чипы тёмные.

   НЕ ТАБЛЕТКА. Здесь стояло `--ui-radius-pill`: чип баланса на кадре 1
   действительно вытянутая пилюля. Но в игре таких чипов не два, а до
   четырёх в строку шапки плюс по паре в каждом разделе — и ряд пилюль
   рядом с прямоугольными карточками читался как чужой набор форм.
   Владелец потребовал скругление меньше и в шапке, и на страницах
   («Выполнено», «Получено», «Монет»), поэтому у чипа тот же мелкий шаг
   `--ui-radius-sm`, что у вложенных плашек и строк списка.
   ========================================================================== */

.ui-pill.ui-panel-ivory,
.tam-store__chip,
.trumpamole__skins-chip,
.trumpamole__tasks-chip,
.trumpamole__arenapvp-chip,
/* Счёт прошедшей дуэли — такой же тёмный чип: он показывает значение,
   а не зовёт нажать. Цвет исхода даёт кромка и цифра, не заливка. */
.trumpamole__arenapvp-duel-mark,
.trumpamole__map-chip,
/* Строка фактов в окне уровня: цель боя, цена входа, состав врагов.
   Те же значения без нажатия, что и в чипах шапки. */
.trumpamole__map-fact,
.trumpamole__tw-chip,
/* Вывеска под зданием квартала и строка итога под площадкой: обе держали
   свою заливку с золотой линией в 1px и стояли мимо чипов остальной
   игры — а показывают они ровно то же, значение без нажатия. */
.trumpamole__tw-building-plate,
.trumpamole__tw-summary,
.tam-bonusgame__stat,
/* Прибавки выбранного молота («ОПЫТ +12 %», «МОНЕТЫ +8 %»): те же
   значения без нажатия. Заливали себя чернотой в 30 % и на сцене
   стойки читались тремя пятнами, а не чипами. */
.tam-col__stat,
.tam-season__premium-on,
/* «Мест нет» в строке клана и «ОБЛАВА МИРА» на картинке босса: оба
   показывают значение и оба не зовут нажать — тот же тёмный чип, что
   в шапке разделов. Первый заливал себя чернотой в 30 %, второй — своей
   чернотой с золотой линией в 1px. */
.tam-clan__full,
.tam-raid__scope,
/* Строка состава товара («36 000 монет», «5 жизней») — то же значение
   без нажатия. Раздел держал свою копию этого материала числами
   (#1d1351 → #140d38), то есть на полтона мимо чипов остальной игры. */
.tam-store__content,
/* Место в таблице лидеров и титул игрока в карточке соперника: те же
   значения без нажатия. Оба держали свою копию этого материала числами
   (#181043 → #0e0927 и `--ui-wood-dark` → #0d0924). */
.trumpamole__leaderboard-player-place-num,
.tam-guest__title,
/* Подпись предмета на сцене главной («БАШНЯ», «СЕЙФ», «КЛАН»). Это тот
   же чип: значение без нажатия, только стоит оно не в строке шапки, а на
   нарисованной комнате. Материала у него было два — тёмная плашка в 72 %
   черноты у предметов и свой градиент с золотой линией в 1px у построек,
   и подпись сейфа на стене читалась голым белым текстом. */
.trumpamole__home-spot-label,
/* Запас пыли на сцене лаборатории («270 пыль») — то же значение без
   нажатия, что чипы шапки, и держало оно свою копию материала числами
   (`--ui-wood-dark` → #0d0924). Стоит чип рядом с кнопкой «ХРОНИКА»
   того же роста, и разница в полтона читалась сбоем, а не набором. */
.tam-lab__dust,
/* Встреча с боссом: факт в карточке узла («Фаз: 3», «Побеждён: 4») и
   клеймо фазы в полосе боя. Оба показывают значение и оба не зовут
   нажать. Факт заливал себя чернотой в 72 % с лиловой линией в 1px,
   клеймо — чернотой в 70 % с такой же линией: два варианта одного чипа
   мимо остальной игры. */
.trumpamole__boss-fact,
.tam-boss__phase,
.tam-event-chip {
    border-radius: var(--ui-radius-sm);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-b) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
    box-shadow: var(--ui-inner-well), 0 3px 0 rgba(0, 0, 0, 0.45);
    color: var(--ui-text-main);
}

/* Значение в чипе — крупное и светлое: на кадре это самая заметная
   цифра экрана после заголовка. Чипы шапки сюда не входят: там их
   четыре в строку, и на 360px крайний уже упирается в край. */
.tam-store__chip .tam-store__chip-value {
    font-size: var(--ui-size-section);
    letter-spacing: 0.01em;
}

.ui-pill.ui-panel-ivory .ui-pill__value,
.tam-store__chip .tam-store__chip-value {
    color: var(--ui-text-main);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.5);
}

/*
 * Купленный сезонный пропуск — тёмный чип в золотом кольце.
 *
 * Золотой заливкой его красить нельзя: золото в игре означает «нажми»,
 * а это состояние. Кольцо и корона говорят «премиум есть» и при этом не
 * спорят с зелёной кнопкой «забрать всё», которая стоит прямо под ним.
 */
.tam-season__premium-on {
    border-color: var(--ui-gold-dark);
    box-shadow: var(--ui-inner-well), 0 3px 0 var(--ui-gold-deep);
    color: var(--ui-gold-light);
}

/* Золотой ободок под значком: значок перестаёт «висеть» на тёмном. */
.ui-pill.ui-panel-ivory .ui-pill__icon {
    border-radius: 50%;
    background: radial-gradient(closest-side,
        color-mix(in srgb, var(--ui-gold-light) 30%, transparent), transparent 76%);
    color: var(--ui-gold-light);
}

/*
 * Плитка счётчика (кадр «ПРОФИЛЬ»: «25 340 ТРОФЕИ», «1 245 ПОБЕДЫ»).
 *
 * У нас на этом месте были прозрачные прямоугольники с волосяной рамкой
 * и обрезанной подписью («TREASU…», «PER HO…»). В референсе это плотная
 * тёмная плитка: крупное значение, мелкая подпись под ним.
 */
.tam-stat,
.trumpamole__profile-stat,
.trumpamole__arenapvp-stat,
/* Два счёта коллекции в шапке раздела — игровой и косметический. Плитка
   держала копию этого же материала числами (#1d1351 → #160e3d), то есть
   стояла на полтона мимо счётчиков профиля и арены. */
.tam-col__track,
.tam-raid__meta-item,
.tam-tower__legend-item {
    /* Тот же тёплый шаг, что у выемок §8: плитки счётчиков в профиле
       лежат внутри доски и чернее её быть не должны. */
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

/*
 * Подпись счётчика не обрезается.
 *
 * `text-overflow: ellipsis` в узкой плитке съедал ровно то слово, ради
 * которого плитка существует: «СОКРОВИЩНИЦА» превращалась в «TREASU…».
 * Подпись мельче, в две строки — и целиком.
 */
.tam-stat__label,
.tam-col__stat-label,
.tam-store__chip-label,
.trumpamole__skins-chip-label,
.trumpamole__tasks-chip-label,
.trumpamole__arenapvp-chip-label,
.trumpamole__match3-chip-label,
.trumpamole__arenapvp-stat-label {
    overflow: visible;
    white-space: normal;
    text-overflow: clip;
    font-size: var(--ui-size-micro);
    line-height: 1.15;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ui-text-muted);
}

/* Значение крупнее подписи: в референсе читается сначала число. */
.tam-stat__value,
.trumpamole__skins-chip-value,
.trumpamole__tasks-chip-value,
.trumpamole__arenapvp-chip-value {
    font-size: var(--ui-size-value);
    font-weight: var(--ui-weight-title);
    color: var(--ui-text-main);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.5);
}

/* ==========================================================================
   11. ВКЛАДКИ

   Вкладка — физический контрол (§16 ТЗ): дерево в покое, золото в
   выбранном. Ряд вкладок прокручивается, а не переносится: в клане
   четыре вкладки не помещались в ширину и последняя уезжала за экран,
   в магазине — падала на вторую строку во всю ширину.
   ========================================================================== */

.trumpamole__skins-tabs,
.trumpamole__profile-tabs,
.tam-col__tabs,
.tam-vault__tabs,
.tam-chr__tabs,
.tam-cos__tabs,
.tam-store__tabs,
.tam-event-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.trumpamole__skins-tabs::-webkit-scrollbar,
.tam-store__tabs::-webkit-scrollbar,
.tam-chr__tabs::-webkit-scrollbar { display: none; }

/*
 * Утопленная дорожка под рядом вкладок.
 *
 * Прилавок магазина — единственный ряд игры, у которого вкладки стоят в
 * выемке: на кадре «МАГАЗИН» это один физический переключатель, а не
 * четыре отдельные кнопки. Материал дорожки лежал в `store.css` своим
 * градиентом; здесь он собран из того же словаря, что и остальные
 * утопленные поверхности §8, и новый ряд получит его дописыванием
 * класса, а не копией.
 */
.tam-store__tabs {
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    border-radius: var(--ui-radius-md);
    background: linear-gradient(180deg, var(--ui-bg-deep) 0%, var(--ui-panel-dark) 100%);
    box-shadow: var(--ui-inner-well);
}

/*
 * Ширину вкладки задаёт `flex: 1 1 auto`, а не `0 0 auto`.
 *
 * На кадрах инвентаря и клуба (as/5.png) вкладки делят полосу поровну и
 * стоят от края до края — ряд из четырёх плиток одной ширины. Жёсткое
 * `0 0 auto` собирало их в кучу у левого края и оставляло справа пустое
 * место, а деление ровно поровну (`1 1 0`) обрезало длинные названия
 * («ПОЖЕРТВОВАНИЯ» в клане). `1 1 auto` держит и то и другое: короткие
 * подписи растягиваются до общей ширины, длинная забирает по себе.
 */
.tam-store__tab,
.tam-clan__tab,
.tam-season__tab,
.tam-event-tab {
    flex: 1 1 auto;
}

/*
 * Материал вкладки снят пипеткой с ряда «СКИНЫ · МОЛИ · МОЛОТКИ ·
 * ЭФФЕКТЫ» (as/5.png, кадр инвентаря):
 *
 *   покой:   заливка #1e1856 → #181246, светлая линия сверху #4a3fa8,
 *            тёмный контур #0a0820
 *   выбор:   заливка #d29014 → #ca8004, ЯРКИЙ золотой кант #ffd873
 *
 * Два вывода, которых прежняя версия не держала. Первый: выбранная
 * вкладка не жёлтая, а бронзовая — она темнее золотой кнопки на две
 * ступени, и отличает её от соседей прежде всего кант, а не заливка.
 * Второй: подпись остаётся КРЕМОВОЙ в обоих состояниях. Прежде в покое
 * она была приглушённой (`--ui-text-muted`), а на выборе коричневой
 * (`--ui-text-dark`), и ряд читался как «одна кнопка и три неактивных
 * поля» вместо переключателя.
 */
.trumpamole__skins-tab-btn,
.trumpamole__tasks-tab-btn,
.trumpamole__profile-tab-btn,
.tam-store__tab,
.tam-clan__tab,
.tam-season__tab,
/* Рубашка карточки бонусной игры — тот же контрол в покое: дерево,
   тёмная кромка, светлая фаска сверху, грань снизу. Геометрию (размер,
   скругление) задаёт `bonusgame.css`, материал — здесь. */
.tam-bonusgame__face--back,
/* Ряд быстрых адресов башни («МОИ · АТАКИ · ЗАКЛАДКИ · НЕДАВНИЕ ·
   ОСОБЫЕ») — тот же переключатель, только в два этажа. Он держал свою
   копию материала с тусклой бронзой в выборе. */
.tam-tower__addr-btn,
.tam-event-tab {
    min-height: 42px;
    padding: 0 var(--ui-space-2);
    border-radius: var(--ui-radius-md);
    border: var(--ui-border) solid var(--ui-bg-dark);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-row-a) 100%);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-light) 55%, transparent),
                0 2px 0 rgba(0, 0, 0, 0.42);
    color: var(--ui-ivory-light);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    /* Ступень МЕЛКАЯ, а не основная. Подпись вкладки не переносится
       (`nowrap`), а ряд из четырёх-пяти вкладок обязан уместиться в
       320px: при основном кегле ряд магазина («RESOURCES · COSMETICS ·
       SPECIAL · GEAR») просил 328px при 296 доступных и уезжал за правый
       край, а счётчики коллекции и хроники вылезали и до правки. Плотный
       капслок Roboto Condensed 900 читается и на мелкой ступени. */
    font-size: var(--ui-size-small);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent);
}

.trumpamole__skins-tab-btn.active,
.trumpamole__tasks-tab-btn.active,
.trumpamole__profile-tab-btn.active,
.tam-store__tab.is-active,
.tam-clan__tab.is-active,
.tam-season__tab.is-active,
.tam-tower__addr-btn.is-active,
.tam-event-tab.is-active {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold) 0%, var(--ui-gold-mid) 40%, var(--ui-gold-dark) 100%);
    border-color: var(--ui-gold-light);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.42),
                inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 45%, transparent),
                0 0 10px color-mix(in srgb, var(--ui-gold) 28%, transparent);
    color: var(--ui-ivory-light);
}

/* ==========================================================================
   12. МЕЛКИЕ КОНТРОЛЫ РАЗДЕЛОВ

   Счётчики и ссылки в шапках разделов писались до словаря и выглядят
   стеклянными прямоугольниками: полупрозрачная заливка и рамка в 1px.
   На тёплом дереве такой контрол выглядит дырой, а не кнопкой.
   ========================================================================== */

.tam-cos__stat,
.tam-cos__link,
.tam-arena__link,
.tam-tower__stat,
.trumpamole__profile-title-chip,
/* Строка «о себе» под титулом: тот же материал, что у титула, — два
   соседних чипа не могут быть из разного дерева. */
.trumpamole__profile-bio-chip,
/* Значковая кнопка строки: «скопировать ссылку» у рефералов, «обновить»
   над списком друзей. Была прозрачным чёрным квадратом с волосяной
   светлой линией сверху — тот же стеклянный прямоугольник, о котором
   говорит заголовок раздела. */
.trumpamole__mini-btn,
/* Вход в лабораторию, Хронику, коллекцию и хранилище со страницы музея:
   держал корпус на псевдонимах отменённого тёплого набора. */
.tam-museum__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;
    padding: 0 var(--ui-space-3);
    border-radius: var(--ui-radius-sm);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
    box-shadow: var(--ui-inner-well), 0 3px 0 rgba(0, 0, 0, 0.4);
    color: var(--ui-text-main);
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-section);
    font-size: var(--ui-size-body);
}

/* Квадратный значковый контрол подписи не несёт, и боковые поля списка
   выше съели бы у него значок: 40px стороны минус 28px полей — меньше
   самого рисунка в 18px. */
.trumpamole__mini-btn {
    justify-content: center;
    padding: 0;
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
}

/*
 * ССЫЛКИ В СОСЕДНИЕ РАЗДЕЛЫ — деревянные кнопки, а не контурные пилюли.
 *
 * «ХРАНИЛИЩЕ · ГАРДЕРОБ · ЛАБОРАТОРИЯ · ХРОНИКА» в коллекции и
 * «КОЛЛЕКЦИЯ · МАГАЗИН» в хранилище рисовались одной волосяной линией
 * золотого цвета поверх прозрачной черноты: на тёплом дереве это
 * выглядело обведённой надписью, а не кнопкой, и владелец отметил, что
 * эти разделы «остались со старым стилем». Материал — тот же, что у
 * второстепенных кнопок §9, подпись — плотный капслок как на вкладках.
 */
.tam-col__link,
.tam-vault__link,
.tam-cos__link,
.tam-arena__link,
/* «В ЛАБОРАТОРИЮ» из хроники. Селектор здесь стоял как `.tam-chr__link`
   и не совпадал ни разу: разметка (`chronicle.view.js`) пишет
   `tam-chr__lab-link`, и кнопка держала свою копию этого же материала в
   `chronicle.css`. */
.tam-chr__lab-link,
/* «ОТКРЫТЬ» из блока недвижимости в профиле — такая же ссылка в соседний
   раздел. Стояла среди мелких контролов §12 и получала внутреннюю тень:
   рядом с плитками показаний, у которых тень такая же, кнопка читалась
   ещё одним вырезом в доске, а не тем, что нажимают. */
.trumpamole__profile-tower-go,
/* Подсказка в партии — тот же маленький деревянный контрол: главное
   действие там доска, и кнопке рядом с ней золотом светить нечем. */
.tam-bonusgame__hint,
/* «Пропустить» в обучении: контурная пилюля на 1px рядом с игровым
   пузырём подсказки читалась ссылкой браузера, а не кнопкой. */
.tam-coach__skip,
/* Возврат из события к доске событий — единый игровой Back (§52 ТЗ), а
   не тонкая контурная пилюля: она стояла над крупным кадром события и
   читалась ссылкой браузера. */
.tam-event-back,
/* «ХРОНИКА» со сцены лаборатории. Селектор здесь стоял как
   `.tam-lab__link` и не совпадал с разметкой ни разу: `lab.view.js`
   пишет `tam-lab__chr-link`, и кнопка держала свою копию этого же
   материала в `lab.css`. Четвёртый такой случай за месяц. */
.tam-lab__chr-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    /* §49 ТЗ: нижняя граница нажимаемого — 44px. Здесь стояло 40px, и
       восемь ссылок разделов не дотягивали до неё на палец. */
    min-height: var(--ui-tap-min);
    padding: 0 var(--ui-space-3);
    border-radius: var(--ui-radius-sm);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45), var(--ui-inner-top);
    color: var(--ui-ivory-light);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-body);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent);
    cursor: pointer;
}

.tam-col__link:active,
.tam-vault__link:active,
.tam-cos__link:active,
.tam-event-back:active,
.tam-chr__lab-link:active,
.trumpamole__profile-tower-go:active,
.tam-arena__link:active {
    transform: translateY(var(--ui-press));
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
}

/* Ряд ссылок делит полосу поровну — как ряд вкладок, а не как облако
   разноразмерных наклеек. */
.tam-col__links,
.tam-vault__links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
    align-self: stretch;
}

.tam-col__links > *,
.tam-vault__links > * {
    flex: 1 1 40%;
    min-width: 0;
}

/*
 * Растушёвка у краёв ленты заданий и выполненная строка держали холодный
 * серый (36,26,26) и (42,33,31): на тёплом дереве обе выглядели грязным
 * пятном. Растушёвка обязана повторять фон под лентой, иначе у полосы
 * появляется серая кайма.
 */
.trumpamole__tasks-fade-l {
    background: linear-gradient(90deg, var(--ui-bg-dark) 0%, transparent 100%);
}

.trumpamole__tasks-fade-r {
    background: linear-gradient(270deg, var(--ui-bg-dark) 0%, transparent 100%);
}

/* Выполненное задание — то же дерево, только приглушённое: строка не
   должна выпадать из материала списка, она просто уже не зовёт нажать. */
.trumpamole__tasks-row.done {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-b) 0%, var(--ui-panel-dark) 100%);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 10%, transparent), var(--ui-shadow-xs);
}

/*
 * Мелкие кнопки разделов — дерево, а не стекло.
 *
 * «Примерить», «Сделать активным», «Заявки», «Отметить прочитанным»
 * писались одинаково: полупрозрачная чернота и рамка в 1px. На тёмном
 * поле такая кнопка неотличима от подписи и не выглядит нажимаемой.
 */
.trumpamole__skins-mini-btn,
.trumpamole__skins-owned-mini-btn,
.trumpamole__profile-check-btn,
.tam-clan__link,
/* Кнопки-варианты в окнах кланов: суммы взноса, действия над участником.
   Стояли контурными пилюлями — прозрачная чернота и рамка в 1px, — то
   есть ровно тем стеклом, о котором говорит заголовок раздела. */
.tam-clanform__preset,
.tam-chr__readall {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45), var(--ui-inner-top);
    color: var(--ui-text-main);
}

/*
 * Кнопка кланов — дерево и плотный капслок, а не строка текста.
 *
 * «ВЛОЖИТЬ ИЗ КАЗНЫ» и «УСКОРИТЬ ЗЕМЛЁЙ» набирались обычным шрифтом
 * раздела (`font-family: inherit`, вес 800, без капслока) на
 * полупрозрачной черноте с волосяной рамкой: рядом с вкладками и
 * вывесками штаба они читались подписью, а не действием. Геометрия,
 * включая уменьшенный вариант `--sm`, осталась в `clans.css`: здесь
 * только материал и надпись, иначе рама задавила бы малую кнопку.
 */
.tam-clan__btn {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45), var(--ui-inner-top);
    color: var(--ui-ivory-light);
}

/* Подпись — отдельным правилом: цвет в него не входит, иначе оно
   погасило бы красный оттенок «Распустить» ниже. */
.tam-clan__btn,
.tam-clan__link {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 80%, transparent);
}

/*
 * «Распустить клан» и «Покинуть клан» — необратимое действие (§36), и
 * красным здесь отмечена подпись, а не корпус: красная плашка рядом с
 * золотым «ВНЕСТИ МОНЕТЫ» соревновалась бы с главной кнопкой экрана.
 * Общий материал мелких кнопок красит их белым по одному классу, потому
 * селектор здесь из двух.
 */
.tam-clan__link.tam-clan__link--danger {
    color: var(--ui-red-light);
}

/*
 * Варианты кнопки в окне отмечены кромкой и подписью, а не корпусом.
 *
 * Правила стоят здесь, а не в `clans.css`: материал строкой выше красит
 * корпус и подпись по одному классу, рама грузится последней, и оба
 * варианта, написанные в разделе, до экрана не доживали. Крупная сумма
 * взноса — золотая кромка, «Исключить из клана» — красная подпись:
 * необратимое действие (§36 ТЗ) отмечено буквой, а не плашкой, иначе
 * ряд одинаковых кнопок превращается в ряд запретов.
 */
.tam-clanform__preset--gold {
    border-color: var(--ui-gold-dark);
    color: var(--ui-gold-light);
}

.tam-clanform__preset--danger {
    border-color: var(--ui-red-deep);
    color: var(--ui-red-light);
}

/*
 * «Забрать» в кланах — зелёная (§36 заказа), как в заданиях и событии.
 *
 * Награду за клановую задачу, за стройку и за веху облавы забирали
 * ЗОЛОТОЙ кнопкой, и на экране штаба выходило три золота подряд:
 * «Заложить», «Вложить из казны» и «Забрать» — три разных по смыслу
 * шага одним цветом. Правило стоит здесь, а не в §9.1 вместе с
 * остальными зелёными: материал `.tam-clan__btn` объявлен ниже §9.1 и
 * при равном весе перебивал бы его.
 */
.tam-clan__btn--claim {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
            var(--ui-green-light) 0%, var(--ui-green) 55%, var(--ui-green-deep) 100%);
    border-color: rgba(0, 0, 0, 0.45);
    box-shadow: 0 3px 0 var(--ui-green-deep), var(--ui-inner-top);
    color: var(--ui-ivory-light);
}

.tam-clan__btn--claim:active {
    box-shadow: 0 1px 0 var(--ui-green-deep);
}

/*
 * Стройка штаба — второй корпус, а не золото (§9.1.1).
 *
 * `.tam-clan__btn--gold` красил «ВЛОЖИТЬ ИЗ КАЗНЫ» и «ЗАЛОЖИТЬ», и на
 * вкладке штаба выходило два золота: второе — «ВНЕСТИ МОНЕТЫ» внизу.
 * Главная кнопка вкладки одна, и это нижняя: взнос доступен каждому
 * участнику, казной распоряжаются глава и офицеры. «ЗАЛОЖИТЬ» вдобавок
 * стоит на каждой строке выбора стройки — повторяющееся действие ряда.
 *
 * Класс переименован (`--main`), потому что имя «gold» перестало быть
 * правдой; вместе с ним снято и старое золотое правило.
 */
.tam-clan__btn--main {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
    box-shadow: 0 3px 0 var(--ui-panel-edge), var(--ui-inner-top);
    color: var(--ui-text-main);
}

.tam-clan__btn--main:active {
    box-shadow: 0 1px 0 var(--ui-panel-edge);
}

/* Главное действие среди мелких кнопок остаётся золотым. «ВЫБРАТЬ» на
   строке купленного облика отсюда ушло в §9.1.1: главным оно не было
   никогда — строк на полке столько же, сколько купленных обликов. */
.trumpamole__skins-mini-btn.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), inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 55%, transparent);
    color: var(--ui-text-dark);
}

.tam-cos__stat svg,
.tam-cos__link svg,
.tam-arena__link svg {
    color: var(--ui-gold-light);
    flex: 0 0 auto;
}

/*
 * Недоступная кнопка остаётся деревянной.
 *
 * Прозрачная серая плашка на тёплом фоне читается как сломанный
 * элемент, а не как «уже надето»: именно так выглядела кнопка
 * «Надето» в гардеробе.
 */
.ui-button:disabled,
.ui-btn:disabled,
button.is-disabled,
/*
 * Кнопки разделов дописаны сюда, а не глушатся прозрачностью у себя.
 *
 * У каждой из них стояло собственное `opacity: .52`, и «Надеть»,
 * «Сезонный пропуск активен», «Крутить» превращались в бледные пятна,
 * сквозь которые просвечивал фон, — ровно тот вид «сломанного
 * элемента», из-за которого правило и появилось.
 */
.trumpamole__skins-mini-btn[disabled],
.trumpamole__skins-owned-mini-btn[disabled],
.trumpamole__arenapvp-duel-btn[disabled] {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-locked) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-locked-text);
    text-shadow: none;
    opacity: 1;
}

/* ==========================================================================
   13. НИЖНЯЯ НАВИГАЦИЯ — ЯЧЕЙКИ

   Ряд на референсе устроен просто: тёмная деревянная полоса, в ней пять
   одинаковых ячеек впритык, и ровно ОДНА из них золотая — открытый
   раздел. Золотая ячейка не круглее и не шире остальных, она просто
   выше и выходит вверх за полосу, как язычок закладки.

   Отсюда три правила, которых прежняя версия не держала:

   1. Ширина у всех пяти одна. Центральная кнопка в 82px делала ряд
      несимметричным, а её радиус 20px и подъём 14px читались как
      отдельный элемент поверх меню, а не как его часть.
   2. Золотая ячейка в ряду одна. Центральная кнопка была золотой
      ВСЕГДА, и в магазине золотыми горели сразу две ячейки. Когда
      открыт раздел, центральная возвращается в дерево (класс
      `is-plain` ставит nav.view.js).
   3. Ряд фиксированной высоты. Язычок выше соседей и выходит за верх
      полосы, но измеренная высота меню (`--tam-nav-h`) от этого расти
      не должна: на ней стоит нижний отступ каждой страницы.

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

/*
 * Замеры сняты с кадров as/4.png (полоса на всех шести кадрах одинакова).
 * Кадр — 329px при телефоне в 390 CSS-px, коэффициент 1.186.
 *
 *   ячейка в покое      676…742 = 66px  → 78 CSS-px
 *   золотой язычок      667…740 = 74px  → 88 CSS-px, выше соседей на 11
 *   значок                        30px  → 36 CSS-px
 *   высота прописной подписи       8px  → ~13px кегля
 *
 * Прежняя полоса была вдвое ниже (58px), значок в ней — 30px, и ряд
 * читался служебной панелью браузера, а не частью игры.
 */
.trumpamole__bottom-nav {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-panel-dark) 100%);
    border-top: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 -8px 20px rgba(0, 0, 0, 0.55), inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 16%, transparent);
}

.trumpamole__nav-items {
    height: 70px;
    align-items: flex-end;
    /*
     * ЗАЗОРА НЕТ. На кадре пять ячеек стоят вплотную и делят полосу без
     * остатка — золотой язычок занимает СВОЮ ЯЧЕЙКУ ЦЕЛИКОМ, от границы
     * до границы. С зазором в 4px он оказывался уже ячейки, между ним и
     * соседями открывалось дерево, и он читался отдельной плиткой,
     * положенной поверх меню, а не выделенной ячейкой ряда.
     */
    gap: 0;
    padding: 0;
}

/* Ширина делится поровну: центральная кнопка своей доли больше не берёт. */
.trumpamole__nav-btn,
.trumpamole__nav-btn--center {
    position: relative;
    flex: 1 1 0;
    width: auto;
    min-width: 0;
    height: 68px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 6px 2px 7px;
    border: 0;
    border-radius: 0;
    /*
     * У НЕАКТИВНОЙ ЯЧЕЙКИ НЕТ КОРПУСА.
     *
     * Здесь стояла своя заливка, светлая линия сверху и тёмная канавка
     * по контуру — пять плиток в ряд. На кадре as/5.png у «МАГАЗИН»,
     * «ИНВЕНТАРЬ», «РЕЙТИНГ» и «КЛУБ» нет ни заливки, ни кромки: значок
     * и подпись лежат прямо на доске полосы (замер: цвет фона ячейки
     * #120b31 совпадает с цветом полосы между ячейками). Именно поэтому
     * золотая ячейка на кадре читается единственной — ей не с чем
     * соревноваться.
     */
    background: none;
    box-shadow: none;
    transform: none;
    transition: box-shadow var(--ui-ease), background var(--ui-ease);
}

/* Плитка внутри ячейки больше не корпус — только место под значок.
   Подъём и нажатие теперь у самой ячейки, поэтому плитка не двигается:
   иначе значок уезжал бы дважды. */
.trumpamole__nav-btn .ui-nav-item__tile,
.trumpamole__nav-btn.is-pressed .ui-nav-item__tile,
.trumpamole__nav-btn.is-active.is-pressed .ui-nav-item__tile {
    position: relative;
    width: auto;
    /* Место под значок в 36px плюс запас под его тёмный кант. */
    height: 38px;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    clip-path: none;
    overflow: visible;
    transform: none;
}

.trumpamole__nav-btn .ui-nav-item__tile img,
.trumpamole__nav-btn .ui-nav-item__tile svg {
    position: relative;
    z-index: 1;
}

/*
 * Подпись во всех пяти ячейках одинаковая: кремовая в тёмной обводке.
 * На кадре она белая с контуром и в покое тоже — приглушённой подписи
 * в референсе нет ни на одной ячейке.
 */
.trumpamole__nav-btn .ui-nav-item__label {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-small);
    line-height: 1;
    letter-spacing: 0.01em;
    text-transform: uppercase;
    color: var(--ui-ivory-light);
    /* Обводка, а не мягкая тень: на кадре у буквы плотный тёмный контур. */
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         0    2px 0 color-mix(in srgb, var(--ui-text-outline) 60%, transparent);
}

/*
 * Золотой язычок: открытый раздел либо центральное действие, когда
 * раздел не открыт. Выше соседей на 11px и выходит за верх полосы —
 * ряд при этом остаётся ровным, потому что высота у него своя.
 *
 * Скругление одинаковое сверху и снизу: на кадре язычок — та же плитка,
 * что соседи, только выше и золотая. Разные радиусы по краям делали из
 * неё вкладку, приклеенную к полосе снизу.
 */
/*
 * АКТИВНАЯ ЯЧЕЙКА — золотой столбец во всю ширину своей доли.
 *
 * Замер по кадру 1 as/5.png (полоса y 508…577, ячейка «ГЛАВНАЯ»
 * x 138…206 при ширине кадра 330 и шаге ячейки 66): золото занимает
 * ячейку от края до края, поднимается над верхней кромкой полосы
 * примерно на 7px кадра (≈8 CSS) и доходит до самого низа. Сверху
 * вниз: #EABE4C (1px рим) → #B2802D → #A0691A → #32218b, снизу тёмная
 * грань #191046. Скругление есть только у ВЕРХНИХ углов — низ уходит
 * в полосу без скругления.
 *
 * Прежняя версия рисовала язычок скруглённым со всех сторон и уже
 * ячейки: получалась отдельная «таблетка», приклеенная к меню.
 * Владелец увидел это как «активная страница выделена не совсем
 * прямая» — на кадре у выделения прямые бока и прямой низ.
 */
.trumpamole__nav-btn.is-active,
.trumpamole__nav-btn--center:not(.is-plain) {
    height: 76px;
    padding: 10px 2px 7px;
    border-radius: var(--ui-radius-md) var(--ui-radius-md) 0 0;
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
        var(--ui-gold-light) 0%, var(--ui-gold) 8%, var(--ui-gold-mid) 58%, var(--ui-gold-dark) 100%);
    box-shadow:
        /* тёмная грань под столбцом — она же нижняя кромка полосы */
        inset 0 -3px 0 var(--ui-gold-deep),
        /* тёплая кромка по бокам: столбец отделён от соседей, но не
           обведён по кругу — на кадре бок у него ровный */
        inset 2px 0 0 color-mix(in srgb, var(--ui-gold-deep) 55%, transparent),
        inset -2px 0 0 color-mix(in srgb, var(--ui-gold-deep) 55%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 65%, transparent),
        0 -2px 10px color-mix(in srgb, var(--ui-gold) 22%, transparent);
}

.trumpamole__nav-btn.is-active .ui-nav-item__tile,
.trumpamole__nav-btn--center:not(.is-plain) .ui-nav-item__tile {
    height: 44px;
    background: none;
    box-shadow: none;
    transform: none;
}

/*
 * Подпись на золоте — кремовая в тёмной обводке, а не коричневая.
 * Коричневый капслок на золоте сливается с фоном ячейки: на референсе
 * это всегда белая буква с чёрным контуром, как на игровых вывесках.
 */
.trumpamole__nav-btn.is-active .ui-nav-item__label,
.trumpamole__nav-btn--center:not(.is-plain) .ui-nav-item__label {
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
         0    2px 0 color-mix(in srgb, var(--ui-text-outline) 55%, transparent);
}

/* Нажатие на неактивную ячейку: корпуса у неё нет, поэтому отзывается
   само содержимое — значок и подпись уходят вниз. */
.trumpamole__nav-btn.is-pressed {
    box-shadow: none;
    transform: translateY(2px);
}

.trumpamole__nav-btn.is-active.is-pressed,
.trumpamole__nav-btn--center:not(.is-plain).is-pressed {
    box-shadow: inset 0 -3px 0 var(--ui-gold-deep),
                inset 0 3px 8px color-mix(in srgb, var(--ui-gold-deep) 45%, transparent);
    transform: translateY(2px);
}

.trumpamole__nav-btn--center .ui-nav-item__tile::after { content: none; }

/* ==========================================================================
   14. ПОЛОСЫ (§71 ТЗ)

   Браузерных `<progress>` в игре нет — это правило соблюдалось и раньше.
   Но «своя полоса» была написана заново в каждом разделе: у забега арены
   дорожка `rgba(24,20,44,.78)`, у цели боя `rgba(255,246,230,.18)`, у
   сета инвентаря `rgba(0,0,0,.42)`, у рейда клана — с золотой волосяной
   рамкой. Заливки тоже расходились: где-то градиент шёл сверху вниз,
   где-то слева направо, и половина держала старые `--gold-2`/`--gold-4`,
   которых в словаре давно нет. Одиннадцать шкал одной игры выглядели
   деталями из одиннадцати разных игр.

   Здесь описан один материал на все: дорожка — утопленная в панель
   канавка с фактурой, заливка — выпуклая полоса с бликом под верхней
   кромкой. Размеры (высота, поля, ширина) остаются в файлах разделов:
   полоса опыта в профиле и полоска цели в бою обязаны быть разной
   толщины, а материалом отличаться не должны.

   Цвет заливки — четыре переменные `--bar-*`, и модификатор переопределяет
   только их. Золото — значение по умолчанию: опыт, сезон, лига, сбор
   коллекции. Зелень (`--quest`) — задание: игрок видит по цвету, что
   полоса «до награды», а не «до уровня». Красный (`--hp`) — здоровье
   босса, единственная шкала, которая УБЫВАЕТ.

   Синего «энергия» и фиолетового «сезон» из §71 здесь нет намеренно:
   собственной шкалы у энергии в игре пока не рисуется, а панель сезона
   сама фиолетовая, и фиолетовая полоса на ней пропадает. Цвет заводится
   вместе со шкалой, которой он нужен, — иначе это мёртвый CSS (§87).
   ========================================================================== */

/* --- 14.1. Дорожка ------------------------------------------------------ */

.trumpamole__bar,
.ui-progress__track,
.tam-set__bar,
.tam-arena__run-bar,
.tam-battle-hud__goal-bar,
.tam-raid__hp-bar,
/* Клетка достижения: своя дорожка была написана светлой прозрачной
   плёнкой поверх карточки — стеклянный прямоугольник вместо канавки. */
.trumpamole__seg,
/* Ступень стройки штаба — та же разрезанная шкала, что клетка
   достижения: пять делений, пройденные горят золотом. Своя дорожка
   стояла чернотой в 30 % с золотой линией в 1px. */
.tam-hq__stage,
.notification-progress {
    position: relative;
    overflow: hidden;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-bg-deep) 0%, var(--ui-bg-dark) 100%);
    /*
     * Кромка нарисована тенью, а не рамкой: тонкие шкалы (полоска цели в
     * бою — 5px, таймер уведомления — 3px) при рамке в 2px съедались бы
     * ею целиком, а высоты заданы в разделах и трогать их нельзя.
     */
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.62), var(--ui-inner-well);
}

/* Широкие шкалы держат настоящую толстую кромку — как доска на референсе. */
.trumpamole__bar,
.ui-progress__track,
.tam-raid__hp-bar {
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
}

/* Скругление шкалы — только таблетка (§ шкала радиусов). */
.trumpamole__bar,
.ui-progress__track,
.tam-set__bar,
.tam-arena__run-bar,
.tam-battle-hud__goal-bar,
.tam-raid__hp-bar,
.trumpamole__seg,
.tam-hq__stage {
    border-radius: var(--ui-radius-pill);
}

/* --- 14.2. Заливка ------------------------------------------------------ */

.trumpamole__bar > i,
.ui-progress__fill,
.tam-set__bar i,
.tam-arena__run-bar-fill,
.tam-battle-hud__goal-bar i,
.tam-raid__hp-bar i,
/* Закрашенная клетка достижения — та же заливка, что у сплошной шкалы:
   разрезана она только геометрией. Свой золотой градиент стоял семью
   числами прежнего мира и на пол-тона расходился с соседней полосой. */
.trumpamole__seg.on,
.tam-hq__stage.is-done,
.notification-progress .progress-bar {
    --bar-hi:  var(--ui-gold-light);
    --bar-top: var(--ui-gold);
    --bar-mid: var(--ui-gold-mid);
    --bar-low: var(--ui-gold-dark);

    border-radius: inherit;
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%,
                                rgba(255, 255, 255, 0.00) 48%),
        linear-gradient(180deg,
            var(--bar-hi)  0%,
            var(--bar-top) 42%,
            var(--bar-mid) 74%,
            var(--bar-low) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55),
                inset 0 -2px 5px rgba(0, 0, 0, 0.22);
}

/* Клетка достижения — единственная в списке, кто сам себе и дорожка, и
   заливка. `border-radius: inherit` берёт радиус у строки-сетки, а у той
   его нет: закрашенная клетка выходила прямоугольной, тогда как пустая
   рядом оставалась таблеткой. */
.trumpamole__seg.on,
.tam-hq__stage.is-done {
    border-radius: var(--ui-radius-pill);
}

/*
 * Номер пройденной ступени — тёмный, без обводки.
 *
 * Подпись набрана в 11px, а §21 запрещает контур мельче 13px: он съедает
 * просвет буквы, и «3» на золоте превращается в кляксу.
 */
.tam-hq__stage.is-done {
    color: var(--ui-text-dark);
    text-shadow: none;
}

/* --- 14.3. Цвет по смыслу ----------------------------------------------- */

/* Задание: полоса ведёт к награде, а не к уровню. */
.ui-progress--quest .ui-progress__fill {
    --bar-hi:  var(--ui-green-btn-hi);
    --bar-top: var(--ui-green-light);
    --bar-mid: var(--ui-green);
    --bar-low: var(--ui-green-deep);
}

/* Здоровье босса: единственная шкала, которая идёт назад. */
.tam-raid__hp-bar i,
.ui-progress--hp .ui-progress__fill {
    --bar-hi:  var(--ui-red-light);
    --bar-top: var(--ui-red);
    --bar-mid: var(--ui-red);
    --bar-low: var(--ui-red-deep);
}

/* ==========================================================================
   15. ШАПКА

   Шапка стоит на каждом экране, поэтому её материал важнее любого
   раздела. Пятно земли поверх дерева задумывалось как фактура, но при
   `blur(5px)` и `mix-blend-mode: overlay` давало мутный светлый развод —
   шапка читалась как заляпанное стекло, а не как доска.
   ========================================================================== */

/*
 * Шапка того же тона, что и поле.
 *
 * Пока фон был светлым, светлая шапка была уместна. С тёмным полем она
 * стала самым ярким пятном экрана и перетягивала внимание с раздела —
 * на всех кадрах референса верх, наоборот, темнее содержимого, и светятся
 * в нём только портрет и чипы.
 */
.trumpamole__topbar {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
        var(--ui-wood) 0%,
        var(--ui-bg-dark) 62%,
        var(--ui-bg-deep) 100%);
}

.trumpamole__topbar::before {
    opacity: 0.14;
    filter: blur(9px);
}

/* Почта и карта — служебные входы: тёмное дерево, а не светлая плитка.
   Сюда же дописана кнопка обновления списка друзей: своей заливкой она
   держала `rgba(0,0,0,.22)` и на тёмной панели раздела превращалась в
   значок без кнопки — промахнуться мимо неё было проще, чем попасть. */
.trumpamole__header-icon-btn,
.trumpamole__icon-btn {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45), var(--ui-inner-top);
}

/* ==========================================================================
   16. ПРОФИЛЬ

   Референс (кадр «ПРОФИЛЬ») собирает игрока в одну панель: портрет,
   имя, VIP, шкала. У нас всё это лежало прямо на фоновой картинке
   кабинета и рассыпалось по экрану.
   ========================================================================== */

.trumpamole__profile-center-stack {
    padding: var(--ui-space-3);
    /* На кадре у карточки игрока скругление панели раздела (16px), а не
       окна (20px): 20px тут читались как всплывшее окно поверх ленты. */
    border-radius: var(--ui-radius-lg);
    /*
     * Заливка непрозрачная. С альфой .92 сквозь карточку просвечивала
     * лента раздела того же тона, перепад «поле тёмное — панель светлая»
     * сходил почти на нет, и кромка карточки читалась только по тени.
     */
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-panel-light) 52%, var(--ui-panel-main) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 6px 0 var(--ui-panel-edge), var(--ui-shadow-deep),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
}

/*
 * Портрет в золотой раме.
 *
 * На кадре у портрета толстый золотой кант и тёмная подложка — он
 * отдельный предмет на доске, а не картинка, приклеенная к фону. Свою
 * рисованную рамку (`.trumpamole__profile-frame`) карточка по-прежнему
 * кладёт поверх, если игрок её надел; кант виден и без неё.
 */
.trumpamole__profile-big-avatar-frame {
    border-radius: var(--ui-radius-md);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-bg-dark) 100%);
    box-shadow: 0 0 0 3px var(--ui-gold), 0 0 0 5px var(--ui-panel-edge),
                var(--ui-shadow-soft);
}

.trumpamole__profile-nick {
    font-family: var(--ui-font-title);
    font-weight: 900;
    font-size: var(--ui-size-title);
    color: var(--ui-text-main);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.55);
}

/*
 * VIP — компактный чип «корона + VIP», а не золотая полоса во всю
 * карточку. На кадре VIP набран золотой строкой рядом с короной и
 * занимает ровно свою ширину; растянутая на 240px золотая плашка
 * забирала главное золотое пятно у шкалы опыта под ней.
 */
.trumpamole__profile-vip-badge {
    justify-self: start;
    min-height: 26px;
    padding: 3px var(--ui-space-2);
    border-radius: var(--ui-radius-pill);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold-mid) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.38);
    color: var(--ui-ivory-light);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-body);
    letter-spacing: 0.03em;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent);
}

/*
 * Монеты, земля и энергия — плитки счётчика с кадра: СВЕТЛАЯ доска,
 * крупное значение и подпись мелким капслоком под ним. Прежде они были
 * тёмными выемками (#100e33 → #0c0a28), и на светлой карточке три дыры
 * читались как «здесь чего-то не хватает», а не как показания.
 */
.trumpamole__profile-meta-line > span {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    gap: 2px;
    padding: 6px var(--ui-space-2);
    border-radius: var(--ui-radius-md);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 20%, transparent),
                0 2px 0 rgba(0, 0, 0, 0.35);
    color: var(--ui-text-main);
}

.trumpamole__profile-meta-line b {
    font-family: var(--ui-font-title);
    font-weight: 900;
    font-size: var(--ui-size-section);
    line-height: 1;
    color: var(--ui-ivory-light);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
}

.trumpamole__profile-meta-line i {
    color: var(--ui-gold-light);
    font-size: var(--ui-size-value);
}

.trumpamole__profile-meta-top {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Подпись плитки — тот же мелкий капслок, что «ТРОФЕИ» и «ПОБЕДЫ». */
.trumpamole__profile-meta-label {
    font-family: var(--ui-font-condensed);
    font-weight: 700;
    font-size: var(--ui-size-micro);
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ui-text-muted);
}

/* ==========================================================================
   17. ГЛАВНАЯ — ПОЛОСА ДЕЙСТВИЯ

   На кадре 1 референса низ экрана занимает одна огромная золотая
   кнопка: игрок всегда знает, куда нажать. У нас её роль играет
   карточка «что делать сейчас» — значит, и выглядеть она должна так же
   решительно: тёплое дерево и крупное золотое действие, а не серая
   плашка с маленькой кнопкой сбоку.
   ========================================================================== */

.trumpamole__home-objective {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-panel-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
}

.trumpamole__home-objective-icon {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-gold-light);
}

.trumpamole__home-objective-title {
    color: var(--ui-gold-light);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.5);
}

/* Реплика в кабинете набрана серо-розовым (#4d3636) — того же чужого
   тона, что и корпус окна. На арте кабинета она читается как наклейка. */
.trumpamole__home-bubble {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-panel-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-lg);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
    color: var(--ui-text-main);
    font-weight: var(--ui-weight-body);
}

.trumpamole__home-cta {
    min-height: 52px;
    padding: 0 var(--ui-space-4);
    font-family: var(--ui-font-title);
    font-weight: var(--ui-weight-title);
    font-size: var(--ui-size-body);
    letter-spacing: 0.03em;
}

/*
 * Подпись арены — единственное золото на сцене.
 *
 * Арена и есть цель экрана (§59), и подпись под ней работает второй CTA:
 * тёмный чип §10 её с остальными шестью постройками не разводит. Корпус
 * тот же, что у золотой кнопки, — заливка с пылью, тёмная кромка,
 * направленная грань, — только мельче. Раздел собирал его сам двумя
 * запасками прежнего мира (#ffd76a → #b36f12 при грани #291a70).
 */
.trumpamole__home-spot[data-code="arena"] .trumpamole__home-spot-label {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold) 55%,
                                var(--ui-gold-dark) 100%);
    border-color: var(--ui-gold-deep);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.42),
                0 3px 0 var(--ui-gold-deep), var(--ui-shadow-soft);
    /* Кегль здесь 12px, и восемь обводок §21 съели бы просвет буквы —
       на мелком золоте читается только тёмная подпись. */
    color: var(--ui-text-dark);
    text-shadow: none;
}

/*
 * Место сцены и карточки на время запроса.
 *
 * Ожидание — не серый прямоугольник (§62): это те же два выреза, что
 * придут ему на смену, с блеском по ним. Раздел держал свой градиент
 * тремя числами (rgba 28,23,80 → 46,39,120), то есть мимо словаря.
 */
.trumpamole__home-skeleton-scene,
.trumpamole__home-skeleton-card {
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-lg);
    background:
        linear-gradient(100deg,
            var(--ui-panel-dark) 0%,
            var(--ui-panel-light) 45%,
            var(--ui-panel-dark) 90%);
    background-size: 240% 100%;
    box-shadow: var(--ui-inner-well);
}

/* ==========================================================================
   18. СНАРЯЖЕНИЕ

   Экран героя писался до словаря целиком: название простым текстом,
   ячейки экипировки — тёмные круги с волосяной золотой рамкой, стрелки
   выбора героя такие же. На тёмном поле всё это висит без материала и
   не читается как набор физических ячеек.
   ========================================================================== */

.tam-hero__title {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 8px var(--ui-space-5);
    border-radius: var(--ui-radius-lg);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
        var(--ui-panel-light) 0%, var(--ui-wood) 46%, var(--ui-wood-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 5px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 28%, transparent);
    font-family: var(--ui-font-title);
    font-size: var(--ui-size-value);
    letter-spacing: 0.05em;
    color: var(--ui-text-main);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.55);
}

/* Ячейка витрины в профиле — та же физическая ячейка, что слот
   снаряжения: трофей вставлен в гнездо, а не наклеен на панель. */
.tam-slot,
.trumpamole__profile-trophy,
/* Та же ячейка в карточке соперника из списка лидеров: витрина чужого
   игрока и своя обязаны выглядеть одинаково, а здесь она собиралась
   числами (#26196a → #1a1148) — материалом строки списка. */
.trumpamole__guest-trophy,
.tam-hero__arrow {
    border: var(--ui-border) solid var(--ui-panel-edge);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45), var(--ui-inner-top);
    color: var(--ui-gold-light);
}

/* Занятая ячейка — золотое кольцо внутри кромки, как у карточек редкости. */
.tam-slot.is-filled {
    border-color: var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45),
                inset 0 0 0 2px color-mix(in srgb, var(--ui-gold) 70%, transparent),
                inset 0 0 12px color-mix(in srgb, var(--ui-gold) 22%, transparent);
}

.tam-slot.is-locked {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-locked) 0%, var(--ui-wood-dark) 100%);
    color: var(--ui-locked-text);
}

/* ==========================================================================
   19. ОКНА

   Окно открывается поверх любого раздела, поэтому его материал виден
   чаще, чем материал любого экрана. Корпус был набран серо-розовым
   (#2b2470 → #241e6a): в палитре игры такого цвета нет, и окно выглядело
   деталью из другого приложения — особенно рядом с деревянными строками
   внутри него самого.
   ========================================================================== */

/*
 * Корпус окна — ТЁМНЫЙ, светлые в нём только плитки содержимого.
 *
 * Замер по кадрам as/5.png (двенадцать окон, от «ежедневных наград» до
 * «достижений»): поле окна #171346, плитка внутри #1e1856. То есть окно
 * повторяет перепад экрана — тёмное поле, светлые панели, — и именно так
 * плитки в нём получают объём.
 *
 * Прежняя версия делала наоборот: корпус шёл от `--ui-panel-light`
 * (#251f66) к `--ui-wood-dark`, был СВЕТЛЕЕ собственных строк, и любая
 * плитка внутри читалась вмятиной, а не карточкой. Заодно светлый верх
 * съедал кремовый заголовок.
 *
 * Кромка двойная, как на кадре: почти чёрный контур снаружи и тонкая
 * песочная волосяная линия внутри него.
 */
.trumpamole__modal-card,
.tam-modal.ui-panel-brown {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        radial-gradient(74% 52% at 50% 0%,
            color-mix(in srgb, var(--ui-gold-hi) 10%, transparent) 0%,
            transparent 62%),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-row-a) 46%, var(--ui-row-b) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-xl);
    box-shadow:
        0 8px 0 var(--ui-bg-dark),
        var(--ui-shadow-deep),
        inset 0 0 0 2px color-mix(in srgb, var(--ui-purple-glow) 55%, transparent),
        inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 14%, transparent);
}

/* Значок над окном стоит в такой же утопленной рамке, как в разделах. */
.trumpamole__modal-floating-icon {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-inner-well), var(--ui-shadow-soft);
}

/*
 * Иконочная плитка окна — НАЖИМАЕМАЯ карточка, а не выемка.
 *
 * Она стояла в одном списке со значком над окном и получала ту же
 * утопленную рамку. Но это ряд из двух-трёх кнопок («Монеты», «Земля»,
 * «Ускорение»): у выемки нет направленной нижней грани, и ряд читался
 * тремя дырками в доске, хотя по каждой можно нажать. В `modal.css`
 * плитке был написан правильный материал карточки — до экрана он не
 * доживал, потому что рама подключается последней. Материал переехал
 * сюда, у раздела осталась геометрия.
 */
.trumpamole__modal-icon-card {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
            var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    box-shadow: 0 4px 0 var(--ui-panel-edge), var(--ui-shadow-soft),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
}

/* Справочная плитка нажатия не ждёт — она утоплена в доску окна. */
.trumpamole__modal-icon-card--info {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border-color: var(--ui-panel-edge);
    box-shadow: var(--ui-inner-well);
}

/*
 * Кнопка закрытия — КРУГ, а не скруглённый квадрат.
 *
 * Крестик закрытия одинаков во всех двенадцати окнах as/5.png: тёмный
 * деревянный кружок с толстым почти чёрным ободом и кремовым знаком, и
 * стоит он в верхнем правом углу, наезжая на кант окна. Скруглённый
 * квадрат в 38px читался кнопкой действия, а не закрытием.
 */
.trumpamole__modal-close,
/* Крестик нижнего листа Трампивуда закрывает такое же окно, значит и
   выглядеть обязан так же: свой был скруглённым квадратом в 34px с
   золотой волосяной обводкой. */
.trumpamole__tw-sheet-close,
.tam-modal__close.ui-icon-button {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-row-a) 100%);
    border: var(--ui-border-thick) solid var(--ui-bg-dark);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45),
                inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 22%, transparent);
    color: var(--ui-ivory-light);
    font-size: var(--ui-size-title);
    font-weight: 800;
}

.trumpamole__modal-close:hover,
.trumpamole__tw-sheet-close:hover,
.tam-modal__close.ui-icon-button:hover {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
}

/*
 * Обе кнопки окна набраны одинаково.
 *
 * На кадре «ВЫЙТИ ИЗ ИГРЫ?» подписи «ОСТАТЬСЯ» и «ВЫЙТИ» — один и тот
 * же плотный кремовый капслок с контуром: разница между кнопками в
 * цвете корпуса, а не в наборе. У нас золотую подпись приводил к этому
 * виду §21, а коричневая соседка оставалась строчной и выглядела
 * ссылкой рядом с кнопкой.
 */
.tam-modal__actions .ui-button,
.trumpamole__modal-actions .ui-button {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.tam-modal__actions .ui-button-brown,
.trumpamole__modal-actions .ui-button-brown {
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent);
}

/* Чипы, значки и подложки внутри окна — общий материал утопленных мест.

   Отдельно про `rgba(255,255,255,0.06)`, который стоял у каждой из этих
   подложек в `modal.css`: белый налёт на тёплом дереве даёт серое пятно.
   На экране раздела так набрана ни одна поверхность — только внутри окон,
   и именно поэтому окно читалось деталью из другого приложения. */
.trumpamole__modal-v4-chip,
.trumpamole__modal-v4-msg,
.trumpamole__modal-v4-iconWrap,
/*
   И отдельно про то, чего в этом списке быть не должно. Сюда попали
   пять ОБЁРТОК: ящик поиска соперника (внутри него утоплена сама
   панель), строка сведений о друге, гнездо кнопки «Пригласить», ряд
   значков VIP и гнездо кнопки «Выбрать». Обёртка — это место, а не
   поверхность: за золотой кнопкой «ВЫБРАТЬ» стояла тёмная плашка шире
   самой кнопки, а три значка подписки лежали на второй такой же
   плашке. Материал получает то, у чего есть край, — значок, чип,
   поле, — а не контейнер, который их держит. */
.trumpamole__modal-pvp-badge,
.trumpamole__modal-pvp-search-panel,
/* Пустое состояние списка друзей ушло в §26: это не выемка, а пунктирная
   строка ожидания. */
.trumpamole__modal-pvp-friend-ava,
.trumpamole__modal-pvp-back,
.trumpamole__modal-vip-badge,
.tam-cost {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

/*
 * Гнёзда, в которых лежат строки окна.
 *
 * Меню арены, список друзей и набор сложностей — это не строки, а ящики
 * под них. В референсе такой ящик вырезан внутрь доски глубже строки,
 * иначе строка и её гнездо сливаются в одно пятно.
 *
 * Лента кланового чата — такой же ящик: пузыри лежали прямо на фоне
 * раздела, и переписка выглядела текстом, насыпанным на страницу, без
 * второго уровня глубины из §63.
 */
.trumpamole__modal-pvp-menu,
.trumpamole__modal-pvp-friends-list,
.trumpamole__modal-pvp-mode-pills,
.tam-clan__chat-feed {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
    border-radius: var(--ui-radius-lg);
    box-shadow: var(--ui-inner-well);
}

/*
 * Строки внутри окна — та же доска, что строки списков в разделах (§7).
 *
 * Набраны они были серо-розовым (#2b2470 → #1c1750) и выходили светлее
 * панели, на которой лежат: строка казалась приподнятой над окном, а не
 * вложенной в него, и перепад «поле тёмное — панель светлая» переворачивался
 * с ног на голову. Направленной грани у строки нет намеренно: у списка из
 * дюжины позиций она превращает окно в лестницу.
 */
.trumpamole__modal-pvp-menu-item,
.trumpamole__modal-pvp-friend-row,
.trumpamole__modal-pvp-mode-pill,
.trumpamole__modal-mail-item,
.tam-clan__chat-bubble {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 18%, transparent),
                var(--ui-shadow-xs);
    color: var(--ui-text-main);
}

/*
 * Карточка подписки VIP — доска с картинкой, а не картинка без края.
 *
 * Под содержимым у неё лежит фотография (`--vip-bg`), поэтому корпуса ей
 * не нужно, но кромка и грань нужны: без них три карточки подряд
 * выглядели тремя картинками, положенными на доску окна. Своя волосяная
 * рамка в 1px и тень в 40px давали ровно тот «стеклянный card», который
 * §62 запрещает поимённо.
 */
.trumpamole__modal-vip-card {
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: var(--ui-edge-panel), var(--ui-shadow-soft);
}

/*
 * Карточка бойца в найденной паре.
 *
 * Заливка у неё смысловая — зелёная у себя, красная у соперника (её
 * задаёт `modal.css`), — а кромка и грань общие: без них пара выглядела
 * двумя цветными пятнами без края.
 */
.trumpamole__modal-pvp-found-player {
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: var(--ui-edge-panel), var(--ui-shadow-soft), var(--ui-inner-top);
}

/*
 * Своё сообщение в клановом чате — лиловая доска, чужое — обычная.
 *
 * Разводить их цветом, а не только стороной, нужно на узком экране: при
 * ширине пузыря в 88 % «слева или справа» перестаёт читаться с одного
 * взгляда.
 *
 * Материал был коричневым (`--ui-earth`) — единственная тёплая поверхность
 * за пределами подземных разделов: лента чужих сообщений шла сине-фиолетовой,
 * а своя половина выглядела комьями земли, положенными поверх интерфейса.
 * Золото сюда тоже не годится: подпись на золоте по §21 читается как кнопка,
 * и десяток своих реплик подряд перебивал бы единственную золотую CTA
 * раздела — «Отправить». Лиловая шапка (`--ui-head-*`) — тот же акцент, что
 * у вывески раздела: он ярче корпуса на глаз, но действием не притворяется.
 */
.tam-clan__chat-line.is-mine .tam-clan__chat-bubble {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-head-light) 0%, var(--ui-head-dark) 100%);
    border-color: var(--ui-panel-edge);
}

/* Поле ввода чата — утопленная поверхность, как поиск по кланам. */
.tam-clan__chat-input {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-main);
}

.tam-clan__chat-input::placeholder { color: var(--ui-text-faint); }

.tam-clan__chat-input:focus {
    outline: none;
    border-color: var(--ui-gold-dark);
}

/* Карточки-створки, промо и ежедневная награда — тот же корпус, что окно. */
.trumpamole__modal-split-card,
.trumpamole__modal-promo-mini-card,
.trumpamole__modal-daily-card {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        radial-gradient(70% 60% at 50% 8%,
            color-mix(in srgb, var(--ui-purple-glow) 16%, transparent) 0%,
            transparent 58%),
        linear-gradient(180deg,
            var(--ui-panel-light) 0%,
            var(--ui-panel-main) 34%,
            var(--ui-wood) 72%,
            var(--ui-wood-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow:
        0 8px 0 var(--ui-panel-edge),
        var(--ui-shadow-deep),
        inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 28%, transparent),
        inset 0 -18px 30px rgba(0, 0, 0, 0.30);
}

/* Шаг онбординга: будущий утоплен в доску, текущий — золотая фишка. */
.trumpamole__modal-stepper-dot {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-dark) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
}

.trumpamole__modal-stepper-dot.is-active {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold-mid) 100%);
    border-color: var(--ui-gold-deep);
    box-shadow: 0 2px 0 var(--ui-gold-deep), var(--ui-inner-top);
}

/* На золоте светлый текст не читается — номер становится тёмным. */
.trumpamole__modal-stepper-dot.is-active .trumpamole__modal-stepper-num {
    color: var(--ui-text-dark);
    text-shadow: none;
}

/* ==========================================================================
   20. СЛУЖЕБНОЕ
   ========================================================================== */

/* Пустые состояния и подсказки не должны быть светлее панелей. */
.tam-store__note,
.tam-store__limit {
    color: var(--ui-text-muted);
}

/* --------------------------------------------------------------------------
   ПУСТОЕ МЕСТО (§56 ТЗ)

   Пустой список показывал строку «Предметов нет» с мелким контурным
   значком — ровно то, что ТЗ запрещает: так выглядит таблица в панели
   управления, а не экран игры. Место, где ничего нет, — это тоже кадр
   игры: герой, объяснение и, если есть куда вести, кнопка.

   Материал — утопленная поверхность (§8): пустое место ВЫРЕЗАНО в доске
   раздела, а не лежит на ней отдельной карточкой. Иначе пустой список
   выглядел бы содержательнее полного.

   Разметку собирает `TAM.UI.emptyHtml` (`modules/ui/components.js`), и
   картинка у всех разделов одна: `assets/ui/empty_mole.webp`.
   -------------------------------------------------------------------------- */

/* Наследства в списке больше нет: короткие пустые места арены, клана и
   башни переехали на `ui-empty--compact`. */
.ui-empty,
/* Ожидание внутри раздела (§55) сделано из того же материала, что пустое
   место, и намеренно: в одном списке это два состояния подряд — сперва
   «копаю», потом «пусто». Разъедься они по материалу, переход выглядел бы
   подменой блока, а не сменой состояния. */
.ui-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ui-space-2);
    padding: var(--ui-space-5) var(--ui-space-4);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    border-radius: var(--ui-radius-md);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-dark) 100%);
    box-shadow: var(--ui-inner-well);
    color: var(--ui-text-muted);
    text-align: center;
}

/* Крот сидит в собственной лунке: круглая выемка держит фигуру на месте
   и не даёт ей выглядеть наклейкой, брошенной на панель. */
.ui-empty__art,
.ui-loading__art {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    width: 132px;
    height: 132px;
    margin-bottom: calc(var(--ui-space-1) * -1);
    border-radius: 50%;
    background:
        var(--ui-dirt),
        radial-gradient(circle at 50% 62%,
            var(--ui-earth-hole) 0%, color-mix(in srgb, var(--ui-earth-hole) 85%, transparent) 46%, transparent 72%);
}

.ui-empty__art img,
.ui-loading__art img {
    width: 116px;
    height: 116px;
    object-fit: contain;
    filter: drop-shadow(var(--ui-art-shadow-sm));
}

.ui-empty__title,
.ui-loading__title {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-section);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ui-text-main);
    text-shadow: 0 2px 0 rgba(0, 0, 0, 0.55);
}

.ui-empty__note,
.ui-loading__note {
    max-width: 30ch;
    font-size: var(--ui-size-body);
    line-height: 1.35;
    color: var(--ui-text-muted);
}

.ui-empty__cta {
    margin-top: var(--ui-space-2);
    min-width: 180px;
    /* Капслок задан здесь, а не тоном кнопки: он живёт только у золотой
       (`ui-tokens.css`), и кнопка пустого места второго корпуса — та
       самая «Поделиться» у друзей — стояла строчными среди сплошного
       капслока экрана. */
    text-transform: uppercase;
}

/* Короткое место внутри панели — без героя: в ленте боёв и в чате клана
   фигура в полный рост заняла бы больше самого списка. */
.ui-empty--compact {
    gap: var(--ui-space-1);
    padding: var(--ui-space-4);
}

/* Пустое место внутри сетки занимает всю её ширину: в галерее аватаров
   и рамок оно иначе встаёт в одну колонку из трёх. */
.ui-empty--wide { grid-column: 1 / -1; }

/* Закрытый раздел (§58): картинка приглушена, поверх неё висит замок на
   золотой фишке — «сюда пока нельзя», а не «здесь ничего нет». */
.ui-empty--locked .ui-empty__art { position: relative; }

.ui-empty--locked .ui-empty__art img {
    filter: grayscale(0.55) brightness(0.62) drop-shadow(var(--ui-art-shadow-sm));
}

.ui-empty__lock {
    position: absolute;
    right: 4px;
    bottom: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border: var(--ui-border) solid var(--ui-gold-deep);
    border-radius: 50%;
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold-dark) 100%);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.45);
    color: var(--ui-text-dark);
}

/* --------------------------------------------------------------------------
   ОЖИДАНИЕ ВНУТРИ РАЗДЕЛА (§55 ТЗ)

   Загрузочный экран игры давно сделан кадром (Tonald ждёт, Moley роет), а
   вот ожидание ВНУТРИ разделов — галерея аватаров, рамки, достижения,
   музей, статистика, друзья, рейтинг, задания — до сих пор крутило серое
   кольцо. Кольцо-спиннер не принадлежит ни одной игре: это ровно тот
   generic web-элемент, который запрещает §62, и в списке он выглядел
   чужой заплатой между двумя нарисованными состояниями.

   Теперь ожидание — тот же кадр: крот копает туннель
   (`assets/states/loading_dig.webp`), под ним бежит золотая шкала игры.
   Картинка ОДНА на всю игру намеренно: у ожидания нет своего содержания,
   и второй рисунок только разошёлся бы с первым.

   Разметку собирает `TAM.UI.loadingHtml` (`modules/ui/components.js`).
   -------------------------------------------------------------------------- */

/* Кирка ходит вверх-вниз: неподвижная картинка в месте ожидания читается
   зависшим экраном, а не работой. Ход короткий — качается сама фигура,
   лунка под ней стоит. */
.ui-loading__art img {
    animation: tam-dig calc(var(--tam-t-panel) * 3) ease-in-out infinite;
    transform-origin: 50% 88%;
}

@keyframes tam-dig {
    0%, 100% { transform: rotate(-4deg) translateY(0); }
    50%      { transform: rotate(4deg) translateY(4px); }
}

/* Шкала ожидания шире картинки не бывает: рядом с ней нет числа, и
   растянутая на всю панель она обещает точный прогресс, которого здесь
   нет. */
.ui-loading__bar {
    width: min(216px, 72%);
    margin-top: var(--ui-space-1);
}

/*
 * Заливка не знает доли и ходит от края к краю.
 *
 * Время взято из лестницы движения суммой (`panel` * 6 = 1.32s), а не
 * числом: полный проход быстрее секунды выглядит нервным, медленнее
 * полутора — зависшим. Ступень `ambient` тут не годится — это не дыхание
 * фона, а отчёт о работе.
 */
.ui-loading__bar .ui-progress__fill {
    width: 38%;
    animation: tam-loading-run calc(var(--tam-t-panel) * 6) var(--tam-ease-out) infinite;
}

/* Заливка не уходит из канавки целиком: при полном выезде за край шкала
   на четверть цикла оказывается пустой, и кадр ожидания читается
   сломанной полосой. Крайние положения оставляют в дорожке заметный
   кусок золота. */
@keyframes tam-loading-run {
    0%   { transform: translateX(-58%); }
    100% { transform: translateX(220%); }
}

/* Короткое ожидание внутри панели — без героя, как и пустое место. */
.ui-loading--compact {
    gap: var(--ui-space-1);
    padding: var(--ui-space-4);
}

.ui-loading--wide { grid-column: 1 / -1; }

@media (prefers-reduced-motion: reduce) {
    .ui-btn { transition: none; }

    /* Ожидание остаётся видимым и без движения: шкала просто стоит
       залитой наполовину — иначе игрок с выключенной анимацией видит
       пустую канавку и решает, что экран умер. */
    .ui-loading__art img { animation: none; }

    .ui-loading__bar .ui-progress__fill {
        width: 50%;
        animation: none;
    }
}

/* ==========================================================================
   21. НАДПИСЬ НА ЗОЛОТЕ

   Один приём на всю игру: кремовая буква в толстой тёмной обводке.
   Проверено по всем шести кадрам — «ИГРАТЬ» и «УРОВЕНЬ 45» на главной,
   «ИЗМЕНИТЬ» в профиле, активная вкладка «СКИНЫ» в инвентаре, ценники
   магазина: везде белый текст с контуром, нигде — коричневый.

   Почему список, а не один класс. Золотую кнопку в игре собирают
   шестью разными классами: `.ui-button-gold` из словаря, `.ui-btn--gold`
   из наследства и по своему классу в кланах, скинах, заданиях и
   вкладках разделов. Пока каждый красил надпись сам, половина кнопок
   оставалась с коричневым капслоком, который на золоте почти не виден.

   Раздел стоит ПОСЛЕДНИМ намеренно: §11 (вкладки) и §19 (окна) красят
   те же элементы, и правило обязано идти после них.
   ========================================================================== */

.ui-button-gold,
.ui-btn--gold,
.trumpamole__skins-mini-btn.gold,
/* «ВЫБРАТЬ» на строке облика золотой больше не бывает (§9.1.1), но
   подпись у неё та же кремовая в обводке: корпус под ней тёмный, и
   правило §21 держит её читаемой ровно так же. */
.trumpamole__skins-owned-mini-btn.gold,
.trumpamole__match3-overlay-btn,
.tam-blocker__btn,
.tam-col__btn--gold,
.trumpamole__tasks-mini-btn,
/* Название набора на панели предложения. Подпись здесь не на золоте, но
   приём тот же и по той же причине: капслок в 18px лежит на цветном
   корпусе, и без контура он теряет край. Раздел держал копию этих
   восьми смещений у себя. */
.tam-store__hero-title {
    color: var(--ui-ivory-light);
    /*
     * Контур собран восемью смещениями по 1px, а не четырьмя по 2px.
     *
     * Четыре угловых смещения в 2px оставляют разрывы по сторонам буквы и
     * при этом смыкаются внутри её просвета: подпись «ОСТАТЬСЯ» на кнопке
     * окна расплывалась в пятно. Восемь по 1px дают ровный контур той же
     * плотности и вдвое тоньше — как на кадрах.
     */
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), -1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent);
}

/*
 * Вкладка получает обводку в 1px, а не в 2px.
 *
 * Тот же случай, о котором предупреждает конец этого раздела: подпись
 * вкладки набрана плотным капслоком в 13px, и контур в 2px с четырёх
 * сторон смыкается внутри буквы. Живой пример — «МОЛОТКИ» в гардеробе:
 * на золотой вкладке вместо слова стояла тёмная клякса. Ширина обводки
 * должна быть меньше просвета, а он у 13px условно 2px на всю букву.
 */
.trumpamole__skins-tab-btn.active,
.trumpamole__tasks-tab-btn.active,
.trumpamole__profile-tab-btn.active,
.tam-store__tab.is-active,
.tam-clan__tab.is-active,
.tam-season__tab.is-active,
.tam-tower__addr-btn.is-active,
.tam-event-tab.is-active {
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent);
}

/* Кнопки заданий, рефералов и событий подписаны по тому же правилу.
   Подпись кнопок события набрана в 13px именно поэтому: на 12px обводка
   §21 съедает просвет буквы, и правило ниже требует тёмной подписи без
   контура — а «ЗАБРАТЬ» обязана читаться как главное действие карточки.
   Корпус у неё с этого захода зелёный (§9.1), но кремовая подпись в
   тёмной обводке остаётся: на зелени она читается так же. */
.trumpamole__tasks-small-btn:not([disabled]),
.tam-event-task__btn,
.tam-event-goods__btn:not(.is-off),
/* «ОТКРЫТЬ» на плашке хроники: подписи у неё не было задано вовсе, и
   она наследовала белый текст плашки — белое на золоте без контура. */
.tam-chr-hint__btn,
/* «ОТДАТЬ ДИГГСУ»: подпись стояла тёмно-синей на золоте без контура —
   разница яркости меньше двух ступеней. Корпус у неё с §9.1.1 второй,
   тёмный, и кремовая подпись в обводке на нём читается так же. Зелёная
   «ЗАБРАТЬ РЕЗУЛЬТАТ» сюда не входит: у неё свой контур цвета травы. */
.tam-lab__btn:not(.tam-lab__btn--claim),
/* «НАЙТИ СОПЕРНИКА»: подпись стояла белой без контура на синем корпусе,
   а корпус с этого захода золотой. */
.trumpamole__arenapvp-btn-primary,
.tam-hero__buy {
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), -1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent);
}

/*
 * Премиум-кнопка (`modules/ui/buttons.js`) — отдельная реализация,
 * и подпись у неё красилась своим правилом в
 * common.css: почти чёрная на золоте. Ею собраны «Собрать доход» в
 * башне, кнопки окон, дуэлей и профиля — половина главных действий
 * игры мимо словаря. Тёмной подпись остаётся только на тёмном корпусе
 * (`is-dark`) и на кремовом.
 */
.trumpamole__btn-par:not(.is-dark):not(.trumpamole__btn-par--ivory) .trumpamole__btn-par__text {
    color: var(--ui-ivory-light);
    /*
     * Контур собран восемью смещениями по 1px, а не четырьмя по 2px.
     *
     * Четыре угловых смещения в 2px оставляют разрывы по сторонам буквы и
     * при этом смыкаются внутри её просвета: подпись «ОСТАТЬСЯ» на кнопке
     * окна расплывалась в пятно. Восемь по 1px дают ровный контур той же
     * плотности и вдвое тоньше — как на кадрах.
     */
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), -1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent);
}

.trumpamole__btn-par--ivory .trumpamole__btn-par__text {
    color: var(--ui-text-ivory);
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
}

/*
 * Мелкие значения на золоте обводку НЕ получают.
 *
 * Обводка в 2px съедает внутренний просвет буквы кеглем меньше 13px, и
 * цифра превращается в кляксу. Номер шага в окне, цена в золотом бейдже
 * и подобное остаются тёмными — там контраст даёт сам цвет.
 */
.trumpamole__modal-stepper-dot.is-active .trumpamole__modal-stepper-num,
/* Табличка говорящего в кинематике босса набрана в 12px и красилась
   псевдонимом `--brown-0` отменённого тёплого набора. Цвет по смыслу
   тот же, но названный — и стоит он теперь в одном списке с остальными
   мелкими надписями на золоте. */
.trumpamole__boss-frame-name {
    color: var(--ui-text-dark);
    text-shadow: none;
}

/* ==========================================================================
   22. РЕФЕРЕНС ЦЕЛИКОМ: ВКЛАДКИ, ОКНА, НАБОР

   Раздел закрывает то, что владелец перечислил прямым списком: «табы
   везде переделать на такие, как в референсах», «модальные окна тоже»,
   «как отображается текст». Он стоит после §21 намеренно — §11 и §19
   красят те же контролы, и правило обязано быть последним.
   ========================================================================== */

/* --------------------------------------------------------------------------
   22.1. Вкладки библиотеки компонентов

   `.ui-tabs` рисовал сегментный переключатель iOS: тёмное гнездо с
   утоплением, внутри прозрачные кнопки, выбранная — плоская золотая
   плашка с КОРИЧНЕВОЙ подписью. На кадре инвентаря (as/5.png) вкладки
   устроены иначе: гнезда нет вовсе, каждая вкладка — самостоятельная
   деревянная плитка с тёмным контуром, выбранная бронзовая со светлым
   кантом, подпись кремовая в обоих состояниях.

   Раздел приводит библиотеку к тому же материалу, что §11 даёт живым
   вкладкам разделов: иначе в игре два разных ряда вкладок.
   -------------------------------------------------------------------------- */

.ui-tabs {
    gap: var(--ui-space-1);
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
}

.ui-tabs__tab {
    height: 42px;
    border-radius: var(--ui-radius-md);
    border: var(--ui-border) solid var(--ui-bg-dark);
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-row-a) 100%);
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ui-purple-light) 55%, transparent),
                0 2px 0 rgba(0, 0, 0, 0.42);
    color: var(--ui-ivory-light);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-body);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent);
}

.ui-tabs__tab.is-active {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold) 0%, var(--ui-gold-mid) 40%, var(--ui-gold-dark) 100%);
    border-color: var(--ui-gold-light);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.42),
                inset 0 1px 0 color-mix(in srgb, var(--ui-gold-hi) 45%, transparent),
                0 0 10px color-mix(in srgb, var(--ui-gold) 28%, transparent);
    color: var(--ui-ivory-light);
}

/*
 * Выбранная вкладка приподнята на пиксель, невыбранные утоплены.
 *
 * На кадре ряд читается как физический переключатель прежде всего по
 * высоте: «МОЛОТКИ» стоит выше соседей, у соседей видна тёмная канавка
 * сверху. Одной заливкой этого не получить.
 */
.ui-tabs__tab.is-active,
.trumpamole__skins-tab-btn.active,
.trumpamole__tasks-tab-btn.active,
.trumpamole__profile-tab-btn.active,
.tam-store__tab.is-active,
.tam-clan__tab.is-active,
.tam-season__tab.is-active,
.tam-event-tab.is-active {
    transform: translateY(-1px);
}

/* --------------------------------------------------------------------------
   22.2. Окна

   Материал корпуса §19 совпал с кадром, а набор и раскладка — нет.
   -------------------------------------------------------------------------- */

/*
 * Заголовок окна — плотный кремовый капслок с обводкой.
 *
 * Во всех двенадцати окнах as/5.png заголовок набран ровно так же, как
 * вывеска раздела: Roboto Condensed 900, капслок, кремовая буква в
 * тёмной обводке («НЕДОСТАТОЧНО РЕСУРСОВ», «КОЛЕСО ФОРТУНЫ», «ВЫЙТИ ИЗ
 * ИГРЫ?»). У нас он шёл основным шрифтом в обычном регистре и на тёмном
 * корпусе читался подписью, а не заголовком.
 *
 * Обводка собрана восемью смещениями по 1px, а не одним `2px`: при
 * кегле 18px сплошная двойка смыкается внутри «О» и «Е» и превращает
 * букву в кляксу — уже проверено на подписях золотых кнопок (§21).
 */
.trumpamole__modal-title,
.tam-modal__title {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-section);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0 -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  1px  0   0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), -1px  0   0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         0 3px 0 rgba(0, 0, 0, 0.45);
}

/*
 * Крестик стоит ВНУТРИ окна, в его верхнем правом углу.
 *
 * Замер по кадру «НЕДОСТАТОЧНО РЕСУРСОВ»: круг закрытия целиком внутри
 * корпуса, отступ от правой кромки — 13px, от верхней — 6px, и он стоит
 * на одной линии с заголовком. У нас половина окон открывалась с
 * модификатором `--close-above` (top:-8, right:-4), и круг висел НАД
 * углом в пустоте: на тёмной подложке это выглядело оторванной от окна
 * кнопкой. Оба модификатора теперь ставят его одинаково — расходиться
 * этим двум состояниям незачем.
 */
.trumpamole__modal--close-above .trumpamole__modal-close,
.trumpamole__modal--close-inside .trumpamole__modal-close {
    top: 10px;
    right: 12px;
}

/*
 * Кремовая эмаль внутри окна — чужой материал.
 *
 * Итог боя показывал очки на кремовой плитке с коричневой цифрой. Ни в
 * одном из двенадцати окон референса кремовых плиток нет: значение
 * всегда стоит в тёмной выемке светлой цифрой (окно «ПОВЫСИТЬ УРОВЕНЬ?»,
 * окно «ДОСТИЖЕНИЯ»). Крем в игре остаётся только у кнопки `ivoryCream`.
 */
.tam-result__score {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-row-a) 0%, var(--ui-panel-main) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.55);
    box-shadow: var(--ui-inner-well), inset 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 10%, transparent);
}

.tam-result__score-label {
    color: var(--ui-ivory-dark);
    opacity: 1;
}

.tam-result__score-value {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    color: var(--ui-gold-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 90%, transparent),
         0 3px 0 rgba(0, 0, 0, 0.4);
}

/* --------------------------------------------------------------------------
   22.3. Набор текста

   «Как отображается текст» — отдельный пункт списка владельца. На кадрах
   работает одна пара: округлый Nunito для всего, что читают словами, и
   плотный Roboto Condensed 900 капслоком для всего, что читают как
   ярлык (вывеска, подпись секции, вкладка, подпись кнопки, название
   предмета под картинкой).
   -------------------------------------------------------------------------- */

/*
 * Название предмета под картинкой — ярлык, а не подпись.
 *
 * На кадре инвентаря под каждым молотком стоит тёмная плашка с плотным
 * кремовым капслоком («ДЕРЕВЯННЫЙ», «ПРАЗДНИЧНЫЙ»). У нас это был
 * обычный текст основным шрифтом, и сетка предметов читалась списком.
 */
.tam-vault__card-name,
.tam-col__card-name,
/* Имя блока здесь `.tam-museum__name`, без `card`: разметку музея пишет
   `modules/profile/profile.js`, и с названием `.tam-museum__card-name`
   эта запись не срабатывала ни разу — раздел набирал название своей
   копией тех же шести объявлений. */
.tam-museum__name {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent);
}

/*
 * Крупное значение — тоже плотное.
 *
 * «25 340», «1 245», «100K» на кадре профиля набраны тем же плотным
 * шрифтом, что и заголовки: у округлого Nunito в весе 800 цифры широкие,
 * и четырёхзначное число в чипе ресурса упиралось в края.
 */
.ui-value,
.tam-battle-hud__value {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   22.4. Витрина скина

   Кадр «ИНВЕНТАРЬ · СКИНЫ» (as/4.png) устроен так: герой стоит КРУПНО по
   центру панели, за ним расходятся золотые лучи, под ним имя плотным
   кремовым капслоком, под именем редкость золотом, и только потом кнопка.
   Портрет занимает две трети высоты витрины.

   У нас витрина была строкой: портрет 144px слева, справа название и
   восемь строк описания, ниже две кнопки. Герой — главное, что покупают,
   — занимал шестую часть площади, а две трети отдавались тексту, который
   на кадре не показан вовсе.
   -------------------------------------------------------------------------- */

.trumpamole__skins-active-inner {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: var(--ui-space-2);
    padding: var(--ui-space-4) var(--ui-space-3) var(--ui-space-3);
}

/*
 * Золотые лучи за героем.
 *
 * Приём с кадра: не свечение, а расходящиеся клинья. Собраны
 * `repeating-conic-gradient` и погашены к краю радиальной маской —
 * картинкой это было бы 40 КБ ради восьми треугольников.
 */
.trumpamole__skins-active-preview {
    position: relative;
    width: min(230px, 62vw);
    height: min(230px, 62vw);
    /* Зеркалить героя незачем: персонажи нарисованы лицом к игроку. */
    transform: none;
    overflow: visible;
}

.trumpamole__skins-active-preview::before {
    content: "";
    position: absolute;
    inset: -14%;
    background: repeating-conic-gradient(from 0deg,
        color-mix(in srgb, var(--ui-gold-hi) 30%, transparent) 0deg 9deg,
        transparent 9deg 18deg);
    -webkit-mask-image: radial-gradient(closest-side,
        #000 12%, rgba(0, 0, 0, 0.7) 46%, transparent 78%);
    mask-image: radial-gradient(closest-side,
        #000 12%, rgba(0, 0, 0, 0.7) 46%, transparent 78%);
    animation: tamSkinRays 26s linear infinite;
    pointer-events: none;
}

@keyframes tamSkinRays {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .trumpamole__skins-active-preview::before { animation: none; }
}

/*
 * Портрет прибит к рамке витрины, а не «height: 100 %».
 *
 * Рамка стала квадратом в 230px и потеряла обрезку (`overflow: visible`
 * нужен лучам). При этом `height: 100%` у портрета считается от строки
 * грид-раскладки, а строка здесь авторазмерная — процент превращается в
 * `auto`, и картинка вставала в свой натуральный рост. Герой пропорций
 * 230×280 вылезал на полсотни пикселей вниз и ложился прямо на имя
 * скина: «MOLE FREDDY BURROWBEAR» читалось поверх лап.
 */
.trumpamole__skins-active-preview img {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(var(--ui-art-shadow-lg));
}

.trumpamole__skins-active-meta {
    align-items: center;
    text-align: center;
    width: 100%;
    gap: var(--ui-space-1);
}

.trumpamole__skins-active-name {
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-title);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--ui-ivory-light);
    white-space: normal;
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), 1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), 1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         0 3px 0 rgba(0, 0, 0, 0.45);
}

/*
 * Описание остаётся, но перестаёт быть половиной экрана.
 *
 * Убирать текст целиком нельзя: у каждого скина в базе своя история, и
 * она — часть игры. Три строки с многоточием дают ровно то, что на
 * кадре: подпись под именем, а не статья.
 */
.trumpamole__skins-active-desc {
    max-width: 34ch;
    font-size: var(--ui-size-small);
    line-height: 1.3;
    color: var(--ui-text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.trumpamole__skins-active-actions {
    width: 100%;
    max-width: 300px;
    flex-wrap: nowrap;
    justify-content: center;
}

.trumpamole__skins-active-actions > * {
    flex: 1 1 0;
    min-width: 0;
}

/* --------------------------------------------------------------------------
   22.5. Значки — предметы, а не глифы

   «Иконки должны быть именно в стиль этого» — про сатирическую подачу
   игры. Половину работы делает сама графика (`mvp/icons.js` переведён с
   контура на заливку), вторую — тёмный кант вокруг знака.

   На кадрах референса ни один значок не лежит на фоне плоским пятном: у
   молота, секундомера, звезды, монеты есть толстый тёмный край, и
   именно он отделяет предмет от плитки, на которой тот лежит. В SVG с
   `currentColor` такой край нельзя нарисовать внутри пути — он был бы
   вторым цветом и сломал бы перекрашивание, — поэтому его даёт
   `drop-shadow` четырьмя смещениями по пикселю.

   Список точечный: кант нужен там, где значок — ПРЕДМЕТ (усиление в бою,
   ячейка снаряжения, ресурс в чипе, плитка навигации). В строках списка
   и в подписях знак остаётся служебным, и обводка там только зашумит.
   -------------------------------------------------------------------------- */

.tam-battle-hud__boost-icon svg,
.tam-battle-hud__stat svg,
.tam-slot svg,
.tam-hero__arrow svg,
.trumpamole__map-node-stars svg,
.ui-nav-item__tile svg {
    filter:
        drop-shadow( 1px  0   0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent))
        drop-shadow(-1px  0   0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent))
        drop-shadow( 0    1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent))
        drop-shadow( 0   -1px 0 color-mix(in srgb, var(--ui-text-outline) 85%, transparent))
        drop-shadow( 0    2px 1px rgba(0, 0, 0, 0.45));
}

/*
 * Плитка усиления — цветной предмет на дереве.
 *
 * На кадре боя четыре плитки разного цвета: рыжая с молотом, синяя с
 * молнией, зелёная с секундомером, серо-синяя с ракетой. У нас все
 * четыре шли одной серо-стальной заливкой (#55575e → #3a3c42) — цвета
 * из палитры игры в ней нет вовсе, и ряд читался панелью настроек.
 * Тема приходит атрибутом `data-theme` из `battle-hud.js`.
 *
 * Цвета плиток тоже были набраны числами мимо словаря (#4a9ad6, #5da531,
 * #9a5cc6 и соседи) — близкими к его синему, зелёному и фиолетовому, но
 * не равными им: та же болезнь, из-за которой раздел расходится с рамой.
 * Теперь берутся из словаря. Фиолетовая плитка — на ступень ярче корпуса
 * (`--ui-rar-epic`), иначе щит тонет в фиолетовом HUD.
 */
.tam-battle-hud__boost[data-theme="hammer"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-mid) 0%, var(--ui-gold-dark) 100%);
}

.tam-battle-hud__boost[data-theme="energy"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-blue) 0%, var(--ui-blue-deep) 100%);
}

.tam-battle-hud__boost[data-theme="time"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-green-btn-top) 0%, var(--ui-green-btn-low) 100%);
}

.tam-battle-hud__boost[data-theme="shield"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-rar-epic) 0%, var(--ui-purple-light) 100%);
}

.tam-battle-hud__boost[data-theme="boost"] {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold) 0%, var(--ui-gold-mid) 100%);
}

/*
 * Счётчик на выбранной вкладке — кремовый, как и её подпись.
 *
 * `collection.css` и `vault.css` красят его в тёмно-коричневый
 * (rgba(11, 9, 37,.72)): правило писалось, когда выбранная вкладка была
 * СВЕТЛО-золотой. После §11 она бронзовая, а подпись на ней кремовая с
 * тёмной обводкой — и обводка достаётся счётчику по наследству. Тёмная
 * цифра в тёмной обводке слипается: «4/5» на вкладке «МОЛИ» читалось
 * как одно смазанное пятно.
 *
 * Полупрозрачность вместо своего цвета: цифра остаётся тише подписи, но
 * набрана тем же материалом.
 */
.trumpamole__skins-tab-btn.active .tam-col__tab-count,
.trumpamole__skins-tab-btn.active .tam-vault__tab-count,
.trumpamole__skins-tab-btn.active .tam-chr__tab-count,
.tam-clan__tab.is-active .tam-clan__tab-badge,
.tam-season__tab.is-active .tam-season__tab-badge {
    color: var(--ui-ivory-light);
    opacity: 0.82;
}

/* На невыбранной вкладке счётчик тоже кремовый, только тише: серо-бежевый
   #604ebc из наследства — единственный холодный тон в ряду. */
.trumpamole__skins-tab-btn .tam-col__tab-count,
.trumpamole__skins-tab-btn .tam-vault__tab-count,
.trumpamole__skins-tab-btn .tam-chr__tab-count {
    color: var(--ui-ivory-dark);
}

/* ==========================================================================
   23. СЧЁТЧИКИ И НАКЛЕЙКИ (§53 ТЗ)

   Та же беда, что была у полос: «здесь тебя ждут» игра говорила семью
   разными деталями. Счётчик писем в шапке был ЗОЛОТЫМ (то есть неотличим
   от подписи уровня рядом), счётчик заданий в меню — красным
   прямоугольником в 6px скругления, счётчик наград сезона — своим золотым
   градиентом мимо словаря (`#FCF9A0 → #C37939`), счётчик вкладки клана —
   прозрачной чернотой, точка на предмете главной — плоским `#e53935`, а
   счётчик вкладки магазина жил инлайновым `style` прямо в `shop.js`.

   На кадре 8 референса счётчик один и тот же на всех четырёх кнопках
   (СОБЫТИЯ 2, ГЕРОИ 12, ЗАДАЧИ 3, ПОЧТА 1): КРУГ с толстой тёмной
   кромкой, заливка от светло-красного к красному, белая цифра, вылет за
   угол кнопки. Отличается только цвет — зелёный там, где число значит
   «сколько собрано», а не «сколько ждёт».

   Поэтому здесь два материала, а не один класс:
   23.1 — счётчик (красный круг с числом): почта, задания, сезон, вкладки
          разделов, магазин, башня;
   23.2 — наклейка (капслок на золоте или на красном): «НОВОЕ», «-50 %»,
          редкость. Наклейка НЕ круглая и никогда не несёт числа — иначе
          игрок читает выгоду как счётчик.

   Размеры (вылет за угол, кегль, отступ от подписи) остаются в файлах
   разделов: счётчик на кнопке шапки в 44px и счётчик на вкладке в 30px
   обязаны быть разного размера, а материалом отличаться не должны.
   ========================================================================== */

/* --- 23.1. Счётчик ------------------------------------------------------ */

.ui-badge--red,
.trumpamole__header-mail-badge,
.trumpamole__header-notify-dot,
.trumpamole__nav-badge,
.trumpamole__nav-task-badge,
.tam-season-banner__badge,
.tam-season__tab-badge,
.tam-clan__tab-badge,
/* Счётчик готовых заданий на карточке события: ровно то же «здесь тебя
   ждут», а держал свой золотой градиент числами (#FCF9A0 → #C37939) с
   коричневой цифрой — тот самый счётчик наград сезона, о котором
   говорит заголовок раздела. */
.tam-event-card__badge,
.tam-tower__addr-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /*
     * Круг, а не прямоугольник со скруглением. На кадре все четыре
     * счётчика — правильные круги; таблетка получается сама, когда цифр
     * становится три, потому что растёт только ширина.
     */
    border-radius: var(--ui-radius-pill);
    border: 2px solid var(--ui-panel-edge);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 72%,
                                var(--ui-red-deep) 100%);
    /* Кант наружу + собственная тень: круг лежит НА кнопке, а не в ней. */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.34),
                var(--ui-shadow-xs);
    color: var(--ui-ivory-light);
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-value);
    letter-spacing: 0;
    /*
     * Обводки у цифры нет намеренно. Счётчик мельче любой подписи (10-11px),
     * и восемь смещений §21 съедают просвет у «8» и «0» полностью — на
     * кадре цифра набрана чистым белым по красному.
     */
    text-shadow: none;
    text-transform: none;
}

/*
 * На выбранной вкладке счётчик остаётся красным.
 *
 * §22 гасит его до `opacity: .82` заодно с текстовыми счётчиками вкладок:
 * то правило писалось про «4/5» на бронзе, а не про красный круг — под
 * ним круг выцветал ровно на той вкладке, куда игрока и зовут.
 */
.tam-clan__tab.is-active .tam-clan__tab-badge,
.tam-season__tab.is-active .tam-season__tab-badge,
.trumpamole__skins-tab-btn.active .tam-clan__tab-badge,
.tam-tower__addr-btn.is-active .tam-tower__addr-badge {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 72%,
                                var(--ui-red-deep) 100%);
    color: var(--ui-ivory-light);
    opacity: 1;
}

/*
 * Счётчик ЗАПАСА — золотой, а не красный.
 *
 * Красный круг §23.1 говорит «здесь тебя ждут»: непрочитанное письмо,
 * готовое задание, собранная награда. Число на плитке усиления в бою
 * значит другое — сколько штук лежит в ящике, и краснеть ему не с чего:
 * красный кружок на молоте читался бы как «молот требует внимания».
 * Форма и кромка те же, что у красного, — меняется только заливка.
 *
 * Материал был свой (#f4cd5e → #d59a24 при кромке #0a071c) — золото
 * прежнего мира на единственной плитке игры.
 */
.tam-battle-hud__boost-count,
/* «×2» в углу карточки музея — ровно то же «сколько штук лежит»: игрок
   нашёл артефакт дважды. Держал свою черноту в 44 % с лиловой линией в
   1px и золотой цифрой без корпуса, то есть читался не счётчиком, а
   надписью поверх картинки. */
.tam-museum__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--ui-radius-pill);
    border: 2px solid var(--ui-panel-edge);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold) 55%,
                                var(--ui-gold-dark) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.42),
                var(--ui-shadow-xs);
    /* Цифра тёмная: кегль здесь 13px, и восемь обводок §21 съели бы у
       «8» весь просвет — на золоте в такой мелочи читается только тёмная. */
    color: var(--ui-text-dark);
    font-family: var(--ui-font-condensed);
    font-weight: var(--ui-weight-title);
    text-shadow: none;
}

/*
 * Точка без числа — единственное исключение из «счётчик всегда с цифрой».
 *
 * На главной у предмета комнаты числа нет и быть не может: там либо есть
 * что забрать, либо нет. Материал тот же, только меньше и без содержимого.
 */
.trumpamole__home-spot-badge {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 100%);
    border: 2px solid var(--ui-panel-edge);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.34),
                var(--ui-shadow-xs);
}

/* --- 23.2. Наклейка ----------------------------------------------------- */

/*
 * Выгода и новизна — прямоугольная наклейка, а не круг. На кадре 8 это
 * красное «НОВОЕ» на пропуске сезона: та же кромка и та же заливка, но
 * форма другая, и в ней капслок, а не число.
 */
.tam-store__badge,
.tam-cos__badge,
.ui-badge:not(.ui-badge--red) {
    border-radius: var(--ui-radius-sm);
    border: 2px solid var(--ui-panel-edge);
    font-family: var(--ui-font-condensed);
    font-weight: var(--ui-weight-title);
    letter-spacing: .04em;
    text-transform: uppercase;
}

.tam-cos__badge,
.ui-badge:not(.ui-badge--red):not(.ui-badge--quiet) {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold) 55%,
                                var(--ui-gold-dark) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.42),
                0 2px 0 var(--ui-gold-deep);
    color: var(--ui-text-dark);
}

.tam-store__badge {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-red-light) 0%, var(--ui-red) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.30),
                0 2px 0 var(--ui-red-deep);
    color: var(--ui-ivory-light);
}

/* Тихая наклейка — «скоро», «закрыто»: то же дерево, что у панели, потому
   что она ничего не обещает и звать никуда не должна. */
.ui-badge.ui-badge--quiet {
    background:
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-dark) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 2px 0 var(--ui-bg-deep);
    color: var(--ui-text-main);
}

/* --- 23.3. Кружок замка ------------------------------------------------- */

/*
 * Закрытое помечается замком (§58 ТЗ), и замок этот сидит в углу
 * карточки маленьким кружком: «предмет не расщепляется» в музее, «где
 * взять» в сейфе. Считать его счётчиком нельзя — он ничего не обещает и
 * никуда не зовёт, поэтому и не красный, и не золотой: то же дерево
 * панели, что у тихой наклейки выше, только круглое.
 *
 * Оба кружка держали свой материал: музейный — черноту в 55 % с золотым
 * значком по псевдониму отменённого тёплого набора, сейфовый — свою
 * копию градиента панели. Размер, место в углу и кегль значка остаются
 * в файлах разделов: в музее кружок сидит слева сверху, в сейфе —
 * справа снизу.
 */
.tam-museum__guard,
.tam-vault__card-lock {
    background:
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-dark) 100%);
    border: 2px solid var(--ui-panel-edge);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14),
                var(--ui-shadow-xs);
    color: var(--ui-ivory-dark);
}

/* ==========================================================================
   24. ПОДСКАЗКИ (§54 ТЗ)

   Подсказки в игре не было вовсе: ни компонента, ни стиля. Число вроде
   «14 / 40» или «потолки на период» объяснить было нечем — под плиткой на
   320px не помещается ни одной лишней строки.

   Пузырь собран из того же материала, что премиальная панель кадров
   `grok/8-9.png`: фиолетовое стекло, толстая тёмная кромка, светлый рим по
   верху. Своего цвета у подсказки нет — она обязана читаться поверх любой
   поверхности игры, а фиолетовый на экране игры и так самый тёмный из
   панелей. Текст — белый основной, без обводки: §21 съедает просвет у
   кегля меньше 13px, а подсказку читают, а не разглядывают.

   Разметку и поведение держит `modules/ui/tooltip.js`: пузырь один на
   документ, показывается по тапу и гаснет сам.
   ========================================================================== */

.ui-tip {
    position: fixed;
    top: 0;
    left: 0;
    z-index: var(--tam-z-tip);
    display: none;
    box-sizing: border-box;
    padding: var(--ui-space-3) var(--ui-space-3) calc(var(--ui-space-3) - 2px);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-purple-panel-top) 0%,
                                var(--ui-purple-panel) 55%,
                                var(--ui-purple-panel-low) 100%);
    box-shadow: var(--ui-inner-top),
                inset 0 0 0 1px var(--ui-purple-panel-rim),
                var(--ui-shadow-deep);
    color: var(--ui-text-main);
    text-align: left;
    /* Пузырь стоит поверх раздела и ничего не перехватывает: тап сквозь
       него закрывает подсказку тем же обработчиком, что и тап мимо. */
    pointer-events: none;
}

.ui-tip.is-open {
    display: block;
    animation: ui-tip-in var(--ui-ease);
}

@keyframes ui-tip-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.ui-tip__title {
    margin-bottom: 2px;
    font-family: var(--ui-font-condensed);
    font-weight: var(--ui-weight-title);
    font-size: var(--ui-size-small);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ui-gold-light);
}

.ui-tip__text {
    font-family: var(--ui-font-main);
    font-weight: var(--ui-weight-body);
    font-size: var(--ui-size-body);
    line-height: 1.35;
}

/*
 * Хвост — тот же квадрат под сорок пять градусов, что и корпус.
 *
 * Кромка видна только на двух его гранях: остальные две уходят под
 * пузырь, иначе поперёк подсказки прошла бы тёмная черта.
 */
.ui-tip__tail {
    position: absolute;
    width: 12px;
    height: 12px;
    margin-left: -6px;
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    transform: rotate(45deg);
}

.ui-tip:not(.is-below) .ui-tip__tail {
    bottom: -7px;
    border-top: 0;
    border-left: 0;
    background: var(--ui-purple-panel-low);
}

.ui-tip.is-below .ui-tip__tail {
    top: -7px;
    border-bottom: 0;
    border-right: 0;
    background: var(--ui-purple-panel-top);
}

/*
 * Подсказка обучения — тот же пузырь, что и `.ui-tip`.
 *
 * Своё окно она держала на волосяной золотой рамке поверх тёмно-синего
 * градиента и рядом с настоящей подсказкой читалась чужой. Место, размер
 * и вырезку в затемнении по-прежнему считает `mvp.css`: отсюда приходит
 * только материал.
 */
.tam-coach__tip {
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-purple-panel-top) 0%,
                                var(--ui-purple-panel) 55%,
                                var(--ui-purple-panel-low) 100%);
    box-shadow: var(--ui-inner-top),
                inset 0 0 0 1px var(--ui-purple-panel-rim),
                var(--ui-shadow-deep);
    color: var(--ui-text-main);
}

/* --- 24.2. Значок подсказки --------------------------------------------- */

/*
 * Кнопка со значком «i» рядом с числом или заголовком секции. Она не
 * главное действие и не должна спорить с ним за внимание: тёмный кружок
 * того же рода, что утопленные поверхности, и приглушённый значок.
 *
 * В потоке кружок занимает ровно 20px. Кнопка в 32px, которая стояла
 * здесь сначала, ломала плитку на 320px: подпись «ОФИСЫ» с ней перестала
 * помещаться в строку, значок съезжал под неё, и число уходило за низ
 * плитки. Палец при этом попадает: область касания добита прозрачным
 * полем `::after` на 8px во все стороны, а места в потоке оно не занимает.
 */
.ui-tip-btn {
    position: relative;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: -4px;
    width: 20px;
    height: 20px;
    margin-left: 4px;
    padding: 0;
    border: var(--ui-border) solid var(--ui-purple-panel-rim);
    border-radius: var(--ui-radius-pill);
    background: var(--ui-panel-dark);
    color: var(--ui-text-muted);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.ui-tip-btn::after {
    content: '';
    position: absolute;
    inset: -8px;
    border-radius: var(--ui-radius-pill);
}

.ui-tip-btn > svg {
    display: block;
    width: 14px;
    height: 14px;
}

.ui-tip-btn[aria-describedby],
.ui-tip-btn:active {
    border-color: var(--ui-gold);
    color: var(--ui-gold-light);
}

/*
 * Место значка — строка ЗАГОЛОВКА секции, а не плитка с числом.
 *
 * Плитка башни «ОФИСЫ 8 / 10» проверена обоими способами и не выдержала
 * ни одного: значок в потоке уводил подпись на вторую строку и выталкивал
 * число за низ плитки, а вынесенный в угол — ложился поверх последних
 * букв подписи. При 320px в такой плитке свободных пикселей нет вовсе.
 * Число, которое нуждается в объяснении, объясняется в заголовке своей
 * секции; отдельного «углового» вида у значка нет намеренно.
 */

/* ==========================================================================
   25. НАГРАДА (§64 ТЗ)

   «Награда никогда не должна выглядеть строкой текста `+100 coins`» —
   а выглядела ровно так во всех местах, где игра что-то выдаёт: окно
   уровня писало «Награда за уровень: 750 монет. Так держать!», окно
   задания — «Вы получили 750 монет за задание», итог локации собирал
   список через запятую («250 монет, 3 земли, 40 опыта»), а универсальное
   окно дописывало в подзаголовок строчку «Вы получаете [значок] 750
   монет!» тем же кеглем и цветом, что и пояснение рядом.

   Здесь награда — трофей: рисованная монета (земля, энергия, жизнь,
   билет, свиток опыта) в утопленной ячейке, под ней золотая табличка с
   числом, за монетой тёплое свечение, по ячейке раз в несколько секунд
   проходит блик, в углах вспыхивают две искры. Ровно тот набор, который
   §64 и перечисляет: иконка, «+100», частицы, shine.

   Материал взят у премиальной панели `grok/8-9.png` (кадр «BRAWL PASS»):
   награда яруса там — предмет в тёмно-фиолетовой ячейке с толстой кромкой
   и чип с числом под ней. Своих цветов и своих скруглений раздел не
   заводит.

   Разметку собирает `TAM.UI.rewardsHtml(...)` из `modules/ui/components.js`.
   ========================================================================== */

.ui-reward-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    /* Шире, чем кажется нужным: табличка с числом выступает за ячейку в
       обе стороны, и на «+1 250» соседние плитки сходились вплотную. */
    gap: var(--ui-space-4);
    margin: var(--ui-space-3) 0 var(--ui-space-2);
}

.ui-reward {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Табличка с числом наезжает на низ ячейки — место под неё нужно
       вернуть, иначе соседний блок подойдёт к ней вплотную. */
    padding-bottom: 12px;
    animation: ui-reward-pop var(--tam-t-modal) cubic-bezier(.2, 1.5, .5, 1) backwards;
    animation-delay: var(--ui-reward-delay, 0ms);
}

/* Ячейка предмета: та же выемка, что §8, но с тёплым свечением за
   картинкой — награда обязана светиться, иначе это просто значок. */
.ui-reward__art {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 72px;
    height: 72px;
    padding: 8px;
    overflow: hidden;
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    background:
        radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--ui-gold-light) 34%, transparent) 0%,
                                           transparent 62%),
        linear-gradient(180deg, var(--ui-purple-panel-top) 0%,
                                var(--ui-purple-panel-low) 100%);
    box-shadow: var(--ui-inner-well),
                inset 0 0 0 1px var(--ui-purple-panel-rim),
                var(--ui-shadow-soft);
}

.ui-reward__art img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Тень под предметом отделяет его от ячейки: на кадре у каждой
       награды есть тёмный подпор, без него предмет лежит наклейкой. */
    filter: drop-shadow(var(--ui-art-shadow-pin));
}

.ui-reward__art > svg {
    width: 100%;
    height: 100%;
    color: var(--ui-gold-light);
}

/* Блик — узкая светлая полоса под 20°, проходит по ячейке раз в 3,6 с.
   Реже, чем кажется нужным: на экране наград бывает три ячейки разом, и
   непрерывное мерцание превращает окно в аттракцион (§45). */
.ui-reward__art::after {
    content: '';
    position: absolute;
    top: -40%;
    left: -60%;
    width: 40%;
    height: 180%;
    transform: rotate(20deg);
    background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%,
                                       rgba(255, 255, 255, 0.42) 50%,
                                       rgba(255, 255, 255, 0) 100%);
    animation: ui-reward-shine var(--tam-t-ambient) var(--ui-reward-delay, 0ms) infinite;
}

/* Искры — две точки по углам ячейки. Частицы §64 без единого лишнего
   узла: обе живут на самой награде псевдоэлементами. */
.ui-reward::before,
.ui-reward::after {
    content: '';
    position: absolute;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--ui-gold-hi) 0%,
                                        transparent 70%);
    opacity: 0;
    animation: ui-reward-spark 2.4s infinite;
    pointer-events: none;
}

.ui-reward::before { top: -3px; right: 2px; animation-delay: .2s; }
.ui-reward::after  { top: 26px; left: -4px; animation-delay: 1.3s; }

/*
 * Число на золотой табличке.
 *
 * Кремовая буква в тёмной обводке — §21: подпись на золоте в игре
 * одна на всех, и «+750» здесь ничем не отличается от «ИГРАТЬ».
 * Табличка наезжает на низ ячейки, как чип с числом под наградой яруса
 * на кадре, и потому лежит выше по слою.
 */
.ui-reward__value {
    position: relative;
    z-index: 1;
    margin-top: -12px;
    padding: 2px var(--ui-space-2) 3px;
    border: var(--ui-border) solid var(--ui-gold-btn-edge);
    border-radius: var(--ui-radius-pill);
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-gold-btn-hi) 0%,
                                var(--ui-gold-btn-top) 40%,
                                var(--ui-gold-btn-low) 100%);
    box-shadow: 0 2px 0 var(--ui-gold-btn-deep), var(--ui-shadow-soft);
    font-family: var(--ui-font-condensed);
    font-weight: var(--ui-weight-title);
    font-size: var(--ui-size-value);
    line-height: 1.15;
    letter-spacing: .02em;
    white-space: nowrap;
    color: var(--ui-ivory-light);
    text-shadow:
        -1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px -1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
         1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),  0px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent),
        -1px  1px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent), -1px  0px 0 color-mix(in srgb, var(--ui-text-outline) 92%, transparent);
}

/* Подпись под наградой — чем именно наградили. Нужна там, где предмет
   сам за себя не говорит: «опыт», «билет», название сундука. */
.ui-reward__label {
    margin-top: 4px;
    max-width: 86px;
    font-family: var(--ui-font-condensed);
    font-weight: var(--ui-weight-section);
    font-size: var(--ui-size-small);
    letter-spacing: .04em;
    text-transform: uppercase;
    text-align: center;
    color: var(--ui-text-muted);
}

/* Главная награда окна — крупнее прочих: §64 требует для больших наград
   полноценного показа, а не такой же плитки в ряду. */
.ui-reward--hero .ui-reward__art {
    width: 104px;
    height: 104px;
    border-radius: var(--ui-radius-lg);
}

.ui-reward--hero .ui-reward__value {
    font-size: var(--ui-size-section);
    padding-left: var(--ui-space-3);
    padding-right: var(--ui-space-3);
}

@keyframes ui-reward-pop {
    from { opacity: 0; transform: scale(.72) translateY(8px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes ui-reward-shine {
    0%   { left: -60%; }
    /* Полоса проходит за четверть цикла, остальное время её нет:
       иначе блик идёт непрерывно и читается как сбой отрисовки. */
    24%  { left: 120%; }
    100% { left: 120%; }
}

@keyframes ui-reward-spark {
    0%, 70%, 100% { opacity: 0; transform: scale(.6); }
    82%           { opacity: 1; transform: scale(1.25); }
}

/*
 * Просьба системы уменьшить движение отменяет блик, искры и появление,
 * но не саму награду: §45 запрещает аттракцион, а не показ.
 */
@media (prefers-reduced-motion: reduce) {
    .ui-reward,
    .ui-reward::before,
    .ui-reward::after,
    .ui-reward__art::after {
        animation: none;
    }
    .ui-reward::before,
    .ui-reward::after { opacity: 0; }
}

/* ==========================================================================
   26. ЗВЕЗДА УРОВНЯ (§65 ТЗ)

   «Level Up: крупная звезда, номер, gold glow, rewards, CTA». Из пяти
   пунктов в игре было два — награда и кнопка; сам уровень объявлялся
   строкой заголовка «Уровень 25!», набранной тем же кеглем, каким окно
   сообщает о нехватке монет.

   Звезда — золотой трофей в тёмной кромке: тот же материал, что у
   золотой кнопки и таблички награды, и та же надпись по §21 — кремовая
   цифра в тёмной обводке. За звездой расходятся лучи, как за наградой
   яруса на кадре «BRAWL PASS» референса `grok/8.png`.

   Разметку собирает `TAM.UI.levelStarHtml(level)`; звезду ставит окно
   через поле `levelStar` (`modules/ui/modals.js`).
   ========================================================================== */

.ui-level-star {
    position: relative;
    display: grid;
    place-items: center;
    width: 132px;
    height: 132px;
    /* Звезда наезжает на низ картинки окна: герой и трофей — одна сцена,
       а не два блока друг под другом. */
    margin: -12px auto var(--ui-space-2);
    animation: ui-level-star-pop calc(var(--tam-t-sheet) + var(--tam-t-tap)) cubic-bezier(.2, 1.6, .4, 1) both;
}

/* Лучи славы. Тот же приём, что у победы в итоге боя: повтор конического
   градиента вместо десятка узлов разметки (§84). */
.ui-level-star__rays {
    position: absolute;
    width: 188px;
    height: 188px;
    border-radius: 50%;
    background: repeating-conic-gradient(
        color-mix(in srgb, var(--ui-gold-light) 30%, transparent) 0deg 7deg,
        transparent 7deg 30deg);
    -webkit-mask-image: radial-gradient(circle, #000 24%, transparent 70%);
    mask-image: radial-gradient(circle, #000 24%, transparent 70%);
    animation: ui-level-star-turn 30s linear infinite;
    pointer-events: none;
}

.ui-level-star__shape {
    position: relative;
    width: 100%;
    height: 100%;
    /* Тёплое свечение из-под звезды — тот самый gold glow §65. Тень под
       ней той же семьи, что у награды: трофей лежит на панели, а не
       парит над ней. */
    filter: drop-shadow(0 0 var(--ui-glow-lg) color-mix(in srgb, var(--ui-gold-light) 45%, transparent))
            drop-shadow(var(--ui-art-shadow-sm));
}

.ui-level-star__shape path { stroke: var(--ui-panel-edge); }
.ui-level-star__hi  { stop-color: var(--ui-gold-hi); }
.ui-level-star__mid { stop-color: var(--ui-gold); }
.ui-level-star__lo  { stop-color: var(--ui-gold-dark); }

/*
 * Номер уровня — по §21: на золоте надпись кремовая в тёмной обводке, а
 * не коричневая. Кегль задан от ширины звезды, чтобы трёхзначный уровень
 * не вылезал за её лучи.
 */
.ui-level-star__num {
    position: absolute;
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: 46px;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--ui-ivory-light);
    text-shadow: 0 2px 0 var(--ui-gold-deep),
                 0 0 3px rgba(0, 0, 0, 0.55),
                 0 3px 6px rgba(0, 0, 0, 0.4);
    -webkit-text-stroke: 2.5px var(--ui-panel-edge);
}

/* Трёхзначный уровень набирается мельче: иначе цифры упираются в лучи. */
.ui-level-star__num:not(:empty) { padding-bottom: 2px; }

@keyframes ui-level-star-pop {
    0%   { opacity: 0; transform: scale(.4) rotate(-24deg); }
    100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

@keyframes ui-level-star-turn {
    0%   { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/*
 * Картинка окна уступает звезде часть места.
 *
 * Иначе на экране 320×640 герой, звезда, заголовок, пояснение и награда
 * не помещаются разом: награда уезжала под кромку прокрутки, то есть
 * ровно то, ради чего окно и открывается, оказывалось за краем.
 */
.trumpamole__modal--level .trumpamole__modal-trophy {
    max-height: min(170px, 21vh);
    margin-bottom: 4px;
}

/* На узком экране звезда уступает место награде и кнопке. */
@media (max-width: 360px) {
    .ui-level-star {
        width: 108px;
        height: 108px;
        margin-top: -10px;
    }
    .ui-level-star__rays { width: 156px; height: 156px; }
    .ui-level-star__num  { font-size: 38px; -webkit-text-stroke-width: 2.5px; }
}

/* Низкий экран — то же самое, но по высоте: звезда в 132px на 640
   пикселях высоты съедает пятую часть окна. */
@media (max-height: 700px) {
    .ui-level-star {
        width: 100px;
        height: 100px;
        margin-top: -10px;
    }
    .ui-level-star__rays { width: 146px; height: 146px; }
    .ui-level-star__num  { font-size: 35px; -webkit-text-stroke-width: 2.5px; }
}

@media (prefers-reduced-motion: reduce) {
    .ui-level-star,
    .ui-level-star__rays { animation: none; }
}

/* ==========================================================================
   27. ТРОФЕЙ ВСТРЕЧИ (§68 ТЗ)

   «Победа над боссом: особенная сцена — графика босса, награда, артефакт
   или сундук, крупный эффект». Артефакт за первую победу сервер выдавал
   и раньше (`Boss::defeat` кладёт его в музей), но сцена о нём молчала:
   игрок закрывал окно с абзацем текста, не зная, что в руках у него
   появился пропуск в башню.

   Карточка трофея — тот же материал, что у карточки раздела (§6), только
   кромка и свечение берут цвет редкости из общего набора (`--rar`,
   `game-ui.css`): рамка, свечение и подпись сразу, как требует §15
   tok.txt. Предмет лежит в такой же выемке, что и награда (§25), и с
   таким же бликом — это одна семья вещей, а не два разных трофея.

   Разметку собирает `BossService.prototype._trophy`.
   ========================================================================== */

.tam-bosswin__trophy {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--ui-space-3);
    padding: var(--ui-space-3);
    overflow: hidden;
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 52%, var(--ui-panel-dark) 100%);
    /* Кромка цветом редкости — но поверх неё та же тёмная обводка кольцом
       внутри, что у карточек: без неё яркая рамка висит в воздухе. */
    border: var(--ui-border-thick) solid var(--rar, var(--ui-gold-dark));
    border-radius: var(--ui-radius-lg);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.55),
                0 0 22px -4px var(--rar, var(--ui-gold)),
                var(--ui-shadow-soft);
    animation: ui-trophy-in var(--tam-t-sheet) cubic-bezier(.2, 1.4, .4, 1) calc(var(--tam-t-stagger) * 3) backwards;
}

/* Ячейка предмета — выемка §8 с тёплым светом за рисунком, как у награды. */
.tam-bosswin__trophy-art {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 76px;
    height: 76px;
    padding: 8px;
    overflow: hidden;
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    background:
        radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--ui-gold-light) 32%, transparent) 0%,
                                           transparent 62%),
        linear-gradient(180deg, var(--ui-purple-panel-top) 0%,
                                var(--ui-purple-panel-low) 100%);
    box-shadow: var(--ui-inner-well), inset 0 0 0 1px var(--ui-purple-panel-rim);
}

.tam-bosswin__trophy-art img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(var(--ui-art-shadow-pin));
}

/* Картинки нет — ячейка не остаётся пустой дырой: в ней тот же значок
   трофея, которым подписаны победы в остальных разделах. */
.tam-bosswin__trophy-art.is-empty::after {
    content: '';
    width: 34px;
    height: 34px;
    border-radius: var(--ui-radius-sm);
    background: linear-gradient(180deg, var(--ui-gold-light) 0%, var(--ui-gold-dark) 100%);
    opacity: 0.5;
}

/* Блик по ячейке — тот же, что у награды §25, и с тем же периодом. */
.tam-bosswin__trophy-art::before {
    content: '';
    position: absolute;
    top: -40%;
    left: -60%;
    width: 40%;
    height: 180%;
    transform: rotate(20deg);
    background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%,
                                       rgba(255, 255, 255, 0.4) 50%,
                                       rgba(255, 255, 255, 0) 100%);
    animation: ui-reward-shine var(--tam-t-ambient) infinite;
}

.tam-bosswin__trophy-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.tam-bosswin__trophy-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

/* Чип «Трофей встречи»: второй признак вида предмета рядом с редкостью. */
.tam-bosswin__trophy-kind {
    padding: 2px 8px;
    border-radius: var(--ui-radius-pill);
    background: rgba(0, 0, 0, 0.32);
    border: 1px solid color-mix(in srgb, var(--ui-gold-light) 40%, transparent);
    color: var(--ui-gold-light);
    font-family: var(--ui-font-condensed);
    font-weight: 900;
    font-size: var(--ui-size-micro);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

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

.tam-bosswin__trophy-lore {
    font-family: var(--ui-font-main);
    font-size: var(--ui-size-small);
    line-height: 1.35;
    color: var(--ui-text-muted);
}

/* Трофей выкладывается на панель с перелётом — тем же движением, каким
   выскакивает плитка награды: обе вещи игрок только что заработал. */
@keyframes ui-trophy-in {
    0%   { opacity: 0; transform: scale(0.86) translateY(12px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .tam-bosswin__trophy,
    .tam-bosswin__trophy-art::before { animation: none; }
}

/* --------------------------------------------------------------------------
   23. Нехватка ресурса

   Красный здесь смысловой (§36): это единственное место, где число
   говорит «не хватает». Раньше он стоял в четырёх файлах сырым
   `#ff4757` — цветом прежнего, тёплого мира, — и палитру 28 августа
   пережил незамеченным. Один класс, один токен.
   -------------------------------------------------------------------------- */
.tam-cost__lack,
.trumpamole__modal-v4-msg.is-short {
    color: var(--ui-red-light);
}

/* --------------------------------------------------------------------------
   24. Всплывающее уведомление

   Уведомление всплывает поверх ЛЮБОГО экрана, поэтому его доску игрок
   видит чаще, чем материал любого раздела. Материал у неё тот же, что у
   окна (§19): тёмная доска с фактурой, почти чёрный контур, тонкая
   тёплая линия внутри. В `notifications.css` он стоял семью сырыми
   хексами (`#181043`, `#140d37`, `#100a2d`, `#0a061b`, `#100b2d`,
   `#0b071e`, `#261969`, `#180f41`) — числа уже нового мира, но мимо
   словаря, и ровной заливкой без крупы, чего в игре нет ни у одной
   поверхности.
   -------------------------------------------------------------------------- */
.notification-content {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow:
        var(--ui-shadow-deep),
        inset 0 0 0 2px color-mix(in srgb, var(--ui-purple-glow) 45%, transparent),
        inset 0 2px 0 color-mix(in srgb, var(--ui-purple-glow) 14%, transparent);
}

/*
 * Короткий тост («Скопировано») — та же доска, только мельче.
 *
 * Это вторая, более старая реализация уведомления
 * (`modules/social/referral.js`): она всплывает над нижним меню после
 * копирования ссылки. Материал у неё был свой — прозрачная чернота с
 * волосяной сиреневой рамкой, — и рядом с большим уведомлением игры она
 * читалась подсказкой браузера, а не игровой панелью.
 */
/* Тихая плашка о новой записи хроники (§325) — третья реализация того же
   всплывающего сообщения: она встаёт над нижним меню поверх любого
   раздела. Материал у неё был свой (#241d68 → #1d1656) и на полступени
   светлее тоста рядом. */
.tam-chr-hint,
.trumpamole__toast {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-shadow-deep), var(--ui-inner-top);
    color: var(--ui-text-main);
}

/* Гнездо под значок — утопленная в доску ступень (§10). */
.notification-icon {
    background:
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-dark) 0%, var(--ui-bg-dark) 100%);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.5);
}

/* Крестик закрытия — второстепенная кнопка, а не своя плашка. */
.notification-close {
    background: linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-panel-main) 100%);
    border: 2px solid var(--ui-panel-edge);
    color: var(--ui-ivory-light);
}

.notification-close:hover {
    background: linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
}

/*
 * Цветная грань слева: тот же смысловой набор, что у значка. Раньше здесь
 * лежал второй материальный набор (#4CAF50, #f44336, #ff9800, #2196F3),
 * и не работал вовсе — класс вида на доску не ставил никто.
 */
.notification-content.is-success::after { background: var(--ui-green); }
.notification-content.is-error::after   { background: var(--ui-red); }
.notification-content.is-warning::after { background: var(--ui-gold); }
.notification-content.is-info::after    { background: var(--ui-blue); }

/* --------------------------------------------------------------------------
   24.1. Значки уведомления

   Четыре кружка всплывающего сообщения стояли цветами материального
   набора — #4CAF50, #f44336, #ff9800, #2196F3, — то есть палитрой чужой
   библиотеки, которую смена мира 28 августа не тронула. Смысл у них тот
   же, что у кнопок (§36 ТЗ): успех, опасность, внимание, подсказка, —
   поэтому цвет берётся из смыслового набора словаря.

   Переменная не подставляется в презентационный атрибут SVG, значит
   круг красится `currentColor`, а штрих внутри — правилом. На золоте
   штрих тёмный: белая галочка на жёлтом не читается (§21).

   Разметку значков собирает `mvp/views/notify.view.js`.
   -------------------------------------------------------------------------- */
.notify-glyph circle { fill: currentColor; }
.notify-glyph path   { stroke: var(--ui-ivory-light); }

.notify-glyph.is-success { color: var(--ui-green); }
.notify-glyph.is-error   { color: var(--ui-red); }
.notify-glyph.is-warning { color: var(--ui-gold); }
.notify-glyph.is-info    { color: var(--ui-blue); }

.notify-glyph.is-warning path { stroke: var(--ui-text-dark); }

/* Крестик закрытия наследовал цвет от кнопки, а стоял числом. */
.notify-cross path { stroke: currentColor; opacity: .7; }

/* --------------------------------------------------------------------------
   25. Переключатель (§62, §70 ТЗ)

   Три тумблера настроек — звук, вибрация, уведомления — единственный
   двухпозиционный контрол игры, и материал у него был свой: жёлоб двумя
   числами (#181043 → #0d0924), шайба тремя запасками прежнего, тёплого
   мира (`var(--ui-ivory-light, #fff8e2)` и родня). Запаска переживает
   смену палитры молча — ровно то, чего в проекте быть не должно.

   Форма остаётся прежней и правильной: утопленный жёлоб, объёмная шайба
   с направленной нижней гранью. Включённое состояние читается дважды —
   зелёным жёлобом и положением шайбы, — потому что цветом одним состояние
   передавать нельзя. Размеры и ход шайбы держит `common.css`.
   -------------------------------------------------------------------------- */
.trumpamole__toggle {
    border-radius: var(--ui-radius-pill);
    background:
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-bg-dark) 0%, var(--ui-bg-deep) 100%);
    border: var(--ui-border) solid rgba(0, 0, 0, 0.5);
    box-shadow: var(--ui-inner-well);
}

.trumpamole__toggle.on {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg, var(--ui-green-light) 0%, var(--ui-green-deep) 100%);
    border-color: rgba(0, 0, 0, 0.5);
}

.trumpamole__toggle i {
    border-radius: 50%;
    background: linear-gradient(180deg, var(--ui-ivory-light) 0%, var(--ui-ivory-dark) 100%);
    box-shadow: 0 2px 0 var(--ui-ivory-deep), var(--ui-shadow-xs);
}

/* --------------------------------------------------------------------------
   26. Пунктирная строка ожидания (§56, §58 ТЗ)

   Две строки игры говорят «пока ничего не произошло, но произойдёт»:
   «Заявка отправлена» в списке кланов и свежий призыв на облаву в штабе.
   Пунктир здесь не украшение, а смысл: у сплошной кромки ровно то же
   начертание, что у карточки рядом, и строка читалась готовым
   результатом, а не ожиданием.

   Обе стояли в `clans.css` числами прежнего мира: золото
   `rgba(229, 191, 100, .4)` и `rgba(245, 196, 107, .5)` с заливкой в
   8 % — два разных золота на один приём. Материал общий, разделу
   остаётся геометрия.
   -------------------------------------------------------------------------- */
.tam-clan__pending,
.tam-hq__summon,
/* Третья такая строка нашлась в окне арены: «друзей пока нет, позови».
   Она стояла в списке утопленных поверхностей §19 и читалась готовым
   ответом, хотя это приглашение к действию. */
.trumpamole__modal-pvp-empty-state {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg,
            color-mix(in srgb, var(--ui-gold) 10%, transparent) 0%,
            color-mix(in srgb, var(--ui-gold) 4%, transparent) 100%);
    border: var(--ui-border) dashed
            color-mix(in srgb, var(--ui-gold) 46%, transparent);
    border-radius: var(--ui-radius-md);
    color: var(--ui-gold-light);
}

/* --------------------------------------------------------------------------
   27. ИГРОВАЯ КЛАВИАТУРА (§51, §62 ТЗ)

   Клавиатуру в мини-приложении игра рисует сама (`modules/ui/keyboard.js`):
   системная ломает экран, а её жест закрытия сворачивает приложение.
   Значит, это такой же экран игры, как любой другой, — и выглядеть он
   обязан игровым.

   Материал у неё был описан псевдонимами отменённого тёплого набора
   (`--brown-0..3`, `--gold-2`, `--gold-4`) и жил на одной волосяной
   рамке в 1px: клавиша была плоским прямоугольником без грани и без
   фактуры, то есть ровно тем «flat web design», который запрещает §62.
   Разделу остаются размеры и раскладка, материал — здесь.
   -------------------------------------------------------------------------- */

.tam-kbd {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-dark) 0%, var(--ui-bg-deep) 100%);
    border-top: var(--ui-border-thick) solid var(--ui-panel-edge);
    box-shadow: 0 -18px 42px rgba(0, 0, 0, 0.55);
}

/* Клавиша — маленькая доска с направленной нижней гранью: палец должен
   видеть, куда он попадёт, ещё до нажатия. */
.tam-kbd__key {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood-light) 0%, var(--ui-wood) 100%);
    border: var(--ui-border) solid var(--ui-panel-edge);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.5), var(--ui-inner-top);
    color: var(--ui-text-main);
}

/* Нажатая клавиша садится на грань и уходит в тень — так подтверждение
   попадания видно даже под пальцем, который закрывает саму клавишу. */
.tam-kbd__key:active {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-wood) 0%, var(--ui-wood-dark) 100%);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), var(--ui-inner-well);
}

/*
 * Включённый регистр — доска с золотым кантом, а не золотая клавиша.
 *
 * Золотом на клавиатуре светится ровно одно — «ГОТОВО», главное
 * действие (§59). Регистр это состояние соседней клавиши, и метится оно
 * кромкой и цветом буквы, как любое состояние в игре.
 */
.tam-kbd__key--on {
    background:
        var(--ui-dirt-wide),
        var(--ui-dirt),
        linear-gradient(180deg, var(--ui-panel-light) 0%, var(--ui-wood-light) 100%);
    border-color: var(--ui-gold);
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.5), var(--ui-inner-top),
                0 0 10px color-mix(in srgb, var(--ui-gold) 45%, transparent);
    color: var(--ui-gold-light);
}

/*
 * «ГОТОВО» — золотая кнопка ввода.
 *
 * Подпись здесь тёмная и без обводки: кегль служебного ряда 12px, а на
 * таком кегле контур съедает просвет буквы (§21). Держала она свой цвет
 * числом `#0e0928` и лиловую рамку `rgba(150,120,255,.5)` — единственную
 * такую в игре.
 */
.tam-kbd__key--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-inner-top);
    color: var(--ui-text-dark);
}

.tam-kbd__key--gold:active {
    background:
        var(--ui-dirt-lite),
        linear-gradient(180deg,
        var(--ui-gold-btn-top) 0%,
        var(--ui-gold-btn-low) 100%);
    box-shadow: 0 1px 0 var(--ui-gold-btn-deep), var(--ui-inner-well);
}

/* ==========================================================================
   28. ГЕРОЙ В ШАПКЕ РАЗДЕЛА (§108 ТЗ: character presentation)

   На обоих кадрах референса персонаж стоит почти на каждом экране: он и
   объясняет, куда игрок попал, и держит верх страницы. В игре так было
   не везде — летопись и хранилище открывались вывеской, строкой текста
   и парой кнопок, то есть выглядели документом, а не местом.

   Ряд собран из фигуры и текста, а НЕ из фигуры поверх ленты: вывеска
   раздела занимает всю ширину, и персонаж, поставленный сбоку от неё,
   либо сжимал бы её до многоточия, либо накрывал бы подпись. Здесь он
   стоит ниже вывески и занимает пустое поле слева от описания — то
   самое, из-за которого шапка казалась незаполненной.

   Фигура декоративная: `aria-hidden` в разметке, касания не берёт.
   ========================================================================== */

.tam-hero-figure {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--ui-space-3);
    width: 100%;
    margin-top: var(--ui-space-2);
    text-align: left;
}

/*
 * Тёмный кант и падающая тень вместо обводки: фигура вырезана по
 * силуэту и стоит на фотографии ленты, а не на ровном тоне. Без канта
 * тёмная шерсть сливалась с полками архива.
 */
.tam-hero-figure__art {
    display: block;
    width: 106px;
    height: auto;
    pointer-events: none;
    filter: drop-shadow(var(--ui-art-shadow-md))
            drop-shadow(0 0 2px rgba(0, 0, 0, 0.85));
    transform-origin: bottom center;
    animation: tam-hero-idle 4.4s ease-in-out infinite;
}

.tam-hero-figure__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--ui-space-2);
    min-width: 0;
    text-align: left;
}

/* Подпись раздела в ряду с персонажем выключена влево: по центру она
   рвалась на строки разной длины рядом с фигурой. */
.tam-hero-figure__body .trumpamole__page-sub {
    text-align: left;
}

/* Кнопки под описанием стоят в строку и переносятся: в хранилище их две
   («Коллекция», «Магазин»), и на 320px они не помещаются рядом. */
.tam-hero-figure__links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ui-space-2);
    width: 100%;
}

/* Дыхание фигуры (§45 «character idle»): подъём на три пикселя, без
   поворота и без масштаба — иначе тень отрывается от подписи. */
@keyframes tam-hero-idle {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
}

/* На узком экране фигуре остаётся меньше места, иначе описанию не
   хватает ширины на два слова в строке. */
@media (max-width: 360px) {
    .tam-hero-figure {
        gap: var(--ui-space-2);
    }
    .tam-hero-figure__art { width: 86px; }
}

@media (prefers-reduced-motion: reduce) {
    .tam-hero-figure__art { animation: none; }
}

/* ==========================================================================
   29. НИЗКИЙ ЭКРАН (§108 ТЗ: шапка не съедает содержимое)

   На телефоне высотой 640 страница раздела получает 508px, и шапка
   выедала из них от половины до всего: коллекция — 464px (содержимого
   на первом экране не видно вовсе), арена — 340px, хроника — 323px,
   сезон — 285px, лаборатория — 273px. Игрок открывает «Коллекцию» и
   видит вывеску, две полосы, крота и четыре ссылки — то есть оглавление
   вместо коллекции.

   Здесь снимается воздух, а не части раздела: фигура декоративная и
   уменьшается, ряд ссылок в соседние разделы переносится в один
   прокручиваемый ряд по образцу вкладок §11. Высота нажимаемого
   (`--ui-tap-min`) не трогается ни в одном правиле — на низком экране
   палец не становится тоньше.

   Порог 700px выбран по парку: 640 — низ ряда, 720 и выше — обычные
   телефоны, где ленте ничего ужимать не надо.
   ========================================================================== */

@media (max-height: 700px) {
    .tam-hero-figure {
        margin-top: 0;
        gap: var(--ui-space-2);
    }

    .tam-hero-figure__body {
        gap: var(--ui-space-1);
    }

    /* 106px → 76px: фигура остаётся узнаваемой (голова у канона крупная
       и на трети размера читается), но отдаёт разделу тридцать с лишним
       пикселей высоты. */
    .tam-hero-figure__art {
        width: 76px;
    }

    /*
     * Четыре ссылки коллекции при `flex: 1 1 40%` встают в две строки и
     * стоят 96px. Вбок они прокручиваются так же, как ряд вкладок над
     * содержимым, — жест в игре уже знакомый (вкладки, стена трофеев), а
     * высота ряда падает вдвое.
     */
    /*
     * Прокрутка вбок работает только в полосе известной ширины. Лента
     * собирает содержимое по центру (`justify-items: center`, §4 выше),
     * поэтому столбец берёт max-content вложенного — сумму всех четырёх
     * кнопок, 485px при экране 360px: ряд не прокручивался, а растягивал
     * ленту, и вывеска с плитками уезжала за левый край.
     */
    .tam-col__hero .trumpamole__title-block {
        width: 100%;
    }

    /* Хранилища здесь нет: его ссылок две, они и так стоят в одну
       строку, а в прокручиваемом ряду «МАГАЗИН» уезжал за край. */
    .tam-col__links {
        flex-wrap: nowrap;
        /* Без явного нуля ряд берёт автоминимум флекс-элемента — ширину
           всех четырёх кнопок разом (423px при 360px экрана): он не
           прокручивался, а растягивал ленту, и вывеска с плитками
           уезжала за левый край. */
        min-width: 0;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .tam-col__links::-webkit-scrollbar { display: none; }

    /* Кнопка держит свою ширину: `1 1 40%` в ряду без переноса сжал бы
       все четыре до многоточия вместо прокрутки. */
    .tam-col__links > * {
        flex: 1 0 auto;
    }
}

/* ==========================================================================
   30. ЗАКЛЁПКИ И ГРАНЬ НА ПАНЕЛИ ВТОРОГО ПЛАНА (§108 ТЗ: decorative bolts,
       bevel, panel depth)

   Панель второго плана — это доска, которая держит на себе ДРУГИЕ доски:
   штаб клана, глава сезона, состав призов колеса, имущество башни, защита
   арены, стойка гардероба. На кадрах `grok/8.png` такая панель («POWER
   UPS», «MOLE SKINS», «BRAWLERS») подписана шапкой, шапка отделена от тела
   гранью, а в углах стоят светлые ромбы-заклёпки. У нас у всех шести был
   ровно корпус §6 и больше ничего: панель второго плана ничем не
   отличалась от карточки, которая внутри неё лежит.

   Заклёпка идёт `::after`, а не слоем фона: у панелей §6 материал задан
   сокращённым `background`, и дописать в него две плитки означало бы
   повторить градиент корпуса вторым местом. У вывески §2 всё наоборот —
   там псевдоэлементы погашены намеренно, и заклёпка легла слоем фона.

   Список именной: заклёпки НЕ получают панели, у которых верх занят
   рисунком (сцена кабинета, набор магазина, лента раздела) — ромб лёг бы
   поверх картинки. Обычная карточка их тоже не получает: на кадре
   заклёпка стоит у группы, а если её выдать каждой плитке ряда, она
   перестанет что-либо значить — та же логика, что у золотой кнопки §9.1.1.
   ========================================================================== */

.tam-arena__defense,
.tam-col__showcase,
.tam-cos__stage,
.tam-hq__perks,
.tam-hq__project,
.tam-hq__wall,
.tam-raid,
.tam-season__chapter,
.trumpamole__fortune-oddsBox,
.trumpamole__profile-tower,
.trumpamole__tasks-important-wrap {
    /*
     * Своя рамка нужна псевдоэлементу. Абсолютные потомки всех шести
     * панелей проверены обходом: каждый меряется от положенного предка
     * ВНУТРИ панели (`.tam-cos__dummy`, `.tam-hq__trophy`,
     * `.tam-season__cell`), поэтому ничего не сдвинется.
     */
    position: relative;
}

.tam-arena__defense::after,
.tam-col__showcase::after,
.tam-cos__stage::after,
.tam-hq__perks::after,
.tam-hq__project::after,
.tam-hq__wall::after,
.tam-raid::after,
.tam-season__chapter::after,
.trumpamole__fortune-oddsBox::after,
.trumpamole__profile-tower::after,
.trumpamole__tasks-important-wrap::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 22px;
    /* Полоса лежит поверх содержимого: заклёпка живёт в поле панели, куда
       содержимое не заходит, но нажатия сквозь неё проходить обязаны. */
    pointer-events: none;
    /*
     * Ромб сидит В ПОЛЕ панели, между кромкой и содержимым.
     *
     * Первый заход поставил его на 10px от края в 16px — ровно как на
     * кадре, где надпись группы стоит по центру и углы свободны. У нас
     * шапка прижата влево, а справа в ней стоит значение («1/4», «2 %»),
     * и обе заклёпки легли на текст. Поле панели 12px, поэтому ромб
     * ужат до 11px и отодвинут к самой кромке: он занимает угол, куда
     * содержимое не заходит ни в одной из одиннадцати панелей.
     */
    background:
        var(--ui-bolt) left 4px top 4px / 11px 11px no-repeat,
        var(--ui-bolt) right 4px top 4px / 11px 11px no-repeat;
}

/*
 * 30.1. ГРАНЬ ПОД ШАПКОЙ ГРУППЫ
 *
 * На кадре шапка группы отделена от тела ступенькой: тёмная линия и
 * светлый блик под ней. У нас подпись просто висела над содержимым с
 * отступом в 10px, и панель читалась списком, а не полкой с надписью.
 *
 * Грань — не рамка: она из двух линий, и вторую даёт тень. Отступ снизу
 * добавлен к прежнему `margin-bottom` шапки, а не заменяет его — иначе
 * надпись сядет на линию.
 */
.tam-hq__perks > .tam-hq__title,
.tam-hq__project-head,
.tam-hq__wall-head,
.tam-season__chapter-head,
.trumpamole__fortune-oddsHead,
.trumpamole__profile-tower-head {
    padding-bottom: var(--ui-space-2);
    border-bottom: var(--ui-border) solid color-mix(in srgb, var(--ui-panel-edge) 80%, transparent);
    box-shadow: 0 1px 0 color-mix(in srgb, var(--ui-purple-glow) 20%, transparent);
}
