/* ==========================================================================
   utilities.css — atomic utility layer
   --------------------------------------------------------------------------
   The WebApp markup (index.html + the js/ renderers) is written almost
   entirely in Tailwind-style utility classes, but no Tailwind build has ever
   been shipped with the app. Every one of those classes resolved to nothing,
   which is why screens rendered without flex rows, without padding, at the
   wrong font sizes, and - inside <button>, which does not inherit colour -
   as black text on the dark theme.
   This file implements exactly the utilities the markup actually uses,
   mapped onto the existing design tokens in main.css. Generated from an
   inventory of classes used in webapp/public; keep it in sync when adding
   new utility classes to the markup.
   ========================================================================== */

@keyframes tw-pulse{0%,100%{opacity:1}50%{opacity:.5}}
@keyframes tw-spin{to{transform:rotate(360deg)}}
@keyframes tw-ping{75%,100%{transform:scale(2);opacity:0}}
@keyframes tw-bounce{0%,100%{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}

/* <button>/<input> do not inherit colour from the page: without this every
   button whose text colour comes only from a utility class rendered in the
   UA default (black) on the dark theme. */
button,input,select,textarea{color:inherit;font-family:inherit;}
/* ...and the UA button background (buttonface, a near-white grey) has to go
   with it: on the dark theme a button that sets no background of its own
   otherwise ends up light-text-on-light-grey. */
button{background-color:transparent;}

/* .btn-success / .btn-danger are used by the price-prediction buttons but
   were never defined, so those two buttons fell back to the UA appearance
   entirely. Defined here to match .btn-primary / .btn-secondary. */
.btn-success,.btn-danger{
    width:100%;
    padding:16px;
    border:none;
    border-radius:var(--radius-sm);
    color:#fff;
    font-size:16px;
    font-weight:700;
    cursor:pointer;
    transition:all .3s cubic-bezier(.4,0,.2,1);
    text-transform:uppercase;
    letter-spacing:.5px;
}
.btn-success{background:var(--gradient-success);box-shadow:0 4px 16px var(--success-glow);}
.btn-danger{background:var(--gradient-danger);box-shadow:0 4px 16px var(--danger-glow);}
.btn-success:active,.btn-danger:active{transform:scale(.98);}

/* Tab-style controls the markup uses that had no rule of their own. */
.quest-tab,.collectibles-tab{
    /* 36px was under a comfortable touch target; .league-tab already uses 44px. */
    min-height:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    white-space:nowrap;
    padding:8px 14px;
    background:rgba(255,255,255,.05);
    border:1px solid var(--glass-border);
    border-radius:20px;
    color:var(--text-secondary);
    font-size:11px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:.06em;
    cursor:pointer;
}
.quest-tab.active,.collectibles-tab.active{
    background:var(--gradient-primary);
    border-color:transparent;
    color:#04121a;
}

/* The .quest-tab/.collectibles-tab pills had rules but their containers did
   not. Both rows sit as siblings of .screen-content, so without this they had
   no gap between pills and no side gutter - the tabs ran edge-to-edge and
   wrapped onto several lines on a 320px phone. */
.quest-tabs,.collectibles-tabs{
    display:flex;
    gap:6px;
    padding:.75rem 1rem 0;
    margin-bottom:12px;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
}
.quest-tabs::-webkit-scrollbar,.collectibles-tabs::-webkit-scrollbar{display:none;}

.divide-y>*+*{border-top-width:1px;border-top-style:solid;border-top-color:var(--tw-divide,var(--border-color));}

/* The only stylesheet mention of `hidden` was the compound
   `.market-news-banner.hidden`, so the generic utility never existed and
   seven elements the markup ships as hidden (the notification hub, the
   quick-action menu, the market-event and AI-signal badges, the heist action
   container, the scratch result and the league leaderboard box) were
   permanently visible on top of the UI. */
.hidden{display:none;}

.text-secondary{color:var(--text-secondary);}
.font-bold{font-weight:700;}
.flex{display:flex;}
.text-center{text-align:center;}
.text-xs{font-size:0.75rem;line-height:1rem;}
.uppercase{text-transform:uppercase;}
.items-center{align-items:center;}
.text-\[10px\]{font-size:10px;line-height:1.35;}
.font-black{font-weight:900;}
.justify-between{justify-content:space-between;}
.p-4{padding-top:1rem;padding-right:1rem;padding-bottom:1rem;padding-left:1rem;}
.text-sm{font-size:0.875rem;line-height:1.25rem;}
.text-muted{color:var(--text-muted);}
.tracking-widest{letter-spacing:0.1em;}
.gap-2{gap:0.5rem;}
.text-cyan{color:var(--primary-color);}
.mb-4{margin-bottom:1rem;}
.mb-1{margin-bottom:0.25rem;}
.mb-2{margin-bottom:0.5rem;}
.grid{display:grid;}
.text-gold{color:var(--gold-color);}
.flex-1{flex:1 1 0%;}
.text-\[9px\]{font-size:10px;line-height:1.35;}
.py-2{padding-top:0.5rem;padding-bottom:0.5rem;}
.p-3{padding-top:0.75rem;padding-right:0.75rem;padding-bottom:0.75rem;padding-left:0.75rem;}
.mb-3{margin-bottom:0.75rem;}
.font-mono{font-family:ui-monospace,SFMono-Regular,'SF Mono',Menlo,Consolas,'Liberation Mono',monospace;}
.w-full{width:100%;}
.text-white{color:#fff;}
.mt-2{margin-top:0.5rem;}
.gap-3{gap:0.75rem;}
.text-2xl{font-size:1.5rem;line-height:2rem;}
.border{border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-style:solid;}
.text-xl{font-size:1.25rem;line-height:1.75rem;}
.mb-6{margin-bottom:1.5rem;}
.overflow-hidden{overflow:hidden;}
.mt-1{margin-top:0.25rem;}
.px-4{padding-left:1rem;padding-right:1rem;}
.rounded-lg{border-radius:0.5rem;}
.text-right{text-align:right;}
.text-lg{font-size:1.125rem;line-height:1.75rem;}
.p-8{padding-top:2rem;padding-right:2rem;padding-bottom:2rem;padding-left:2rem;}
.p-2{padding-top:0.5rem;padding-right:0.5rem;padding-bottom:0.5rem;padding-left:0.5rem;}
.rounded-full{border-radius:9999px;}
.text-\[8px\]{font-size:10px;line-height:1.35;}
.border-white\/5{border-color:rgba(255,255,255,0.05);}
.py-4{padding-top:1rem;padding-bottom:1rem;}
.border-white\/10{border-color:rgba(255,255,255,0.1);}
.italic{font-style:italic;}
.gap-4{gap:1rem;}
.mt-4{margin-top:1rem;}
.bg-white\/5{background-color:rgba(255,255,255,0.05);}
.h-full{height:100%;}
.p-6{padding-top:1.5rem;padding-right:1.5rem;padding-bottom:1.5rem;padding-left:1.5rem;}
.text-3xl{font-size:1.875rem;line-height:2.25rem;}
.py-3{padding-top:0.75rem;padding-bottom:0.75rem;}
.justify-center{justify-content:center;}
.mt-3{margin-top:0.75rem;}
.rounded{border-radius:0.25rem;}
.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr));}
.text-green-400{color:rgba(74,222,128,1);}
.py-1{padding-top:0.25rem;padding-bottom:0.25rem;}
.mt-6{margin-top:1.5rem;}
.bg-dark-light{background-color:var(--card-bg-solid);}
.text-left{text-align:left;}
.text-primary{color:var(--primary-color);}
.cursor-pointer{cursor:pointer;}
.animate-pulse{animation:tw-pulse 2s cubic-bezier(.4,0,.6,1) infinite;}
.gap-1{gap:0.25rem;}
.flex-col{flex-direction:column;}
.tracking-tighter{letter-spacing:-0.05em;}
.text-5xl{font-size:3rem;line-height:1;}
.text-red-500{color:rgba(248,113,113,1);} /* red-400: #ef4444 is 4.22:1 on the card bg, this is 5.74:1 */
.tracking-wider{letter-spacing:0.05em;}
.relative{position:relative;}
.px-2{padding-left:0.5rem;padding-right:0.5rem;}
.tracking-tight{letter-spacing:-0.025em;}
.py-6{padding-top:1.5rem;padding-bottom:1.5rem;}
.opacity-30{opacity:0.3;}
.py-0\.5{padding-top:0.125rem;padding-bottom:0.125rem;}
.m-0{margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;}
.text-green-500{color:rgba(34,197,94,1);}
.h-2{height:0.5rem;}
.shadow-lg{box-shadow:var(--shadow-lg);}
.text-6xl{font-size:3.75rem;line-height:1;}
.hover\:bg-white\/5:hover{background-color:rgba(255,255,255,0.05);}
.text-4xl{font-size:2.25rem;line-height:2.5rem;}
.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-from,transparent),var(--tw-to,transparent));}
.to-transparent{--tw-to:transparent;}
.absolute{position:absolute;}
.overflow-y-auto{overflow-y:auto;}
.border-b{border-bottom-width:1px;border-style:solid;}
.text-danger{color:var(--danger-color);}
.text-red-400{color:rgba(248,113,113,1);}
.text-\[11px\]{font-size:11px;line-height:1.35;}
.rounded-xl{border-radius:0.75rem;}
.px-3{padding-left:0.75rem;padding-right:0.75rem;}
.top-0{top:0;}
.border-t{border-top-width:1px;border-style:solid;}
.duration-1000{transition-duration:1000ms;}
.items-start{align-items:flex-start;}
.bg-cyan{background-color:var(--primary-color);}
.block{display:block;}
.py-8{padding-top:2rem;padding-bottom:2rem;}
.border-gold\/30{border-color:rgba(251,191,36,0.3);}
.bg-black\/30{background-color:rgba(0,0,0,0.3);}
.bg-gold\/10{background-color:rgba(251,191,36,0.1);}
.mt-0\.5{margin-top:0.125rem;}
.bg-red-500{background-color:rgba(239,68,68,1);}
.opacity-0{opacity:0.0;}
.border-primary\/20{border-color:rgba(0,242,254,0.2);}
.p-1{padding-top:0.25rem;padding-right:0.25rem;padding-bottom:0.25rem;padding-left:0.25rem;}
.col-span-4{grid-column:span 4/span 4;}
.pt-4{padding-top:1rem;}
.text-success{color:var(--success-color);}
.mb-8{margin-bottom:2rem;}
.w-10{width:2.5rem;}
.h-10{height:2.5rem;}
.col-span-3{grid-column:span 3/span 3;}
.py-10{padding-top:2.5rem;padding-bottom:2.5rem;}
.mb-0\.5{margin-bottom:0.125rem;}
.divide-white\/5{--tw-divide:rgba(255,255,255,0.05);}
.w-4{width:1rem;}
.h-4{height:1rem;}
.space-y-2>*+*{margin-top:0.5rem;}
.max-h-\[300px\]{max-height:300px;}
.h-8{height:2rem;}
.right-0{right:0;}
.w-32{width:8rem;}
.h-32{height:8rem;}
.blur-3xl{filter:blur(64px);}
.-mr-16{margin-right:-4rem;}
.-mt-16{margin-top:-4rem;}
.mb-1\.5{margin-bottom:0.375rem;}
.overflow-x-auto{overflow-x:auto;}
.pr-1{padding-right:0.25rem;}
.bg-green-500{background-color:rgba(34,197,94,1);}
.h-1{height:0.25rem;}
.border-cyan\/20{border-color:rgba(0,242,254,0.2);}
.hover\:bg-white\/10:hover{background-color:rgba(255,255,255,0.1);}
.border-cyan\/30{border-color:rgba(0,242,254,0.3);}
.left-0{left:0;}
.border-2{border-top-width:2px;border-right-width:2px;border-bottom-width:2px;border-left-width:2px;border-style:solid;}
.border-primary\/30{border-color:rgba(0,242,254,0.3);}
.shadow-primary\/20{box-shadow:0 8px 24px rgba(0,242,254,0.2);}
.bg-primary\/10{background-color:rgba(0,242,254,0.1);}
.border-orange-500\/20{border-color:rgba(249,115,22,0.2);}
.bg-gold\/5{background-color:rgba(251,191,36,0.05);}
.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr));}
.h-20{height:5rem;}
.h-3{height:0.75rem;}
.col-span-2{grid-column:span 2/span 2;}
.leading-tight{line-height:1.25;}
.w-6{width:1.5rem;}
.ml-auto{margin-left:auto;}
.bg-green-500\/20{background-color:rgba(34,197,94,0.2);}
.border-green-500{border-color:rgba(34,197,94,1);}
.scale-110{transform:scale(1.1);}
.animate-bounce{animation:tw-bounce 1s infinite;}
.text-\[7px\]{font-size:10px;line-height:1.35;}
.border-gold\/20{border-color:rgba(251,191,36,0.2);}
.gap-1\.5{gap:0.375rem;}
.from-primary\/20{--tw-from:rgba(0,242,254,0.2);}
.gap-5{gap:1.25rem;}
.p-10{padding-top:2.5rem;padding-right:2.5rem;padding-bottom:2.5rem;padding-left:2.5rem;}
.border-l-2{border-left-width:2px;border-style:solid;}
.from-gold\/10{--tw-from:rgba(251,191,36,0.1);}
.-top-1{top:-0.25rem;}
.-right-1{right:-0.25rem;}
.bg-danger{background-color:var(--danger-color);}
.bg-warning\/20{background-color:rgba(245,158,11,0.2);}
.border-gold\/40{border-color:rgba(251,191,36,0.4);}
.border-amber-500\/20{border-color:rgba(245,158,11,0.2);}
.from-amber-500\/10{--tw-from:rgba(245,158,11,0.1);}
.gap-2\.5{gap:0.625rem;}
.text-amber-400{color:rgba(251,191,36,1);}
.bg-white\/10{background-color:rgba(255,255,255,0.1);}
.px-2\.5{padding-left:0.625rem;padding-right:0.625rem;}
.pt-1\.5{padding-top:0.375rem;}
.mt-1\.5{margin-top:0.375rem;}
.text-amber-300{color:rgba(252,211,77,1);}
.pb-2{padding-bottom:0.5rem;}
.space-y-1>*+*{margin-top:0.25rem;}
.pb-1{padding-bottom:0.25rem;}
.bg-green-500\/10{background-color:rgba(34,197,94,0.1);}
.w-1\.5{width:0.375rem;}
.h-1\.5{height:0.375rem;}
.bg-cyan\/10{background-color:rgba(0,242,254,0.1);}
.bg-danger\/40{background-color:rgba(239,68,68,0.4);}
.bg-success\/40{background-color:rgba(16,185,129,0.4);}
.text-white\/50{color:rgba(255,255,255,0.5);}
.mx-auto{margin-left:auto;margin-right:auto;}
.justify-around{justify-content:space-around;}
.mt-8{margin-top:2rem;}
.w-16{width:4rem;}
.h-16{height:4rem;}
.bg-transparent{background-color:transparent;}
.p-0{padding-top:0;padding-right:0;padding-bottom:0;padding-left:0;}
.flex-wrap{flex-wrap:wrap;}
.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr));}
.border-danger\/20{border-color:rgba(239,68,68,0.2);}
.border-danger\/30{border-color:rgba(239,68,68,0.3);}
.bg-danger\/5{background-color:rgba(239,68,68,0.05);}
.hover\:bg-danger\/10:hover{background-color:rgba(239,68,68,0.1);}
.text-orange-400{color:rgba(251,146,60,1);}
.duration-100{transition-duration:100ms;}
.w-8{width:2rem;}
.leading-relaxed{line-height:1.625;}
.text-gray-400{color:rgba(156,163,175,1);}
.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.mx-4{margin-left:1rem;margin-right:1rem;}
.bg-gold{background-color:var(--gold-color);}
.items-baseline{align-items:baseline;}
.text-purple-300{color:rgba(216,180,254,1);}
.space-y-4>*+*{margin-top:1rem;}
.ml-2{margin-left:0.5rem;}
.bg-danger\/20{background-color:rgba(239,68,68,0.2);}
.animate-ping{animation:tw-ping 1s cubic-bezier(0,0,.2,1) infinite;}
.bg-red-500\/20{background-color:rgba(239,68,68,0.2);}
.border-red-500{border-color:rgba(239,68,68,1);}
.aspect-square{aspect-ratio:1/1;}
.leading-none{line-height:1;}
.p-1\.5{padding-top:0.375rem;padding-right:0.375rem;padding-bottom:0.375rem;padding-left:0.375rem;}
.border-primary\/40{border-color:rgba(0,242,254,0.4);}
.max-h-\[240px\]{max-height:240px;}
.w-2{width:0.5rem;}
.bg-primary{background-color:var(--primary-color);}
.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-from,transparent),var(--tw-to,transparent));}
.w-20{width:5rem;}
.shadow-primary\/10{box-shadow:0 8px 24px rgba(0,242,254,0.1);}
.items-end{align-items:flex-end;}
.from-cyan{--tw-from:rgba(0,242,254,1);}
.to-secondary{--tw-to:rgba(168,85,247,1);}
.border-success\/20{border-color:rgba(16,185,129,0.2);}
.bg-success\/5{background-color:rgba(16,185,129,0.05);}
.p-5{padding-top:1.25rem;padding-right:1.25rem;padding-bottom:1.25rem;padding-left:1.25rem;}
.bg-cyan\/5{background-color:rgba(0,242,254,0.05);}
.inline-block{display:inline-block;}
.border-red-500\/20{border-color:rgba(239,68,68,0.2);}
.bg-red-500\/10{background-color:rgba(239,68,68,0.1);}
.border-primary{border-color:rgba(0,242,254,1);}
.space-y-3>*+*{margin-top:0.75rem;}
.max-h-\[150px\]{max-height:150px;}
.py-1\.5{padding-top:0.375rem;padding-bottom:0.375rem;}
.gap-0\.5{gap:0.125rem;}
.pl-3{padding-left:0.75rem;}
.w-12{width:3rem;}
.h-12{height:3rem;}
.px-5{padding-left:1.25rem;padding-right:1.25rem;}
.px-1{padding-left:0.25rem;padding-right:0.25rem;}
.text-base{font-size:1rem;line-height:1.5rem;}
.hover\:border-primary\/40:hover{border-color:rgba(0,242,254,0.4);}
.border-y{border-top-width:1px;border-bottom-width:1px;border-style:solid;}
.bg-primary\/20{background-color:rgba(0,242,254,0.2);}
.text-primary-light{color:#4facfe;}

/* --------------------------------------------------------------------------
   Utilities the markup uses that the first pass of this file missed. Each one
   resolved to nothing until now, so every rule below is restoring behaviour
   the markup already assumed - not new design.
   -------------------------------------------------------------------------- */

/* Layout - these two were real, visible layout breaks. */
/* #trading-league-leaderboard-rows pairs this with overflow-y-auto; with no
   max-height the list grew without bound and pushed the rest of the Trading
   screen off the viewport instead of scrolling inside its own box. */
.max-h-56{max-height:14rem;}
/* The Season Pass reward table header. .sp-level-row (season-pass.css) is a
   `40px 1fr 1fr` grid, but the header above it only had `grid`, so it
   collapsed to a single column and none of the three labels lined up with
   the rows they title. Horizontal padding matches .sp-level-row's 10px. */
.grid-cols-\[40px_1fr_1fr\]{grid-template-columns:40px 1fr 1fr;padding:0 10px;}

/* Borders. `.border-*` colour utilities existed but these style/width ones did
   not, so e.g. the guild empty-state cards asked for a dashed border and got
   no border at all, and the profile-modal close button kept the UA button
   border now that `button{background:transparent}` strips its background. */
.border-none{border-style:none;border-width:0;}
.border-dashed{border-style:dashed;border-width:1px;}
.border-success{border-color:var(--success-color);}
.border-danger{border-color:var(--danger-color);}
.border-white\/20{border-color:rgba(255,255,255,0.2);}
.last\:border-0:last-child{border-width:0;}

/* The AI signal badge (js/ai-assistant.js) toggles between three states; the
   bearish/neutral tints existed but the bullish background did not, so a
   bullish signal rendered with no fill at all. */
.bg-success\/20{background-color:rgba(16,185,129,0.2);}

/* Decorative - no layout effect, but these were silently dead too. */
.cursor-crosshair{cursor:crosshair;}
.tracking-\[0\.3em\]{letter-spacing:0.3em;}
.shadow-2xl{box-shadow:0 25px 50px -12px rgba(0,0,0,0.45);}
.shadow-inner{box-shadow:inset 0 2px 4px rgba(0,0,0,0.35);}
.shadow-\[0_0_10px_rgba\(0\,242\,254\,0\.5\)\]{box-shadow:0 0 10px rgba(0,242,254,0.5);}
.shadow-\[0_0_8px_rgba\(0\,242\,254\,0\.3\)\]{box-shadow:0 0 8px rgba(0,242,254,0.3);}
.drop-shadow-glow{filter:drop-shadow(0 0 8px currentColor);}
.drop-shadow-\[0_0_10px_rgba\(255\,215\,0\,0\.5\)\]{filter:drop-shadow(0 0 10px rgba(255,215,0,0.5));}
/* Scoped to the one banner that uses it: adding a `via` stop to the shared
   .bg-gradient-to-* rules would change every existing two-stop gradient. */
.bg-gradient-to-r.via-purple-500\/5{background-image:linear-gradient(to right,var(--tw-from,transparent),rgba(168,85,247,0.05),var(--tw-to,transparent));}

/* --------------------------------------------------------------------------
   Structural classes the markup uses that were never defined either.
   Kept deliberately minimal - these only restore the container behaviour the
   markup already assumes (a padded, scrollable body under a screen header),
   they do not introduce new visual design.
   -------------------------------------------------------------------------- */
.screen-content{
    /* top padding: tab rows (PvP, Quests, Sammlung) sat flush against the
       sticky header's bottom border */
    padding:.75rem 1rem 1rem;
    overflow-y:auto;
    overflow-x:hidden;
    -webkit-overflow-scrolling:touch;
}
.screen-content.p-4{padding:1rem;}

/* The Collectibles screen's progress summary renders four label/value rows
   with these two classes and no utilities, so without them the label and the
   value ran together inline ("Badges:3/12 (25%)") in an unpadded block. */
.progress-overview{
    background:var(--glass-bg);
    border:1px solid var(--glass-border);
    border-radius:var(--radius-md,10px);
    padding:.75rem 1rem;
}
.progress-item{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:.75rem;
    padding:.35rem 0;
    font-size:.8125rem;
}
.progress-item+.progress-item{border-top:1px solid var(--border-color);}

.section-title{
    font-size:.8125rem;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:.08em;
    color:var(--text-secondary);
    margin:0 0 .5rem;
}

/* --------------------------------------------------------------------------
   Phone-layout & legibility hardening (360-430px wide Telegram viewports).
   -------------------------------------------------------------------------- */

/* Trade screen asset cards: flex:1 + min-width:120px squeezed three cards into
   390px while their content (name + category badge + price + vol badge) was
   ~170px wide, so badges and prices spilled over the neighbouring card. Size
   each card to its content and let the row scroll horizontally instead. */
.asset-row > .asset-btn {
    flex: 0 0 auto;
    min-width: 150px;
    max-width: 85vw;
}
.asset-btn .asset-info { min-width: 0; }
.asset-btn .asset-name,
.asset-btn .asset-info > .flex { white-space: nowrap; }

/* Trading-league widget: the "Ranking" button inherited .btn-secondary's
   width:100%, took half the card and crushed the league name / rank pill
   into a 3-line stack; it was also only 22px tall. */
#trading-league-toggle-btn {
    width: auto;
    flex-shrink: 0;
    min-height: 32px;
    font-size: 11px;
    padding: 4px 10px;
}
#trading-league-widget-container .flex.items-center.gap-2 { flex-wrap: wrap; row-gap: 2px; }

/* 20px-tall, 9px-text "Vorschlag" (AI trade suggestion) button. */
button[onclick="AiAssistant.suggestTrade()"] {
    min-height: 30px;
    font-size: 11px !important;
    padding: 4px 10px !important;
}

/* White text on the light cyan primary gradient (#00f2fe -> #4facfe) measured
   ~1.4:1 - below any legibility bar. Same dark ink the newer components
   (.trade-result-btn.primary, .quest-tab.active, ...) already use. */
.btn-primary,
.checkin-btn:not(:disabled):not(.is-claimed),
.claim-btn,
.tab-btn.active,
.btn-purchase,
.premium-btn,
.reward-btn,
.achievement-btn,
.asset-filter-chip.active,
.opt-in-btn.primary,
.btn-glow {
    color: #04121a;
}
/* Green/red buttons keep white text - their gradients are darkened in
   main.css :root instead (see --gradient-success / --gradient-danger). */

/* Inactive tab in a btn-primary tab pair (PvP): it used to switch to the green
   .btn-secondary, so both tabs looked "selected". */
.btn-primary.btn-tab-inactive {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    box-shadow: none;
}

/* Never let a transient off-canvas element (slide-in animation, toast) make
   the whole page pan sideways on iOS. */
html { overflow-x: hidden; }
