/* ==========================================================================
   TIER shell — the floating tab bar and the overhead light.

   Both are traced off app.mira.top rather than reinvented: the geometry,
   radii, fill values and easing below are the computed styles read straight
   off that app's .app-nav-bar / top-down-gradient elements. The class names
   stay TIER's, so app.js keeps driving the bar through the hooks it already
   owns — `.is-active` on each button and `data-active` on the nav.

   Loads last, after tier.css, because the bar is currently described three
   times over (market.css, glass.css, tier.css) and those passes disagree.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Typeface

   lawx drives its components off --ui-font and sets that to Onest. TIER
   already ships SF Pro — the real iOS system face, and what its own sheets
   hardcode — so the token is pointed at that instead. Without this the
   lawx-derived components would render in one face and TIER's in another.
   Apple Color Emoji stays at the end of the stack; tier-ui.css serves it.
   -------------------------------------------------------------------------- */
@font-face {
    font-family: "Roboto";
    src: url("/fonts/roboto-variable.sub.woff2") format("woff2");
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
}

@font-face {
    font-family: "Racama";
    src: url("/fonts/racama.woff2?v=20260918") format("woff2");
    font-style: normal;
    /* One master, declared at 400 only: with a range the browser would map every
       weight onto it and the whole hierarchy would flatten to a single weight.
       Left at 400 it synthesises the heavier steps and headings still read. */
    font-weight: 400;
    font-display: swap;
}

/* Wallet uses the native Apple face on iOS and Roboto on other platforms. */
html,
body,
button,
input,
textarea,
select,
* {
    font-family: var(--ui-font) !important;
}

html[data-ios-emoji],
:root {
    --ui-font: -apple-system, "Roboto", "SF Pro", sans-serif;
    --pm-font: var(--ui-font);
    --safe-b: max(env(safe-area-inset-bottom, 0px), var(--ui-safe-bottom, 0px));
    --tabbar-h: 64px;
    --tier-nav-gap: 16px;
    --tier-nav-bg: #1c1c1e;
    --tier-nav-selected: #303034;
    --tier-nav-ink: #a8c7ef;
    --tier-dock-height: 64px;
    --tier-edge: rgba(255, 255, 255, .16);
    /* @wallet's card colour: var(--tg-theme-section-bg-color), rgb(28,28,30) on
       its dark theme. Flat, no bevel, no gradient. */
    --tier-tile-bg: rgb(28, 28, 30);
    /* The confirm button and the light in the room share one muted slate. */
    --tier-muted: #8191a9;
    --tier-muted-sheen: #aebbcd;
    /* One sheet colour for the panel, its header and the footer scrim. tier.css
       and market.css each hardcode their own near-black here (#121214, #141416),
       which left a seam under the create button and broke outright in light. */
    --tier-sheet-bg: #121214;
}

#catalogViewTab {
    font-family: "Racama", sans-serif !important;
}

html {
    height: 100%;
    overflow: hidden !important;
}

body {
    height: 100dvh;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-gutter: auto;
}

html, body, body * {
    scrollbar-width: none !important;
}

html::-webkit-scrollbar, body::-webkit-scrollbar, body *::-webkit-scrollbar {
    display: none !important;
    width: 0 !important;
    height: 0 !important;
}

html[data-theme="light"] {
    --tier-glow-top: #c7d3e4;
    --tier-glow-bloom: #dbe2ec;
    --tier-edge: rgba(30, 40, 60, .1);
    --tier-tile-bg: #ffffff;
    /* Grouped-list grey, not white: the cards inside the sheet are white, and
       on a white sheet they disappeared entirely. */
    --tier-sheet-bg: var(--ui-bg);

    /* tier.css is a dark-only palette — its ink is white alpha and its surfaces
       are near-black, hardcoded in ~25 rules. Repointing the tokens here turns
       all of them over at once instead of chasing each rule. */
    --ink: var(--ui-text);
    --ink-2: var(--ui-text-2);
    --ink-3: var(--ui-hint);
    --bg: var(--ui-bg);
    --surface-1: #ffffff;
    --surface-2: #f2f2f7;
    --surface-3: #ffffff;
    --hairline: rgba(30, 40, 60, .12);
    --hairline-strong: rgba(30, 40, 60, .2);
    --tg-separator: rgba(30, 40, 60, .16);

    /* portals.css is dark-only in the same way: --pm-primary is a near-white
       that carries the back button's label and the picked row in the category
       list, both of which went invisible on a light page. */
    --pm-text: var(--ui-text);
    --pm-primary: var(--ui-text);
    --pm-text-muted: var(--ui-hint);
    --pm-surface: var(--ui-card);
}

/* --------------------------------------------------------------------------
   Page ground

   tier.css pins html to its own --bg with !important, which left the page a
   shade lighter than the black the glow resolves into — the seam showed as a
   hard line straight across the screen where the glow ended.
   -------------------------------------------------------------------------- */
html,
body,
body.oem-body {
    background: var(--ui-bg) !important;
}

html[data-theme] body.oem-body {
    background: transparent !important;
}

.market-cart-sheet {
    background: var(--tier-sheet-bg) !important;
    color: var(--ui-text);
}

/* A picker is a plain card, not a grouped list, so it stays the card colour. */
html[data-theme="light"] .oem-sheet,
html[data-theme="light"] .oem-picker.ui-modal {
    background: var(--ui-card) !important;
    color: var(--ui-text);
}

.market-cart-header {
    background: var(--tier-sheet-bg);
}

/* The create button sits in the sheet's bottom bar. market.css clears that
   bar's background and tier.css paints a short gradient in its own near-black,
   so the button floated over a fully legible settings row and its rounded edge
   cut straight across the card behind it. Telegram's own sheets end in a solid
   bar over a hairline instead of a fade — content passes cleanly under it. */
.market-checkout-bar {
    padding-top: 14px !important;
    background: var(--tier-sheet-bg) !important;
    box-shadow: inset 0 .5px 0 var(--tier-edge);
}

/* The picked emoji in the sheet use the same flat card as the catalog tiles. */
.market-cart-preview {
    background: var(--tier-tile-bg) !important;
    box-shadow: none !important;
}

/* Three surfaces in the sheet are painted with a white alpha rather than a
   token, so light theme left them invisible on the white-ish panel. */
html[data-theme="light"] .market-pack-type {
    background: var(--ui-fill-2);
}

/* The thumb is white on a light track, so it needs the iOS lift to read. */
html[data-theme="light"] .market-pack-type-button.is-active {
    box-shadow: 0 3px 8px rgba(30, 40, 60, .12), 0 3px 1px rgba(30, 40, 60, .04);
}

html[data-theme="light"] .oem-emoji {
    background: var(--ui-fill-2) !important;
    color: var(--ui-text) !important;
}

html[data-theme="light"] .market-settings-card.ui-card,
html[data-theme="light"] .market-cart-sheet .ui-card {
    background: var(--ui-card);
}

/* Glyphs and glass bevels drawn in white alpha: invisible on a light sheet. */
html[data-theme="light"] .oem-emoji svg {
    fill: var(--ui-text-2) !important;
    color: var(--ui-text-2) !important;
}

html[data-theme="light"] .market-close-button {
    background: var(--ui-fill-2);
    box-shadow: none;
    color: var(--ui-hint);
}

html[data-theme="light"] .oem-sheet-handle,
html[data-theme="light"] .market-cart-sheet .oem-sheet-handle {
    background: rgba(30, 40, 60, .2);
}

/* market.css paints the create button as dark glass — a black tint plus a
   white-alpha bevel — for both states, with !important throughout. On a light
   sheet that is a grey slab with white text on it. Light gets the plain iOS
   pair instead: accent when it can be pressed, a filled grey when it cannot. */
html[data-theme="light"] .market-create-cta.ui-cta > .market-create-button.ui-button {
    background: var(--ui-accent) !important;
    box-shadow: 0 4px 14px rgba(30, 40, 60, .16) !important;
    color: #fff !important;
}

html[data-theme="light"] .market-create-cta.ui-cta--off > .market-create-button.ui-button:disabled {
    background: var(--ui-fill-2) !important;
    box-shadow: none !important;
    color: var(--ui-hint) !important;
}

/* A swatch showing #FFFFFF has nothing to show against a white card. The dark
   theme gets this free from portals.css's white-alpha ring; light needs its
   own hairline, drawn on the edge so it works for any fill. */
html[data-theme="light"] .oem-color-swatch {
    outline: .5px solid rgba(30, 40, 60, .22);
    outline-offset: -.5px;
}

/* The chat preview is a mock of a Telegram thread, so it follows the client:
   a grey incoming bubble with dark text, not the dark one. The :after is the
   tail's cut-out and has to match the canvas it sits on. */
html[data-theme="light"] .market-chat-bubble,
html[data-theme="light"] .market-chat-bubble:before {
    background: #e9e9eb;
}

html[data-theme="light"] .market-chat-bubble {
    color: var(--ui-text);
}

html[data-theme="light"] .market-chat-bubble:after {
    background: var(--ui-card);
}

html[data-theme="light"] .market-chat-time {
    color: rgba(60, 60, 67, .45);
}

/* --------------------------------------------------------------------------
   Surface reset

   Four sheets describe the same surfaces here — liquid-glass.css, portals.css,
   market.css and tier.css each paint .ui-card, .oem-pager, .ui-icon-button and
   the filter pill, with frosted fills, specular rims and 56px squircles. The
   reference is flat: a plain fill at one radius, no blur, no rim. This strips
   the accumulated decoration back to that.
   -------------------------------------------------------------------------- */
.ui-card,
.ui-draglist,
.oem-pager,
.market-pager,
.market-pager.oem-pager,
.oem-pager.market-pager,
.ui-card.market-settings-card,
.market-settings-card.ui-card,
.market-preview-card.ui-card,
.market-summary-card.ui-card,
#packsScreen .ui-card {
    border: 0 !important;
    border-radius: var(--ui-radius-card) !important;
    background: var(--ui-card) !important;
    box-shadow: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    corner-shape: normal;
}

/* The specular rims are ::before overlays, so they survive any change to the
   element's own box-shadow and have to be switched off by name. */
.market-hero-banner::before,
.market-pager.oem-pager::before,
.market-filter-pill::before,
.market-cart-sheet::before,
.ui-card::before {
    display: none !important;
}

/* Round chrome: transparent at rest, filled on press — lawx's .ui-icon-button. */
.ui-icon-button,
.oem-nav-btn,
.market-page-button.ui-icon-button,
.market-page-button.oem-nav-btn {
    border: 0 !important;
    background: var(--ui-fill) !important;
    box-shadow: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    color: var(--ui-text);
}

.ui-icon-button:active:not(:disabled),
.oem-nav-btn:active:not(:disabled) {
    background: var(--ui-fill-2) !important;
}

/* The collection chip, rebuilt as lawx's .ui-chip. */
.market-filter-pill {
    height: 44px;
    min-height: 44px;
    padding: 0 14px;
    border: 0 !important;
    border-radius: var(--ui-radius-pill) !important;
    background: var(--ui-card-raised) !important;
    box-shadow: inset 0 0 0 1px var(--tier-edge), inset 0 1px 0 #ffffff08 !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    color: var(--ui-text);
    font-family: var(--ui-font) !important;
    font-size: 15px !important;
    font-weight: 590 !important;
}

.market-filter-pill:active {
    background: var(--ui-fill-2) !important;
    transform: scale(.97);
}

/* --------------------------------------------------------------------------
   The overhead light

   Three stacked layers, in mira's own order: the page colour climbing back up
   from the bottom edge, the cyan bloom, and the indigo wash coming down from
   the top. The skirt carries that indigo 1000px above the scroll origin so it
   bleeds into the Telegram header instead of ending in a seam on overscroll.
   -------------------------------------------------------------------------- */
:root {
    /* The blue the page had before, pulled back to the muted slate the user
       picked (#8191a9) so it reads as light in the room rather than paint. */
    --tier-glow-top: #4b6c9c;
    --tier-glow-bloom: #8191a9;
    --tier-glow-h: 420px;
}

.tier-glow {
    /* Anchored to the top of the document, not the viewport. Fixed, it rode
       down with the scroll and the light followed you instead of staying where
       the header is. */
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: var(--tier-glow-h);
    z-index: -3;
    pointer-events: none;
    overflow: hidden;
    opacity: var(--glow-strength, 1);
    /* The wash that pins the light to the top edge. The moving part is the two
       blooms below; this layer never moves, so nothing detaches from the header. */
    /* The lower stop runs most of the height so the wash dissolves into the page
       instead of ending on a visible line part-way down. */
    background:
        linear-gradient(to top, var(--ui-bg) 0, color-mix(in srgb, var(--ui-bg) 40%, transparent) 38%, transparent 78%),
        linear-gradient(var(--tier-glow-top) -24%, transparent 82%);
}

/* Two slow, offset blooms drifting behind the wash: the light breathes instead
   of sitting there as a static gradient, and both stay inside the top band. */
.tier-glow::before,
.tier-glow::after {
    content: "";
    position: absolute;
    top: -40%;
    left: -30%;
    width: 80%;
    height: 120%;
    border-radius: 50%;
    filter: blur(42px);
    opacity: .85;
    background: radial-gradient(closest-side, var(--tier-glow-bloom), transparent 72%);
    will-change: transform, opacity;
    animation: tier-glow-drift-a 13s ease-in-out infinite alternate;
}

.tier-glow::after {
    left: auto;
    right: -34%;
    width: 72%;
    opacity: .6;
    background: radial-gradient(closest-side, var(--tier-glow-top), transparent 74%);
    animation: tier-glow-drift-b 17s ease-in-out infinite alternate;
    animation-delay: -6s;
}

/* Wide, plainly visible travel — the earlier 7% nudge under a 58px blur was
   technically animating and looked static. */
@keyframes tier-glow-drift-a {
    0%   { transform: translate3d(0, 0, 0) scale(1); opacity: .85; }
    50%  { transform: translate3d(55%, 12%, 0) scale(1.25); opacity: .62; }
    100% { transform: translate3d(104%, -6%, 0) scale(1.05); opacity: .88; }
}

@keyframes tier-glow-drift-b {
    0%   { transform: translate3d(0, 0, 0) scale(1.1); opacity: .6; }
    50%  { transform: translate3d(-62%, 16%, 0) scale(.9); opacity: .82; }
    100% { transform: translate3d(-112%, -4%, 0) scale(1.18); opacity: .55; }
}

.tier-glow__skirt {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1000px;
    transform: translateY(-100%);
    background: var(--tier-glow-top);
}

/* Not decoration: painting a 1px dot on an 80x80 canvas promotes the layer to
   the GPU, which is what stops the wide gradient banding in Telegram's WebView. */
.tier-glow__canvas {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0;
    opacity: 0;
}

/* --------------------------------------------------------------------------
   Bottom tab bar

   mira floats a glass pill with a fill that slides between tabs. Its panel
   spans 336 of a 393pt screen — sizing TIER's two tabs to their content
   instead left a stub floating in the middle, so the bar is given the same
   share of the width and the tabs divide it.

   It also gets a scrim. mira can go without one because its pill sits on a
   quiet page; TIER's sits directly over the pager and the catalogue grid,
   which read straight through the glass. This is a wide soft fade, not the
   hard band the previous build drew.
   -------------------------------------------------------------------------- */
.tier-bottom-scrim {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--tabbar-h) + 52px + var(--safe-b));
    z-index: 69;
    pointer-events: none;
    /* The wash is drawn on ::after, not here. Its own background would paint
       underneath the blur layers, which would then be blurring the wash instead
       of the page — and at any real density that is a blur of flat black. Blur
       first, tint over the top. */
    background: none;
}

/* Properly dark under the chrome, just never a solid slab. Two failure modes
   here and the gap between them is narrow: a flat opaque bottom reads as a
   black bar stuck to the screen, and a wash this light stops reading as a
   darkening at all. The blur carries the separation; the wash still has to look
   like black is there. */
.tier-bottom-scrim::after {
    content: "";
    position: absolute;
    inset: 0;
    display: block;
    pointer-events: none;
    background: linear-gradient(
        to top,
        color-mix(in srgb, var(--ui-bg) 80%, transparent) 0%,
        color-mix(in srgb, var(--ui-bg) 68%, transparent) 48%,
        color-mix(in srgb, var(--ui-bg) 36%, transparent) 74%,
        transparent 100%);
}

/* Progressive blur under the floating chrome.

   One blurred layer with a faded mask gives a blur that is either on or off at
   any given height — the mask only fades how much of the blurred copy shows,
   not how blurred it is. Three layers instead, each masked to a shorter band at
   the bottom: a layer's backdrop includes whatever was painted below it, the
   previous blurred layer included, so their radii compound and the blur ramps
   from nothing at the top to the full amount at the bottom edge.

   They sit inside the scrim, which is a plain div with no fixed descendants —
   backdrop-filter would otherwise turn it into their containing block.

   The band is taller than the scrim and does NOT follow its box. Matching it
   put the heavy end of the ramp in the scrim's bottom third: measured against
   the live page, the blur changed nothing above 116px from the bottom edge, and
   the 64px it did change sit behind an opaque bar. Content shows above the bar,
   and in the 75px strips either side of it since the bar is 240 of 390 wide, so
   the ramp covers that instead — but only just: run longer and the whole bottom
   of the page reads as going soft. */
.tier-bottom-blur {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--tabbar-h) + 76px + var(--safe-b));
    display: block;
    pointer-events: none;
}

body.market-has-cart .tier-bottom-blur {
    height: calc(var(--tabbar-h) + var(--tier-dock-height) + 76px + var(--safe-b));
}

.tier-bottom-blur[data-step="1"] {
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 60%, transparent 100%);
    mask-image: linear-gradient(to top, #000 0%, #000 60%, transparent 100%);
}

.tier-bottom-blur[data-step="2"] {
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 34%, transparent 76%);
    mask-image: linear-gradient(to top, #000 0%, #000 34%, transparent 76%);
}

.tier-bottom-blur[data-step="3"] {
    -webkit-backdrop-filter: blur(11px);
    backdrop-filter: blur(11px);
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 14%, transparent 48%);
    mask-image: linear-gradient(to top, #000 0%, #000 14%, transparent 48%);
}

/* The correct query for this is transparency, not motion — the blur is static,
   it is the see-through effect a user turns off. The wash above it is already
   dense enough to stand on its own. */
@media (prefers-reduced-transparency: reduce) {
    .tier-bottom-blur {
        display: none;
    }

    .tier-bottom-scrim::after {
        background: linear-gradient(
            to top,
            var(--ui-bg) 0%,
            color-mix(in srgb, var(--ui-bg) 88%, transparent) 62%,
            transparent 100%);
    }
}

/* With the dock on screen the covered band is taller, so the solid part has to
   reach past the dock's top edge before it starts to fade. */
body.market-has-cart .tier-bottom-scrim {
    height: calc(var(--tabbar-h) + var(--tier-dock-height) + 64px + var(--safe-b));
}

body.market-has-cart .tier-bottom-scrim::after {
    background: linear-gradient(
        to top,
        color-mix(in srgb, var(--ui-bg) 84%, transparent) 0%,
        color-mix(in srgb, var(--ui-bg) 72%, transparent) 66%,
        color-mix(in srgb, var(--ui-bg) 38%, transparent) 84%,
        transparent 100%);
}

/* @wallet's bar, transcribed from its bundle rather than eyeballed:
     .yEKB7  radius 100px, padding var(--container-padding,4px), gap --tab-spacing,
             background rgb(from var(--tg-theme-section-bg-color) r g b/70%)
     .jML7Q  backdrop-filter: saturate(300%) blur(8px)
     .PaKio  box-shadow: 0 0 10px 0 #0000001a
     .yEKB7 > [data-first-tab] / [data-last-tab]  margin-inline: --tab-spacing
   With --tab-spacing at 8px that first/last margin folds into the side padding,
   so 4px all round becomes 4px 12px here. Measured inset is 21pt a side and the
   bar sits flush on the safe area with no gap under it. */
.market-tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--safe-b) + var(--tier-nav-gap));
    z-index: 70;
    margin-inline: auto;
    width: 240px;
    max-width: calc(100% - 32px);
    margin-left: auto;
    margin-right: auto;
    height: var(--tabbar-h);
    /* 2px. Everything below is re-derived from it: content box is
       240 - 2 border - 4 padding = 234, two tabs and a 4px gap, so a tab is
       (234 - 4) / 2 = 115 and the second one starts 119 along. */
    padding: 2px !important;
    box-sizing: border-box;

    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 4px;
    grid-template-columns: none;
    grid-auto-flow: unset;
    grid-auto-columns: unset;

    /* Dimmed a step: #414145 sat brighter than the fill it separates. */
    border: 1px solid #333338;
    border-radius: 100px;
    /* .KaTw3[data-theme=material] .yEKB7 — the glass variant, which is the one
       the client actually shows. Not the flat `apple` variant. */
    background: var(--tier-nav-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
    isolation: isolate;
    overflow: hidden;
    transform: none;
    transition: background-color .2s ease-out;
}

/* Same rule, resolved against the light section colour. */
html[data-theme="light"] .market-tabbar {
    background: #f2f2f7;
    border-color: #d1d1d6;
}

html[data-theme="light"] .market-tabbar::after {
    background: #e1e1e6;
}

html[data-theme="light"] #catalogTab,
html[data-theme="light"] #packsTab {
    color: #50596a;
}

html[data-theme="light"] #catalogTab.is-active,
html[data-theme="light"] #packsTab.is-active {
    color: #3677bd;
}

/* .KaTw3[data-theme=material] .yEKB7:after — the lit rim. Two white hairlines
   on the top and bottom edges, laid over the glass in soft-light so they read
   as light caught on a bevel rather than a drawn border. */
.market-tabbar::before {
    content: "" !important;
    display: none !important;
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    box-shadow: inset 0 1px 0 0 #ffffff80, inset 0 -.5px 0 0 #ffffff80;
    mix-blend-mode: soft-light;
    pointer-events: none;
    background: none;
}

/* market.css reserves room inside the bar for a cart segment that now lives in
   its own dock above it. Left alone it narrows the bar and adds a 66px right
   pad the moment something is selected, so the fill overhangs the tabs. */
body.market-has-cart .market-tabbar,
body.market-has-cart:not(.oem-packs-active) .market-tabbar {
    width: 240px;
    padding: 2px !important;
}

.market-tabbar:active {
    background-color: var(--tier-nav-bg);
    transform: none;
}

@media (min-width: 600px) {
    .market-tabbar,
    body.market-has-cart .market-tabbar,
    body.market-has-cart:not(.oem-packs-active) .market-tabbar {
        width: 240px;
        margin-inline: auto;
    }
}

/* @wallet's .nK_WK overlay: background var(--tertiary-fill-background) —
   rgba(118,118,128,.24) resolved — radius 100px, inset at the container
   padding. There it holds a second copy of the row and is revealed with an
   animated clip-path; with two tabs a solid pill that slides is the same
   picture. The tabs are (W - 24 - 8)/2 wide, so the pill is 50% - 16px. */
.market-tabbar::after {
    content: "";
    display: block;
    position: absolute;
    top: 2px;
    bottom: 2px;
    left: 2px;
    z-index: 0;
    /* glass.css pins an explicit height on this pseudo-element (62 - 8), which
       beats the top/bottom pair and left a taller gap under the fill than over
       it. `auto` hands sizing back to the insets so it is centred. */
    height: auto;
    width: 115px;
    border-radius: 100px;
    /* .KaTw3[data-theme=material] .nK_WK — the glass variant tints the thumb
       with the accent at 10%, not the grey the flat variant uses. */
    background: var(--tier-nav-selected);
    box-shadow: none;
    translate: none;
    transform: translateX(0);
    transition: transform .28s cubic-bezier(.22, 1, .36, 1);
}

.market-tabbar[data-active="packs"]::after {
    width: 115px;
    /* market.css declares `translate` (the standalone property) on this very
       selector. It is not overridden by `transform` — the two compose — so the
       fill was being shifted twice and slid out past the bar's right end. */
    translate: none;
    transform: translateX(119px);
}

.market-tabbar-item {
    position: relative;
    z-index: 2;
    box-sizing: border-box;
    display: flex;
    flex: 0 0 115px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 0;
    min-height: 0;
    width: 115px;
    height: 100%;
    /* .o7k40[data-theme=material] { padding-block: 5px } */
    padding: 5px 0;

    border: 0;
    border-radius: 100px;
    background: none;
    /* .o7k40: the text colour for every tab — an idle tab is dimmed, not
       repainted grey. The glass variant uses .9. */
    color: #e0e2e8;
    opacity: 1;
    font-family: inherit;
    font-size: 11px;
    font-weight: 510;
    line-height: 13px;
    letter-spacing: 0;
    transition: color .2s ease-out, opacity .2s ease-out;
}

/* glass.css tints the idle tab with its own washed blue and singles out
   #packsTab by id, so both states are restated here at id specificity —
   otherwise the two tabs disagree about what "idle" looks like. */
#catalogTab.market-tabbar-item,
#packsTab.market-tabbar-item {
    color: #e0e2e8;
    opacity: 1;
}

.market-tabbar-item.is-active,
#catalogTab.market-tabbar-item.is-active,
#packsTab.market-tabbar-item.is-active {
    /* Always the design system's own blue. An earlier pass read Telegram's
       --tg-theme-link-color here, which let a user's client theme repaint the
       active tab — on a red theme the bar came out red. The app's identity is
       not the user's theme, so nothing here reads from the client palette. */
    color: var(--tier-nav-ink);
    background: none;
    /* .yEKB7 [data-active-tab] { opacity: var(--active-tab-opacity, 1) } */
    opacity: 1;
    font-size: 11px;
    font-weight: 510;
}

.market-tabbar-item:active {
    transform: none;
}

/* Tapping a tab must not draw a ring around it. Two sheets ring every <button>
   on the page: app.css in gold at rgba(212,168,83,.5), and tier.css in the
   accent with a 2px offset and `border-radius: var(--r-xs)` — a small square
   radius, so the ring did not even follow the pill it was drawn around. Which
   tab is selected is already said by the fill and the colour, so the ring
   carried nothing. Scoped to the bar: every other control in the app keeps its
   focus ring. */
.market-tabbar-item:focus,
.market-tabbar-item:focus-visible,
.market-tabbar:focus,
.market-tabbar:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}

/* mira's icons are solid shapes in a 40x32 slot above the label. TIER's were
   hairline outlines at 21px, which is what made them read as weak next to the
   reference; index.html now carries filled paths and they get the full slot. */
.market-tabbar-icon {
    display: flex !important;
    align-items: center;
    justify-content: center;
    width: 40px;
    /* .o7k40[data-theme=material] .LcPDp > svg { height: 24px } */
    height: 24px;
    flex: none;
}

/* The static glyph: what the tab shows until its Lottie is mounted, and what it
   keeps showing if the player never loads. Matched on `>` so it never catches
   the SVG lottie-web builds inside the holder below. */
.market-tabbar-icon > svg,
.market-tabbar-glyph {
    width: 24px;
    height: 24px;
    fill: currentcolor;
    stroke: none;
}

/* --------------------------------------------------------------------------
   Animated tab icons

   Each tab carries a Lottie that plays once, on arrival — a still icon the rest
   of the time. app.js mounts it and sets `has-lottie`, which is the only thing
   that hides the fallback: until then, and forever if the fetch fails, the tab
   still has an icon.
   -------------------------------------------------------------------------- */
.market-tabbar-lottie {
    display: block;
    width: 24px;
    height: 24px;
    flex: none;
    pointer-events: none;
}

/* tier.css pins `.market-tabbar-icon svg` at 21px with a descendant selector,
   which reaches inside the holder; the player's canvas has to fill it. */
.market-tabbar-lottie svg {
    display: block;
    width: 100% !important;
    height: 100% !important;
    overflow: visible;
}

.market-tabbar-icon.has-lottie > .market-tabbar-glyph {
    display: none;
}

/* The packs tab draws its fallback with a mask on ::before rather than an svg. */
.market-tabbar-icon.has-lottie::before {
    display: none !important;
}

/* Flat-black artwork repainted in the tab's own colour, so it follows active and
   idle like the glyph it replaces. Only for tints marked in the markup —
   forcing this on a shaded illustration would flatten it to a silhouette. */
.market-tabbar-icon[data-lottie-tint="ink"] .market-tabbar-lottie svg * {
    fill: currentColor !important;
}

.market-tabbar-label {
    display: block;
    /* One step up from the reference's 13px, as asked. The line box stays at 16px:
       the item's content height is exactly 44px (54 inner − 2×5 padding), and
       24 icon + 4 gap + 16 line fills it with nothing to spare, so growing the
       leading instead of the glyphs would clip the row. */
    font-size: 14px;
    line-height: 16px;
    font-weight: 500;
    white-space: nowrap;
}

.tier-packs-icon::before {
    content: "";
    width: 24px;
    height: 24px;
    background: currentColor;
    -webkit-mask: url('/cart.svg?v=20260918') center / contain no-repeat;
    mask: url('/cart.svg?v=20260918') center / contain no-repeat;
}

/* The cart dock rides above the bar, so it clears the new 62px pill. */
.market-cart-dock {
    bottom: calc(var(--safe-b) + var(--tier-nav-gap) + var(--tabbar-h) + 10px);
}

@media (prefers-reduced-motion: reduce) {
    .market-tabbar,
    .market-tabbar::after,
    .market-tabbar-item {
        transition: none;
    }

    .tier-glow::before,
    .tier-glow::after {
        animation: none;
    }

    .oem-template-tile--selected .oem-template-preview::before,
    .oem-template-tile--selected .oem-template-preview::after,
    .oem-template-tile--unselecting .oem-template-preview::before,
    .oem-template-tile--unselecting .oem-template-preview::after {
        animation: none !important;
    }

    .market-tabbar-lottie {
        display: none;
    }

    .market-tabbar-icon.has-lottie > .market-tabbar-glyph {
        display: block;
    }

    .market-tabbar-icon.has-lottie::before {
        display: block !important;
    }

    html.tier-reveal .oem-template-tile {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* --------------------------------------------------------------------------
   Emoji coverage for TIER's own font stacks

   tier-ui.css registers Apple Color Emoji as six unicode-range subsets, and
   --ui-font puts that family at the end of the stack. TIER's older sheets,
   though, hardcode `"SF Pro", ... sans-serif` and `"Montserrat", ...` with no
   emoji family at all, so those screens never reached the face and fell back
   to whatever the device ships.

   Rather than rewrite every one of those declarations, the same subsets are
   registered a second time *under those family names*. A family may hold many
   faces with disjoint unicode-ranges, so "SF Pro" keeps its own glyphs for
   text and picks these up for emoji codepoints — which is precisely what
   unicode-range is for.
   -------------------------------------------------------------------------- */

@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-001.ttf") format("truetype"); unicode-range: U+A9, U+AE, U+200C-200D, U+203C, U+2049, U+20E3, U+2122, U+2139, U+2194-2199, U+21A9-21AA, U+231A-231B, U+2328, U+23CF, U+23E9-23F3, U+23F8-23FA, U+24C2, U+25AA-25AB, U+25B6, U+25C0, U+25FB-25FE, U+2600-2604, U+260E, U+2611, U+2614-2615, U+2618, U+261D, U+2620, U+2622-2623, U+2626, U+262A, U+262E-262F, U+2638-263A, U+2640, U+2642, U+2648-2653, U+265F-2660, U+2663, U+2665-2666, U+2668, U+267B, U+267E-267F, U+2692-2697, U+2699, U+269B-269C, U+26A0-26A1, U+26A7, U+26AA-26AB, U+26B0-26B1, U+26BD-26BE, U+26C4-26C5, U+26C8, U+26CE-26CF, U+26D1, U+26D3-26D4, U+26E9-26EA, U+26F0-26F5, U+26F7-26FA, U+26FD, U+2702, U+2705, U+2708-270D, U+270F, U+2712, U+2714, U+2716, U+271D, U+2721, U+2728, U+2733-2734, U+2744, U+2747, U+274C, U+274E, U+2753-2755, U+2757, U+2763-2764, U+2795-2797, U+27A1, U+27B0, U+27BF, U+2934-2935, U+2B05-2B07, U+2B1B-2B1C, U+2B50, U+2B55, U+3030, U+303D, U+3297, U+3299, U+FE0F, U+1F004, U+1F0CF, U+1F170-1F171, U+1F17E-1F17F, U+1F18E, U+1F191-1F19A, U+1F1E6-1F1FF, U+1F201-1F202, U+1F21A, U+1F22F, U+1F232-1F23A, U+1F250-1F251, U+1F300-1F321, U+1F324-1F393, U+1F396-1F397, U+1F399-1F39B, U+1F39E-1F3D3, U+1F3FB-1F3FF, U+1F4A5, U+1F525, U+1F7E9, U+1F7EB, U+1FA79; }
@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-002.ttf") format("truetype"); unicode-range: U+200C-200D, U+2620, U+2695-2696, U+26A7, U+2708, U+2744, U+2764, U+27A1, U+2B1B, U+FE0F, U+1F308, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3D4-1F3F0, U+1F3F3-1F3F5, U+1F3F7-1F469, U+1F48B, U+1F4BB-1F4BC, U+1F525, U+1F527, U+1F52C, U+1F5E8, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BA, U+1F9BC-1F9BD, U+1FAEF, U+E0062-E0063, U+E0065, U+E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F; }
@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-003.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F466-1F4A8, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BC-1F9BD, U+1FAEF; }
@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-004.ttf") format("truetype"); unicode-range: U+200C-200D, U+2194-2195, U+2640, U+2642, U+27A1, U+FE0F, U+1F32B, U+1F3FB-1F3FF, U+1F4A8-1F4FD, U+1F4FF-1F53D, U+1F549-1F54E, U+1F550-1F567, U+1F56F-1F570, U+1F573-1F57A, U+1F587, U+1F58A-1F58D, U+1F590, U+1F595-1F596, U+1F5A4-1F5A5, U+1F5A8, U+1F5B1-1F5B2, U+1F5BC, U+1F5C2-1F5C4, U+1F5D1-1F5D3, U+1F5DC-1F5DE, U+1F5E1, U+1F5E3, U+1F5E8, U+1F5EF, U+1F5F3, U+1F5FA-1F64F, U+1F680-1F6C5, U+1F6CB-1F6D2, U+1F6D5-1F6D8, U+1F6DC-1F6E5, U+1F6E9, U+1F6EB-1F6EC, U+1F6F0, U+1F6F3-1F6FC, U+1F7E0-1F7EB, U+1F7F0, U+1F90C-1F931; }
@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-005.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F384, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F48B, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F932-1F93A, U+1F93C-1F945, U+1F947-1F9D2, U+1FA70, U+1FAEF; }
@font-face { font-family: "SF Pro"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-006.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+FE0F, U+1F3FB-1F3FF, U+1F9D3-1F9FF, U+1FA70-1FA7C, U+1FA80-1FA8A, U+1FA8E-1FAC6, U+1FAC8, U+1FACD-1FADC, U+1FADF-1FAEA, U+1FAEF-1FAF8, U+E0061-E007A, U+E007F; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-001.ttf") format("truetype"); unicode-range: U+A9, U+AE, U+200C-200D, U+203C, U+2049, U+20E3, U+2122, U+2139, U+2194-2199, U+21A9-21AA, U+231A-231B, U+2328, U+23CF, U+23E9-23F3, U+23F8-23FA, U+24C2, U+25AA-25AB, U+25B6, U+25C0, U+25FB-25FE, U+2600-2604, U+260E, U+2611, U+2614-2615, U+2618, U+261D, U+2620, U+2622-2623, U+2626, U+262A, U+262E-262F, U+2638-263A, U+2640, U+2642, U+2648-2653, U+265F-2660, U+2663, U+2665-2666, U+2668, U+267B, U+267E-267F, U+2692-2697, U+2699, U+269B-269C, U+26A0-26A1, U+26A7, U+26AA-26AB, U+26B0-26B1, U+26BD-26BE, U+26C4-26C5, U+26C8, U+26CE-26CF, U+26D1, U+26D3-26D4, U+26E9-26EA, U+26F0-26F5, U+26F7-26FA, U+26FD, U+2702, U+2705, U+2708-270D, U+270F, U+2712, U+2714, U+2716, U+271D, U+2721, U+2728, U+2733-2734, U+2744, U+2747, U+274C, U+274E, U+2753-2755, U+2757, U+2763-2764, U+2795-2797, U+27A1, U+27B0, U+27BF, U+2934-2935, U+2B05-2B07, U+2B1B-2B1C, U+2B50, U+2B55, U+3030, U+303D, U+3297, U+3299, U+FE0F, U+1F004, U+1F0CF, U+1F170-1F171, U+1F17E-1F17F, U+1F18E, U+1F191-1F19A, U+1F1E6-1F1FF, U+1F201-1F202, U+1F21A, U+1F22F, U+1F232-1F23A, U+1F250-1F251, U+1F300-1F321, U+1F324-1F393, U+1F396-1F397, U+1F399-1F39B, U+1F39E-1F3D3, U+1F3FB-1F3FF, U+1F4A5, U+1F525, U+1F7E9, U+1F7EB, U+1FA79; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-002.ttf") format("truetype"); unicode-range: U+200C-200D, U+2620, U+2695-2696, U+26A7, U+2708, U+2744, U+2764, U+27A1, U+2B1B, U+FE0F, U+1F308, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3D4-1F3F0, U+1F3F3-1F3F5, U+1F3F7-1F469, U+1F48B, U+1F4BB-1F4BC, U+1F525, U+1F527, U+1F52C, U+1F5E8, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BA, U+1F9BC-1F9BD, U+1FAEF, U+E0062-E0063, U+E0065, U+E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-003.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F466-1F4A8, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BC-1F9BD, U+1FAEF; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-004.ttf") format("truetype"); unicode-range: U+200C-200D, U+2194-2195, U+2640, U+2642, U+27A1, U+FE0F, U+1F32B, U+1F3FB-1F3FF, U+1F4A8-1F4FD, U+1F4FF-1F53D, U+1F549-1F54E, U+1F550-1F567, U+1F56F-1F570, U+1F573-1F57A, U+1F587, U+1F58A-1F58D, U+1F590, U+1F595-1F596, U+1F5A4-1F5A5, U+1F5A8, U+1F5B1-1F5B2, U+1F5BC, U+1F5C2-1F5C4, U+1F5D1-1F5D3, U+1F5DC-1F5DE, U+1F5E1, U+1F5E3, U+1F5E8, U+1F5EF, U+1F5F3, U+1F5FA-1F64F, U+1F680-1F6C5, U+1F6CB-1F6D2, U+1F6D5-1F6D8, U+1F6DC-1F6E5, U+1F6E9, U+1F6EB-1F6EC, U+1F6F0, U+1F6F3-1F6FC, U+1F7E0-1F7EB, U+1F7F0, U+1F90C-1F931; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-005.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F384, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F48B, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F932-1F93A, U+1F93C-1F945, U+1F947-1F9D2, U+1FA70, U+1FAEF; }
@font-face { font-family: "SFProText"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-006.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+FE0F, U+1F3FB-1F3FF, U+1F9D3-1F9FF, U+1FA70-1FA7C, U+1FA80-1FA8A, U+1FA8E-1FAC6, U+1FAC8, U+1FACD-1FADC, U+1FADF-1FAEA, U+1FAEF-1FAF8, U+E0061-E007A, U+E007F; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-001.ttf") format("truetype"); unicode-range: U+A9, U+AE, U+200C-200D, U+203C, U+2049, U+20E3, U+2122, U+2139, U+2194-2199, U+21A9-21AA, U+231A-231B, U+2328, U+23CF, U+23E9-23F3, U+23F8-23FA, U+24C2, U+25AA-25AB, U+25B6, U+25C0, U+25FB-25FE, U+2600-2604, U+260E, U+2611, U+2614-2615, U+2618, U+261D, U+2620, U+2622-2623, U+2626, U+262A, U+262E-262F, U+2638-263A, U+2640, U+2642, U+2648-2653, U+265F-2660, U+2663, U+2665-2666, U+2668, U+267B, U+267E-267F, U+2692-2697, U+2699, U+269B-269C, U+26A0-26A1, U+26A7, U+26AA-26AB, U+26B0-26B1, U+26BD-26BE, U+26C4-26C5, U+26C8, U+26CE-26CF, U+26D1, U+26D3-26D4, U+26E9-26EA, U+26F0-26F5, U+26F7-26FA, U+26FD, U+2702, U+2705, U+2708-270D, U+270F, U+2712, U+2714, U+2716, U+271D, U+2721, U+2728, U+2733-2734, U+2744, U+2747, U+274C, U+274E, U+2753-2755, U+2757, U+2763-2764, U+2795-2797, U+27A1, U+27B0, U+27BF, U+2934-2935, U+2B05-2B07, U+2B1B-2B1C, U+2B50, U+2B55, U+3030, U+303D, U+3297, U+3299, U+FE0F, U+1F004, U+1F0CF, U+1F170-1F171, U+1F17E-1F17F, U+1F18E, U+1F191-1F19A, U+1F1E6-1F1FF, U+1F201-1F202, U+1F21A, U+1F22F, U+1F232-1F23A, U+1F250-1F251, U+1F300-1F321, U+1F324-1F393, U+1F396-1F397, U+1F399-1F39B, U+1F39E-1F3D3, U+1F3FB-1F3FF, U+1F4A5, U+1F525, U+1F7E9, U+1F7EB, U+1FA79; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-002.ttf") format("truetype"); unicode-range: U+200C-200D, U+2620, U+2695-2696, U+26A7, U+2708, U+2744, U+2764, U+27A1, U+2B1B, U+FE0F, U+1F308, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3D4-1F3F0, U+1F3F3-1F3F5, U+1F3F7-1F469, U+1F48B, U+1F4BB-1F4BC, U+1F525, U+1F527, U+1F52C, U+1F5E8, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BA, U+1F9BC-1F9BD, U+1FAEF, U+E0062-E0063, U+E0065, U+E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-003.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F466-1F4A8, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F9AF-1F9B3, U+1F9BC-1F9BD, U+1FAEF; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-004.ttf") format("truetype"); unicode-range: U+200C-200D, U+2194-2195, U+2640, U+2642, U+27A1, U+FE0F, U+1F32B, U+1F3FB-1F3FF, U+1F4A8-1F4FD, U+1F4FF-1F53D, U+1F549-1F54E, U+1F550-1F567, U+1F56F-1F570, U+1F573-1F57A, U+1F587, U+1F58A-1F58D, U+1F590, U+1F595-1F596, U+1F5A4-1F5A5, U+1F5A8, U+1F5B1-1F5B2, U+1F5BC, U+1F5C2-1F5C4, U+1F5D1-1F5D3, U+1F5DC-1F5DE, U+1F5E1, U+1F5E3, U+1F5E8, U+1F5EF, U+1F5F3, U+1F5FA-1F64F, U+1F680-1F6C5, U+1F6CB-1F6D2, U+1F6D5-1F6D8, U+1F6DC-1F6E5, U+1F6E9, U+1F6EB-1F6EC, U+1F6F0, U+1F6F3-1F6FC, U+1F7E0-1F7EB, U+1F7F0, U+1F90C-1F931; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-005.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+2695-2696, U+2708, U+2764, U+27A1, U+FE0F, U+1F33E, U+1F373, U+1F37C, U+1F384, U+1F393, U+1F3A4, U+1F3A8, U+1F3EB, U+1F3ED, U+1F3FB-1F3FF, U+1F430, U+1F48B, U+1F4BB-1F4BC, U+1F527, U+1F52C, U+1F680, U+1F692, U+1F91D, U+1F932-1F93A, U+1F93C-1F945, U+1F947-1F9D2, U+1FA70, U+1FAEF; }
@font-face { font-family: "Montserrat"; font-style: normal; font-weight: 400; font-display: swap; src: local("Apple Color Emoji"), url("/fonts/apple-emoji/apple-emoji-006.ttf") format("truetype"); unicode-range: U+200C-200D, U+2640, U+2642, U+FE0F, U+1F3FB-1F3FF, U+1F9D3-1F9FF, U+1FA70-1FA7C, U+1FA80-1FA8A, U+1FA8E-1FAC6, U+1FAC8, U+1FACD-1FADC, U+1FADF-1FAEA, U+1FAEF-1FAF8, U+E0061-E007A, U+E007F; }
/* --------------------------------------------------------------------------
   Catalogue grid

   The previous build put every thumbnail as bare artwork inside one grey slab,
   which read as a wall of emoji. lawx and mira both give each item its own
   rounded surface with air around it — the tool cards on lawx's home screen
   are the model — so the slab is dropped and the tiles become the surfaces.
   -------------------------------------------------------------------------- */
.oem-template-grid,
.market-template-grid,
.oem-template-grid.market-template-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    margin: 0;
    padding: 0 !important;
    border-radius: 0 !important;
    background: none !important;
    box-shadow: none !important;
}

.market-template-grid .oem-template-tile,
.oem-template-tile {
    border-radius: var(--ui-radius-card);
    background: none;
    overflow: visible;
}

/* Scroll reveal. oem-ui.css already fires a staggered fade on every tile, but
   it runs at render time — 144 tiles, so everything below the fold had played
   out before it was ever on screen and the grid arrived pre-settled. The tiles
   are held back instead and released as they cross into view.

   Gated on `.tier-reveal`, which app.js sets only once it has an
   IntersectionObserver in hand: if the script never runs the tiles are simply
   visible, rather than a grid of invisible buttons. */
html.tier-reveal .market-template-grid .oem-template-tile,
html.tier-reveal .oem-template-tile {
    animation: none !important;
    opacity: 0;
    /* Scale only. The old reveal also slid the tile up 14px, and on a grid that
       reads as the whole page settling rather than the artwork arriving. */
    transform: scale(.9);
    transition: opacity .32s cubic-bezier(.22, 1, .36, 1),
                transform .42s cubic-bezier(.2, 1.25, .4, 1);
    will-change: opacity, transform;
}

html.tier-reveal .market-template-grid .oem-template-tile.is-inview,
html.tier-reveal .oem-template-tile.is-inview {
    opacity: 1;
    transform: none;
    will-change: auto;
}

/* @wallet's own card, rule for rule (.pK3y3 / .qQ3P6 from its bundle):
   background-color: var(--tg-theme-section-bg-color); padding: 16px;
   border-radius: var(--border-radius-regular) — 26px computed; no border, no
   shadow, and no overflow clip, because the ribbon hangs off the corner. */
.market-template-grid .oem-template-preview,
.oem-template-preview {
    aspect-ratio: 1;
    display: grid;
    place-items: center;
    /* .pK3y3 is `position: relative` for exactly this reason: the badge is
       absolutely placed against the card. Without it the badge resolves against
       whatever ancestor happens to be positioned and lands off the tile. */
    position: relative;
    padding: 16px;
    border-radius: 26px !important;
    background: var(--tier-tile-bg) !important;
    box-shadow: none !important;
    border: 0 !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    overflow: visible;
    transition: background var(--ui-dur, .22s) var(--ui-ease, ease),
                transform var(--ui-dur, .22s) var(--ui-ease, ease);
}

.market-template-grid .oem-template-preview::before,
.market-template-grid .oem-template-preview::after,
.oem-template-preview::before,
.oem-template-preview::after {
    display: none !important;
}

.oem-template-tile:active .oem-template-preview,
.market-card-preview-button:active .oem-template-preview {
    transform: scale(.94);
}

/* Selected: the card itself does not change at all — no fill, no outline. The
   only mark is @wallet's badge, which is that app's own SVG (56x55, the
   #6DD1FF -> #37A6FB gradient, pulled out of its bundle) hung off the corner by
   3px on both axes, exactly as .Wb1nA places it. */
.market-template-grid .oem-template-tile--selected .oem-template-preview,
.oem-template-tile--selected .oem-template-preview {
    background: var(--tier-tile-bg) !important;
    box-shadow: none !important;
    transform: none;
}

.market-template-grid .oem-template-tile--selected .oem-template-preview::before,
.oem-template-tile--selected .oem-template-preview::before,
.market-template-grid .oem-template-tile--unselecting .oem-template-preview::before,
.oem-template-tile--unselecting .oem-template-preview::before {
    content: "";
    display: block !important;
    position: absolute;
    /* oem-ui.css centres this pseudo-element with left/top 50% and a
       translate(-50%,-50%); both have to be cleared or the badge is dragged
       into the middle of the tile. */
    top: -3px;
    right: -3px;
    left: auto;
    bottom: auto;
    transform: none;
    width: 56px;
    height: 55px;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    /* Above the artwork, not level with it. market.css puts the thumbnail and
       the live Lottie slot at z-index 2 as well, and on a tie the later child
       wins — which is why tall templates were painting over the ribbon. The
       live slot claims 5 in oem-ui.css, so the ribbon sits above that too. */
    z-index: 8;
    /* @wallet's own #6DD1FF -> #37A6FB is that app's accent, not TIER's. The
       gradient now runs the confirm button's slate, sheen end first, so the two
       marks of "this one is in the pack" are the same colour. */
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='55' fill='none' viewBox='0 0 56 55'%3E%3Cpath fill='url(%23g)' d='M50.024 52.309 3.321 5.605C1.607 3.89.75 3.035.692 2.299A2 2 0 0 1 1.387.621C1.948.142 3.16.142 5.583.142h13.932c2.446 0 3.669 0 4.82.276a10 10 0 0 1 2.89 1.198c1.01.618 1.874 1.483 3.603 3.212l19.973 19.973c1.73 1.73 2.594 2.594 3.212 3.603a10 10 0 0 1 1.198 2.89c.276 1.152.276 2.375.276 4.82v13.932c0 2.423 0 3.635-.48 4.196a2 2 0 0 1-1.677.695c-.735-.058-1.592-.915-3.306-2.628'/%3E%3Cdefs%3E%3ClinearGradient id='g' x1='4.929' x2='62.558' y1='-6.929' y2='50.7' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23AEBBCD'/%3E%3Cstop offset='1' stop-color='%238191A9'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
    /* The corner it is pinned to, so it unfolds out of the card rather than
       growing from its own middle. */
    transform-origin: 100% 0;
    animation: tier-ribbon-in .44s cubic-bezier(.22, 1.4, .36, 1) both;
}

/* The badge's label, placed by @wallet's .wMBS1 verbatim. */
.market-template-grid .oem-template-tile--selected .oem-template-preview::after,
.oem-template-tile--selected .oem-template-preview::after,
.market-template-grid .oem-template-tile--unselecting .oem-template-preview::after,
.oem-template-tile--unselecting .oem-template-preview::after {
    content: "выбрано";
    display: flex !important;
    align-items: center;
    justify-content: center;
    position: absolute;
    /* Same story: a stray `left: 0` over-constrains the box and `right` is
       dropped, which parks the label on the wrong corner. */
    top: 0;
    right: 0;
    left: auto;
    bottom: auto;
    width: 82px;
    height: 20px;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    transform: rotate(45deg) translate(23px, -10px);
    background: none;
    color: #fff;
    font-family: var(--ui-font);
    font-size: 10px;
    font-weight: 600;
    line-height: 13px;
    text-align: center;
    pointer-events: none;
    z-index: 9;
    /* Slides out along the band's own axis, a beat after the band itself, so
       the word appears to be carried in by it. */
    animation: tier-ribbon-label-in .34s cubic-bezier(.22, 1, .36, 1) .1s both;
}

@keyframes tier-ribbon-in {
    from {
        opacity: 0;
        transform: scale(.2);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes tier-ribbon-label-in {
    from {
        opacity: 0;
        /* The extra translate is appended, so it runs along the rotated x axis —
           up the diagonal, back under the corner the band comes from. */
        transform: rotate(45deg) translate(23px, -10px) translateX(-18px);
    }

    to {
        opacity: 1;
        transform: rotate(45deg) translate(23px, -10px) translateX(0);
    }
}

/* The badge's lengths, restated where they beat what oem-ui.css centres.

   This block used to make every tile a query container so the badge could be
   sized in cqw — but nothing here is in cqw, and `@container` is not used
   anywhere in the app: the sizes below are plain pixels. What was left was
   size, layout and style containment on fifteen elements for no benefit, paid
   again every time the catalogue is shown, which is most of what made coming
   back to it block the main thread for a third of a second. */
@supports (container-type: inline-size) {
    .market-template-grid .oem-template-tile--selected .oem-template-preview::before,
    .oem-template-tile--selected .oem-template-preview::before,
    .market-template-grid .oem-template-tile--unselecting .oem-template-preview::before,
    .oem-template-tile--unselecting .oem-template-preview::before {
        top: -3px;
        right: -3px;
        width: 56px;
        height: 55px;
    }

    .market-template-grid .oem-template-tile--selected .oem-template-preview::after,
    .oem-template-tile--selected .oem-template-preview::after,
    .market-template-grid .oem-template-tile--unselecting .oem-template-preview::after,
    .oem-template-tile--unselecting .oem-template-preview::after {
        width: 82px;
        height: 20px;
        /* "bonus" is five characters, "выбрано" is seven — at @wallet's 6.36%
           the word runs past the ends of the band, so it is set a touch
           tighter to sit inside it the way theirs does. */
        font-size: 10px;
        letter-spacing: -.02em;
        line-height: 20px;
        transform: rotate(45deg) translate(23px, -10px);
    }
}

/* Taking the ribbon off again.

   Both marks are pseudo-elements, so the instant `--selected` goes they are
   display:none and there is nothing left to animate. app.js hangs
   `--unselecting` on the tile for the length of the exit instead — every rule
   above matches it too, so the band is still fully dressed while it leaves.
   Declared after the @supports block so it beats the `transform` restated
   there on equal specificity. */
.market-template-grid .oem-template-tile--unselecting .oem-template-preview::before,
.oem-template-tile--unselecting .oem-template-preview::before {
    /* Out is not just in reversed: it leaves faster and without the overshoot,
       which is what makes a dismissal read as a dismissal. */
    animation: tier-ribbon-out .24s cubic-bezier(.4, 0, .9, .6) both;
}

.market-template-grid .oem-template-tile--unselecting .oem-template-preview::after,
.oem-template-tile--unselecting .oem-template-preview::after {
    animation: tier-ribbon-label-out .16s cubic-bezier(.4, 0, 1, 1) both;
}

@keyframes tier-ribbon-out {
    from {
        opacity: 1;
        transform: scale(1);
    }

    to {
        opacity: 0;
        transform: scale(.25);
    }
}

@keyframes tier-ribbon-label-out {
    from {
        opacity: 1;
        transform: rotate(45deg) translate(23px, -10px) translateX(0);
    }

    to {
        opacity: 0;
        transform: rotate(45deg) translate(23px, -10px) translateX(-14px);
    }
}

.market-card-preview-button:focus-visible {
    outline: 2px solid var(--ui-accent-strong);
    outline-offset: 3px;
    border-radius: 26px;
}

@media (hover: hover) and (pointer: fine) {
    .market-card-preview-button:hover .oem-template-preview {
        filter: brightness(1.08);
    }
}

.oem-template-tile--selected {
    background: none;
}

/* oem-ui.css draws its own badge on ::before; the ribbon is now the only mark
   of selection, so both that badge and the tick element are switched off. */
.oem-template-tile--selected::before,
.tier-tile-check {
    display: none !important;
}

/* --------------------------------------------------------------------------
   Selection dock

   The confirm button is lawx's .ui-cta: an accent pill inside a 1.6px frame
   whose gradient travels, which is the sheen the reference button has. The
   animation is defined in tier-ui.css as ui-shimmer.
   -------------------------------------------------------------------------- */
.market-cart-dock {
    left: 0;
    right: 0;
    width: min(calc(100% - 32px), 420px);
    height: auto;
    min-height: var(--tier-dock-height);
    margin-inline: auto;
    padding: 8px 8px 8px 14px;
    bottom: calc(var(--safe-b) + var(--tier-nav-gap) + var(--tabbar-h) + 10px);
    z-index: 71;
    display: flex;
    align-items: center;
    gap: 12px;
    border-radius: var(--ui-radius-pill) !important;
    background: var(--ui-card) !important;
    box-shadow:
        0 2px 16px 1px #0000002e,
        -.6px -.5px 0 0 #ffffff33 inset,
        .5px .6px 0 0 #ffffff33 inset !important;
    -webkit-backdrop-filter: blur(15px);
    backdrop-filter: blur(15px);
    transform: none;
}

.market-cart-dock::before {
    display: none !important;
}

/* Dark avatar circles sit below the selection panel's surface tone. */
.market-cart-dock-stack {
    display: flex;
    align-items: center;
    isolation: isolate;
}

.market-cart-dock-thumb {
    width: 32px;
    height: 32px;
    padding: 3px;
    border: 2px solid var(--ui-card);
    border-radius: 50%;
    background: #0d0d0f;
    overflow: hidden;
    box-shadow: none;
    flex: none;
}

.market-cart-dock-thumb + .market-cart-dock-thumb {
    margin-left: -8px;
}

.market-cart-dock-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

html[data-theme="light"] .market-cart-dock-thumb {
    background: #d1d1d6;
}

.market-cart-dock-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    text-align: left;
}

.market-cart-dock-text strong {
    color: var(--ui-text);
    font-size: var(--ui-font-callout, 16px);
    font-weight: 590;
    line-height: 1.25;
    white-space: nowrap;
}

.market-cart-dock-text small {
    color: var(--ui-hint);
    font-size: var(--ui-font-footnote, 13.5px);
    line-height: 1.25;
}

/* The travelling sheen, exactly lawx's .ui-cta construction: an outer frame
   carrying a gradient near three times its own width and animated across it,
   with a solid accent pill inset by 1.6px on top. app.js writes the label with
   textContent, so the pill is a ::before behind the text rather than a wrapper
   element — the markup stays untouched. */
.market-cart-dock-go {
    position: relative;
    isolation: isolate;
    flex: none;
    display: grid;
    place-items: center;
    min-height: 46px;
    padding: 0 26px;
    border-radius: var(--ui-radius-pill) !important;
    /* lawx's lit frame kept as it was — a sheen travelling round a 1.6px rim
       with a solid core inside it — only recoloured to the muted slate. */
    background: linear-gradient(110deg,
        var(--tier-muted) 0%,
        var(--tier-muted-sheen) 25%,
        var(--tier-muted) 50%,
        var(--tier-muted-sheen) 75%,
        var(--tier-muted) 100%) !important;
    background-size: 280% 100% !important;
    animation: ui-shimmer 5s linear infinite;
    color: #fff;
    font-family: var(--ui-font);
    font-size: var(--ui-font-callout, 16px);
    font-weight: 590;
    line-height: 1;
    text-align: center;
    transition: transform var(--ui-dur, .22s) var(--ui-ease, ease);
}

.market-cart-dock-go::before {
    content: "";
    position: absolute;
    inset: 1.6px;
    z-index: -1;
    border-radius: inherit;
    background: var(--tier-muted);
}

.market-cart-dock:active .market-cart-dock-go {
    transform: scale(.97);
}

@media (prefers-reduced-motion: reduce) {
    .market-cart-dock-go {
        animation: none;
    }
}

/* --------------------------------------------------------------------------
   Page clearance

   The pager was sliding under the floating bar. The page reserves the bar,
   the dock and the safe area so the last row always clears them.
   -------------------------------------------------------------------------- */
.ui-page.oem-page {
    padding-top: calc(var(--tier-top, 0px) + max(env(safe-area-inset-top, 0px) - var(--ui-fullscreen-top, 0px), 0px) + 12px) !important;
    padding-left: calc(var(--gutter) + var(--tier-safe-left, 0px)) !important;
    padding-right: calc(var(--gutter) + var(--tier-safe-right, 0px)) !important;
    padding-bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--tier-nav-gap) + 36px) !important;
}

body.market-has-cart .ui-page.oem-page {
    padding-bottom: calc(var(--tabbar-h) + var(--tier-dock-height) + var(--safe-b) + var(--tier-nav-gap) + 48px) !important;
}

.ui-cta-spacer,
.oem-bottom-spacer,
.market-bottom-spacer,
/* market.css sets 138px + safe + bar on this pair with !important, and oem-ui
   another 112px — on top of the page's own bottom padding, which already
   reserves the bar, the dock and the safe area. That left ~330px of empty
   black under the last row to scroll through. */
.market-bottom-spacer.oem-bottom-spacer {
    height: 0 !important;
}

/* --------------------------------------------------------------------------
   Catalogue header

   lawx labels a group with a small grey section header and lets the content
   carry the weight — it never states a row count. The 20px bold headline, the
   "144 шаблонов" tally and the "Ничего не выбрано" line under the pager were
   all noise of that kind, so the header collapses to one quiet label with the
   collection chip under it.
   -------------------------------------------------------------------------- */
.market-tabs .market-tab,
#catalogViewTab.market-tab,
.tier-packs-list #packsScreenTitle {
    padding: 0;
    /* lawx's --ui-section-header grey is tuned for its black page; here the
       label sits inside the blue wash, where that grey turns muddy. A dimmed
       white keeps the same quiet weight and reads over both. */
    color: var(--ui-text);
    font-family: var(--ui-font);
    /* Racama is a narrow face — at 22px it read as a caption next to the chip
       beside it rather than as the screen's title. iOS large titles are 34pt;
       30px lands just under that and still clears the chip at 320px. */
    font-size: 30px !important;
    font-weight: 700 !important;
    letter-spacing: -.025em;
    line-height: 36px;
    text-transform: none;
}

.market-tabs {
    margin: 0;
    padding: 0;
}

.market-filter-row {
    margin: 0;
    min-width: 0;
}

/* The wordmark and tagline are gone from the markup, so the catalog heading is
   the first thing on the page and carries the top gap itself. */
.tier-catalog-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 10px 0 16px;
}

#packsScreen.tier-packs-list .oem-titlebar--packs {
    justify-content: flex-start;
    min-height: 44px;
    margin: 10px 0 16px;
    padding: 0;
    border: 0;
}

.tier-packs-list #packsScreenTitle {
    font-family: "Racama", sans-serif !important;
    position: static;
    max-width: none;
    margin: 0;
    text-align: left;
}

.tier-packs-list .oem-titlebar-balance,
.tier-packs-list #createTab {
    display: none;
}

#packsScreen #packsList.tier-empty-host {
    background: transparent !important;
    border: 0;
    box-shadow: none;
}

html:has(body.oem-packs-active #packsScreen.tier-packs-list .tier-empty-host),
body.oem-packs-active:has(#packsScreen.tier-packs-list .tier-empty-host) {
    height: 100dvh;
    overflow: hidden !important;
    overflow: clip !important;
    overscroll-behavior: none;
}

body.oem-packs-active:has(#packsScreen.tier-packs-list .tier-empty-host) .ui-page.oem-page {
    height: 100%;
    overflow: hidden;
    box-sizing: border-box;
    padding-bottom: 0 !important;
}

#packsList .tier-empty {
    /* #packsList — это .cfg-pack-grid в две колонки. Без этой строки пустое
       состояние становилось ячейкой первой колонки, и уточка стояла по
       центру левой половины, а не страницы: на телефоне сдвиг ~87px, а в
       широком окне на Mac — больше 100px, и уже нельзя не заметить. */
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: calc(100dvh - var(--tier-top, 0px) - max(env(safe-area-inset-top, 0px) - var(--ui-fullscreen-top, 0px), 0px) - var(--tabbar-h) - var(--safe-b) - var(--tier-nav-gap) - 94px);
    gap: 16px;
    padding: 32px 16px;
}

.tier-empty__animation {
    display: block;
    width: 180px;
    height: 180px;
}

#packsList .tier-empty__title {
    margin: 0;
}

#collectionValue {
    max-width: min(38vw, 180px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#collectionChevron {
    color: var(--ui-hint);
}

@media (max-width: 370px) {
    .market-cart-dock {
        gap: 8px;
        padding-left: 10px;
    }

    .market-cart-dock-go {
        padding-inline: 18px;
        font-size: 15px;
    }

    .market-cart-dock-text strong {
        font-size: 15px;
    }
}

/* The tally, the cart's second line and the selection caption: all removed. */
#collectionCount.market-result-count,
#cartDockHint,
#selectedTemplates {
    display: none !important;
}

/* --------------------------------------------------------------------------
   Pager

   A pill, like every other floating control here, with the page label centred
   between two round buttons and nothing underneath it.
   -------------------------------------------------------------------------- */
.oem-pager.market-pager,
.market-pager.oem-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 14px auto 0;
    width: fit-content;
    max-width: 100%;
    padding: 5px;
    border-radius: var(--ui-radius-pill) !important;
    background: var(--ui-card) !important;
}

.oem-pager .oem-pager-body,
.market-pager .oem-pager-body {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 6px;
}

#catalogPage.ui-row-title {
    color: var(--ui-text);
    font-size: var(--ui-font-sub, 15px);
    font-weight: 510;
    line-height: 1.2;
    white-space: nowrap;
}

/* 999px, not 50%. A percentage radius is resolved against the box, so the
   moment anything makes the button non-square — a flex rule from another sheet,
   a padding, a min-width — 50% silently becomes an ellipse, which at this size
   is indistinguishable from a rounded rectangle. A length cannot do that: it
   clamps to half the shorter side and stays a circle whatever the box does.
   The width/height are restated with !important for the same reason. */
.market-page-button,
.market-page-button.ui-icon-button,
.market-page-button.oem-nav-btn {
    width: 40px !important;
    height: 40px !important;
    min-width: 40px !important;
    padding: 0 !important;
    flex: 0 0 40px !important;
    border-radius: 999px !important;
    overflow: hidden;
}

.market-page-button:disabled {
    opacity: .35;
}

/* --------------------------------------------------------------------------
   Switching tabs

   No transition, deliberately, after three of them failed on the same wall.

   A cross-push needs the outgoing screen kept alive and out of flow, which
   re-anchored it and fought the scroll reset. Sliding only the arriving screen
   removes that, but the arriving screen has to start somewhere the old one no
   longer is — so the page goes black for a frame and then a strip of black
   rides in beside it, which is exactly the "черно, потом смещается в сторону"
   this was reported as. And a fade cannot cover it either without both screens
   on screen at once.

   Underneath all three is the same fact: the catalogue costs ~270ms to paint
   the first time it is shown, so on a phone the animation's frames are never
   scheduled and what lands is a jump. Telegram's own tab bars switch instantly;
   the moving part of a tab change is the bar's own fill, which still animates.
   Worth revisiting once the pack screen is rebuilt and both sides are cheap.

   content-visibility went with it. It was only ever here to make the animated
   trip back cheaper, and keeping a screen's subtree alive but unrendered is
   what left the pack rows painting their Lottie previews without the row
   surfaces under them.
   -------------------------------------------------------------------------- */
.oem-page {
    /* Nothing slides any more, but the grid still must not be able to push a
       horizontal scrollbar out. */
    overflow-x: clip;
}
