/* ============================================================
   personal-design-system — canonical base + component layer

   Load AFTER tokens.css. References tokens only — no literal colors, no
   literal spacing. Mobile-first. Every rule here should be portable to any
   consuming app; anything app-specific belongs in that app's own stylesheet.
   ============================================================ */

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--ds-font-body);
  font-size: var(--ds-fs-body);
  line-height: var(--ds-lh-body);
  color: var(--ds-text);
  background: var(--ds-bg);
  -webkit-text-size-adjust: 100%;
}

a { color: var(--ds-link); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Any figure that changes in place gets tabular-nums, so digits don't jitter
   as values update. Applies to KPI values by default; add .numeric elsewhere. */
.numeric { font-variant-numeric: tabular-nums; }

/* Visible focus everywhere. Non-negotiable a11y baseline. */
:focus-visible { outline: 3px solid var(--ds-link); outline-offset: 2px; }

/* ---- App shell ---- */
.app-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--ds-surface);
  border-bottom: 1px solid var(--ds-border);
  box-shadow: var(--ds-shadow-sm);
}
.app-header__bar {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  max-width: var(--ds-maxw);
  margin: 0 auto;
  padding: var(--ds-space-3) var(--ds-space-4);
}

/* The wordmark IS the branding system: all-lowercase, one word, no space,
   bold, negative tracking, second half in copper. bodylog = body + log. */
.wordmark {
  font-size: var(--ds-fs-display);
  font-weight: var(--ds-fw-bold);
  letter-spacing: -0.02em;
  color: var(--ds-ink);
}
.wordmark__dot { color: var(--ds-copper); }

/* ---- Nav (scrollable pill row on mobile) ---- */
.nav {
  display: flex;
  gap: var(--ds-space-1);
  overflow-x: auto;
  max-width: var(--ds-maxw);
  margin: 0 auto;
  padding: 0 var(--ds-space-4) var(--ds-space-2);
  scrollbar-width: none;
}
.nav::-webkit-scrollbar { display: none; }
.nav a {
  flex: 0 0 auto;
  min-height: var(--ds-tap);
  display: inline-flex;
  align-items: center;
  padding: var(--ds-space-2) var(--ds-space-3);
  border-radius: var(--ds-radius-pill);
  color: var(--ds-muted);
  font-size: var(--ds-fs-sm);
  font-weight: var(--ds-fw-medium);
  white-space: nowrap;
}
.nav a:hover { background: var(--ds-surface-alt); text-decoration: none; }
.nav a.is-active { background: var(--ds-primary-soft); color: var(--ds-link); }

/* ---- Content ---- */
main { max-width: var(--ds-maxw); margin: 0 auto; padding: var(--ds-space-5) var(--ds-space-4) var(--ds-space-8); }
h1 { font-size: var(--ds-fs-display); color: var(--ds-ink); margin: 0 0 var(--ds-space-4); line-height: var(--ds-lh-tight); }
h2 { font-size: var(--ds-fs-h2); color: var(--ds-ink); margin: var(--ds-space-6) 0 var(--ds-space-3); }

/* Card: border AND shadow-sm together, never shadow alone. */
.card {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-lg);
  box-shadow: var(--ds-shadow-sm);
  padding: var(--ds-space-5);
}
.card h2:first-child { margin-top: 0; }

/* ---- KPI tile ----
   The signature component: uppercase xs muted label with 0.04em tracking
   over a 2.25rem bold tabular value. */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--ds-space-3); }
.kpi { background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-md); padding: var(--ds-space-4); }
.kpi__label { font-size: var(--ds-fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--ds-muted); }
.kpi__value { font-size: var(--ds-fs-kpi); font-weight: var(--ds-fw-bold); color: var(--ds-ink); font-variant-numeric: tabular-nums; }
.kpi__unit { font-size: 1rem; color: var(--ds-muted); }
.kpi__sub { font-size: var(--ds-fs-xs); color: var(--ds-muted); margin-top: var(--ds-space-1); }

/* ---- Buttons ---- */
.btn {
  min-height: var(--ds-tap);
  display: inline-flex; align-items: center; justify-content: center;
  padding: var(--ds-space-2) var(--ds-space-4);
  border-radius: var(--ds-radius-md);
  border: 1px solid var(--ds-primary);
  background: var(--ds-primary);
  color: #fff;
  font-weight: var(--ds-fw-semibold);
  cursor: pointer;
}
.btn:hover { background: var(--ds-primary-strong); border-color: var(--ds-primary-strong); text-decoration: none; }
.btn--ghost { background: transparent; color: var(--ds-link); }
.btn--quiet { background: transparent; border-color: var(--ds-border); color: var(--ds-text); }
.btn--quiet:hover { background: var(--ds-surface-alt); border-color: var(--ds-border); }

/* ---- Forms (real labels, inputs sit on surface — LIGHTER than the page bg) ---- */
label { display: block; font-size: var(--ds-fs-sm); font-weight: var(--ds-fw-medium); color: var(--ds-text); margin-bottom: var(--ds-space-1); }
input, select, textarea {
  width: 100%; min-height: var(--ds-tap);
  padding: var(--ds-space-2) var(--ds-space-3);
  font: inherit; color: var(--ds-text);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-md);
}
input::placeholder, textarea::placeholder { color: var(--ds-faint); }
input:disabled, select:disabled, textarea:disabled { color: var(--ds-faint); background: var(--ds-surface-alt); cursor: not-allowed; }

/* The dropdown popup is painted by the browser, not by us. `color-scheme` in
   tokens.css is what makes it dark — this is the backstop for when a <select>
   has a transparent background (e.g. it sits inside a styled wrapper), which
   otherwise leaves the popup inheriting nothing and falling back to UA white. */
option { background: var(--ds-surface); color: var(--ds-text); }

.form-grid { display: grid; grid-template-columns: 1fr; gap: var(--ds-space-3); }
@media (min-width: 560px) { .form-grid { grid-template-columns: 1fr 1fr; } }
.form-actions { display: flex; gap: var(--ds-space-3); margin-top: var(--ds-space-4); }
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--ds-space-4); margin-bottom: var(--ds-space-4); }
.filter-bar label { display: inline-flex; flex-direction: column; }
.filter-bar select { width: auto; min-width: 160px; }

/* ---- Range input ----
   The generic form rule above would otherwise give a range a border, a solid
   background and 10px of padding, which renders it as a broken-looking text
   box. Ranges must opt out explicitly and be styled from scratch. */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  padding: 0;
  border: 0;
  background: transparent;
  min-height: var(--ds-tap);
  cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 12px;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-surface-alt);
  border: 1px solid var(--ds-border);
}
input[type="range"]::-moz-range-track {
  height: 12px;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-surface-alt);
  border: 1px solid var(--ds-border);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px; height: 24px;
  margin-top: -7px;                       /* centers a 24px thumb on a 12px track */
  border-radius: var(--ds-radius-pill);
  background: var(--ds-primary);
  border: 2px solid var(--ds-surface);
  box-shadow: var(--ds-shadow-sm);
}
input[type="range"]::-moz-range-thumb {
  width: 24px; height: 24px;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-primary);
  border: 2px solid var(--ds-surface);
  box-shadow: var(--ds-shadow-sm);
}

/* ---- Checkbox / radio: opt out of the full-width form rule ---- */
input[type="checkbox"], input[type="radio"] {
  width: auto; min-height: 0;
  accent-color: var(--ds-primary);
}

/* ---- Table: bottom hairlines only, no vertical rules ---- */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--ds-fs-sm); }
th, td { text-align: left; padding: var(--ds-space-2) var(--ds-space-3); border-bottom: 1px solid var(--ds-border); }
th { color: var(--ds-muted); font-weight: var(--ds-fw-semibold); }
tbody tr:nth-child(even) { background: var(--ds-surface-alt); }

/* ---- Badges / chips: colored by border + text, never filled ---- */
.badge { display: inline-block; padding: 0.1rem 0.5rem; border-radius: var(--ds-radius-pill);
  font-size: var(--ds-fs-xs); font-weight: var(--ds-fw-semibold); background: var(--ds-surface-alt);
  color: var(--ds-muted); border: 1px solid var(--ds-border); white-space: nowrap; }
.chip { display: inline-flex; align-items: center; gap: var(--ds-space-1); font-size: var(--ds-fs-xs); color: var(--ds-muted); }
.chip::before { content: ""; width: 10px; height: 10px; border-radius: 2px; background: var(--dot, var(--ds-faint)); }

/* ---- Error badge (illustration for error / empty states) ----
   Note this is NOT the `.badge` pill above — different component, deliberately
   different class. This is the raptor artwork shown on error routes.

   The ink is `currentColor`, so ONE asset serves both themes: it inherits
   whatever text color the theme resolved to (--ds-text in body flow, --ds-ink
   inside a heading). There is no color declared here on purpose — declaring one
   would break the entire mechanism.

   REQUIRES the SVG to be INLINED into the DOM. Loaded through <img src> or
   background-image, an external SVG cannot see the page's CSS and currentColor
   falls back to black in both themes. Use --mask below where <img> is forced.
   See SKILL.md § "Error badge".

   Size via --ds-error-badge-w. That's a component dimension, not a brand value,
   so a literal default is fine here; colors still come only from tokens. */
.ds-error-badge {
  display: block;
  width: 100%;
  max-width: var(--ds-error-badge-w, 22rem);
  margin: 0 auto var(--ds-space-4);
}
.ds-error-badge svg { display: block; width: 100%; height: auto; }

/* Mask variant — same adaptivity without inlining, for the rare context that
   forces an external image. Tints a solid block through the artwork's alpha,
   so the paint is currentColor and the detail is the full original stipple.
   Set --ds-error-badge-mask to the URL of mongo-error-mask.png as resolved by
   the consuming app (paths differ per repo, so it can't be hardcoded here). */
.ds-error-badge--mask {
  aspect-ratio: 1037 / 684;
  background-color: currentColor;
  -webkit-mask: var(--ds-error-badge-mask) center / contain no-repeat;
          mask: var(--ds-error-badge-mask) center / contain no-repeat;
}

/* Error route layout: centers the badge over the existing copy. Purely
   positional — it sets no color, so the badge keeps inheriting the theme. */
.error-state { text-align: center; padding: var(--ds-space-8) var(--ds-space-4); }
.error-state__code { font-size: var(--ds-fs-kpi); font-weight: var(--ds-fw-bold);
  color: var(--ds-ink); font-variant-numeric: tabular-nums; line-height: var(--ds-lh-tight); }
.error-state__msg { color: var(--ds-muted); margin: var(--ds-space-2) 0 var(--ds-space-5); }

/* ---- Callout: left-border accent + soft tint. Use for computed results. ---- */
.callout { margin-top: var(--ds-space-4); padding: var(--ds-space-4);
  border: 1px solid var(--ds-primary); border-left-width: 4px; border-radius: var(--ds-radius-md);
  background: var(--ds-primary-soft); }

/* ---- Flash messages ---- */
.flash { padding: var(--ds-space-3) var(--ds-space-4); border-radius: var(--ds-radius-md);
  margin-bottom: var(--ds-space-4); font-size: var(--ds-fs-sm); border: 1px solid transparent; }
.flash--success { background: var(--ds-success-soft); color: var(--ds-success); border-color: var(--ds-success); }
.flash--warning { background: var(--ds-warning-soft); color: var(--ds-warning); border-color: var(--ds-warning); }
.flash--danger  { background: var(--ds-danger-soft);  color: var(--ds-danger);  border-color: var(--ds-danger); }

/* ---- Progress ---- */
.progress { height: 12px; border-radius: var(--ds-radius-pill); background: var(--ds-surface-alt);
  overflow: hidden; border: 1px solid var(--ds-border); }
.progress__bar { height: 100%; background: var(--ds-primary); border-radius: var(--ds-radius-pill); }

/* ---- Layout helpers ---- */
.grid-2 { display: grid; grid-template-columns: 1fr; gap: var(--ds-space-4); margin-top: var(--ds-space-4); }
@media (min-width: 640px) { .grid-2 { grid-template-columns: 1fr 1fr; } }
.section-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--ds-space-3); margin-bottom: var(--ds-space-3); }
.section-head h1, .section-head h2 { margin: 0; }
.tidy-list { list-style: none; padding: 0; margin: 0; }
.tidy-list li { padding: var(--ds-space-1) 0; }
.muted { color: var(--ds-muted); }
.linklike { background: none; border: 0; padding: 0; min-height: 0; color: var(--ds-danger);
  cursor: pointer; font: inherit; text-decoration: underline; }
.row-actions { display: flex; gap: var(--ds-space-3); align-items: center; white-space: nowrap; }
canvas { max-width: 100%; }
