/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: light dark;

  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, Helvetica,
    Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
    'Liberation Mono', monospace;

  --step-0: 0.9375rem;
  --step--1: 0.8125rem;
  --step--2: 0.6875rem;
  --step-1: 1.125rem;
  --step-2: 1.5rem;
  --step-3: 2rem;

  --rail-width: 15rem;
  --measure: 62rem;
  --radius: 0.5rem;
  --radius-sm: 0.3125rem;

  /* Ultramarine, not the acid green every API dashboard reaches for. It reads as
     instrumentation, which is what this product is. */
  --accent: #3b5bdb;
  --accent-text: #ffffff;
  --accent-weak: rgba(59, 91, 219, 0.1);

  /* Delivery and job states. Four hues is a lot of colour, and it is spent here rather
     than on decoration because these genuinely encode distinct information. */
  --ok: #0f8a7d;
  --warn: #b4690e;
  --bad: #c93b40;
  /* 'Not assessed' — the state this service insists is not the same as zero. */
  --unread: #6b7784;

  --paper: #f6f7f9;
  --panel: #ffffff;
  --panel-2: #f0f2f5;
  --line: #dfe3e8;
  --line-strong: #c6ccd4;
  --text: #14181d;
  --muted: #59636f;
  --faint: #8b95a1;
  --hatch: rgba(20, 24, 29, 0.09);
  --shadow: 0 1px 2px rgba(16, 20, 24, 0.05), 0 8px 24px -12px rgba(16, 20, 24, 0.18);
}

@media (prefers-color-scheme: dark) {
  :root {
    --accent: #7c93f5;
    --accent-text: #0b0e13;
    --accent-weak: rgba(124, 147, 245, 0.14);

    --ok: #3ec9b4;
    --warn: #e0a44a;
    --bad: #f0666b;
    --unread: #7d8896;

    --paper: #0d1116;
    --panel: #141a21;
    --panel-2: #1a212a;
    --line: #262f3a;
    --line-strong: #38434f;
    --text: #e6eaf0;
    --muted: #9aa5b2;
    --faint: #6d7986;
    --hatch: rgba(230, 234, 240, 0.08);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px -16px rgba(0, 0, 0, 0.7);
  }
}

/* The toggle writes data-theme on <html> and must win over the media query in both
   directions, so both values are spelled out rather than relying on one to fall through. */
:root[data-theme='light'] {
  --accent: #3b5bdb; --accent-text: #ffffff; --accent-weak: rgba(59, 91, 219, 0.1);
  --ok: #0f8a7d; --warn: #b4690e; --bad: #c93b40; --unread: #6b7784;
  --paper: #f6f7f9; --panel: #ffffff; --panel-2: #f0f2f5;
  --line: #dfe3e8; --line-strong: #c6ccd4;
  --text: #14181d; --muted: #59636f; --faint: #8b95a1;
  --hatch: rgba(20, 24, 29, 0.09);
  --shadow: 0 1px 2px rgba(16, 20, 24, 0.05), 0 8px 24px -12px rgba(16, 20, 24, 0.18);
}

:root[data-theme='dark'] {
  --accent: #7c93f5; --accent-text: #0b0e13; --accent-weak: rgba(124, 147, 245, 0.14);
  --ok: #3ec9b4; --warn: #e0a44a; --bad: #f0666b; --unread: #7d8896;
  --paper: #0d1116; --panel: #141a21; --panel-2: #1a212a;
  --line: #262f3a; --line-strong: #38434f;
  --text: #e6eaf0; --muted: #9aa5b2; --faint: #6d7986;
  --hatch: rgba(230, 234, 240, 0.08);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px -16px rgba(0, 0, 0, 0.7);
}

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

   Browser defaults this sheet does not want, dropped once here rather than overridden in
   twenty component rules. Deliberately short: normalize.css and its descendants spend most
   of their length on browsers this app does not support, and a reset too long to read is a
   reset nobody can reason about.

   One theme runs through it. Spacing in this UI comes from '.stack' and from 'gap', never
   from margins on elements, so margins are removed rather than replaced with a different
   number — which is why a component can be dropped anywhere without bringing whitespace
   along with it. The prefers-reduced-motion block at the end of the sheet is the other half
   of a reset: a default about motion rather than about layout. */

*, *::before, *::after { box-sizing: border-box; }

/* Stops iOS Safari inflating body text when a phone is turned to landscape. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* 'overflow-wrap' so an unbroken string — an API key, a webhook URL — wraps instead of
   widening its container and pushing a table off the side of the screen. '.nowrap' and
   '.truncate' still win where a value has to stay on one line, because 'white-space'
   outranks this. */
body { margin: 0; overflow-wrap: break-word; }

h1, h2, h3, h4, h5, h6, p, pre, ul, ol, dl, dd, figure, blockquote { margin: 0; }
form { margin-block-end: 0; }

/* Form controls opt out of font inheritance in every browser, which is how a button ends up
   set in 13px Arial on a page that is not. 'font' carries line-height with it. */
button, input, optgroup, select, textarea { font: inherit; color: inherit; }
button { padding: 0; border: 0; background: none; cursor: pointer; }

/* Replaced elements are inline by default, so they sit on the text baseline and leave a few
   pixels of gap underneath that reads as a broken layout. */
img, svg, video, canvas { display: block; max-width: 100%; }

table { border-collapse: collapse; border-spacing: 0; }

/* ---------------------------------------------------------------- base */

body {
  background: var(--paper);
  color: var(--text);
  font: var(--step-0) / 1.55 var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-weight: 620; letter-spacing: -0.018em; line-height: 1.2; }
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

/* One visible focus treatment for everything, so keyboard navigation is never guesswork. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Numbers are the product. Tabular figures everywhere means a column of counts lines up
   and a changing quota does not make the layout twitch. */
.num, .mono, code, pre, input, .table td, .table th {
  font-variant-numeric: tabular-nums;
}
.mono, code, pre { font-family: var(--font-mono); font-size: 0.9em; }

.stack { display: flex; flex-direction: column; }
.stack > * + * { margin-top: var(--gap, 1rem); }
.row { display: flex; align-items: center; gap: 0.75rem; }
.row--between { justify-content: space-between; }
.row--wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.right { margin-left: auto; }

/* Letterspaced micro-caps. The structural device of this UI: it labels a region without
   competing with the numbers inside it. */
.eyebrow {
  font-size: var(--step--2);
  font-weight: 660;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--faint);
}

.muted { color: var(--muted); }
.faint { color: var(--faint); }
.small { font-size: var(--step--1); }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.hr { height: 1px; margin: 1.5rem 0; background: var(--line); border: 0; }

/* ---------------------------------------------------------------- shell */

.shell { display: grid; grid-template-columns: var(--rail-width) minmax(0, 1fr); min-height: 100vh; }

.rail {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  padding: 1.25rem 1rem;
  background: var(--panel);
  border-right: 1px solid var(--line);
  overflow-y: auto;
}

.brand { display: flex; align-items: center; gap: 0.5rem; font-weight: 640; letter-spacing: -0.02em; }
.brand__mark {
  width: 1.5rem; height: 1.5rem; flex: none;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-text);
  display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 0.75rem; font-weight: 700;
}

.nav { display: flex; flex-direction: column; gap: 0.125rem; }
.nav a {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.4375rem 0.625rem;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--step--1);
  font-weight: 520;
}
.nav a:hover { background: var(--panel-2); color: var(--text); text-decoration: none; }
.nav a[aria-current='page'] { background: var(--accent-weak); color: var(--accent); font-weight: 600; }

/* Who you are signed in as, the theme toggle and sign out, pinned to the bottom of the rail
   and centred across it. The email keeps its full width so '.truncate' has a box to
   ellipsis against; only the text inside it is centred. */
.rail__account { margin-top: auto; text-align: center; }
.rail__account .row { justify-content: center; }

.main { min-width: 0; padding: 2.25rem 2rem 5rem; }
.main__inner { max-width: var(--measure); margin: 0 auto; }

/* One vertical rhythm for page content, set on the container rather than as an adjacency
   rule between cards.
   An adjacency rule gets this wrong in both directions: it misses a card followed by a
   grid of cards (so the two sit flush), and it *applies* to the second card inside a grid,
   pushing that column down out of alignment with the first. Spacing direct children of the
   container has neither problem, and these margins collapse with the explicit
   margin-bottom on .page-head and .flash rather than stacking on top of them. */
.main__inner > * + * { margin-top: 1.25rem; }

.page-head { margin-bottom: 2rem; }
.page-head h1 { margin-bottom: 0.375rem; }
.page-head p { color: var(--muted); max-width: 46rem; }

/* ------------------------------------------------- environment switcher */

.envs { display: flex; flex-direction: column; gap: 0.25rem; }

.env {
  display: block;
  padding: 0.5rem 0.625rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-size: var(--step--1);
}
.env:hover { border-color: var(--line-strong); color: var(--text); text-decoration: none; }
.env[aria-current='true'] { border-color: var(--accent); color: var(--text); background: var(--accent-weak); }
.env__name { display: block; font-weight: 580; }
.env__kind { font-size: var(--step--2); letter-spacing: 0.06em; text-transform: uppercase; }

/* The hatch. Sandbox is textured so you cannot mistake it for production at a glance —
   the one mistake this dashboard must not let you make quietly. */
.env--sandbox {
  background-image: repeating-linear-gradient(
    135deg, transparent 0 5px, var(--hatch) 5px 6px
  );
}
.env--sandbox[aria-current='true'] {
  background-image: repeating-linear-gradient(135deg, transparent 0 5px, var(--hatch) 5px 6px);
  background-color: var(--accent-weak);
}
.env--archived { opacity: 0.55; }

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.card__head {
  display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--line);
}
.card__head h3 { font-size: var(--step-0); font-weight: 620; }
.card__head p { font-size: var(--step--1); color: var(--muted); flex-basis: 100%; }
.card__body { padding: 1.25rem; }
.card__body--flush { padding: 0; }
.card__foot {
  padding: 0.875rem 1.25rem;
  border-top: 1px solid var(--line);
  background: var(--panel-2);
  border-radius: 0 0 var(--radius) var(--radius);
  font-size: var(--step--1);
  color: var(--muted);
}

.grid-2 { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }

/* ------------------------------------------------------------ the gauge */

/* The signature element: today's quota as a measured scale rather than a progress bar.
   Ticks make it a reading you can estimate against, which is the point of the product. */
.gauge { display: flex; flex-direction: column; gap: 0.625rem; }
.gauge__figure { display: flex; align-items: baseline; gap: 0.5rem; }
.gauge__value {
  font-family: var(--font-mono);
  font-size: var(--step-3);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
}
.gauge__limit { font-family: var(--font-mono); font-size: var(--step-0); color: var(--faint); }

.gauge__track {
  position: relative;
  height: 0.625rem;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.gauge__fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px 0 0 999px;
  transition: width 0.4s ease;
}
.gauge__fill--warn { background: var(--warn); }
.gauge__fill--over { background: var(--bad); }

/* Quartile ticks, drawn on the track rather than as elements so they cost no markup. */
.gauge__ticks {
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    to right, transparent 0 calc(25% - 1px), var(--line-strong) calc(25% - 1px), var(--line-strong) 25%
  );
  pointer-events: none;
}
.gauge__legend { display: flex; justify-content: space-between; font-size: var(--step--2); color: var(--faint); }

/* --------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: 0.3125rem;
  padding: 0.125rem 0.4375rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.badge::before { content: ''; width: 0.375rem; height: 0.375rem; border-radius: 999px; background: currentColor; }
.badge--ok { color: var(--ok); border-color: currentColor; }
.badge--warn { color: var(--warn); border-color: currentColor; }
.badge--bad { color: var(--bad); border-color: currentColor; }
.badge--accent { color: var(--accent); border-color: currentColor; }
.badge--plain::before { display: none; }

/* -------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.375rem;
  padding: 0.4375rem 0.875rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 560;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.btn:hover { background: var(--panel-2); text-decoration: none; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn--primary:hover { background: var(--accent); filter: brightness(1.08); }
.btn--danger { color: var(--bad); border-color: var(--bad); background: transparent; }
.btn--danger:hover { background: var(--bad); color: var(--panel); }
.btn--ghost { border-color: transparent; background: transparent; color: var(--muted); }
.btn--ghost:hover { background: var(--panel-2); color: var(--text); }
.btn--sm { padding: 0.25rem 0.5rem; font-size: var(--step--2); }
.btn--block { width: 100%; }

.btn-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* --------------------------------------------------------------- forms */

.field { display: flex; flex-direction: column; gap: 0.375rem; }
.field + .field { margin-top: 1rem; }
.field__label { font-size: var(--step--1); font-weight: 580; }
.field__hint { font-size: var(--step--1); color: var(--muted); }
.field__error { font-size: var(--step--1); color: var(--bad); }

.input, .select {
  width: 100%;
  padding: 0.5rem 0.625rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--text);
  font-size: var(--step-0);
}
.input:focus, .select:focus { border-color: var(--accent); outline-offset: 1px; }
.input::placeholder { color: var(--faint); }
.input--mono { font-family: var(--font-mono); font-size: var(--step--1); }

.checks { display: flex; flex-direction: column; gap: 0.5rem; }
.check { display: flex; align-items: flex-start; gap: 0.5rem; font-size: var(--step--1); }
.check input { margin: 0.1875rem 0 0; accent-color: var(--accent); }
.check code { color: var(--text); }

/* ---------------------------------------------------------------- table */

.table-wrap { overflow-x: auto; }
.table { width: 100%; font-size: var(--step--1); }
.table th {
  padding: 0.625rem 1.25rem;
  text-align: left;
  font-size: var(--step--2);
  font-weight: 660;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--faint);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table td { padding: 0.75rem 1.25rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--panel-2); }
.table__actions { text-align: right; }
.table td.num, .table th.num { text-align: right; }

/* --------------------------------------------------------- key display */

.keystring {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.4375rem 0.625rem;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--step--1);
}
.keystring__value { flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; }

/* Shown once, after a key is created. Deliberately loud: it is the only moment the
   plaintext exists in the page, and a user who navigates away has to make a new key. */
.reveal {
  padding: 1.25rem;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* --------------------------------------------------------------- flash */

.flash {
  display: flex; gap: 0.625rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--line-strong);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  background: var(--panel);
  font-size: var(--step--1);
  margin-bottom: 1.5rem;
}
.flash--ok { border-left-color: var(--ok); }
.flash--bad { border-left-color: var(--bad); }
.flash--warn { border-left-color: var(--warn); }

/* --------------------------------------------------------------- empty */

.empty { padding: 2.5rem 1.25rem; text-align: center; }
.empty h3 { font-size: var(--step-0); margin-bottom: 0.375rem; }
.empty p { color: var(--muted); font-size: var(--step--1); max-width: 30rem; margin: 0 auto 1rem; }

/* --------------------------------------------------------------- plans */

.plans { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.plan {
  display: flex; flex-direction: column; gap: 0.875rem;
  padding: 1.25rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.plan--current { border-color: var(--accent); }
.plan__price { display: flex; align-items: baseline; gap: 0.25rem; }
.plan__amount { font-family: var(--font-mono); font-size: var(--step-2); font-weight: 620; letter-spacing: -0.03em; }
.plan__features { padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.375rem; font-size: var(--step--1); color: var(--muted); }
.plan__features li { display: flex; gap: 0.5rem; }
.plan__features li::before { content: '—'; color: var(--faint); }
.plan__cta { margin-top: auto; }

/* ---------------------------------------------------------------- auth */

.auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem 1.25rem;
}
.auth__card { width: 100%; max-width: 25rem; }
.auth__card .brand { justify-content: center; margin-bottom: 1.5rem; }
.auth__lede { text-align: center; color: var(--muted); font-size: var(--step--1); margin-bottom: 1.5rem; }
.auth__alt { text-align: center; font-size: var(--step--1); color: var(--muted); margin-top: 1.25rem; }

/* --------------------------------------------------------------- misc */

.scores { display: grid; gap: 0.375rem 1rem; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
.score { display: flex; justify-content: space-between; gap: 0.5rem; font-size: var(--step--1); padding: 0.1875rem 0; }
.score__value { font-family: var(--font-mono); font-weight: 560; }
/* A null score is styled as absent, not as low. Rendering it as 0.0000 would be the one
   misreading this product cannot afford. */
.score__value--null { color: var(--unread); font-style: italic; }

.copy-ok { color: var(--ok); }

/* ---------------------------------------------------------- responsive */

@media (max-width: 52rem) {
  .shell { grid-template-columns: 1fr; }
  .rail {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .nav { flex-direction: row; flex-wrap: wrap; }
  .envs { flex-direction: row; flex-wrap: wrap; }
  .env { flex: 1 1 8rem; }
  /* 'margin-top: auto' has nothing to push against once the rail is an auto-height band, so
     the gap above the account block becomes explicit. It stays centred. */
  .rail__account { margin-top: 0.5rem; }
  .main { padding: 1.5rem 1.125rem 4rem; }
  h1 { font-size: var(--step-2); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}