/* lh-ui.css v1 — GENERATED by build.sh (tokens.css + components.css). Do not hand-edit. */

/* ============================================================================
   lh-ui v1 — Token Layer (the contract, made executable)
   Owner: claude-foundation · designteam · DRAFT pending glm-pm ack

   Semantic role tokens under :root (House default) + [data-theme] presets for
   sociotype | dala | tapbots | manuscript. Components reference ROLES, never brand names.
   Set data-theme on <html>, <body>, or any subtree (themes nest).
   Sources: ~/screenshots-inbox/DESIGN (2|4|5).md + apps.letsharkness.com/design-lab/
   ============================================================================ */

/* ============================================================================
   SELF-HOSTED DISPLAY FACES (v2.1 — additive; first self-hosted fonts in the kit)
   New house convention: NO CDN fonts for these faces. Variable woff2 vendored from
   Fontsource (`@fontsource-variable/<name>`, SIL OFL 1.1) into fonts/<family>/ next
   to this file; licenses in each fonts/<family>/OFL.txt. URLs are RELATIVE to this
   stylesheet, so they resolve the same whether loaded as tokens.css or the built
   lh-ui.css (both live at /lh-ui/v1/). Verified axis ranges (from the actual woff2
   fvar tables, not memory):
     · Bodoni Moda        wght 400–900 · opsz 6–96 (default 11) · ital 0–1
     · Cormorant          wght 300–700 · ital 0–1        (no opsz axis)
     · Playfair Display   wght 400–900 · ital 0–1        (no opsz/wdth axis)
   Only the manuscript theme consumes these (via --font-display). Bodoni Moda is the
   live default; Cormorant / Playfair ship for the Phase-2 taste gate (specimen page).
   Optical size on Bodoni is driven by `font-optical-sizing: auto` (browser default) —
   larger rendered sizes automatically pull the high-contrast display cut; no
   font-variation-settings needed. Subsets vendored: latin + latin-ext (unicode-range
   exactly as Fontsource ships). Optional preload for the default face:
     <link rel="preload" as="font" type="font/woff2" crossorigin
           href="/lh-ui/v1/fonts/bodoni-moda/bodoni-moda-latin-standard-normal.woff2">
   ============================================================================ */

/* — Bodoni Moda (Didone; wght 400–900 + opsz 6–96) — */
@font-face {
  font-family: 'Bodoni Moda'; font-style: normal; font-weight: 400 900; font-display: swap;
  src: url(fonts/bodoni-moda/bodoni-moda-latin-standard-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Bodoni Moda'; font-style: normal; font-weight: 400 900; font-display: swap;
  src: url(fonts/bodoni-moda/bodoni-moda-latin-ext-standard-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Bodoni Moda'; font-style: italic; font-weight: 400 900; font-display: swap;
  src: url(fonts/bodoni-moda/bodoni-moda-latin-standard-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Bodoni Moda'; font-style: italic; font-weight: 400 900; font-display: swap;
  src: url(fonts/bodoni-moda/bodoni-moda-latin-ext-standard-italic.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* — Cormorant (warm Garamond hairlines; wght 300–700) — */
@font-face {
  font-family: 'Cormorant'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url(fonts/cormorant/cormorant-latin-wght-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Cormorant'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url(fonts/cormorant/cormorant-latin-ext-wght-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Cormorant'; font-style: italic; font-weight: 300 700; font-display: swap;
  src: url(fonts/cormorant/cormorant-latin-wght-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Cormorant'; font-style: italic; font-weight: 300 700; font-display: swap;
  src: url(fonts/cormorant/cormorant-latin-ext-wght-italic.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* — Playfair Display (Didone/transitional; wght 400–900) — */
@font-face {
  font-family: 'Playfair Display'; font-style: normal; font-weight: 400 900; font-display: swap;
  src: url(fonts/playfair-display/playfair-display-latin-wght-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Playfair Display'; font-style: normal; font-weight: 400 900; font-display: swap;
  src: url(fonts/playfair-display/playfair-display-latin-ext-wght-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display'; font-style: italic; font-weight: 400 900; font-display: swap;
  src: url(fonts/playfair-display/playfair-display-latin-wght-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Playfair Display'; font-style: italic; font-weight: 400 900; font-display: swap;
  src: url(fonts/playfair-display/playfair-display-latin-ext-wght-italic.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

:root {
  color-scheme: light;

  /* — Color: semantic roles — */
  --color-bg: #ffffff;
  --color-bg-deep: #f6f6f7;
  --color-surface: #ffffff;
  --color-surface-2: #f6f6f7;
  --color-fg: #16161a;
  --color-fg-muted: #5b5b66;
  --color-fg-subtle: #8a8a94;
  --color-fg-on-accent: #ffffff;
  --color-border: #e4e4e8;
  --color-border-strong: #c8c8d0;
  --color-accent: #5a40e0;
  --color-accent-hover: #472fc0;
  --color-accent-muted: #eeebfb;
  --color-link: #5a40e0;
  --color-success: #15846e;
  --color-warning: #b8860b;
  --color-danger: #d23b3b;
  --color-focus-ring: color-mix(in srgb, var(--color-accent) 55%, transparent);

  /* — Typography: families — */
  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: var(--font-sans);
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* — Typography: scale (size / leading / tracking triads) — */
  --text-caption: 12px;     --leading-caption: 1.4;    --tracking-caption: 0.02em;
  --text-body-sm: 13px;     --leading-body-sm: 1.5;    --tracking-body-sm: 0em;
  --text-body: 15px;        --leading-body: 1.6;       --tracking-body: 0em;
  --text-body-lg: 18px;     --leading-body-lg: 1.6;    --tracking-body-lg: 0em;
  --text-subheading: 21px;  --leading-subheading: 1.4; --tracking-subheading: -0.005em;
  --text-heading-sm: 24px;  --leading-heading-sm: 1.3; --tracking-heading-sm: -0.01em;
  --text-heading: 30px;     --leading-heading: 1.25;   --tracking-heading: -0.015em;
  --text-heading-lg: 40px;  --leading-heading-lg: 1.15;--tracking-heading-lg: -0.02em;
  --text-display: 60px;     --leading-display: 1.05;   --tracking-display: -0.025em;
  --text-hero: 88px;        --leading-hero: 1.0;       --tracking-hero: -0.03em;

  /* — Typography: semantic weights (Sociotype=400 only, Dala→700, Tapbots→600) — */
  --weight-body: 400;
  --weight-medium: 500;
  --weight-strong: 600;
  --weight-display: 600;

  /* — Spacing: fixed house ramp (NOT theme-overridden; keeps components stable) — */
  --spacing-2xs: 4px;
  --spacing-xs: 8px;
  --spacing-sm: 12px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
  --spacing-2xl: 48px;
  --spacing-3xl: 64px;
  --spacing-4xl: 96px;
  --spacing-5xl: 128px;

  /* — Layout: theme-overridable densities — */
  --page-max-width: 1200px;
  --section-gap: var(--spacing-4xl);
  --card-padding: var(--spacing-lg);
  --element-gap: var(--spacing-md);

  /* — Radius: generic scale + component roles — */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-pill: 9999px;
  --radius-button: 8px;
  --radius-card: 12px;
  --radius-input: 8px;
  --radius-badge: 6px;

  /* — Motion (names per locked contract: --duration-* / --ease-*) — */
  --duration-fast: 120ms;
  --duration: 200ms;
  --duration-slow: 360ms;
  --ease-standard: cubic-bezier(.2, 0, 0, 1);
  --ease-out: cubic-bezier(0, 0, .2, 1);
  --ease-in: cubic-bezier(.4, 0, 1, 1);
  --motion-scale: 1;   /* budget multiplier; reduced-motion → 0 */

  /* — Elevation (near-flat; prefer borders over shadow) — */
  --shadow-1: 0 1px 2px rgba(16, 16, 26, .06), 0 1px 1px rgba(16, 16, 26, .04);
  --shadow-2: 0 4px 12px rgba(16, 16, 26, .08), 0 2px 4px rgba(16, 16, 26, .05);
}

/* ─────────────────────────────────────────────────────────────────────────
   SOCIOTYPE — light type-foundry · monochrome · 0 radius · weight 400 only
   ───────────────────────────────────────────────────────────────────────── */
[data-theme="sociotype"] {
  color-scheme: light;

  --color-bg: #ffffff;
  --color-bg-deep: #ffffff;
  --color-surface: #ffffff;
  --color-surface-2: #ffffff;
  --color-fg: #000000;
  --color-fg-muted: #818181;
  --color-fg-subtle: #9d9d9d;
  --color-fg-on-accent: #ffffff;
  --color-border: #d6d6d6;
  --color-border-strong: #000000;
  --color-accent: #000000;          /* "no distinct CTA color" — action = ink */
  --color-accent-hover: #1a1818;
  --color-accent-muted: #f2f2f2;
  --color-link: #000000;            /* arrow-suffix idiom; underline on hover */
  --color-success: #15846e;         /* functional state only (documented exception) */
  --color-warning: #7a5b00;
  --color-danger: #9e2b25;

  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: var(--font-sans);

  --text-caption: 11px;    --leading-caption: 1.38;   --tracking-caption: 0.08em;
  --text-body-sm: 12px;    --leading-body-sm: 1.3;    --tracking-body-sm: 0.05em;
  --text-body: 14px;       --leading-body: 1.29;      --tracking-body: 0.015em;
  --text-body-lg: 16px;    --leading-body-lg: 1.22;   --tracking-body-lg: 0.015em;
  --text-subheading: 18px; --leading-subheading: 1.19;--tracking-subheading: 0.025em;
  --text-heading-sm: 20px; --leading-heading-sm: 1.19;--tracking-heading-sm: 0.02em;
  --text-heading: 26px;    --leading-heading: 1.13;   --tracking-heading: 0.015em;
  --text-heading-lg: 40px; --leading-heading-lg: 1.0; --tracking-heading-lg: 0.015em;
  --text-display: 88px;    --leading-display: 1.0;    --tracking-display: 0.001em;
  --text-hero: 160px;      --leading-hero: 1.0;       --tracking-hero: 0.001em;

  --weight-body: 400;
  --weight-medium: 400;             /* one calm voice — never bold */
  --weight-strong: 400;
  --weight-display: 400;

  --section-gap: 120px;
  --card-padding: var(--spacing-sm);
  --element-gap: var(--spacing-sm);

  --radius-sm: 0; --radius-md: 0; --radius-lg: 0; --radius-pill: 0;
  --radius-button: 0; --radius-card: 0; --radius-input: 0; --radius-badge: 0;

  --shadow-1: none;
  --shadow-2: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   DALA — dark void · single violet pulse · 24px pill · weight 200–700
   ───────────────────────────────────────────────────────────────────────── */
[data-theme="dala"] {
  color-scheme: dark;

  --color-bg: #000000;
  --color-bg-deep: #000000;
  --color-surface: #000000;          /* card = hairline on the void */
  --color-surface-2: rgba(255, 255, 255, .03);
  --color-fg: #ffffff;
  --color-fg-muted: #bdbdbd;
  --color-fg-subtle: #9a9a9a;
  --color-fg-on-accent: #ffffff;
  --color-border: rgba(255, 255, 255, .12);
  --color-border-strong: rgba(128, 82, 255, .5);
  --color-accent: #8052ff;           /* plum voltage — the only filled chroma */
  --color-accent-hover: #6f43e8;
  --color-accent-muted: rgba(128, 82, 255, .14);
  --color-link: #8052ff;
  --color-success: #15846e;          /* lichen */
  --color-warning: #ffb829;          /* amber spark */
  --color-danger: #ff5470;

  --font-sans: 'Space Grotesk', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: var(--font-sans);

  --text-caption: 12px;    --leading-caption: 1.5;    --tracking-caption: 0.021em;
  --text-body-sm: 14px;    --leading-body-sm: 1.5;    --tracking-body-sm: 0.021em;
  --text-body: 15px;       --leading-body: 1.5;       --tracking-body: 0.025em;
  --text-body-lg: 18px;    --leading-body-lg: 1.5;    --tracking-body-lg: 0.025em;
  --text-subheading: 18px; --leading-subheading: 1.5; --tracking-subheading: 0.025em;
  --text-heading-sm: 24px; --leading-heading-sm: 1.3; --tracking-heading-sm: 0.021em;
  --text-heading: 36px;    --leading-heading: 1.2;    --tracking-heading: 0.021em;
  --text-heading-lg: 48px; --leading-heading-lg: 1.1; --tracking-heading-lg: -0.02em;
  --text-display: 78px;    --leading-display: 0.9;    --tracking-display: -0.04em;
  --text-hero: 113px;      --leading-hero: 0.81;      --tracking-hero: -0.04em;

  --weight-body: 400;
  --weight-medium: 600;
  --weight-strong: 700;
  --weight-display: 200;             /* etched-thin signature */

  --section-gap: 60px;
  --card-padding: var(--spacing-lg);
  --element-gap: 15px;

  --radius-sm: 24px; --radius-md: 24px; --radius-lg: 24px; --radius-pill: 9999px;
  --radius-button: 24px; --radius-card: 24px; --radius-input: 24px; --radius-badge: 9999px;

  --shadow-1: none;
  --shadow-2: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   TAPBOTS — dark violet dusk · system font · 40 pill / 18 list · weight 300–600
   ───────────────────────────────────────────────────────────────────────── */
[data-theme="tapbots"] {
  color-scheme: dark;

  --color-bg: #1a1a1a;
  --color-bg-deep: #05050b;
  --color-surface: #212121;          /* graphite — 1-step lift */
  --color-surface-2: #111111;        /* carbon */
  --color-fg: #ffffff;
  --color-fg-muted: #b3b3b3;
  --color-fg-subtle: #999999;
  --color-fg-on-accent: #ffffff;
  --color-border: rgba(255, 255, 255, .10);
  --color-border-strong: rgba(186, 148, 255, .5);
  --color-accent: #7047ba;           /* signal violet (filled brand) */
  --color-accent-hover: #5d3a9e;
  --color-accent-muted: #301e4f;     /* twilight */
  --color-link: #ba94ff;             /* glow violet (interactive emphasis) */
  --color-success: #74ec5a;          /* neon green */
  --color-warning: #e0a93b;
  --color-danger: #ff3543;           /* alarm red */

  --font-sans: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, sans-serif; /* no web font */
  --font-display: var(--font-sans);

  --text-caption: 13px;    --leading-caption: 1.5;    --tracking-caption: 0em;
  --text-body-sm: 14px;    --leading-body-sm: 1.5;    --tracking-body-sm: 0em;
  --text-body: 16px;       --leading-body: 1.7;       --tracking-body: 0em;
  --text-body-lg: 18px;    --leading-body-lg: 1.6;    --tracking-body-lg: 0em;
  --text-subheading: 21px; --leading-subheading: 1.4; --tracking-subheading: 0em;
  --text-heading-sm: 24px; --leading-heading-sm: 1.3; --tracking-heading-sm: 0em;
  --text-heading: 28px;    --leading-heading: 1.2;    --tracking-heading: -0.01em;
  --text-heading-lg: 32px; --leading-heading-lg: 1.2; --tracking-heading-lg: -0.01em;
  --text-display: 36px;    --leading-display: 1.1;    --tracking-display: -0.015em;
  --text-hero: 56px;       --leading-hero: 1.05;      --tracking-hero: -0.02em;

  --weight-body: 400;
  --weight-medium: 500;
  --weight-strong: 600;
  --weight-display: 300;             /* airy */

  --page-max-width: 900px;
  --section-gap: 80px;
  --card-padding: var(--spacing-md);
  --element-gap: var(--spacing-md);

  --radius-sm: 12px; --radius-md: 18px; --radius-lg: 24px; --radius-pill: 9999px;
  --radius-button: 40px; --radius-card: 18px; --radius-input: 18px; --radius-badge: 9999px;

  --shadow-1: none;
  --shadow-2: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   MANUSCRIPT v2 — warm paper · self-hosted Didone display (Bodoni Moda) · deep
   value ramp with a true dark-ink anchor + hairline rules · committed oxblood
   (rubrication) accent · intense top-scale variability · editorial whitespace.
   Promoted from edu.letsharkness.com's "The Manuscript" identity; overhauled for
   Design Language v2 (V4). Overrides palette + display face + top-of-scale +
   section rhythm and flattens shadows; INHERITS House's caption→heading-lg scale,
   spacing ramp, radius, and mid weights. The display face is SELF-HOSTED — the
   @font-face blocks at the top of this file ship Bodoni Moda / Cormorant /
   Playfair; no CDN, no consuming-app font load required (unlike v1's Fraunces).

   THE PICK POINT: face choice is ONE variable (--font-display + its optimum
   --font-display-weight). Swapping to a taste-gate alternative is a 2-line change
   (uncomment one pair below). The accent is likewise one hue swap.
   Additive discipline: new tokens (--color-ink / --color-fg-on-ink[-muted] /
   --color-rule / --color-accent-on-ink / --font-display-weight / --space-section)
   + value changes WITHIN this selector only. No role renames.
   ───────────────────────────────────────────────────────────────────────── */
[data-theme="manuscript"] {
  color-scheme: light;

  /* — Deep paper ramp: four visibly-stepped bands (v1 values spread ~L .96→.65)
       brightness order surface > bg > surface-2 > bg-deep, all still warm paper — */
  --color-bg: #f4efe4;               /* aged paper — the anchor band (unchanged)  L.87 */
  --color-bg-deep: #ddd2bb;           /* deepest backdrop band (was #ece5d6)        L.65 */
  --color-surface: #fdfaf3;           /* leaf — brightest, cards lift off paper     L.96 */
  --color-surface-2: #eadfca;         /* embedded well / table stripe (was #f2ece0) L.75 */
  --color-fg: #211d17;               /* warm ink                       16.1–11.2:1 on paper */
  --color-fg-muted: #5f5645;          /* secondary (darkened from #6a6153 → AA on bg-deep 4.83:1) */
  --color-fg-subtle: #9b9182;         /* tertiary — captions/metadata (decorative, not body) */
  --color-fg-on-accent: #ffffff;      /* white on oxblood = 11:1 */
  --color-border: #e2d9c7;            /* soft parchment divider (unchanged) */
  --color-border-strong: #cabfa8;     /* emphasized parchment divider (unchanged) */

  /* — Dark-ink anchor (NEW): a deep warm near-black band for inverted sections — */
  --color-ink: #1c1710;               /* deep warm near-black surface           L.009 */
  --color-fg-on-ink: #f2ebdb;         /* paper-white text on ink                14.99:1 */
  --color-fg-on-ink-muted: #b8ad95;   /* muted text on ink                       8.01:1 */
  --color-rule: #3a3225;              /* crisp ink HAIRLINE rule (8.4–12.1:1 on paper) —
                                          distinct from the soft --color-border dividers;
                                          use for ledger/ruled lines drawn in ink */

  /* — Accent: committed oxblood (rubrication — the manuscript red-ink gesture).
       Replaces the house violet WITHIN manuscript. WCAG (measured, sRGB):
         as text on paper — surface 9.84 · bg 8.94 · surface-2 7.77 · bg-deep 6.84  (all ≥4.5 ✓)
       A deep-enough-for-paper accent cannot also clear near-black ink (raw on ink 1.74),
       so display type on the ink band uses --color-accent-on-ink (same hue, lightened). — */
  --color-accent: #7a1e2b;            /* oxblood */
  --color-accent-hover: #641320;      /* deeper oxblood (8.5–12.2:1 on paper) */
  --color-accent-muted: #f0e3e0;      /* warm blush — low-emphasis fill / selected bg */
  --color-accent-on-ink: #cf7078;     /* NEW — rubric rose; large-display on ink 5.29:1 (≥3 ✓) */
  --color-link: #7a1e2b;              /* inline link = the rubric accent */
  --color-success: #15846e;           /* functional colors kept at House values */
  --color-warning: #b8860b;
  --color-danger: #d23b3b;

  /* Rejected accents (same paper-vs-ink tension; rejected on CHARACTER, not contrast):
       forest      #234d33  paper 9.24–6.42 ✓  raw-on-ink 1.85 — cool green muddies warm paper
       ultramarine #263a8c  paper 9.75–6.78 ✓  raw-on-ink 1.75 — over-cools (cold face+accent+warm paper) */

  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-display: 'Bodoni Moda', Georgia, 'Times New Roman', serif;   /* DEFAULT — coldest, highest-contrast Didone */
  --font-display-weight: 650;         /* NEW — Didone display optimum (axis wght 400–900; ≥650 committed) */
  /* ── taste-gate swaps (specimen A/B/C) — uncomment ONE pair to change the face: ──
     --font-display: 'Cormorant', Georgia, 'Times New Roman', serif;         --font-display-weight: 600;  (warm Garamond; axis 300–700)
     --font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;  --font-display-weight: 700;  (middle path; axis 400–900) */

  /* — Intense top-scale variability (V4): manuscript overrides ONLY the top two
       rungs to ~1.5–2× the House scale. Jumps (base 16px):
         heading-lg 40px/2.5rem  →  display 96px/6rem (×2.4)  →  hero 168px/10.5rem (×1.75)
       (House display/hero are 60/88px; caption→heading-lg inherit House unchanged.)
       Optical size is automatic on Bodoni via font-optical-sizing: auto. — */
  --text-display: 96px;   --leading-display: 1.0;   --tracking-display: -0.02em;
  --text-hero: 168px;     --leading-hero: 0.92;     --tracking-hero: -0.025em;
  --weight-display: var(--font-display-weight);   /* display headings render the Didone at 650 */

  /* — Editorial whitespace: generous section rhythm (NEW --space-section drives the
       layout --section-gap). Big air is part of the "expensive" read. — */
  --space-section: 160px;             /* NEW — manuscript section rhythm (House is 96px) */
  --section-gap: var(--space-section);

  --shadow-1: none;
  --shadow-2: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   Smooth anchor / programmatic scroll (DL1) — additive, v1-legal.
   Anchor + programmatic scroll jumps ease under no-preference; inertia itself
   is handled by the Lenis layer (lh-scroll.js). The reduced-motion block below
   forces `scroll-behavior: auto !important` and stays authoritative under reduce.
   ───────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Motion budget — reduced motion neutralizes ambient motion globally
   ───────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  :root { --motion-scale: 0; --duration-fast: 0ms; --duration: 0ms; --duration-slow: 0ms; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}


/* ============================================================================
   lh-ui v1 — Component Kit
   Owner: claude-foundation · designteam · authored against ANTI-SLOP.md

   References SEMANTIC ROLE tokens only (see tokens.css / TOKEN-CONTRACT.md).
   No hex, no brand names, no hardcoded weights — every value is a var() so the
   kit reskins across House / sociotype / dala / tapbots with zero markup change.

   Classes are `lh-`-prefixed and opt-in, so linking this file over an existing
   app does NOT restyle its markup. Apps adopt the base via <body class="lh-base">
   or wrap a subtree in .lh-base; components are used by class.
   ============================================================================ */

/* ── Base (opt-in; never clobbers a host app's bare elements) ───────────────*/
.lh-base {
  box-sizing: border-box;
  margin: 0;
  background: var(--color-bg);
  color: var(--color-fg);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  font-weight: var(--weight-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.lh-base *, .lh-base *::before, .lh-base *::after { box-sizing: border-box; }
.lh-base ::selection { background: var(--color-accent-muted); color: var(--color-fg); }

/* ── Layout utilities ───────────────────────────────────────────────────────*/
.lh-container { width: 100%; max-width: var(--page-max-width); margin-inline: auto; padding-inline: var(--spacing-lg); }
.lh-section   { padding-block: var(--section-gap); }
.lh-stack > * + * { margin-top: var(--element-gap); }       /* vertical rhythm */
.lh-cluster   { display: flex; flex-wrap: wrap; align-items: center; gap: var(--element-gap); }
.lh-grid      { display: grid; gap: var(--spacing-lg); }
.lh-grid--2   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.lh-grid--3   { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.lh-grid--4   { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ── Type roles (utility classes; size+leading+tracking+weight together) ─────*/
.lh-display   { font-family: var(--font-display); font-size: var(--text-display);   line-height: var(--leading-display);   letter-spacing: var(--tracking-display);   font-weight: var(--weight-display); margin: 0; }
.lh-hero      { font-family: var(--font-display); font-size: var(--text-hero);      line-height: var(--leading-hero);      letter-spacing: var(--tracking-hero);      font-weight: var(--weight-display); margin: 0; }
.lh-h1        { font-family: var(--font-display); font-size: var(--text-heading-lg); line-height: var(--leading-heading-lg); letter-spacing: var(--tracking-heading-lg); font-weight: var(--weight-display); margin: 0; }
.lh-h2        { font-size: var(--text-heading);    line-height: var(--leading-heading);    letter-spacing: var(--tracking-heading);    font-weight: var(--weight-strong); margin: 0; }
.lh-h3        { font-size: var(--text-heading-sm); line-height: var(--leading-heading-sm); letter-spacing: var(--tracking-heading-sm); font-weight: var(--weight-strong); margin: 0; }
.lh-subheading{ font-size: var(--text-subheading); line-height: var(--leading-subheading); letter-spacing: var(--tracking-subheading); font-weight: var(--weight-medium); margin: 0; }
.lh-body      { font-size: var(--text-body);       line-height: var(--leading-body);       letter-spacing: var(--tracking-body); margin: 0; }
.lh-body-lg   { font-size: var(--text-body-lg);    line-height: var(--leading-body-lg);    letter-spacing: var(--tracking-body-lg); margin: 0; }
.lh-caption   { font-size: var(--text-caption);    line-height: var(--leading-caption);    letter-spacing: var(--tracking-caption); margin: 0; }
.lh-eyebrow   { font-size: var(--text-caption); line-height: 1; letter-spacing: var(--tracking-caption); text-transform: uppercase; font-weight: var(--weight-strong); color: var(--color-accent); margin: 0; }
.lh-muted     { color: var(--color-fg-muted); }
.lh-subtle    { color: var(--color-fg-subtle); }
.lh-measure   { max-width: 62ch; }                         /* readable line length */

/* ── Focus: one accessible ring for every interactive lh- element ───────────*/
.lh-btn:focus-visible, .lh-link:focus-visible, .lh-input:focus-visible,
.lh-textarea:focus-visible, .lh-select:focus-visible, .lh-nav__link:focus-visible,
.lh-nav__action:focus-visible, .lh-card--interactive:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* ── Button ─────────────────────────────────────────────────────────────────
   Flat fills, schema radius. NO gradient, NO glow shadow (anti-slop Tier-1 #2).*/
.lh-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--spacing-xs);
  box-sizing: border-box;
  font-family: inherit;
  font-size: var(--text-body-sm);
  line-height: 1;
  letter-spacing: var(--tracking-body-sm);
  font-weight: var(--weight-strong);
  padding: var(--spacing-sm) var(--spacing-lg);
  border: 1px solid transparent;
  border-radius: var(--radius-button);
  background: var(--color-accent);
  color: var(--color-fg-on-accent);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--duration) var(--ease-standard),
              border-color var(--duration) var(--ease-standard),
              color var(--duration) var(--ease-standard);
}
.lh-btn:hover { background: var(--color-accent-hover); }
.lh-btn:disabled, .lh-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }

.lh-btn--secondary {            /* outlined; reads quiet next to primary */
  background: transparent; color: var(--color-fg); border-color: var(--color-border-strong);
}
.lh-btn--secondary:hover { background: var(--color-surface-2); border-color: var(--color-fg); }

.lh-btn--ghost { background: transparent; color: var(--color-fg); border-color: transparent; }
.lh-btn--ghost:hover { background: var(--color-surface-2); }

.lh-btn--danger { background: var(--color-danger); color: #fff; }
.lh-btn--danger:hover { filter: brightness(.92); }

.lh-btn--sm { padding: var(--spacing-xs) var(--spacing-sm); font-size: var(--text-caption); }
.lh-btn--lg { padding: var(--spacing-md) var(--spacing-xl); font-size: var(--text-body); }

/* Text link with the arrow-suffix idiom (Sociotype-native; works everywhere).*/
.lh-link {
  display: inline-flex; align-items: center; gap: var(--spacing-2xs);
  color: var(--color-link); text-decoration: none; font-weight: var(--weight-medium);
  border-bottom: 1px solid transparent;
  transition: border-color var(--duration) var(--ease-standard), color var(--duration) var(--ease-standard);
}
.lh-link:hover { border-bottom-color: currentColor; }
.lh-link::after { content: " →"; }                          /* the affordance IS the arrow */
.lh-link--plain::after { content: none; }

/* ── Card ───────────────────────────────────────────────────────────────────
   Border-defined, shadowless on flat schemas (anti-slop Tier-1 #5).          */
.lh-card {
  box-sizing: border-box;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--card-padding);
  box-shadow: var(--shadow-1);             /* `none` in sociotype/dala/tapbots; subtle in House */
}
.lh-card__title  { font-size: var(--text-heading-sm); line-height: var(--leading-heading-sm); letter-spacing: var(--tracking-heading-sm); font-weight: var(--weight-strong); margin: 0 0 var(--spacing-xs); }
.lh-card__body   { color: var(--color-fg-muted); margin: 0; }
.lh-card__footer { margin-top: var(--card-padding); padding-top: var(--spacing-sm); border-top: 1px solid var(--color-border); }
.lh-card--interactive { cursor: pointer; transition: border-color var(--duration) var(--ease-standard), transform var(--duration) var(--ease-standard); }
.lh-card--interactive:hover { border-color: var(--color-border-strong); }
.lh-card--lead { border-color: var(--color-border-strong); }   /* the one card with more weight */

/* ── Nav (top bar) ──────────────────────────────────────────────────────────
   Active state = weight + color + inset border, NEVER a left-edge filled pill
   (anti-slop Tier-1 #1).                                                       */
.lh-nav {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-lg);
  padding: var(--spacing-md) var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg);
}
.lh-nav__brand { font-size: var(--text-body-lg); font-weight: var(--weight-strong); letter-spacing: var(--tracking-body); color: var(--color-fg); text-decoration: none; }
.lh-nav__links { display: flex; align-items: center; gap: var(--spacing-lg); list-style: none; margin: 0; padding: 0; }
.lh-nav__link {
  position: relative;
  font-size: var(--text-body-sm); letter-spacing: var(--tracking-body-sm); font-weight: var(--weight-medium);
  color: var(--color-fg-muted); text-decoration: none; padding-block: var(--spacing-2xs);
  border-bottom: 2px solid transparent;
  transition: color var(--duration) var(--ease-standard), border-color var(--duration) var(--ease-standard);
}
.lh-nav__link:hover { color: var(--color-fg); }
.lh-nav__link.is-active { color: var(--color-fg); border-bottom-color: var(--color-accent); font-weight: var(--weight-strong); }

/* ── Inputs & forms ─────────────────────────────────────────────────────────
   Real labels always (anti-slop Tier-2: no placeholder-as-label).             */
.lh-field { display: flex; flex-direction: column; gap: var(--spacing-2xs); }
.lh-label { font-size: var(--text-body-sm); font-weight: var(--weight-medium); letter-spacing: var(--tracking-body-sm); color: var(--color-fg); }
.lh-input, .lh-textarea, .lh-select {
  box-sizing: border-box; width: 100%;
  font-family: inherit; font-size: var(--text-body); line-height: var(--leading-body); color: var(--color-fg);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
  padding: var(--spacing-sm) var(--spacing-md);
  transition: border-color var(--duration) var(--ease-standard), box-shadow var(--duration) var(--ease-standard);
}
.lh-input::placeholder, .lh-textarea::placeholder { color: var(--color-fg-subtle); }
.lh-input:focus, .lh-textarea:focus, .lh-select:focus {
  outline: none; border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-focus-ring);
}
.lh-textarea { min-height: 6rem; resize: vertical; }
.lh-input[aria-invalid="true"], .lh-textarea[aria-invalid="true"] { border-color: var(--color-danger); }
.lh-help  { font-size: var(--text-caption); color: var(--color-fg-subtle); letter-spacing: var(--tracking-caption); }
.lh-error { font-size: var(--text-caption); color: var(--color-danger); letter-spacing: var(--tracking-caption); }

/* ── Badge ──────────────────────────────────────────────────────────────────*/
.lh-badge {
  display: inline-flex; align-items: center; gap: var(--spacing-2xs);
  font-size: var(--text-caption); line-height: 1; letter-spacing: var(--tracking-caption);
  font-weight: var(--weight-strong); text-transform: uppercase;
  padding: var(--spacing-2xs) var(--spacing-sm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-badge);
  background: var(--color-surface-2); color: var(--color-fg-muted);
}
.lh-badge--accent  { background: var(--color-accent-muted); color: var(--color-accent); border-color: transparent; }
.lh-badge--success { background: color-mix(in srgb, var(--color-success) 16%, transparent); color: var(--color-success); border-color: transparent; }
.lh-badge--warning { background: color-mix(in srgb, var(--color-warning) 18%, transparent); color: var(--color-warning); border-color: transparent; }
.lh-badge--danger  { background: color-mix(in srgb, var(--color-danger) 16%, transparent);  color: var(--color-danger);  border-color: transparent; }

/* ── Table ──────────────────────────────────────────────────────────────────
   Hairline structure + value-step zebra; no heavy chrome.                     */
.lh-table { width: 100%; border-collapse: collapse; font-size: var(--text-body-sm); color: var(--color-fg); }
.lh-table th, .lh-table td { text-align: left; padding: var(--spacing-sm) var(--spacing-md); border-bottom: 1px solid var(--color-border); }
.lh-table thead th {
  font-size: var(--text-caption); letter-spacing: var(--tracking-caption); text-transform: uppercase;
  font-weight: var(--weight-strong); color: var(--color-fg-subtle);
  border-bottom-color: var(--color-border-strong);
}
.lh-table tbody tr { transition: background-color var(--duration) var(--ease-standard); }
.lh-table tbody tr:nth-child(even) { background: var(--color-surface-2); }
.lh-table tbody tr:hover { background: var(--color-accent-muted); }
.lh-table--flush th:first-child, .lh-table--flush td:first-child { padding-left: 0; }
.lh-table--flush th:last-child,  .lh-table--flush td:last-child  { padding-right: 0; }

/* ── Divider ────────────────────────────────────────────────────────────────*/
.lh-divider { border: none; border-top: 1px solid var(--color-border); margin-block: var(--spacing-lg); }

/* ── Responsive: collapse multi-col grids on small screens ──────────────────*/
@media (max-width: 720px) {
  .lh-grid--2, .lh-grid--3, .lh-grid--4 { grid-template-columns: 1fr; }
  .lh-nav { flex-wrap: wrap; gap: var(--spacing-sm); }
  .lh-nav__links { gap: var(--spacing-md); flex-wrap: wrap; }
}

/* ── View Transitions — house enter/exit choreography (Design Language v2.1) ──
   Authored ::view-transition-old/new so DISJOINT DOM swaps (filter changes, list
   add/remove, category switches) get a real exit+enter instead of the UA default
   crossfade — which, on a non-surviving element, reads as a snap (V1: nothing snaps).

   Opt in per element: give each transitioning node a UNIQUE `view-transition-name`
   (duplicates make ViewTransition.ready reject and the whole transition skip) PLUS
   the shared class:  `view-transition-class: card;`. One rule set below then covers
   every card via ::view-transition-*(.card) (Chrome "Same-document view transitions").

   FEATURE DETECTION: `view-transition-class` is Chromium 125+ / Safari 18.4+ only.
   `@supports (view-transition-class: none)` is the CSS-native form of
   CSS.supports('view-transition-class: none') — modern browsers apply the class
   rules below; older VT browsers (Chrome/Edge 111+, Safari 18, Firefox 144+) get no
   match here and fall back to PER-NAME rules the consumer authors under
   `@supports not (view-transition-class: none)` (reference fallback: the motion
   showcase page). Keyframes use house tokens + a translateY settle.

   Support: same-document VT interoperable now (Chrome/Edge 111+, Safari 18+, FF 144+). */
@keyframes lh-vt-fade-in  { from { opacity: 0; } }
@keyframes lh-vt-fade-out { to   { opacity: 0; } }
@keyframes lh-vt-rise-in  { from { transform: translateY(12px); } }
@keyframes lh-vt-rise-out { to   { transform: translateY(-8px); } }

/* Survivors (present in both states) reflow to their new slot at house tempo. */
html::view-transition-group(.card) {
  animation-duration: var(--duration-slow);
  animation-timing-function: var(--ease-standard);
}
/* Entering card (present only after): fade + settle up into place. */
::view-transition-new(.card):only-child {
  animation: var(--duration-slow) var(--ease-out) both lh-vt-fade-in,
             var(--duration-slow) var(--ease-out) both lh-vt-rise-in;
}
/* Leaving card (present only before): quicker fade + lift out. */
::view-transition-old(.card):only-child {
  animation: var(--duration) var(--ease-in) both lh-vt-fade-out,
             var(--duration) var(--ease-in) both lh-vt-rise-out;
}

/* MANDATORY reduced-motion guard — kills every view-transition animation. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
