/* ---- tokens.css ---- */

/**
 * Design tokens - the single source of truth for the Coin Bank visual
 * language. Lifted from design/handoff-v1's "Coin Bank Prototype.dc.html"
 * (the live, current turn - the design board's earlier "rationale" turn
 * is explicitly superseded and occasionally names slightly different
 * hex values; wherever the two disagree, the values below follow the
 * prototype, since that's the one the design board itself points to as
 * canonical). See DESIGN.md for what each token is for and the rules
 * around when to use which.
 *
 * Dark only - there is no light theme to swap tokens for.
 */
:root {
  /* ---- surfaces ---- */
  --cb-bg: #0b1622;
  --cb-bg-gradient: radial-gradient(ellipse at 50% 0%, #132436 0%, #0b1622 60%);
  --cb-surface-1: #1a2635; /* card */
  --cb-surface-2: #111e2b; /* recessed: input rows, chips, dashed empty-states */
  --cb-surface-3: rgba(18, 24, 42, 0.9); /* tab bar / sheet backdrop, blur 12 */
  --cb-sheet-top: #151c33;

  --cb-border-weak: rgba(255, 255, 255, 0.06);
  --cb-border: rgba(255, 255, 255, 0.1);
  --cb-border-strong: rgba(255, 255, 255, 0.14);
  --cb-border-top-highlight: rgba(255, 255, 255, 0.05);

  /* ---- text ---- */
  --cb-text: #ffffff;
  --cb-text-hero: #eafbff;
  --cb-text-secondary: #8fa3b8;
  /* X2 (Phase 10 closeout): both of these were WCAG AA contrast
     failures at their real usage sizes (11px/10px labels, disabled
     button text, footer text - all "normal text", none large enough
     for the 3:1 exemption). Old values: --cb-text-label #6b7f94 (~4.42:1
     on --cb-bg, ~3.71:1 on --cb-surface-1 - the card background several
     of its real usages sit on, e.g. Button.module.css's :disabled
     states); --cb-text-dim #4e6075 (~2.83:1 on --cb-bg, worse on any
     lighter surface). Fixed by lightening the TEXT shade only, per this
     step's own rule - the brand accents (cyan/orange) were NOT the
     failure (see DESIGN.md's contrast audit: both measure ~9-10:1 as
     text on this palette, comfortably passing). New values keep >=4.5:1
     against every background token these colors are ACTUALLY used on,
     with a real margin against hand-calculation rounding. */
  --cb-text-label: #859aae;
  --cb-text-dim: #7d95a9;

  /* ---- cyan: $ / actions / the vault's charge ---- */
  --cb-cyan-rgb: 0, 209, 255;
  --cb-cyan: #00d1ff;
  --cb-cyan-hi: #22dfff;
  --cb-cyan-lo: #0095e0;
  --cb-cyan-gradient: linear-gradient(180deg, var(--cb-cyan-hi) 0%, var(--cb-cyan) 40%, var(--cb-cyan-lo) 100%);

  /* ---- orange: ₿ / cost / bitcoin ---- */
  --cb-orange-rgb: 255, 186, 0;
  --cb-orange: #ffba00;
  --cb-orange-hi: #ffcf3d;
  --cb-orange-lo: #e09a00;
  --cb-orange-gradient: linear-gradient(180deg, var(--cb-orange-hi) 0%, var(--cb-orange) 60%, var(--cb-orange-lo) 100%);
  --cb-orange-fg: #2a1a00; /* ink text on solid-orange surfaces */

  /* neutral: spending $ on something that isn't a currency (an upgrade
     purchase) - deliberately neither cyan nor orange, per DESIGN.md's
     color rule (E1). A light slate gradient, dark-navy ink text. */
  --cb-neutral-hi: #e7ecf7;
  --cb-neutral-lo: #a9b4ce;
  --cb-neutral-gradient: linear-gradient(180deg, var(--cb-neutral-hi) 0%, var(--cb-neutral-lo) 100%);
  --cb-neutral-fg: #0b1622;

  /* cash ($) icon - radial, distinct from the flat cost-button orange */
  --cb-cash-icon-hi: #ffe28a;
  --cb-cash-icon-mid: #ffba00;
  --cb-cash-icon-lo: #b87700;
  --cb-cash-icon-fg: #3a2600;

  /* bitcoin (₿) icon - radial, distinct hue from cost-button orange */
  --cb-btc-icon-hi: #ffb74a;
  --cb-btc-icon-mid: #f7931a;
  --cb-btc-icon-lo: #b85f00;
  --cb-btc-icon-fg: #ffffff;

  /* ---- status: green/red reserved for exactly one job - ahead/behind,
     buy/sell markers, live dot. Never used decoratively elsewhere. ---- */
  --cb-green-rgb: 34, 197, 94;
  --cb-green: #22c55e;
  --cb-red-rgb: 239, 68, 68;
  --cb-red: #ef4444;
  --cb-red-text: #f87171; /* AA-safe red for body text on navy */
  --cb-caution: #ffba00;
  --cb-caution-text: #ffd466;

  /* ornate gold - vault level 3 only, nowhere else */
  --cb-gold-hi: #f3d48a;
  --cb-gold-lo: #b98a3a;

  /* Phase 12 Step 4b: Ranking's rank-1/2/3 medal discs (design/handoff-v3).
     Ranks 4+ reuse --cb-surface-2/--cb-text-secondary directly (no new
     tokens needed - already the exact colors); "you" reuses --cb-cyan
     with its own ink (--cb-cyan-fg below). */
  --cb-medal-gold-hi: #ffe28a;
  --cb-medal-gold-mid: #ffba00;
  --cb-medal-gold-lo: #c98a00;
  --cb-medal-gold-fg: #3a2600;
  --cb-medal-silver-hi: #e6ecf2;
  --cb-medal-silver-mid: #b8c4d0;
  --cb-medal-silver-lo: #8393a3;
  --cb-medal-silver-fg: #1a2635;
  --cb-medal-bronze-hi: #e0a272;
  --cb-medal-bronze-mid: #c77b45;
  --cb-medal-bronze-lo: #8e5027;
  --cb-medal-bronze-fg: #2a1300;
  --cb-cyan-fg: #062330;

  /* ---- AS2: layout scale - see DESIGN.md's "Layout scale" section for
     the full reference table and rationale. Set at runtime, as inline
     style, on the app shell root (App.tsx's Shell, via useLayoutScale) -
     these defaults (1) are what every OTHER consumer of this stylesheet
     (Storybook, a screen test that doesn't mount Shell, packages/ui's
     own dist consumers) sees, matching today's shipped layout exactly.
     `--cb-scale` drives box heights/gaps/radii/icons; `--cb-type-scale`
     (sqrt-damped) drives ONLY font sizes - never conflate the two, a
     font using `--cb-scale` directly would shrink as fast as the boxes
     around it and become illegible before the layout looks cramped. ---- */
  --cb-scale: 1;
  --cb-type-scale: 1;

  /* ---- radii ---- */
  --cb-r-sm: calc(10px * var(--cb-scale));
  --cb-r-md: calc(12px * var(--cb-scale));
  --cb-r-lg: calc(14px * var(--cb-scale));
  --cb-r-xl: calc(16px * var(--cb-scale));
  --cb-r-2xl: calc(20px * var(--cb-scale));
  --cb-r-sheet: calc(24px * var(--cb-scale));
  --cb-r-pill: 999px; /* always fully rounded regardless of size - never scaled */

  /* ---- spacing: 4pt grid ---- */
  --cb-sp-1: calc(4px * var(--cb-scale));
  --cb-sp-2: calc(8px * var(--cb-scale));
  --cb-sp-3: calc(12px * var(--cb-scale));
  --cb-sp-4: calc(16px * var(--cb-scale));
  --cb-sp-5: calc(24px * var(--cb-scale));

  /* ---- icon sizes - AS2: previously hardcoded as SVG width/height
     attributes wherever an icon appeared (e.g. TabBar's nav icons);
     those are now CSS-sized against these tokens instead, so an icon
     scales the same way as everything else around it. ---- */
  --cb-icon-sm: calc(16px * var(--cb-scale));
  --cb-icon-md: calc(22px * var(--cb-scale));
  --cb-icon-lg: calc(28px * var(--cb-scale));

  /* ---- type scale: Manrope, tabular numerals on every changing number.
     AS2: every size below is `max(<floor>, calc(<ref-px> * var(--cb-
     type-scale)))` - the floor NEVER binds at scale 1 (every floor here
     is <= its own token's reference px), so the iPhone reference is
     pixel-identical to before this change; it only stops a SHRINKING
     scale from making text illegible. Two floors, per AS2's own
     absolute invariants: `--cb-fs-sm` (12px) is the "labels" reference -
     nothing below it ever renders smaller than 12px; `--cb-fs-md` (14px)
     is the "body" reference - it and everything visually larger than it
     never renders smaller than 14px. `--cb-fs-2xs`/`--cb-fs-xs` (below
     the labels tier - tick marks, tiny badges) scale freely with no
     extra floor beyond `--cb-type-scale`'s own bounded range
     (sqrt(0.7)..sqrt(1.15), i.e. never more than ~16% smaller than
     today at the scale floor). ---- */
  --cb-font: 'Manrope', system-ui, -apple-system, sans-serif;
  --cb-fs-2xs: calc(10px * var(--cb-type-scale));
  --cb-fs-xs: calc(11px * var(--cb-type-scale));
  --cb-fs-sm: max(12px, calc(12px * var(--cb-type-scale)));
  --cb-fs-base: max(12px, calc(13px * var(--cb-type-scale)));
  --cb-fs-md: max(14px, calc(14px * var(--cb-type-scale)));
  --cb-fs-lg: max(14px, calc(15px * var(--cb-type-scale)));
  --cb-fs-xl: max(14px, calc(17px * var(--cb-type-scale)));
  --cb-fs-2xl: max(14px, calc(18px * var(--cb-type-scale)));
  --cb-fs-3xl: max(14px, calc(20px * var(--cb-type-scale)));
  --cb-fs-stat-sm: max(14px, calc(26px * var(--cb-type-scale)));
  --cb-fs-stat: max(14px, calc(28px * var(--cb-type-scale)));
  --cb-fs-stat-lg: max(14px, calc(32px * var(--cb-type-scale)));
  --cb-fs-display: max(14px, calc(36px * var(--cb-type-scale)));
  --cb-fs-hero: max(14px, calc(44px * var(--cb-type-scale)));
  --cb-fs-hero-xl: max(14px, calc(52px * var(--cb-type-scale)));

  /* ---- shadows / glows: accent as a box-shadow at 30-55% alpha, never a
     filter on text below 16px ---- */
  --cb-glow-cyan-sm: 0 0 12px rgba(var(--cb-cyan-rgb), 0.3);
  --cb-glow-cyan: 0 0 22px rgba(var(--cb-cyan-rgb), 0.4);
  --cb-glow-cyan-lg: 0 0 30px rgba(var(--cb-cyan-rgb), 0.45);
  --cb-glow-cyan-xl: 0 0 36px rgba(var(--cb-cyan-rgb), 0.55);
  --cb-glow-orange: 0 0 22px rgba(var(--cb-orange-rgb), 0.4);
  --cb-glow-orange-lg: 0 0 30px rgba(var(--cb-orange-rgb), 0.5);
  --cb-glow-green: 0 0 24px rgba(var(--cb-green-rgb), 0.4);
  --cb-glow-red: 0 0 24px rgba(var(--cb-red-rgb), 0.4);
  --cb-card-top-light: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --cb-sheet-shadow: 0 -20px 60px rgba(0, 0, 0, 0.6);

  /* ---- motion ---- */
  --cb-dur-fast: 0.2s;
  --cb-dur: 0.25s;
  --cb-dur-slow: 0.3s;
  --cb-dur-fill: 0.8s;
  --cb-ease: ease;

  /* ---- tap targets ---- */
  /* AS2: an ABSOLUTE floor, never derived from --cb-scale - this IS the
     floor value itself. A breached floor means the content region
     scrolls (it already does, per H2/H3 - see App.module.css's .main),
     never a smaller tap target. */
  --cb-tap-min: 44px;
  /* AS2: the primary action's height is a fixed share of content height
     at the reference (56px / 754px reference content height =~ 7.4%,
     see DESIGN.md's "Layout scale" table) - scaling it by THE SAME
     `--cb-scale` used for everything else keeps that share consistent
     whenever height is the binding dimension (the common, reported
     failure: a short/squeezed screen), which is exactly when the old
     fixed 56px used to dominate a collapsing layout. Floored at the
     44px tap-target minimum, same as everything else. */
  --cb-cta-height: max(var(--cb-tap-min), calc(56px * var(--cb-scale)));
}


/* ---- fonts.css ---- */

/**
 * Self-hosted Manrope - subset to Basic Latin + Latin-1 + Latin Extended
 * A/B (covers Romanian diacritics once ro.json is actually translated) +
 * general punctuation/math/currency symbols actually used in the UI
 * (₿ U+20BF, − U+2212, ≈ U+2248, … U+2026, › U+203A). No Cyrillic yet -
 * ru.json is still English-fallback text (see i18n/index.ts), so it costs
 * nothing to add that range here the day ru.json is real.
 *
 * NOT loaded from Google Fonts or any CDN - self-hosted so Telegram
 * WebViews never make a third-party font request, and so this keeps
 * working if the host domain's outbound access is ever restricted.
 * `tnum` (tabular numerals) is confirmed present in this subset - see
 * DESIGN.md.
 */
@font-face {
  font-family: 'Manrope';
  src: url('./assets/fonts/Manrope-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Manrope';
  src: url('./assets/fonts/Manrope-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Manrope';
  src: url('./assets/fonts/Manrope-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Manrope';
  src: url('./assets/fonts/Manrope-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Manrope';
  src: url('./assets/fonts/Manrope-800.woff2') format('woff2');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}


/* ---- base.css ---- */

/**
 * ZZ1 (Phase 15 Step 4a): the minimum global CSS the shared components
 * actually depend on - lifted out of apps/web/src/styles/global.css,
 * which stays where it is for everything Telegram/PWA-specific
 * (overscroll-behavior, scrollbar-hiding, the body background gradient).
 * Both consumers load this file; apps/web's own global.css layers on
 * top of it unchanged.
 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Design system rule: tabular numerals on every element that shows a
   changing number, so ticking digits never shift the surrounding layout
   (vault accrual, price, countdowns, balances, admin ledger figures).
   Apply this class to any number-bearing element - see DESIGN.md. */
.cb-num {
  font-variant-numeric: tabular-nums;
}

/* Accessibility heading landmark that stays in the DOM without
   reproducing text a screen deliberately omits. */
.cb-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Shared across any "attention, but not urgent" indicator - InlineNotice's
   blinking dot, a stale-price notice, etc. */
@keyframes cb-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}


/* ---- components/BtcAmount.css ---- */

.ui-btc-amount {
  font-weight: 800;
}

.ui-btc-amount__head {
  color: var(--cb-text-secondary);
}

.ui-btc-amount__tail {
  color: var(--cb-btc-icon-hi);
  text-shadow: 0 0 10px rgba(var(--cb-orange-rgb), 0.5);
}

.ui-btc-amount__tail--plain {
  color: var(--cb-text);
}

.ui-btc-amount__suffix {
  font-size: 0.5em;
  color: var(--cb-text-secondary);
  font-weight: 700;
  margin-left: 0.3em;
}


/* ---- components/Button.css ---- */

.ui-btn {
  font-family: var(--cb-font);
  font-weight: 800;
  border: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cb-sp-2);
  transition:
    filter var(--cb-dur-fast) var(--cb-ease),
    box-shadow var(--cb-dur-fast) var(--cb-ease),
    transform var(--cb-dur-fast) var(--cb-ease);
  min-height: var(--cb-tap-min);
}

.ui-btn:active:not(:disabled) {
  transform: scale(0.98);
}

.ui-btn:disabled {
  cursor: not-allowed;
}

/* ---- sizes ---- */
.ui-btn--cta {
  min-height: var(--cb-cta-height);
  border-radius: var(--cb-r-2xl);
  font-size: var(--cb-fs-xl);
  padding: 0 var(--cb-sp-4);
}
.ui-btn--md {
  min-height: 40px;
  border-radius: var(--cb-r-md);
  font-size: var(--cb-fs-md);
  padding: 0 var(--cb-sp-3);
}
.ui-btn--sm {
  min-height: 36px;
  border-radius: var(--cb-r-pill);
  font-size: var(--cb-fs-sm);
  padding: 0 var(--cb-sp-3);
}

.ui-btn--block {
  width: 100%;
}

/* ---- variants ---- */
.ui-btn--primary {
  color: #ffffff;
  background: var(--cb-cyan-gradient);
  box-shadow:
    var(--cb-glow-cyan-lg),
    inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.ui-btn--primary:disabled {
  background: var(--cb-surface-1);
  color: var(--cb-text-label);
  box-shadow: inset 0 0 0 1px var(--cb-border-weak);
}

.ui-btn--accent {
  color: var(--cb-orange-fg);
  background: var(--cb-orange-gradient);
  box-shadow:
    var(--cb-glow-orange-lg),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.ui-btn--accent:disabled {
  background: var(--cb-surface-1);
  color: var(--cb-text-label);
  box-shadow: inset 0 0 0 1px var(--cb-border-weak);
}

.ui-btn--neutral {
  color: var(--cb-neutral-fg);
  background: var(--cb-neutral-gradient);
  box-shadow:
    0 0 18px rgba(255, 255, 255, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.ui-btn--neutral:disabled {
  background: var(--cb-surface-1);
  color: var(--cb-text-label);
  box-shadow: inset 0 0 0 1px var(--cb-border-weak);
}

.ui-btn--secondary {
  color: var(--cb-text);
  background: transparent;
  border: 1px solid var(--cb-border-strong);
}
.ui-btn--secondary:disabled {
  color: var(--cb-text-label);
  border-color: var(--cb-border-weak);
}

.ui-btn--danger {
  color: var(--cb-red-text);
  background: rgba(var(--cb-red-rgb), 0.12);
  border: 1px solid rgba(var(--cb-red-rgb), 0.5);
}
.ui-btn--danger:disabled {
  color: var(--cb-text-label);
  background: var(--cb-surface-1);
  border-color: var(--cb-border-weak);
}

/* BB1 (Phase 12): the "safe" half of a destructive-confirmation pair -
   identical shape/opacity formula to .danger above, cyan instead of
   red, so "keep" and "cancel" read as one deliberate pair rather than
   a bare text link next to a boxed button. */
.ui-btn--outline-cyan {
  color: var(--cb-cyan);
  background: rgba(var(--cb-cyan-rgb), 0.12);
  border: 1px solid rgba(var(--cb-cyan-rgb), 0.5);
}
.ui-btn--outline-cyan:disabled {
  color: var(--cb-text-label);
  background: var(--cb-surface-1);
  border-color: var(--cb-border-weak);
}

.ui-btn--ghost {
  color: var(--cb-text-secondary);
  background: transparent;
}


/* ---- components/Card.css ---- */

.ui-card {
  border-radius: var(--cb-r-xl);
  background: var(--cb-surface-1);
  border: 1px solid var(--cb-border-weak);
  box-shadow: var(--cb-card-top-light);
  padding: var(--cb-sp-3) var(--cb-sp-4);
}

.ui-card--recessed {
  background: var(--cb-surface-2);
  border-color: var(--cb-border-weak);
  box-shadow: none;
}

.ui-card--pad-sm {
  padding: var(--cb-sp-2) var(--cb-sp-3);
}

.ui-card--pad-none {
  padding: 0;
}


/* ---- components/CurrencyIcon.css ---- */

.ui-currency-icon {
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: none;
  font-weight: 800;
}

.ui-currency-icon--cash {
  background: radial-gradient(circle at 35% 30%, var(--cb-cash-icon-hi), var(--cb-cash-icon-mid) 55%, var(--cb-cash-icon-lo));
  color: var(--cb-cash-icon-fg);
}

.ui-currency-icon--btc {
  background: radial-gradient(circle at 35% 30%, var(--cb-btc-icon-hi), var(--cb-btc-icon-mid) 55%, var(--cb-btc-icon-lo));
  color: var(--cb-btc-icon-fg);
  transform: rotate(-12deg);
}

.ui-currency-icon--hero {
  width: 56px;
  height: 56px;
  font-size: 30px;
}
.ui-currency-icon--hero.ui-currency-icon--cash {
  box-shadow:
    var(--cb-glow-cyan),
    inset 0 -4px 10px rgba(0, 0, 0, 0.3);
}
.ui-currency-icon--hero.ui-currency-icon--btc {
  box-shadow:
    0 0 24px rgba(var(--cb-orange-rgb), 0.55),
    inset 0 -4px 10px rgba(0, 0, 0, 0.3);
}

.ui-currency-icon--card {
  width: 34px;
  height: 34px;
  font-size: 17px;
}
.ui-currency-icon--card.ui-currency-icon--cash {
  box-shadow: 0 0 14px rgba(var(--cb-orange-rgb), 0.45), inset 0 -3px 6px rgba(0, 0, 0, 0.25);
}
.ui-currency-icon--card.ui-currency-icon--btc {
  box-shadow: 0 0 14px rgba(247, 147, 26, 0.5), inset 0 -3px 6px rgba(0, 0, 0, 0.25);
}

.ui-currency-icon--inline {
  width: 16px;
  height: 16px;
  font-size: 10px;
}


/* ---- components/EmptyState.css ---- */

.ui-empty-state {
  padding: 22px 20px;
  border-radius: var(--cb-r-xl);
  border: 1px dashed var(--cb-border-strong);
  background: var(--cb-surface-2);
  text-align: center;
}

.ui-empty-state__title {
  font-weight: 800;
  font-size: var(--cb-fs-lg);
}

.ui-empty-state__description {
  font-size: var(--cb-fs-sm);
  color: var(--cb-text-secondary);
  line-height: 1.4;
  margin-top: var(--cb-sp-1);
}

.ui-empty-state__action {
  margin-top: var(--cb-sp-3);
}


/* ---- components/InlineNotice.css ---- */

.ui-inline-notice {
  display: flex;
  align-items: center;
  gap: var(--cb-sp-3);
  padding: var(--cb-sp-3);
  border-radius: var(--cb-r-lg);
  font-size: var(--cb-fs-base);
  font-weight: 600;
  line-height: 1.35;
}

.ui-inline-notice--warn {
  background: rgba(var(--cb-orange-rgb), 0.1);
  border: 1px solid rgba(var(--cb-orange-rgb), 0.3);
  color: var(--cb-caution-text);
}

.ui-inline-notice--error {
  background: rgba(var(--cb-red-rgb), 0.1);
  border: 1px solid rgba(var(--cb-red-rgb), 0.3);
  color: var(--cb-red-text);
}

.ui-inline-notice__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  background: currentColor;
}

.ui-inline-notice__dot--blink {
  animation: cb-blink 1.2s infinite;
}


/* ---- components/Segmented.css ---- */

.ui-segmented {
  display: grid;
  gap: 4px;
  padding: 4px;
  border-radius: var(--cb-r-lg);
  background: var(--cb-surface-1);
  border: 1px solid var(--cb-border-weak);
}

.ui-segmented__option {
  font-family: var(--cb-font);
  font-weight: 700;
  font-size: var(--cb-fs-md);
  min-height: 42px;
  border: 0;
  border-radius: 11px;
  color: var(--cb-text-secondary);
  background: transparent;
  cursor: pointer;
  transition:
    color var(--cb-dur-fast) var(--cb-ease),
    background var(--cb-dur-fast) var(--cb-ease),
    box-shadow var(--cb-dur-fast) var(--cb-ease);
}

.ui-segmented__option--active-cyan {
  color: #ffffff;
  background: var(--cb-cyan-gradient);
  box-shadow: var(--cb-glow-cyan-sm);
}

.ui-segmented__option--active-orange {
  color: var(--cb-orange-fg);
  background: var(--cb-orange-gradient);
  box-shadow: 0 0 16px rgba(var(--cb-orange-rgb), 0.4);
}


/* ---- components/SheetShell.css ---- */

@keyframes cb-sheet-in {
  from {
    transform: translateY(40px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.ui-sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(3, 8, 14, 0.65);
  backdrop-filter: blur(4px);
  /* AM3: tappable/clickable in the common case (onClose or closeHref
     set) - a plain cursor hint costs nothing on the rare non-
     interactive fallback (see SheetShell.tsx's own `backdrop` logic). */
  cursor: pointer;
}

.ui-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 31;
  display: flex;
  flex-direction: column;
  border-radius: var(--cb-r-sheet) var(--cb-r-sheet) 0 0;
  background: var(--cb-sheet-top);
  border-top: 1px solid var(--cb-border);
  box-shadow: var(--cb-sheet-shadow);
  animation: cb-sheet-in var(--cb-dur-slow) var(--cb-ease);
}

.ui-sheet__scroll-area {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  padding: var(--cb-sp-3) var(--cb-sp-4);
}

.ui-sheet__grabber {
  width: 40px;
  height: 4px;
  border-radius: var(--cb-r-pill);
  background: rgba(255, 255, 255, 0.2);
  margin: 0 auto var(--cb-sp-3);
}

.ui-sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-sp-2);
}

.ui-sheet__title {
  font-size: var(--cb-fs-3xl);
  font-weight: 800;
  min-width: 0;
}

.ui-sheet__close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 0;
  background: var(--cb-surface-2);
  color: var(--cb-text-secondary);
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: var(--cb-fs-lg);
  line-height: 1;
  flex: none;
  text-decoration: none;
}

.ui-sheet__pinned-action {
  flex: none;
  padding: var(--cb-sp-3) var(--cb-sp-4) calc(var(--cb-sp-3) + var(--cb-safe-bottom, 0px));
}

.ui-sheet__scroll-area:last-child {
  padding-bottom: calc(var(--cb-sp-4) + var(--cb-safe-bottom, 0px));
}

/* Structural, non-overlay usage (ZZ1/apps/admin): a page section styled
   like a sheet's chrome but laid out in normal document flow, not
   fixed/overlaying anything - used when no onClose/closeHref backdrop
   is needed at all, e.g. a confirm page that IS the whole page rather
   than a modal on top of one. */
.ui-sheet--static {
  position: static;
  animation: none;
  border-radius: var(--cb-r-sheet);
}


/* ---- components/Skeleton.css ---- */

@keyframes cb-shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

.ui-skeleton {
  background: linear-gradient(90deg, var(--cb-surface-2) 25%, #1f2f40 50%, var(--cb-surface-2) 75%);
  background-size: 200% 100%;
  animation: cb-shimmer 1.4s infinite;
  border-radius: var(--cb-r-md);
}


/* ---- components/Toast.css ---- */

@keyframes cb-toast-in {
  from {
    transform: translateY(40px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.ui-toast {
  position: fixed;
  left: var(--cb-sp-4);
  right: var(--cb-sp-4);
  /* H3: clears the tab bar + version footer (~100px) AND a pinned
     primary-action button (~66px, CTA height + slot padding) when one
     is present (Vault/Trade) - a static estimate rather than reading
     the real slot height. This positioning is game-shell-specific (a
     tab bar/primary-action layout apps/admin doesn't have) - a future
     admin use of Toast should override `bottom` for its own layout
     rather than assuming this number means anything there. */
  bottom: calc(172px + env(safe-area-inset-bottom, 0px));
  z-index: 20;
  padding: var(--cb-sp-3) var(--cb-sp-4);
  border-radius: var(--cb-r-lg);
  font-size: var(--cb-fs-md);
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: var(--cb-sp-3);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
  animation: cb-toast-in var(--cb-dur-slow) var(--cb-ease);
  border: 1px solid transparent;
}

.ui-toast--ok {
  background: #0f2a1c;
  border-color: rgba(var(--cb-green-rgb), 0.5);
  color: #bbf7d0;
}

.ui-toast--info {
  background: var(--cb-surface-1);
  border-color: var(--cb-border-strong);
  color: var(--cb-text);
}
