/* ============================================================
   GLASS MODAL — дизайн-система модалок (.gm)

   Вынесена из index.css без единой правки: порядок правил сохранён,
   в бандле /styles/app.css файл стоит СРАЗУ после index.css, поэтому
   каскад относительно остальных стилей не изменился.

   Смысл выноса: страница гачи (app/gatcha.ejs) — отдельный документ,
   она не грузит app.css, но модалки ей нужны. Тот же приём уже применён
   к usermenu-head.css.

   Спецификация блоков: docs/GLASS_MODAL_DESIGN_SYSTEM.md
   ============================================================ */



/* ═══════════════════════════════════════════════════════════════════════
   GLASS-MODAL — универсальная Apple-style модалка (auth, edit-profile, ...).
   BEM префикс .gm__. Дочерние модули можно комбинировать: card + form +
   field + btn + msg + и т.д.
   ═══════════════════════════════════════════════════════════════════════ */

.gm {
    position: fixed;
    inset: 0;
    width: 100vw;
    max-width: 100vw;
    /* Не 100vh: тот считает убирающуюся шапку браузера убранной, и во встроенном
       браузере (или в окне, открытом target=_blank из PWA) низ модалки вместе с
       кнопками уезжает за пределы видимой области — а прокрутки у fixed-диалога
       нет. --wc-vvh приходит из visualViewport (см. modules/footer.ejs),
       dvh — фолбэк, если JS ещё не отработал. */
    height: var(--wc-vvh, 100dvh);
    max-height: var(--wc-vvh, 100dvh);
    padding: 0;
    margin: 0;
    border: none;
    background: transparent;
    /* Открывается через .show() (не top layer — чтобы challenge reCAPTCHA был виден),
       поэтому z-index должен перебивать header (1001) и оверлеи (до 10050),
       но оставаться ниже тостов уведомлений (99999) и iframe капчи (~2e9). */
    z-index: 20000;
    overflow: hidden;
    /* Центрирование карточки по горизонтали и ВЕРТИКАЛИ */
    display: flex;
    align-items: center;
    justify-content: center;
}
.gm::backdrop { display: none; }
.gm:not([open]) { display: none; }
.gm:focus, .gm:focus-visible { outline: none; }
/* Карточка получает фокус при открытии (см. openModal в assets/index.ejs) —
   это программный фокус на tabindex="-1", кольцо на нём не нужно. */
.gm__card:focus, .gm__card:focus-visible,
.modal-frame:focus, .modal-frame:focus-visible { outline: none; }

/* Убираем automatic focus-ring при .showModal() (браузер сам фокусит первый
   focusable элемент). Оставляем outline только для keyboard-навигации
   через :focus-visible. */
.gm *:focus:not(:focus-visible) { outline: none; }
.gm__iconbtn:focus-visible,
.gm__tabs-item:focus-visible,
.gm__btn:focus-visible,
.gm__sidebar-item:focus-visible,
.gm__field__action:focus-visible {
    outline: 2px solid rgba(127, 45, 232, 0.55);
    outline-offset: 2px;
}
#dark .gm__iconbtn:focus-visible,
#dark .gm__tabs-item:focus-visible,
#dark .gm__btn:focus-visible,
#dark .gm__sidebar-item:focus-visible,
#dark .gm__field__action:focus-visible {
    outline-color: rgba(179, 129, 255, 0.65);
}

.gm__backdrop {
    position: absolute;
    inset: 0;
    /* Ровно та же подложка, что у мобильной шапки (#mobile-header .backdrop):
       одна глубина размытия и один тон на весь сайт. Прежние blur(60px) и 89%
       черноты давали не «стекло», а глухую заливку — страницы под модалкой
       не было видно вовсе. */
    background: rgba(13, 12, 14, 0.85);
    -webkit-backdrop-filter: blur(15px);
    backdrop-filter: blur(15px);
    animation: gm-fade-in .32s cubic-bezier(.16, 1, .3, 1);
    z-index: 1;
}
@keyframes gm-fade-in { from { opacity: 0; } to { opacity: 1; } }
/* В светлой теме тёмная подложка просвечивала сквозь карточку (её фон 86%
   непрозрачности) и красила «белый лист» в грязно-серый. Здесь, как и в
   мобильной шапке, подложка светлая и холодная — карточка на ней читается
   именно листом. Размытие общее, из правила выше. */
body#light .gm__backdrop {
    background: rgba(166, 177, 199, 0.73);
}
body#light .gm__card {
    background: rgba(255, 255, 255, 0.93);
    box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.28),
                0 12px 24px -12px rgba(0, 0, 0, 0.14);
}

.gm__card {
    position: relative;
    z-index: 2;
    width: min(100% - 32px, 380px);
    margin: 20px 16px;
    max-height: calc(var(--wc-vvh, 100dvh) - 40px);
    overflow-y: auto;
    padding: 12px 24px 24px;
    box-sizing: border-box;
    background: rgba(252, 252, 253, 0.86);
    -webkit-backdrop-filter: blur(50px) saturate(180%);
    backdrop-filter: blur(50px) saturate(180%);
    border: 0.5px solid rgba(0, 0, 0, 0.08);
    border-radius: 22px;
    box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.35),
                0 12px 24px -12px rgba(0, 0, 0, 0.18);
    color: rgb(28, 28, 30);
    -webkit-font-smoothing: antialiased;
    animation: gm-card-in .38s cubic-bezier(.16, 1, .3, 1);
    scrollbar-width: thin;
}
.gm__card::-webkit-scrollbar { width: 8px; }
.gm__card::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }
#dark .gm__card::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); }
.gm__card--slim { max-width: 340px; }
.gm__card--wide { max-width: 440px; }
.gm__card--xwide { max-width: 640px; }
/* .gm__card--xwide САМ по себе не расширяет модалку: у .gm__card задан явный
   width: min(100% - 32px, 380px), а max-width его не перебивает (max-width
   капает только когда он МЕНЬШЕ width — см. комментарий у .gm__card--subscription
   ниже, то же самое ограничение). Портрету текст нужен шире — задаём width сами. */
.gm__card--portrait { width: min(100% - 32px, 640px); }
/* Редактор страницы профиля: в строке помещаются название блока, кнопка
   «Настроить» и ручка перетаскивания — на 380px они наезжают друг на друга. */
.gm__card--profile-layout { width: min(100% - 32px, 460px); }
/* «Где купить набор»: витрина товаров в две колонки (обложка + продавец +
   кнопка покупки). На 380px колонка выходит уже обложки карточки товара. */
.gm__card--shop { width: min(100% - 32px, 560px); }
/* Отзывы маркетплейса: длинные абзацы и ряды фотографий 64px. */
.gm__card--reviews { width: min(100% - 32px, 520px); }
@keyframes gm-card-in {
    from { opacity: 0; transform: translateY(24px) scale(.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

#dark .gm__card {
    background: rgba(30, 30, 34, 0.82);
    border-color: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.95);
    box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6),
                0 12px 24px -12px rgba(0, 0, 0, 0.4);
}

/* ═══════════════════════════════════════════════════════════════════════
   ВЕРХНЯЯ АУРА (.gm__card--aura + .gm__aura) — цветное пятно в шапке окна

   Что это. Размытая мозаика из цветных клеток под шапкой модалки: окно
   получает «настроение» (редкость карточки, тир подписки, статус сделки),
   не тратя на это ни строчки текста.

   ПОЧЕМУ НЕ ГРАДИЕНТ. Линейный или радиальный градиент одного тона на такой
   площади читается дёшево: глаз сразу видит математику — ровный переход и
   полосы бандинга. Живым пятно делают три вещи, и все три обязательны:
     1) несколько СОСЕДНИХ, но разных цветов (--gm-aura-1…4);
     2) фигуры, а не переход: клетки под сильным размытием;
     3) зерно поверх — оно съедает бандинг (см. ::after).

   ПОЧЕМУ ТРИ СЛОЯ, А НЕ ОДИН. Узор должен ЖИТЬ. Один слой, качающийся
   целиком, этого не даёт: он читается как съехавшая картинка. Три слоя с
   разными периодами и траекториями расходятся и сходятся между собой —
   размытая картинка каждую секунду другая, хотя ничего быстрее 24 секунд
   на цикл не движется.

   ЦЕНА КАДРА. Анимируется ТОЛЬКО transform. У каждого слоя свой filter:
   blur(), поэтому слой растрируется один раз и дальше ездит на композиторе;
   ни размытие, ни цвета в кадре не пересчитываются. Анимировать вместо
   этого background-position (или двигать детей ВНУТРИ одного размытого
   контейнера) нельзя: тогда blur считается заново каждый кадр — на
   телефоне это верных 60 пересчётов в секунду.

   Подключение — два шага: класс .gm__card--aura на .gm__card и первым
   ребёнком карточки контейнер:
       <div class="gm__aura" aria-hidden="true"><i></i><i></i><i></i></div>
   Палитра задаётся переменными (--gm-aura-1…4), сила/высота — --gm-aura-k
   и --gm-aura-h. Готовые палитры ступеней ОР — ниже, у блока .gm__rp.
   ═══════════════════════════════════════════════════════════════════════ */
.gm__card--aura {
    /* по умолчанию — брендовая семья; модалка переопределяет под себя */
    --gm-aura-1: #6235e8;
    --gm-aura-2: #8b5cf6;
    --gm-aura-3: #4f7bff;
    --gm-aura-4: #b06bff;
    --gm-aura-k: .2;     /* сила: непрозрачность всего пятна */
    --gm-aura-bl: 34px;  /* базовое размытие */
    --gm-aura-h: 380px;  /* высота области */
    --gm-aura-g: .09;    /* зерно */
    --gm-aura-t: 16s;    /* базовый период дрейфа */
    /* Итоговая непрозрачность пятна. Отдельной переменной, потому что её
       использует и правило, и @keyframes появления: тёмная тема добавляет
       полуторный запас, и без общего значения анимация гасила бы его. */
    --gm-aura-op: var(--gm-aura-k);
}
#dark .gm__card--aura { --gm-aura-op: calc(var(--gm-aura-k) * 1.5); }

/* Контейнер обрезает слои (overflow: hidden), и это не украшение, а два
   исправленных бага сразу:
     — СКВОЗЯЩИЙ УГОЛ. Слой, заканчивающийся ровно по краю карточки, съедает
       blur'ом собственную альфу у кромки, и в углу проступает фон карточки.
       Слои внутри вылезают за контейнер на треть — размытая кромка остаётся
       за кадром.
     — ГОРИЗОНТАЛЬНАЯ ПРОКРУТКА. У .gm__card стоит overflow-y: auto, значит
       по горизонтали он тоже auto: любой потомок, вылезающий ВПРАВО (или
       повёрнутый transform'ом), растягивает область прокрутки и внизу
       карточки появляется полоса. overflow: hidden на контейнере
       останавливает это на себе. */
.gm__card--aura > .gm__aura {
    position: absolute;
    top: 0; left: 0; right: 0;
    height: var(--gm-aura-h);
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
    opacity: var(--gm-aura-op);
    border-radius: 22px 22px 0 0;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 96%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 96%);
    /* Перерисовка ограничена своим прямоугольником: три размытых слоя не
       должны тянуть за собой перерасчёт остального окна. */
    contain: paint;
    /* НАЛИВАЕТСЯ ПОСЛЕ ТОГО, КАК ОКНО ДОЕХАЛО, и это не украшение.
       Карточка появляется анимацией gm-card-in — translate + scale. Размытие
       зависит от масштаба растрирования, поэтому во время scale браузер
       пересчитывает blur КАЖДЫЙ кадр, на трёх слоях сразу: открытие окна
       дёргалось и заметно тормозило. Задержка равна длительности gm-card-in,
       так что к моменту появления пятна масштаб уже единичный и слои
       растрируются один раз. */
    animation: gm-aura-in .3s ease .38s both;
}
@keyframes gm-aura-in {
    from { opacity: 0 }
    to   { opacity: var(--gm-aura-op) }
}

.gm__aura > i {
    position: absolute;
    top: -34%; left: -34%; right: -34%; bottom: -34%;
    display: block;
    background-repeat: no-repeat;
    will-change: transform;
}
/* РОЛИ СЛОЁВ РАЗВЕДЕНЫ ПО ГЛУБИНЕ, и это не вкусовщина: пока все три слоя
   брали цвета вперемешку, они под размытием давали почти одинаковую кашу, и
   движение переставало читаться — картинка ехала, а глаз этого не замечал.
   Теперь низ тёмный (--gm-aura-1/3), верх светлый (--gm-aura-4/2): светлые
   пятна ездят по тёмной основе, и перепад виден.

   Слой 1 — глубокая основа: четыре крупных поля, самое мягкое размытие,
   самый медленный ход. */
.gm__aura > i:nth-child(1) {
    background-size: 52% 54%;
    background-image:
        linear-gradient(var(--gm-aura-1), var(--gm-aura-1)),
        linear-gradient(var(--gm-aura-3), var(--gm-aura-3)),
        linear-gradient(var(--gm-aura-3), var(--gm-aura-3)),
        linear-gradient(var(--gm-aura-1), var(--gm-aura-1));
    background-position: 0% 0%, 100% 0%, 0% 100%, 100% 100%;
    filter: blur(calc(var(--gm-aura-bl) * 1.25));
    animation: gm-aura-1 calc(var(--gm-aura-t) * 1.45) ease-in-out infinite;
}
/* Слой 2 — средние плитки вразнобой и С ПРОПУСКАМИ: сквозь дырки видно
   первый слой, и на стыке двух движущихся слоёв рождается сам узор */
.gm__aura > i:nth-child(2) {
    background-size: 34% 30%;
    background-image:
        linear-gradient(var(--gm-aura-2), var(--gm-aura-2)),
        linear-gradient(var(--gm-aura-4), var(--gm-aura-4)),
        linear-gradient(var(--gm-aura-2), var(--gm-aura-2)),
        linear-gradient(var(--gm-aura-1), var(--gm-aura-1)),
        linear-gradient(var(--gm-aura-4), var(--gm-aura-4));
    background-position: 8% 12%, 74% 4%, 40% 52%, 92% 62%, 18% 88%;
    filter: blur(var(--gm-aura-bl));
    animation: gm-aura-2 var(--gm-aura-t) ease-in-out infinite;
}
/* Слой 3 — светлые акценты-кругляши: самый резкий и самый быстрый, именно он
   даёт ощущение, что пятно дышит */
.gm__aura > i:nth-child(3) {
    background-size: 26% 26%;
    background-image:
        radial-gradient(circle at 50% 50%, var(--gm-aura-4) 0%, transparent 68%),
        radial-gradient(circle at 50% 50%, var(--gm-aura-2) 0%, transparent 68%),
        radial-gradient(circle at 50% 50%, var(--gm-aura-4) 0%, transparent 68%),
        radial-gradient(circle at 50% 50%, var(--gm-aura-2) 0%, transparent 68%);
    background-position: 22% 26%, 88% 34%, 56% 78%, 4% 66%;
    filter: blur(calc(var(--gm-aura-bl) * 0.8));
    opacity: .9;
    animation: gm-aura-3 calc(var(--gm-aura-t) * 0.72) ease-in-out infinite;
}
/* Амплитуды разные и НЕ КРАТНЫЕ: у слоёв не должно быть общего такта, иначе
   через пару циклов они сходятся в исходную картинку и движение застывает.
   Проценты считаются от размера слоя, а он на треть больше контейнера с
   каждой стороны — 13% это примерно полклетки, край при этом не оголяется. */
@keyframes gm-aura-1 {
    0%   { transform: translate3d(-7%, -3%, 0) rotate(-2deg) }
    50%  { transform: translate3d(8%, 5%, 0) rotate(7deg) }
    100% { transform: translate3d(-7%, -3%, 0) rotate(-2deg) }
}
@keyframes gm-aura-2 {
    0%   { transform: translate3d(11%, 4%, 0) rotate(3deg) }
    50%  { transform: translate3d(-12%, -7%, 0) rotate(-6deg) }
    100% { transform: translate3d(11%, 4%, 0) rotate(3deg) }
}
@keyframes gm-aura-3 {
    0%   { transform: translate3d(-6%, 9%, 0) }
    33%  { transform: translate3d(13%, -6%, 0) }
    66%  { transform: translate3d(-11%, -10%, 0) }
    100% { transform: translate3d(-6%, 9%, 0) }
}
@media (prefers-reduced-motion: reduce) {
    .gm__aura > i { animation: none !important; }
}

/* Волосяная кромка по верхнему краю — намёк на источник света, тот же приём,
   что у .gm__sub-tier__plate-bar. Делится на силу пятна: контейнер гасит
   всё своим opacity, а кромка должна остаться видимой и при --gm-aura-k .14. */
.gm__card--aura > .gm__aura::before {
    content: '';
    position: absolute;
    top: 0; left: 16px; right: 16px;
    height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--gm-aura-2) 70%, transparent), transparent);
    opacity: clamp(0, calc(.5 / max(var(--gm-aura-k), .12)), 1);
}
/* Зерно — БЕЗ размытия, поэтому отдельным слоем, а не ещё одним <i>. Без него
   большое мягкое пятно идёт полосами: 8-битного канала не хватает на плавный
   переход такой площади. Делится на силу по той же причине, что и кромка. */
.gm__card--aura > .gm__aura::after {
    content: '';
    position: absolute;
    inset: 0;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.92' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / 120px 120px repeat;
    opacity: clamp(0, calc(var(--gm-aura-g) / max(var(--gm-aura-k), .12)), 1);
    mix-blend-mode: overlay;
}
/* Всё остальное содержимое карточки — поверх пятна. Контейнер позиционирован,
   поэтому без этого он перекрыл бы обычный поток. */
.gm__card--aura > *:not(.gm__aura) { position: relative; z-index: 1; }
@media (max-width: 540px) {
    /* Хват шторки — блок в потоке (не absolute), и без подъёма он оказался бы
       ПОД пятном: полоска проступала бы сквозь цвет приглушённой. */
    dialog.gm .gm__card--aura::before { position: relative; z-index: 1; }
}

.gm__topbar {
    display: flex;
    align-items: center;
    height: 40px;
    margin: 0 -8px 4px;
}
.gm__topbar-spacer { flex: 1; }

/* Nav-bar-style заголовок ВНУТРИ topbar (как заголовок iOS-шторки) — для
   насыщенных контентом модалок (списки/секции), где отдельный крупный
   .gm__title + .gm__subtitle центрированной колонкой смотрится "ёлочкой".
   Абсолютное позиционирование держит текст по центру бара независимо от
   ширины левого/правого контента. */
.gm__topbar--titled { position: relative; }
.gm__topbar-title {
    padding-left: 10px;
    font-size: 16px;
    font-weight: 600;
}
#dark .gm__topbar-title { color: var(--ink-on-dark); }
.gm__iconbtn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: none;
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.75);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s ease, color .15s ease, transform .1s ease;
    padding: 0;
    -webkit-appearance: none;
    appearance: none;
    flex-shrink: 0;
}
.gm__iconbtn:hover { background: rgba(120, 120, 128, 0.22); color: rgb(28, 28, 30); }
.gm__iconbtn:active { transform: scale(.94); }
#dark .gm__iconbtn { background: rgba(255, 255, 255, 0.1); color: rgba(255, 255, 255, 0.7); }
#dark .gm__iconbtn:hover { background: rgba(255, 255, 255, 0.16); color: var(--ink-on-dark); }

.gm__view { display: flex; flex-direction: column; gap: 14px; }

.gm__title {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", system-ui, sans-serif;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.5px;
    line-height: 1.15;
    margin: 4px 0 0;
    text-align: center;
    color: inherit;
}
.gm__subtitle {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    font-size: 14px;
    color: rgba(60, 60, 67, 0.72);
    text-align: center;
    margin: 0 0 8px;
    line-height: 1.4;
}
.gm__subtitle--ok { color: var(--temp-ok-vivid-b); }
#dark .gm__subtitle { color: rgba(235, 235, 245, 0.62); }

.gm__form { display: flex; flex-direction: column; gap: 10px; }

.gm__field { position: relative; }
.gm__field input,
.gm__field select,
.gm__field textarea {
    width: 100%;
    box-sizing: border-box;
    height: 52px;
    padding: 20px 14px 4px;
    border: 0.5px solid rgba(0, 0, 0, 0.1);
    border-radius: 12px;
    background: rgba(120, 120, 128, 0.08);
    color: rgb(28, 28, 30);
    font-size: 16px;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    outline: none;
    transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
    -webkit-appearance: none;
    appearance: none;
    -webkit-text-fill-color: rgb(28, 28, 30);
}
.gm__field input:focus,
.gm__field select:focus,
.gm__field textarea:focus {
    border-color: rgba(127, 45, 232, 0.5);
    background: rgba(120, 120, 128, 0.05);
    box-shadow: 0 0 0 3.5px rgba(127, 45, 232, 0.14);
}
/* Многострочный вариант того же поля с плавающей подписью: высота по строкам,
   тянуть можно только по вертикали (по горизонтали ломало бы сетку модалки). */
.gm__field textarea {
    height: auto;
    min-height: 86px;
    padding-top: 24px;
    line-height: 1.4;
    resize: vertical;
}
.gm__field label {
    position: absolute;
    top: 16px;
    left: 15px;
    right: 15px;
    font-size: 16px;
    color: rgba(60, 60, 67, 0.6);
    pointer-events: none;
    transition: transform .18s ease, color .18s ease;
    transform-origin: 0 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Если у поля справа inline-кнопка — оставляем место под неё */
.gm__field--with-action label { right: 120px; }
.gm__field input:focus + label,
.gm__field input:not(:placeholder-shown) + label,
.gm__field textarea:focus + label,
.gm__field textarea:not(:placeholder-shown) + label,
.gm__field select:focus + label,
.gm__field select:valid + label {
    transform: translateY(-10px) scale(0.72);
    color: rgba(60, 60, 67, 0.7);
}
.gm__field input:focus + label,
.gm__field textarea:focus + label,
.gm__field select:focus + label {
    color: rgba(127, 45, 232, 0.85);
}
/* Native <option> в dropdown иногда рендерится white-on-white — фиксим явно. */
.gm__field select option {
    color: rgb(28, 28, 30);
    background: var(--ink-on-dark);
}
#dark .gm__field select option {
    color: rgba(255, 255, 255, 0.95);
    background: rgb(45, 45, 50);
}

/* Select: стрелка через ::after — надёжнее и без data-URI. */
.gm__field--select { position: relative; }
.gm__field--select select { padding-right: 34px; }
.gm__field--select::after {
    content: '';
    position: absolute;
    top: 50%;
    right: 14px;
    width: 10px;
    height: 6px;
    transform: translateY(-50%);
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M5 6L0 0h10z'/%3E%3C/svg%3E") no-repeat center / contain;
    mask: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M5 6L0 0h10z'/%3E%3C/svg%3E") no-repeat center / contain;
    color: rgba(60, 60, 67, 0.55);
    pointer-events: none;
}
#dark .gm__field--select::after { color: rgba(235, 235, 245, 0.5); }

#dark .gm__field input,
#dark .gm__field select,
#dark .gm__field textarea {
    background: #4141473d;
    border-color: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.95);
    -webkit-text-fill-color: rgba(255, 255, 255, 0.95);
    background-image: linear-gradient(114deg, rgb(68 68 71 / 52%), rgb(76 76 85 / 45%), rgb(109 109 109 / 14%));
}
#dark .gm__field input:focus,
#dark .gm__field select:focus,
#dark .gm__field textarea:focus {
    border-color: rgba(179, 129, 255, 0.5);
    background: rgba(118, 118, 128, 0.18);
    box-shadow: 0 0 0 3.5px rgba(179, 129, 255, 0.18);
}
#dark .gm__field label { color: rgba(235, 235, 245, 0.55); }
#dark .gm__field input:focus + label,
#dark .gm__field textarea:focus + label,
#dark .gm__field select:focus + label { color: rgba(179, 129, 255, 0.85); }

/* Autofill (webkit + Яндекс.Браузер) — убираем белую заливку.
   Ключ: inset box-shadow с цветом фона поля перекрывает нативный autofill-фон.
   transition 5555s держит цвет, пока браузер не отпустит autofill-state.
   Также важно `!important` — Яндекс агрессивно перекрашивает. */
.gm__field input:-webkit-autofill,
.gm__field input:-webkit-autofill:hover,
.gm__field input:-webkit-autofill:focus,
.gm__field input:-webkit-autofill:active,
.gm__field input:autofill {
    -webkit-box-shadow: 0 0 0 100px rgba(120, 120, 128, 0.08) inset !important;
    box-shadow: 0 0 0 100px rgba(120, 120, 128, 0.08) inset !important;
    -webkit-text-fill-color: rgb(28, 28, 30) !important;
    caret-color: rgb(28, 28, 30);
    background-color: transparent !important;
    background-image: none !important;
    transition: background-color 5555s ease-in-out 0s, color 5555s ease-in-out 0s !important;
}
#dark .gm__field input:-webkit-autofill,
#dark .gm__field input:-webkit-autofill:hover,
#dark .gm__field input:-webkit-autofill:focus,
#dark .gm__field input:-webkit-autofill:active,
#dark .gm__field input:autofill {
    -webkit-box-shadow: 0 0 0 100px rgba(118, 118, 128, 0.32) inset !important;
    box-shadow: 0 0 0 100px rgba(118, 118, 128, 0.32) inset !important;
    -webkit-text-fill-color: rgba(255, 255, 255, 0.95) !important;
    caret-color: rgba(255, 255, 255, 0.95);
}
/* На focus — соответствующий focus-цвет фона поля (иначе после autofill остаётся
   светлый фон при клике). */
.gm__field input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px rgba(120, 120, 128, 0.05) inset,
                        0 0 0 3.5px rgba(127, 45, 232, 0.14) !important;
}
#dark .gm__field input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px rgba(118, 118, 128, 0.18) inset,
                        0 0 0 3.5px rgba(179, 129, 255, 0.18) !important;
}

.gm__row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }


/* Ошибки валидации: красная подсветка поля + конкретная подсказка под ним */
.gm__field--invalid input {
    border-color: rgba(255, 59, 48, 0.55);
    background: rgba(255, 59, 48, 0.045);
}
.gm__field--invalid input:focus {
    border-color: rgba(255, 59, 48, 0.7);
    box-shadow: 0 0 0 3.5px rgba(255, 59, 48, 0.13);
}
.gm__field--invalid input + label,
.gm__field--invalid input:focus + label { color: rgba(215, 0, 21, 0.85); }
.gm__field-err {
    margin: -5px 3px 0;   /* поджимаем к полю: компенсируем gap .gm__form */
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--danger-strong);
}
#dark .gm__field--invalid input {
    border-color: rgba(255, 105, 97, 0.55);
    background: rgba(255, 105, 97, 0.08);
}
#dark .gm__field--invalid input:focus {
    border-color: rgba(255, 105, 97, 0.7);
    box-shadow: 0 0 0 3.5px rgba(255, 105, 97, 0.16);
}
#dark .gm__field--invalid input + label,
#dark .gm__field--invalid input:focus + label { color: rgba(255, 105, 97, 0.9); }
#dark .gm__field-err { color: #FF6961; }

.gm__check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 2px 0;
    cursor: pointer;
    user-select: none;
    font-size: 13.5px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.85);
    position: relative;
}
.gm__check input { position: absolute; opacity: 0; pointer-events: none; }
.gm__check-mark {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    border: 1.5px solid rgba(60, 60, 67, 0.25);
    border-radius: 6px;
    background: var(--ink-on-dark);
    margin-top: 1px;
    position: relative;
    transition: all .15s ease;
}
.gm__check input:checked + .gm__check-mark {
    background: var(--temp-brand-a);
    border-color: var(--temp-brand-a);
}
.gm__check input:checked + .gm__check-mark::after {
    content: '';
    position: absolute;
    left: 6px;
    top: 2px;
    width: 5px;
    height: 10px;
    border: solid var(--ink-on-dark);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.gm__check-text a { color: var(--temp-brand-a); text-decoration: none; font-weight: 500; }
.gm__check-text a:hover { text-decoration: underline; }
.gm__check--invalid .gm__check-mark { border-color: rgba(255, 59, 48, 0.7); }
#dark .gm__check { color: rgba(235, 235, 245, 0.75); }
#dark .gm__check-mark { background: rgba(118, 118, 128, 0.24); border-color: rgba(255, 255, 255, 0.2); }
#dark .gm__check--invalid .gm__check-mark { border-color: rgba(255, 105, 97, 0.75); }
#dark .gm__check-text a { color: var(--accent-orchid); }

/* Segmented control (radio для reset method) */
.gm__seg {
    display: grid;
    grid-template-columns: 1fr 1fr;
    padding: 2px;
    background: rgba(120, 120, 128, 0.14);
    border-radius: 10px;
}
.gm__seg-opt {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 34px;
    font-size: 13.5px;
    font-weight: 500;
    color: rgba(60, 60, 67, 0.85);
    cursor: pointer;
    border-radius: 8px;
    transition: all .2s ease;
    user-select: none;
}
.gm__seg-opt input { position: absolute; opacity: 0; pointer-events: none; }
.gm__seg-opt--on {
    background: var(--ink-on-dark);
    color: rgb(28, 28, 30);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1), 0 0 0 0.5px rgba(0, 0, 0, 0.05);
    font-weight: 600;
}
#dark .gm__seg { background: rgba(118, 118, 128, 0.24); }
#dark .gm__seg-opt { color: rgba(235, 235, 245, 0.75); }
#dark .gm__seg-opt--on {
    background: rgba(99, 99, 102, 0.95);
    color: var(--ink-on-dark);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

/* Виджет reCAPTCHA — жёсткие 304×78px, и в колонке 332px он висел уже полей
   и кнопок: единственный элемент формы, не попадающий в её края. Масштаб
   считает JS (_authCaptchaFit) от реальной ширины контейнера и кладёт в
   --gm-captcha-scale — на узком экране (320px) коэффициент < 1, там виджет
   раньше вылезал за край шторки. Высота обёртки едет тем же коэффициентом,
   иначе после scale остаётся «дыра» от нетронутого layout'а. */
.gm__captcha {
    --gm-captcha-scale: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    height: calc(78px * var(--gm-captcha-scale));
    margin: 2px 0;
    position: relative;
    overflow: hidden;
}
.gm__captcha > div:first-child {
    min-height: 78px;
    transform: scale(var(--gm-captcha-scale));
    transform-origin: center center;
}

.gm__captcha-skeleton {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    border-radius: 4px;
    background: linear-gradient(
        90deg,
        rgba(120, 120, 128, 0.10) 0%,
        rgba(120, 120, 128, 0.22) 50%,
        rgba(120, 120, 128, 0.10) 100%
    );
    background-size: 200% 100%;
    animation: gm-shimmer 1.6s ease-in-out infinite;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(60, 60, 67, 0.4);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.5px;
}
.gm__captcha-skeleton::after {
    content: "reCAPTCHA";
    text-transform: uppercase;
    letter-spacing: 2px;
}
#dark .gm__captcha-skeleton {
    background: linear-gradient(
        90deg,
        rgba(118, 118, 128, 0.14) 0%,
        rgba(118, 118, 128, 0.28) 50%,
        rgba(118, 118, 128, 0.14) 100%
    );
    background-size: 200% 100%;
    border-color: rgba(255, 255, 255, 0.06);
    color: rgba(235, 235, 245, 0.35);
}
@keyframes gm-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.gm__msg {
    padding: 10px 14px;
    border-radius: 10px;
    font-size: 13px;
    line-height: 1.4;
    margin: 0;
    text-align: center;
    font-weight: 500;
}
.gm__msg--error { background: rgba(255, 59, 48, 0.1);  color: var(--danger-strong); }
.gm__msg--success { background: rgba(52, 199, 89, 0.12); color: var(--ok-strong); }
#dark .gm__msg--error   { background: rgba(255, 69, 58, 0.15); color: #FF6961; }
#dark .gm__msg--success { background: rgba(48, 209, 88, 0.15); color: var(--ok-mint); }
/* Пояснение, а не ошибка: раньше --info не имел ни фона, ни цвета и выглядел
   обычным абзацем — заметка «что будет с текущей подпиской» в него терялась. */
.gm__msg--info { background: rgba(0, 122, 255, 0.1); color: #0B63CE; }
#dark .gm__msg--info { background: rgba(10, 132, 255, 0.16); color: #8CC2FF; }
/* Предупреждение: не ошибка (человек ничего не сломал), но и не заметка —
   последствие наступит после сохранения. Янтарный ряд системных оттенков,
   те же альфы, что у соседей. Текст здесь длиннее одной строки, поэтому
   выключка по левому краю: центрированный абзац в три строки не читается. */
.gm__msg--warning { background: rgba(255, 149, 0, 0.12); color: #A2600A; text-align: left; }
#dark .gm__msg--warning { background: rgba(255, 159, 10, 0.16); color: #FFCE7A; }
.gm__msg--warning b { display: block; margin-bottom: 3px; }
/* Нейтральная плашка — для спокойных пояснений (например статус кристаллов). */
.gm__msg--soft { background: rgba(120, 120, 128, 0.1); color: rgba(60, 60, 67, 0.8); }
#dark .gm__msg--soft { background: rgba(255, 255, 255, 0.07); color: rgba(235, 235, 245, 0.7); }
/* Адрес, на который уводит #confirm-link. Ссылки маркетплейсов — это одно
   слово в полторы сотни символов: без break-all оно распирает карточку. */
.gm__confirm-url {
    word-break: break-all;
    font-weight: 400;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
}

/* ── Свёрнутый алерт: вердикт в заголовке, подробности по клику ──────────
   В отличие от .gm__msg это не строчка статуса, а блок с двумя состояниями:
   человек видит одну фразу и раскрывает объяснение, только если оно ему нужно.
   Красным набраны рамка, иконка и заголовок; тело — обычным текстом модалки:
   абзац в четыре строки, целиком красный, не читается.
   Основа — нативный <details>: состояние держит браузер, работает с клавиатуры,
   переживает перерисовку Vue и не требует ни строчки JS. */
.gm__alert {
    width: 100%;
    margin: 0 0 18px;
    border-radius: 12px;
    text-align: left;
    background: rgba(255, 59, 48, 0.08);
    border: 1px solid rgba(255, 59, 48, 0.22);
}
.gm__alert__head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    cursor: pointer;
    color: var(--danger-strong);
    list-style: none;              /* стандартный треугольник у <summary> */
}
.gm__alert__head::-webkit-details-marker { display: none; }
.gm__alert__icon { flex: none; display: flex; margin-top: 1px; }
.gm__alert__title { flex: 1 1 auto; font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.gm__alert__more {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 1px;
    font-size: 12px;
    font-weight: 500;
    opacity: .75;
}
.gm__alert__more-close { display: none; }
.gm__alert[open] .gm__alert__more-open  { display: none; }
.gm__alert[open] .gm__alert__more-close { display: inline; }
.gm__alert__chev { transition: transform .18s ease; }
.gm__alert[open] .gm__alert__chev { transform: rotate(180deg); }
/* Отступ слева равен иконке с зазором — тело встаёт под заголовок, а не под значок */
.gm__alert__body {
    padding: 0 14px 14px 44px;
    font-size: 13px;
    line-height: 1.5;
    color: rgba(60, 60, 67, 0.85);
}
.gm__alert__body a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.gm__alert__support { display: inline-block; margin-top: 10px; }
#dark .gm__alert { background: rgba(255, 69, 58, 0.12); border-color: rgba(255, 69, 58, 0.28); }
#dark .gm__alert__head { color: #FF6961; }
#dark .gm__alert__body { color: rgba(235, 235, 245, 0.72); }
/* `#dark a` красит все ссылки в синий и по специфичности бьёт селектор с одним
   классом. Ссылки внутри блока должны остаться цвета текста: их роль показывает
   подчёркивание, а не цвет — иначе в четырёх строках горят три разных оттенка. */
#dark .gm__alert__body a { color: inherit; }
@media (max-width: 420px) {
    /* На узком экране «Развернуть» рядом с длинным заголовком ужимает его
       до двух слов в строке — оставляем только стрелку. */
    .gm__alert__more-open, .gm__alert__more-close { display: none; }
    .gm__alert[open] .gm__alert__more-close { display: none; }
}

.gm__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    height: 50px;
    border: none;
    border-radius: 14px;
    font-size: 15px;
    font-weight: 600;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    cursor: pointer;
    transition: transform .1s ease, opacity .18s, background .18s, box-shadow .18s;
    outline: none;
    text-decoration: none;
    letter-spacing: -0.2px;
    padding: 0 16px;
    -webkit-appearance: none;
    appearance: none;
}
.gm__btn:disabled { opacity: .5; cursor: not-allowed; }
/* Кнопка-ссылка (<a class="gm__btn">, например «Перейти» в #confirm-link).
   `#dark a` (index.css:241) — это id + тег, он бьёт любой селектор с одним
   классом и красил бы кнопку в синий поверх её собственного цвета. */
#dark a.gm__btn { color: var(--ink-on-dark); }
#dark a.gm__btn--secondary { color: rgba(255, 255, 255, 0.92); }
#dark a.gm__btn--secondary:hover { color: var(--ink-on-dark); }
/* Secondary в disabled — гасим до нейтрального читаемого серого. */
.gm__btn--secondary:disabled {
    opacity: 1;
    background: rgba(120, 120, 128, 0.10);
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__btn--secondary:disabled {
    background: rgba(118, 118, 128, 0.20);
    color: rgba(235, 235, 245, 0.5);
}
/* Ghost в disabled — тоже не должен становиться совсем прозрачным. */
.gm__btn--ghost:disabled { opacity: 1; color: rgba(60, 60, 67, 0.4); }
#dark .gm__btn--ghost:disabled { color: rgba(235, 235, 245, 0.4); }
.gm__btn:not(:disabled):active { transform: scale(0.98); }

.gm__btn--primary {
    background-color: var(--accent-indigo);
    background-image: linear-gradient(98.17deg, var(--accent-blue) 4%, transparent 40%, var(--accent-magenta) 93%);
    color: var(--ink-on-dark);
    box-shadow: 0 0 0 1px rgb(217 182 255 / 41%) inset, 0 8px 16px -4px rgb(40 69 94 / 45%);
    min-height: 46px;

    transition: .2s;
}
.gm__btn--primary:hover:not(:disabled) {
    background-color: #37a3f0;
    box-shadow: 0 0 0 1px rgb(217 182 255 / 41%) inset, 0 8px 58px -4px rgb(132 92 255 / 54%);
}

.gm__btn--tg {
    background: rgba(52, 152, 219, 0.14);
    color: #1D8BC4;
}
.gm__btn--tg:hover:not(:disabled) { background: rgba(52, 152, 219, 0.22); }
.gm__btn--tg svg { flex-shrink: 0; }
#dark .gm__btn--tg { background: rgba(56, 176, 245, 0.18); color: #64B5F6; }
#dark .gm__btn--tg:hover:not(:disabled) { background: rgba(56, 176, 245, 0.26); }

/* Secondary — тихая альтернатива primary в том же ряду кнопок. Класс был
   описан ТОЛЬКО в :disabled-состоянии, поэтому активная кнопка доставалась
   UA-стилю <button>: белый прямоугольник кричал громче primary-градиента. */
.gm__btn--secondary {
    background: rgba(120, 120, 128, 0.12);
    color: rgb(28, 28, 30);
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.06);
}
.gm__btn--secondary:hover:not(:disabled) { background: rgba(120, 120, 128, 0.20); }
#dark .gm__btn--secondary {
    background: rgba(255, 255, 255, 0.10);
    color: rgba(255, 255, 255, 0.92);
    box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.08);
}
#dark .gm__btn--secondary:hover:not(:disabled) { background: rgba(255, 255, 255, 0.16); color: var(--ink-on-dark); }

.gm__btn--ghost {
    background: transparent;
    color: rgba(60, 60, 67, 0.65);
    box-shadow: none;
    font-weight: 500;
    box-shadow: inset 0 0 0 1px rgba(60, 60, 67, 0.05);
}
.gm__btn--ghost:hover:not(:disabled) {
    background: rgba(120, 120, 128, 0.1);
    color: rgb(28, 28, 30);
}
#dark .gm__btn--ghost { color: rgba(235, 235, 245, 0.55); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);}
#dark .gm__btn--ghost:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: var(--ink-on-dark); }

/* Компактный размер для действий ВНУТРИ блока-карточки: базовые 50px во всю
   ширину там читаются как главная кнопка экрана, хотя это локальное действие. */
.gm__btn--sm {
    width: auto;
    height: 34px;
    /* .gm__btn--primary держит min-height: 46px, и без сброса компактная
       primary-кнопка оказывалась на 12px выше соседней обычной. Раньше это
       чинили точечно у каждой такой кнопки (см. .gm__cart-foot__send). */
    min-height: 34px;
    border-radius: 10px;
    font-size: 13px;
    padding: 0 14px;
}

.gm__spinner {
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: var(--ink-on-dark);
    border-radius: 50%;
    animation: gm-spin .7s linear infinite;
}
@keyframes gm-spin { to { transform: rotate(360deg); } }

.gm__foot {
    text-align: center;
    font-size: 13.5px;
    color: rgba(60, 60, 67, 0.7);
    margin-top: 8px;
    line-height: 1.6;
}
.gm__foot a {
    color: var(--temp-brand-a);
    text-decoration: none;
    font-weight: 500;
    cursor: pointer;
}
.gm__foot a:hover { text-decoration: underline; }
.gm__foot-dot { margin: 0 6px; opacity: .35; }
#dark .gm__foot { color: rgba(235, 235, 245, 0.55); }
#dark .gm__foot a { color: var(--accent-orchid); }

.gm__hint {
    font-size: 14px;
    text-align: center;
    color: rgba(60, 60, 67, 0.7);
    line-height: 1.5;
    margin: 4px 0 12px;
}
#dark .gm__hint { color: rgba(235, 235, 245, 0.6); }

/* Разделитель с подписью: ниже — другой способ сделать то же самое
   (в auth-модалке отделяет вход по паролю от входа через Telegram). */
.gm__divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 2px 0;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.2px;
    color: rgba(60, 60, 67, 0.45);
}
.gm__divider::before, .gm__divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: rgba(60, 60, 67, 0.12);
}
#dark .gm__divider { color: rgba(235, 235, 245, 0.4); }
#dark .gm__divider::before, #dark .gm__divider::after { background: rgba(255, 255, 255, 0.1); }

/* Подсказка под полем: правила ввода ДО ошибки, а не после неё. Отступы те же,
   что у .gm__field-err — обе строки занимают один и тот же слот под полем. */
.gm__field-hint {
    margin: -5px 3px 0;
    font-size: 12.5px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__field-hint { color: rgba(235, 235, 245, 0.4); }
/* Ошибка капчи относится к центрированному виджету — левый край текста
   под ним выглядел бы обрывком строки поля. */
.gm__captcha + .gm__field-err { text-align: center; }

/* Капча не доехала (заблокирована сетью/расширением/VPN). Раньше на этом
   месте вечно мерцал скелетон, а кнопка молча требовала отметить галочку,
   которой нет. Теперь — честный тупик с выходом: «Повторить» и подсказка. */
.gm__captcha-fail {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(255, 149, 0, 0.10);
    color: #A2600A;
    font-size: 12.5px;
    line-height: 1.45;
}
#dark .gm__captcha-fail { background: rgba(255, 159, 10, 0.14); color: #FFCE7A; }
.gm__captcha-fail b { display: block; font-size: 13px; font-weight: 600; }
.gm__captcha-fail__act {
    align-self: flex-start;
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-weight: 600;
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.gm__captcha-fail__act:disabled { opacity: .55; cursor: default; text-decoration: none; }

/* Вспомогательная ссылка у формы («Забыли пароль?») — по правому краю полей. */
.gm__form-aside { display: flex; justify-content: flex-end; margin: -2px 3px 0; }
.gm__link {
    font-size: 13px;
    font-weight: 500;
    color: var(--temp-brand-a);
    text-decoration: none;
    cursor: pointer;
}
.gm__link:hover { text-decoration: underline; }
#dark .gm__link { color: var(--accent-orchid); }
/* Тот же вид, но <button>: нужен сброс UA-стилей (ср. button.gm__seg-opt). */
button.gm__link--btn {
    display: block;
    margin: 3px auto 0;
    padding: 0;
    border: none;
    background: none;
    font-family: inherit;
    cursor: pointer;
}

/* Шапка auth-view: заголовок и подзаголовок — одна группа. Без неё gap
   .gm__view (14px) складывался с их margin'ами и разбивал пару на два блока. */
.gm__view--auth { gap: 12px; }
.gm__auth-head { display: flex; flex-direction: column; gap: 4px; margin: 2px 0; }
.gm__auth-head .gm__title { margin: 0; }
.gm__auth-head .gm__subtitle { margin: 0; }

.gm__recov {
    padding: 14px;
    background: rgba(120, 120, 128, 0.08);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.gm__recov-title { font-size: 13.5px; font-weight: 600; color: rgb(28, 28, 30); letter-spacing: -0.1px; }
.gm__recov-hint { font-size: 12.5px; color: rgba(60, 60, 67, 0.7); line-height: 1.45; margin-top: -4px; }
#dark .gm__recov { background: rgba(118, 118, 128, 0.16); }
#dark .gm__recov-title { color: var(--ink-on-dark); }
#dark .gm__recov-hint { color: rgba(235, 235, 245, 0.55); }

/* Field with inline action button — компактная apple-style pill справа
   внутри поля. Padding-right у input делает место, чтобы текст не наезжал. */
.gm__field--with-action input { padding-right: 140px; }
.gm__field__action {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    height: 34px;
    line-height: 34px;    /* точный вертикальный центр текста */
    padding: 0 14px;
    min-width: 110px;
    border: none;
    border-radius: 8px;
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-a);
    font-size: 13px;
    font-weight: 600;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    letter-spacing: -0.1px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, transform .1s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
}
.gm__field__action span { display: inline-flex; align-items: center; line-height: 1; }
.gm__field__action:not(:disabled):hover { background: rgba(127, 45, 232, 0.20); }
.gm__field__action:not(:disabled):active { transform: translateY(-50%) scale(0.96); }
.gm__field__action:disabled {
    cursor: default;
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.4);
}
.gm__field__action--ok, .gm__field__action--ok:disabled {
    background: rgba(52, 199, 89, 0.16);
    color: var(--ok-strong);
    cursor: default;
}
.gm__field__action--clear {
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.72);
    min-width: 72px;
}
.gm__field__action--clear:not(:disabled):hover { background: rgba(120, 120, 128, 0.22); }
#dark .gm__field__action--clear {
    background: rgba(118, 118, 128, 0.24);
    color: rgba(235, 235, 245, 0.7);
}
#dark .gm__field__action--clear:not(:disabled):hover { background: rgba(118, 118, 128, 0.34); }
#dark .gm__field__action { background: rgba(179, 129, 255, 0.18); color: var(--accent-orchid); box-shadow: inset 0 0 0 0.5px #c68cff47; }
#dark .gm__field__action:not(:disabled):hover { background: rgba(179, 129, 255, 0.28); }
#dark .gm__field__action:disabled {
    background: rgba(118, 118, 128, 0.20);
    color: rgba(235, 235, 245, 0.4);
}
#dark .gm__field__action--ok, #dark .gm__field__action--ok:disabled {
    background: rgba(48, 209, 88, 0.20);
    color: var(--ok-mint);
    box-shadow: inset 0 0 0 0.5px #8cffa547;
}

/* Иконочный вариант той же pill — «показать пароль». Узкий и нейтральный:
   это переключатель просмотра, а не действие с данными. Стоит ПОСЛЕ тёмных
   правил .gm__field__action — иначе #dark-селектор той же специфичности,
   но объявленный ниже, вернул бы фиолетовую заливку. */
.gm__field--with-icon input { padding-right: 46px; }
.gm__field--with-icon label { right: 46px; }
.gm__field__action--icon {
    min-width: 34px;
    width: 34px;
    padding: 0;
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.6);
}
.gm__field__action--icon:not(:disabled):hover { background: rgba(120, 120, 128, 0.22); color: rgb(28, 28, 30); }
#dark .gm__field__action--icon { background: rgba(118, 118, 128, 0.24); color: rgba(235, 235, 245, 0.6); box-shadow: none; }
#dark .gm__field__action--icon:not(:disabled):hover { background: rgba(118, 118, 128, 0.34); color: var(--ink-on-dark); }

/* Inline confirm block — раскрывается под полем в onboarding. */
.gm__inline {
    background: rgba(120, 120, 128, 0.06);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 12px;
    padding: 14px;
    margin: -4px 0 4px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow: hidden;
}
#dark .gm__inline {
    background: rgba(118, 118, 128, 0.10);
    border-color: rgba(255, 255, 255, 0.06);
}
.gm__inline__hint {
    font-size: 13px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.75);
}
.gm__inline__hint b { color: rgb(28, 28, 30); }
#dark .gm__inline__hint { color: rgba(235, 235, 245, 0.7); }
#dark .gm__inline__hint b { color: var(--ink-on-dark); }
.gm__inline__actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.gm__inline__actions .gm__btn { flex: 1; }

/* Compact вариант кнопки — для inline-подтверждений и вспомогательных мест. */
.gm__btn--compact { height: 40px; font-size: 13.5px; border-radius: 11px; }

/* ─── Sections (Apple-style Settings) ─── */
.gm__section {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 10px;
}
.gm__section + .gm__section { margin-top: 20px; }
.gm__section-title {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.55);
    padding: 0 4px 6px;
}
#dark .gm__section-title { color: rgba(235, 235, 245, 0.45); }
.gm__section-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.gm__section-footnote {
    font-size: 12px;
    color: rgba(60, 60, 67, 0.55);
    padding: 6px 4px 0;
    line-height: 1.4;
}
#dark .gm__section-footnote { color: rgba(235, 235, 245, 0.45); }
/* Для модалок с центрированной типографикой (.gm__title/.gm__subtitle по центру) —
   иначе сноска одна выбивается влево. */
.gm__section-footnote--center { text-align: center; }

/* ─── List rows (iOS style grouped list) ─── */
.gm__list {
    background: rgba(120, 120, 128, 0.08);
    border-radius: 12px;
    overflow: hidden;
}
#dark .gm__list {
    background: rgba(118, 118, 128, 0.14);
    background-image: linear-gradient(114deg, rgb(68 68 71 / 52%), rgb(0 0 0 / 14%));
}

.gm__list-row {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: 12px;
    padding: 12px 14px;
    cursor: pointer;
    user-select: none;
    position: relative;
}
.gm__list-row + .gm__list-row::before {
    content: '';
    position: absolute;
    top: 0;
    left: 14px;
    right: 14px;
    height: 0.5px;
    background: rgba(60, 60, 67, 0.14);
}
#dark .gm__list-row + .gm__list-row::before { background: rgba(255, 255, 255, 0.08); }

.gm__list-row__label {
    grid-column: 1;
    grid-row: 1;
    font-size: 15px;
    font-weight: 500;
    color: rgb(28, 28, 30);
    letter-spacing: -0.2px;
}
#dark .gm__list-row__label { color: rgba(255, 255, 255, 0.95); }

.gm__list-row__hint {
    grid-column: 1;
    grid-row: 2;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.6);
    line-height: 1.35;
    margin-top: 2px;
}
#dark .gm__list-row__hint { color: rgba(235, 235, 245, 0.5); }

/* Фактическое состояние разрешения (сейчас — push-уведомления под списком
   каналов): точка-индикатор, подпись и действия по месту. Отдельно от .gm__list,
   потому что это не настройка, которую человек переключает, а состояние,
   которое ему сообщают, — и кнопки в нём чинят, а не настраивают. */
.gm__push-check {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 10px;
    margin-top: 10px;
    padding: 12px 14px;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.08);
}
#dark .gm__push-check { background: rgba(255, 255, 255, 0.06); }
.gm__push-check__dot {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(60, 60, 67, 0.3);
}
.gm__push-check--on .gm__push-check__dot { background: var(--temp-ok-strong-b); box-shadow: 0 0 0 4px rgba(28, 143, 69, 0.12); }
.gm__push-check--off .gm__push-check__dot { background: #C2374A; box-shadow: 0 0 0 4px rgba(194, 55, 74, 0.1); }
#dark .gm__push-check--on .gm__push-check__dot { background: var(--ok-bright); box-shadow: 0 0 0 4px rgba(78, 215, 123, 0.14); }
#dark .gm__push-check--off .gm__push-check__dot { background: #FF7A8A; box-shadow: 0 0 0 4px rgba(255, 122, 138, 0.14); }
.gm__push-check__txt {
    flex: 1;
    min-width: 140px;
    font-size: 14px;
    font-weight: 500;
    color: rgb(28, 28, 30);
}
#dark .gm__push-check__txt { color: rgba(255, 255, 255, 0.95); }
.gm__push-check__acts { display: flex; flex-wrap: wrap; gap: 8px; }
.gm__push-check__res {
    margin: 8px 4px 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__push-check__res { color: rgba(235, 235, 245, 0.5); }
.gm__push-check__res--ok { color: var(--temp-ok-strong-b); }
.gm__push-check__res--bad { color: #C2374A; }
#dark .gm__push-check__res--ok { color: var(--ok-bright); }
#dark .gm__push-check__res--bad { color: #FF7A8A; }

/* Строка-справка: значение показывают, но трогать нечего (дата в окне
   «Информация о карточке»). Без неё курсор обещает действие, которого нет. */
.gm__list-row--plain { cursor: default; }

/* Заблокированная строка (нет PRO-подписки): полупрозрачная, свитч не кликается.
   Сам PRO-тег видимости не теряет — просто «подкачаешь подписку, разблокируется». */
.gm__list-row--locked { opacity: 0.55; cursor: not-allowed; }
.gm__list-row--locked .gm__switch { pointer-events: none; }

/* Метка со встроенным PRO-тегом: flex-центрирует текст и бейдж по вертикали.
   Правило-миксин: не ломает grid-column/grid-row из базового .gm__list-row__label,
   переопределяет только внутренний layout. */
.gm__list-row__label {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.gm__pro-tag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 18px;
    padding: 0 5px;
    background: linear-gradient(120deg, #ff9c21a1 0%, #ff6428c2 100%);
    color: var(--ink-on-dark);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.5px;
    line-height: 1;
    border-radius: 6px;
    text-transform: uppercase;
    box-shadow: 0 1px 2px rgb(255 122 0);
    cursor: pointer;
}
.gm__pro-tag:active { transform: scale(.92); }

/* ─── Строка выбора сущности с аватаркой (психологический портрет) ───
   Чекбокс — .gm__check (см. auth-модалку), аватарка — общий .entity-avatar,
   имя — как в .loved-item__name. Ничего нового не изобретаем, просто
   компонуем в ряд с кнопками сортировки справа. */
.gm__pick-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: rgba(120, 120, 128, 0.06);
    border-radius: 12px;
    transition: opacity .14s ease;
}
.gm__pick-row + .gm__pick-row { margin-top: 6px; }
.gm__pick-row--off { opacity: .5; }
#dark .gm__pick-row { background: rgba(255, 255, 255, 0.05); }

.gm__pick-row__check {
    flex: 1;
    min-width: 0;
    padding: 0;
    gap: 10px;
    align-items: center;
}
.gm__pick-row__check .gm__check-mark { margin-top: 0; }
.gm__pick-row__name {
    flex: 1;
    min-width: 0;
    font-size: 13.5px;
    font-weight: 500;
    color: rgb(28, 28, 30);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__pick-row__name { color: rgba(255, 255, 255, 0.92); }
.gm__pick-row__badge {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: rgba(60, 60, 67, 0.5);
    background: rgba(120, 120, 128, 0.12);
    padding: 2px 7px;
    border-radius: 99px;
    flex-shrink: 0;
}
#dark .gm__pick-row__badge { color: rgba(235, 235, 245, 0.4); background: rgba(255, 255, 255, 0.08); }

.gm__pick-row__order { display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }
.gm__pick-row__order button {
    width: 22px;
    height: 16px;
    border: none;
    background: rgba(120, 120, 128, 0.12);
    color: rgba(60, 60, 67, 0.55);
    border-radius: 4px;
    font-size: 9px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background .14s ease;
}
.gm__pick-row__order button:hover { background: rgba(120, 120, 128, 0.22); }
.gm__pick-row__order button:disabled { opacity: .3; cursor: default; }
#dark .gm__pick-row__order button { background: rgba(255, 255, 255, 0.08); color: rgba(235, 235, 245, 0.6); }
#dark .gm__pick-row__order button:hover { background: rgba(255, 255, 255, 0.16); }

/* ─── Перетаскиваемый список строк (.gm__pick-list) ───
   Порядок задаётся ручкой справа, как в списках iOS: стрелки «выше/ниже»
   слишком мелкие для пальца. Строки переставляет JS (startLayoutDrag в
   assets/index.ejs), плавность даёт <transition-group> — он же FLIP.
   Живёт в #profile-layout; .gm__pick-row__order выше остался у психологического
   портрета, где строк много и порядок правят точечно. */
.gm__pick-list { display: flex; flex-direction: column; gap: 6px; }
/* Во время перетаскивания палец «рисует» выделение по всему списку — гасим */
.gm__pick-list--dragging { user-select: none; -webkit-user-select: none; }
/* .gm__pick-row + .gm__pick-row даёт margin-top: 6px — внутри списка расстояние
   держит gap, иначе при перестановке строки прыгают на 6px. */
.gm__pick-list .gm__pick-row + .gm__pick-row { margin-top: 0; }
/* Название блока переносится, а не обрезается многоточием: в списке из шести
   строк важно прочитать, что именно скрываешь. Высота строки от этого «плавает»,
   но перетаскивание считает позиции по реальным rect'ам и это переживает. */
.gm__pick-list .gm__pick-row__name { white-space: normal; line-height: 1.3; }

.gm__pick-row__handle {
    flex-shrink: 0;
    /* 36px — минимум, в который уверенно попадает палец: строка всего 48px
       высотой, больше сюда не влезет без роста самой строки. */
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: rgba(60, 60, 67, 0.35);
    cursor: grab;
    /* Без этого браузер на телефоне уводит жест в скролл модалки */
    touch-action: none;
    transition: background .14s ease, color .14s ease;
}
.gm__pick-row__handle:hover { background: rgba(120, 120, 128, 0.12); color: rgba(60, 60, 67, 0.6); }
.gm__pick-row__handle:active { cursor: grabbing; }
.gm__pick-row__handle:disabled { opacity: .35; cursor: default; }
.gm__pick-row__handle:disabled:hover { background: transparent; }
#dark .gm__pick-row__handle { color: rgba(235, 235, 245, 0.35); }
#dark .gm__pick-row__handle:hover { background: rgba(255, 255, 255, 0.08); color: rgba(235, 235, 245, 0.65); }

/* Тащимая строка: приподнята и не участвует в FLIP-анимации — иначе она
   догоняла бы палец с задержкой перехода. */
.gm__pick-row--dragging {
    position: relative;
    z-index: 2;
    transition: none !important;
    background: rgba(252, 252, 253, 0.96);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14), inset 0 0 0 0.5px rgba(0, 0, 0, 0.06);
}
#dark .gm__pick-row--dragging {
    background: rgba(58, 58, 63, 0.98);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), inset 0 0 0 0.5px rgba(255, 255, 255, 0.1);
}

/* Кнопка действия в строке (например «Настроить» у витрины). Те же токены,
   что у .gm__list-row__action, но без grid-раскладки той строки. */
.gm__pick-row__action {
    flex-shrink: 0;
    height: 30px;
    padding: 0 12px;
    border: none;
    border-radius: 8px;
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-a);
    font-size: 12.5px;
    font-weight: 600;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    transition: background .14s ease;
}
.gm__pick-row__action:hover { background: rgba(127, 45, 232, 0.20); }
#dark .gm__pick-row__action { background: rgba(179, 129, 255, 0.18); color: var(--accent-orchid); }
#dark .gm__pick-row__action:hover { background: rgba(179, 129, 255, 0.28); }
/* На узком экране слово «Настроить» съедает название блока (оно уезжает в
   многоточие), поэтому там кнопка сжимается до «счётчик ›» — строка читается
   как обычная строка-переход iOS. */
@media (max-width: 480px) {
    .gm__pick-row__action { padding: 0 8px; gap: 4px; }
    .gm__pick-row__action-label { display: none; }
    .gm__pick-row__action::after {
        content: '›';
        font-size: 16px;
        line-height: 1;
        opacity: .75;
    }
}

/* Счётчик выбранных плиток — подсказка, что внутри уже что-то настроено */
.gm__pick-row__action-num {
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: rgba(127, 45, 232, 0.55);
    color: var(--ink-on-dark);
    font-size: 11px;
    line-height: 18px;
    text-align: center;
}
#dark .gm__pick-row__action-num { background: rgba(179, 129, 255, 0.45); }

/* ─── Редактор соцсетей (external_links) ─── */
.gm__extlinks {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.gm__extlink {
    display: grid;
    grid-template-columns: 32px 1fr 32px;
    gap: 8px;
    align-items: center;
}
.gm__extlink__icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background: rgba(120, 120, 128, 0.16);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}
#dark .gm__extlink__icon { background: rgba(255, 255, 255, 0.08); }
.gm__extlink__icon::before {
    content: '';
    position: absolute;
    inset: 6px;
    background: currentColor;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-size: contain;
            mask-size: contain;
}
.gm__extlink--empty  .gm__extlink__icon { color: rgba(60, 60, 67, 0.35); }
#dark .gm__extlink--empty .gm__extlink__icon { color: rgba(255, 255, 255, 0.35); }
.gm__extlink--empty  .gm__extlink__icon::before,
.gm__extlink--unknown .gm__extlink__icon::before {
    /* link-иконка (SVG data URL): скрепка */
    -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M10.59 13.41a1 1 0 0 1 1.42 0 1 1 0 0 1 0 1.41l-3.18 3.18a3 3 0 1 1-4.24-4.24l3.18-3.18a1 1 0 0 1 1.41 1.41l-3.18 3.18a1 1 0 1 0 1.41 1.42ZM13.41 10.59a1 1 0 0 1-1.42 0 1 1 0 0 1 0-1.41l3.18-3.18a3 3 0 0 1 4.24 4.24l-3.18 3.18a1 1 0 1 1-1.41-1.41l3.18-3.18a1 1 0 1 0-1.41-1.42ZM8.71 15.29a1 1 0 0 1 0-1.41l5.58-5.58a1 1 0 1 1 1.42 1.41l-5.58 5.58a1 1 0 0 1-1.42 0Z"/></svg>');
            mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M10.59 13.41a1 1 0 0 1 1.42 0 1 1 0 0 1 0 1.41l-3.18 3.18a3 3 0 1 1-4.24-4.24l3.18-3.18a1 1 0 0 1 1.41 1.41l-3.18 3.18a1 1 0 1 0 1.41 1.42ZM13.41 10.59a1 1 0 0 1-1.42 0 1 1 0 0 1 0-1.41l3.18-3.18a3 3 0 0 1 4.24 4.24l-3.18 3.18a1 1 0 1 1-1.41-1.41l3.18-3.18a1 1 0 1 0-1.41-1.42ZM8.71 15.29a1 1 0 0 1 0-1.41l5.58-5.58a1 1 0 1 1 1.42 1.41l-5.58 5.58a1 1 0 0 1-1.42 0Z"/></svg>');
}
.gm__extlink--unknown .gm__extlink__icon {
    background: rgba(255, 179, 0, 0.16);
    color: #E39F00;
}
.gm__extlink--unknown .gm__extlink__icon::before {
    /* alert-triangle */
    -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2 1 21h22L12 2Zm0 6 7.53 13H4.47L12 8Zm-1 4v4h2v-4h-2Zm0 6v2h2v-2h-2Z"/></svg>');
            mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2 1 21h22L12 2Zm0 6 7.53 13H4.47L12 8Zm-1 4v4h2v-4h-2Zm0 6v2h2v-2h-2Z"/></svg>');
}
.gm__extlink--telegram_channel .gm__extlink__icon { color: #2AABEE; }
.gm__extlink--telegram_channel .gm__extlink__icon::before {
    -webkit-mask-image: url('/ui/channel-icon.svg');
            mask-image: url('/ui/channel-icon.svg');
}
.gm__extlink--youtube .gm__extlink__icon { color: #FF0000; }
.gm__extlink--youtube .gm__extlink__icon::before {
    -webkit-mask-image: url('/ui/youtube-icon.svg');
            mask-image: url('/ui/youtube-icon.svg');
}
.gm__extlink--tiktok .gm__extlink__icon { color: #010101; }
#dark .gm__extlink--tiktok .gm__extlink__icon { color: var(--ink-on-dark); }
.gm__extlink--tiktok .gm__extlink__icon::before {
    -webkit-mask-image: url('/ui/tiktok-icon.svg');
            mask-image: url('/ui/tiktok-icon.svg');
}
.gm__extlink--vk .gm__extlink__icon { color: #0077FF; }
.gm__extlink--vk .gm__extlink__icon::before {
    -webkit-mask-image: url('/ui/vk-icon.svg');
            mask-image: url('/ui/vk-icon.svg');
}
.gm__extlink__input {
    height: 32px;
    padding: 0 12px;
    border: 1px solid rgba(60, 60, 67, 0.16);
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font-size: 14px;
    outline: none;
}
.gm__extlink--unknown .gm__extlink__input { border-color: rgba(255, 179, 0, 0.6); }
.gm__extlink__input:focus { border-color: rgba(0, 122, 255, 0.5); }
#dark .gm__extlink__input { border-color: rgba(255, 255, 255, 0.12); }
.gm__extlink__remove {
    width: 32px;
    height: 32px;
    border: none;
    background: rgba(255, 59, 48, 0.12);
    color: #FF3B30;
    border-radius: 8px;
    cursor: pointer;
    font-size: 18px;
    line-height: 1;
}
.gm__extlink__remove:hover { background: rgba(255, 59, 48, 0.22); }
.gm__extlink__add {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    padding: 8px 14px;
    border: 1px dashed rgba(60, 60, 67, 0.25);
    border-radius: 10px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
}
#dark .gm__extlink__add { border-color: rgba(255, 255, 255, 0.16); }
.gm__extlink__add:hover { background: rgba(120, 120, 128, 0.08); }
.gm__extlink__add-plus {
    font-size: 16px;
    line-height: 1;
    font-weight: 700;
}

/* ─── iOS-style Switch (toggle) — компактный, с явной сменой цвета ─── */
.gm__switch {
    grid-column: 2;
    grid-row: 1 / span 2;
    position: relative;
    display: inline-block;
    width: 44px;
    height: 26px;
    flex-shrink: 0;
    align-self: center;
}
.gm__switch input {
    position: absolute;
    opacity: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    cursor: pointer;
    z-index: 2;
}
.gm__switch__slider {
    position: absolute;
    inset: 0;
    background: rgba(120, 120, 128, 0.32);
    border-radius: 26px;
    transition: background .2s cubic-bezier(.4, 0, .2, 1);
    cursor: pointer;
}
.gm__switch__slider::before {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 22px;
    height: 22px;
    background: var(--ink-on-dark);
    border-radius: 50%;
    transition: transform .22s cubic-bezier(.4, 0, .2, 1);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 2px 1px rgba(0, 0, 0, 0.06);
}
/* Sibling selector — исправлено на ~ на случай если в DOM ещё элементы */
.gm__switch input:checked ~ .gm__switch__slider {
    background: linear-gradient(6deg, var(--ok-vivid), #3e8d51);
}
.gm__switch input:checked ~ .gm__switch__slider::before {
    transform: translateX(18px);
}
#dark .gm__switch__slider { background: rgba(118, 118, 128, 0.42); }
#dark .gm__switch input:checked ~ .gm__switch__slider { background: var(--ok-vivid); }

/* ─── Horizontal tabs — иконка сверху + подпись снизу (edit-profile) ─── */
.gm__tabs {
    display: flex;
    gap: 4px;
    margin: 12px 0 0;
    padding-bottom: 24px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
#dark .gm__tabs {
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.gm__tabs-item {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 12px 6px 10px;
    background: transparent;
    border: none;
    color: rgba(60, 60, 67, 0.72);
    font-size: 11.5px;
    font-weight: 500;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    letter-spacing: -0.1px;
    border-radius: 12px;
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
    -webkit-appearance: none;
    appearance: none;
    line-height: 1.2;
    text-align: center;
}
.gm__tabs-item:hover:not(.gm__tabs-item--active) {
    background: rgba(120, 120, 128, 0.08);
    color: rgb(28, 28, 30);
}
.gm__tabs-item--active {
    background: rgb(255 255 255 / 12%);
    color: #a2acb7;
    font-weight: 600;
    box-shadow: 0 4px 10px #7489c557;
}
.gm__tabs-icon {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    filter: brightness(.9);
}
.gm__tabs-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0.72;
    transition: opacity .18s ease, filter .18s ease;
}
.gm__tabs-item:hover:not(.gm__tabs-item--active) .gm__tabs-icon img { opacity: 0.92; }
.gm__tabs-item--active .gm__tabs-icon img {
    opacity: 1;
    /* Красим SVG в brand-цвет через filter (для одноцветных иконок работает) */
}
.gm__tabs-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    display: none;
}

#dark .gm__tabs-item { color: rgba(235, 235, 245, 0.65); }
#dark .gm__tabs-item:hover:not(.gm__tabs-item--active) {
    background: rgba(255, 255, 255, 0.06);
    color: var(--ink-on-dark);
}
#dark .gm__tabs-item--active {
    box-shadow: 0 4px 10px #161616e3;
    background: rgb(233 233 233 / 3%);
}
#dark .gm__tabs-icon img {
    filter: unset;
    opacity: 0.2;
}
#dark .gm__tabs-item:hover:not(.gm__tabs-item--active) .gm__tabs-icon img { opacity: 0.95; }
#dark .gm__tabs-item--active .gm__tabs-icon img {
    opacity: 1;
}

/* На узких экранах — только иконки, подписи скрываются */
@media (max-width: 480px) {
    .gm__tabs-label { display: none; }
    .gm__tabs--shop .gm__tabs-item { padding: 8px 4px 7px; }
    .gm__tabs--shop .gm__tabs-icon { width: 18px; height: 18px; }
    .gm__tabs-item { padding: 10px 4px; }
}

/* ─── Sticky actions в конце длинного edit-profile ─── */
.gm__sticky-actions {
    position: sticky;
    bottom: -24px;
    margin: 20px -24px -24px;
    padding: 14px 24px 20px;
    background: linear-gradient(to top, rgb(229 229 229) 60%, rgb(229 229 229) 100%);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    display: flex;
    flex-direction: row;
    gap: 20px;
    flex-wrap: revert;
    border-top: 0.5px solid rgba(0, 0, 0, 0.08);
    z-index: 5;
}
#dark .gm__sticky-actions {
    background: linear-gradient(
        to top,
        rgba(30, 30, 34, 0.95) 60%,
        rgba(30, 30, 34, 0.7) 100%
    );
    border-top-color: rgba(255, 255, 255, 0.08);
}

/* Autosave hint — маленькая надпись под полями */
.gm__autosave-hint {
    font-size: 11.5px;
    color: rgba(52, 199, 89, 0.9);
    text-align: center;
    padding-top: 4px;
    font-weight: 500;
    animation: gm-fade-in .3s ease-in;
}
#dark .gm__autosave-hint { color: var(--ok-mint); }

/* OL для verify-tg deeplink инструкций */
.gm__ol {
    padding-left: 22px;
    margin: 8px 0 12px;
    font-size: 14px;
    color: rgba(60, 60, 67, 0.85);
    line-height: 1.6;
}
.gm__ol li { margin-bottom: 4px; }
#dark .gm__ol { color: rgba(235, 235, 245, 0.75); }

.gm__cities {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: rgba(252, 252, 253, 0.95);
    -webkit-backdrop-filter: blur(30px) saturate(180%);
    backdrop-filter: blur(30px) saturate(180%);
    border: 0.5px solid rgba(0, 0, 0, 0.1);
    border-radius: 12px;
    box-shadow: 0 10px 30px -8px rgba(0, 0, 0, 0.2);
    max-height: 210px;
    overflow-y: auto;
    z-index: 10;
}
.gm__cities-item {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 14px;
    transition: background .12s;
    display: flex;
    justify-content: space-between;
    color: inherit;
}
.gm__cities-item + .gm__cities-item { border-top: 0.5px solid rgba(0, 0, 0, 0.06); }
.gm__cities-item:hover { background: rgba(120, 120, 128, 0.1); }
.gm__cities-item span { opacity: .5; font-size: 12.5px; }
#dark .gm__cities { background: rgba(45, 45, 50, 0.95); border-color: rgba(255, 255, 255, 0.1); color: rgba(255, 255, 255, 0.9); }
#dark .gm__cities-item + .gm__cities-item { border-color: rgba(255, 255, 255, 0.06); }
#dark .gm__cities-item:hover { background: rgba(255, 255, 255, 0.06); }

/* ── Список языков (#lang-modal) ─────────────────────────────────────────────
   Языков шестнадцать, поэтому список, а не ряд флажков: у каждого пункта
   самоназвание и галочка у текущего — как в боковом меню (.sm__lang).
   Токены — общие .gm: заливки rgba(120,120,128,…), хайрлайны 0.5px, радиус 14. */
.gm__langs {
    margin-top: 10px;
    max-height: min(46vh, 340px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.08);
    padding: 4px;
}
.gm__lang {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 12px;
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
    font-size: 15px;
    cursor: pointer;
    transition: background .12s cubic-bezier(.16, 1, .3, 1);
}
.gm__lang + .gm__lang { box-shadow: 0 -0.5px 0 rgba(0, 0, 0, 0.06); }
.gm__lang:hover { background: rgba(120, 120, 128, 0.12); }
.gm__lang img {
    width: 22px;
    height: 22px;
    /* Радиус 4px, а не круг: у языковых флагов в проекте уже есть трактовка —
       .sm__lang img в боковом меню. Своя вводила бы третью форму для одних и
       тех же картинок. */
    border-radius: 4px;
    object-fit: cover;
    flex: 0 0 auto;
}
.gm__lang-name { flex: 1 1 auto; }
/* Подпись группы языков — в языке .gm__section-title: капс, мелко, приглушённо */
.gm__langs-cap {
    padding: 10px 12px 6px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.5);
}
.gm__langs-cap[hidden] { display: none; }
.gm__langs-cap:first-child { padding-top: 6px; }
#dark .gm__langs-cap { color: rgba(235, 235, 245, 0.45); }
/* Скроллбар — как у .gm__card: глобальный тёмный трек в светлой теме выглядит
   тяжёлой серой полосой поперёк списка */
.gm__langs { scrollbar-width: thin; }
.gm__langs::-webkit-scrollbar { width: 8px; }
.gm__langs::-webkit-scrollbar-track { background: transparent; }
.gm__langs::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.15); border: 0; border-radius: 4px; }
#dark .gm__langs::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); }
.gm__lang-check {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    opacity: 0;
    color: var(--temp-brand-a);
}
.gm__lang-check svg { width: 100%; height: 100%; }
.gm__lang--on { background: rgba(122, 45, 232, 0.1); }
.gm__lang--on .gm__lang-check { opacity: 1; }
/* Скрытый поиском пункт не должен оставлять линию-разделитель */
.gm__lang[hidden] { display: none; }
/* .gm__empty объявлен как display:flex — класс перебивает браузерное
   правило [hidden]{display:none}, поэтому гасим явно */
.gm__empty[hidden] { display: none; }

/* Пункт списка — ссылка, а глобальное «#dark a { color: #4FA0FF }» бьёт класс
   по специфичности: названия языков красились в синий, как ссылки. Тот же приём,
   что у .sm__lang в боковом меню — префикс #dark/#root поднимает специфичность. */
#dark .gm__lang, #root .gm__lang { color: inherit; }
#dark .gm__langs { background: rgba(255, 255, 255, 0.06); }
#dark .gm__lang + .gm__lang { box-shadow: 0 -0.5px 0 rgba(255, 255, 255, 0.06); }
#dark .gm__lang:hover { background: rgba(255, 255, 255, 0.1); }
#dark .gm__lang--on { background: rgba(122, 45, 232, 0.22); }
#dark .gm__lang-check { color: #B98BFF; }

@media (max-width: 480px) {
    .gm__title { font-size: 24px; }
    .gm__row { grid-template-columns: 1fr; }
    .gm__daily-card__head { flex-wrap: wrap; row-gap: 8px; }
    .gm__daily-card__amount { text-align: left; }
}

/* ═══════════════════════════════════════════════════════════════════════
   .gm НА ТЕЛЕФОНЕ — bottom sheet (шторка), как #findCard/.fcm

   Карточка прижата к нижнему краю: контент оказывается под большим пальцем,
   а не в середине экрана. Закрывается свайпом вниз за верхнюю кромку —
   Закрывается протяжкой вниз: за верхнюю кромку — всегда, за содержимое —
   когда прокрутка внутри стоит наверху. Жест общий на весь проект и живёт в
   static/js/sheet-drag.js; какие узлы считать шторками — в initSheetGestures()
   (assets/index.ejs).

   Брейкпоинт 540px — тот же, что у .fcm, чтобы обе шторки переключались
   на одной ширине и не расходились на планшетах в портрете.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 540px) {
    .gm { align-items: flex-end; }

    /* Над шторкой — только затемнение, прокручивать под ним нечего: без этого
       свайп мимо карточки увозил страницу под модалкой */
    .gm .gm__backdrop { touch-action: none; }

    /* Селектор dialog.gm .gm__card (0,2,1) специально перебивает ВСЕ
       модификаторы ширины (--editcard/--bulkprice/--share/--portrait/
       --subscription): они заданы одиночным классом с явным width,
       который max-width не перекрывает. */
    dialog.gm .gm__card {
        /* Падинги шторки живут в переменных: к ним привязаны отрицательные
           поля .gm__sticky-actions — иначе бар с кнопками торчит из-под краёв */
        --gm-sheet-pad: 18px;
        /* env() даст 0, пока в <meta viewport> нет viewport-fit=cover —
           это запас на будущее, а не рабочее значение сегодня */
        --gm-sheet-pad-bottom: calc(18px + env(safe-area-inset-bottom));
        width: 100%;
        max-width: 100%;
        margin: 0;
        /* См. .gm выше: считаем от видимой области, а не от «большого» вьюпорта */
        max-height: calc(var(--wc-vvh, 92dvh) * 0.92);
        padding: 8px var(--gm-sheet-pad) var(--gm-sheet-pad-bottom);
        border-radius: 22px 22px 0 0;
        border-bottom: none;
        overscroll-behavior: contain;   /* докрутили список — страница под шторкой не едет */
        animation: gm-sheet-in .34s cubic-bezier(.16, 1, .3, 1);
        transition: transform .22s cubic-bezier(.4, 0, .2, 1),
                    opacity   .22s cubic-bezier(.4, 0, .2, 1);
    }
    /* Пока тянут пальцем — переходов быть не должно, иначе шторка отстаёт.
       Атрибут ставит sheet-drag.js: класс тут не годится — у многих .gm__card
       есть :class-биндинг, и Vue затёр бы чужой класс на ближайшем рендере. */
    dialog.gm .gm__card[data-sheet-dragging] { transition: none; }

    @keyframes gm-sheet-in {
        from { opacity: .5; transform: translateY(100%); }
        to   { opacity: 1;  transform: translateY(0); }
    }

    /* Хват. Псевдоэлемент, а не узел разметки: шторкой становятся все два
       десятка .gm-модалок, и вставлять ручку в каждую — двадцать правок
       с риском разъехаться. Тач по нему всё равно приходит на .gm__card. */
    dialog.gm .gm__card::before {
        content: '';
        display: block;
        width: 38px;
        height: 4px;
        margin: 2px auto 8px;
        border-radius: 2px;
        background: rgba(60, 60, 67, 0.22);
    }
    #dark dialog.gm .gm__card::before { background: rgba(255, 255, 255, 0.22); }

    /* Кнопки прижаты к нижней кромке шторки и видны при любом объёме контента */
    .gm__sticky-actions {
        margin: 16px calc(-1 * var(--gm-sheet-pad)) calc(-1 * var(--gm-sheet-pad-bottom));
        padding: 12px var(--gm-sheet-pad) var(--gm-sheet-pad-bottom);
        bottom: calc(-1 * var(--gm-sheet-pad-bottom));
        gap: 12px;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   Rewards modal (dialog#rewards) — построена поверх Glass-Modal токенов
   и переиспользует .gm__section/.gm__list/.gm__list-row из edit-profile.
   ═══════════════════════════════════════════════════════════════════════ */

/* Баланс — компактная пилюля в topbar рядом с крестиком (не отдельная
   центрированная строка — иначе ломает вертикальный ритм title/subtitle). */
.gm__topbar { gap: 8px; }
.gm__balance-chip {
    display: inline-flex;
    align-items: center;
    height: 30px;
    padding: 0 13px;
    border-radius: 99px;
    background: rgba(120, 120, 128, 0.08);
    font-size: 13px;
    font-weight: 600;
    color: rgb(28, 28, 30);
    flex-shrink: 0;
}
#dark .gm__balance-chip { background: rgba(118, 118, 128, 0.20); color: var(--ink-on-dark); }

/* Skeleton на первую загрузку — тот же shimmer, что у капчи (gm-shimmer). */
.gm__skeleton {
    border-radius: 16px;
    background: linear-gradient(90deg, rgba(120, 120, 128, 0.10) 0%, rgba(120, 120, 128, 0.22) 50%, rgba(120, 120, 128, 0.10) 100%);
    background-size: 200% 100%;
    animation: gm-shimmer 1.6s ease-in-out infinite;
}
.gm__skeleton--hero { height: 96px; }
.gm__skeleton--row { height: 56px; margin-top: 10px; }
#dark .gm__skeleton {
    background: linear-gradient(90deg, rgba(118, 118, 128, 0.14) 0%, rgba(118, 118, 128, 0.28) 50%, rgba(118, 118, 128, 0.14) 100%);
    background-size: 200% 100%;
}

/* Пустое состояние списка (карточек-подписок и т.п.): иконка-чип + заголовок +
   пояснение. .gm__msg — строчная плашка внутри контента, а не состояние экрана
   целиком, поэтому для «здесь пока ничего нет» нужен отдельный центрированный блок. */
.gm__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 36px 20px 30px;
    text-align: center;
}
.gm__empty__icon {
    width: 52px;
    height: 52px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.10);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 8px;
}
.gm__empty__icon img { width: 24px; height: 24px; object-fit: contain; opacity: .45; }
.gm__empty__title {
    font-size: 15.5px;
    font-weight: 600;
    color: rgb(28, 28, 30);
    letter-spacing: -0.2px;
}
.gm__empty__hint {
    font-size: 13px;
    color: rgba(60, 60, 67, 0.6);
    line-height: 1.45;
    max-width: 260px;
}
#dark .gm__empty__icon { background: rgba(255, 255, 255, 0.07); }
#dark .gm__empty__icon img { opacity: .55; }
#dark .gm__empty__title { color: rgba(255, 255, 255, 0.95); }
#dark .gm__empty__hint { color: rgba(235, 235, 245, 0.5); }

/* ─── Ежедневная награда: hero-блок ───
   Не заявка/кнопка со спрятанной суммой, а карточка с крупным акцентом на
   сумме (как Apple Wallet/Fitness+) — сумма и статус читаются с одного взгляда,
   CTA — отдельная строка на всю ширину. В состоянии "получено" карточка гаснет
   и превращается в тихую строку статуса, без кнопки. */
.gm__daily-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border-radius: 16px;
    background: linear-gradient(135deg, rgba(127, 45, 232, 0.14), rgba(127, 45, 232, 0.03));
    border: 0.5px solid rgba(127, 45, 232, 0.20);
    transition: background .25s ease, border-color .25s ease;
}
#dark .gm__daily-card {
    background: linear-gradient(135deg, rgba(179, 129, 255, 0.18), rgba(179, 129, 255, 0.04));
    border-color: rgba(179, 129, 255, 0.24);
}
.gm__daily-card--claimed {
    background: rgba(120, 120, 128, 0.05);
    border-color: rgba(60, 60, 67, 0.10);
}
#dark .gm__daily-card--claimed {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.08);
}
.gm__daily-card__head {
    display: flex;
    align-items: center;
    gap: 14px;
}
.gm__daily-card__icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    flex-shrink: 0;
    background: rgba(127, 45, 232, 0.14);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .25s ease, opacity .25s ease;
}
.gm__daily-card__icon img { width: 24px; height: 24px; }
#dark .gm__daily-card__icon { background: rgba(179, 129, 255, 0.20); }
.gm__daily-card--claimed .gm__daily-card__icon { background: rgba(120, 120, 128, 0.10); opacity: .7; }
#dark .gm__daily-card--claimed .gm__daily-card__icon { background: rgba(255, 255, 255, 0.06); }
.gm__daily-card__body { flex: 1; min-width: 0; }
.gm__daily-card__title {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    font-size: 15px;
    font-weight: 600;
    color: rgb(28, 28, 30);
    letter-spacing: -0.2px;
}
#dark .gm__daily-card__title { color: var(--ink-on-dark); }
.gm__daily-card__desc { font-size: 12.5px; color: rgba(60, 60, 67, 0.65); margin-top: 2px; }
#dark .gm__daily-card__desc { color: rgba(235, 235, 245, 0.55); }
.gm__daily-card__tier { font-size: 11.5px; color: rgba(60, 60, 67, 0.65); text-align: center; }
.gm__daily-card__tier b { font-weight: 700; }
#dark .gm__daily-card__tier { color: rgba(235, 235, 245, 0.55); }
/* Строка статуса подписки под ежедневкой кликабельна (открывает управление),
   но выглядит именно строкой: подписчику здесь не нужна ещё одна кнопка. */
.gm__daily-card__tier--btn {
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 0;
    margin: 0;
    padding: 0;
    width: 100%;
    font-family: inherit;
    cursor: pointer;
    transition: opacity .15s ease;
}
.gm__daily-card__tier--btn:hover { opacity: .7; }

/* Крупная сумма справа от заголовка — главный акцент карточки, а не мелкий текст в кнопке. */
.gm__daily-card__amount {
    flex-shrink: 0;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.5px;
    color: var(--temp-brand-a);
    text-align: right;
    line-height: 1.1;
}
#dark .gm__daily-card__amount { color: var(--accent-orchid); }
.gm__daily-card__amount-base {
    display: block;
    font-size: 11px;
    font-weight: 500;
    opacity: .6;
    text-decoration: line-through;
}

/* Зарезервированное место под будущий баннер (рендерится только если есть контент). */
.gm__reward-banner {
    margin-top: 10px;
    border-radius: 14px;
    border: 1px dashed rgba(127, 45, 232, 0.25);
    padding: 14px;
    min-height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__reward-banner { border-color: rgba(179, 129, 255, 0.3); color: rgba(235, 235, 245, 0.45); }

/* ─── Строки с иконкой слева (квесты + "как потратить") — вариант .gm__list-row ─── */
.gm__list-row--quest {
    grid-template-columns: 40px 1fr auto;
    cursor: default;
}
.gm__list-row--quest .gm__list-row__label,
.gm__list-row--quest .gm__list-row__hint { grid-column: 2; }
.gm__list-row__icon {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: center;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    flex-shrink: 0;
    background: rgba(120, 120, 128, 0.10);
    display: flex;
    align-items: center;
    justify-content: center;
}
.gm__list-row__icon img { width: 18px; height: 18px; object-fit: contain; }
#dark .gm__list-row__icon { background: rgba(255, 255, 255, 0.08); }

/* Свитч внутри quest-строки: базовый .gm__switch стоит в колонке 2 (для строк
   label+hint без иконки слева), а у --quest три колонки — сдвигаем в третью. */
.gm__list-row--quest .gm__switch { grid-column: 3; }

/* ── #sub-card: три события, у каждого галка и своя сумма ────────────────
   Строка не грид, как .gm__list-row--quest, а два этажа: сверху галка с
   подписью, снизу сумма. Сумма относится к своему событию, и ставить её
   в один ряд с подписью значило бы запихнуть в строку две мысли.

   Галка и подпись лежат внутри ОДНОГО <label>, поэтому клик по строке
   включает подписку. Поле суммы намеренно снаружи метки: внутри неё любой
   клик по полю снимал бы галку. */
.gm__sub-list { display: flex; flex-direction: column; gap: 4px; }

.gm__sub-row {
    padding: 12px 14px;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.08);
    box-shadow: inset 0 0 0 1px transparent;
    transition: background .16s, box-shadow .16s;
}
#dark .gm__sub-row { background: rgba(255, 255, 255, 0.04); }

/* Включённое видно с одного взгляда. Три одинаковые плашки не отвечали на
   вопрос «что у меня вообще стоит», а он здесь главный. */
.gm__sub-row.is-on {
    background: color-mix(in srgb, var(--brand) 7%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 20%, transparent);
}
#dark .gm__sub-row.is-on {
    background: color-mix(in srgb, var(--brand) 13%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 30%, transparent);
}
/* Пока идёт запрос, строка глушится целиком — но не прыгает и не мигает */
.gm__sub-row.is-busy { opacity: .72; }

.gm__sub-row__head { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; }
.gm__sub-row__head .gm__check { padding: 0; margin-top: 7px; }
.gm__sub-row__head .gm__list-row__icon { flex: none; }
.gm__sub-row__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }

/* Подтверждение сохранения. Сохранение по уходу с поля без него выглядит как
   «ничего не произошло», а кнопки «Сохранить» здесь нет намеренно. */
.gm__sub-row__saved {
    flex: none;
    align-self: center;
    font-size: 11.5px;
    font-weight: 500;
    color: var(--ok, #34c759);
    white-space: nowrap;
    animation: gmSavedIn .18s ease-out;
}
@keyframes gmSavedIn { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }

/* Сумма — вторым этажом во всю ширину строки, отделённая волоском.
   Отступа под текст события здесь быть не может: модалка .gm узкая (около
   380 px), и вычет 78 px под галку с иконкой оставлял строке меньше трети
   ширины — «объявить в розыск за» переносилось на три строки. */
.gm__sub-row__price {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 11px;
    padding-top: 11px;
    border-top: 1px solid rgba(120, 120, 128, 0.16);
    font-size: 13px;
    color: rgba(60, 60, 67, 0.75);
}
#dark .gm__sub-row__price {
    color: rgba(235, 235, 245, 0.6);
    border-top-color: rgba(255, 255, 255, 0.08);
}
/* Подпись тянется, поле прижимается вправо: у всех трёх строк край один */
.gm__sub-row__prefix { flex: 1 1 auto; min-width: 0; }
.gm__sub-row__price .gm__wanted { flex: none; }
.gm__sub-row__note { flex: 1 1 100%; font-size: 12px; opacity: .7; }

/* Врезка про розыск: это не пояснение мелким шрифтом, а предупреждение о
   том, что деньги спишутся без дополнительного подтверждения. */
.gm__sub-warn {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 12px;
    padding: 12px 14px;
    border-radius: 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--warn-strong);
    background: rgba(255, 179, 64, 0.1);
    box-shadow: inset 0 0 0 1px rgba(178, 94, 0, 0.18);
}
.gm__sub-warn svg { flex: none; margin-top: 1px; }
.gm__sub-warn b { font-weight: 600; }
#dark .gm__sub-warn {
    color: var(--warn);
    box-shadow: inset 0 0 0 1px rgba(255, 179, 64, 0.22);
}

/* Второй этаж (сумма) выезжает, а не подставляется рывком: скачок высоты
   дёргал всю модалку, и на телефоне это читалось как сбой.

   grid-template-rows 0fr → 1fr анимирует ИМЕННО высоту содержимого, без
   магических max-height, которые приходится подбирать под самый длинный
   перевод и которые ломаются, когда подпись переносится на строку больше. */
.gm-tier-enter-active,
.gm-tier-leave-active {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows .2s ease, opacity .2s ease;
}
.gm-tier-enter-active > *,
.gm-tier-leave-active > * { overflow: hidden; min-height: 0; }
.gm-tier-enter-from,
.gm-tier-leave-to { grid-template-rows: 0fr; opacity: 0; }

/* Поле суммы. Знак валюты внутри рамки: в розыске это всегда вайфукойны,
   в порогах — валюта бумажного рынка, и выбирать её человеку не из чего. */
.gm__wanted {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0 10px;
    height: 34px;
    border-radius: 10px;
    background: rgba(120, 120, 128, 0.12);
    box-shadow: inset 0 0 0 1px rgba(120, 120, 128, 0.16);
    transition: box-shadow .14s;
}
.gm__wanted:focus-within { box-shadow: inset 0 0 0 1px var(--brand); }
.gm__wanted__input {
    width: 68px;
    border: none;
    outline: none;
    background: transparent;
    font-family: 'Rubik', sans-serif;
    font-size: 14px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: inherit;
    padding: 0;
}
.gm__wanted__input::placeholder { color: rgba(60, 60, 67, 0.4); }
.gm__wanted__input:disabled { opacity: .5; }
.gm__wanted__cur { font-size: 13px; opacity: .55; flex: none; }

#dark .gm__wanted {
    background: rgba(255, 255, 255, 0.07);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
}
#dark .gm__wanted:focus-within { box-shadow: inset 0 0 0 1px #a58fff; }
#dark .gm__wanted__input::placeholder { color: rgba(235, 235, 245, 0.35); }

/* Вертикальная миниатюра карточки — вариант __icon для строк списка подписок
   (#cards-subs): карта 63×88, квадратный чип её обрежет неправильно. */
.gm__cardsub-thumb {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: center;
    width: 34px;
    height: 47px;
    border-radius: 7px;
    overflow: hidden;
    flex-shrink: 0;
    background: rgba(120, 120, 128, 0.10);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}
.gm__cardsub-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
#dark .gm__cardsub-thumb { background: rgba(255, 255, 255, 0.08); }

.gm__list-row--claimed { opacity: 0.55; }
.gm__list-row--claimed .gm__list-row__icon { filter: grayscale(0.5); }
.gm__list-row__hint--ok { color: var(--temp-ok-vivid-b); font-weight: 600; }

.gm__list-row__action {
    grid-column: 3;
    grid-row: 1 / span 2;
    align-self: center;
    height: 32px;
    padding: 0 14px;
    border: none;
    border-radius: 8px;
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-a);
    font-size: 12.5px;
    font-weight: 600;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background .15s ease;
}
.gm__list-row__action:hover { background: rgba(127, 45, 232, 0.20); }
.gm__list-row__action:disabled { opacity: 0.5; cursor: not-allowed; }
#dark .gm__list-row__action { background: rgba(179, 129, 255, 0.18); color: var(--accent-orchid); }
#dark .gm__list-row__action:hover { background: rgba(179, 129, 255, 0.28); }

.gm__list-row__action--ghost { background: rgba(120, 120, 128, 0.10); color: rgba(60, 60, 67, 0.75); }
.gm__list-row__action--ghost:hover { background: rgba(120, 120, 128, 0.18); }
#dark .gm__list-row__action--ghost { background: rgba(255, 255, 255, 0.06); color: rgba(235, 235, 245, 0.7); }
#dark .gm__list-row__action--ghost:hover { background: rgba(255, 255, 255, 0.1); }

/* Маленькая иконка "внешняя ссылка" после текста — для действий, уводящих из модалки. */
.gm__list-row__action--link::after {
    content: '';
    width: 11px;
    height: 11px;
    margin-left: 6px;
    flex-shrink: 0;
    background: currentColor;
    opacity: .75;
    -webkit-mask: url('/ui/url-icon.svg') no-repeat center / contain;
            mask: url('/ui/url-icon.svg') no-repeat center / contain;
}

/* Готовая иконка (не текстовый "✓") — переиспользует зелёный ph_check-circle,
   тот же оттенок #4DC167, что и completed-состояния в прогрессе наборов. */
.gm__list-row__check {
    grid-column: 3;
    grid-row: 1 / span 2;
    align-self: center;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}
.gm__list-row__check img { width: 100%; height: 100%; display: block; }

/* Раскрывающаяся подсказка ("Как потратить") ВНУТРИ .gm__list — не отдельная
   плавающая карточка со своими скруглениями, а продолжение той же группы:
   плоская, во всю ширину, отделена волосяной линией сверху (как между
   .gm__list-row), нижние углы подхватывает overflow:hidden родителя. */
.gm__list .gm__inline {
    margin: 0;
    border: none;
    border-radius: 0;
    border-top: 0.5px solid rgba(60, 60, 67, 0.14);
    background: rgba(120, 120, 128, 0.04);
    padding: 12px 14px;
}
#dark .gm__list .gm__inline {
    border-top-color: rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.02);
}
.gm__inline__actions .gm__btn { white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════
   Subscription-plans modal (dialog#subscription-plans) — покупка/подарок
   Pro/Premium/Max за shards. Три карточки тиров намеренно решены как
   отдельная тёмная "витрина" внутри модалки — не подчиняются светлой/тёмной
   теме сайта, всегда премиальный тёмный планшет с акцентом тира через
   --tier-accent (проставляется инлайн из tierColor()). У каждой карточки
   своя именная плашка (.gm__sub-tier__plate) с ОДНИМ holo-пресетом —
   Pro/holo, Premium/holo-chrome, Max/holo-texture — без коллизий, потому
   что каждый пресет живёт на своём собственном элементе. ═══════════════ */

/* .gm__card--xwide ограничивает именно WIDTH (min(100%-32px,380px)) —
   max-width там не спасает, потому что width уже ужЕ меньше. Здесь
   переопределяем width целиком, а не только max-width. */
.gm__card--subscription {
    width: min(100% - 32px, 960px);
    max-width: 960px;
}
@media (max-width: 900px) {
    .gm__card--subscription { width: min(100% - 24px, 640px); }
}

/* Иконка валюты (shards) — вместо эмодзи. currentColor + собственный тон по умолчанию. */
.gm__shard-icon { width: 12px; height: 12px; flex-shrink: 0; color: #57C7FF; vertical-align: -1px; }
.gm__shard-icon--lg { width: 20px; height: 20px; }
/* Кристаллы — вторая валюта, живёт рядом с осколками во всех балансах. Цвет
   сиреневый, чтобы отличаться от голубых осколков без чтения подписи.
   Базовые размеры обеих иконок объявлены ЗДЕСЬ, до всех модификаторов вроде
   .gm__wallet-item__ic — иначе одинаковая по специфичности запись ниже по файлу
   перебивала бы размер только у одной из двух валют. */
.gm__crystal-icon { width: 12px; height: 12px; flex-shrink: 0; color: #B98CFF; vertical-align: -1px; }
.gm__crystal-icon--hero { width: 42px; height: 42px; }
/* Вайфукойны — третья валюта. В журнал пока не пишутся (см. описание миграции
   в docs/WAIFUCOINS_LEDGER_MIGRATION.md), но иконка нужна уже сейчас: история
   строит табы по валютам, которые ей вернул сервер. */
.gm__coin-icon { width: 12px; height: 12px; flex-shrink: 0; color: #F5B33C; vertical-align: -1px; }

/* Автопродление — строка внутри карточки текущей подписки (.gm__sub-current).
   Сама тонкая строка статуса, которая была здесь раньше, заменена этой карточкой:
   у подписчика срок и автопродление — главное, а не сноска над витриной. */
/* Строка автопродления: состояние слева, действие справа.
   Включение — обычная текстовая кнопка акцентом тира (один клик). Отключение —
   такая же кнопка, но приглушённая, и ведёт она в #autorenew-off, а не сразу в API:
   тумблер, стоявший здесь раньше, снимался случайным касанием и молча. */
.gm__sub-renew-state {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 12.5px; color: rgba(60, 60, 67, 0.6);
}
.gm__sub-renew-state::before {
    content: ''; width: 6px; height: 6px; border-radius: 50%;
    background: rgba(120, 120, 128, 0.45);
}
.gm__sub-renew-state--on::before { background: var(--ok); }
#dark .gm__sub-renew-state { color: rgba(235, 235, 245, 0.55); }

/* margin-left: auto — страховка на перенос: подписи полные («Отключить автопродление»),
   и на узком экране кнопка уезжает на вторую строку. Без этого она прижималась бы
   там влево и читалась как случайная. */
.gm__sub-renew-act {
    margin-left: auto;
    padding: 4px 0; border: none; background: none; cursor: pointer;
    font-family: inherit; font-size: 12.5px; font-weight: 600;
    color: rgba(60, 60, 67, 0.5);
    transition: color .15s ease, opacity .15s ease;
}
.gm__sub-renew-act:hover:not(:disabled) { color: rgba(60, 60, 67, 0.85); }
.gm__sub-renew-act:disabled { opacity: .5; cursor: not-allowed; }
.gm__sub-renew-act--on,
.gm__sub-renew-act--on:hover:not(:disabled) { color: var(--tier-accent); }
#dark .gm__sub-renew-act { color: rgba(235, 235, 245, 0.5); }
#dark .gm__sub-renew-act:hover:not(:disabled) { color: var(--ink-on-dark); }

/* Что перестанет работать без автопродления (#autorenew-off). Не «фичи», а потери —
   поэтому маркер минусом, а не галочкой: галочка читалась бы как «вы это получите».
   Группы по тирам: старший тир включает младшие, и человек должен видеть весь объём,
   а не отсылку «все привилегии Pro».
   max-height + своя прокрутка: у Max больше двух десятков пунктов, и без потолка
   кнопки решения уезжали бы за нижнюю границу экрана. overscroll-behavior — чтобы
   докрутив список до конца, не начать прокручивать саму карточку модалки. */
.gm__renew-loss {
    margin: 16px 0 12px;
    padding: 12px 14px;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.07);
    text-align: left;
    max-height: 42vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}
#dark .gm__renew-loss { background: rgba(255, 255, 255, 0.05); }
.gm__renew-loss__group + .gm__renew-loss__group { margin-top: 14px; }
.gm__renew-loss__tier {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--tier-accent);
    margin-bottom: 7px;
}
.gm__renew-loss ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
}
.gm__renew-loss li {
    position: relative;
    padding-left: 22px;
    font-size: 13.5px;
    line-height: 1.35;
    color: rgba(60, 60, 67, 0.75);
}
#dark .gm__renew-loss li { color: rgba(235, 235, 245, 0.7); }
.gm__renew-loss li::before {
    content: '';
    position: absolute;
    left: 4px; top: .62em;
    width: 10px; height: 1.5px; border-radius: 1px;
    background: currentColor;
    opacity: .45;
}
/* Отключение — второе по важности действие: без заливки и без цвета опасности.
   Красная кнопка превратила бы отмену подписки в драму, а она обратима. */
.gm__renew-loss__confirm { margin-top: 2px; }

/* ─── Слайдер периода — свободный выбор месяцев, скидка по порогу ─── */
.gm__sub-slider-block { margin-top: 8px; padding: 4px 2px 0; }
.gm__sub-slider-block__head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.gm__sub-slider-block__months {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", system-ui, sans-serif;
    font-size: 19px;
    font-weight: 700;
}
#dark .gm__sub-slider-block__months { color: var(--ink-on-dark); }
.gm__sub-slider-block__discount {
    font-size: 13px;
    font-weight: 700;
    color: var(--tier-accent);
    border: 1px solid color-mix(in srgb, var(--tier-accent) 45%, transparent);
    border-radius: 8px;
    padding: 2px 9px;
    white-space: nowrap;
}
/* «картой» в бейдже — скидка за срок действует только на рублёвую оплату, и умолчать
   об этом нельзя: осколками тот же период стоит номинал. */
.gm__sub-slider-block__discount i { font-style: normal; font-weight: 600; font-size: 11px; opacity: .75; }

/* Ряд слайдера, ряд меток и лесенка скидок используют ОДИНАКОВУЮ grid-раскладку
   (22px/1fr/22px) — средняя колонка у всех одной ширины, поэтому проценты-позиции
   меток и ступеней совпадают с реальным треком слайдера, а не со всей строкой
   (которая шире из-за степпера). */
.gm__sub-slider-row, .gm__sub-slider-ticks-row, .gm__sub-discount-row {
    display: grid;
    grid-template-columns: 22px 1fr 22px;
    gap: 8px;
    align-items: center;
}

/* ─── Лесенка скидок ───
   Мини-график «срок → скидка» над слайдером. Ступени растут слева направо, так что
   «дольше = выгоднее» видно до того, как человек тронет ползунок: раньше выгода
   существовала только цифрой рядом с текущим сроком, и на старте (1 месяц, скидки
   нет) её не было видно вовсе. Подпись висит НАД своей ступенью (bottom: 100%),
   поэтому строка подписей поднимается вместе со ступенями и не пересекается с ними
   ни на одной высоте. */
.gm__sub-discount-hint {
    font-size: 12px;
    line-height: 1.35;
    color: rgba(60, 60, 67, 0.5);
    margin-bottom: 10px;
}
#dark .gm__sub-discount-hint { color: rgba(235, 235, 245, 0.45); }

/* Верхний отступ ряда — место для подписей: они висят НАД ступенями и выходят за
   пределы контейнера. Padding здесь не годится: у абсолютных ступеней содержащий
   блок — padding-box, и «100 %» стало бы выше самих ступеней. */
.gm__sub-discount-row { margin: 22px 0 10px; align-items: end; }
.gm__sub-discount {
    position: relative;
    height: 40px;          /* высота ступеней: % в --band-h считается от неё */
}
.gm__sub-discount__band {
    position: absolute;
    bottom: 0;
    height: var(--band-h, 20%);
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.gm__sub-discount__bar {
    position: absolute;
    inset: 0 1.5px;
    border-radius: 5px 5px 3px 3px;
    background: rgba(120, 120, 128, 0.16);
    transition: background .2s ease;
}
#dark .gm__sub-discount__bar { background: rgba(255, 255, 255, 0.10); }
.gm__sub-discount__band:hover .gm__sub-discount__bar { background: color-mix(in srgb, var(--tier-accent) 30%, transparent); }
.gm__sub-discount__band--on .gm__sub-discount__bar,
#dark .gm__sub-discount__band--on .gm__sub-discount__bar { background: var(--tier-accent); }

.gm__sub-discount__label {
    position: absolute;
    bottom: 100%;
    left: 0; right: 0;
    padding-bottom: 3px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .2px;
    text-align: center;
    color: rgba(60, 60, 67, 0.4);
    white-space: nowrap;
    transition: color .2s ease;
}
#dark .gm__sub-discount__label { color: rgba(235, 235, 245, 0.4); }
.gm__sub-discount__band--on .gm__sub-discount__label,
#dark .gm__sub-discount__band--on .gm__sub-discount__label { color: var(--tier-accent); }

.gm__sub-stepper {
    width: 22px; height: 22px;
    border-radius: 50%;
    border: 1px solid rgba(120, 120, 128, 0.22);
    background: rgba(120, 120, 128, 0.08);
    color: rgba(60, 60, 67, 0.75);
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}
.gm__sub-stepper:hover { background: color-mix(in srgb, var(--tier-accent) 18%, transparent); border-color: color-mix(in srgb, var(--tier-accent) 45%, transparent); }
.gm__sub-stepper:disabled { opacity: .35; cursor: not-allowed; }
#dark .gm__sub-stepper { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); color: rgba(235, 235, 245, 0.8); }

.gm__sub-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--tier-accent) var(--sub-slider-fill, 0%), rgba(120, 120, 128, 0.18) var(--sub-slider-fill, 0%));
    outline: none;
    cursor: pointer;
}
#dark .gm__sub-slider { background: linear-gradient(90deg, var(--tier-accent) var(--sub-slider-fill, 0%), rgba(255, 255, 255, 0.14) var(--sub-slider-fill, 0%)); }
.gm__sub-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--ink-on-dark);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 0 0 1px color-mix(in srgb, var(--tier-accent) 55%, transparent);
    cursor: pointer;
    transition: transform .12s ease;
}
.gm__sub-slider::-webkit-slider-thumb:active { transform: scale(1.15); }
.gm__sub-slider::-moz-range-thumb {
    width: 20px; height: 20px;
    border: none;
    border-radius: 50%;
    background: var(--ink-on-dark);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 0 0 1px color-mix(in srgb, var(--tier-accent) 55%, transparent);
    cursor: pointer;
}
.gm__sub-slider::-moz-range-track { background: transparent; }

.gm__sub-slider-ticks-row { margin-top: 4px; }
.gm__sub-slider__ticks { position: relative; height: 18px; }
.gm__sub-slider__tick {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    font-size: 11px;
    color: rgba(60, 60, 67, 0.4);
    cursor: pointer;
    padding: 2px 4px;
}
#dark .gm__sub-slider__tick { color: rgba(235, 235, 245, 0.35); }
.gm__sub-slider__tick--active { color: var(--tier-accent); font-weight: 700; }

/* ─── Три карточки тиров ─── */
.gm__sub-tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 18px; }
@media (max-width: 820px) {
    .gm__sub-tiers { grid-template-columns: 1fr; }
}
.gm__sub-tier {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 20px;
    border-radius: 18px;
    background: linear-gradient(165deg, #1b1b21 0%, #101013 100%);
    border: 1px solid rgba(255, 255, 255, 0.08);
    cursor: pointer;
    transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.gm__sub-tier:hover { transform: translateY(-2px); }
.gm__sub-tier--active {
    border-color: color-mix(in srgb, var(--tier-accent) 65%, transparent);
    box-shadow: 0 16px 32px -18px color-mix(in srgb, var(--tier-accent) 55%, transparent);
}

/* "Рекомендуем" — классический якорь на средний тир */
.gm__sub-tier__badge {
    position: absolute;
    top: -10px; left: 20px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .4px;
    text-transform: uppercase;
    color: #14141a;
    background: linear-gradient(120deg, #F5D889, #D4AF37);
    padding: 3px 10px;
    border-radius: 7px;
    box-shadow: 0 4px 10px -2px rgba(212, 175, 55, 0.55);
}

/* Именная плашка тира — свой единственный holo-пресет (Pro/Premium/Max) */
.gm__sub-tier__plate {
    position: relative;
    border-radius: 14px;
    padding: 16px 16px 14px;
    color: var(--ink-on-dark);
    background:
        radial-gradient(130% 160% at 15% -20%, color-mix(in srgb, var(--tier-accent) 30%, transparent), transparent 55%),
        linear-gradient(160deg, #1e1e24 0%, #0c0c0f 100%);
    border: 1px solid color-mix(in srgb, var(--tier-accent) 42%, transparent);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    overflow: hidden;
}
.gm__sub-tier__plate-bar {
    position: absolute !important;
    z-index: 3;
    top: 0; left: 12px; right: 12px;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--tier-accent), transparent);
    opacity: .9;
}
.gm__sub-tier__plate-body { position: relative; z-index: 2; }
.gm__sub-tier__plate-name {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", system-ui, sans-serif;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .6px;
    color: rgba(255, 255, 255, 0.85);
}
.gm__sub-tier__plate-price { display: flex; align-items: baseline; gap: 6px; margin-top: 8px; font-size: 28px; font-weight: 700; letter-spacing: -.3px; }
/* Цена картой под ценой в осколках. Зачёркнутый номинал и итог — отдельными
   элементами с зазором: без gap «900 ₽ 810 ₽» слипались в нечитаемое «900810 ₽». */
.gm__sub-tier__plate-sub {
    display: flex; align-items: baseline; justify-content: start; gap: 6px;
    font-size: 11.5px; color: rgba(235, 235, 245, 0.45); margin-top: 3px;
}
.gm__sub-tier__approx { opacity: .7; }
.gm__sub-tier__plate-sub s { opacity: .55; text-decoration-thickness: 1px; }
/* Итоговая цена светлее зачёркнутой — она главная в этой строке. */
.gm__sub-tier__plate-sub b { font-weight: 600; font-size: 12.5px; color: rgba(235, 235, 245, 0.85); }
/* Фактический процент скидки — акцентом тира, чтобы читался как выгода. */
.gm__sub-tier__off {
    font-size: 10.5px; font-weight: 700; letter-spacing: .2px;
    padding: 2px 6px; border-radius: 999px;
    color: var(--tier-accent); background: rgba(255, 255, 255, 0.08);
}

.gm__sub-tier__savings { margin-top: 8px; font-size: 11.5px; font-weight: 600; color: var(--tier-accent); text-align: center; }

.gm__sub-tier__select {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    margin-top: auto;
    padding-top: 14px;
    border-top: 0.5px solid rgba(255, 255, 255, 0.08);
    font-size: 12.5px;
    font-weight: 600;
    color: rgba(235, 235, 245, 0.55);
}
.gm__sub-tier__plate, .gm__sub-tier__savings, .gm__sub-tier__perks { flex-shrink: 0; }
.gm__sub-tier--active .gm__sub-tier__select { color: var(--ink-on-dark); }
.gm__sub-tier__radio {
    width: 14px; height: 14px;
    border-radius: 50%;
    border: 1.5px solid rgba(255, 255, 255, 0.25);
    position: relative;
    flex-shrink: 0;
}
.gm__sub-tier--active .gm__sub-tier__radio { border-color: var(--tier-accent); }
.gm__sub-tier--active .gm__sub-tier__radio::after {
    content: '';
    position: absolute; inset: 2.5px;
    border-radius: 50%;
    background: var(--tier-accent);
}

.gm__sub-tier__perks { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.gm__sub-tier__perks li {
    font-size: 12px;
    line-height: 1.35;
    color: rgba(235, 235, 245, 0.68);
    padding-left: 15px;
    position: relative;
}
.gm__sub-tier__perks li::before {
    content: '';
    position: absolute;
    left: 0; top: 5px;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--tier-accent);
    opacity: .8;
}

/* ─── Подарок + оформление — в ряд на десктопе, друг под другом на мобильном ─── */
.gm__sub-gift { margin-top: 18px; }
.gm__sub-action-row {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
@media (min-width: 640px) {
    .gm__sub-action-row { flex-direction: row; align-items: center; }
}
.gm__sub-gift__toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    flex-shrink: 0;
    white-space: nowrap;
    flex-grow: 1;
}
/* Две кнопки оплаты (осколками и картой) делят строку поровну. Тумблер «подарить»
   больше не растягивается: раньше он забирал место, и кнопка с длинной подписью
   («Оформить Premium — 540 шардов») сжималась в узкий столбик с переносами. */
.gm__sub-submit-btn,
.gm__sub-money-btn {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    line-height: 1.25;
    padding-left: 12px;
    padding-right: 12px;
}
@media (min-width: 640px) {
    .gm__sub-gift__toggle { flex-grow: 0; }
}

/* Обе кнопки — авто-высота вместо фиксированных 50px из .gm__btn: подпись с
   зачёркнутой ценой переносится на вторую строку и в 50px не помещается. */
.gm__sub-money-btn,
.gm__sub-submit-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-wrap: wrap;
    min-height: 46px;
    padding-top: 8px;
    padding-bottom: 8px;
}
.gm__sub-money-btn s { opacity: .55; font-weight: 400; text-decoration-thickness: 1px; }
.gm__sub-money-btn b { font-weight: 600; }

/* Акцент — на оплате картой: только на ней действует скидка за срок, и только она
   работает с пустым балансом. Осколки — стеклянная кнопка рядом: рядом с яркой
   основной две заливки конкурировали бы за внимание.
   Исключение — подарок: там карта недоступна, кнопка осколков остаётся
   единственной и получает .gm__btn--primary из шаблона (правило ниже её не трогает). */
.gm__sub-submit-btn:not(.gm__btn--primary) {
    background: rgba(120, 120, 128, 0.12);
    color: rgba(28, 28, 30, 0.92);
    border: 1px solid rgba(0, 0, 0, 0.06);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
}
.gm__sub-submit-btn:not(.gm__btn--primary):not(:disabled):hover { background: rgba(120, 120, 128, 0.18); }

#dark .gm__sub-submit-btn:not(.gm__btn--primary) {
    background: rgba(255, 255, 255, 0.10);
    color: var(--ink-on-dark);
    border-color: rgba(255, 255, 255, 0.14);
}
#dark .gm__sub-submit-btn:not(.gm__btn--primary):not(:disabled):hover { background: rgba(255, 255, 255, 0.16); }

/* ─── Кошелёк — строка балансов и действий над содержимым модалки ───
   Балансы — данные (крупная цифра + подпись валюты), действия — две пилюли
   справа. Раньше балансы были пилюлями в topbar рядом с крестиком: мелко,
   не читалось как кнопка и визуально спорило с заголовком. */
.gm__wallet {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.07);
    border: 0.5px solid rgba(60, 60, 67, 0.1);
}
#dark .gm__wallet { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.09); }

.gm__wallet__bals { display: flex; align-items: center; gap: 22px; min-width: 0; }
.gm__wallet__acts { display: flex; align-items: center; gap: 8px; }

.gm__wallet-item {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
    font-family: inherit;
    text-align: left;
}
.gm__wallet-item--btn { cursor: pointer; transition: opacity .15s ease; }
.gm__wallet-item--btn:hover { opacity: .65; }
.gm__wallet-item__ic { width: 17px; height: 17px; }
.gm__wallet-item__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gm__wallet-item__num {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 19px;
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.4px;
    font-variant-numeric: tabular-nums;
}
.gm__wallet-item__label { font-size: 11px; color: rgba(60, 60, 67, 0.55); }
#dark .gm__wallet-item__label { color: rgba(235, 235, 245, 0.45); }

.gm__wallet-act {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 13px;
    border: 0;
    border-radius: 99px;
    background: rgba(120, 120, 128, 0.14);
    color: rgb(28, 28, 30);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s ease;
}
.gm__wallet-act:hover { background: rgba(120, 120, 128, 0.22); }
#dark .gm__wallet-act { background: rgba(255, 255, 255, 0.1); color: var(--ink-on-dark); }
#dark .gm__wallet-act:hover { background: rgba(255, 255, 255, 0.17); }

/* На узком экране кошелёк складывается в два ряда во всю ширину — те же отступы
   со всех сторон, без «прижатого к краю» варианта. */
@media (max-width: 560px) {
    .gm__wallet { flex-direction: column; align-items: stretch; gap: 12px; }
    .gm__wallet__bals { justify-content: space-between; gap: 12px; }
    .gm__wallet__acts { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
    .gm__wallet-act { justify-content: center; }
}

/* ═══ История операций с валютой ═══
   Первая версия была одним потоком строк на все валюты сразу: «+3 осколка»
   стояло рядом с «−120 вайфукойнов», подвести итог за период было нельзя в
   принципе, а листалась история кнопкой «Показать ещё». Здесь валюта вынесена
   в табы и стала главной осью экрана — всё ниже (итоги, фильтры, список,
   пагинация) относится ровно к одной валюте. ═══════════════════════════════ */

/* ─── Валюта ─── */
.gm__hist__cur {
    display: flex; gap: 4px; padding: 3px;
    background: rgba(120, 120, 128, 0.12);
    border-radius: 12px;
}
#dark .gm__hist__cur { background: rgba(255, 255, 255, 0.06); }
.gm__hist__cur-tab {
    flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px;
    height: 38px; padding: 0 12px; border: 0; background: transparent;
    border-radius: 9px; cursor: pointer;
    font: inherit; font-size: 13.5px; font-weight: 500;
    color: rgba(60, 60, 67, 0.75);
    transition: background .2s cubic-bezier(.16,1,.3,1), color .2s, box-shadow .2s;
}
.gm__hist__cur-tab:hover { color: rgb(28, 28, 30); }
.gm__hist__cur-tab--on {
    background: var(--ink-on-dark); color: rgb(28, 28, 30); font-weight: 600;
    box-shadow: 0 2px 6px rgba(0,0,0,.1), 0 0 0 0.5px rgba(0,0,0,.05);
}
#dark .gm__hist__cur-tab { color: rgba(235, 235, 245, 0.7); }
#dark .gm__hist__cur-tab:hover { color: var(--ink-on-dark); }
#dark .gm__hist__cur-tab--on { background: rgba(99, 99, 102, 0.95); color: var(--ink-on-dark); box-shadow: 0 2px 6px rgba(0,0,0,.3); }
.gm__hist__cur-tab .gm__shard-icon,
.gm__hist__cur-tab .gm__crystal-icon,
.gm__hist__cur-tab .gm__coin-icon { width: 15px; height: 15px; flex: none; }
.gm__hist__cur-tab__n { font-variant-numeric: tabular-nums; opacity: .55; font-weight: 500; }

/* ─── Итоги за выбранный период ───
   Три числа, которые раньше приходилось считать глазами по списку. */
.gm__hist__sum {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 1px; margin-top: 12px;
    background: rgba(120, 120, 128, 0.14);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 14px; overflow: hidden;
}
#dark .gm__hist__sum { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.08); }
.gm__hist__sum-cell {
    display: flex; flex-direction: column; gap: 3px;
    padding: 12px 14px; background: rgba(252, 252, 253, 0.6);
}
#dark .gm__hist__sum-cell { background: rgba(30, 30, 34, 0.5); }
.gm__hist__sum-cap { font-size: 11.5px; color: rgba(60, 60, 67, 0.55); letter-spacing: -.1px; }
#dark .gm__hist__sum-cap { color: rgba(235, 235, 245, 0.45); }
.gm__hist__sum-val {
    display: flex; align-items: center; gap: 5px;
    font-size: 19px; font-weight: 600; letter-spacing: -.4px;
    font-variant-numeric: tabular-nums;
}
.gm__hist__sum-val .gm__shard-icon,
.gm__hist__sum-val .gm__crystal-icon,
.gm__hist__sum-val .gm__coin-icon { width: 14px; height: 14px; opacity: .85; }
.gm__hist__sum-val--in { color: var(--ok-strong); }
.gm__hist__sum-val--out { color: rgba(60, 60, 67, 0.85); }
#dark .gm__hist__sum-val--in { color: var(--ok-mint); }
#dark .gm__hist__sum-val--out { color: rgba(235, 235, 245, 0.85); }

/* ─── Панель фильтров ───
   У каждого контрола своя подпись: без неё «Все» и «Сначала новые» рядом
   читаются как два одинаковых серых прямоугольника. */
.gm__hist__filters {
    display: grid; grid-template-columns: 1.1fr 1fr 1fr; gap: 10px;
    margin-top: 14px;
}
.gm__hist__filter { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.gm__hist__filter-cap {
    font-size: 11px; font-weight: 500; letter-spacing: -.1px;
    color: rgba(60, 60, 67, 0.5); padding-left: 2px;
}
#dark .gm__hist__filter-cap { color: rgba(235, 235, 245, 0.4); }
/* Компактный селект: .gm__field--select — это поле формы в 50px с плавающим
   лейблом, в панели фильтров три таких читаются как форма ввода, а не как
   переключатели вида. */
.gm__hist__select { position: relative; }
.gm__hist__select select {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 38px; padding: 0 32px 0 12px;
    font: inherit; font-size: 13.5px; font-weight: 500; letter-spacing: -.2px;
    color: rgb(28, 28, 30);
    background: rgba(120, 120, 128, 0.1);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 10px; cursor: pointer;
    transition: background .18s, border-color .18s;
}
.gm__hist__select select:hover { background: rgba(120, 120, 128, 0.16); }
.gm__hist__select select:focus { outline: none; border-color: rgba(127, 45, 232, 0.5); }
.gm__hist__select::after {
    content: ''; position: absolute; right: 12px; top: 50%; pointer-events: none;
    width: 7px; height: 7px; margin-top: -5px;
    border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
    transform: rotate(45deg); color: rgba(60, 60, 67, 0.4);
}
#dark .gm__hist__select select {
    color: rgba(255,255,255,.95);
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.08);
}
#dark .gm__hist__select select:hover { background: rgba(255, 255, 255, 0.12); }
#dark .gm__hist__select::after { color: rgba(235, 235, 245, 0.4); }
.gm__hist__select select option { background: var(--ink-on-dark); color: #1c1c1e; }
#dark .gm__hist__select select option { background: #2b2b30; color: var(--ink-on-dark); }

/* display: grid/flex у блоков ниже перебивает браузерное [hidden] { display:none } */
.gm__hist__range[hidden], .gm__hist__applied[hidden], .gm__hist__pager[hidden] { display: none; }

/* Свой диапазон дат — отдельной строкой, появляется только когда выбран. */
.gm__hist__range {
    display: grid; grid-template-columns: 1fr auto 1fr auto; align-items: end;
    gap: 10px; margin-top: 10px;
}
.gm__hist__range-dash { padding-bottom: 11px; color: rgba(60,60,67,.4); }
#dark .gm__hist__range-dash { color: rgba(235,235,245,.35); }
.gm__hist__date-input {
    width: 100%; height: 38px; padding: 0 12px; box-sizing: border-box;
    font: inherit; font-size: 13.5px; font-weight: 500;
    color: rgb(28, 28, 30);
    background: rgba(120, 120, 128, 0.1);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 10px;
}
.gm__hist__date-input:focus { outline: none; border-color: rgba(127, 45, 232, 0.5); }
#dark .gm__hist__date-input {
    color: rgba(255,255,255,.95); background: rgba(255,255,255,.07);
    border-color: rgba(255,255,255,.08); color-scheme: dark;
}
.gm__hist__range-apply { height: 38px; background: rgba(120,120,128,.14); color: inherit; }
#dark .gm__hist__range-apply { background: rgba(255,255,255,.1); }

/* Активные фильтры + сброс. Строка появляется, только когда есть что сбрасывать. */
.gm__hist__applied {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
    margin-top: 12px; font-size: 12.5px; color: rgba(60,60,67,.6);
}
#dark .gm__hist__applied { color: rgba(235,235,245,.5); }
.gm__hist__reset {
    margin-left: auto; border: 0; background: transparent; cursor: pointer;
    font: inherit; font-size: 12.5px; font-weight: 500; color: var(--temp-brand-b); padding: 4px 6px;
    border-radius: 8px; transition: background .15s;
}
.gm__hist__reset:hover { background: rgba(127,45,232,.08); }
#dark .gm__hist__reset { color: var(--accent-orchid); }
#dark .gm__hist__reset:hover { background: rgba(198,140,255,.12); }

/* ─── Список ───
   Строки сгруппированы по дню: дата ушла в заголовок группы (там же — итог
   дня), в строке осталось время. Раньше полная дата дублировалась в каждой
   строке и занимала место, которое теперь отдано сути операции. */
.gm__hist { display: flex; flex-direction: column; margin-top: 6px; }

/* Заголовок дня БЕЗ собственного фона и без position: sticky. Прилипающему
   заголовку нужна заливка, чтобы прятать уезжающие под него строки, — а любая
   заливка поверх полупрозрачной .gm__card складывается с ней в двойной слой и
   на светлой теме выходит заметно белее карточки. */
.gm__hist__day {
    display: flex; align-items: baseline; gap: 10px;
    padding: 16px 2px 8px;
}
.gm__hist__day-name {
    font-size: 12.5px; font-weight: 600; letter-spacing: -.1px;
    color: rgba(60, 60, 67, 0.75);
}
#dark .gm__hist__day-name { color: rgba(235, 235, 245, 0.65); }
.gm__hist__day-net {
    margin-left: auto; font-size: 12px; font-variant-numeric: tabular-nums;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__hist__day-net { color: rgba(235, 235, 245, 0.38); }

/* Операции одного дня — один залитый блок со скруглением по краям (первая и
   последняя строки скругляются самим контейнером через overflow: hidden). */
.gm__hist__group {
    background: var(--ink-on-dark);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 14px;
    overflow: hidden;
}
#dark .gm__hist__group { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.06); }

.gm__hist__row {
    position: relative;
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) 58px 132px 18px;
    align-items: center; column-gap: 12px;
    width: 100%; padding: 11px 12px; box-sizing: border-box;
    border: 0; background: transparent; text-align: left; font: inherit; color: inherit;
    cursor: pointer;
    transition: background .15s ease;
}
.gm__hist__row:hover { background: rgba(120, 120, 128, 0.07); }
#dark .gm__hist__row:hover { background: rgba(255, 255, 255, 0.05); }
/* Разделитель — во всю ширину блока: любой боковой отступ на скруглённом
   контейнере читается как съехавшая набок линия. :not(:first-child) вместо
   соседства строк — между строками может стоять раскрытая карточка операции. */
.gm__hist__row:not(:first-child)::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0;
    height: 0.5px; background: rgba(60, 60, 67, 0.12);
}
#dark .gm__hist__row:not(:first-child)::before { background: rgba(255, 255, 255, 0.08); }

/* Иконка группы: плитка, а не точка. Точку 10×10 нельзя было опознать без
   легенды, а легенды в модалке нет и быть не должно. */
.gm__hist__ico {
    width: 34px; height: 34px; border-radius: 11px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: rgba(120, 120, 128, 0.14); color: #8E8E93;
}
.gm__hist__ico svg { width: 17px; height: 17px; }
#dark .gm__hist__ico { background: rgba(255,255,255,.08); }
.gm__hist__ico--topup        { background: rgba(52, 199, 89, .14);  color: var(--ok-strong); }
.gm__hist__ico--subscription { background: rgba(167, 139, 250, .18); color: #7C4DFF; }
.gm__hist__ico--purchase     { background: rgba(255, 159, 10, .16);  color: #C77700; }
.gm__hist__ico--reward       { background: rgba(100, 210, 255, .2);  color: #0A7EA4; }
.gm__hist__ico--craft        { background: rgba(34, 211, 238, .18);  color: #0E7490; }
.gm__hist__ico--refund       { background: rgba(255, 105, 97, .16);  color: var(--danger-strong); }
.gm__hist__ico--donation     { background: rgba(224, 68, 124, .16);  color: #C0356A; }
.gm__hist__ico--admin        { background: rgba(245, 179, 60, .18);  color: #B57500; }
#dark .gm__hist__ico--topup        { background: rgba(52, 199, 89, .18);  color: var(--ok-mint); }
#dark .gm__hist__ico--subscription { background: rgba(167, 139, 250, .2); color: #C4B0FF; }
#dark .gm__hist__ico--purchase     { background: rgba(255, 159, 10, .18); color: #FFC46B; }
#dark .gm__hist__ico--reward       { background: rgba(100, 210, 255, .18); color: #8FE1FF; }
#dark .gm__hist__ico--craft        { background: rgba(34, 211, 238, .18); color: #6FE3F5; }
#dark .gm__hist__ico--refund       { background: rgba(255, 105, 97, .18); color: #FF9C96; }
#dark .gm__hist__ico--donation     { background: rgba(224, 68, 124, .2);  color: #FF8CB4; }
#dark .gm__hist__ico--admin        { background: rgba(245, 179, 60, .2);  color: #F7CE84; }

.gm__hist__body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gm__hist__title {
    font-size: 14px; font-weight: 550; letter-spacing: -.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gm__hist__sub {
    font-size: 12.5px; color: rgba(60, 60, 67, 0.6);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dark .gm__hist__sub { color: rgba(235, 235, 245, 0.5); }
/* Время в строке есть в двух местах: отдельной колонкой (широкий экран, где
   колонка выравнивает все строки в столбик) и внутри подписи (узкий экран,
   где на отдельную колонку нет ширины). Видимо всегда ровно одно из двух. */
.gm__hist__time-inline { display: none; font-style: normal; }
/* Строка без подписи: на широком экране второй строки просто нет (иначе она
   съедала бы высоту пустотой), на узком в ней остаётся время. */
.gm__hist__sub--timeonly { display: none; }

.gm__hist__time {
    font-size: 12.5px; font-variant-numeric: tabular-nums;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__hist__time { color: rgba(235, 235, 245, 0.38); }

.gm__hist__amt { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; white-space: nowrap; }
.gm__hist__amt b {
    display: flex; align-items: center; gap: 4px;
    font-size: 14.5px; font-weight: 620; font-variant-numeric: tabular-nums; letter-spacing: -.2px;
}
.gm__hist__amt b .gm__shard-icon,
.gm__hist__amt b .gm__crystal-icon,
.gm__hist__amt b .gm__coin-icon { width: 12px; height: 12px; opacity: .8; }
.gm__hist__amt small { font-size: 11px; font-variant-numeric: tabular-nums; color: rgba(60, 60, 67, 0.42); }
#dark .gm__hist__amt small { color: rgba(235, 235, 245, 0.35); }
.gm__hist__plus { color: var(--ok-strong); }
#dark .gm__hist__plus { color: var(--ok-mint); }

.gm__hist__chev { color: rgba(60,60,67,.28); transition: transform .22s cubic-bezier(.16,1,.3,1); }
#dark .gm__hist__chev { color: rgba(235,235,245,.25); }
.gm__hist__chev svg { width: 14px; height: 14px; display: block; }
.gm__hist__row--open .gm__hist__chev { transform: rotate(90deg); }
/* Открытая строка остаётся светлой: подсветить её так же, как карточку под
   ней, значило бы слить их в одно пятно. */
.gm__hist__row--open { background: rgba(120, 120, 128, 0.04); }
#dark .gm__hist__row--open { background: rgba(255, 255, 255, 0.03); }

/* Раскрытая карточка операции — то, с чем человек идёт в поддержку: номер
   операции, номер заказа, кто провёл. Раньше этих данных не было нигде, кроме
   админки. Не вложенная плитка, а полоса во всю ширину блока: собственные
   скругления и отступы внутри уже скруглённого контейнера дают двойную рамку. */
.gm__hist__detail {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px 18px; padding: 12px;
    background: rgba(120, 120, 128, 0.13);
    animation: gm-hist-detail .28s cubic-bezier(.16, 1, .3, 1);
}
#dark .gm__hist__detail { background: rgba(0, 0, 0, 0.22); }
@keyframes gm-hist-detail { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.gm__hist__detail-k { font-size: 11px; color: rgba(60,60,67,.5); margin-bottom: 2px; }
#dark .gm__hist__detail-k { color: rgba(235,235,245,.4); }
.gm__hist__detail-v { font-size: 12.5px; font-weight: 500; overflow-wrap: anywhere; }
.gm__hist__detail-v--mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* ─── Пагинация ─── */
.gm__hist__pager {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin-top: 16px; padding-top: 14px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.08);
}
#dark .gm__hist__pager { border-top-color: rgba(255, 255, 255, 0.1); }
.gm__hist__pager-count { font-size: 12.5px; color: rgba(60,60,67,.55); font-variant-numeric: tabular-nums; }
#dark .gm__hist__pager-count { color: rgba(235,235,245,.45); }
.gm__hist__pages { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.gm__hist__page {
    min-width: 32px; height: 32px; padding: 0 8px; border: 0;
    display: flex; align-items: center; justify-content: center;
    background: transparent; border-radius: 9px; cursor: pointer;
    font: inherit; font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums;
    color: rgba(60, 60, 67, 0.75);
    transition: background .15s, color .15s;
}
.gm__hist__page:hover:not(:disabled) { background: rgba(120,120,128,.14); color: rgb(28,28,30); }
.gm__hist__page:disabled { opacity: .3; cursor: default; }
.gm__hist__page--on { background: rgba(127, 45, 232, 0.1); color: var(--temp-brand-b); font-weight: 620; }
.gm__hist__page svg { width: 14px; height: 14px; }
.gm__hist__gap { padding: 0 2px; color: rgba(60,60,67,.35); font-size: 13px; }
#dark .gm__hist__page { color: rgba(235,235,245,.7); }
#dark .gm__hist__page:hover:not(:disabled) { background: rgba(255,255,255,.1); color: var(--ink-on-dark); }
#dark .gm__hist__page--on { background: rgba(198,140,255,.16); color: var(--accent-orchid); }
#dark .gm__hist__gap { color: rgba(235,235,245,.3); }

/* ─── Пустое состояние ─── */
.gm__hist__empty {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 44px 20px; text-align: center;
}
.gm__hist__empty-ic {
    width: 46px; height: 46px; border-radius: 15px; margin-bottom: 6px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(120,120,128,.12); color: rgba(60,60,67,.45);
}
#dark .gm__hist__empty-ic { background: rgba(255,255,255,.07); color: rgba(235,235,245,.4); }
.gm__hist__empty-ic svg { width: 22px; height: 22px; }
.gm__hist__empty-t { font-size: 14.5px; font-weight: 600; }
.gm__hist__empty-s { font-size: 13px; color: rgba(60,60,67,.55); max-width: 320px; line-height: 1.45; }
#dark .gm__hist__empty-s { color: rgba(235,235,245,.45); }

/* ─── Скелет загрузки ─── */
.gm__hist__skel { display: flex; align-items: center; gap: 12px; padding: 13px 10px; }
.gm__hist__skel i {
    display: block; height: 10px; border-radius: 5px;
    background: linear-gradient(90deg, rgba(120,120,128,.12) 25%, rgba(120,120,128,.2) 37%, rgba(120,120,128,.12) 63%);
    background-size: 400% 100%; animation: gm-hist-shimmer 1.3s ease infinite;
}
#dark .gm__hist__skel i {
    background: linear-gradient(90deg, rgba(255,255,255,.06) 25%, rgba(255,255,255,.12) 37%, rgba(255,255,255,.06) 63%);
    background-size: 400% 100%;
}
@keyframes gm-hist-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ─── Мобильная раскладка ───
   Та же геометрия, что на десктопе (одинаковые отступы со всех сторон,
   одинаковый радиус по всем углам) — просто время уезжает под подзаголовок,
   а колонка суммы сужается. */
@media (max-width: 720px) {
    /* Валюта: иконка над названием — на узком экране три подписи в строку
       не помещаются, а обрезать «Вайфукойны» многоточием нельзя.
       Баланс при этом раньше просто прятался, и на телефоне у табов не
       оставалось ни одной цифры; теперь он лежит пилюлей в правом верхнем
       углу — своей строкой грида, а не абсолютом поверх, иначе у длинных
       чисел пилюля наезжала бы на иконку. */
    .gm__hist__cur { display: grid; grid-template-columns: repeat(3, 1fr); padding: 4px; gap: 3px; }
    .gm__hist__cur-tab {
        display: grid;
        grid-template-rows: 16px 19px auto;
        justify-items: center;
        align-items: center;
        row-gap: 3px;
        height: auto;
        min-width: 0;
        padding: 4px 6px 8px;
        font-size: 12px;
    }
    .gm__hist__cur-tab .gm__shard-icon,
    .gm__hist__cur-tab .gm__crystal-icon,
    .gm__hist__cur-tab .gm__coin-icon { grid-row: 2; width: 19px; height: 19px; }
    .gm__hist__cur-tab__t {
        grid-row: 3;
        max-width: 100%;
        font-size: 11.5px;
        letter-spacing: -.1px;
        line-height: 1.15;
    }
    .gm__hist__cur-tab__n {
        grid-row: 1;
        justify-self: end;
        max-width: 100%;
        padding: 0 6px;
        border-radius: 7px;
        background: rgba(120, 120, 128, 0.16);
        color: rgba(60, 60, 67, 0.6);
        font-size: 10.5px;
        line-height: 16px;
        opacity: 1;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    #dark .gm__hist__cur-tab__n { background: rgba(255, 255, 255, 0.12); color: rgba(235, 235, 245, 0.6); }
    .gm__hist__cur-tab--on .gm__hist__cur-tab__n { background: rgba(127, 45, 232, 0.12); color: var(--temp-brand-b); }
    #dark .gm__hist__cur-tab--on .gm__hist__cur-tab__n { background: rgba(198, 140, 255, 0.18); color: var(--accent-orchid); }

    /* В «Аналитике» фильтров всего два, и правило «первый — во всю ширину»
       ниже разгоняло бы их на две строки с полупустой второй. Колонки при этом
       неравные: «Последние 90 дней» в половину ширины не помещается и обрезается
       селектом без многоточия, а «По неделям» коротко. */
    .gm__hist__filters.gm__hist__filters--an { grid-template-columns: 1.35fr 1fr; }
    .gm__hist__filters.gm__hist__filters--an > :first-child { grid-column: auto; }

    /* Баланс — во всю ширину, приход и расход — парой: они сравниваются друг
       с другом, а баланс ни с чем. */
    .gm__hist__sum { grid-template-columns: 1fr 1fr; }
    .gm__hist__sum-cell:first-child { grid-column: 1 / -1; }
    .gm__hist__sum-val { font-size: 17px; }

    .gm__hist__filters { grid-template-columns: 1fr 1fr; }
    .gm__hist__filters > :first-child { grid-column: 1 / -1; }
    .gm__hist__range { grid-template-columns: 1fr; }
    .gm__hist__range-dash { display: none; }

    /* Время уходит в строку подписи: отдельная колонка съедала бы треть ширины. */
    .gm__hist__row { grid-template-columns: 34px minmax(0, 1fr) auto; column-gap: 10px; padding: 10px 8px; }
    .gm__hist__time { display: none; }
    .gm__hist__time-inline { display: inline; }
    .gm__hist__sub--timeonly { display: block; }
    .gm__hist__chev { display: none; }
    /* Колонка в 150px оставляла карточку одноколоночной на пол-экрана в высоту. */
    .gm__hist__detail { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); }

    .gm__hist__pager { row-gap: 12px; }
    .gm__hist__pager-count { width: 100%; }
    .gm__hist__pages { margin-left: 0; width: 100%; justify-content: space-between; }
}

/* ═══ Аналитика истории операций (.gm__an__*) ═══
   Второй вид того же экрана: не «что было 14 августа», а «куда уходят
   деньги». Своих цветов и радиусов не заводит — всё из токенов .gm-модалок,
   зелёный дохода тот же, что у .gm__hist__plus.
   Разметка — modules/modals.ejs, данные — /api/user/currencies/analytics. */

/* ─── Табы валют: подпись обёрнута в span ──────────────────────────────────
   На десктопе таб остаётся строкой «иконка + название + число» из index.css —
   там ширины хватает. Обёртка нужна только чтобы длинное название можно было
   обрезать многоточием: голый текстовый узел этому не поддаётся.
   Колоночный вид таба — ниже, в @media для телефона. */
.gm__hist__cur-tab__t {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ─── Сводка за период ─────────────────────────────────────────────────── */
.gm__an__hero {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1px;
    background: rgba(0, 0, 0, 0.07);
    border-radius: 16px;
    overflow: hidden;
}
#dark .gm__an__hero { background: rgba(255, 255, 255, 0.09); }
.gm__an__hero-cell {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 13px 15px 14px;
    background: rgba(120, 120, 128, 0.07);
}
#dark .gm__an__hero-cell { background: rgba(255, 255, 255, 0.05); }
.gm__an__hero-cap {
    font-size: 11.5px;
    letter-spacing: -.1px;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__an__hero-cap { color: rgba(235, 235, 245, 0.45); }
.gm__an__hero-val {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 22px;
    font-weight: 650;
    letter-spacing: -0.6px;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.gm__an__hero-val .gm__coin-icon,
.gm__an__hero-val .gm__shard-icon,
.gm__an__hero-val .gm__crystal-icon { width: 15px; height: 15px; opacity: .85; }
.gm__an__hero-val--in  { color: var(--ok-strong); }
#dark .gm__an__hero-val--in { color: var(--ok-bright); }
.gm__an__hero-val--out { color: rgba(60, 60, 67, 0.9); }
#dark .gm__an__hero-val--out { color: rgba(235, 235, 245, 0.8); }
.gm__an__hero-val--neg { color: #C7361F; }
#dark .gm__an__hero-val--neg { color: #FF6E5B; }
/* Подпись под числом: «сколько это в день» и «сколько операций» — иначе цифра
   висит без масштаба и сравнивать периоды нечем. */
.gm__an__hero-sub {
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.42);
    font-variant-numeric: tabular-nums;
}
#dark .gm__an__hero-sub { color: rgba(235, 235, 245, 0.35); }

/* ─── График потока ────────────────────────────────────────────────────── */
.gm__an__chart {
    border: 0.5px solid rgba(0, 0, 0, 0.08);
    border-radius: 16px;
    padding: 14px 16px 10px;
}
#dark .gm__an__chart { border-color: rgba(255, 255, 255, 0.1); }
.gm__an__chart-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 12px;
}
.gm__an__chart-title { font-size: 13px; font-weight: 600; letter-spacing: -.2px; }
.gm__an__legend {
    display: flex;
    gap: 12px;
    margin-left: auto;
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__an__legend { color: rgba(235, 235, 245, 0.45); }
.gm__an__legend i {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 3px;
    margin-right: 5px;
    vertical-align: 0;
}
.gm__an__legend i.in  { background: var(--temp-ok-vivid-b); }
.gm__an__legend i.out { background: rgba(120, 120, 128, 0.45); }
.gm__an__legend i.bal { background: var(--temp-brand-b); }
#dark .gm__an__legend i.out { background: rgba(255, 255, 255, 0.32); }
#dark .gm__an__legend i.bal { background: var(--accent-orchid); }
.gm__an__chart svg { display: block; width: 100%; height: 140px; overflow: visible; }
.gm__an__bar-in  { fill: var(--temp-ok-vivid-b); }
.gm__an__bar-out { fill: rgba(120, 120, 128, 0.42); }
#dark .gm__an__bar-out { fill: rgba(255, 255, 255, 0.3); }
.gm__an__bar-g { cursor: pointer; }
.gm__an__bar-g:hover .gm__an__bar-in  { fill: var(--ok-strong); }
.gm__an__bar-g:hover .gm__an__bar-out { fill: rgba(120, 120, 128, 0.7); }
.gm__an__zero { stroke: rgba(0, 0, 0, 0.12); stroke-width: 1; }
#dark .gm__an__zero { stroke: rgba(255, 255, 255, 0.16); }
.gm__an__tick {
    font-size: 10px;
    fill: rgba(60, 60, 67, 0.42);
    font-variant-numeric: tabular-nums;
}
#dark .gm__an__tick { fill: rgba(235, 235, 245, 0.35); }
/* Линия накопленного баланса поверх столбцов: столбцы отвечают на «сколько
   пришло и ушло за неделю», линия — на «к чему это в итоге привело». */
.gm__an__line {
    fill: none;
    stroke: var(--temp-brand-b);
    stroke-width: 1.6;
    stroke-linejoin: round;
    stroke-linecap: round;
}
#dark .gm__an__line { stroke: var(--accent-orchid); }

/* ─── Две колонки разбивок ─────────────────────────────────────────────── */
.gm__an__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
.gm__an__col { display: flex; flex-direction: column; gap: 8px; }

/* ─── Строка разбивки (категория / игрок) ──────────────────────────────── */
.gm__an__list {
    display: flex;
    flex-direction: column;
    border: 0.5px solid rgba(0, 0, 0, 0.08);
    border-radius: 14px;
    overflow: hidden;
}
#dark .gm__an__list { border-color: rgba(255, 255, 255, 0.1); }
.gm__an__item {
    position: relative;
    text-decoration: none;
    display: grid;
    grid-template-columns: 30px 1fr auto 14px;
    align-items: center;
    gap: 11px;
    padding: 10px 12px;
    background: none;
    border: none;
    width: 100%;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: background .15s ease;
}
.gm__an__item + .gm__an__item { border-top: 0.5px solid rgba(0, 0, 0, 0.06); }
#dark .gm__an__item + .gm__an__item { border-top-color: rgba(255, 255, 255, 0.07); }
.gm__an__item:hover { background: rgba(120, 120, 128, 0.07); }
#dark .gm__an__item:hover { background: rgba(255, 255, 255, 0.05); }
/* Доля категории — заливкой самой строки, а не отдельной полоской под текстом:
   полоска добавляла бы третий ярус в строку, а понять «эта втрое больше той»
   можно и по длине подложки. */
.gm__an__item::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--share, 0%);
    background: rgba(120, 120, 128, 0.1);
    pointer-events: none;
}
#dark .gm__an__item::before { background: rgba(255, 255, 255, 0.07); }
.gm__an__item--in::before { background: rgba(52, 199, 89, 0.13); }
#dark .gm__an__item--in::before { background: rgba(52, 199, 89, 0.16); }
.gm__an__item > * { position: relative; }
.gm__an__ico {
    width: 30px; height: 30px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.7);
    flex: none;
}
#dark .gm__an__ico { background: rgba(255, 255, 255, 0.1); color: rgba(235, 235, 245, 0.7); }
.gm__an__ico svg { width: 16px; height: 16px; }
.gm__an__ico--topup        { background: rgba(52, 199, 89, .14);  color: var(--ok-strong); }
.gm__an__ico--subscription { background: rgba(167, 139, 250, .18); color: #7C4DFF; }
.gm__an__ico--purchase     { background: rgba(255, 159, 10, .16);  color: #C77700; }
.gm__an__ico--reward       { background: rgba(100, 210, 255, .2);  color: #0A7EA4; }
.gm__an__ico--craft        { background: rgba(34, 211, 238, .18);  color: #0E7490; }
.gm__an__ico--refund       { background: rgba(255, 105, 97, .16);  color: var(--danger-strong); }
.gm__an__ico--donation     { background: rgba(224, 68, 124, .16);  color: #C0356A; }
.gm__an__ico--admin        { background: rgba(245, 179, 60, .18);  color: #B57500; }
.gm__an__body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gm__an__name {
    font-size: 13.5px;
    font-weight: 550;
    letter-spacing: -.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gm__an__meta {
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.5);
    font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dark .gm__an__meta { color: rgba(235, 235, 245, 0.42); }
.gm__an__val { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.gm__an__val b {
    font-size: 13.5px;
    font-weight: 620;
    letter-spacing: -.2px;
    font-variant-numeric: tabular-nums;
    display: flex; align-items: center; gap: 4px;
}
.gm__an__val b .gm__coin-icon, .gm__an__val b .gm__shard-icon { width: 12px; height: 12px; opacity: .8; }
.gm__an__val small {
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: rgba(60, 60, 67, 0.42);
}
#dark .gm__an__val small { color: rgba(235, 235, 245, 0.35); }
.gm__an__val--in b { color: var(--ok-strong); }
#dark .gm__an__val--in b { color: var(--ok-bright); }
.gm__an__chev { color: rgba(60, 60, 67, 0.28); display: flex; }
#dark .gm__an__chev { color: rgba(235, 235, 245, 0.28); }
.gm__an__chev svg { width: 14px; height: 14px; }

/* ─── Разбивка по наборам ──────────────────────────────────────────────── */
/* Четыре колонки цифр в строке .gm__an__item не помещаются, поэтому у наборов
   своя сетка: код набора чипом, три суммы столбцами и итог справа. */
.gm__an__sets { display: flex; flex-direction: column; }
.gm__an__sets-head {
    display: grid;
    grid-template-columns: 1fr 104px 104px 104px 14px;
    gap: 10px;
    padding: 0 12px 7px;
    font-size: 11px;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__an__sets-head { color: rgba(235, 235, 245, 0.38); }
.gm__an__sort {
    background: none; border: none; padding: 0; font: inherit; color: inherit;
    font-size: 11px; letter-spacing: .02em; text-transform: uppercase;
    cursor: pointer; text-align: right;
    display: flex; align-items: center; justify-content: flex-end; gap: 3px;
}
.gm__an__sort:hover { color: rgba(60, 60, 67, 0.8); }
#dark .gm__an__sort:hover { color: rgba(235, 235, 245, 0.75); }
.gm__an__sort--on { color: var(--temp-brand-b); }
#dark .gm__an__sort--on { color: var(--accent-orchid); }
.gm__an__sort svg { width: 11px; height: 11px; }
.gm__an__set {
    position: relative;
    text-decoration: none;
    display: grid;
    grid-template-columns: 1fr 104px 104px 104px 14px;
    gap: 10px;
    align-items: center;
    padding: 9px 12px;
    background: none; border: none; width: 100%;
    font: inherit; color: inherit; text-align: left; cursor: pointer;
    -webkit-appearance: none; appearance: none;
    border-radius: 10px;
    transition: background .15s ease;
}
.gm__an__set:hover { background: rgba(120, 120, 128, 0.08); }
#dark .gm__an__set:hover { background: rgba(255, 255, 255, 0.06); }
.gm__an__set + .gm__an__set::after {
    content: "";
    position: absolute;
    left: 12px; right: 12px; top: 0;
    height: 0.5px;
    background: rgba(0, 0, 0, 0.07);
}
#dark .gm__an__set + .gm__an__set::after { background: rgba(255, 255, 255, 0.08); }
.gm__an__set-name { display: flex; align-items: center; gap: 9px; min-width: 0; }
.gm__an__set-title { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.gm__an__num {
    text-align: right;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.2px;
    color: rgba(60, 60, 67, 0.85);
}
#dark .gm__an__num { color: rgba(235, 235, 245, 0.8); }
.gm__an__num--muted { color: rgba(60, 60, 67, 0.35); }
#dark .gm__an__num--muted { color: rgba(235, 235, 245, 0.28); }
.gm__an__num--in { color: var(--ok-strong); }
#dark .gm__an__num--in { color: var(--ok-bright); }
.gm__an__num--net { font-weight: 620; }
.gm__an__num--net.pos { color: var(--ok-strong); }
#dark .gm__an__num--net.pos { color: var(--ok-bright); }
.gm__an__num--net.neg { color: #C7361F; }
#dark .gm__an__num--net.neg { color: #FF6E5B; }
/* Итоговая строка таблицы наборов: те же колонки, но без ховера и с полужирным. */
.gm__an__set--total {
    cursor: default;
    margin-top: 4px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.1);
    border-radius: 0;
    padding-top: 11px;
    font-weight: 600;
}
#dark .gm__an__set--total { border-top-color: rgba(255, 255, 255, 0.12); }
.gm__an__set--total:hover { background: none; }
.gm__an__set--total::after { display: none; }

/* Кнопка «Показать все наборы» — плоская строка во всю ширину списка. */
.gm__an__more {
    background: none; border: none; width: 100%;
    padding: 9px; margin-top: 2px;
    font: inherit; font-size: 12.5px; font-weight: 550;
    color: var(--temp-brand-b); cursor: pointer; border-radius: 10px;
    transition: background .15s ease;
}
#dark .gm__an__more { color: var(--accent-orchid); }
.gm__an__more:hover { background: rgba(127, 45, 232, 0.08); }

/* ─── Плитки показателей ───────────────────────────────────────────────── */
.gm__an__tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.gm__an__tile {
    display: flex; flex-direction: column; gap: 4px;
    padding: 11px 13px 12px;
    border-radius: 12px;
    background: rgba(120, 120, 128, 0.08);
    min-width: 0;
}
#dark .gm__an__tile { background: rgba(255, 255, 255, 0.05); }
.gm__an__tile-cap { font-size: 11.5px; color: rgba(60, 60, 67, 0.55); }
#dark .gm__an__tile-cap { color: rgba(235, 235, 245, 0.45); }
.gm__an__tile-val {
    font-size: 17px; font-weight: 620; letter-spacing: -.4px;
    font-variant-numeric: tabular-nums;
    display: flex; align-items: center; gap: 4px;
}
.gm__an__tile-val .gm__coin-icon { width: 13px; height: 13px; opacity: .8; }
/* Название набора в плитке: одной строкой с многоточием — полные названия
   вроде «Naruto Shippuden · Wave 10» в четверть ширины не помещаются. */
.gm__an__tile-val--name {
    display: block;
    font-size: 15px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gm__an__tile-sub {
    font-size: 11.5px; color: rgba(60, 60, 67, 0.42);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#dark .gm__an__tile-sub { color: rgba(235, 235, 245, 0.35); }

/* Пояснение под секцией. */
.gm__an__note {
    font-size: 11.5px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.45);
    padding: 0 2px;
}
#dark .gm__an__note { color: rgba(235, 235, 245, 0.38); }

/* ─── Телефон ──────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
    /* В «Аналитике» фильтров всего два, и правило «первый — во всю ширину»
       (index.css, @media 540) разгоняет их на две строки с полупустой второй.
       Здесь они укладываются в одну. */
    .gm__hist__filters--an > :first-child { grid-column: auto; }

    .gm__an__cols { grid-template-columns: 1fr; }
    .gm__an__tiles { grid-template-columns: 1fr 1fr; }
    /* Три плитки в колонку заняли бы пол-экрана до первого графика, поэтому на
       телефоне сводка становится списком «подпись слева — число справа». */
    .gm__an__hero { grid-template-columns: 1fr; }
    /* Число занимает обе строки и центрируется по ним: выровненное по базовой
       линии заголовка, оно висело у верхнего края двухстрочной ячейки. */
    .gm__an__hero-cell {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-rows: auto auto;
        align-items: center;
        gap: 2px 10px;
        padding: 11px 14px 12px;
    }
    .gm__an__hero-cap { grid-area: 1 / 1; }
    .gm__an__hero-sub { grid-area: 2 / 1; }
    .gm__an__hero-val {
        grid-area: 1 / 2 / span 2 / auto;
        align-self: center;
        justify-self: end;
        font-size: 19px;
    }
    .gm__an__chart-head { flex-wrap: wrap; }
    .gm__an__legend { margin-left: 0; width: 100%; }
    /* На узком экране три колонки цифр не помещаются: набор становится строкой
       «код + название» сверху и тремя подписанными числами снизу. */
    .gm__an__sets-head { display: none; }
    .gm__an__set {
        grid-template-columns: 1fr 1fr 1fr;
        grid-template-areas: "name name name" "c1 c2 c3";
        row-gap: 7px;
    }
    .gm__an__set-name { grid-area: name; }
    .gm__an__num--c1 { grid-area: c1; }
    .gm__an__num--c2 { grid-area: c2; }
    .gm__an__num--c3 { grid-area: c3; }
    .gm__an__set .gm__an__chev { display: none; }
    .gm__an__num { text-align: left; }
    .gm__an__num::before {
        content: attr(data-cap);
        display: block;
        font-size: 10.5px;
        text-transform: uppercase;
        letter-spacing: .02em;
        color: rgba(60, 60, 67, 0.4);
        margin-bottom: 1px;
    }
    #dark .gm__an__num::before { color: rgba(235, 235, 245, 0.32); }
}

/* ─── Пополнение осколков ───
   Карточка пакета несёт иерархию «сколько → из чего сложилось → цена». Прежние
   плитки «53 💠 / 500 ₽» не отвечали на главный вопрос экрана — чем один пакет
   выгоднее другого, — и подарочные осколки в них не были видны вообще. */
.gm__topup-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    gap: 10px;
}
.gm__topup-pack {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 18px 12px 14px;
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: linear-gradient(165deg, #1b1b21 0%, #101013 100%);
    color: var(--ink-on-dark);
    font-family: inherit;
    cursor: pointer;
    transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.gm__topup-pack:hover { transform: translateY(-2px); border-color: rgba(255, 255, 255, 0.2); }
.gm__topup-pack:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.gm__topup-pack--hero {
    border-color: rgba(87, 199, 255, 0.65);
    box-shadow: 0 14px 30px -18px rgba(87, 199, 255, 0.55);
}
/* Плашка выгоды — на границе карточки, как «Рекомендуем» у тиров */
.gm__topup-pack__tag {
    position: absolute;
    top: -9px; left: 50%;
    transform: translateX(-50%);
    max-width: calc(100% - 16px);
    padding: 3px 9px;
    border-radius: 7px;
    background: linear-gradient(120deg, #9BE1FF, #57C7FF);
    color: #08131a;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .3px;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gm__topup-pack__ic { width: 20px; height: 20px; }
.gm__topup-pack__num {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.6px;
    font-variant-numeric: tabular-nums;
}
.gm__topup-pack__bonus {
    font-size: 11px;
    font-weight: 600;
    color: #6FD3FF;
    text-align: center;
}
.gm__topup-pack__bonus--plain { color: rgba(235, 235, 245, 0.4); font-weight: 400; }
.gm__topup-pack__price {
    margin-top: 8px;
    padding: 5px 12px;
    border-radius: 99px;
    background: rgba(255, 255, 255, 0.1);
    font-size: 12.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.gm__topup-pack:hover .gm__topup-pack__price { background: rgba(255, 255, 255, 0.16); }

/* Своя сумма — ровно столько, сколько не хватает. Поле, живая цена и кнопка
   в одну строку; на узком экране — друг под другом, поле на всю ширину. */
.gm__topup-custom {
    padding: 14px 16px 16px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.07);
    border: 0.5px solid rgba(60, 60, 67, 0.1);
}
#dark .gm__topup-custom { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.09); }
.gm__topup-custom__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}
.gm__topup-custom__title { font-size: 14.5px; font-weight: 600; }
.gm__topup-custom__hint { font-size: 11.5px; color: rgba(60, 60, 67, 0.5); white-space: nowrap; }
#dark .gm__topup-custom__hint { color: rgba(235, 235, 245, 0.42); }
.gm__topup-custom__row { display: flex; align-items: center; gap: 12px; }
.gm__topup-custom__field { flex: 1 1 auto; min-width: 0; margin: 0; }
/* Стрелки number-инпута тут только мешают: шаг 1 при диапазоне до 10 000. */
.gm__topup-custom__field input::-webkit-outer-spin-button,
.gm__topup-custom__field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.gm__topup-custom__field input[type=number] { -moz-appearance: textfield; appearance: textfield; }
.gm__topup-custom__sum {
    flex: 0 0 auto;
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: rgba(60, 60, 67, 0.7);
    white-space: nowrap;
}
#dark .gm__topup-custom__sum { color: rgba(235, 235, 245, 0.6); }
/* Высота ровно как у поля (.gm__field input — 52px): кнопка стоит с ним в одной
   строке, и разница в 12px из .gm__btn--compact читалась бы как съехавшая вёрстка. */
.gm__topup-custom__btn { flex: 0 0 auto; width: auto; height: 52px; padding: 0 22px; }
@media (max-width: 520px) {
    .gm__topup-custom__row { flex-wrap: wrap; }
    .gm__topup-custom__field { flex-basis: 100%; }
    .gm__topup-custom__sum { flex: 1 1 auto; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Пожертвование (dialog#donate). Собрана из готовых gm-блоков: .gm__seg,
   .gm__field, .gm__list-row + .gm__switch, .gm__btn. Своё — только вводный
   абзац, ряд пресетов суммы и экран благодарности.
   ═══════════════════════════════════════════════════════════════════════ */
.gm__donate-lead {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.65);
}
#dark .gm__donate-lead { color: rgba(235, 235, 245, 0.55); }

/* Подпись минимальной суммы стоит вплотную под полем, поэтому свой отступ, а не
   gap от .gm__view (14px разрывал бы связь поля и его подписи). */
.gm__donate-hint {
    margin-top: -8px;
    padding: 0 4px;
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__donate-hint { color: rgba(235, 235, 245, 0.42); }

.gm__donate-thanks { text-align: center; padding: 8px 0 4px; }
.gm__donate-thanks__ic {
    width: 66px;
    height: 66px;
    margin: 0 auto 6px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #E0447C;
    background: rgba(224, 68, 124, 0.12);
}
#dark .gm__donate-thanks__ic { color: #FF7FA8; background: rgba(255, 127, 168, 0.16); }

.gm__crystal-hero {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin: 4px 0 14px;
}
.gm__crystal-hero__num {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 34px;
    font-weight: 700;
    letter-spacing: -1px;
    font-variant-numeric: tabular-nums;
}

/* ─── Окно «О карточке»: очки редкости и айди ───────────────────────────
   Одно окно — один акцент. Акцент здесь ровно один: число ОР. Всё остальное
   (надзаголовок, ступень, айди, дата) держится серым, иначе окно распадается
   на пять одинаково громких блоков — так первая версия и выглядела.

   Плашки под числом нет намеренно: заливка превращала показатель в баннер.
   Цвет несёт число само, а фон остаётся фоном модалки.

   Ступеней шесть, лестница (серый → зелёный → синий → приглушённый красный →
   золото → живой пурпур): цвет читается раньше цифры. Пороги
   200/1000/5000/20000/200000 делят каталог на 42% / 28% / 16% / 10% / 3.3% /
   0.41%, поэтому и золото, и тем более пурпур — действительно редкость. Считает сервер (DUST.rarityPoints), ступень — rpTierOf
   в assets/index.ejs. Свои токены не нужны: цвета те же, что у состояний
   выше по файлу (ok-strong/ok-mint, brand-a/orchid). */
.gm__rp {
    position: relative;
    margin-top: 16px;
    text-align: center;
    padding: 2px 0 4px;
}
/* Надзаголовок объясняет единицу один раз и снимает необходимость в подписи
   «ОР» у числа и в отдельной строке-пояснении под ним. */
.gm__rp__eyebrow {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.9px;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__rp__eyebrow { color: rgba(235, 235, 245, 0.4); }

/* Вес 800, а не 700. Rubik стоит в стопке ТРЕТЬИМ, сразу за эпловскими, и
   это не украшение: у системного Segoe UI на Windows выше Bold ничего нет,
   восьмисотка там просто откатывалась к семисотке и число оставалось таким
   же. У Rubik (шрифт всего сайта, уже загружен) ExtraBold есть, 700 у него
   нет вовсе — то есть на Windows выбор между 600 и 800, и 800 это ровно то,
   что нужно крупному числу. На Apple по-прежнему берётся SF Pro Display, у
   него своя настоящая восьмисотка. */
.gm__rp__num {
    margin-top: 5px;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", 'Rubik', system-ui, sans-serif;
    font-size: 46px;
    /* 600, и это ЕДИНСТВЕННЫЙ способ сделать число легче.
       У Rubik в проекте (static/fonts/rubik.css) подключены веса 300, 400,
       500, 600 и 800 — семисотого НЕТ. По правилу подбора CSS запрос 700
       сначала ищет веса ВЫШЕ целевого, то есть берёт те же 800: «700» и
       «800» на Windows рисуются одинаково, и правка выглядит как будто не
       применилась. На macOS и iOS стек начинается с SF Pro Display, там 600
       это Semibold — тоже честный шаг вниз с Heavy. */
    font-weight: 600;
    line-height: 1.02;
    letter-spacing: -2.2px;
    font-variant-numeric: tabular-nums;
}
/* Место под число, пока оно грузится. Высота — сумма строк числа и подписи
   (46px × 1.02 + 5px отступ + строка ступени), чтобы при подстановке готового
   значения окно не меняло высоту ни на пиксель. */
.gm__rp__skel {
    height: 68px;
    width: 172px;
    margin: 5px auto 0;
    border-radius: 14px;
}

.gm__rp__cap {
    margin-top: 5px;
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: -0.1px;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__rp__cap { color: rgba(235, 235, 245, 0.5); }

/* t1 (обычная) цвета не получает: число идёт основным текстом. Красить
   «обычное» незачем, а лишний оттенок спорил бы с остальными четырьмя. */
.gm__rp--t2 .gm__rp__num { color: #1e8f47; }
#dark .gm__rp--t2 .gm__rp__num { color: var(--ok-mint); }

.gm__rp--t3 .gm__rp__num { color: #0a6fd8; }
#dark .gm__rp--t3 .gm__rp__num { color: #6ab7ff; }

/* Красная, а не фиолетовая. Фиолетовый ушёл мифической (ниже), и держать
   два фиолетовых через ступень было нельзя: рядом они не различаются, а
   «очень редкая» и «мифическая» — это разница в двадцать раз по ОР.

   Не --danger-strong и не --danger, хотя начиналось с них: чистый сигнальный
   красный на своей ступени читался как ошибка, а не как редкость. Насыщенность
   снята со 100% до 64% на светлой и с 90% до 69% на тёмной — цвет тот же,
   крика меньше. Контраст при этом даже вырос: 5.59:1 и 5.57:1 против 5.38 и
   4.89 у токенов. Литералы здесь в порядке вещей — у второй и третьей
   ступени они тоже свои. */
.gm__rp--t4 .gm__rp__num { color: #c42b3a; }
#dark .gm__rp--t4 .gm__rp__num { color: #e5727d; }

/* СВЕЧЕНИЯ ПОД ЧИСЛОМ БОЛЬШЕ НЕТ. У t4, t5 и t6 здесь стоял мягкий радиальный
   ореол прямо за цифрой — пока он был единственным цветом в окне, он держал
   ступень. Рядом с верхней аурой (.gm__card--aura) он стал лишним: два пятна
   одного цвета на одном экране, причём ближнее к числу — самое грубое, обычный
   радиальный градиент без фигур и зерна. Не возвращать: цвет ступени теперь
   несёт шапка, а число держится собственной заливкой. */

/* Легенда — единственное место с градиентом по самому числу: у неё и должно
   быть ощущение трофея. */
.gm__rp--t5 .gm__rp__num {
    background-image: linear-gradient(115deg, #b8860b 0%, #e0a419 44%, #c2760a 100%);
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
}
#dark .gm__rp--t5 .gm__rp__num {
    background-image: linear-gradient(115deg, #f0c35a 0%, #ffe9a8 46%, #ffb347 100%);
}

/* ─── Шестая ступень: мифическая ────────────────────────────────────────
   Легендарная (от 20 000 ОР) накрывала диапазон в триста раз — от карточки
   за 10 657 ₩ до карточки за 3 600 000 ₩. Верхние 0.41% каталога (69 карточек
   в восьми сериях, от 200 000 ОР) выделены отдельно: пороги и разбор —
   в modules/dust.js.

   ФИОЛЕТОВЫЙ ЗДЕСЬ ТЕПЕРЬ ТОЛЬКО ОДИН. Четвёртая ступень была фиолетовой и
   стала красной ровно поэтому: два фиолетовых через ступень на глаз не
   различаются, а разница между ними — двадцать раз по ОР.
   Сверх цвета мифическую отличает поведение: градиент через пурпур ЖИВОЙ
   (gm-shimmer) и по глифам идёт полупрозрачный контур. Отдельной полоски
   света сверху НЕТ — почему, разобрано ниже по файлу, у самого правила.
   Ступенью выше золота читается именно движение: неподвижных трофеев у нас
   уже два.

   Контраст посчитан по всем стопам, а не на глаз. На белом заливка держит
   от 4.0:1 (самый светлый стоп #d926e0) до 11.2:1; на тёмном — от 4.40:1
   (#b054ff) до 5.66:1. Тонирующих слоёв поверх заливки НЕТ: всё, что
   светлее, лежит по контуру, шириной в доли пикселя. Ниже этих значений не
   опускать — 4.4:1 это ещё AA для обычного текста, дальше запаса нет.

   Свой @keyframes не заводится: gm-shimmer выше по файлу двигает ровно
   background-position, а больше здесь ничего и не нужно. */
.gm__rp--t6 .gm__rp__num {
    /* Заливка — ТОЛЬКО цветной градиент, одним слоем. Тонирующий слой поверх
       него (светлее сверху, темнее снизу) пробовали — он красит глиф ВНУТРИ
       по всей высоте, и вместо объёма получается выцветшая цифра. Объём
       здесь делают две вещи снаружи заливки: контур и блик, оба ниже. */
    background-image: linear-gradient(115deg, #6d28d9 0%, #b013c9 26%, #d926e0 50%, #8b2ff5 74%, #6d28d9 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
    animation: gm-shimmer 4.5s linear infinite;
    /* Контур по самим глифам, полупрозрачный: -webkit-text-stroke рисуется
       поверх подрезанного фона (заливка-то прозрачная) и обводит ровно форму
       цифры, не залезая внутрь.

       0.2 — значение автора. Выше 0.4 белое начинает съедать край глифа, и
       цифра читается бледнее, чем совсем без контура; на 0.2 это фаска,
       которую видно, но за которую взгляд не цепляется. Обе темы держат
       одно число: контур такой тонкий, что разводить их незачем. */
    -webkit-text-stroke: 0.5px rgba(255, 255, 255, 0.2);
    filter: drop-shadow(0 0 9px rgba(192, 38, 211, 0.18));
}
/* ТЁМНАЯ ТЕМА: ГЛУБИНА, А НЕ СВЕТЛОТА. Первые стопы были #ffc2fb и #cfbcff —
   по насыщенности честные 100%, но светлота под 80%, и глаз читает такое как
   выцветшую пастель, а не как пурпур. На тёмном фоне цвет набирает силу,
   когда его ПРИГЛУШАЮТ по светлоте, а не когда высветляют: контраст там и
   так берётся фоном. Стопы опущены с 7.4…11.4:1 до 4.4…5.7:1 — это всё ещё
   выше AA для обычного текста, а число здесь 46px. */
#dark .gm__rp--t6 .gm__rp__num {
    background-image: linear-gradient(115deg, #9f66ff 0%, #c14dff 26%, #e05cff 50%, #b054ff 74%, #9f66ff 100%);
    -webkit-text-stroke: 0.5px rgba(255, 255, 255, 0.2);
    filter: drop-shadow(0 0 10px rgba(198, 77, 255, 0.3));
}

/* ── ПОЧЕМУ ЗДЕСЬ НЕТ ОТДЕЛЬНОГО БЛИКА СВЕРХУ ────────────────────────────
   Пробовали дважды, оба раза одна и та же беда — белое заливает цифру
   ИЗНУТРИ вместо пары пикселей по верхней кромке:

   1. text-shadow прямо на числе. У элемента с background-clip: text заливка
      прозрачная, и тень текста рисуется ПОВЕРХ подрезанного фона, причём не
      кромкой, а целым силуэтом цифры, сдвинутым на пиксель.
   2. Копия цифры в ::before с z-index: -1. Кажется, что она уйдёт под фон
      родителя, — не уходит: отрицательный z-index кладёт потомка ПОСЛЕ
      фона родителя и лишь перед его содержимым. Результат тот же.

   Чтобы блик был настоящим, копия должна лежать в ОТДЕЛЬНОМ элементе позади
   числа, а не в его псевдоэлементе, — и тогда её надо совмещать с числом
   вручную по координатам. Ради двух пикселей это не стоит того: кромку
   держит полупрозрачный контур выше. */




/* Свой ореол за числом мифическая тоже потеряла — вместе с t4 и t5, по той же
   причине (см. выше). Вес ступени держат живая заливка глифов и самая яркая
   палитра верхней ауры. */

/* Подпись ступени — единственное место, где она получает цвет: слово
   «мифическая» должно опознаваться и без числа. Остальные пять ступеней
   держат подпись серой, и это правило окна («один акцент») здесь нарушается
   осознанно — ради ступени, которую человек видит раз в тысячу карточек. */
.gm__rp--t6 .gm__rp__cap { color: #8b1fd0; font-weight: 600; }
#dark .gm__rp--t6 .gm__rp__cap { color: #dd93ff; }

@media (prefers-reduced-motion: reduce) {
    .gm__rp--t6 .gm__rp__num { animation: none; background-position: 25% 50%; }
}

/* ─── Палитры верхней ауры по ступеням ──────────────────────────────────
   Окно «О карточке» красит шапку в цвет ступени: редкость видна раньше, чем
   прочитано число. Механика — .gm__card--aura выше по файлу, здесь только
   краски.

   В каждой ступени ЧЕТЫРЕ тона, а не один осветлённый. Пятно из одного цвета
   под размытием снова превращается в градиент — ровно то, ради чего всё это
   и затевалось.

   ТОНА РАЗВЕДЕНЫ ПО СВЕТЛОТЕ, а не только по цвету, и это второй заход:
   первая раскладка держала все четыре тона в одной светлоте, и под
   размытием они сливались — движение слоёв переставало читаться вовсе.
   Порядок теперь строгий и его нельзя перемешивать, слои рассчитывают
   именно на него:
       --gm-aura-1  глубокий основной   (низ, самый тёмный)
       --gm-aura-2  основной цвет ступени
       --gm-aura-3  глубокий сосед по тону (другая сторона семьи)
       --gm-aura-4  светлый акцент      (верх, самый светлый)

   Ступень 1 держится тише всех (--gm-aura-k .14) и уходит в серый: это 42%
   каталога, и красить «обычную» карточку не за что. Совсем без пятна тоже
   нельзя — тогда у окна два разных характера в зависимости от карточки. */
.gm__card--aura[data-aura="1"] { --gm-aura-1: #6e7681; --gm-aura-2: #9a9aa3; --gm-aura-3: #7f8792; --gm-aura-4: #c8ccd4; --gm-aura-k: .16; }
.gm__card--aura[data-aura="2"] { --gm-aura-1: #0b6b35; --gm-aura-2: #1e8f47; --gm-aura-3: #0f7d8a; --gm-aura-4: #a8e36a; }
.gm__card--aura[data-aura="3"] { --gm-aura-1: #0546a8; --gm-aura-2: #0a6fd8; --gm-aura-3: #4b2fd8; --gm-aura-4: #4fd6f0; }
.gm__card--aura[data-aura="4"] { --gm-aura-1: #96132c; --gm-aura-2: #c42b3a; --gm-aura-3: #8f2f66; --gm-aura-4: #ff9a5c; }
.gm__card--aura[data-aura="5"] { --gm-aura-1: #a35c05; --gm-aura-2: #e0a419; --gm-aura-3: #c2760a; --gm-aura-4: #ffe06b; }
.gm__card--aura[data-aura="6"] { --gm-aura-1: #5b17b0; --gm-aura-2: #aa19d2; --gm-aura-3: #2f5bd9; --gm-aura-4: #ff6ff0; }
/* На тёмном фоне вся лестница сдвинута вверх по светлоте: там, где на белом
   работает глубокий тон, на тёмном получается дыра, а движение видно только
   по светлым пятнам. */
#dark .gm__card--aura[data-aura="1"] { --gm-aura-1: #565f6e; --gm-aura-2: #9a9aa3; --gm-aura-3: #6e7787; --gm-aura-4: #c8c8d0; }
#dark .gm__card--aura[data-aura="2"] { --gm-aura-1: #149e4a; --gm-aura-2: #34c759; --gm-aura-3: #12a89f; --gm-aura-4: #c2f06a; }
#dark .gm__card--aura[data-aura="3"] { --gm-aura-1: #1d5fe0; --gm-aura-2: #3d8cff; --gm-aura-3: #6a5cff; --gm-aura-4: #5ee7ff; }
#dark .gm__card--aura[data-aura="4"] { --gm-aura-1: #c0374a; --gm-aura-2: #e5727d; --gm-aura-3: #b0468c; --gm-aura-4: #ffb36a; }
#dark .gm__card--aura[data-aura="5"] { --gm-aura-1: #c8820f; --gm-aura-2: #ffd166; --gm-aura-3: #ffb347; --gm-aura-4: #fff0b8; }
#dark .gm__card--aura[data-aura="6"] { --gm-aura-1: #7a1fd0; --gm-aura-2: #c14dff; --gm-aura-3: #3f6bff; --gm-aura-4: #ff8ae8; }

/* ─── Значение-айди в строке списка ─────────────────────────────────────
   Не пилюля-кнопка: пилюля в каждой строке делала список пёстрым, а тут
   показывают ЗНАЧЕНИЕ, которое заодно можно забрать. Цифры табличные, чтобы
   три строки выстраивались колонкой, глиф копирования приглушён и оживает
   на наведении. Подтверждение — та же строка, позеленевшая с галочкой:
   алерт поверх модалки звать нельзя, он закрыл бы её по hashchange. */
.gm__idv {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.2px;
    font-variant-numeric: tabular-nums;
    color: rgb(28, 28, 30);
    /* У .gm__list-row стоит user-select: none — значению его возвращаем:
       если буфер недоступен (http, отказ в разрешении), копирование
       вырождается в выделение, и забрать айди всё равно можно. */
    user-select: text;
    transition: color .18s ease;
}
#dark .gm__idv { color: rgba(255, 255, 255, 0.92); }
.gm__idv__ico {
    width: 15px;
    height: 15px;
    flex: none;
    opacity: 0.3;
    transition: opacity .18s ease;
}
.gm__list-row:hover .gm__idv__ico { opacity: 0.65; }
.gm__idv--ok { color: var(--ok-strong); }
.gm__idv--ok .gm__idv__ico { opacity: 1; }
#dark .gm__idv--ok { color: var(--ok-mint); }

/* Значение без действия (дата) — тем же кеглем, но серым и без глифа. */
.gm__idv--mute { color: rgba(60, 60, 67, 0.6); font-weight: 500; }
#dark .gm__idv--mute { color: rgba(235, 235, 245, 0.5); }

/* Подсветка строки на наведении — только здесь: в остальных списках .gm
   строка это переключатель, и лишний фон там ни к чему. */
#card-info .gm__list-row { transition: background-color .18s ease; }
#card-info .gm__list-row:not(.gm__list-row--plain):hover { background: rgba(120, 120, 128, 0.07); }
#dark #card-info .gm__list-row:not(.gm__list-row--plain):hover { background: rgba(255, 255, 255, 0.05); }

/* Заголовок вложенного экрана модалки (история, пополнение) — человек должен
   видеть, куда попал, а не догадываться по содержимому списка. */
.gm__sub-screen-head { padding: 0 2px; }
.gm__sub-screen-head__title {
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 17px;
    font-weight: 700;
    letter-spacing: -0.3px;
}
.gm__sub-screen-head__sub {
    margin-top: 3px;
    font-size: 12.5px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__sub-screen-head__sub { color: rgba(235, 235, 245, 0.45); }

/* ─── Текущая подписка ───
   Первый блок модалки для того, у кого подписка есть: срок и автопродление —
   то, за чем он сюда и пришёл. Заливка и рамка берут акцент своего тира, так
   что Pro/Premium/Max отличаются с одного взгляда, без чтения подписи. */
.gm__sub-current {
    position: relative;
    overflow: hidden;
    padding: 16px 18px 14px;
    border-radius: 18px;
    background:
        linear-gradient(150deg,
            color-mix(in srgb, var(--tier-accent) 15%, transparent),
            color-mix(in srgb, var(--tier-accent) 3%, transparent));
    border: 0.5px solid color-mix(in srgb, var(--tier-accent) 32%, transparent);
}
.gm__sub-current__bar {
    position: absolute;
    top: 0; left: 18px; right: 18px;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--tier-accent), transparent);
}
.gm__sub-current__head { display: flex; align-items: center; gap: 10px; }
.gm__sub-current__badge {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--tier-accent);
    border: 1px solid color-mix(in srgb, var(--tier-accent) 45%, transparent);
    border-radius: 7px;
    padding: 3px 9px;
    flex-shrink: 0;
}
.gm__sub-current__state { font-size: 13px; font-weight: 600; }
.gm__sub-current__days {
    margin-left: auto;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.6);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.gm__sub-current__until {
    margin-top: 10px;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.3px;
}
/* Полоса срока: дата отвечает «когда», полоса — «много ли осталось». */
.gm__sub-current__track {
    margin-top: 12px;
    height: 4px;
    border-radius: 2px;
    background: rgba(120, 120, 128, 0.2);
    overflow: hidden;
}
.gm__sub-current__fill { height: 100%; border-radius: 2px; background: var(--tier-accent); }
.gm__sub-current__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 12px;
}
.gm__sub-current__note { font-size: 12.5px; color: rgba(60, 60, 67, 0.6); }
#dark .gm__sub-current__days,
#dark .gm__sub-current__note { color: rgba(235, 235, 245, 0.55); }
#dark .gm__sub-current__track { background: rgba(255, 255, 255, 0.14); }

/* ─── Очередь периодов ───
   Приостановленные и отложенные периоды. Без этого блока человек, купивший
   тир выше, считает, что оплаченное время предыдущего сгорело. */
.gm__sub-queue {
    margin-top: 12px;
    padding: 12px 14px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.07);
}
#dark .gm__sub-queue { background: rgba(255, 255, 255, 0.05); }
.gm__sub-queue__title {
    font-size: 11px;
    font-weight: 650;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.5);
    margin-bottom: 6px;
}
#dark .gm__sub-queue__title { color: rgba(235, 235, 245, 0.42); }
.gm__sub-queue__row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 13px; }
.gm__sub-queue__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--tier-accent); flex: none; }
.gm__sub-queue__name { font-weight: 650; flex-shrink: 0; }
/* Пауза и очередь — разные состояния, и разница между ними видна без чтения:
   пауза жёлтая (было активно, приостановлено), очередь нейтральная. */
.gm__sub-queue__state {
    font-size: 11px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(120, 120, 128, 0.14);
    color: rgba(60, 60, 67, 0.65);
    white-space: nowrap;
}
.gm__sub-queue__state--paused { background: rgba(245, 179, 60, 0.18); color: #9a6400; }
#dark .gm__sub-queue__state { background: rgba(255, 255, 255, 0.1); color: rgba(235, 235, 245, 0.6); }
#dark .gm__sub-queue__state--paused { background: rgba(245, 179, 60, 0.2); color: #F5B33C; }
.gm__sub-queue__days {
    margin-left: auto;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.6);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.gm__sub-queue__note {
    margin-top: 8px;
    font-size: 11.5px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__sub-queue__note { color: rgba(235, 235, 245, 0.5); }
#dark .gm__sub-queue__days { color: rgba(235, 235, 245, 0.55); }
/* Ручное снятие с паузы: кнопка и объяснение, почему она вообще предлагается.
   Подпись обязательна — «Включить сейчас» без причины читается как способ
   потратить оплаченное время раньше срока. */
.gm__sub-queue__resume {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(60, 60, 67, 0.08);
}
#dark .gm__sub-queue__resume { border-top-color: rgba(255, 255, 255, 0.08); }
.gm__sub-queue__resume .gm__sub-queue__note { margin-top: 0; flex: 1; min-width: 160px; }

/* Витрина тарифов отделена заголовком от статуса — иначе у подписчика вся
   модалка читается одним полотном «купи подписку». */
.gm__sub-plans-title { margin-top: 22px; }


/* ═══════════════════════════════════════════════════════════════════════
   Set-info modal (dialog#set-info-modal) — «Цены / Бокс / Состав» набора.
   Собрана из готовых gm-блоков (card + seg + section + list + inline), свои
   только те части, для которых в системе не было формы: денежный hero,
   строка «редкость → цена» и плитки статистики. Ключевое решение по вёрстке —
   строка списка здесь ОДНОСТРОЧНАЯ (чип редкости · пояснение · цена · шеврон),
   а не двухэтажная label+hint: цифры разных строк должны стоять в одной
   колонке, иначе их невозможно сравнивать глазом, ради чего таблица и нужна.
   ═══════════════════════════════════════════════════════════════════════ */

/* Сегментированный переключатель на три позиции. Именно seg, а не .gm__tabs:
   у табов подписи скрыты (остаются одни иконки), а «Цены/Бокс/Состав» по
   иконке не угадываются. */
.gm__seg--3 { grid-template-columns: repeat(3, 1fr); }
/* Ссылка-пилюля в topbar (переиспользуем форму balance-chip) */
a.gm__balance-chip { text-decoration: none; transition: background .15s ease; }
a.gm__balance-chip:hover { background: rgba(120, 120, 128, 0.16); }
#dark a.gm__balance-chip:hover { background: rgba(118, 118, 128, 0.32); }
/* Базовый .gm__seg-opt рассчитан на <label> — кнопке нужен сброс UA-стилей */
button.gm__seg-opt {
    border: none;
    background: transparent;
    padding: 0;
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
}
/* Сброс выше специфичнее `.gm__seg-opt--on` (0,1,1 против 0,1,0) и стоит позже,
   поэтому у seg-переключателей НА КНОПКАХ он затирал подсветку активного пункта:
   в тёмной теме её возвращало `#dark .gm__seg-opt--on` (селектор с id весомее),
   а в светлой активная кнопка оставалась прозрачной и от соседних не отличалась.
   Касалось #psych-portrait, #set-info-modal, #bulk-price и истории операций. */
button.gm__seg-opt--on {
    background: var(--ink-on-dark);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1), 0 0 0 0.5px rgba(0, 0, 0, 0.05);
}

/* Денежный hero: смысл слева, сумма справа — горизонталь, а не ещё один
   центрированный блок под заголовком (см. «ёлочка» в GLASS_MODAL_DESIGN_SYSTEM). */
.gm__si-hero {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.08);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
}
#dark .gm__si-hero {
    background: rgba(118, 118, 128, 0.14);
    border-color: rgba(255, 255, 255, 0.07);
}
.gm__si-hero__body { flex: 1; min-width: 0; }
.gm__si-hero__title {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: rgb(28, 28, 30);
}
#dark .gm__si-hero__title { color: rgba(255, 255, 255, 0.95); }
.gm__si-hero__desc {
    font-size: 12.5px;
    line-height: 1.35;
    margin-top: 2px;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__si-hero__desc { color: rgba(235, 235, 245, 0.5); }
.gm__si-hero__amount {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.5px;
    white-space: nowrap;
    color: var(--temp-brand-a);
}
#dark .gm__si-hero__amount { color: var(--accent-orchid); }
.gm__si-hero__amount--muted {
    font-size: 13px;
    font-weight: 500;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__si-hero__amount--muted { color: rgba(235, 235, 245, 0.4); }

/* Строка «редкость → цена». Колонки: чип · пояснение · цена · шеврон. */
.gm__si-row {
    grid-template-columns: auto 1fr auto auto;
    grid-template-rows: auto;
    column-gap: 10px;
    width: 100%;
    text-align: left;
    border: none;
    background: transparent;
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
    color: inherit;
    text-decoration: none;
    transition: background .15s ease;
}
.gm__si-row:hover { background: rgba(120, 120, 128, 0.07); }
#dark .gm__si-row:hover { background: rgba(255, 255, 255, 0.04); }
/* Статические строки — div, а не button: без border-box width:100% + padding вылезали за карточку и резали цену */
.gm__si-row--static { cursor: default; box-sizing: border-box; }
.gm__si-row--static:hover { background: transparent; }
#dark .gm__si-row--static:hover { background: transparent; }
.gm__si-row--link { grid-template-columns: 1fr auto; }

/* Волосяная линия между строками рисуется через `.gm__list-row + .gm__list-row`,
   а раскрытый .gm__inline встаёт между ними и разрывает эту пару — строке под
   ним линия уже не достаётся. Возвращаем её снизу самому inline-блоку; когда
   он последний в списке, линия не нужна и не рисуется. */
.gm__list .gm__inline:not(:last-child) { border-bottom: 0.5px solid rgba(60, 60, 67, 0.14); }
#dark .gm__list .gm__inline:not(:last-child) { border-bottom-color: rgba(255, 255, 255, 0.08); }

/* Чип редкости — переиспользуем .card-info-rarity (единственный носитель
   цветовой схемы редкостей в проекте), только ужимаем под строку списка.
   Селектор ОБЯЗАТЕЛЬНО составной: card.css идёт в бандле /styles/app.css
   после index.css, и при равной специфичности выиграли бы его 34px/12px. */
.card-info-rarity.gm__si-row__chip {
    height: 26px;
    padding: 0 10px;
    font-size: 12.5px;
    font-weight: 600;
    flex-shrink: 0;
}
.card-info-rarity.gm__si-row__chip::after { top: 0; border-radius: 8px; }

.gm__si-row__meta {
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.6);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__si-row__meta { color: rgba(235, 235, 245, 0.5); }

.gm__si-row__price {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    font-size: 16.5px;
    font-weight: 600;
    letter-spacing: -0.3px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: rgb(28, 28, 30);
}
#dark .gm__si-row__price { color: rgba(255, 255, 255, 0.95); }
.gm__si-row__price small {
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0;
    color: rgba(60, 60, 67, 0.45);
    margin-top: 1px;
}
#dark .gm__si-row__price small { color: rgba(235, 235, 245, 0.38); }
.gm__si-row__price--none {
    font-size: 12.5px;
    font-weight: 400;
    color: rgba(60, 60, 67, 0.38);
}
#dark .gm__si-row__price--none { color: rgba(235, 235, 245, 0.32); }

.gm__si-row__chevron {
    display: inline-flex;
    color: rgba(60, 60, 67, 0.35);
    transition: transform .22s cubic-bezier(.16, 1, .3, 1);
}
#dark .gm__si-row__chevron { color: rgba(235, 235, 245, 0.35); }
.gm__si-row--open .gm__si-row__chevron { transform: rotate(180deg); }

.gm__si-row__name {
    font-size: 14.5px;
    font-weight: 500;
    letter-spacing: -0.2px;
    color: rgb(28, 28, 30);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__si-row__name { color: rgba(255, 255, 255, 0.95); }
.gm__si-row__count {
    font-size: 13px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.45);
    font-variant-numeric: tabular-nums;
}
#dark .gm__si-row__count { color: rgba(235, 235, 245, 0.4); }

/* Плитки статистики: min/медиана/max внутри раскрытой строки и параметры бокса */
.gm__si-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
.gm__si-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 9px 6px;
    border-radius: 10px;
    background: rgba(120, 120, 128, 0.08);
}
#dark .gm__si-stat { background: rgba(255, 255, 255, 0.05); }
.gm__si-stats--wide .gm__si-stat { padding: 12px 6px; }
.gm__si-stat__value {
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -0.2px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.gm__si-stat__label {
    font-size: 11px;
    color: rgba(60, 60, 67, 0.5);
    text-align: center;
}
#dark .gm__si-stat__label { color: rgba(235, 235, 245, 0.42); }

/* Живые лоты, догруженные при раскрытии редкости */
.gm__si-lots { display: flex; flex-direction: column; gap: 2px; }
.gm__si-lots__title {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.45);
    margin-bottom: 4px;
}
#dark .gm__si-lots__title { color: rgba(235, 235, 245, 0.4); }
.gm__si-lots__err { font-size: 12.5px; color: rgba(255, 59, 48, 0.85); }

.gm__si-lot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    margin: 0 -8px;
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
    transition: background .15s ease;
}
.gm__si-lot:hover { background: rgba(120, 120, 128, 0.1); }
#dark .gm__si-lot:hover { background: rgba(255, 255, 255, 0.05); }
.gm__si-lot__img {
    width: 28px;
    height: 40px;
    object-fit: cover;
    border-radius: 4px;
    flex-shrink: 0;
    background: rgba(120, 120, 128, 0.12);
}
.gm__si-lot__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.gm__si-lot__name {
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.1px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Номер карточки перед именем персонажа: HR-001 Derpy Hooves. Отдельного
   разделителя нет намеренно — в самом номере уже есть дефис, второй рядом
   («HR-001 - Derpy») читается как мусор. Роль разделителя играет контраст:
   номер приглушён и моноширинный, имя — основной текст. */
.gm__si-lot__num {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 11.5px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.5);
    margin-right: 5px;
}
#dark .gm__si-lot__num { color: rgba(235, 235, 245, 0.42); }
.gm__si-lot__seller { font-size: 11.5px; color: rgba(60, 60, 67, 0.5); }
#dark .gm__si-lot__seller { color: rgba(235, 235, 245, 0.42); }
.gm__si-lot__price {
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.gm__si-more { align-self: flex-start; margin-top: 6px; padding: 0 16px; }

.gm__si-empty {
    padding: 26px 16px;
    text-align: center;
    font-size: 13.5px;
    line-height: 1.5;
    color: rgba(60, 60, 67, 0.55);
}
#dark .gm__si-empty { color: rgba(235, 235, 245, 0.45); }

@media (max-width: 480px) {
    .gm__si-row { column-gap: 8px; }
    .gm__si-row__meta { font-size: 11.5px; }
    .gm__si-stats { grid-template-columns: repeat(2, 1fr); }
    .gm__si-hero__amount { font-size: 19px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Share modal (dialog#share-modal) — «Поделиться». Собрана из готовых
   gm-блоков (card + section + list + list-row + switch + inline + chips),
   своего здесь ровно четыре вещи, которых в системе не было:
   превью того, ЧТО откроется по ссылке, сама ссылка как кнопка-копирование,
   плитки мессенджеров и чипы-переключатели параметров ссылки.

   Порядок экрана — от результата к настройкам: человек сначала видит, чем
   делится, копирует одним касанием, и только потом (если надо) уточняет,
   что войдёт в ссылку. Обратный порядок (сначала форма опций, ссылка внизу)
   был у старой версии и заставлял читать настройки до того, как понятно,
   зачем они. ═══════════════════════════════════════════════════════════ */

/* .gm__card--wide задаёт только max-width, а у .gm__card стоит явный
   width: min(100% - 32px, 380px) — то же ограничение, что описано у
   --xwide/--subscription. Здесь ширина нужна больше: в 380px чипы фильтров
   («Набор: NS-5M02») ломаются по одному в строку. */
.gm__card--share { width: min(100% - 32px, 440px); }

/* ─── Превью: что именно откроется по ссылке ─── */
.gm__share-hero {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 16px;
    background: rgba(120, 120, 128, 0.08);
    border: 0.5px solid rgba(0, 0, 0, 0.06);
}
#dark .gm__share-hero {
    background: rgba(118, 118, 128, 0.14);
    border-color: rgba(255, 255, 255, 0.07);
}
.gm__share-hero__thumb {
    width: 52px;
    height: 52px;
    flex-shrink: 0;
    border-radius: 12px;
    overflow: hidden;
    background: rgba(120, 120, 128, 0.16);
    color: rgba(60, 60, 67, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
}
#dark .gm__share-hero__thumb { background: rgba(255, 255, 255, 0.08); color: rgba(235, 235, 245, 0.4); }
/* Профиль — круглая аватарка, как везде на сайте (.entity-avatar) */
.gm__share-hero__thumb--round { border-radius: 50%; }
/* Карточка — вертикальная (пропорции карты 63×88), иначе квадратный кроп
   срезает персонажу голову; ради этого у hero и фиксированная высота строки. */
.gm__share-hero__thumb--card { width: 56px; height: 78px; border-radius: 8px; }
.gm__share-hero__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gm__share-hero__body { flex: 1; min-width: 0; }
.gm__share-hero__title {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: rgb(28, 28, 30);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__share-hero__title { color: rgba(255, 255, 255, 0.95); }
.gm__share-hero__meta {
    margin-top: 2px;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.6);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__share-hero__meta { color: rgba(235, 235, 245, 0.5); }

/* ─── Скан карточки (#card-scan): превью результата кроппера. Клетка под
   картинкой обязательна — у скана прозрачная рамка и скруглённые углы, на ровном
   фоне их не отличить от белой заливки. Пропорции карты 398×544. */
.gm__scan-preview {
    width: min(100%, 190px);
    aspect-ratio: 398 / 544;
    margin: 0 auto;
    border-radius: 14px;
    overflow: hidden;
    background: rgba(120, 120, 128, 0.08) repeating-conic-gradient(rgba(120,120,128,0.14) 0% 25%, transparent 0% 50%) 0 0 / 16px 16px;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
}
#dark .gm__scan-preview { background-color: rgba(118, 118, 128, 0.14); border-color: rgba(255, 255, 255, 0.07); }
.gm__scan-preview img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* ─── Ссылка = кнопка. Клик по всей плашке копирует: отдельная мелкая
   иконка-копирования рядом с длинным урлом промахивается пальцем. ─── */
.gm__share-url {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
    padding: 8px 8px 8px 16px;
    border-radius: 14px;
    border: 0.5px solid rgba(0, 0, 0, 0.08);
    background: rgba(120, 120, 128, 0.06);
    font-family: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    transition: background .18s ease, border-color .18s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__share-url:hover { background: rgba(127, 45, 232, 0.05); border-color: rgba(127, 45, 232, 0.32); }
#dark .gm__share-url { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.09); }
#dark .gm__share-url:hover { background: rgba(179, 129, 255, 0.08); border-color: rgba(179, 129, 255, 0.35); }
.gm__share-url__text {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    line-height: 1.35;
    direction: ltr;
    color: rgba(60, 60, 67, 0.8);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    user-select: text;
}
#dark .gm__share-url__text { color: rgba(235, 235, 245, 0.75); }
.gm__share-url__act {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 38px;
    padding: 0 14px;
    border-radius: 10px;
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-a);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.1px;
    white-space: nowrap;
    transition: background .18s ease, color .18s ease;
}
.gm__share-url__act svg { width: 15px; height: 15px; flex-shrink: 0; }
#dark .gm__share-url__act { background: rgba(179, 129, 255, 0.18); color: var(--accent-orchid); }
/* Подтверждение живёт в самой кнопке, а не во всплывающем алерте: alert()
   открывает свой <dialog> и по hashchange закрывает share-modal (см.
   «Одна модалка = один hash» в этом же файле выше). */
.gm__share-url--copied { border-color: rgba(52, 199, 89, 0.4); background: rgba(52, 199, 89, 0.06); }
.gm__share-url--copied .gm__share-url__act { background: rgba(52, 199, 89, 0.16); color: var(--ok-strong); }
#dark .gm__share-url--copied { border-color: rgba(48, 209, 88, 0.4); background: rgba(48, 209, 88, 0.08); }
#dark .gm__share-url--copied .gm__share-url__act { background: rgba(48, 209, 88, 0.2); color: var(--ok-mint); }

/* ─── Плитки мессенджеров: иконка сверху, подпись снизу ─── */
.gm__share-ways {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    gap: 8px;
}
.gm__share-way {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 6px 11px;
    border-radius: 14px;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    background: rgba(120, 120, 128, 0.06);
    color: rgba(60, 60, 67, 0.8);
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.1px;
    text-decoration: none;
    cursor: pointer;
    transition: transform .16s cubic-bezier(.16, 1, .3, 1), background .16s ease, border-color .16s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__share-way:hover { transform: translateY(-2px); background: rgba(120, 120, 128, 0.12); }
.gm__share-way:active { transform: scale(.97); }
#dark .gm__share-way {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.08);
    color: rgba(235, 235, 245, 0.75);
}
#dark .gm__share-way:hover { background: rgba(255, 255, 255, 0.1); }
/* Бренд-глифы — одноцветные маски поверх currentColor (тот же приём, что у
   .gm__extlink__icon): цвет бренда задаётся на плитке, файл иконки один. */
.gm__share-way__ic {
    width: 26px;
    height: 26px;
    display: block;
    background: currentColor;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}
/* Внутренний чат WaifuCards — акцентный цвет проекта */
.gm__share-way--wfc { color: var(--temp-accent-indigo-b); }
#dark .gm__share-way--wfc { color: #8f7dff; }
.gm__share-way--wfc .gm__share-way__ic {
    -webkit-mask-image: url('/ui/chats.svg');
            mask-image: url('/ui/chats.svg');
}
.gm__share-way--tg { color: #2AABEE; }
.gm__share-way--tg .gm__share-way__ic {
    -webkit-mask-image: url('/ui/tg-icon.svg');
            mask-image: url('/ui/tg-icon.svg');
}
.gm__share-way--vk { color: #0077FF; }
.gm__share-way--vk .gm__share-way__ic {
    -webkit-mask-image: url('/ui/vk-icon.svg');
            mask-image: url('/ui/vk-icon.svg');
}
.gm__share-way--dc { color: #5865F2; }
.gm__share-way--dc .gm__share-way__ic {
    -webkit-mask-image: url('/ui/discord-icon.svg');
            mask-image: url('/ui/discord-icon.svg');
}
/* X — единственный бренд без своего цвета: чёрный на светлой теме, белый на
   тёмной, иначе на одной из них он просто исчезает. */
.gm__share-way--x { color: rgb(28, 28, 30); }
#dark .gm__share-way--x { color: var(--ink-on-dark); }
.gm__share-way--x .gm__share-way__ic {
    -webkit-mask-image: url('/ui/x-icon.svg');
            mask-image: url('/ui/x-icon.svg');
}
.gm__share-way--wb { color: #E6162D; }
.gm__share-way--wb .gm__share-way__ic {
    -webkit-mask-image: url('/ui/weibo-icon.svg');
            mask-image: url('/ui/weibo-icon.svg');
}
.gm__share-way--ln { color: #06C755; }
.gm__share-way--ln .gm__share-way__ic {
    -webkit-mask-image: url('/ui/line-icon.svg');
            mask-image: url('/ui/line-icon.svg');
}
/* Системное «Ещё» (Web Share API) — не бренд, поэтому нейтральный цвет
   и инлайновая stroke-иконка вместо маски. */
.gm__share-way--more { color: rgba(60, 60, 67, 0.6); }
#dark .gm__share-way--more { color: rgba(235, 235, 245, 0.55); }
.gm__share-way--more svg { width: 24px; height: 24px; display: block; }
.gm__share-way__label { color: rgba(60, 60, 67, 0.8); }
#dark .gm__share-way__label { color: rgba(235, 235, 245, 0.75); }

/* ─── Чипы параметров (языки, фильтры) внутри раскрытого .gm__inline ───
   Чип несёт подпись И значение: «Набор: NS-5M02» понятнее галочки «Набор». */
.gm__share-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.gm__share-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    height: 32px;
    padding: 0 12px;
    border-radius: 99px;
    border: 0.5px solid rgba(60, 60, 67, 0.14);
    background: rgba(120, 120, 128, 0.08);
    color: rgba(60, 60, 67, 0.75);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: -0.1px;
    white-space: nowrap;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__share-chip:hover { background: rgba(120, 120, 128, 0.16); }
.gm__share-chip__val {
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.9);
}
.gm__share-chip--on {
    background: rgba(127, 45, 232, 0.12);
    border-color: rgba(127, 45, 232, 0.28);
    color: var(--temp-brand-a);
}
.gm__share-chip--on .gm__share-chip__val { color: var(--temp-brand-a); }
.gm__share-chip--on:hover { background: rgba(127, 45, 232, 0.18); }
#dark .gm__share-chip {
    border-color: rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.06);
    color: rgba(235, 235, 245, 0.7);
}
#dark .gm__share-chip:hover { background: rgba(255, 255, 255, 0.12); }
#dark .gm__share-chip__val { color: rgba(255, 255, 255, 0.9); }
#dark .gm__share-chip--on {
    background: rgba(179, 129, 255, 0.2);
    border-color: rgba(179, 129, 255, 0.4);
    color: var(--accent-orchid);
}
#dark .gm__share-chip--on .gm__share-chip__val { color: var(--accent-orchid); }

/* Ссылка длинная, а экран узкий: подпись кнопки прячем, оставляя иконку —
   урл важнее слова «Копировать», которое и так дублируется галочкой. */
@media (max-width: 420px) {
    .gm__share-url { padding-left: 12px; }
    .gm__share-url__act { padding: 0 11px; }
    .gm__share-url__act span { display: none; }
    .gm__share-ways { grid-template-columns: repeat(2, 1fr); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   КОРЗИНА ПОКУПАТЕЛЯ (dialog#cart-modal)
   Разметка — modules/modals.ejs, логика — cart* в assets/index.ejs,
   данные — handlers/cart.js. Свои классы только для строки лота и шапки
   продавца: такой формы (миниатюра + цена + инлайн-подпись) в системе не было.
   ═══════════════════════════════════════════════════════════════════════════ */

.gm__card--cart { max-width: 480px; width: 480px; }

/* Шапка модалки: крупный заголовок + пилюля «N из лимита» */
.gm__cart-top { padding-bottom: 2px; }
.gm__cart-top__title { font-size: 17px; font-weight: 700; letter-spacing: -0.3px; }
.gm__cart-top__chip {
    font-size: 11.5px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.6);
    background: rgba(120, 120, 128, 0.12);
    border-radius: 99px;
    padding: 3px 10px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
#dark .gm__cart-top__chip { color: rgba(235, 235, 245, 0.6); background: rgba(255, 255, 255, 0.08); }
.gm__cart-view { padding-top: 12px; }

/* Группа продавца — «карточка»: заливка + тонкое кольцо, всё содержимое
   (шапка, строки, футер/трекер) внутри. Ровно как .seller-group в моке. */
.gm__cart-group {
    background: rgba(120, 120, 128, 0.07);
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.07);
    border-radius: 16px;
    overflow: hidden;
}
#dark .gm__cart-group {
    background: rgba(255, 255, 255, 0.05);
    box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.07);
}

.gm__cart-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 26px 0 10px;
}
.gm__cart-empty__ic {
    width: 40px;
    height: 40px;
    color: rgba(60, 60, 67, 0.35);
}
#dark .gm__cart-empty__ic { color: rgba(235, 235, 245, 0.3); }

/* Шапка группы: продавец. Та же горизонталь, что у .gm__pick-row. Клик по
   всей строке сворачивает/разворачивает группу (Задача 3) — навигация на
   витрину продавца осталась только на вложенных __avatar/__info (свои <a>
   с @click.stop в разметке), иначе каждое сворачивание открывало бы
   фоновую вкладку профиля. */
.gm__cart-seller {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 12px 14px;
    cursor: pointer;
    user-select: none;
    transition: background .15s ease;
}
.gm__cart-seller:hover { background: rgba(120, 120, 128, 0.05); }
#dark .gm__cart-seller:hover { background: rgba(255, 255, 255, 0.03); }
.gm__cart-seller__avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background-size: cover;
    background-position: center;
    background-color: rgba(120, 120, 128, 0.16);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.12);
}
#dark .gm__cart-seller__avatar {
    background-color: rgba(255, 255, 255, 0.1);
    box-shadow: 0 0 0 0.5px rgba(255, 255, 255, 0.14);
}
/* Продавец без аватарки: инициал на заливке вместо «слепого» серого круга */
.gm__cart-seller__initial {
    font-size: 15px;
    font-weight: 700;
    color: rgba(60, 60, 67, 0.55);
    user-select: none;
}
#dark .gm__cart-seller__initial { color: rgba(235, 235, 245, 0.6); }
/* НЕ flex:1: блок сжимается по контенту, чтобы клик по свободной середине
   строки сворачивал группу, а ссылкой в профиль было только имя/подстрока */
.gm__cart-seller__info {
    min-width: 0;
    flex: 0 1 auto;
    text-decoration: none;
    color: inherit;
}
.gm__cart-seller__info:hover .gm__cart-seller__name { text-decoration: underline; }
.gm__cart-seller__name {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: rgb(28, 28, 30);
    overflow: hidden;
    white-space: nowrap;
}
#dark .gm__cart-seller__name { color: var(--ink-on-dark); }
/* ✓N — продажи, подтверждённые покупателями (сигнал доверия у имени) */
.gm__cart-trust {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--ok-strong);
}
#dark .gm__cart-trust { color: var(--ok-bright); }
.gm__cart-trust svg { flex-shrink: 0; }
.gm__cart-seller__sub {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.6);
    overflow: hidden;
    white-space: nowrap;
}
#dark .gm__cart-seller__sub { color: rgba(235, 235, 245, 0.55); }
.gm__cart-seller__tg { color: #3478F6; }
#dark .gm__cart-seller__tg { color: #6cb2ff; }
.gm__cart-seller__dot {
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: rgba(60, 60, 67, 0.35);
    flex-shrink: 0;
}
#dark .gm__cart-seller__dot { background: rgba(235, 235, 245, 0.35); }
.gm__cart-seller__online { color: var(--ok-strong); }
#dark .gm__cart-seller__online { color: var(--ok-bright); }
/* Правый кластер: необязательная плашка «недавно» + счётчик/статус + шеврон */
.gm__cart-seller__right {
    margin-left: auto;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
}
.gm__cart-seller__count {
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.6);
    background: rgba(120, 120, 128, 0.1);
    border-radius: 99px;
    padding: 2px 9px;
    white-space: nowrap;
}
#dark .gm__cart-seller__count {
    color: rgba(235, 235, 245, 0.6);
    background: rgba(255, 255, 255, 0.08);
}
/* Активная сделка вместо количества лотов — цвет по тому же принципу,
   что и бейдж трекера (амбер = нужно внимание, зелёный = получена) */
.gm__cart-seller__count--pending { color: var(--warn-strong); background: rgba(255, 159, 10, 0.14); }
#dark .gm__cart-seller__count--pending { color: var(--warn); background: rgba(255, 159, 10, 0.18); }
.gm__cart-seller__count--received { color: var(--ok-strong); background: rgba(52, 199, 89, 0.14); }
#dark .gm__cart-seller__count--received { color: var(--ok-bright); background: rgba(48, 209, 88, 0.16); }
/* Подсказка, почему эта группа раскрыта, а остальные свёрнуты — явная подпись
   вместо «сама догадайся» (см. feedback_visual_style в памяти проекта) */
.gm__cart-seller__recent {
    flex-shrink: 0;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--temp-brand-a);
    background: rgba(127, 45, 232, 0.12);
    padding: 3px 8px;
    border-radius: 99px;
    white-space: nowrap;
}
#dark .gm__cart-seller__recent { color: var(--accent-orchid); background: rgba(198, 140, 255, 0.14); }
.gm__cart-seller__chev {
    flex-shrink: 0;
    display: inline-flex;
    color: rgba(60, 60, 67, 0.35);
    transition: transform .22s cubic-bezier(.16, 1, .3, 1);
}
#dark .gm__cart-seller__chev { color: rgba(235, 235, 245, 0.35); }
.gm__cart-seller__chev--collapsed { transform: rotate(-90deg); }

/* Строка лота внутри карточки группы: волосяной разделитель сверху, hover
   подсвечивает строку, кнопка удаления проявляется по ховеру (мок .ci) */
.gm__cart-item {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 10px 14px;
    position: relative;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
    transition: background .15s ease;
}
#dark .gm__cart-item { border-top-color: rgba(255, 255, 255, 0.06); }
.gm__cart-item:hover { background: rgba(120, 120, 128, 0.05); }
#dark .gm__cart-item:hover { background: rgba(255, 255, 255, 0.025); }
.gm__cart-item__thumb {
    width: 42px;
    height: 59px;
    border-radius: 8px;
    object-fit: cover;
    flex-shrink: 0;
    cursor: pointer;
    background: rgba(120, 120, 128, 0.12);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
    transition: transform .18s cubic-bezier(.16, 1, .3, 1);
}
.gm__cart-item__thumb:hover { transform: scale(1.05); }
#dark .gm__cart-item__thumb { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }
/* Горизонтальная карта (ориентация выясняется по @load) — широкая миниатюра
   той же площади, а не вертикальный кроп */
.gm__cart-item__thumb--h {
    width: 59px;
    height: 42px;
    margin: 8px 0;
}
.gm__cart-item__body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.gm__cart-item__title {
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: -0.15px;
    color: rgb(28, 28, 30);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__cart-item__title { color: var(--ink-on-dark); }
/* Набор · Редкость-номер под именем персонажа */
.gm__cart-item__sub {
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.6);
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#dark .gm__cart-item__sub { color: rgba(235, 235, 245, 0.55); }
/* Правый столбец строки: цена (за всё количество) + степпер */
.gm__cart-item__right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex-shrink: 0;
    padding-top: 1px;
}
.gm__cart-item__price {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.85);
    font-variant-numeric: tabular-nums;
}
#dark .gm__cart-item__price { color: rgba(235, 235, 245, 0.8); }
.gm__cart-item__noprice {
    font-weight: 500;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__cart-item__noprice { color: rgba(235, 235, 245, 0.45); }
.gm__cart-item__qty {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.gm__cart-item__qty button {
    width: 20px;
    height: 20px;
    border: 0;
    border-radius: 6px;
    background: rgba(120, 120, 128, 0.12);
    color: rgba(60, 60, 67, 0.8);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-item__qty button:disabled { opacity: 0.35; cursor: default; }
#dark .gm__cart-item__qty button {
    background: rgba(255, 255, 255, 0.1);
    color: rgba(235, 235, 245, 0.8);
}
.gm__cart-item__qty b { font-variant-numeric: tabular-nums; }
/* Подпись покупателя — её увидит продавец в присланной корзине.
   Три состояния (паттерн из дизайн-мока): «призрачная» кнопка добавления
   (на десктопе проявляется при наведении на строку, на таче видна всегда),
   цитата с акцент-полосой и карандашом, инпут на время редактирования. */
.gm__cart-item__note-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    align-self: flex-start;
    margin-top: 3px;
    border: 0;
    background: none;
    padding: 0;
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 500;
    color: rgba(60, 60, 67, 0.45);
    cursor: pointer;
    opacity: 0;
    transition: color .15s ease, opacity .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-item:hover .gm__cart-item__note-btn { opacity: 1; }
.gm__cart-item__note-btn:hover { color: var(--temp-brand-a); }
#dark .gm__cart-item__note-btn { color: rgba(235, 235, 245, 0.4); }
#dark .gm__cart-item__note-btn:hover { color: var(--accent-orchid); }
@media (hover: none) {
    .gm__cart-item__note-btn { opacity: 1; }
}
.gm__cart-item__quote {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 3px;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.75);
    min-width: 0;
}
#dark .gm__cart-item__quote { color: rgba(235, 235, 245, 0.75); }
.gm__cart-item__quote-bar {
    width: 2px;
    align-self: stretch;
    border-radius: 2px;
    background: #8f7dff;
    opacity: 0.55;
    flex-shrink: 0;
}
.gm__cart-item__quote-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm__cart-item__quote-edit {
    border: 0;
    background: none;
    padding: 2px;
    color: rgba(60, 60, 67, 0.45);
    display: inline-flex;
    cursor: pointer;
    opacity: 0;
    flex-shrink: 0;
    transition: opacity .15s ease, color .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-item:hover .gm__cart-item__quote-edit { opacity: 1; }
.gm__cart-item__quote-edit:hover { color: var(--temp-brand-a); }
#dark .gm__cart-item__quote-edit { color: rgba(235, 235, 245, 0.4); }
#dark .gm__cart-item__quote-edit:hover { color: var(--accent-orchid); }
@media (hover: none) {
    .gm__cart-item__quote-edit { opacity: 1; }
}
.gm__cart-item__note {
    width: 100%;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: rgba(120, 120, 128, 0.08);
    padding: 0 9px;
    font-family: inherit;
    font-size: 12px;
    color: rgb(28, 28, 30);
    outline: none;
    transition: background .15s ease;
}
.gm__cart-item__note::placeholder { color: rgba(60, 60, 67, 0.45); }
.gm__cart-item__note:focus { background: rgba(120, 120, 128, 0.14); }
#dark .gm__cart-item__note {
    background: rgba(255, 255, 255, 0.07);
    color: var(--ink-on-dark);
}
#dark .gm__cart-item__note::placeholder { color: rgba(235, 235, 245, 0.4); }
#dark .gm__cart-item__note:focus { background: rgba(255, 255, 255, 0.12); }
/* Удаление — проявляется при наведении на строку (на таче видно всегда) */
.gm__cart-item__remove {
    width: 22px;
    height: 22px;
    margin-top: 1px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: rgba(60, 60, 67, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    opacity: 0;
    transition: background .15s ease, color .15s ease, opacity .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-item:hover .gm__cart-item__remove { opacity: 1; }
.gm__cart-item__remove:hover { background: rgba(255, 69, 58, 0.14); color: #ff453a; }
#dark .gm__cart-item__remove { color: rgba(235, 235, 245, 0.45); }
#dark .gm__cart-item__remove:hover { background: rgba(255, 69, 58, 0.16); color: #ff7a72; }
@media (hover: none) {
    .gm__cart-item__remove { opacity: 1; }
}

/* Большая группа рендерится порциями (8 + по 40, см. cartShowMore):
   кнопка догрузки следующей порции внутри списка */
.gm__cart-more {
    display: block;
    width: calc(100% - 28px);
    margin: 8px 14px 10px;
    border: 0;
    border-radius: 10px;
    background: rgba(120, 120, 128, 0.1);
    color: rgba(60, 60, 67, 0.65);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 8px;
    cursor: pointer;
    transition: background .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-more:hover { background: rgba(120, 120, 128, 0.18); color: rgb(28, 28, 30); }
#dark .gm__cart-more {
    background: rgba(255, 255, 255, 0.07);
    color: rgba(235, 235, 245, 0.6);
}
#dark .gm__cart-more:hover { background: rgba(255, 255, 255, 0.12); color: var(--ink-on-dark); }

/* Футер группы: подытог + отправка + «⋯», внутри карточки группы */
.gm__cart-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px 13px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
    flex-wrap: wrap;
}
#dark .gm__cart-foot { border-top-color: rgba(255, 255, 255, 0.06); }
.gm__cart-foot__total {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: 13px;
    color: rgba(60, 60, 67, 0.6);
}
.gm__cart-foot__total b {
    color: rgb(28, 28, 30);
    font-size: 14px;
    letter-spacing: -0.2px;
    font-variant-numeric: tabular-nums;
}
#dark .gm__cart-foot__total { color: rgba(235, 235, 245, 0.55); }
#dark .gm__cart-foot__total b { color: var(--ink-on-dark); }
.gm__cart-foot__unpriced { font-size: 11.5px; }
.gm__cart-foot { position: relative; }
/* Глобальный min-height: 46px у кнопок раздувал «Отправить продавцу» —
   в футере группы все контролы одного роста: 34px (как gm__btn--sm) */
.gm__cart-foot__send {
    width: auto;
    margin-left: auto;
    height: 34px;
    min-height: 34px;
    font-size: 12.5px;
    white-space: nowrap;
    gap: 7px;
}
.gm__cart-track__act.gm__btn {
    height: 34px;
    min-height: 34px;
    font-size: 12.5px;
    white-space: nowrap;
}
/* «⋯» — редкие действия группы (профиль продавца, очистить) в поповере,
   чтобы не конкурировали с главной кнопкой отправки */
.gm__cart-foot__more {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    border: 0;
    border-radius: 10px;
    background: rgba(120, 120, 128, 0.1);
    color: rgba(60, 60, 67, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-foot__more:hover { background: rgba(120, 120, 128, 0.18); color: rgb(28, 28, 30); }
#dark .gm__cart-foot__more {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(235, 235, 245, 0.6);
}
#dark .gm__cart-foot__more:hover { background: rgba(255, 255, 255, 0.14); color: var(--ink-on-dark); }
/* Невидимая подложка ловит клик мимо поповера и закрывает его */
.gm__cart-pop-backdrop {
    position: fixed;
    inset: 0;
    z-index: 4;
}
.gm__cart-pop {
    position: absolute;
    right: 12px;
    bottom: 50px;
    z-index: 5;
    min-width: 190px;
    background: rgba(252, 252, 254, 0.97);
    backdrop-filter: blur(30px);
    -webkit-backdrop-filter: blur(30px);
    border-radius: 13px;
    padding: 5px;
    box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.08), 0 12px 40px rgba(0, 0, 0, 0.18);
    animation: gm-cart-pop-in .18s cubic-bezier(.16, 1, .3, 1);
}
#dark .gm__cart-pop {
    background: rgba(44, 44, 50, 0.97);
    box-shadow: 0 0 0 0.5px rgba(255, 255, 255, 0.12), 0 12px 40px rgba(0, 0, 0, 0.5);
}
@keyframes gm-cart-pop-in {
    from { opacity: 0; transform: translateY(6px) scale(.97); }
}
.gm__cart-pop a,
.gm__cart-pop button {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    border: 0;
    background: none;
    border-radius: 9px;
    color: rgb(28, 28, 30);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    padding: 8px 10px;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-pop a:hover,
.gm__cart-pop button:hover { background: rgba(0, 0, 0, 0.05); }
#dark .gm__cart-pop a,
#dark .gm__cart-pop button { color: var(--ink-on-dark); }
#dark .gm__cart-pop a:hover,
#dark .gm__cart-pop button:hover { background: rgba(255, 255, 255, 0.08); }
.gm__cart-pop svg { flex-shrink: 0; opacity: 0.7; }
.gm__cart-pop .gm__cart-pop__danger { color: var(--danger-strong); }
#dark .gm__cart-pop .gm__cart-pop__danger { color: #ff7a72; }

/* Янтарный баннер о «осиротевших» позициях (лот снят/скрыт/продавец в бане) */
.gm__cart-orphan {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(255, 159, 10, 0.1);
    box-shadow: inset 0 0 0 0.5px rgba(255, 159, 10, 0.3);
    border-radius: 12px;
    padding: 9px 12px;
    font-size: 12.5px;
    color: var(--warn-strong);
}
#dark .gm__cart-orphan {
    background: rgba(255, 159, 10, 0.09);
    box-shadow: inset 0 0 0 0.5px rgba(255, 159, 10, 0.25);
    color: rgba(255, 197, 113, 0.95);
}
.gm__cart-orphan svg { flex-shrink: 0; }
.gm__cart-orphan__act {
    margin-left: auto;
    flex-shrink: 0;
    border: 0;
    border-radius: 8px;
    background: rgba(255, 159, 10, 0.16);
    color: var(--warn-strong);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 5px 11px;
    cursor: pointer;
    transition: background .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-orphan__act:hover { background: rgba(255, 159, 10, 0.28); }
#dark .gm__cart-orphan__act { color: #ffc571; }

/* Сделка получена и подтверждена, но не блокирует новую отправку — тонкая
   справка НАД обычным футером (не вместо него): покупатель может собирать
   у того же продавца заново. */
.gm__cart-donenote {
    display: flex;
    align-items: center;
    gap: 7px;
    /* Отступ снизу обязателен: дальше идёт футер с border-top, без отступа
       текст прилипает к линии */
    padding: 10px 14px 10px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--ok-strong);
}
#dark .gm__cart-donenote { color: var(--ok-mint); }
.gm__cart-donenote svg { flex-shrink: 0; }

/* Живой трекер сделки — заменяет обычный футер (подытог + «Отправить
   продавцу»), пока активная сделка с этим продавцом не доехала до
   покупателя (cartDealBlocking в assets/index.ejs). Цвета бейджа переиспользуют
   имена классов cartDealPillCls(), чтобы не разъезжаться с тем, что видно
   в самом чате. */
.gm__cart-track {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 11px 14px 13px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
}
#dark .gm__cart-track { border-top-color: rgba(255, 255, 255, 0.06); }
.gm__cart-track__top { display: flex; align-items: center; gap: 8px; }
.gm__cart-track__badge {
    font-size: 11px;
    font-weight: 700;
    padding: 3px 9px;
    border-radius: 99px;
    white-space: nowrap;
}
.gm__cart-track__badge--sent,
.gm__cart-track__badge--preparing { background: rgba(255, 159, 10, 0.14); color: var(--warn-strong); }
#dark .gm__cart-track__badge--sent,
#dark .gm__cart-track__badge--preparing { background: rgba(255, 159, 10, 0.18); color: var(--warn); }
.gm__cart-track__badge--picking,
.gm__cart-track__badge--shipped { background: rgba(10, 132, 255, 0.12); color: #0B63CE; }
#dark .gm__cart-track__badge--picking,
#dark .gm__cart-track__badge--shipped { background: rgba(79, 160, 255, 0.18); color: #7DB8FF; }
.gm__cart-track__badge--fixed { background: rgba(127, 45, 232, 0.12); color: var(--temp-brand-a); }
#dark .gm__cart-track__badge--fixed { background: rgba(179, 129, 255, 0.18); color: var(--accent-orchid); }
.gm__cart-track__badge--accepted { background: rgba(10, 132, 255, 0.12); color: #0B63CE; }
#dark .gm__cart-track__badge--accepted { background: rgba(79, 160, 255, 0.16); color: #4FA8FF; }
.gm__cart-track__badge--received { background: rgba(52, 199, 89, 0.14); color: var(--ok-strong); }
#dark .gm__cart-track__badge--received { background: rgba(48, 209, 88, 0.16); color: var(--ok-bright); }
/* Архив: сорвавшийся заказ и отложенная корзина — нейтральные, серые. Это
   уже история, и кричать цветом ей незачем */
.gm__cart-track__badge--cancelled,
.gm__cart-track__badge--archived { background: rgba(120, 120, 128, 0.14); color: rgba(60, 60, 67, 0.7); }
#dark .gm__cart-track__badge--cancelled,
#dark .gm__cart-track__badge--archived { background: rgba(235, 235, 245, 0.12); color: rgba(235, 235, 245, 0.7); }
.gm__cart-track__step { font-size: 11.5px; color: rgba(60, 60, 67, 0.6); }
#dark .gm__cart-track__step { color: rgba(235, 235, 245, 0.55); }
.gm__cart-track__dots { display: flex; align-items: center; gap: 5px; }
.gm__cart-track__dots i { flex: 1; height: 3px; border-radius: 3px; background: rgba(120, 120, 128, 0.14); }
#dark .gm__cart-track__dots i { background: rgba(255, 255, 255, 0.1); }
.gm__cart-track__dots i.done { background: #B381FF; opacity: .6; }
.gm__cart-track__dots i.cur { background: var(--temp-brand-a); }
#dark .gm__cart-track__dots i.cur { background: var(--accent-orchid); }
/* Подсказка и кнопки — РАЗНЫМИ строками: в одну строку подсказка сжималась
   в узкую колонку и липла к кнопкам. Кнопки прижаты к правому краю. */
.gm__cart-track__bottom {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
}
.gm__cart-track__acts {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
}
.gm__cart-track__hint { min-width: 0; font-size: 12px; color: rgba(60, 60, 67, 0.65); line-height: 1.4; }
#dark .gm__cart-track__hint { color: rgba(235, 235, 245, 0.55); }
/* Требуется решение покупателя (fixed) или посылка уже в пути (shipped, не
   подтверждено) — акцент цветом на подсказке, без восклицаний и иконок-тревог */
.gm__cart-track--urgent .gm__cart-track__hint { color: var(--warn-strong); font-weight: 500; }
#dark .gm__cart-track--urgent .gm__cart-track__hint { color: var(--warn); }
/* Состав заказа в трекере: раскрывашка со снапшотом. Нужна потому, что живые
   строки корзины выше — это не заказ, и они могут исчезнуть (продавец снял
   проданный лот с продажи → каскад по cart_items). */
.gm__cart-track__compo {
    display: flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    padding: 0;
    border: 0;
    background: transparent;
    color: rgba(60, 60, 67, 0.7);
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
}
.gm__cart-track__compo:hover { color: rgb(28, 28, 30); }
.gm__cart-track__compo-note {
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--warn-strong);
}
#dark .gm__cart-track__compo { color: rgba(235, 235, 245, 0.6); }
#dark .gm__cart-track__compo:hover { color: var(--ink-on-dark); }
#dark .gm__cart-track__compo-note { color: var(--warn); }

/* «Добавили после отправки — продавец не видит»: то же янтарное предупреждение,
   что и у недобора до минимального заказа. Тон один на весь модуль. */
.gm__cart-track__hint--warn { color: var(--warn-strong); font-weight: 500; }
#dark .gm__cart-track__hint--warn { color: var(--warn); }
.gm__cart-track__act { flex-shrink: 0; white-space: nowrap; width: auto; }
/* ── Условия магазина продавца ────────────────────────────────────────────
   Подсказка, а не запрет: заказ ниже минимума всё равно уходит. Поэтому
   строка спокойная, без иконок тревоги и без красного. */
.gm__cart-shophint {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 14px 0;
    font-size: 12px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.6);
}
.gm__cart-shophint--checkout { padding: 0; }
.gm__cart-shophint__warn { color: var(--warn-strong); }
.gm__cart-shophint__ok { color: var(--teal); }
#dark .gm__cart-shophint { color: rgba(235, 235, 245, 0.5); }
#dark .gm__cart-shophint__warn { color: var(--warn); }
#dark .gm__cart-shophint__ok { color: #4FD1A5; }

/* ── Магазин: приветствие, условия, формы ─────────────────────────────── */
.gm__shop-greet {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 12px 14px;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.08);
}
.gm__shop-greet__head { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.gm__shop-greet__ava { width: 24px; height: 24px; flex-shrink: 0; }
.gm__shop-greet__text { font-size: 13.5px; line-height: 1.5; white-space: pre-line; overflow-wrap: anywhere; }
.gm__shop-greet__text--clamp {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.gm__shop-greet__more {
    align-self: flex-start;
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--temp-brand-a);
    font-size: 12px;
    cursor: pointer;
}
#dark .gm__shop-greet { background: rgba(255, 255, 255, 0.05); }
#dark .gm__shop-greet__more { color: var(--accent-orchid); }

.gm__shop-terms {
    font-size: 13px;
    line-height: 1.5;
    color: rgba(60, 60, 67, 0.75);
    white-space: pre-line;
    overflow-wrap: anywhere;
}
#dark .gm__shop-terms { color: rgba(235, 235, 245, 0.7); }

/* Вкладки магазина — сегментированный контрол, а не ряд плоских иконок:
   без залитой дорожки и приподнятой активной пилюли пользователи не понимали,
   что на это вообще можно нажимать. */
.gm__tabs--shop {
    margin: 0 0 8px;
    padding: 4px;
    gap: 2px;
    border: 0;
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.12);
}
.gm__tabs--shop .gm__tabs-item {
    padding: 8px 6px 7px;
    gap: 4px;
    border-radius: 11px;
    color: rgba(60, 60, 67, 0.75);
}
.gm__tabs--shop .gm__tabs-item:hover:not(.gm__tabs-item--active) {
    background: rgba(255, 255, 255, 0.5);
    color: rgb(28, 28, 30);
}
.gm__tabs--shop .gm__tabs-item--active {
    background: var(--ink-on-dark);
    color: rgb(28, 28, 30);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 0 0 0.5px rgba(0, 0, 0, 0.04);
}
.gm__tabs--shop .gm__tabs-icon { width: 20px; height: 20px; }
#dark .gm__tabs--shop { background: rgba(255, 255, 255, 0.07); border-bottom: 0; }
#dark .gm__tabs--shop .gm__tabs-item { color: rgba(235, 235, 245, 0.6); }
#dark .gm__tabs--shop .gm__tabs-item:hover:not(.gm__tabs-item--active) { background: rgba(255, 255, 255, 0.06); color: var(--ink-on-dark); }
#dark .gm__tabs--shop .gm__tabs-item--active {
    background: rgba(255, 255, 255, 0.16);
    color: var(--ink-on-dark);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
/* В настройках профиля вкладки иконочные (.gm__tabs-label скрыт всегда), но
   «Магазин / Условия / Доставка» по иконкам не угадать — здесь подписи нужны */
.gm__tabs--shop .gm__tabs-label { display: block; }
/* Кнопка сохранения прижата вправо и отделена от содержимого вкладки */
.gm__shop-foot { border-top: 0; padding-bottom: 0; margin-top: 4px; }

.gm__shop-block { display: flex; flex-direction: column; gap: 7px; }
.gm__shop-block__cap {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__shop-block__cap { color: rgba(235, 235, 245, 0.55); }

.gm__shop-input {
    /* В проекте нет глобального border-box: без него ширина 100% + паддинги
       вылезают за карточку — на 375px это заметные 5px вправо */
    box-sizing: border-box;
    width: 100%;
    min-height: 36px;
    padding: 8px 11px;
    border: 1px solid rgba(60, 60, 67, 0.14);
    border-radius: 10px;
    background: rgba(120, 120, 128, 0.06);
    color: inherit;
    font-family: inherit;
    font-size: 13.5px;
}
.gm__shop-input--area { resize: vertical; line-height: 1.5; }
.gm__shop-input--num { width: 92px; min-width: 0; flex-shrink: 0; }
.gm__shop-input:focus { outline: none; border-color: rgba(122, 45, 232, 0.5); }
#dark .gm__shop-input { border-color: rgba(235, 235, 245, 0.16); background: rgba(255, 255, 255, 0.06); }
#dark .gm__shop-input:focus { border-color: rgba(198, 140, 255, 0.6); }

/* Условия оплаты койнами на экране оформления: янтарный, как сама валюта,
   но приглушённый — это факт, а не призыв к действию */
.gm__shop-coins {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 10px 12px;
    border-radius: 12px;
    background: rgba(255, 176, 32, 0.08);
    font-size: 12.5px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.75);
}
.gm__shop-coins { flex-direction: column; gap: 8px; }
.gm__shop-coins__head { display: flex; align-items: flex-start; gap: 9px; }
.gm__shop-coins b { flex-shrink: 0; color: var(--warn-strong); font-size: 14px; }
.gm__shop-coins__pick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.gm__shop-coins__pick button {
    width: 28px;
    height: 28px;
    min-height: 28px;
    flex-shrink: 0;
    border: 1px solid rgba(60, 60, 67, 0.16);
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}
.gm__shop-coins__pick button:disabled { opacity: 0.4; cursor: default; }
.gm__shop-coins__max { width: auto !important; padding: 0 10px; font-size: 12px !important; }
.gm__shop-coins__val { display: flex; flex-direction: column; min-width: 108px; }
.gm__shop-coins__val b { color: var(--warn-strong); font-size: 13px; }
.gm__shop-coins__val span { font-size: 11.5px; color: rgba(60, 60, 67, 0.55); }
.gm__shop-coins__bal { font-size: 11.5px; color: rgba(60, 60, 67, 0.5); }
#dark .gm__shop-coins__pick button { border-color: rgba(235, 235, 245, 0.18); }
#dark .gm__shop-coins__val b { color: #FFC43C; }
#dark .gm__shop-coins__val span, #dark .gm__shop-coins__bal { color: rgba(235, 235, 245, 0.45); }
#dark .gm__shop-coins { background: rgba(255, 196, 60, 0.1); color: rgba(235, 235, 245, 0.7); }
#dark .gm__shop-coins b { color: #FFC43C; }

/* Оценка доставки под итогом. Намеренно НЕ складывается с суммой заказа в
   один диапазон: вилку легко принять за окончательную цену, а точную сумму
   продавец фиксирует при сборке. */
.gm__shop-est {
    text-align: center;
    font-size: 12px;
    line-height: 1.45;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__shop-est { color: rgba(235, 235, 245, 0.5); }
/* Личная встреча за сотни километров — не ошибка ввода, но почти наверняка
   недоразумение: подсвечиваем, не блокируя выбор */
.gm__shop-est--warn { color: var(--warn-strong); font-weight: 500; }
#dark .gm__shop-est--warn { color: var(--warn); }

/* Способ без цены (Авито, личная встреча) */
.gm__shop-ship__ext {
    align-self: center;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__shop-ship__ext { color: rgba(235, 235, 245, 0.45); }

/* Выбранный город: строка-факт со сменой. Блок не прячем после выбора —
   иначе ошибиться городом было бы необратимо прямо на оформлении. */
.gm__shop-city {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 11px;
    border-radius: 12px;
    background: rgba(120, 120, 128, 0.06);
    font-size: 13.5px;
}
.gm__shop-city svg { flex-shrink: 0; opacity: 0.6; }
.gm__shop-city b { min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm__shop-city button {
    flex-shrink: 0;
    margin-left: auto;
    padding: 4px 11px;
    min-height: 0;
    border: 0;
    border-radius: 99px;
    background: rgba(120, 120, 128, 0.14);
    color: inherit;
    font-family: inherit;
    font-size: 12px;
    cursor: pointer;
}
.gm__shop-city button:hover:not(:disabled) { background: rgba(120, 120, 128, 0.24); }
.gm__shop-city button:disabled { opacity: 0.5; cursor: default; }
#dark .gm__shop-city { background: rgba(255, 255, 255, 0.05); }
#dark .gm__shop-city button { background: rgba(255, 255, 255, 0.1); }

/* Поле с подписью и звёздочкой обязательности */
.gm__shop-labeled { display: flex; flex-direction: column; gap: 4px; }
.gm__shop-labeled > span { font-size: 11.5px; color: rgba(60, 60, 67, 0.55); padding-left: 2px; }
.gm__shop-labeled > span i { font-style: normal; color: #D93636; margin-left: 2px; }
#dark .gm__shop-labeled > span { color: rgba(235, 235, 245, 0.5); }
#dark .gm__shop-labeled > span i { color: #FF7A7A; }

.gm__shop-methods { display: flex; flex-wrap: wrap; gap: 8px; }
.gm__shop-method {
    display: flex;
    flex-direction: column;
    gap: 2px;
    align-items: flex-start;
    padding: 9px 13px;
    border: 1px solid rgba(60, 60, 67, 0.14);
    border-radius: 12px;
    background: transparent;
    color: inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    /* Без сброса appearance iOS рисует поверх нативную кнопку, и от оформления
       не остаётся ничего — ни рамки, ни скруглений, ни отметки выбора.
       box-sizing здесь обязателен: глобального border-box в проекте нет. */
    -webkit-appearance: none;
    appearance: none;
    box-sizing: border-box;
    transition: border-color .15s ease, background-color .15s ease;
}
.gm__shop-method:hover { border-color: rgba(60, 60, 67, 0.3); }
.gm__shop-method__label { font-size: 13.5px; }
.gm__shop-method__price { font-size: 11.5px; color: rgba(60, 60, 67, 0.55); font-variant-numeric: tabular-nums; }
.gm__shop-method__note { font-size: 11px; color: rgba(60, 60, 67, 0.5); }
/* Выбранный способ: одной сменой цвета рамки на телефоне не читается —
   добавляем внутреннее кольцо (та же рамка, но в два раза заметнее) и
   акцент на подписи */
.gm__shop-method--on {
    border-color: var(--temp-brand-a);
    background: rgba(122, 45, 232, 0.08);
    box-shadow: inset 0 0 0 1px var(--temp-brand-a);
}
.gm__shop-method--on .gm__shop-method__label { font-weight: 600; color: var(--temp-brand-c); }
#dark .gm__shop-method { border-color: rgba(235, 235, 245, 0.16); }
#dark .gm__shop-method__price, #dark .gm__shop-method__note { color: rgba(235, 235, 245, 0.5); }
#dark .gm__shop-method:hover { border-color: rgba(235, 235, 245, 0.3); }
#dark .gm__shop-method--on {
    border-color: var(--accent-orchid);
    background: rgba(198, 140, 255, 0.12);
    box-shadow: inset 0 0 0 1px var(--accent-orchid);
}
#dark .gm__shop-method--on .gm__shop-method__label { color: var(--temp-accent-lilac-c); }

.gm__shop-disc {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.6);
}
.gm__shop-disc__del {
    margin-left: auto;
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    min-height: 26px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: rgba(120, 120, 128, 0.12);
    color: inherit;
    cursor: pointer;
}
#dark .gm__shop-disc { color: rgba(235, 235, 245, 0.55); }
#dark .gm__shop-disc__del { background: rgba(255, 255, 255, 0.1); }

.gm__shop-ship {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 9px 11px;
    border-radius: 12px;
    background: rgba(120, 120, 128, 0.06);
}
.gm__shop-ship__head { display: flex; align-items: center; gap: 10px; font-size: 13.5px; cursor: pointer; }
/* Свой чекбокс вместо системного: синий квадрат браузера выбивался из
   оформления. Форма и зелёный — те же, что у переключателей проекта
   (.gm__switch), галочка нарисована фоном: ::after у <input> ненадёжен. */
.gm__shop-ship__head input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    margin: 0;
    border: 1.5px solid rgba(60, 60, 67, 0.28);
    border-radius: 6px;
    /* Длинные свойства, а не шорткат: с `background: transparent ...`
       снятая галочка оставляла зелёную заливку — состояние «выключено»
       должно быть объявлено так же явно, как «включено» */
    background-color: transparent;
    background-image: none;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12px 12px;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.gm__shop-ship__head:hover input[type="checkbox"]:not(:checked) { border-color: rgba(60, 60, 67, 0.45); }
.gm__shop-ship__head input[type="checkbox"]:checked {
    border-color: var(--ok-vivid);
    background-color: var(--ok-vivid);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
}
.gm__shop-ship__head input[type="checkbox"]:focus-visible { outline: 2px solid var(--temp-brand-a); outline-offset: 2px; }
.gm__shop-ship__head span { font-weight: 500; }
/* Отмеченный способ выделяем всей карточкой — список читается с одного взгляда */
.gm__shop-ship--on { background: rgba(48, 209, 88, 0.07); }
#dark .gm__shop-ship__head input[type="checkbox"] { border-color: rgba(235, 235, 245, 0.3); }
#dark .gm__shop-ship__head:hover input[type="checkbox"]:not(:checked) { border-color: rgba(235, 235, 245, 0.5); }
#dark .gm__shop-ship--on { background: rgba(48, 209, 88, 0.1); }
.gm__shop-ship__row { display: flex; flex-wrap: wrap; gap: 7px; align-items: flex-end; }
.gm__shop-ship__note { flex: 1 1 100%; width: auto; }
/* Ячейка цены с подписью над полем: без подписи заполненная строка
   «150 / 300 / 500» нечитаема — какое число по городу, а какое вилка,
   видно только пока поля пустые */
.gm__shop-price { display: flex; flex-direction: column; gap: 3px; flex: 1 1 84px; min-width: 0; }
.gm__shop-price span { font-size: 11px; color: rgba(60, 60, 67, 0.5); padding-left: 2px; }
.gm__shop-price .gm__shop-input--num { width: 100%; }
#dark .gm__shop-price span { color: rgba(235, 235, 245, 0.45); }
/* Подсказки внутри блоков формы читаются слева: по центру они выглядят
   оторванными от полей, к которым относятся */
.gm__shop-block > .gm__hint { text-align: left; }
#dark .gm__shop-ship { background: rgba(255, 255, 255, 0.05); }

/* Оплата в трекере: своя половина — переключатель, чужая — строка состояния.
   Деньги ходят мимо сайта, это чек-лист сторон, а не платёж. */
.gm__cart-track__pay {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 2px 0 1px;
}
.gm__cart-track__paybtn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex-shrink: 0;
    height: 26px;
    min-height: 26px;
    padding: 0 11px 0 5px;
    border: 1px solid rgba(60, 60, 67, 0.16);
    border-radius: 99px;
    background: transparent;
    color: rgba(60, 60, 67, 0.85);
    font-size: 12px;
    cursor: pointer;
}
.gm__cart-track__paybtn:disabled { opacity: 0.55; cursor: default; }
.gm__cart-track__paybtn--on { border-color: rgba(0, 155, 118, 0.45); color: var(--teal); }
/* Квадрат читается как чекбокс, кружок читался как индикатор статуса:
   пользователь не понимал, что на это можно нажать */
.gm__cart-track__paybox {
    display: grid;
    place-items: center;
    width: 17px;
    height: 17px;
    border-radius: 5px;
    border: 1.5px solid rgba(60, 60, 67, 0.3);
    background: transparent;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.gm__cart-track__paybtn:hover:not(:disabled) { border-color: rgba(0, 155, 118, 0.45); }
.gm__cart-track__paybtn--on .gm__cart-track__paybox { background: var(--teal); border-color: var(--teal); }
.gm__cart-track__paynote { min-width: 0; font-size: 11.5px; color: rgba(60, 60, 67, 0.55); }
.gm__cart-track__paynote--on { color: var(--teal); }
#dark .gm__cart-track__paybtn { border-color: rgba(235, 235, 245, 0.18); color: rgba(235, 235, 245, 0.85); }
#dark .gm__cart-track__paybtn--on { border-color: rgba(60, 220, 170, 0.45); color: #4FD1A5; }
#dark .gm__cart-track__paybox { background: transparent; border-color: rgba(235, 235, 245, 0.32); }
#dark .gm__cart-track__paybtn--on .gm__cart-track__paybox { background: #34C79A; border-color: #34C79A; }
#dark .gm__cart-track__paynote { color: rgba(235, 235, 245, 0.45); }
#dark .gm__cart-track__paynote--on { color: #4FD1A5; }
/* «Найти другого продавца» — под всеми группами корзины */
.gm__cart-alts-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    border: 0;
    border-radius: 12px;
    background: rgba(120, 120, 128, 0.1);
    color: rgba(60, 60, 67, 0.75);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    padding: 11px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-alts-btn:hover { background: rgba(120, 120, 128, 0.18); color: rgb(28, 28, 30); }
#dark .gm__cart-alts-btn { background: rgba(255, 255, 255, 0.07); color: rgba(235, 235, 245, 0.7); }
#dark .gm__cart-alts-btn:hover { background: rgba(255, 255, 255, 0.12); color: var(--ink-on-dark); }

/* Карточка альтернативного продавца: шапка + лента его карт с ценами */
.gm__cart-alt {
    border-radius: 14px;
    overflow: hidden;
    background: rgba(120, 120, 128, 0.07);
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.07);
}
#dark .gm__cart-alt {
    background: rgba(255, 255, 255, 0.05);
    box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.07);
}
.gm__cart-alt__head {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 12px;
    text-decoration: none;
    color: inherit;
    transition: background .15s ease;
}
.gm__cart-alt__head:hover { background: rgba(120, 120, 128, 0.08); }
#dark .gm__cart-alt__head:hover { background: rgba(255, 255, 255, 0.05); }
.gm__cart-alt__head:hover .gm__cart-seller__name { text-decoration: underline; }

/* Лента карт продавца: миниатюра + цена под ней */
.gm__cart-alt__cards {
    display: flex;
    gap: 8px;
    padding: 0 12px 10px;
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
}
.gm__cart-alt__cards::-webkit-scrollbar { height: 4px; }
.gm__cart-alt__cards::-webkit-scrollbar-thumb { background: rgba(120, 120, 128, 0.3); border-radius: 2px; }
.gm__cart-alt__card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    width: 44px;
    border: 0;
    background: none;
    padding: 0;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-alt__card-img {
    width: 44px;
    height: 61px;
    border-radius: 7px;
    object-fit: cover;
    background: rgba(120, 120, 128, 0.12);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
    transition: opacity .15s ease;
}
/* Без scale на ховере: миниатюры мелкие, увеличение дёргает ленту */
.gm__cart-alt__card:hover .gm__cart-alt__card-img { opacity: .82; }
#dark .gm__cart-alt__card-img { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }
/* Горизонтальная карта — та же площадь, широкий кроп */
.gm__cart-alt__card-img--h { width: 61px; height: 44px; margin: 8px 0; }
.gm__cart-alt__card:has(.gm__cart-alt__card-img--h) { width: 61px; }
.gm__cart-alt__card-price {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: -0.1px;
    font-variant-numeric: tabular-nums;
    color: rgb(28, 28, 30);
    white-space: nowrap;
}
#dark .gm__cart-alt__card-price { color: rgba(255, 255, 255, 0.92); }
.gm__cart-alt__card-price--none { color: rgba(60, 60, 67, 0.4); font-weight: 500; }
#dark .gm__cart-alt__card-price--none { color: rgba(235, 235, 245, 0.4); }

/* Карты из вишлиста — отдельной лентой под картами корзины, с подписью */
.gm__cart-alt__wish { border-top: 0.5px solid rgba(0, 0, 0, 0.06); }
#dark .gm__cart-alt__wish { border-top-color: rgba(255, 255, 255, 0.06); }
.gm__cart-alt__wish-cap {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 8px 12px 6px;
    font-size: 10.5px;
    font-weight: 600;
    color: #C31E77;
}
#dark .gm__cart-alt__wish-cap { color: #FF8CC8; }
.gm__cart-alt__wish-cap svg { flex-shrink: 0; }
/* Розовое кольцо отличает вишлист от карт корзины в общей ленте */
.gm__cart-alt__card-img--wish { box-shadow: 0 0 0 1.5px rgba(232, 45, 145, 0.45); }
#dark .gm__cart-alt__card-img--wish { box-shadow: 0 0 0 1.5px rgba(255, 140, 200, 0.4); }
.gm__cart-alt__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.gm__cart-alt__tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 4px; }
.gm__cart-alt__tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 99px;
    font-size: 10.5px;
    font-weight: 600;
    white-space: nowrap;
}
.gm__cart-alt__tag--match { background: rgba(82, 79, 255, 0.12); color: #5d55e6; }
#dark .gm__cart-alt__tag--match { background: rgba(82, 79, 255, 0.2); color: #aeb4ff; }
.gm__cart-alt__tag--wish { background: rgba(232, 45, 145, 0.1); color: #C31E77; }
#dark .gm__cart-alt__tag--wish { background: rgba(232, 45, 145, 0.18); color: #FF8CC8; }
.gm__cart-alt__incart {
    font-size: 10px;
    font-weight: 600;
    color: rgba(60, 60, 67, 0.5);
    background: rgba(120, 120, 128, 0.14);
    border-radius: 99px;
    padding: 1px 7px;
}
#dark .gm__cart-alt__incart { color: rgba(235, 235, 245, 0.5); background: rgba(255, 255, 255, 0.1); }
.gm__cart-alt__price {
    flex-shrink: 0;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: -0.2px;
    font-variant-numeric: tabular-nums;
    color: rgb(28, 28, 30);
    align-self: flex-start;
    padding-top: 2px;
}
#dark .gm__cart-alt__price { color: var(--ink-on-dark); }

/* Группа осталась только ради отслеживания сделки (лотов в корзине нет) */
/* Фиолетовая точка «продавец этого ещё не видит»: карта попала в корзину
   после того, как заказ уехал снапшотом. Без неё человек добавляет карту и
   считает, что она сама доехала до продавца. */
.gm__cart-item__new {
    display: inline-block;
    width: 6px;
    height: 6px;
    flex-shrink: 0;
    margin-right: 5px;
    vertical-align: 1px;
    border-radius: 50%;
    background: var(--temp-brand-b);
}
#dark .gm__cart-item__new { background: #B381FF; }
.gm__cart-track__act--dot { padding-left: 10px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ОТЗЫВ ПО СДЕЛКЕ (dialog#deal-review) и хвост завершённой сделки в корзине.
   Разметка — modules/modals.ejs, логика — assets/index.ejs (openDealReview),
   правила — handlers/deal-reviews.js.
   ═══════════════════════════════════════════════════════════════════════════ */

/* .gm__hint по умолчанию по центру — так задумано у экранов-подсказок. В форме
   отзыва подпись идёт под конкретным полем, и центр рвёт связь с ним. */
#deal-review .gm__view,
#deal-review .gm__hint { text-align: left; font-size: 12px; }

/* Оценка прямо в корзине: не кнопка «оставить отзыв», а сами звёзды. Клик по
   звезде открывает форму уже с этой оценкой — человек сделал первый шаг, и
   дописать словами проще, чем начинать с нуля. */
.gm__cart-rate {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 12px;
}
.gm__cart-rate__cap { font-size: 12.5px; font-weight: 500; }
.gm__cart-rate__stars { display: flex; gap: 2px; }
.gm__cart-rate__star {
    display: inline-flex;
    padding: 2px;
    border: 0;
    background: transparent;
    color: rgba(60, 60, 67, 0.3);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: color .12s ease, transform .12s ease;
}
.gm__cart-rate__star:hover { transform: scale(1.1); }
.gm__cart-rate__star--on { color: var(--warn-vivid); }
#dark .gm__cart-rate__star { color: rgba(235, 235, 245, 0.3); }
#dark .gm__cart-rate__star--on { color: var(--warn); }

/* Хвост завершённой сделки в архивной полке корзины */
.gm__cart-after {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
}
.gm__cart-after__act {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    align-self: flex-start;
    padding: 7px 12px;
    border: 0;
    border-radius: 10px;
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-c);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.gm__cart-after__act:hover { background: rgba(127, 45, 232, 0.2); }

/* Просьба о поддержке — самая тихая строка на экране: сначала дело, потом
   просьба, и никакого давления на человека, который только что заплатил */
.gm__cart-thanks {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 8px;
    font-size: 12px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.55);
}
.gm__cart-thanks--wide {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
}
.gm__cart-thanks__act {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--temp-brand-c);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.gm__cart-thanks__act:hover { opacity: 0.8; }
#dark .dlrev__role,
#dark .dlrev__time,
#dark .dlrev__stars-note,
#dark .gm__cart-thanks { color: rgba(235, 235, 245, 0.55); }
#dark .dlrev__times,
#dark .gm__cart-after,
#dark .gm__cart-thanks--wide { border-top-color: rgba(255, 255, 255, 0.07); }
#dark .gm__cart-after__act { background: rgba(179, 129, 255, 0.18); color: var(--temp-accent-lilac-c); }
#dark .gm__cart-after__act:hover { background: rgba(179, 129, 255, 0.28); }
#dark .gm__cart-thanks__act { color: var(--temp-accent-lilac-c); }

/* Янтарная полоса-предупреждение внутри группы продавца. Тон такой у всех
   предупреждений корзины: это не ошибка, а то, о чём человек должен знать.
   Два потребителя, и оба — «сайт что-то сделает, а ты не в курсе»:
     • уведомления выключены (иначе человек решит, что сайт про заказ молчит);
     • --due: срок автозавершения отправленного заказа со ссылками «Я не
       получил заказ» и «Написать в поддержку».
   Имя осталось от первого — заводить второе семейство ради того же блока
   дороже, чем прочитать этот комментарий (см. docs/CSS_CLEANUP.md). */
.gm__cart-push {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin: 10px 14px 0;
    padding: 9px 11px;
    border-radius: 12px;
    background: rgba(255, 159, 10, 0.1);
    color: var(--warn-strong);
    font-size: 11.5px;
    line-height: 1.4;
}
.gm__cart-push > svg { flex-shrink: 0; margin-top: 1px; }
.gm__cart-push__txt { flex: 1; min-width: 140px; }
.gm__cart-push__act {
    flex-shrink: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.gm__cart-push__act:hover { opacity: 0.75; }
.gm__cart-push__act[disabled] { opacity: 0.45; cursor: default; }
/* Внутри архивной полки (.gm__cart-prior__body) горизонтальные поля уже даёт
   сама полка — свои превратили бы полосу в узкий столбик по центру.
   Здесь ДВА действия, а не одно, и в ширину полки они с текстом не помещаются:
   без явного переноса «Я не получил заказ» уезжало вправо от срока, а
   «Написать в поддержку» падало под него в левый край — будто два обрывка
   разных строк. Отдаём сроку всю первую строку, действиям — вторую.
   Первую строку срок занимает ВМЕСТЕ со значком (14px значка + 10px колонки =
   24px), иначе часы остаются висеть над пустой строкой. Действия на второй
   встают под текст, а не под значок. */
.gm__cart-push--due { margin: 10px 0 0; }
.gm__cart-push--due .gm__cart-push__txt { flex: 1 1 calc(100% - 24px); }
.gm__cart-push--due .gm__cart-push__act:first-of-type { margin-left: 24px; }
#dark .gm__cart-push { background: rgba(255, 159, 10, 0.14); color: var(--warn); }
/* `#dark a` (1,0,1) бьёт по специфичности `.gm__cart-push__act` (0,1,0) и красит
   ссылку в синий: в янтарной полосе рядом с такой же кнопкой это читалось как
   две разные сущности. Роль ссылки здесь показывает подчёркивание, а не цвет —
   те же грабли и то же лечение, что у `#dark .gm__alert__body a`. */
#dark .gm__cart-push__act { color: inherit; }

/* Архив (#cart-archive): список закрытых заказов и отложенных корзин.
   Каждая запись — свёрнутая строка «с кем, чем кончилось, когда, на сколько»;
   состав раскрывается на месте той же вёрсткой, что архивная полка группы. */
.gm__arch {
    border-radius: 14px;
    background: rgba(120, 120, 128, 0.06);
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.05);
    overflow: hidden;
}
.gm__arch + .gm__arch { margin-top: 8px; }
.gm__arch__head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    background: transparent;
    font: inherit;
    /* Именно color, а не только font: кнопка НЕ наследует цвет текста, и имя
       продавца внутри неё оказывалось чёрным на тёмной карточке */
    color: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__arch__head:hover { background: rgba(120, 120, 128, 0.06); }
.gm__arch__avatar { width: 32px; height: 32px; flex-shrink: 0; }
.gm__arch__who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Обе строки — строго в одну линию с обрезкой: на телефоне длинное имя или
   дата иначе переносятся и наезжают на состав заказа */
.gm__arch__line {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
.gm__arch__name {
    font-size: 13.5px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm__arch__line .gm__cart-track__badge { flex-shrink: 0; }
.gm__arch__sub {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.55);
}
.gm__arch__sub > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm__arch__sum {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 12.5px;
    color: rgba(60, 60, 67, 0.9);
    font-variant-numeric: tabular-nums;
}
.gm__arch__myrate { color: var(--warn-vivid); letter-spacing: -1px; }
.gm__arch__body {
    padding: 10px 12px 12px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
}
.gm__arch__note {
    margin-top: 8px;
    font-size: 12px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.7);
    word-break: break-word;
}
.gm__arch__foot {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}
.gm__arch__foot .gm__cart-prior__hint { flex: 1; min-width: 0; }
.gm__arch__drop { color: #D93025; }
#dark .gm__arch {
    background: rgba(255, 255, 255, 0.05);
    box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.07);
}
#dark .gm__arch__head:hover { background: rgba(255, 255, 255, 0.05); }
#dark .gm__arch__sub { color: rgba(235, 235, 245, 0.5); }
#dark .gm__arch__sum { color: rgba(255, 255, 255, 0.92); }
#dark .gm__arch__body { border-top-color: rgba(255, 255, 255, 0.07); }
#dark .gm__arch__myrate { color: var(--warn); }
#dark .gm__arch__note { color: rgba(235, 235, 245, 0.65); }
#dark .gm__arch__drop { color: #FF6B60; }

/* «Архив» в шапке корзины — тихая кнопка рядом с крестиком: вход в историю,
   а не действие над текущей корзиной */
.gm__cart-top__archive {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border: 0;
    border-radius: 99px;
    background: rgba(120, 120, 128, 0.1);
    color: inherit;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-top__archive:hover { background: rgba(120, 120, 128, 0.16); }
#dark .gm__cart-top__archive { background: rgba(255, 255, 255, 0.08); }
#dark .gm__cart-top__archive:hover { background: rgba(255, 255, 255, 0.14); }

/* Прошлый заказ — нижняя «архивная» полка той же группы продавца. Уехавшую
   посылку уже не изменить, поэтому она свёрнута и стоит ПОД активной корзиной:
   вложенная сверху, она читалась как часть новой сделки и путала. */
.gm__cart-prior { border-top: 0.5px solid rgba(0, 0, 0, 0.06); }
.gm__cart-prior__head {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 14px;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.gm__cart-prior__head:hover { background: rgba(120, 120, 128, 0.06); }
.gm__cart-prior__txt {
    flex: 1;
    min-width: 0;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.6);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm__cart-prior__dot {
    width: 6px;
    height: 6px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--warn-vivid);
}
.gm__cart-prior__chev {
    display: inline-flex;
    flex-shrink: 0;
    color: rgba(60, 60, 67, 0.35);
    transition: transform .2s ease;
}
.gm__cart-prior__chev--open { transform: rotate(180deg); }
.gm__cart-prior__body { padding: 0 14px 12px; }

/* Состав отправленного заказа — плотный read-only список: это справка
   «что и почём уехало», а не редактируемые строки корзины */
.gm__cart-snap {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 168px;
    overflow-y: auto;
}
.gm__cart-snap__row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: rgba(60, 60, 67, 0.75);
}
.gm__cart-snap__row--out { opacity: 0.5; text-decoration: line-through; }
.gm__cart-snap__thumb {
    width: 22px;
    height: 30px;
    flex-shrink: 0;
    border-radius: 3px;
    object-fit: cover;
    background: rgba(120, 120, 128, 0.12);
}
.gm__cart-snap__thumb--ph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    color: rgba(60, 60, 67, 0.4);
}
.gm__cart-snap__code {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm__cart-snap__qty { flex-shrink: 0; color: rgba(60, 60, 67, 0.45); }
.gm__cart-snap__price { flex-shrink: 0; font-variant-numeric: tabular-nums; }

.gm__cart-snap__sum {
    margin: 10px 0 0;
    padding-top: 8px;
    border-top: 0.5px solid rgba(0, 0, 0, 0.06);
    font-size: 12px;
}
.gm__cart-snap__sum > div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 1px 0;
}
.gm__cart-snap__sum dt { color: rgba(60, 60, 67, 0.55); }
.gm__cart-snap__sum dd { margin: 0; font-variant-numeric: tabular-nums; }
.gm__cart-snap__sum--total dt,
.gm__cart-snap__sum--total dd { font-weight: 600; color: inherit; }

.gm__cart-prior__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
}
.gm__cart-prior__hint {
    flex: 1;
    min-width: 140px;
    font-size: 12px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.6);
}
.gm__cart-prior__act { flex-shrink: 0; }
#dark .gm__cart-snap__row { color: rgba(235, 235, 245, 0.7); }
#dark .gm__cart-snap__qty { color: rgba(235, 235, 245, 0.4); }
#dark .gm__cart-snap__thumb { background: rgba(255, 255, 255, 0.08); }
#dark .gm__cart-snap__thumb--ph { color: rgba(235, 235, 245, 0.4); }
#dark .gm__cart-snap__sum { border-top-color: rgba(255, 255, 255, 0.07); }
#dark .gm__cart-snap__sum dt { color: rgba(235, 235, 245, 0.5); }
#dark .gm__cart-prior { border-top-color: rgba(255, 255, 255, 0.07); }
#dark .gm__cart-prior__head:hover { background: rgba(255, 255, 255, 0.05); }
#dark .gm__cart-prior__txt,
#dark .gm__cart-prior__hint { color: rgba(235, 235, 245, 0.55); }
#dark .gm__cart-prior__chev { color: rgba(235, 235, 245, 0.35); }

.gm__cart-dealonly {
    padding: 10px 14px 0;
    font-size: 12px;
    line-height: 1.4;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__cart-dealonly { color: rgba(235, 235, 245, 0.55); }

/* Непрочитанные сообщения от продавца — ненавязчивая пилюля на «Переписка» */
.gm__cart-track__unread {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 17px;
    padding: 0 5px;
    margin-left: 6px;
    border-radius: 9px;
    background: rgba(127, 45, 232, 0.14);
    color: var(--temp-brand-a);
    font-size: 10.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
#dark .gm__cart-track__unread {
    background: rgba(198, 140, 255, 0.18);
    color: var(--accent-orchid);
}

/* Задача 5: градиент проекта (как у дропа/гачи) вместо сплошного .gm__btn--primary
   — только для «Отправить продавцу» и «Подтвердить получение» в корзине.
   Модификатор НЕ трогает .gm__btn--primary саму — она используется по всему
   сайту в других модалках. */
/* Подтверждение получения — тонированная кнопка, а не второй градиент.
   Рядом с ней в карточке уже стоит «Отправить продавцу»: два одинаковых
   акцентных CTA спорят друг с другом и ломают иерархию. */
.gm__btn--confirm {
    background: rgba(127, 45, 232, 0.12);
    color: var(--temp-brand-c);
    box-shadow: none;
    font-weight: 600;
}
.gm__btn--confirm:hover:not(:disabled) { background: rgba(127, 45, 232, 0.2); }
#dark .gm__btn--confirm { background: rgba(179, 129, 255, 0.18); color: var(--temp-accent-lilac-c); }
#dark .gm__btn--confirm:hover:not(:disabled) { background: rgba(179, 129, 255, 0.28); }

.gm__btn--cart-send {
    background-color: var(--accent-indigo);
    background-image: linear-gradient(120deg, var(--accent-blue) -5%, var(--accent-indigo) 48%, var(--accent-magenta) 105%);
}
.gm__btn--cart-send:hover:not(:disabled) {
    background-color: var(--accent-indigo);
    filter: brightness(1.08) saturate(1.05);
}

/* ═══════════════════════════════════════════════════════════════════════════
   МОДАЛКА ЦЕНЫ КАРТОЧКИ (dialog#edit-card) и МАССОВАЯ ПРОСТАНОВКА (#bulk-price)
   Разметка — modules/modals.ejs, логика — assets/index.ejs (editCard*, bp*).
   ═══════════════════════════════════════════════════════════════════════════ */

/* Сброс UA-стилей для строки-кнопки. Раньше он жил только внутри .gm__si-row
   (модалка набора), из-за чего любой новый <button class="gm__list-row">
   приезжал с белым фоном и чёрным текстом. Правило общее — держим его рядом
   с базовым блоком, а не внутри конкретной модалки. */
button.gm__list-row {
    width: 100%;
    text-align: left;
    border: none;
    background: transparent;
    color: inherit;
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
    transition: background .15s ease;
}
button.gm__list-row:hover { background: rgba(120, 120, 128, 0.07); }
#dark button.gm__list-row:hover { background: rgba(255, 255, 255, 0.04); }

/* .gm__list-row как <a> (строка карточки-подписки ведёт на её страницу) —
   тот же сброс UA-стилей, что у button.gm__list-row, плюс убрать подчёркивание. */
a.gm__list-row { display: grid; text-decoration: none; }
a.gm__list-row:hover { background: rgba(120, 120, 128, 0.07); }
#dark a.gm__list-row:hover { background: rgba(255, 255, 255, 0.04); }

/* ─── Тултипы ───────────────────────────────────────────────────────────────
   Общий механизм для всех gm-модалок: атрибут data-tip="текст" на любом
   элементе. На ПК — наведение, на тач-устройствах — тап (тап вне закрывает).
   Пузырь кладётся СОСЕДОМ .gm__card внутрь <dialog>, а не в body и не внутрь
   карточки: у .gm__card есть backdrop-filter, а он делает элемент containing
   block для position:fixed — пузырь внутри карточки позиционировался бы
   относительно неё и обрезался её скроллом. В body тоже нельзя: модалки
   открываются через .show(), то есть живут не в top layer, а на z-index 20000. */
.gm__tip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    flex: none;
    padding: 0;
    margin-left: 5px;
    border-radius: 50%;
    border: none;
    cursor: pointer;
    vertical-align: middle;
    background: rgba(120, 120, 128, 0.22);
    color: rgba(60, 60, 67, 0.75);
    font: 700 10px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui;
    transition: background .15s ease;
}
.gm__tip:hover { background: rgba(120, 120, 128, 0.34); }
#dark .gm__tip { background: rgba(255, 255, 255, 0.16); color: rgba(255, 255, 255, 0.75); }
#dark .gm__tip:hover { background: rgba(255, 255, 255, 0.26); }

.gm__tip-bubble {
    position: fixed;
    /* Пузырь работает не только в gm-модалках: для entity-popover (z-index
       10050, живёт в body) он тоже вставляется в body — с прежним z-index: 3
       тонул под поповером. Внутри <dialog> число локально его stacking
       context'у, так что большим оно не мешает. */
    z-index: 20001;
    max-width: 250px;
    padding: 9px 12px;
    border-radius: 12px;
    background: rgba(38, 38, 42, 0.97);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
    color: rgba(255, 255, 255, 0.94);
    font: 500 12.5px/1.42 -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui;
    letter-spacing: -0.1px;
    /* Переносы в data-tip (напр. «перцентиль\n\nобъяснение» у чипа спроса) */
    white-space: pre-line;
    box-shadow: 0 12px 28px -8px rgba(0, 0, 0, 0.5);
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity .16s ease, transform .16s cubic-bezier(.16, 1, .3, 1);
}
.gm__tip-bubble--on { opacity: 1; transform: none; }

/* ─── Строки рекомендации и конкуренции ─────────────────────────────────── */

.gm__ec-rec { display: flex; align-items: center; gap: 7px; }
.gm__ec-rec__price {
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.3px;
    font-variant-numeric: tabular-nums;
    color: var(--temp-brand-a);
    white-space: nowrap;
}
#dark .gm__ec-rec__price { color: var(--accent-orchid); }
/* Число лотов — не деньги, поэтому без акцентного цвета: оно не должно
   спорить с ценой строкой выше */
.gm__ec-rec__count {
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -0.2px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: rgb(28, 28, 30);
}
#dark .gm__ec-rec__count { color: rgba(255, 255, 255, 0.92); }

/* Совет по цене. Иконка повторяет метку спроса из строки выше — без неё текст
   висит сам по себе и не читается как следствие востребованности персонажа.
   Базовый .gm__msg центрирует текст, здесь нужна строка «иконка + текст». */
.gm__ec-advice {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    text-align: left;
}
.gm__ec-advice__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex: none;
    margin-top: -1px;
    border-radius: 7px;
    background: rgba(120, 120, 128, 0.16);
    color: rgba(60, 60, 67, 0.7);
}
#dark .gm__ec-advice__icon { background: rgba(255, 255, 255, 0.1); color: rgba(235, 235, 245, 0.7); }
/* Цвет иконки совпадает с меткой спроса: зелёный — можно поднимать,
   янтарный — цену лучше не задирать */
.gm__ec-advice--hot .gm__ec-advice__icon,
.gm__ec-advice--up .gm__ec-advice__icon { background: rgba(28, 158, 74, 0.14); color: var(--temp-ok-strong-b); }
#dark .gm__ec-advice--hot .gm__ec-advice__icon,
#dark .gm__ec-advice--up .gm__ec-advice__icon { background: rgba(48, 209, 88, 0.18); color: var(--ok-bright); }
.gm__ec-advice--down .gm__ec-advice__icon { background: rgba(191, 120, 0, 0.14); color: #A56A00; }
#dark .gm__ec-advice--down .gm__ec-advice__icon { background: rgba(255, 176, 32, 0.18); color: #F0A93B; }

/* ─── Обучающая плашка при отметке карточки ─────────────────────────────────
   Показывается только в момент самой отметки (ecFresh в assets/index.ejs):
   предупреждение о смысле вишлиста и напоминание иностранцу про цену лота.
   Цвета целиком от .gm__msg--warning / --soft — своих здесь нет, поэтому и
   парных #dark-правил не требуется. Свой только каркас: базовый .gm__msg —
   это ОДНА центрированная строка, а тут заголовок, пояснение и кнопки. */
.gm__ec-warn {
    display: flex;
    flex-direction: column;
    gap: 8px;
    text-align: left;
}
/* .gm__msg--warning b даёт заголовку блок и отступ снизу; здесь расстояние
   держит gap, иначе между заголовком и пояснением копятся два зазора. */
.gm__msg.gm__ec-warn b {
    margin: 0;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: 0.2px;
}
/* Пояснение — тем же цветом, но тише: заглавные строкой выше и так кричат. */
.gm__ec-warn__why { opacity: .82; font-weight: 450; }
/* Кнопки в ряд и во всю ширину плашки: «Снять отметку» — это полноценный
   выход из сценария, а не мелкая ссылка в углу. */
.gm__ec-warn__actions { display: flex; gap: 8px; flex-wrap: wrap; }
.gm__ec-warn__actions .gm__btn { flex: 1 1 auto; }
/* Одинокая кнопка («Как продавать» у не-СНГ продавца) во всю ширину читается
   как главное действие экрана, хотя это всего лишь ссылка на гайд. */
.gm__ec-warn__actions .gm__btn:only-child { flex: 0 0 auto; }

/* ─── Поля со ступенчатыми кнопками (цена, количество) ──────────────────────
   У цены шаг пропорционален ей самой (см. ecStep в assets/index.ejs): на 90 ₽
   это ±5, на 4000 ₽ уже ±200 — иначе на пятистах карточках подряд кнопки
   бесполезны. У количества шаг всегда ±1. Родные стрелки number-инпута
   гасим: рядом с нашими кнопками они выглядят мусором. */
.gm__ec-steps-field { position: relative; }
.gm__ec-steps-field input { padding-right: 92px; }
.gm__ec-steps-field input::-webkit-outer-spin-button,
.gm__ec-steps-field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.gm__ec-steps-field input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.gm__ec-steps {
    position: absolute;
    top: 50%;
    right: 7px;
    transform: translateY(-50%);
    display: flex;
    gap: 5px;
}
.gm__ec-step {
    width: 36px;
    height: 38px;
    border-radius: 10px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(120, 120, 128, 0.12);
    border: none;
    color: rgb(28, 28, 30);
    transition: background .16s cubic-bezier(.16, 1, .3, 1);
}
.gm__ec-step:hover:not(:disabled) { background: rgba(120, 120, 128, 0.2); }
.gm__ec-step:active:not(:disabled) { background: rgba(127, 45, 232, 0.18); }
.gm__ec-step:disabled { opacity: .35; cursor: default; }
#dark .gm__ec-step { background: rgba(255, 255, 255, 0.09); color: rgba(255, 255, 255, 0.92); }
#dark .gm__ec-step:hover:not(:disabled) { background: rgba(255, 255, 255, 0.15); }

/* Отклонение введённой цены от рыночной — подпись под полем. Тон зависит
   и от величины отклонения, и от спроса: у востребованного персонажа
   умеренная наценка оправдана, у непопулярного та же наценка означает,
   что покупателя придётся ждать. */
.gm__ec-dev {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.1px;
    padding: 0 4px;
    margin-top: -4px;
}
.gm__ec-dev--ok   { color: rgba(60, 60, 67, 0.5); }
.gm__ec-dev--good { color: var(--temp-ok-strong-b); }
.gm__ec-dev--warn { color: #A56A00; }
#dark .gm__ec-dev--ok   { color: rgba(235, 235, 245, 0.42); }
#dark .gm__ec-dev--good { color: var(--ok-bright); }
#dark .gm__ec-dev--warn { color: #F0A93B; }

/* Лимитный номер: «номер ИЗ тиража». Оба поля редактируемые — экземпляр
   может быть из другой партии (13 из 256 при базовом тираже 500). */
.gm__ec-limit {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 9px;
    align-items: center;
}
.gm__ec-limit__sep {
    display: inline-flex;
    align-items: center;
    font-size: 13px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__ec-limit__sep { color: rgba(235, 235, 245, 0.45); }

/* Подсказка про горячие клавиши над sticky-панелью */
.gm__ec-keys {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 11.5px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__ec-keys { color: rgba(235, 235, 245, 0.42); }
.gm__ec-keys kbd {
    padding: 2px 6px;
    border-radius: 5px;
    background: rgba(120, 120, 128, 0.14);
    font: 600 10.5px/1.4 inherit;
}
#dark .gm__ec-keys kbd { background: rgba(255, 255, 255, 0.1); }
/* На тач-устройствах клавиатуры нет — подсказка про Enter только мешает */
@media (hover: none) { .gm__ec-keys { display: none; } }

/* Ширина карточек: .gm__card--wide задаёт только max-width (см.
   docs/GLASS_MODAL_DESIGN_SYSTEM.md), поэтому нужен собственный width */
.gm__card--editcard { width: 400px; }
.gm__card--bulkprice { width: 420px; }

/* Предпросмотр массовой простановки: строка «карточка → новая цена».
   Старая цена зачёркнута рядом с новой — видно и что было, и что станет. */
.gm__bp-row { padding-top: 9px; padding-bottom: 9px; }
.gm__bp-price {
    display: flex;
    align-items: baseline;
    gap: 7px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.gm__bp-price__old {
    font-size: 12.5px;
    text-decoration: line-through;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__bp-price__old { color: rgba(235, 235, 245, 0.38); }
.gm__bp-price__new {
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: var(--temp-brand-a);
}
#dark .gm__bp-price__new { color: var(--accent-orchid); }

/* ── Модалка #feed-settings ─────────────────────────────────────────────── */
/* .gm__card--wide задаёт только max-width (см. docs/GLASS_MODAL_DESIGN_SYSTEM.md),
   поэтому ширину задаём своим модификатором */
.gm__card--feed { width: min(100% - 32px, 440px); }

/* Флаг внутри поля выбора страны (#intro-modal). Своего блока под это в
   системе не было: у .gm__field--select правый край занят стрелкой ::after,
   поэтому флаг ставим слева и сдвигаем и текст, и плавающий лейбл.

   Набор static/metronic/media/flags — КВАДРАТНЫЙ (viewBox 512×512, полотно
   залито целиком), а не флаги в своих пропорциях. Поэтому размер задаём обеими
   сторонами: width:auto тут ничего не даст, а max-width только путал бы. */
.gm__field--flag select { padding-left: 46px; }
.gm__field--flag label { left: 46px; }
.gm__field-flag {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    width: 15px;
    height: 15px;
    border-radius: 3px;
    box-shadow: 0 0 0 0.5px rgba(127, 141, 158, 0.3);
    pointer-events: none;
}
#dark .gm__field-flag { box-shadow: 0 0 0 0.5px rgba(255, 255, 255, 0.18); }

/* ─── Приглашённые (#referrals) ───────────────────────────────────────────
   Токены те же, что у остальных .gm-модалок: заливка rgba(120,120,128,.14),
   радиусы 10–12, отдельная ветка #dark. Ничего своего по цвету — экран должен
   читаться как часть системы, а не как отдельная страница. */
.gm__ref-hero {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin: 4px 0 14px;
}
.gm__ref-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 12px 6px;
    background: rgba(120, 120, 128, 0.14);
    border-radius: 12px;
}
.gm__ref-stat__n {
    font-size: 22px;
    font-weight: 600;
    letter-spacing: -0.4px;
    line-height: 1.1;
}
.gm__ref-stat__l {
    font-size: 11.5px;
    text-align: center;
    color: rgba(60, 60, 67, 0.6);
}

/* Ссылка: моноширинный хвост и кнопка копирования в одной строке. */
.gm__ref-link {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: rgba(120, 120, 128, 0.14);
    border-radius: 10px;
}
.gm__ref-link__url {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    color: rgba(60, 60, 67, 0.85);
}

/* Полоса до следующей вехи. */
.gm__ref-bar {
    height: 6px;
    border-radius: 3px;
    background: rgba(120, 120, 128, 0.2);
    overflow: hidden;
}
.gm__ref-bar__fill {
    height: 100%;
    border-radius: 3px;
    background: #0A84FF;
    transition: width .4s ease;
}

/* Статус приглашённого. Словами, не цветными точками: «ждёт» без подписи
   выглядит как ошибка, хотя это нормальное состояние. */
.gm__ref-chip {
    flex-shrink: 0;
    padding: 3px 8px;
    font-size: 11.5px;
    font-weight: 500;
    border-radius: 6px;
    background: rgba(120, 120, 128, 0.16);
    color: rgba(60, 60, 67, 0.7);
}
.gm__ref-chip--qualified { background: rgba(52, 199, 89, 0.16); color: var(--ok-strong); }

.gm__ref-user {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 2px;
}
.gm__ref-user__av {
    width: 30px; height: 30px;
    border-radius: 50%;
    object-fit: cover;
    background: rgba(120, 120, 128, 0.2);
}
.gm__ref-user__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.gm__ref-user__date { flex-shrink: 0; font-size: 11.5px; color: rgba(60, 60, 67, 0.5); }

#dark .gm__ref-stat,
#dark .gm__ref-link,
#dark .gm__ref-chip { background: rgba(118, 118, 128, 0.24); }
#dark .gm__ref-stat__l,
#dark .gm__ref-link__url,
#dark .gm__ref-chip { color: rgba(235, 235, 245, 0.6); }
#dark .gm__ref-user__date { color: rgba(235, 235, 245, 0.45); }
#dark .gm__ref-chip--qualified { background: rgba(48, 209, 88, 0.22); color: var(--ok-vivid); }
#dark .gm__ref-bar { background: rgba(118, 118, 128, 0.3); }

/* Модалка набора шире стандартных 380px: у неё три вкладки с таблицами, деревом
   структуры бокса и списком лотов. Один .gm__card--xwide этого НЕ делает —
   у .gm__card задан явный width, а max-width его не перебивает (та же ловушка
   описана у --subscription и --share). */
#set-info-modal .gm__card { width: min(100% - 32px, 560px); }

/* Модалка набора, вкладка «Шансы»: строка редкости — «сколько с бокса» слева,
   деньги справа. Иерархия в строке ровно двухступенчатая: цифра и цена крупные,
   всё остальное (источник карт, цена за карту) — мелкой серой подписью. */
.gm__si-row__meta--stack { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow: hidden; white-space: normal; line-height: 1.3; padding: 3px 0; }
.gm__si-row__meta--stack > span { color: rgb(28, 28, 30); font-weight: 500; }
#dark .gm__si-row__meta--stack > span { color: rgba(255, 255, 255, 0.92); }
.gm__si-row__meta--wrap { white-space: normal; line-height: 1.4; }
/* Цена карты — слева, второй строкой: деньги здесь справочные */
.gm__si-money { font-size: 14px; font-weight: 600; letter-spacing: -0.2px; font-variant-numeric: tabular-nums; }
.gm__si-money--none { font-weight: 500; }
.gm__si-row__meta--stack > .gm__si-money--none { color: rgba(60, 60, 67, 0.45); }
#dark .gm__si-row__meta--stack > .gm__si-money--none { color: rgba(235, 235, 245, 0.4); }
.gm__si-sub { font-size: 11.5px; line-height: 1.35; color: rgba(60, 60, 67, 0.5); }
#dark .gm__si-sub { color: rgba(235, 235, 245, 0.4); }
/* Сколько карт с бокса — главная цифра строки: вкладку открывают ради неё.
   Перенос разрешён: «≈ 1 шт на 3 200 боксов» в одну строку не влезает. */
.gm__si-row__price--lg { font-size: 17.5px; letter-spacing: -0.4px; white-space: normal; text-align: right; }
/* Крупно — только само число: «≈» и единица измерения идут мелким по бокам,
   иначе служебный знак и слово занимают больше места, чем значение */
.gm__si-approx {
    margin-right: 4px;
    font-size: 12px;
    font-style: normal;
    font-weight: 500;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__si-approx { color: rgba(235, 235, 245, 0.45); }
.gm__si-unit {
    /* Отступ именно margin'ом: между {{ значением }} и <i> в in-DOM шаблоне
       пробела нет — Vue его вырезает (см. «слипается MAX+20₩») */
    margin-left: 6px;
    font-size: 12px;
    font-style: normal;
    font-weight: 500;
    letter-spacing: -0.1px;
    color: rgba(60, 60, 67, 0.5);
}
#dark .gm__si-unit { color: rgba(235, 235, 245, 0.45); }
/* У цены та же логика, только кегль меньше: она сама второстепенна */
.gm__si-money .gm__si-unit { font-size: 11.5px; margin-left: 5px; }

/* На узком экране «500 000 ₽ за карту» и «≈ 1 шт на 3 200 боксов» в одну
   строку не помещаются и рвутся по слогам. Раскладываем строку в два этажа:
   сверху главная цифра, снизу деньги — чип остаётся слева на оба этажа. */
@media (max-width: 560px) {
    .gm__si-row--static { grid-template-columns: auto minmax(0, 1fr); row-gap: 2px; }
    .gm__si-row--static > .gm__si-row__chip { grid-row: 1 / span 2; align-self: center; }
    .gm__si-row--static > .gm__si-row__price {
        grid-column: 2;
        grid-row: 1;
        align-items: flex-start;
        text-align: left;
    }
    .gm__si-row--static > .gm__si-row__meta--stack { grid-column: 2; grid-row: 2; padding: 0 0 3px; }
    /* Матожидание в деньгах на телефоне остаётся только в тултипе: три строки
       цифр в строке списка — это уже не список, а простыня */
    .gm__si-row--static > .gm__si-row__price small { display: none; }
    .gm__si-money { font-size: 12.5px; font-weight: 500; }
    .gm__si-money .gm__si-unit { font-size: 11px; margin-left: 4px; }
}

/* Примечания под деревом структуры: репринты, лимиты повторок, годпаки.
   Редкость вынесена в отдельную колонку и держит контраст — без неё
   строки «R 001-018 · 18 карт» слипались в одно серое полотно. */
.gm__si-notes { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.gm__si-note { display: flex; flex-direction: column; gap: 4px; }
.gm__si-note__head {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: rgba(60, 60, 67, 0.45);
}
#dark .gm__si-note__head { color: rgba(235, 235, 245, 0.38); }
/* Тот же ритм, что у треков дерева: редкость слева, пояснение по центру,
   число по правому краю — иначе примечания висят слева одним комом */
.gm__si-note__part {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 10px;
    font-size: 12.5px;
    line-height: 1.5;
    color: rgba(60, 60, 67, 0.6);
}
#dark .gm__si-note__part { color: rgba(235, 235, 245, 0.5); }
.gm__si-note__rar {
    padding: 2px 8px;
    border-radius: 7px;
    background: rgba(120, 120, 128, 0.1);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: -0.1px;
    color: rgb(28, 28, 30);
}
#dark .gm__si-note__rar { background: rgba(255, 255, 255, 0.07); color: rgba(255, 255, 255, 0.92); }
.gm__si-note__part > .gm__si-note__txt:first-child { grid-column: 1 / 3; }
.gm__si-note__val { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* ── Компактный диалог: gmConfirm / gmAlert / gmPrompt ──────────────────
   Шапка с крестиком по умолчанию НЕ рисуется: у окна всегда есть кнопка
   действия, а пустая строка в 40px наверху («лоб») съедала высоту и
   заставляла давать заголовку боковые отступы под крестик — с ними
   «Удалить портрет?» и «Купить карточку?» ломались на две строки
   (замерено). Крестик и «назад» включаются опциями closable / onBack,
   тогда шапка появляется и верхний отступ берётся из неё.

   ОТСТУПЫ. Здесь они заданы ОДИН раз и только сверху у каждого блока,
   а gap флекса погашен. До этого gap:14 складывался с собственными
   маржинами блоков и с инлайновыми в разметке, и получался разнобой
   21 / 14 / 36 / 30 / 25 пикселей. Теперь ритм читаемый:
   24 (край) · 8 (заголовок↔текст — это одна пара) · 16 (плашка/поле)
   · 20 (перед кнопками) · 24 (край). */
.gm__card--ask .gm__view { gap: 0; padding-top: 0; }

.gm__card--ask .gm__title { margin: 0; }
.gm__card--ask .gm__subtitle { margin: 8px 0 0; }
.gm__card--ask .gm__msg,
.gm__card--ask .gm__field { margin: 16px 0 0; }
.gm__card--ask .gm__row,
.gm__card--ask .gm__view > .gm__btn { margin: 20px 0 0; }

/* Без шапки заголовку нужен свой воздух сверху: у .gm__card задан
   padding 12px 24px 24px, где 12 наверху рассчитаны на шапку.

   Два имени у одного правила: --ask-bare ставит gm-dialog.js своим кодом
   (переименование там — правка JS ради косметики), --bare пишут руками в
   разметке. Новым окнам без шапки брать --bare.

   На телефоне не работает и не должно: шторка задаёт .gm__card свой
   padding-top: 8px селектором dialog.gm .gm__card — он специфичнее, и место
   сверху там занимает хват. */
.gm__card--ask-bare,
.gm__card--bare { padding-top: 24px; }
