@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/space-grotesk-600.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-400.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-500.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-600.woff2") format("woff2");
}

:root {
  --bg: #0B0B0F;
  --surface: #101014;
  --surface-2: #15151A;
  --surface-3: rgba(255, 255, 255, .03);
  --input: rgba(0, 0, 0, .35);
  --rule: rgba(255, 255, 255, .10);
  --rule-strong: rgba(255, 255, 255, .18);
  --purple: #B173E7;
  --cyan: #00EEFF;
  --yellow: #F9C824;
  --pink: #F6D2FF;
  --danger: #EF4343;
  --warn: #F9C824;
  --ink: #ffffff;
  --ink-2: rgba(255, 255, 255, .78);
  --ink-3: rgba(255, 255, 255, .58);
  /* Muted-but-meaningful text (labels, hints, meta): >=4.5:1 on every app
     surface for WCAG AA. --ink-faint (below AA) is reserved for purely
     decorative glyphs only (e.g. the "$" input adornment). */
  --ink-4: rgba(255, 255, 255, .62);
  --ink-faint: rgba(255, 255, 255, .38);
  /* avelin.ai has no bloom; keep the tokens valid but invisible so any
     `var(--glow-*)` in a shadow list is a no-op. */
  --glow-purple: 0 0 0 0 transparent;
  --glow-cyan: 0 0 0 0 transparent;
  --mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  --display: "Space Grotesk", "Helvetica Neue", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --body: "Helvetica Neue", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

html {
  min-height: 100%;
  overflow-x: hidden;
  background: #0B0B0F;
}

body {
  margin: 0;
  min-height: 100vh;
  overflow-x: hidden;
  color: var(--ink);
  font-family: var(--body);
  /* avelin.ai's canvas: a near-black field with a faint 64px grid that scrolls
     with the page (html carries its own bg, so this is NOT propagated to a
     fixed viewport layer). No radial glows — the site has none. */
  background-color: #0B0B0F;
  background-image:
    linear-gradient(rgba(255, 255, 255, .03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .03) 1px, transparent 1px);
  background-size: 64px 64px;
}

button, input, select { font: inherit; }
button { cursor: pointer; }
button:focus { outline: none; }
button:focus-visible {
  outline: 1px solid var(--purple);
  outline-offset: -1px;
}
button:disabled { cursor: not-allowed; opacity: .48; }
.hidden { display: none !important; }

/* avelin.ai top bar: one horizontal row — wordmark left, inline mono nav in the
   middle, single ghost-purple account button right. */
.sidebar {
  position: sticky;
  inset: 0 0 auto;
  z-index: 20;
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
  min-height: 72px;
  padding: 0 40px;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  background: rgba(11, 11, 15, .72);
  backdrop-filter: blur(14px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

/* Everything in the brand row rides one optical centre line. Baseline
   alignment used to push the wordmark and the mono tag up against the mark,
   because the logo is centred while the text sat on a shared baseline that
   flexbox packs to the start of the line. With line-height:1 on both text
   spans, centring their em boxes puts their cap centres within ~0.1px of each
   other and of the logo's centre, at any of the responsive font sizes. */
.brand {
  min-height: 50px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand-logo {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: block;
  align-self: center;
}

.brand-name {
  font-size: 14px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: .32em;
}

/* Tiny inline mono tag next to the wordmark (replaces the stacked subtitle). */
.brand-tag {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1;
  letter-spacing: .22em;
  text-transform: uppercase;
}

nav {
  display: flex;
  align-items: center;
  gap: 6px;
}

.nav-item {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  color: var(--ink-3);
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .02em;
  text-transform: lowercase;
  transition: color .18s ease;
}

.nav-item:hover:not(:disabled) {
  color: var(--ink);
}

/* Active route is signalled by colour only (purple) — no cyan tab or underline. */
.nav-item.active,
.nav-item.active:hover:not(:disabled) {
  color: var(--purple);
}

.dev-box {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 30;
  width: 220px;
  display: grid;
  gap: 10px;
  padding: 13px;
  border: 1px solid rgba(177, 115, 231, .28);
  border-radius: 0;
  background: rgba(255, 255, 255, .025);
}

label, .section-title {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .15em;
  text-transform: uppercase;
}

.eyebrow {
  color: var(--cyan);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .15em;
  text-transform: uppercase;
}

input, select {
  width: 100%;
  min-height: 44px;
  color: var(--ink);
  background: var(--input);
  border: 1px solid var(--rule-strong);
  border-radius: 0;
  padding: 10px 12px;
  outline: none;
}

input:focus, select:focus {
  border-color: rgba(177, 115, 231, .72);
  box-shadow: none;
}

.main {
  min-height: 100vh;
  max-width: 1440px;
  margin: 0 auto;
  padding: 26px 40px 72px;
  position: relative;
  z-index: 1;
}

.topbar {
  min-height: 38px;
  margin-bottom: 42px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.updated-line {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
}

.last-updated {
  color: var(--ink-3);
  letter-spacing: .04em;
}

.dot, .status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 6px rgba(0, 238, 255, .5);
}

.status-dot.ok {
  background: var(--cyan);
  box-shadow: 0 0 6px rgba(0, 238, 255, .5);
}

.status-dot.warn {
  background: var(--yellow);
  box-shadow: 0 0 6px rgba(249, 200, 36, .5);
}

.status-dot.danger {
  background: var(--danger);
  box-shadow: 0 0 6px rgba(239, 67, 67, .55);
}

/* Account menu + dev field, right-aligned inside the top nav bar. Wraps on
   narrow viewports so the header never clips. */
.header-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
}

/* Dev-only X-User-Sub field: kept, but compact and subtle so it never competes
   with the account button. */
.header-controls label {
  white-space: nowrap;
  font-size: 10px;
}
.header-controls #userSub {
  width: 118px;
  min-height: 32px;
  padding: 6px 9px;
  font-size: 12px;
}

/* Header account menu: a dropdown that holds the account id (click-to-copy),
   the signed-in email + Log out, and the Terms/Privacy links. */
.account-menu { position: relative; }

/* Single ghost-purple account button on the right of the bar. */
.account-menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 16px;
  color: var(--ink);
  background: rgba(177, 115, 231, .1);
  border: 1px solid rgba(177, 115, 231, .6);
  border-radius: 0;
  font-family: var(--mono);
  font-size: 13px;
  transition: border-color .18s ease, background .18s ease;
}

.account-menu-btn:hover {
  border-color: rgba(177, 115, 231, .85);
  background: rgba(177, 115, 231, .16);
}

.account-menu-btn[aria-expanded="true"] {
  border-color: rgba(177, 115, 231, .9);
  background: rgba(177, 115, 231, .18);
}

.account-menu-glyph { color: var(--purple); }
.account-menu-caption { letter-spacing: .08em; text-transform: lowercase; }

.account-menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 30;
  width: 260px;
  display: grid;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--rule-strong);
  background: rgba(16, 16, 20, .97);
  backdrop-filter: blur(14px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .5);
}

.account-menu-block { display: grid; gap: 8px; }

.account-menu-block + .account-menu-block {
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}

.account-menu-label {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
}

.account-id-copy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 9px 11px;
  color: var(--ink-2);
  background: rgba(0, 0, 0, .4);
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 0;
  font-family: var(--mono);
  font-size: 12px;
}

.account-id-copy:hover {
  color: var(--ink);
  border-color: rgba(0, 238, 255, .4);
}

.account-id-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-id-copyhint {
  flex: 0 0 auto;
  color: var(--cyan);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.account-menu-email {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-size: 13px;
}

.account-menu-links { display: flex; gap: 16px; }

.account-menu-links a {
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  text-decoration: none;
}

.account-menu-links a:hover {
  color: var(--cyan);
  text-decoration: underline;
}

/* Pre-auth landing: shown to signed-out users instead of the console. */
.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-gate-card {
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  padding: 44px;
  border: 1px solid var(--rule);
  background: rgba(16, 16, 20, .9);
  backdrop-filter: blur(14px);
}

.auth-gate-card .brand-logo { width: 46px; height: 46px; }
.auth-gate-card h1 { margin: 6px 0 0; font-size: 46px; line-height: 1.02; }
.auth-gate-card p { margin: 0; color: var(--ink-3); max-width: 42ch; }
.gate-signin { margin-top: 14px; min-height: 44px; }

/* Value bullets + legal/docs footer on the pre-auth gate. */
.gate-values {
  width: 100%;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
}

.gate-values li {
  position: relative;
  padding-left: 22px;
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.4;
}

.gate-values li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: .5em;
  width: 7px;
  height: 7px;
  background: var(--cyan);
  box-shadow: 0 0 10px rgba(0, 238, 255, .5);
}

.auth-gate-card .gate-consent {
  margin: 0;
  max-width: none;
  color: var(--ink-4);
  font-size: 12.5px;
  line-height: 1.5;
}

.auth-gate-card .gate-docs {
  margin: 0;
  font-family: var(--mono);
  font-size: 12.5px;
}

.gate-consent a, .gate-docs a {
  color: var(--cyan);
  text-decoration: none;
}

.gate-consent a:hover, .gate-docs a:hover {
  text-decoration: underline;
}

.gate-message {
  width: 100%;
  padding: 11px 13px;
  color: #ffd7d7;
  border: 1px solid rgba(239, 67, 67, .5);
  border-left: 3px solid var(--danger);
  border-radius: 0;
  background: rgba(239, 67, 67, .1);
  font-size: 14px;
}

.btn {
  min-height: 40px;
  padding: 0 15px;
  color: var(--ink);
  background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 0;
  transition: transform .18s ease, border-color .18s ease, background .18s ease, box-shadow .18s ease;
}

.btn:hover:not(:disabled) {
  transform: translateY(-1px);
  border-color: rgba(177, 115, 231, .5);
  background: rgba(177, 115, 231, .07);
  box-shadow: none;
}

.btn.primary {
  color: var(--ink);
  font-weight: 700;
  border-color: rgba(177, 115, 231, .8);
  background: rgba(177, 115, 231, .1);
  box-shadow: none;
}

.btn.primary:hover:not(:disabled) {
  color: var(--ink);
  border-color: rgba(177, 115, 231, .95);
  background: rgba(177, 115, 231, .18);
}

.btn.small {
  min-height: 34px;
  padding: 0 11px;
  font-size: 13px;
  border-radius: 0;
}

.btn.block { width: 100%; }

.btn.danger-action {
  color: #ffd6d6;
  border-color: rgba(239, 67, 67, .42);
  background: rgba(239, 67, 67, .08);
}

.btn.danger-action:hover:not(:disabled) {
  border-color: rgba(239, 67, 67, .72);
  background: rgba(239, 67, 67, .14);
  box-shadow: none;
}

.banner {
  margin-bottom: 18px;
  padding: 13px 15px;
  color: var(--ink);
  border: 1px solid rgba(249, 200, 36, .5);
  border-left: 3px solid var(--warn);
  border-radius: 0;
  background: rgba(249, 200, 36, .1);
}

.banner.danger {
  border-color: rgba(239, 67, 67, .52);
  background: rgba(239, 67, 67, .1);
}

.banner.ok {
  border-color: rgba(0, 238, 255, .42);
  background: rgba(0, 238, 255, .08);
}

.page {
  max-width: none;
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 28px;
  margin-bottom: 28px;
}

.page-head > .btn {
  flex: 0 0 auto;
  margin-top: 12px;
}

/* Overview hero: small "Overview" title on the left, the promoted balance +
   status badge on the right (the balance leads the page). */
.overview-hero { align-items: center; }

.overview-hero-lead h1 {
  margin-top: 6px;
  font-size: clamp(28px, 3.4vw, 38px);
}

.overview-hero-lead p {
  margin-top: 10px;
  font-size: 15px;
}

.balance-hero {
  min-width: 320px;
  gap: 8px;
}

.balance-hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.balance-hero-top span {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .15em;
  text-transform: uppercase;
}

.balance-hero .balance-figure {
  font-family: var(--display);
  font-size: clamp(40px, 4.4vw, 50px);
  line-height: 1.02;
  font-weight: 650;
  text-transform: none;
  color: var(--ink);
}

.balance-hero .balance-figure.low { color: var(--yellow); }
.balance-hero .balance-figure.empty { color: var(--danger); }

.balance-hero #creditMeta { color: var(--ink-3); }
.balance-hero .balance-hero-state { color: var(--ink-4); }

.balance-hero .balance-hero-add {
  justify-self: start;
  margin-top: 8px;
}

/* Status badge (shared vocabulary), colored by state kind. */
.balance-hero .state-badge {
  justify-self: end;
  min-height: 26px;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cyan);
  border: 1px solid rgba(0, 238, 255, .4);
  background: rgba(0, 238, 255, .08);
}

.balance-hero .state-badge.warn {
  color: var(--yellow);
  border-color: rgba(249, 200, 36, .45);
  background: rgba(249, 200, 36, .1);
}

.balance-hero .state-badge.danger {
  color: #ffd7d7;
  border-color: rgba(239, 67, 67, .45);
  background: rgba(239, 67, 67, .1);
}

h1, h2, h3, p { margin: 0; }

h1 {
  margin-top: 10px;
  font-family: var(--display);
  font-size: clamp(44px, 5vw, 68px);
  line-height: 1;
  letter-spacing: -.02em;
  font-weight: 650;
}

h1 span {
  color: var(--ink);
  background: none;
  background-clip: border-box;
  -webkit-background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  filter: none;
}

.page-head p {
  max-width: 660px;
  margin-top: 16px;
  color: var(--ink-3);
  font-size: 17px;
  line-height: 1.55;
}

h2 {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -.02em;
}

.live-card, .metric-card, .panel, .meter-card {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: 0;
  background: var(--surface);
  box-shadow: none;
}

.live-card::before, .metric-card::before, .panel::before, .meter-card::before {
  content: none;
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: none;
}

.live-card > *, .metric-card > *, .panel > *, .meter-card > * {
  position: relative;
  z-index: 1;
}

.live-card {
  min-width: 270px;
  padding: 24px;
  display: grid;
  align-content: center;
  gap: 9px;
}

.live-card > span, .metric-card > span, .panel-code {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .15em;
  text-transform: uppercase;
}

.panel-code { color: var(--cyan); }

.live-card strong {
  color: var(--cyan);
  font-size: 30px;
  font-weight: 650;
  text-transform: capitalize;
  text-shadow: none;
}

.live-card strong.danger { color: var(--danger); text-shadow: none; }
.live-card strong.warn { color: var(--yellow); text-shadow: none; }
.live-card small, .metric-card small, .hint, .compact-key small, td small { color: var(--ink-4); }

.console-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 18px;
}

.metric-card {
  min-height: 136px;
  padding: 24px;
  display: grid;
  align-content: center;
  gap: 9px;
}

.metric-card strong {
  font-family: var(--display);
  font-size: 38px;
  line-height: 1;
  font-weight: 650;
  color: var(--cyan);
}

.console-grid .metric-card:nth-child(1) {
  border-color: rgba(0, 238, 255, .3);
}

.console-grid .metric-card:nth-child(2) {
  border-color: rgba(177, 115, 231, .3);
}

.panel {
  padding: 26px;
  margin-bottom: 18px;
}

.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding-bottom: 16px;
  margin-bottom: 18px;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
}

.topup-form {
  display: grid;
  grid-template-columns: minmax(140px, .7fr) minmax(260px, 1fr);
  gap: 12px;
  align-items: end;
}

.topup-form .btn.primary {
  grid-column: 1 / -1;
  justify-self: end;
  min-width: 156px;
  white-space: nowrap;
}

.quick-amounts {
  display: grid;
  grid-template-columns: repeat(4, minmax(72px, 1fr));
  gap: 8px;
}

.quick-amounts button {
  min-height: 44px;
  color: var(--cyan);
  background: rgba(0, 238, 255, .035);
  border: 1px solid rgba(0, 238, 255, .26);
  border-radius: 0;
}

.quick-amounts button:hover {
  color: var(--yellow);
  border-color: rgba(249, 200, 36, .42);
  background: rgba(249, 200, 36, .055);
  box-shadow: none;
}

/* Selected quick amount stays clearly lit (no yellow hover-flip stealing it). */
.quick-amounts button[aria-pressed="true"],
.quick-amounts button[aria-pressed="true"]:hover {
  color: var(--cyan);
  border-color: var(--cyan);
  background: rgba(0, 238, 255, .16);
  box-shadow: inset 0 0 0 1px rgba(0, 238, 255, .45);
}

/* "$" adornment inside the amount field. */
.amount-field {
  position: relative;
  display: block;
}

.amount-adornment {
  position: absolute;
  top: 50%;
  left: 12px;
  transform: translateY(-50%);
  color: var(--ink-faint);
  font-family: var(--mono);
  pointer-events: none;
}

.amount-field input {
  padding-left: 24px;
}

.field-error {
  grid-column: 1 / -1;
  color: #ffb4b4;
  font-family: var(--mono);
  font-size: 12.5px;
}

input[aria-invalid="true"] {
  border-color: rgba(239, 67, 67, .7);
}

/* Top-up modal: the form stacks in one column here (the old 2-col grid was for
   the wide panel), and the submit spans full width. */
.topup-modal-body {
  padding: 4px 28px 26px;
  display: grid;
  gap: 4px;
}

#topUpModal .topup-form {
  grid-template-columns: 1fr;
  gap: 14px;
}

#topUpModal .topup-form .btn.primary {
  justify-self: stretch;
  min-width: 0;
}

.hint {
  margin-top: 13px;
  font-size: 13px;
}

.redirect-note { color: var(--ink-2); }

/* First-run guided next steps (shown only when the account has never funded). */
.first-run {
  margin-bottom: 18px;
  padding: 22px 26px;
  border: 1px solid rgba(0, 238, 255, .34);
  border-radius: 0;
  background: rgba(0, 238, 255, .04);
}

.first-run-head { margin-bottom: 16px; }
.first-run-head h2 { margin-top: 4px; }

.first-run-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.first-run-steps li {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 14px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 0;
  background: rgba(255, 255, 255, .02);
}

.step-num {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-weight: 650;
  color: var(--cyan);
  border: 1px solid rgba(0, 238, 255, .4);
}

.first-run-steps strong { display: block; }
.first-run-steps small { color: var(--ink-3); }
.first-run-steps .btn { white-space: nowrap; }

.state-legend {
  display: grid;
  gap: 16px;
}

/* Current state, led prominently. */
.state-current {
  display: grid;
  grid-template-columns: 12px 1fr;
  gap: 5px 11px;
  align-items: center;
  padding: 13px 14px;
  background: rgba(177, 115, 231, .08);
  border-left: 2px solid var(--purple);
}

.state-current strong {
  color: var(--ink);
  font-size: 15px;
}

.state-current small {
  grid-column: 2;
  color: var(--ink-3);
}

/* The other states, tucked behind a disclosure. */
.state-more {
  border-top: 1px solid rgba(255, 255, 255, .08);
  padding-top: 14px;
}

.state-more > summary {
  cursor: pointer;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .04em;
  list-style: none;
}

.state-more > summary::-webkit-details-marker { display: none; }

.state-more > summary::before {
  content: "+ ";
  color: var(--purple);
}

.state-more[open] > summary::before { content: "\2013 "; }

.state-more-list {
  display: grid;
  gap: 14px;
  margin-top: 14px;
}

.state-more-list > div {
  display: grid;
  grid-template-columns: 12px 1fr;
  gap: 5px 11px;
  align-items: center;
}

.state-more-list strong { color: var(--ink-2); }

.state-more-list small {
  grid-column: 2;
  color: var(--ink-4);
}

.compact-key-list {
  display: grid;
  gap: 9px;
}

.compact-key {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 12px;
  padding: 13px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 0;
  background: rgba(255, 255, 255, .035);
}

.compact-key-id { min-width: 0; }

.compact-key-id strong,
.compact-key-id small {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.compact-key-spend {
  display: grid;
  justify-items: end;
  gap: 2px;
  text-align: right;
  white-space: nowrap;
}

.compact-key-spend strong { color: var(--ink); }
.compact-key-spend small { color: var(--ink-4); font-size: 11px; }

/* Compact rows double as shortcuts into the edit modal (mirrors .key-row-clickable). */
.compact-key-clickable {
  cursor: pointer;
  /* Touch: no lingering translucent slab over the whole row — the :active rule
     below is the tap feedback, and it ends with the touch. */
  -webkit-tap-highlight-color: transparent;
}

/* Hover paint is for pointer devices only. On touch, :hover latches after a tap
   and leaves the row lit like a stuck selection. */
@media (hover: hover) {
  .compact-key-clickable:hover {
    border-color: rgba(177, 115, 231, .4);
    background: rgba(177, 115, 231, .06);
  }
}

/* Brief press feedback, on every input type. */
.compact-key-clickable:active {
  border-color: rgba(177, 115, 231, .4);
  background: rgba(177, 115, 231, .08);
}
/* Match the app's custom button focus ring rather than the low-contrast UA default. */
.compact-key-clickable:focus-visible {
  outline: 1px solid var(--purple);
  outline-offset: -1px;
}

/* Create-key page head: the button + the zero-balance shortcut sit top-right. */
.page-head-actions {
  flex: 0 0 auto;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.key-gate-hint {
  min-height: 0;
  padding: 0;
  color: var(--yellow);
  background: transparent;
  border: 0;
  font-family: var(--mono);
  font-size: 12px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.key-gate-hint:hover { color: var(--yellow); }

/* ===== Modal (create/edit key + one-time reveal; revoke confirm) ===== */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 56px 20px;
  overflow-y: auto;
  background: rgba(2, 0, 8, .74);
  backdrop-filter: blur(6px);
}

body.modal-open { overflow: hidden; }

.modal {
  width: 100%;
  max-width: 620px;
  margin: auto;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  box-shadow: 0 30px 80px rgba(0, 0, 0, .6), var(--glow-purple);
}

.modal-sm { max-width: 460px; }

.modal-view { padding: 26px 28px 24px; }
.modal-sm .confirm-body { padding: 0 28px; }
.modal-sm .modal-head, .modal-sm .modal-actions { padding: 26px 28px 0; }
.modal-sm .modal-actions { padding-bottom: 26px; }

.modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
}

.modal-head h2 { margin-top: 4px; }

.modal-close {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: var(--ink-3);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 0;
  font-size: 15px;
  line-height: 1;
}

.modal-close:hover {
  color: var(--ink);
  border-color: rgba(177, 115, 231, .5);
  background: rgba(177, 115, 231, .08);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 24px;
}

.modal-actions .btn { min-width: 116px; }

.modal-error {
  margin-top: 16px;
  padding: 11px 13px;
  color: #ffd7d7;
  border: 1px solid rgba(239, 67, 67, .5);
  border-left: 3px solid var(--danger);
  background: rgba(239, 67, 67, .1);
  font-size: 13px;
}

.confirm-body {
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.5;
}

/* Billing (purchase) history modal. */
.billing-history-body { padding: 4px 28px 26px; }

.billing-history-empty {
  min-height: 76px;
  display: grid;
  place-items: center;
  color: var(--ink-4);
  border: 1px dashed rgba(255, 255, 255, .16);
  background: rgba(0, 0, 0, .16);
}

.billing-history-list { display: grid; gap: 8px; }

.billing-history-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, .1);
  background: rgba(255, 255, 255, .02);
}

.billing-history-main { display: grid; gap: 3px; }
.billing-history-main strong { color: var(--ink); font-size: 15px; }
.billing-history-main small { color: var(--ink-4); font-family: var(--mono); font-size: 12px; }

.billing-history-date {
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 12px;
  white-space: nowrap;
}

/* Stacked form inside the modal (replaces the old 5-col inline grid). */
.key-form {
  display: grid;
  gap: 16px;
}

.field { display: grid; gap: 7px; }

.field-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.field-label {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .15em;
  text-transform: uppercase;
}

.models-field {
  margin: 0;
  padding: 0;
  border: 0;
  display: grid;
  gap: 8px;
}

.models-field legend { padding: 0; }

.field-hint {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 12px;
  text-transform: none;
  letter-spacing: normal;
}

/* Inline field error, shown directly under the field it belongs to. */
.key-form .field-error {
  color: #ffb4b4;
  font-family: var(--mono);
  font-size: 12.5px;
  text-transform: none;
  letter-spacing: normal;
}

/* Modal inputs read as legible mono, not the tiny uppercase label inheritance. */
.modal input,
.modal select {
  text-transform: none;
  letter-spacing: normal;
  font-size: 13px;
}

.radio-row {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--ink-2);
  font-family: var(--body);
  font-size: 14px;
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
}

.radio-row input {
  width: 16px;
  height: 16px;
  min-height: 0;
  margin: 0;
  padding: 0;
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  appearance: auto;
  -webkit-appearance: radio;
  accent-color: var(--purple);
}

/* Edit-modal per-key spend + recent activity. */
.key-usage-detail {
  display: grid;
  gap: 14px;
  margin-bottom: 20px;
  padding: 16px;
  border: 1px solid rgba(255, 255, 255, .1);
  background: rgba(255, 255, 255, .02);
}

.key-usage-summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.key-usage-stat { display: grid; gap: 5px; }

.key-usage-stat strong {
  font-family: var(--display);
  font-size: 26px;
  font-weight: 650;
  color: var(--ink);
}

.key-usage-recent { display: grid; gap: 8px; }

.key-usage-events {
  display: grid;
  gap: 6px;
  max-height: 156px;
  overflow: auto;
}

.key-usage-event {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border: 1px solid rgba(255, 255, 255, .08);
  background: rgba(0, 0, 0, .25);
  font-family: var(--mono);
  font-size: 12px;
}

.key-usage-when { color: var(--ink-4); white-space: nowrap; }

.key-usage-model {
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.key-usage-cost { color: var(--ink); white-space: nowrap; }
.key-usage-tokens { color: var(--ink-4); margin-left: 6px; }

.key-usage-status {
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-4);
  white-space: nowrap;
}

.key-usage-status.ok { color: var(--cyan); }
.key-usage-status.danger { color: #ffb4b4; }

.key-usage-muted {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 12px;
}

/* One-time reveal view. */
.reveal-body { display: grid; gap: 16px; }

.reveal-warn {
  margin: 0;
  padding: 11px 13px;
  color: var(--yellow);
  border: 1px solid rgba(249, 200, 36, .42);
  border-left: 3px solid var(--warn);
  background: rgba(249, 200, 36, .08);
  font-size: 13px;
  line-height: 1.45;
}

.reveal-field { display: grid; gap: 7px; }

.copy-row {
  display: flex;
  gap: 10px;
  align-items: stretch;
  min-width: 0;
}

.copy-row .btn { flex: 0 0 auto; }
.copy-row-block { flex-direction: column; }
.copy-row-block .btn { align-self: flex-end; }

.copy-row code, .curl-example {
  display: block;
  width: 100%;
  min-width: 0;
  overflow: auto;
  color: var(--cyan);
  background: rgba(0, 0, 0, .45);
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 0;
  padding: 12px;
  font-family: var(--mono);
  font-size: 13px;
  word-break: break-all;
}

.curl-example {
  margin: 0;
  color: var(--ink-2);
  white-space: pre-wrap;
  word-break: normal;
}

.scope-grid {
  margin: 0;
  border: 1px solid rgba(255, 255, 255, .1);
}

.scope-row {
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: 12px;
  padding: 9px 12px;
}

.scope-row + .scope-row { border-top: 1px solid rgba(255, 255, 255, .08); }

.scope-row dt {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.scope-row dd {
  margin: 0;
  color: var(--ink);
  font-size: 13px;
  word-break: break-word;
}

/* align-content is flex-start, NOT center: this is a scroll container, and
   centred wrapped rows overflow in BOTH directions — the block-start overflow
   is not scrollable, so once the chips needed more than max-height the top rows
   were unreachable and the bottom row read as cut off. Starting the rows at the
   top keeps every row reachable, and the container's own padding keeps the last
   row clear of the edge. */
.model-picker {
  min-height: 44px;
  max-height: 88px;
  overflow: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  gap: 8px;
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 0;
  background: rgba(0, 0, 0, .42);
  padding: 7px 8px;
}

.model-empty {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 12px;
  text-transform: none;
  letter-spacing: normal;
}

/* A chip can never be wider than the picker: a long raw model id (the fallback
   label when the catalog has no display name) used to push past the container
   instead of wrapping. */
.model-chip {
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.model-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* The real checkbox is visually hidden, so surface keyboard focus on the chip. */
.model-chip input:focus-visible + span {
  outline: 2px solid var(--cyan);
  outline-offset: 1px;
  border-color: var(--cyan);
}

.model-chip span, .chip-row span {
  min-height: 29px;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  color: var(--cyan);
  background: rgba(0, 238, 255, .035);
  border: 1px solid rgba(0, 238, 255, .26);
  border-radius: 0;
  font-size: 13px;
}

.model-chip span {
  max-width: 100%;
  overflow-wrap: break-word;
}

.model-chip input:checked + span {
  color: var(--yellow);
  background: rgba(249, 200, 36, .06);
  border-color: rgba(249, 200, 36, .46);
  box-shadow: none;
}

.table-wrap { overflow: auto; }

.keys-table {
  width: 100%;
  min-width: 1040px;
  border-collapse: collapse;
  table-layout: fixed;
}

.key-col-name { width: 17%; }
.key-col-status { width: 13%; }
.key-col-models { width: 17%; }
.key-col-usage { width: 15%; }
.key-col-cap { width: 11%; }
.key-col-rate { width: 9%; }
.key-col-actions { width: 170px; }

th, td {
  padding: 13px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, .09);
  text-align: left;
  vertical-align: middle;
}

th {
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
}

td { color: var(--ink-2); }
td:nth-child(5) { white-space: nowrap; }
td strong {
  display: block;
  color: var(--ink);
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-width: 220px;
}

.usage-cell {
  display: grid;
  gap: 5px;
  min-width: 110px;
}

.mini-bar, .bar {
  height: 8px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .11);
  border-radius: 0;
  background: rgba(255, 255, 255, .06);
}

.mini-bar i, .bar i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--cyan);
}

.bar {
  height: 10px;
  margin: 16px 0 10px;
}

.bar.warn i { background: var(--yellow); }
.bar.danger i { background: var(--danger); }

/* Flex lives on this inner wrapper (not the <td>), so the actions column keeps
   its declared width and the buttons sit centered on one baseline. */
.row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  white-space: nowrap;
}

.row-actions .btn.small { text-align: center; }
.row-actions .btn.icon-btn {
  min-width: 34px;
  padding: 0 8px;
  font-size: 16px;
  line-height: 1;
}

/* Per-row "⋯" menu (Copy ID / Revoke). Edit is a button of its own in the
   row, so it is deliberately not repeated here. */
.row-menu { position: relative; }

/* Fixed, not absolute: the panel's offset parent sits inside `.table-wrap`,
   which scrolls (overflow: auto) and therefore clips anything hanging past its
   edges. On the last row — and on a one-row table, where there is no room above
   either — that left the options unreachable without scrolling. Taking the panel
   out of the flow entirely is the only placement that is always fully visible;
   `placeRowMenu` supplies the coordinates and the menu closes on scroll so they
   can never go stale. */
.row-menu-panel {
  position: fixed;
  z-index: 15;
  min-width: 140px;
  display: grid;
  padding: 4px;
  border: 1px solid var(--rule-strong);
  background: rgba(16, 16, 20, .98);
  box-shadow: 0 14px 32px rgba(0, 0, 0, .5);
}

/* Flipped placement. placeRowMenu() adds this at open time when the panel
   would be cut off by .table-wrap's overflow or by the viewport bottom — the
   rows at the end of the table would otherwise need scrolling to reach. */
/* Flipping only changes the shadow direction now; the coordinates come from
   placeRowMenu, which has already decided which side the panel sits on. */
.row-menu-panel.row-menu-up {
  box-shadow: 0 -14px 32px rgba(0, 0, 0, .5);
}

.row-menu-panel button {
  min-height: 34px;
  padding: 0 10px;
  text-align: left;
  color: var(--ink-2);
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--mono);
  font-size: 12px;
}

.row-menu-panel button:hover,
.row-menu-panel button:focus-visible {
  color: var(--ink);
  background: rgba(177, 115, 231, .12);
}

.row-menu-panel .row-menu-danger { color: #ffbcbc; }
.row-menu-panel .row-menu-danger:hover,
.row-menu-panel .row-menu-danger:focus-visible {
  color: #ffd7d7;
  background: rgba(239, 67, 67, .14);
}

.key-row-clickable {
  cursor: pointer;
  /* Touch: suppress the platform's own full-row flash; :active below is the
     feedback and it releases with the finger. */
  -webkit-tap-highlight-color: transparent;
}

/* Row hover is pointer-only. On a touch screen :hover sticks after a tap, so
   the whole row stayed lit and read as a stuck selection. */
@media (hover: hover) {
  .key-row-clickable:hover td { background: rgba(177, 115, 231, .05); }
  .key-row-clickable:hover .row-menu-panel button { background: transparent; }
  .key-row-clickable:hover .row-menu-panel button:hover { background: rgba(177, 115, 231, .12); }
}

/* Brief press feedback, on every input type. */
.key-row-clickable:active td { background: rgba(177, 115, 231, .07); }

/* No-cap usage: "$ used · N req", no misleading %/bar. */
.usage-cell.no-cap { gap: 2px; }
.usage-cell.no-cap strong { color: var(--ink); }

.pill {
  min-height: 29px;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  color: var(--ink-2);
  background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 0;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
}

.pill.ok {
  color: var(--cyan);
  border-color: rgba(0, 238, 255, .38);
  background: rgba(0, 238, 255, .08);
}

.pill.warn {
  color: var(--yellow);
  border-color: rgba(249, 200, 36, .42);
  background: rgba(249, 200, 36, .1);
}

.pill.danger {
  color: #ffd7d7;
  border-color: rgba(239, 67, 67, .42);
  background: rgba(239, 67, 67, .09);
}

.meters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  margin-bottom: 18px;
}

/* Four cards (prepaid balance, last 30 days, lifetime, burn rate) in a 2x2 grid
   at desktop; stacks to one column under 980px with the rest of the meters. */
.usage-meters {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.meter-card {
  min-height: 196px;
  padding: 24px;
}

.meter-value {
  margin-top: 20px;
  font-family: var(--display);
  font-size: 44px;
  font-weight: 650;
}

.meter-value span {
  color: var(--ink);
}

/* The prepaid "% used" figure tracks balance health: neutral until low, then
   yellow (>=80% used), red when empty — same model as the Overview balance. */
.meter-value span.low { color: var(--yellow); }
.meter-value span.empty { color: var(--danger); }

.meter-meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: var(--ink-4);
  font-size: 13px;
}

.usage-stat-line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 30px;
  padding-top: 12px;
  color: var(--ink-4);
  border-top: 1px solid rgba(255, 255, 255, .1);
  font-family: var(--mono);
  font-size: 12px;
}

.usage-stat-line span:first-child {
  color: var(--cyan);
}

.keys-list {
  display: grid;
  gap: 9px;
}

.key-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 12px;
  padding: 13px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 0;
  background: rgba(255, 255, 255, .03);
}

.empty-row {
  min-height: 76px;
  display: grid;
  place-items: center;
  color: var(--ink-4);
  border: 1px dashed rgba(255, 255, 255, .16);
  border-radius: 0;
  background: rgba(0, 0, 0, .16);
}

.empty-cta { gap: 12px; padding: 18px; }
.empty-cta span { color: var(--ink-3); }

/* ===== Usage analytics (range control, metrics, chart, breakdowns) ===== */

/* Section header for everything driven by the analytics snapshot: title left,
   the range segmented control right. */
.analytics-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin: 34px 0 18px;
}

.analytics-head h2 { margin: 4px 0 0; }

/* Segmented range control — mono, sharp, one shared 1px frame with hairline
   dividers between the segments. */
.segmented {
  display: inline-flex;
  border: 1px solid var(--rule-strong);
  border-radius: 0;
  background: rgba(0, 0, 0, .28);
}

.segmented-btn {
  min-height: 38px;
  padding: 0 16px;
  color: var(--ink-3);
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .06em;
  white-space: nowrap;
  transition: color .16s ease, background .16s ease;
}

.segmented-btn + .segmented-btn {
  border-left: 1px solid var(--rule);
}

.segmented-btn:hover { color: var(--ink); }

.segmented-btn[aria-pressed="true"],
.segmented-btn[aria-pressed="true"]:hover {
  color: var(--cyan);
  background: rgba(0, 238, 255, .1);
}

/* Loading / error line for the analytics fetch. */
.analytics-status {
  margin-bottom: 16px;
  padding: 11px 14px;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 0;
  background: rgba(255, 255, 255, .025);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .03em;
}

.analytics-status.danger {
  color: #ffd7d7;
  border-color: rgba(239, 67, 67, .38);
  background: rgba(239, 67, 67, .08);
}

/* One loading treatment for the whole analytics snapshot. Instead of four
   panels each swapping in their own "Loading …" row (and seven figures blanking
   to "…"), the block dims in place and carries aria-busy: the painted numbers,
   chart and tables keep their exact geometry, so a refresh or a 7/30/90 change
   never reflows the page. #analyticsStatus above the block is the single
   loading/error indication. */
.analytics-block {
  transition: opacity .18s ease;
}

/* The dim has to stay READABLE, not just visible: at .45 every token in the
   block composited below AA against #0B0B0F (--ink-4, documented above as
   >=4.5:1 everywhere, fell to ~2.4:1) and the purple focus ring on the still
   focusable key rows inside dropped under 3:1. .75 keeps --ink-4 at ~4.7:1 and
   the ring above 3:1 while still reading as "this snapshot is stale"; the
   #analyticsStatus line carries the actual loading message. */
.analytics-block[aria-busy="true"] {
  opacity: .75;
}

/* First load only: the four panel bodies have no markup defaults, so while
   they are still empty they hold a reserved height — otherwise the block would
   jump when the first snapshot lands. Once a panel has content the rule stops
   matching, and later loads hold the real content anyway. */
.analytics-block[aria-busy="true"] .analytics-body:empty { min-height: 108px; }
.analytics-block[aria-busy="true"] .chart-wrap:empty { min-height: 210px; }

@media (prefers-reduced-motion: reduce) {
  .analytics-block { transition: none; }
}

/* Seven metric cards, reusing .metric-card. The cyan/purple accents on
   .console-grid come from nth-child rules that deliberately don't apply here.
   Column counts are explicit rather than auto-fit: seven is prime, so auto-fit
   strands a lone card on a second row at most widths. */
.analytics-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.analytics-grid .metric-card {
  min-height: 116px;
  padding: 20px;
  gap: 7px;
}

/* Numbers must never gain an arbitrary break point: `overflow-wrap: anywhere`
   split a ten-digit token count mid-digit ("1,243,456,7" / "89"), which reads
   as two separate figures at a glance. Keep the value atomic and let the type
   size flex with the column instead. */
.analytics-grid .metric-card strong {
  font-size: clamp(17px, 1.45vw, 25px);
  overflow-wrap: normal;
  word-break: keep-all;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 1280px) {
  .analytics-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* --- Daily spend chart --- */
/* Everything inside the SVG is in viewBox units, so the whole drawing — tick
   type included — shrinks with the panel. Floor the drawing width and scroll
   past it the way .table-wrap already does for the by-model table, instead of
   letting the axis labels scale down to 5-6px on a phone. */
.chart-wrap { width: 100%; overflow-x: auto; }

.usage-chart {
  display: block;
  width: 100%;
  min-width: 560px;
  height: auto;
  overflow: visible;
}

.chart-bar {
  fill: var(--cyan);
  fill-opacity: .82;
}

/* Full-slot transparent hit area so zero days and hairline bars still show the
   native <title> tooltip. */
.chart-hit { fill: transparent; }

.usage-chart g:hover .chart-bar { fill-opacity: 1; }

/* Both are graphical objects needed to read the chart, so WCAG 1.4.11's 3:1
   applies: the bars are measured against the baseline, and the gridlines are
   what the $ labels anchor to. At .22 / .08 they were 1.97:1 and 1.21:1 —
   effectively invisible on the near-black panel. */
.chart-axis {
  stroke: rgba(255, 255, 255, .34);
  stroke-width: 1;
}

.chart-grid {
  stroke: rgba(255, 255, 255, .14);
  stroke-width: 1;
}

.chart-tick {
  fill: var(--ink-4);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .04em;
}

.chart-empty {
  fill: var(--ink-4);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .05em;
}

/* --- By-model breakdown --- */
.usage-table {
  min-width: 560px;
  display: grid;
  gap: 1px;
}

.usage-table-head,
.usage-table-row {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) 96px 96px 84px 108px;
  align-items: center;
  gap: 12px;
  padding: 12px 4px;
}

.usage-table-head {
  padding-bottom: 10px;
  color: var(--ink-4);
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.usage-table-row + .usage-table-row,
/* The head already draws a bottom rule; a top rule on the first row would sit
   1px below it (the grid has a 1px gap) and read as a double line. */
.usage-table-head + .usage-table-row {
  border-top: 0;
}

.usage-model-name {
  display: grid;
  gap: 8px;
  min-width: 0;
}

.usage-model-name strong {
  overflow: hidden;
  color: var(--ink);
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Share-of-spend proportion bar; same hairline meter as the per-key usage cell,
   capped so it stays a subtle cue rather than a full-width band. */
.usage-model-name .mini-bar {
  height: 4px;
  max-width: 260px;
}

.usage-num {
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 13px;
  text-align: right;
}

.usage-table-head .usage-num { font-size: 11px; }

.usage-num-warn { color: var(--yellow); }

/* Footnote under the breakdown table. .table-wrap scrolls horizontally, so the
   note sits outside it and stays put while the table pans.
   The note is a `.calm-note` too, and `.calm-note { margin: 0 }` lives later in
   this file at equal specificity — a bare `.usage-table-note` rule would lose
   the cascade and collapse the gap to 0. Qualify with both classes so the
   spacing survives wherever either block ends up. */
.calm-note.usage-table-note { margin-top: 14px; }

/* --- Reliability panel --- */
.error-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  margin-bottom: 18px;
}

.error-stat { display: grid; gap: 6px; }

.error-stat strong {
  color: var(--ink);
  font-family: var(--display);
  font-size: 26px;
  font-weight: 650;
}

.error-stat strong.warn { color: var(--yellow); }

.error-models {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.error-model {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 10px;
  color: var(--ink-2);
  border: 1px solid rgba(249, 200, 36, .3);
  border-radius: 0;
  background: rgba(249, 200, 36, .06);
  font-family: var(--mono);
  font-size: 12px;
}

.error-model em {
  color: var(--ink);
  font-style: normal;
}

/* Visible to screen readers only: labels a value that reads as a bare number. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Calm, non-alarming line — the healthy "no failures" case and the footnotes. */
.calm-note {
  margin: 0;
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: .03em;
}

/* No `--ink-faint` override here: this footnote is real explanatory copy and it
   only appears when there ARE failures, i.e. exactly when it needs reading. The
   base --ink-4 is 7.64:1 on the panel and already reads as suitably quiet. */

@keyframes glow-line-move {
  0% { background-position: 0% 0; }
  100% { background-position: 220% 0; }
}

@media (max-width: 980px) {
  .sidebar {
    position: sticky;
    min-height: auto;
    padding: 14px 16px 0;
    flex-wrap: wrap;
    gap: 12px 18px;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
  }

  .brand {
    min-height: 44px;
  }

  .sidebar nav {
    order: 3;
    width: calc(100% + 32px);
    min-height: 46px;
    margin: 0 -16px;
    padding: 0 8px;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    overflow: hidden;
  }

  .nav-item {
    min-height: 46px;
    justify-content: center;
    padding: 0 8px;
  }

  .main {
    margin-left: 0;
    padding: 22px 16px 40px;
  }

  .page-head {
    display: grid;
    grid-template-columns: 1fr;
  }

  .console-grid, .meters, .key-form {
    grid-template-columns: 1fr;
  }

  .balance-hero { min-width: 0; }

  .first-run-steps li {
    grid-template-columns: 34px minmax(0, 1fr);
  }

  .first-run-steps li .btn {
    grid-column: 1 / -1;
    justify-self: start;
  }

  .topup-form {
    grid-template-columns: 1fr;
  }

  .topup-form .btn.primary {
    justify-self: stretch;
  }

  /* Range control drops under the section title rather than squeezing it, and
     its segments share the full row instead of leaving a dead tail. */
  .analytics-head {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }

  .segmented {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .error-stats { gap: 22px; }
  .analytics-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .brand-name { font-size: 12px; letter-spacing: .24em; }
  .brand-tag { display: none; }
  .brand-logo { width: 32px; height: 32px; }
  .topbar { margin-bottom: 28px; }
  h1 { font-size: 42px; }
  .page-head p { font-size: 16px; }
  .quick-amounts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .panel { padding: 20px; }
  .account-menu-panel { width: min(260px, calc(100vw - 32px)); }
  .modal-backdrop { padding: 20px 12px; }
  .modal-view { padding: 20px 18px; }
  .field-grid-2 { grid-template-columns: 1fr; }
  .page-head-actions { align-items: stretch; }
  .modal-actions { flex-wrap: wrap; }
  /* Segments share the row evenly instead of overflowing the viewport. */
  .segmented { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .segmented-btn { padding: 0 8px; }
  .analytics-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Model picker on a phone. The 88px cap turned the picker into a two-row
     peephole nested inside the modal's own scroll — it now grows with the
     chips and only scrolls when the catalog is genuinely long, with enough
     bottom padding that the last row is never cropped. Chips get 40px touch
     targets (the desktop 29px is a mouse target) and wrap their label instead
     of running past the container. */
  .model-picker {
    max-height: min(46vh, 300px);
    gap: 10px;
    padding: 10px;
    scroll-padding-block-end: 10px;
  }

  .model-chip span {
    min-height: 40px;
    padding: 7px 13px;
    line-height: 1.35;
  }

  .radio-row { min-height: 40px; }
}

/* The same treatment keyed on the INPUT DEVICE rather than the viewport. A
   portrait tablet is 768px wide — past every width step above — but it is still
   a finger: without this it got the 88px peephole back (2 of 7 chip rows on a
   13-model catalog) and mouse-sized 29px chips / 17px radio rows. Kept as a
   second copy rather than a shared selector list so the phone rules above stand
   on their own for a narrow mouse window. */
@media (pointer: coarse) {
  .model-picker {
    max-height: min(46vh, 300px);
    gap: 10px;
    padding: 10px;
    scroll-padding-block-end: 10px;
  }

  .model-chip span {
    min-height: 40px;
    padding: 7px 13px;
    line-height: 1.35;
  }

  .radio-row { min-height: 40px; }
}

/* Chart type ramp. Tick size on screen is (font-size x drawn width / 720), and
   the drawn width now floors at 560px, so a single breakpoint could not hold
   it: one 620px step left 621px rendering at 7.4px while 620px got 12.1px.
   These steps track the shrinking panel so the effective size stays in an
   11-14px band all the way down, with no cliff. CHART.padL is sized for the
   widest labels this produces. */
@media (max-width: 900px) {
  .chart-tick { font-size: 12px; }
  .chart-empty { font-size: 14px; }
}

@media (max-width: 780px) {
  .chart-tick { font-size: 14px; }
  .chart-empty { font-size: 17px; }
}

@media (max-width: 660px) {
  .chart-tick { font-size: 16px; }
  .chart-empty { font-size: 20px; }
}
