/* ============================================================================
   agentcensus — design tokens
   ----------------------------------------------------------------------------
   Categorical slots are assigned to discovery mechanisms in ADR-010 PRECEDENCE
   ORDER, so visual order encodes trust order. Both modes are selected, each
   stepped for its own surface — dark is not an inversion of light.

   WHAT IS VALIDATED HERE, AND BY WHAT. The two halves of this file are held to
   their numbers in different ways, so a claim about one is not a claim about
   the other.

   Ink — checked arithmetically, on every build.
     `web/app/scripts/palette-guard.mjs` computes WCAG relative luminance for
     --text-primary, --text-secondary and --text-muted against --surface-page
     and --surface-1, in all three mode blocks, and fails under 4.5:1 (AA for
     normal text; every consumer of these tokens draws at 13px or smaller, so
     the large-text exemption never applies). There is no ratio in this header
     to trust — the guard divides. It exists because light-mode --text-muted
     shipped at 3.41:1 for months underneath a header that said all checks
     pass (#226).

   Hues — a dated measurement, re-checked by nothing.
     The six categorical slots passed the CVD / normal-vision separation
     validator on 2026-08-08, in both modes:
       light  worst adjacent CVD ΔE 9.1 · normal-vision 19.6
       dark   worst adjacent CVD ΔE 8.4 · normal-vision 19.3
     Those figures describe THAT set of six at THOSE hex values, and are
     recorded in UI_UX.md §5.2. The guard checks the count, that each hue is
     declared in both modes, and that no two mechanisms share a tier and a
     stroke form — it does not compute ΔE. Editing a hex therefore passes the
     build and leaves the run above describing a palette that no longer
     exists: re-run the validator and record the new result in §5.2.

   Three light-mode slots sit below 3:1 against the light surface, which
   obligates visible direct labels or the table view. Both ship, so the relief
   holds — on the same terms as the hues, since the guard does not measure
   non-text contrast either.

   Do not add a 7th mechanism hue. `openapi` and `gateway` are deliberately
   folded — both mean "inferred from API shape", the weakest ADR-010 tier.
   ========================================================================= */

:root {
  color-scheme: light;

  /* ── surfaces & ink ───────────────────────────────────────────────────── */
  --surface-1:      #fcfcfb;   /* chart surface */
  --surface-page:   #f9f9f7;
  --text-primary:   #0b0b0b;
  --text-secondary: #52514e;
  /* Darker than the dark-mode muted, and deliberately so. One grey cannot sit
     correctly against both a #f9f9f7 page and a #0d0d0d one: #898781 measures
     5.41:1 on the dark page but only 3.41:1 here, an AA failure at the 13px
     and smaller sizes every consumer of this token actually uses. #6e6d68
     clears 4.5:1 on both light surfaces with margin, keeps the warm cast, and
     stays a visible step below --text-secondary so the tier still reads muted. */
  --text-muted:     #6e6d68;
  --gridline:       #e1e0d9;
  --axis:           #c3c2b7;
  --hairline:       rgba(11, 11, 11, .10);
  /* The boundary a control draws when it is called out — hover today, and any
     future state that leans on a border to say "this one". WCAG 1.4.11 asks
     3:1 of a UI component boundary, and the input hover border was built as
     `--text-muted` at 45% over the page: 1.85:1 light, 2.00:1 dark. Both modes
     failed (#230). An alpha mix cannot be measured by palette-guard, which is
     the reason the failure survived two passes over the ink, so a boundary
     that has to clear a ratio is a stepped token per mode and the token is
     what the guard measures. Here: 3.42:1 on --surface-page, 3.52:1 on
     --surface-1. Lighter than --text-muted on purpose — a border that outweighs
     the label is a different bug. */
  --border-interactive: #88877f;
  --success-text:   #006300;

  /* ── discovery mechanisms (categorical, ADR-010 precedence order) ───────
     SIX slots, and six is the number the validator was run on — the ΔE and
     lightness-band figures in UI_UX.md §5.2 describe exactly this set.

     A slot is a PRECEDENCE TIER, not a mechanism. Twelve mechanisms map onto
     these six by tier, and are told apart inside a tier by stroke form
     (solid / dashed / dotted) in lib/palette.ts. Slots 7–12 existed briefly,
     one per mechanism; they took the set past the 7–8 perceptual ceiling, were
     never validated, and — since charts direct-label only at ≤4 visible series
     — left twelve lines identified by colour alone. Adding a seventh hue here
     means re-running the validator on the whole set and recording the result
     in §5.2, exactly as these six are.

     openapi is deliberately the same value in light and dark: it validated in
     both, and a token that does not need to move should not move. */
  --mech-ans:       #2a78d6;   /* tier 1 — registry-verified, TL entry      */
  --mech-ard:       #eb6834;   /* tier 2 — publisher-curated catalog        */
  --mech-dnsaid2:   #1baf7a;   /* tier 3 — DNS/document-verifiable          */
  --mech-a2a:       #eda100;   /* tier 4 — self-asserted card               */
  --mech-dnsaid1:   #e87ba4;   /* tier 5 — index file, often a stub         */
  --mech-openapi:   #008300;   /* tier 6 — inferred from API shape          */

  /* ── status (reserved — never a series colour; always icon + label) ───── */
  --status-good:     #0ca30c;
  --status-warning:  #fab219;
  --status-serious:  #ec835a;
  --status-critical: #d03b3b;

  /* de-emphasis / "no result" — a miss is not a category, it is absence */
  --neutral:        #c3c2b7;
  --neutral-wash:   rgba(137, 135, 129, .18);

  /* Magnitude, single-series. The Trust Vector is five measures of ONE agent on
     ONE scale, so it is sequential-blue — deliberately NOT a mechanism hue, which
     would imply the score belongs to a discovery source. Track is a lighter step
     of the same ramp, per the meter rule. */
  --viz-magnitude:       #2a78d6;
  --viz-magnitude-track: #cde2fb;

  /* ── type ─────────────────────────────────────────────────────────────── */
  --sans: "Inter Variable", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Identifiers only: domains, agentIds, DNS names, SVCB params — strings a
     reader compares character by character. Never prose, never figures. */
  --mono: "JetBrains Mono Variable", ui-monospace, "SF Mono", Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;

    --surface-1:      #1a1a19;
    --surface-page:   #0d0d0d;
    --text-primary:   #ffffff;
    /* Raised 2026-09-03 from #c3c2b7 and #898781: both cleared 4.5:1, and
       both read as faded, because grey on near-black has no chroma to hold.
       #dedcd4 is 13.6:1 on the page and #adaba3 is 8.9:1; the three tiers
       still step down in the same order. */
    --text-secondary: #dedcd4;
    --text-muted:     #adaba3;
    --gridline:       #2c2c2a;
    --axis:           #383835;
    --hairline:       rgba(255, 255, 255, .10);
    /* 4.32:1 on --surface-page, 3.87:1 on --surface-1. Stepped for this
       surface, not inverted from light — see the light block for why this is
       a token rather than a mix. */
    --border-interactive: #78776f;
    --success-text:   #0ca30c;

    --mech-ans:       #3987e5;
    --mech-ard:       #d95926;
    --mech-dnsaid2:   #199e70;
    --mech-a2a:       #c98500;
    --mech-dnsaid1:   #d55181;
    --mech-openapi:   #008300;

    --neutral:        #383835;
    --neutral-wash:   rgba(137, 135, 129, .22);
    --viz-magnitude:       #3987e5;
    --viz-magnitude-track: #184f95;
  }
}

/* The viewer's toggle wins over the OS setting, both directions. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --surface-1:      #1a1a19;
  --surface-page:   #0d0d0d;
  --text-primary:   #ffffff;
  /* Raised 2026-09-03 from #c3c2b7 and #898781: both cleared 4.5:1, and
     both read as faded, because grey on near-black has no chroma to hold.
     #dedcd4 is 13.6:1 on the page and #adaba3 is 8.9:1; the three tiers
     still step down in the same order. */
  --text-secondary: #dedcd4;
  --text-muted:     #adaba3;
  --gridline:       #2c2c2a;
  --axis:           #383835;
  --hairline:       rgba(255, 255, 255, .10);
  /* 4.32:1 on --surface-page, 3.87:1 on --surface-1. Stepped for this
     surface, not inverted from light — see the light block for why this is
     a token rather than a mix. */
  --border-interactive: #78776f;
  --success-text:   #0ca30c;

  --mech-ans:       #3987e5;
  --mech-ard:       #d95926;
  --mech-dnsaid2:   #199e70;
  --mech-a2a:       #c98500;
  --mech-dnsaid1:   #d55181;
  --mech-openapi:   #008300;

  --neutral:        #383835;
  --neutral-wash:   rgba(137, 135, 129, .22);
  --viz-magnitude:       #3987e5;
  --viz-magnitude-track: #184f95;
}

/* ── Infoblox ─────────────────────────────────────────────────────────────
   A light theme in the house colours, proposed 2026-09-03. Sampled from
   infoblox.com on that date, not from a brand book: navy #101820 as ink,
   teal #0c818e as the accent (darkened to #096b76 so a link on the page
   ground clears 4.5:1), green #007d4d for "good". The ground is a pale blue
   rather than the warm off-white, which is the one departure from the site
   and the whole point of the request: grey ink on a dark ground read badly,
   and this is the opposite corner. Mechanism hues are the validated light
   set, redeclared so an OS-dark reader who picks this theme does not get the
   dark-stepped hues on a light ground. palette-guard checks this block like
   the other three. */
:root[data-theme="infoblox"] {
  color-scheme: light;

  --surface-1:      #ffffff;
  --surface-page:   #eaf3f7;
  --text-primary:   #101820;
  --text-secondary: #1c2b36;
  --text-muted:     #3f5866;
  --gridline:       #d3e3ea;
  --axis:           #a9c3cf;
  --hairline:       rgba(16, 24, 32, .12);
  --border-interactive: #5f7d8c;
  --success-text:   #007d4d;

  --mech-ans:       #2a78d6;
  --mech-ard:       #eb6834;
  --mech-dnsaid2:   #1baf7a;
  --mech-a2a:       #eda100;
  --mech-dnsaid1:   #e87ba4;
  --mech-openapi:   #008300;

  --status-good:     #007d4d;
  --status-warning:  #fab219;
  --status-serious:  #ec835a;
  --status-critical: #d03b3b;

  --neutral:        #a9c3cf;
  --neutral-wash:   rgba(12, 129, 142, .12);
  --viz-magnitude:       #096b76;
  --viz-magnitude-track: #cfe9ed;

  --shadow-sm: 0 1px 2px rgba(16, 24, 32, .06);
  --shadow-md: 0 2px 4px rgba(16, 24, 32, .07), 0 8px 24px rgba(16, 24, 32, .07);
  --shadow-lg: 0 4px 8px rgba(16, 24, 32, .08), 0 16px 48px rgba(16, 24, 32, .11);
}

/* ============================================================================
   Scale
   ----------------------------------------------------------------------------
   Added because the palette was a system and everything else was not: spacing,
   type sizes, and radii were literals typed at each call site, which is what
   makes a page read as assembled rather than designed. Two elements 5px apart
   and two 6px apart are not expressing anything; they are just different.

   A 4px base with a modular type ramp. The named steps exist so a component
   CHOOSES a size rather than inventing one.
   ========================================================================= */
:root {
  /* ── space (4px base) ─────────────────────────────────────────────────── */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  24px;
  --s-6:  32px;
  --s-7:  48px;
  --s-8:  64px;
  --s-9:  96px;
  --s-10: 128px;

  /* ── type ─────────────────────────────────────────────────────────────── */
  /* A census is read as much as it is looked at, so the ramp is conservative
     below the display sizes and only gets dramatic at the hero. */
  /* 12 is the floor (Material's 12sp, Apple's 11pt), 16 the body every
     platform guideline lands on; 15 was a step under it everywhere and the
     caps labels two steps under the floor. A 16px field also stops iOS Safari
     zooming the page when one is focused. */
  --t-xs:   12px;
  --t-sm:   14px;
  --t-base: 16px;
  --t-md:   18px;
  --t-lg:   20px;
  --t-xl:   26px;
  --t-2xl:  34px;
  --t-3xl:  clamp(34px, 5vw, 52px);
  --t-hero: clamp(44px, 7vw, 76px);

  --lh-tight: 1.15;
  --lh-snug:  1.35;
  --lh-body:  1.6;

  /* Tracking tightens as size grows - the same optical correction a type
     designer would apply, expressed once instead of guessed per heading. */
  --track-hero:  -0.03em;
  --track-tight: -0.02em;
  --track-snug:  -0.01em;
  --track-caps:   0.08em;

  --w-regular: 400;
  --w-medium:  500;
  --w-semi:    600;
  --w-bold:    700;

  /* ── radii ────────────────────────────────────────────────────────────── */
  --r-sm:   6px;
  --r-md:   10px;
  --r-lg:   14px;
  --r-full: 999px;

  /* ── elevation ────────────────────────────────────────────────────────── */
  /* Restrained on purpose. This is a document, not a dashboard chrome demo:
     shadows mark what LIFTS on interaction, and a resting card does not. */
  --shadow-sm: 0 1px 2px rgba(11, 11, 11, .05);
  --shadow-md: 0 2px 4px rgba(11, 11, 11, .06), 0 8px 24px rgba(11, 11, 11, .06);
  --shadow-lg: 0 4px 8px rgba(11, 11, 11, .07), 0 16px 48px rgba(11, 11, 11, .10);

  /* ── motion ───────────────────────────────────────────────────────────── */
  --ease: cubic-bezier(.2, .6, .3, 1);
  --dur-fast: 120ms;
  --dur-base: 180ms;

  /* ── layout ───────────────────────────────────────────────────────────── */
  /* `ch` is the width of a zero, which in Inter is wider than the average
     glyph: 68ch measured 729px at 17px, about 89 characters a line, past the
     45-75 a reader holds without losing the line. 60ch lands near 78. */
  --measure:      60ch;   /* prose */
  --measure-tight: 48ch;  /* lede and standfirst */
  --w-page:      1200px;
  --w-narrow:     820px;
  --header-h:      60px;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    /* Dark surfaces need more spread and less opacity, or a shadow reads as a
       smudge. Stepped for the surface rather than inherited from light. */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, .45), 0 8px 24px rgba(0, 0, 0, .40);
    --shadow-lg: 0 4px 8px rgba(0, 0, 0, .50), 0 16px 48px rgba(0, 0, 0, .55);
  }
}

:root[data-theme="dark"] {
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
  --shadow-md: 0 2px 4px rgba(0, 0, 0, .45), 0 8px 24px rgba(0, 0, 0, .40);
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, .50), 0 16px 48px rgba(0, 0, 0, .55);
}
