/* =============================================================================
   HrChronicle — design tokens ("Harbor")
   Ported from design/prototypes/theme-directions.html (2026-07-21).
   The prototype's markup was throwaway; this file is the keeper.

   THREE TIERS, and the order matters:

     1. PRIMITIVE  --hrc-p-*        Raw scales. Never referenced by a component.
                                    Referencing one from a component is a BUG.
     2. SEMANTIC   --hrc-*          Meaning, not value. This is ALL a component may use.
                                    Theming rebinds this tier and nothing else.
     3. COMPONENT  --hrc-<name>-*   Knobs a consumer may turn. Defined next to the
                                    component that owns them, defaulting to semantic.

   Light/dark uses the CSS `light-dark()` function against `color-scheme`, so every
   semantic token is declared exactly ONCE and still follows prefers-color-scheme,
   with `data-theme` on <html> overriding in both directions. See §2.

   Never hard-code a colour, radius, spacing or row height in a component. If the value
   is not here, add it here.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   §1  PRIMITIVE TIER — raw scales, no meaning attached
   -------------------------------------------------------------------------- */
:root {
  /* -- neutral / harbor slate ------------------------------------------------ */
  --hrc-p-white: #ffffff;
  --hrc-p-slate-25: #f6f8fd;
  --hrc-p-slate-50: #f4f6fb;
  --hrc-p-slate-75: #f4f7fd;
  --hrc-p-slate-100: #eef1f7;
  --hrc-p-slate-200: #e6eaf3;
  --hrc-p-slate-300: #d2d9e8;
  --hrc-p-slate-400: #8a93a9;
  --hrc-p-slate-500: #6f7a93;
  --hrc-p-slate-550: #4e576f;
  --hrc-p-slate-600: #a3adc4;
  --hrc-p-slate-650: #8e9ab5;
  --hrc-p-slate-700: #313d58;
  --hrc-p-slate-750: #242e45;
  --hrc-p-slate-800: #1e263a;
  --hrc-p-slate-825: #1a2237;
  --hrc-p-slate-850: #151c2e;
  --hrc-p-slate-875: #1c2438;
  --hrc-p-slate-900: #141b2d;
  --hrc-p-slate-950: #0d1220;
  --hrc-p-slate-975: #0b1024;
  --hrc-p-slate-050-ink: #e8ecf6;

  /* -- navy (the rail) ------------------------------------------------------- */
  --hrc-p-navy-500: #22304f;
  --hrc-p-navy-600: #1f2c48;
  --hrc-p-navy-700: #152039;
  --hrc-p-navy-800: #1c2740;
  --hrc-p-navy-850: #182134;
  --hrc-p-navy-900: #0a0f1c;
  --hrc-p-navy-ink: #98a5c0;

  /* -- blue (accent) --------------------------------------------------------- */
  --hrc-p-blue-100: #e9eefe;
  --hrc-p-blue-200: #ccd9fd;
  --hrc-p-blue-300: #9ab2ff;
  --hrc-p-blue-400: #7d9cff;
  --hrc-p-blue-500: #3b6cf6;
  --hrc-p-blue-600: #2f59d4;
  --hrc-p-blue-800: #2a3760;
  --hrc-p-blue-900: #1a2340;

  /* -- violet (admin variant accent) ---------------------------------------- */
  /* Admin plane wears the violet accent to make it unambiguous that this is
     the platform-operator surface, not a tenant. The palette mirrors the blue
     scale one-for-one so the same semantic tokens can rebind cleanly on
     :root[data-variant="admin"] below (§3 admin re-binding block). */
  --hrc-p-violet-100: #f2edff;
  --hrc-p-violet-200: #dcd0ff;
  --hrc-p-violet-300: #d68eff;
  --hrc-p-violet-400: #c26aff;
  --hrc-p-violet-500: #7239c4;
  --hrc-p-violet-600: #5c2ba0;
  --hrc-p-violet-800: #4b2c8a;
  --hrc-p-violet-900: #2a1a4d;
  --hrc-p-violet-on-dark: #1a0f2c;

  /* -- status ---------------------------------------------------------------- */
  --hrc-p-green-300: #3fbf9b;
  --hrc-p-green-100: #e3f5f0;
  --hrc-p-green-600: #0d8a6a;
  --hrc-p-green-900: #0f2620;
  --hrc-p-amber-300: #dfa45c;
  --hrc-p-amber-100: #fdf3e3;
  --hrc-p-amber-600: #b06a00;
  --hrc-p-amber-900: #2a2013;
  --hrc-p-red-300: #ef7a6d;
  --hrc-p-red-100: #fdedeb;
  --hrc-p-red-600: #c33327;
  --hrc-p-red-900: #2d1719;

  /* -- spacing scale (rem, 1rem = 16px) -------------------------------------- */
  --hrc-p-space-0: 0;
  --hrc-p-space-1: 0.25rem;
  --hrc-p-space-2: 0.5rem;
  --hrc-p-space-3: 0.75rem;
  --hrc-p-space-4: 1rem;
  --hrc-p-space-5: 1.25rem;
  --hrc-p-space-6: 1.5rem;
  --hrc-p-space-8: 2rem;
  --hrc-p-space-10: 2.5rem;
  --hrc-p-space-12: 3rem;
  --hrc-p-space-16: 4rem;

  /* -- radii ----------------------------------------------------------------- */
  --hrc-p-radius-1: 7px;
  --hrc-p-radius-2: 10px;
  --hrc-p-radius-3: 14px;
  --hrc-p-radius-pill: 999px;

  /* -- type ------------------------------------------------------------------ */
  /* IBM Plex Sans (+ Arabic) is the chosen face (OFL, self-hosted). The @font-face
     files are not vendored yet — the stack falls back to the system UI font until
     they land, so no layout depends on the download. Fonts are served as FILES,
     never inlined as data: URIs (that would force `font-src data:` for nothing). */
  --hrc-p-font-sans: "IBM Plex Sans", "IBM Plex Sans Arabic", system-ui, -apple-system,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --hrc-p-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --hrc-p-text-xs: 0.75rem;
  --hrc-p-text-sm: 0.8125rem;
  --hrc-p-text-md: 0.875rem;
  --hrc-p-text-lg: 1rem;
  --hrc-p-text-xl: 1.25rem;
  --hrc-p-text-2xl: 1.5rem;

  --hrc-p-weight-regular: 400;
  --hrc-p-weight-medium: 500;
  --hrc-p-weight-semibold: 600;

  --hrc-p-leading-tight: 1.25;
  --hrc-p-leading-normal: 1.5;
  --hrc-p-leading-loose: 1.65;

  /* -- elevation & motion ---------------------------------------------------- */
  --hrc-p-shadow-light: 0 1px 2px rgba(20, 27, 45, 0.04), 0 4px 14px rgba(20, 27, 45, 0.05);
  --hrc-p-shadow-dark: 0 1px 2px rgba(0, 0, 0, 0.35), 0 4px 16px rgba(0, 0, 0, 0.35);
  --hrc-p-shadow-pop-light: 0 16px 44px rgba(10, 16, 32, 0.22);
  --hrc-p-shadow-pop-dark: 0 20px 50px rgba(0, 0, 0, 0.6);
  --hrc-p-scrim-light: rgba(16, 22, 40, 0.42);
  --hrc-p-scrim-dark: rgba(4, 8, 18, 0.62);

  --hrc-p-duration-fast: 120ms;
  --hrc-p-duration-normal: 180ms;
  --hrc-p-ease: cubic-bezier(0.2, 0, 0.2, 1);

  /* -- z scale --------------------------------------------------------------- */
  --hrc-p-z-sticky: 100;
  --hrc-p-z-rail: 200;
  --hrc-p-z-popover: 300;
  --hrc-p-z-dialog: 400;
}

/* -----------------------------------------------------------------------------
   §2  THEME SWITCHING

   `color-scheme` is the single source of truth and `light-dark()` reads it, so each
   semantic token below is written once instead of once per theme.

     - default            → `light dark`, i.e. follow the OS (prefers-color-scheme)
     - [data-theme=light] → pinned light, wins over a dark OS
     - [data-theme=dark]  → pinned dark, wins over a light OS

   Setting `color-scheme` also fixes native form controls, scrollbars and the canvas
   background for free — a JS-free win we would otherwise have to fake.
   The attribute is written by wwwroot/js/theme.js from localStorage BEFORE first
   paint (the script is loaded in <head> without `defer`), so there is no flash and
   no inline <script> — CSP has no unsafe-inline to fall back on.
   -------------------------------------------------------------------------- */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* -----------------------------------------------------------------------------
   VARIANT AXIS

   Independent of theme. The admin plane stamps `data-variant="admin"` on <html>
   so its accent shifts from blue to violet, marking the platform-operator
   surface unambiguously. Other consumers (tenant Web) omit the attribute and
   get the default blue.

   Lives here rather than in a component stylesheet because it re-binds SEMANTIC
   tokens - the same three-tier discipline as theme and density. A component
   file that referenced --hrc-p-violet-* directly would fail DesignTokenTests
   for the same reason no component may reach for --hrc-p-blue-*: theming
   rebinds semantic tokens and nothing else.
   -------------------------------------------------------------------------- */
:root[data-variant="admin"] {
  --hrc-accent: light-dark(var(--hrc-p-violet-500), var(--hrc-p-violet-400));
  --hrc-accent-hover: light-dark(var(--hrc-p-violet-600), var(--hrc-p-violet-300));
  --hrc-accent-on: light-dark(var(--hrc-p-white), var(--hrc-p-violet-on-dark));
  --hrc-accent-soft: light-dark(var(--hrc-p-violet-100), var(--hrc-p-violet-900));
  --hrc-accent-line: light-dark(var(--hrc-p-violet-200), var(--hrc-p-violet-800));
  --hrc-rail-accent: var(--hrc-p-violet-400);
}

/* -----------------------------------------------------------------------------
   §3  SEMANTIC TIER — the ONLY tier a component may reference
   -------------------------------------------------------------------------- */
:root {
  /* -- surfaces -------------------------------------------------------------- */
  --hrc-canvas: light-dark(var(--hrc-p-slate-50), var(--hrc-p-slate-950));
  --hrc-surface: light-dark(var(--hrc-p-white), var(--hrc-p-slate-850));
  --hrc-surface-raised: light-dark(var(--hrc-p-slate-25), var(--hrc-p-slate-825));
  --hrc-surface-hover: light-dark(var(--hrc-p-slate-75), var(--hrc-p-slate-875));

  /* -- borders --------------------------------------------------------------- */
  --hrc-border: light-dark(var(--hrc-p-slate-200), var(--hrc-p-slate-750));
  --hrc-border-strong: light-dark(var(--hrc-p-slate-300), var(--hrc-p-slate-700));

  /* -- ink ------------------------------------------------------------------- */
  --hrc-ink: light-dark(var(--hrc-p-slate-900), var(--hrc-p-slate-050-ink));
  --hrc-ink-muted: light-dark(var(--hrc-p-slate-550), var(--hrc-p-slate-600));
  --hrc-ink-subtle: light-dark(var(--hrc-p-slate-400), var(--hrc-p-slate-500));

  /* -- accent ---------------------------------------------------------------- */
  --hrc-accent: light-dark(var(--hrc-p-blue-500), var(--hrc-p-blue-400));
  --hrc-accent-hover: light-dark(var(--hrc-p-blue-600), var(--hrc-p-blue-300));
  --hrc-accent-on: light-dark(var(--hrc-p-white), var(--hrc-p-slate-975));
  --hrc-accent-soft: light-dark(var(--hrc-p-blue-100), var(--hrc-p-blue-900));
  --hrc-accent-line: light-dark(var(--hrc-p-blue-200), var(--hrc-p-blue-800));

  /* -- status ---------------------------------------------------------------- */
  --hrc-ok: light-dark(var(--hrc-p-green-600), var(--hrc-p-green-300));
  --hrc-ok-soft: light-dark(var(--hrc-p-green-100), var(--hrc-p-green-900));
  --hrc-warn: light-dark(var(--hrc-p-amber-600), var(--hrc-p-amber-300));
  --hrc-warn-soft: light-dark(var(--hrc-p-amber-100), var(--hrc-p-amber-900));
  --hrc-crit: light-dark(var(--hrc-p-red-600), var(--hrc-p-red-300));
  --hrc-crit-soft: light-dark(var(--hrc-p-red-100), var(--hrc-p-red-900));
  --hrc-neutral-soft: light-dark(var(--hrc-p-slate-100), var(--hrc-p-slate-800));

  /* -- navigation rail (dark in both themes by design) ----------------------- */
  --hrc-rail: light-dark(var(--hrc-p-navy-700), var(--hrc-p-navy-900));
  --hrc-rail-ink: light-dark(var(--hrc-p-navy-ink), var(--hrc-p-slate-650));
  --hrc-rail-ink-strong: var(--hrc-p-white);
  --hrc-rail-active: light-dark(var(--hrc-p-navy-500), var(--hrc-p-navy-800));
  --hrc-rail-border: light-dark(var(--hrc-p-navy-600), var(--hrc-p-navy-850));
  --hrc-rail-accent: var(--hrc-p-blue-400);

  /* Rail brand plate (packet admin-harbor-retrofit B1, 2026-08-01) - the lighter
     surface behind the wordmark so a tile-plus-currentColor mark reads on the
     dark rail. Fixed white/ink pair (not themed) because brand recognition wants
     a stable plate; the ink pair balances the white plate so the wordmark's
     currentColor text reads regardless of the viewer's theme. Semantic pair
     alongside --hrc-rail-ink-strong (also fixed-white), same reasoning: some
     rail chrome must not rebind with the theme. */
  --hrc-rail-plate-bg: var(--hrc-p-white);
  --hrc-rail-plate-ink: var(--hrc-p-slate-900);

  /* -- elevation ------------------------------------------------------------- */
  --hrc-shadow: light-dark(var(--hrc-p-shadow-light), var(--hrc-p-shadow-dark));
  --hrc-shadow-pop: light-dark(var(--hrc-p-shadow-pop-light), var(--hrc-p-shadow-pop-dark));
  --hrc-scrim: light-dark(var(--hrc-p-scrim-light), var(--hrc-p-scrim-dark));

  /* -- shape ----------------------------------------------------------------- */
  --hrc-radius: var(--hrc-p-radius-3);
  --hrc-radius-sm: var(--hrc-p-radius-2);
  --hrc-radius-xs: var(--hrc-p-radius-1);
  --hrc-radius-pill: var(--hrc-p-radius-pill);

  /* -- type ------------------------------------------------------------------ */
  --hrc-font: var(--hrc-p-font-sans);
  --hrc-font-mono: var(--hrc-p-font-mono);

  --hrc-text-xs: var(--hrc-p-text-xs);
  --hrc-text-sm: var(--hrc-p-text-sm);
  --hrc-text-md: var(--hrc-p-text-md);
  --hrc-text-lg: var(--hrc-p-text-lg);
  --hrc-text-xl: var(--hrc-p-text-xl);
  --hrc-text-2xl: var(--hrc-p-text-2xl);

  --hrc-weight-regular: var(--hrc-p-weight-regular);
  --hrc-weight-medium: var(--hrc-p-weight-medium);
  --hrc-weight-semibold: var(--hrc-p-weight-semibold);

  --hrc-leading-tight: var(--hrc-p-leading-tight);
  --hrc-leading: var(--hrc-p-leading-normal);
  --hrc-leading-loose: var(--hrc-p-leading-loose);

  /* -- focus (WCAG 2.2 AA: every interactive element shows a visible ring) ---- */
  --hrc-focus-ring: 2px solid var(--hrc-accent);
  --hrc-focus-offset: 2px;

  /* -- motion ---------------------------------------------------------------- */
  --hrc-duration: var(--hrc-p-duration-normal);
  --hrc-ease: var(--hrc-p-ease);

  /* -- stacking --------------------------------------------------------------
     The primitive z scale existed from the port but had no semantic names, so the
     first component that needed one (the Select popover) could only have reached
     for --hrc-p-z-popover — which DesignTokenTests correctly forbids. Named here
     rather than hard-coded, because a popover appearing UNDER a sticky grid header
     is the kind of bug that is invisible until the two components meet. */
  --hrc-z-sticky: var(--hrc-p-z-sticky);
  --hrc-z-rail: var(--hrc-p-z-rail);
  --hrc-z-popover: var(--hrc-p-z-popover);
  --hrc-z-dialog: var(--hrc-p-z-dialog);

  /* -- spacing aliases (semantic names for the primitive scale) -------------- */
  --hrc-space-none: var(--hrc-p-space-0);
  --hrc-space-2xs: var(--hrc-p-space-1);
  --hrc-space-xs: var(--hrc-p-space-2);
  --hrc-space-sm: var(--hrc-p-space-3);
  --hrc-space-md: var(--hrc-p-space-4);
  --hrc-space-lg: var(--hrc-p-space-6);
  --hrc-space-xl: var(--hrc-p-space-8);
  --hrc-space-2xl: var(--hrc-p-space-12);
}

/* -----------------------------------------------------------------------------
   §4  DENSITY — a token set, exactly like theme.
   `comfortable` is the default; `data-density="compact"` on <html> rebinds it.
   Written by the same theme.js from the same localStorage store.
   -------------------------------------------------------------------------- */
:root {
  --hrc-density-row-height: 54px;
  --hrc-density-control-height: 38px;
  --hrc-density-pad: var(--hrc-p-space-6);
  --hrc-density-gap: var(--hrc-p-space-5);
  --hrc-density-nav-height: 36px;
  --hrc-density-text: var(--hrc-p-text-md);
  --hrc-density-text-secondary: var(--hrc-p-text-xs);
}

:root[data-density="compact"] {
  --hrc-density-row-height: 40px;
  --hrc-density-control-height: 32px;
  --hrc-density-pad: var(--hrc-p-space-4);
  --hrc-density-gap: var(--hrc-p-space-3);
  --hrc-density-nav-height: 31px;
  --hrc-density-text: var(--hrc-p-text-sm);
  --hrc-density-text-secondary: var(--hrc-p-text-xs);
}

/* -----------------------------------------------------------------------------
   §5  COMPONENT TIER — knobs a consumer may turn.
   Component-owned knobs live beside their component in a scoped .razor.css; these
   are the cross-cutting ones that exist before their component does.
   Every one of them defaults to a SEMANTIC token, never to a primitive.
   -------------------------------------------------------------------------- */
:root {
  --hrc-grid-row-height: var(--hrc-density-row-height);
  --hrc-field-height: var(--hrc-density-control-height);
  --hrc-section-padding: var(--hrc-density-pad);
  --hrc-page-max-inline-size: 92rem;

  /* Checkbox and radio box size. Deliberately NOT tied to density: a control that is
     also a touch target must not shrink when a user asks for a denser grid, and at
     compact density a density-derived box would land under the 24px minimum that
     WCAG 2.2 target size (minimum) asks for. The spacing around it still varies. */
  --hrc-choice-size: 1.125rem;

  /* Default cap on the inline-size of a form input. A 100%-width text field inside a
     wide section reads as "type an essay here" when the value is actually a code or a
     database name, and it dwarfs the field's own label. Applied as a max-inline-size
     on .hrc-input in forms.css (packet edit-tenant 2026-07-30). Opt-out per field with
     .hrc-input--wide when the value is legitimately freeform (a street address, a
     multi-line note). */
  --hrc-input-max-inline-size: 32rem;
}

/* -----------------------------------------------------------------------------
   §6  BREAKPOINTS

   Two, and only two. NOTE THE PITFALL: a CSS custom property CANNOT be used inside
   a media query condition, so these values are written literally at every use site.
   They are recorded here as the single documented source; if one changes, grep for
   the literal. (`@custom-media` would fix this and is not yet Baseline.)

       md  →  48rem   (768px)  phone/tablet boundary — Sidebar stacks below this
       lg  →  75rem  (1200px)  desktop — the rail can sit alongside comfortably
   -------------------------------------------------------------------------- */
