@font-face {
  font-family: "Inter";
  src: url("/fonts/inter.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════
   Design tokens — the single source of truth for typography and text
   colour. Every rule in this file and in every *.razor.css references a
   token; literal font sizes and literal text colours are rejected by
   TypographyTokenTests.
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  color-scheme: dark;

  /* ---------- surfaces ---------- */
  --sf-bg: #110d16;
  --sf-surface: #1a1424;
  --sf-surface-hover: #201828;
  --sf-border: rgba(255, 255, 255, 0.08);
  --sf-border-strong: rgba(255, 255, 255, 0.18);
  --sf-accent: #A78BFA;
  --sf-accent-soft: rgba(167, 139, 250, 0.12);
  --sf-accent-strong: #7B48A4;

  /* ---------- text colour ramp ----------
     A single ramp, tinted #f5f3ff to match the purple brand. Every text
     colour on the storefront resolves to one of these steps — a second,
     untinted ramp would read as a different temperature side by side. */
  --sf-text: #f5f3ff;              /* primary copy, headings */
  --sf-text-strong: rgba(245, 243, 255, 0.9);  /* metric values */
  --sf-text-muted: rgba(245, 243, 255, 0.55);  /* secondary copy */
  --sf-text-subtle: rgba(245, 243, 255, 0.4);  /* captions, empty states */
  --sf-text-faint: rgba(245, 243, 255, 0.3);   /* stat labels, hints */
  --sf-text-ghost: rgba(245, 243, 255, 0.25);  /* the quietest sub-labels */
  --sf-text-success: rgba(34, 197, 94, 0.8);
  --sf-text-danger: rgba(239, 68, 68, 0.7);
  --sf-text-on-accent: #fff;       /* on a filled accent surface, not the page bg */

  /* ---------- font families ---------- */
  --sf-font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --sf-font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* ---------- type scale ----------
     Sans carries reading and heading text; mono carries labels, metrics
     and anything code-adjacent. Sizes below are shared by both. */
  --sf-text-hero: 3.5rem;     /* 56px — landing hero only */
  --sf-text-5xl: 3rem;        /* 48px — account balance */
  --sf-text-4xl: 2.25rem;     /* 36px — plan price */
  --sf-text-3xl: 1.875rem;    /* 30px — page h1 */
  --sf-text-2xl: 1.5rem;      /* 24px — h2, large metric */
  --sf-text-xl: 1.25rem;      /* 20px — h3, metric value */
  --sf-text-lg: 1.125rem;     /* 18px — h4 */
  --sf-text-md: 1rem;         /* 16px — card title, h5 */
  --sf-text-base: 0.875rem;   /* 14px — h6, section heading */
  --sf-text-sm: 0.8125rem;    /* 13px — body copy (MudBlazor Body1) */
  --sf-text-xs: 0.75rem;      /* 12px — small copy (MudBlazor Body2) */
  --sf-text-2xs: 0.6875rem;   /* 11px — dense controls, tabs */
  --sf-text-3xs: 0.625rem;    /* 10px — caption, stat label */
  --sf-text-micro: 0.5625rem; /* 9px  — the smallest label we ship */

  /* ---------- spacing ----------
     --sf-page-top is the gap between the sticky header and a page's first
     element, on top of .storefront-main's own 1.5rem. Every routed page uses
     it, so the header sits the same distance from the content everywhere. */
  --sf-page-top: 1.5rem;      /* 24px + 24px from .storefront-main = 48px */
  --sf-section-y: 3rem;       /* vertical rhythm between bands inside a page */

  /* ---------- line heights ---------- */
  --sf-leading-tight: 1.3;
  --sf-leading-snug: 1.45;
  --sf-leading-normal: 1.55;
  --sf-leading-relaxed: 1.6;

  /* ---------- weights ---------- */
  --sf-weight-normal: 400;
  --sf-weight-medium: 500;
  --sf-weight-semibold: 600;
}

/* font-size stays off <html>: every --sf-text-* token is in rem, so rem must
   keep resolving against the browser's 16px root. Sizing <html> too would
   scale the root and then scale body again against the new root — 13px
   becomes 10.56px and the whole scale shifts under it. */
html {
  background: var(--sf-bg);
  color: var(--sf-text);
  font-family: var(--sf-font-sans) !important;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body {
  background: var(--sf-bg);
  color: var(--sf-text);
  font-family: var(--sf-font-sans) !important;
  font-size: var(--sf-text-sm);
  line-height: var(--sf-leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* Force Inter font on all MudBlazor typography elements */
.mud-typography, .mud-typography-body1, .mud-typography-body2,
.mud-typography-h1, .mud-typography-h2, .mud-typography-h3,
.mud-typography-h4, .mud-typography-h5, .mud-typography-h6,
.mud-typography-subtitle1, .mud-typography-subtitle2,
.mud-typography-caption, .mud-typography-overline,
.mud-input, .mud-input-text, .mud-button-root,
.mud-table, .mud-tab, .mud-chip {
  font-family: var(--sf-font-sans) !important;
}

/* ── Heading baseline ──
   StorefrontTheme's Typography.H1–H6 only reaches <MudText Typo="...">.
   Most headings on the storefront are plain <h1>…<h4>, which the theme
   never sees, so without these rules they fall back to the user-agent
   stylesheet: sizes derived from the 13px body and weight 700 where the
   brand uses 600. Declaring the scale here means a heading renders the
   same whether it is written as markup or as a MudText. */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--sf-font-sans);
  color: var(--sf-text);
  font-weight: var(--sf-weight-semibold);
  /* The user-agent stylesheet gives each heading level its own em-based
     margin, so an h1 opening a page pushed its title further from the header
     than an h2 or a wrapper div did. Spacing below the header belongs to
     .storefront-page; spacing between blocks is set where it is needed. */
  margin: 0 0 0.5rem;
}
/* h1 is the only step that changes with viewport: a 30px page title costs
   too much width on a phone, and every page carries one. */
h1 { font-size: var(--sf-text-2xl); line-height: var(--sf-leading-tight); letter-spacing: -0.02em; }
@media (min-width: 640px) { h1 { font-size: var(--sf-text-3xl); } }
h2 { font-size: var(--sf-text-2xl); line-height: var(--sf-leading-tight); letter-spacing: -0.02em; }
h3 { font-size: var(--sf-text-xl); line-height: 1.35; letter-spacing: -0.01em; }
h4 { font-size: var(--sf-text-lg); line-height: 1.4; letter-spacing: -0.01em; }
h5 { font-size: var(--sf-text-md); line-height: var(--sf-leading-snug); }
h6 { font-size: var(--sf-text-base); line-height: var(--sf-leading-normal); }

/* ── Reset browser focus outline on non-interactive elements ──
   Blazor Server sets focus on headings / sections after navigation,
   which triggers the default white outline ring on dark backgrounds. */
*:focus:not(:focus-visible) { outline: none; }
h1:focus, h2:focus, h3:focus, h4:focus, h5:focus, h6:focus,
p:focus, div:focus, section:focus, main:focus, article:focus,
[tabindex="-1"]:focus { outline: none; }

code, pre { font-family: var(--sf-font-mono); }

.surface {
  background: var(--sf-surface);
  border-radius: 16px;
}
.surface-hover:hover { background: var(--sf-surface-hover); }
.smooth { transition: all .2s ease; }
.f-smooth { transition: opacity .2s ease, transform .2s ease; }
.border-dotted { border: 1.5px dotted var(--sf-border); }

/* ---------- layout ----------
   Component-owned rules live in the matching *.razor.css. What remains
   here is what no single component owns: tokens, element baselines, and
   classes shared across components. */
/* Two different jobs, so two different classes. `.storefront-page` is the
   root element of a routed page and owns the gap below the sticky header;
   `.storefront-section` is a band *within* a page and owns the rhythm
   between bands. One class doing both is what pushed each page to patch its
   own top padding — the gap below the header ranged from 24px to 88px. */
.storefront-page { padding: var(--sf-page-top) 0 0; }
.storefront-section { padding: var(--sf-section-y) 0; }
.storefront-section__intro { text-align: center; margin-bottom: 2rem; }
.storefront-section__header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1.5rem; gap: 1rem; flex-wrap: wrap; }
.storefront-section__subtitle { color: var(--sf-text-muted); }

/* Brand lockup — rendered by both Header and Footer, so it cannot live in
   either one's scoped stylesheet. */
.storefront-brand { display: flex; align-items: center; gap: 0.5rem; text-decoration: none; color: var(--sf-text); }
.storefront-brand__mark { height: 48px; width: auto; }

/* ---------- buttons ---------- */
.storefront-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.5rem 1.25rem; border-radius: 999px; border: 1.5px dotted var(--sf-border-strong); text-decoration: none; font-family: var(--sf-font-mono); font-size: var(--sf-text-sm); cursor: pointer; transition: all .2s ease; background: transparent; color: var(--sf-text); }
.storefront-btn:hover { border-color: var(--sf-accent); background: var(--sf-accent-soft); }
.storefront-btn--primary { background: var(--sf-accent-soft); color: var(--sf-text); border-color: var(--sf-accent); }
.storefront-btn--primary:hover { background: rgba(167, 139, 250, 0.22); }
.storefront-btn--ghost { background: transparent; }
.storefront-btn--block { width: 100%; padding: 0.75rem 1rem; }

/* ---------- api keys ---------- */
.api-keys__subtitle { color: var(--sf-text-muted); font-family: var(--sf-font-mono); font-size: var(--sf-text-xs); margin: 0.25rem 0 0.5rem; }
.api-keys__toolbar { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }
.api-keys__search-sm { width: 275px; }
.api-keys__search-sm .mud-input-adornment-start { margin-inline-end: 0px !important;}
.api-keys__search-sm input.mud-input-slot { padding: 7px 5px 7px 0px !important; height: auto !important; }
.api-keys__search-sm .mud-input-root-outlined { height: auto !important; }
.api-keys__search-sm .mud-input { font-size: var(--sf-text-xs); }
.api-keys__search-sm .mud-input-outlined-border { border-color: var(--sf-border-strong); }
@media (max-width: 768px) { .api-keys__search-sm { width: 180px; } .api-keys__toolbar { flex-wrap: wrap; } }
/* Rendered by both ApiKeys and Usage. */
.api-keys__empty { padding: 2rem; text-align: center; color: var(--sf-text-muted); }

/* ---------- register ---------- */
.register-page__form { display: flex; flex-direction: column; gap: 0.5rem; }
.register-page__form label { color: var(--sf-text-muted); font-family: var(--sf-font-mono); font-size: var(--sf-text-2xs); text-transform: uppercase; letter-spacing: 0.08em; display: block; margin-top: 0.5rem; }

/* ---------- footer ---------- */
.storefront-chip { padding: 0.25rem 0.75rem; border: 1.5px dotted var(--sf-border); border-radius: 999px; color: var(--sf-text-muted); font-family: var(--sf-font-mono); font-size: var(--sf-text-2xs); text-decoration: none; }
.storefront-chip:hover { color: var(--sf-accent); border-color: var(--sf-accent); }

/* ---------- language switcher ----------
   The <option> list is painted by the OS popup, outside the component's
   scope attribute, so this rule cannot move into LanguageSwitcher.razor.css. */
.storefront-lang__select option {
  background: var(--sf-surface);
  color: var(--sf-text);
}

/* ---------- user menu ----------
   MudMenu renders its popover into a portal at the document root, so a
   scoped rule would never reach it. */
.storefront-user-popover { max-width: 220px !important; }
.storefront-user-popover .mud-list-item { padding: 8px 16px !important; }

/* ---------- api key settings drawer ----------
   MudDrawer portals its content, same reason as above. */
.apikey-drawer__field-label { font-family: var(--sf-font-mono); font-size: var(--sf-text-2xs); color: var(--sf-text-muted); margin: 0 0 0.25rem; }

/* ── Active nav item highlighting ── */
.storefront-nav__item--active {
  color: var(--sf-text) !important;
  border-bottom: 2px solid var(--sf-accent);
  padding-bottom: 2px;
}

/* ── Mobile hamburger toggle (kept here for SSR reliability — see commit 6cd7c0c) ── */
.storefront-nav-toggle { flex-shrink: 0; color: var(--sf-text); }
@media (min-width: 900px) {
  .storefront-nav-toggle { display: none !important; }
}

/* ── Mobile drop-down nav panel ── */
.storefront-mobile-nav {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  padding: 0.5rem 1.25rem 0.75rem;
  background: rgba(17, 13, 22, 0.97);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--sf-border);
  border-bottom: 1.5px dotted var(--sf-border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  z-index: 49;
}
@media (min-width: 900px) {
  .storefront-mobile-nav { display: none !important; }
}
.storefront-mobile-nav__item {
  display: block;
  width: 100%;
  color: var(--sf-text-muted);
  font-family: var(--sf-font-mono);
  font-size: var(--sf-text-base);
  text-decoration: none;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--sf-border);
}
.storefront-mobile-nav__item:last-child { border-bottom: none; }
.storefront-mobile-nav__item:hover,
.storefront-mobile-nav__item.storefront-nav__item--active { color: var(--sf-text); }

/* ── Dashboard top-up button ──
   MudButton's own .mud-button-root carries a font-size, so this override
   needs the compound selector to win on specificity. */
.dashboard__topup-btn.mud-button-root {
  margin-left: auto;
  font-size: var(--sf-text-2xs) !important;
  letter-spacing: 0.04em;
  padding: 3px 10px !important;
  min-width: auto !important;
  height: 28px !important;
  border-radius: 6px !important;
}

/* ── Dashboard: mobile model-cost breakdown ──
   Dashboard.razor.css owns the desktop rules; these mobile overrides stay
   global because the breakdown rows are also reached by MudTable markup
   that renders outside the page's scope attribute. */
@media (max-width: 639px) {
    .dashboard__section-hint { margin-left: 0; width: 100%; }
    .model-breakdown { overflow-x: hidden; }
    .model-breakdown__row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
        padding: 0.625rem 0.75rem;
        width: 100%;
        min-width: 0;
    }
    .model-breakdown__name { min-width: 0; width: 100%; }
    .model-breakdown__name strong {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: block;
    }
    .model-breakdown__stats {
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 0.375rem;
        width: 100%;
        min-width: 0;
        max-width: 100%;
        padding-bottom: 0.25rem;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
    }
    .model-breakdown__stat {
        flex: 0 0 auto;
        min-width: 72px;
        padding: 0.3rem 0.5rem;
    }
    .model-breakdown__stat-value { font-size: var(--sf-text-xs); }
    .model-breakdown__stat-label {
        font-size: var(--sf-text-micro);
        white-space: nowrap;
        overflow: hidden;
    }
}
