/* GeoLiquefy design harness, at console density.

   This sheet replaces app/static/css/classical.css (parked at
   docs/parked/classical.css) as the engine's single token source and component
   layer. It carries the design system geoliquefy.com wears: Inter body,
   DM Sans headings, the surface/on-surface palette, the accent and status
   roles, the tracking ladder, and the focus/selection/motion conventions.

   Source of truth: where geoliquefy-design/tokens.css and the shipped
   geoliquefy-new-site/styles/main.css disagree on a VALUE, main.css wins.
   Where main.css lacks a CAPABILITY the console needs (border tiers, forms,
   dense tables, the full ease/duration vocabulary, the dark arm), it comes
   from tokens.css. The per-token derivation, including every contrast figure
   and the two places a value is new, is recorded in
   docs/design/harness-mapping-2026-09.md.

   Density is NOT adopted. The site is a marketing page at 17px body with
   120px sections and 16px radii; this is a dense engineering instrument on a
   fluid rem root. The spacing scale, the small radii and the panel paddings
   keep the ENGINE's values under the shared token names. See section 3.

   Fonts are self-hosted under app/static/fonts/ (byte-identical to the site's,
   see fonts/FONTS-LICENSE.txt for OFL-1.1 provenance), so the CSP keeps
   font-src 'self' and no external origin is introduced. */

/* ==========================================================================
   1. FONT LOADING
   The five faces the harness ships, plus the two metric-matched fallback
   faces ported from main.css lines 64 to 93. The fallback metrics are
   computed against Arial from the real published OS/2 and hhea metrics via
   the Fontaine/Capsize formula, so the reflow when the webfont arrives is
   minimal rather than a guess.

   DM Sans has no 600 cut. A heading asking for font-weight 600 would
   synthesize one; the allowed weights are 300, 400, 500 and 700.
   ========================================================================== */

@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-var.woff2") format("woff2-variations"),
       url("../fonts/inter-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("../fonts/dm-sans-300.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("../fonts/dm-sans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("../fonts/dm-sans-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("../fonts/dm-sans-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  ascent-override: 90.44%;
  descent-override: 22.52%;
  line-gap-override: 0%;
  size-adjust: 107.12%;
}
@font-face {
  font-family: "DM Sans Fallback";
  src: local("Arial");
  ascent-override: 94.90%;
  descent-override: 29.66%;
  line-gap-override: 0%;
  size-adjust: 104.53%;
}

:root {
  /* ========================================================================
     2. HARNESS TOKENS
     ======================================================================== */

  /* -- families and weights -- */
  --font-body: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-heading: "DM Sans", "DM Sans Fallback", -apple-system,
    BlinkMacSystemFont, sans-serif;
  /* New to the engine. Classical had no mono token, which is why every hash on
     the public certificate page lost its monospace treatment. System stack,
     per the site. */
  --font-mono: "SF Mono", "Monaco", "Courier New", monospace;

  --font-light: 300;
  --font-regular: 400;
  --font-medium: 500;
  --font-bold: 700;
  /* Interface headings need weight at small sizes; 500 is the ceiling because
     600 does not exist as a file. Display and verdict text go lighter still. */
  --font-heading-weight: 500;

  /* -- tracking ladder -- */
  --tracking-display: -0.03em;
  --tracking-h1: -0.03em;
  --tracking-h2: -0.025em;
  --tracking-h3: -0.02em;
  --tracking-h4: -0.015em;
  --tracking-body: -0.011em;
  --tracking-body-s: -0.008em;
  --tracking-micro: 0.05em;
  --tracking-eyebrow: 0.12em;
  /* The wordmark lockup: Geo at 700, Liquefy at 300, tightened. */
  --tracking-wordmark: -0.035em;

  --leading-tight: 1.1;
  --leading-marketing: 1.47059;
  --leading-dossier: 1.6;
  --measure-dossier: 75ch;

  /* -- type sizes, retuned for console density --
     The site's marketing scale (17px body, 40 to 48px h1) is not adopted. The
     figures below are the classical scale brought down where the family swap
     demands it: 42px of Cormorant 600 and 42px of DM Sans are not the same
     mass on the page. */
  --text-h1: 2.125rem;    /* 34px at the 16px root, was 42px Cormorant */
  --text-h2: 1.625rem;    /* 26px, was 32px */
  --text-h3: 1.3125rem;   /* 21px, was 25px */
  --text-h4: 1.0625rem;   /* 17px, was 20px */
  --text-h5: 0.9375rem;   /* 15px, was 16px */
  --text-h6: 0.75rem;     /* 12px, was 13px */
  --text-body-s: 0.9375rem;  /* 15px, the console body size */
  --text-caption: 0.875rem;  /* 14px */
  --text-micro: 0.75rem;     /* 12px floor */

  /* -- surfaces and ink --
     LOAD-BEARING PAIR, carried over from main.css: --on-surface-1 on
     --surface-1 computes to 4.66:1, AA with almost no margin. At the 11 to
     13px instrument sizes this console sets, secondary ink on a raised panel
     takes --on-surface-2 (8.09:1) instead. Re-verify contrast before changing
     either value. */
  --surface-0: #FFFFFF;
  --surface-1: #F5F5F7;
  --surface-2: #EBEBEE;
  --on-surface-0: #1D1D1F;  /* 16.83:1 on surface-0 */
  --on-surface-1: #6E6E73;  /* 5.07:1 on surface-0 */
  --on-surface-2: #4A4A4F;  /* 8.81:1 on surface-0 */

  /* -- accent -- */
  --accent-600: #0066CC;   /* 5.57:1 on white; white on this fill is 5.57:1 */
  --accent-700: #004499;   /* 9.18:1 on white, link text at console sizes */
  --accent-soft: rgba(0, 102, 204, 0.05);
  --accent-ring: rgba(0, 102, 204, 0.2);

  /* -- status --
     The engine's screening vocabulary maps onto these directly: PASS to
     success, MAYBE to warn, FAIL to danger, no-data to neutral ink. Classical
     could not express any of it, so the warm ramp did double duty and every
     danger was a hardcoded literal. Color is never the sole signal: each
     status keeps its rendered text label. */
  --success-700: #1E7A43;  /* 5.36:1 on white */
  --success-soft: rgba(30, 122, 67, 0.08);
  --warn-800: #8A5A00;     /* 5.93:1 on white */
  --warn-soft: rgba(138, 90, 0, 0.08);
  --danger-600: #C4291F;   /* danger TEXT and 1px edges, 5.70:1 on white */
  /* Danger FILL, for a solid badge or destructive button. White on it is
     3.55:1, which fails AA, so any text placed on this fill must be
     --on-surface-0 rather than white, or the fill must be large-text only.
     Danger TEXT and 1px edges take --danger-600. Nothing in the engine uses
     this yet; it is here so that when something does, the constraint is
     already written down. */
  --danger-fill: #FF3B30;
  --danger-soft: rgba(255, 59, 48, 0.08);

  /* -- borders --
     Three tiers. --border-control is new: the harness has nothing darker than
     its divider, and tokens.css --border-strong resolves to #D9D9D9 on white,
     LIGHTER than --border-divider, so it cannot carry a hover darkening. */
  --border-subtle: rgba(0, 0, 0, 0.08);
  --border-divider: #D1D1D6;
  --border-control: #A1A1A8;
  --border-strong: rgba(0, 0, 0, 0.15);  /* vocabulary completeness, unused */

  /* -- elevation -- */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 12px 30px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.12);
  --shadow-accent: 0 4px 12px rgba(0, 102, 204, 0.3);

  /* -- motion -- */
  --ease-default: ease;
  --ease-btn: cubic-bezier(0.25, 0.1, 0.25, 1);
  --ease-entrance: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-instant: 0.1s;
  --duration-fast: 0.2s;
  --duration-base: 0.3s;
  --duration-slow: 0.5s;
  --duration-entrance: 0.8s;
  --duration-shimmer: 2.2s;

  /* ========================================================================
     3. DENSITY: THE ENGINE'S OWN VALUES, KEPT
     These names collide with the site's, which sets --space-1 to 8px and
     --radius-md to 16px on an 8pt marketing grid. Redefining them to those
     values would inflate every panel in a frame whose column arithmetic
     (414 / 664 / 296 at the design viewport) is test-pinned. They are rem so
     they ride html.db-root's clamp, and identical to the old px values at the
     16px default root. Do not "fix" them to the 8pt scale.
     ======================================================================== */
  --space-1: 0.2875rem;
  --space-2: 0.575rem;
  --space-3: 0.8625rem;
  --space-4: 1.15rem;
  --space-6: 1.725rem;
  --space-8: 2.3rem;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;
  /* Adopted from the site at its own value, and applied ONLY to action
     buttons (ruling D2). Panels, inputs and wells keep the small radii. */
  --radius-full: 980px;
}

/* ==========================================================================
   4. DARK ARM, INERT
   Ruling D3: plumbed, never activated. There is no toggle and no
   prefers-color-scheme activation, matching the site, which disabled its own
   auto-activation for the same reason. Activating dark is its own tranche
   with its own contrast work over the console's light-only components.
   Values are the site's, which are in turn the Atlas console's dark palette.
   ========================================================================== */
:root[data-theme="dark"] {
  --surface-0: #0B1016;
  --surface-1: #121A24;
  --surface-2: #0D141D;
  --on-surface-0: #E7EDF3;
  --on-surface-1: #93A3B5;
  --on-surface-2: #5C6B7D;
  --accent-600: #4FB0FF;
  --accent-700: #1C4A6B;
  --accent-soft: #16283A;
  --accent-ring: #16283A;
  --success-700: #57C785;
  --success-soft: #10241A;
  --warn-800: #E0A340;
  --warn-soft: #2A2110;
  --danger-600: #E0605A;
  --danger-fill: #E0605A;
  --danger-soft: #2A1414;
  --border-subtle: #223042;
  --border-divider: #223042;
  --border-control: #2A3A4C;
  --border-strong: #2A3A4C;
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.24);
  --shadow-md: 0 12px 30px rgba(0, 0, 0, 0.36);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.48);
  --shadow-accent: 0 4px 12px rgba(79, 176, 255, 0.3);
}

/* ==========================================================================
   5. BASE
   ========================================================================== */

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

/* Form controls do not inherit font-family from their ancestors, so without
   this every unclassed button, input and select renders in the UA's own face
   next to the page's Inter. The dialog and delta-strip close buttons are the
   visible ones. */
button, input, select, textarea { font-family: inherit; }

body {
  margin: 0;
  background: var(--surface-0);
  color: var(--on-surface-0);
  font-family: var(--font-body);
  font-size: var(--text-body-s);
  line-height: 1.55;
  font-weight: var(--font-regular);
  letter-spacing: var(--tracking-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-2);
}
h1 { font-size: var(--text-h1); font-weight: var(--font-light); letter-spacing: var(--tracking-h1); }
h2 { font-size: var(--text-h2); font-weight: var(--font-light); letter-spacing: var(--tracking-h2); }
h3 { font-size: var(--text-h3); letter-spacing: var(--tracking-h3); }
h4 { font-size: var(--text-h4); letter-spacing: var(--tracking-h4); }
h5 { font-size: var(--text-h5); letter-spacing: var(--tracking-h4); }
h6 {
  font-size: var(--text-h6);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--on-surface-1);
}

p { margin: 0 0 var(--space-3); }
a { color: var(--accent-700); text-underline-offset: 3px; }
a:hover { color: var(--accent-600); }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px;
  margin-top: var(--space-1);
  color: var(--on-surface-1);
}
.text-muted { color: var(--on-surface-1); }

/* Every figure, table cell and numeric input carries tabular figures. Inter
   now sets ALL instrument text, so this is stated explicitly rather than
   inherited from the platform sans stack classical used. */
table, td, th, input, output, time, .mono, .tnum {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent-600); outline-offset: 2px; }
::selection { background: var(--accent-ring); }

.hr {
  height: 1px;
  border: 0;
  margin: var(--space-4) 0;
  background: var(--border-divider);
}

/* ==========================================================================
   6. BUTTONS
   Ruling D2: the site's action language. Primary is filled accent with the
   accent shadow; secondary and ghost stay outlined. Pill radius applies HERE
   and nowhere else. The press state is a scale nudge at --duration-instant,
   per tokens.css item 23.

   This is action language only. The verdict box is outlined and never filled
   regardless (dashboard.css .db-verdict-box), and no screening status is ever
   carried by a fill.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-body);
  font-weight: var(--font-medium);
  font-size: 0.8125rem;
  line-height: 1.2;
  letter-spacing: var(--tracking-body-s);
  color: var(--on-surface-0);
  background: transparent;
  border: 1px solid transparent;
  padding: calc(var(--space-2) * 0.85) var(--space-3);
  border-radius: var(--radius-full);
  transition: background-color var(--duration-fast) var(--ease-btn),
    border-color var(--duration-fast) var(--ease-btn),
    transform var(--duration-instant) var(--ease-btn);
}
.btn svg { display: block; }
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* aria-disabled, not the disabled attribute: Run Engine stays a real Tab
   stop while signed out (finding 10) so its state is announced rather than
   removed from the tab order, but it must still look inert. */
.btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }

.btn-primary {
  color: #FFFFFF;
  background: var(--accent-600);
  border-color: var(--accent-600);
  box-shadow: var(--shadow-accent);
}
.btn-primary:hover:not(:disabled) {
  background: var(--accent-700);
  border-color: var(--accent-700);
}
.btn-primary:disabled { box-shadow: none; }

.btn-secondary { border-color: var(--border-divider); }
.btn-secondary:hover:not(:disabled) {
  background: var(--surface-1);
  border-color: var(--border-control);
}
.btn-secondary:active:not(:disabled) { background: var(--surface-2); }

.btn-ghost { color: var(--accent-700); padding-inline: var(--space-1); }
.btn-ghost:hover:not(:disabled) { background: var(--accent-soft); }

.btn-icon { width: 34px; height: 34px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); }

/* ==========================================================================
   7. FORMS
   The console is mostly forms and the site has none, so the pattern comes
   from tokens.css, re-set at console density: the marketing spec's 9px by
   11px padding and 15px text would cost roughly a third of the rail.
   ========================================================================== */
.field > label {
  display: block;
  font-size: var(--text-micro);
  margin-bottom: 5px;
  color: var(--on-surface-1);
}
.input {
  width: 100%;
  min-height: 36px;
  padding: 6px 10px;
  font: inherit;
  font-size: var(--text-caption);
  color: var(--on-surface-0);
  caret-color: var(--accent-600);
  background: var(--surface-0);
  border: 1px solid var(--border-divider);
  border-radius: var(--radius-md);
  transition: border-color var(--duration-fast) var(--ease-default),
    box-shadow var(--duration-fast) var(--ease-default);
}
.input:hover { border-color: var(--border-control); }
.input:focus-visible {
  border-color: var(--accent-600);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline-offset: 0;
}
textarea.input { min-height: 90px; resize: vertical; }

.radio {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: var(--text-caption);
}
.radio input, .seg-opt input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
.radio .dot {
  width: 16px;
  height: 16px;
  flex: none;
  border-radius: 50%;
  border: 1.5px solid var(--border-divider);
}
.radio:hover .dot { border-color: var(--accent-600); }
.radio input:checked + .dot {
  border-color: var(--accent-600);
  background: var(--accent-600);
  box-shadow: inset 0 0 0 4px var(--surface-0);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--accent-600); outline-offset: 2px; }

.seg {
  display: inline-flex;
  overflow: hidden;
  border: 1px solid var(--border-divider);
  border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font-size: 13px;
  cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--border-divider); }
.seg-opt:has(input:checked) {
  color: var(--accent-700);
  box-shadow: inset 0 0 0 1px var(--accent-600);
}
.seg-opt:not(:has(input:checked)):hover { background: var(--surface-1); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--accent-600); outline-offset: -2px; }

/* ==========================================================================
   8. CARDS
   Product density: a 1px edge, never a marketing hover lift. This matches the
   site's own product-mode rule, where .card-evidence does not lift either.
   ========================================================================== */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid var(--border-divider);
}
.card-kicker {
  font-size: 10px;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--on-surface-1);
}
.card-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: var(--text-h4);
  letter-spacing: var(--tracking-h4);
  line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; color: var(--on-surface-2); flex: 1; }
.card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--on-surface-1);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* ==========================================================================
   9. TAGS
   Status tags carry a rendered text label in every case; the wash is a second
   signal, never the only one.
   ========================================================================== */
.tag {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: var(--text-micro);
  letter-spacing: 0.02em;
  padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--accent-soft); color: var(--accent-700); }
.tag-neutral { background: var(--surface-1); color: var(--on-surface-2); }
.tag-outline { border: 1px solid var(--border-divider); color: var(--on-surface-2); }
.tag-pass { background: var(--success-soft); color: var(--success-700); }
.tag-maybe { background: var(--warn-soft); color: var(--warn-800); }
.tag-fail { background: var(--danger-soft); color: var(--danger-600); }
.tag-nodata { background: var(--surface-1); color: var(--on-surface-1); font-style: italic; }

/* ==========================================================================
   10. NAVIGATION AND THE WORDMARK
   Geo at 700, Liquefy at 300, DM Sans, tightened. The two-weight split is the
   lockup the apex site uses.
   ========================================================================== */
.nav {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-divider);
}
.nav-brand {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 18px;
  margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: var(--text-caption); }
.nav a:hover, .nav a[aria-current="page"] { color: var(--accent-600); }


/* ==========================================================================
   11. TABLES
   ========================================================================== */
.table { width: 100%; border-collapse: collapse; font-size: var(--text-caption); }
.table th {
  text-align: left;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-surface-1);
  padding: var(--space-2);
  border-bottom: 1px solid var(--border-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--border-divider);
}
.table tbody tr:hover { background: var(--surface-1); }
.table-dense th, .table-dense td { padding: var(--space-1) var(--space-2); }

/* ==========================================================================
   12. DIALOG
   ========================================================================== */
.dialog-backdrop {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: rgba(29, 29, 31, 0.5);
}
.dialog {
  width: min(440px, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--surface-0);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--border-divider);
}
.dialog-title {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: var(--text-h4);
  letter-spacing: var(--tracking-h4);
}
.dialog-body { font-size: var(--text-caption); color: var(--on-surface-2); }
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* ==========================================================================
   13. SKELETON
   Shimmer cadence matches the Atlas console's, per tokens.css item 26.
   ========================================================================== */
/* NOT the dashboard's loading treatment. dashboard.css's .db-skel is, and it
   predates this tranche; this is the harness's own variant, lifted from
   tokens.css per the plan's S3. If the two ever need to be one thing, .db-skel
   is the one in use. */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--surface-1) 25%,
    var(--surface-2) 37%,
    var(--surface-1) 63%
  );
  background-size: 400% 100%;
  animation: harness-shimmer var(--duration-shimmer) var(--ease-default) infinite;
  border-radius: var(--radius-sm);
}
@keyframes harness-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
  .btn { transition: none; }
}
