:root {
  /* ---------- Base neutrals: warm ink on warm paper ---------- */
  --ink-000: #0B0B0A; /* near-black, the only "black" we use */
  --ink-900: #161614;
  --ink-800: #2A2925;
  --ink-700: #4A4842;
  --ink-600: #6B6860;
  --ink-500: #8C887E;
  --ink-400: #ADA89C;
  --ink-300: #CAC4B6;
  --ink-200: #DFDACD;
  --ink-100: #EBE6DA;
  --ink-050: #F3EFE6;
  --paper: #FFFDF8; /* warm off-white — the default page ground */
  --paper-raised: #FFFDF8; /* cards sit on the same ground; a hairline defines them, not a fill */
  --paper-sunken: #F7F4ED; /* recessed bands and alternating sections */
  --white: #FFFFFF;

  /* ---------- Signal green: correspondence, active, mapped ---------- */
  --green-050: #E4F7EE;
  --green-100: #C0EFDB;
  --green-300: #61DDAD;
  --green-500: #00C87F; /* base signal */
  --green-600: #00A76A;
  --green-700: #00784D; /* text-safe on paper */
  --green-900: #0A452E;
  --green-950: #052E1F;

  /* ---------- Warm red: transformation, attention, destructive ---------- */
  --coral-050: #FDEDE9;
  --coral-100: #FAD5CB;
  --coral-300: #F19980;
  --coral-500: #E8452C; /* base */
  --coral-600: #C63821;
  --coral-700: #9E2B18; /* text-safe on paper */
  --coral-950: #3A130C;

  /* ---------- Semantic surfaces ---------- */
  --surface-page: var(--paper);
  --surface-card: var(--paper-raised);
  --surface-sunken: var(--paper-sunken);
  --surface-inverse: var(--ink-000);
  --surface-accent: var(--green-050);
  --surface-alert: var(--coral-050);

  /* ---------- Semantic text ---------- */
  --text-primary: var(--ink-000);
  --text-secondary: var(--ink-700);
  --text-tertiary: var(--ink-500);
  --text-inverse: var(--paper);
  --text-accent: var(--green-700);
  --text-alert: var(--coral-700);
  --text-link: var(--ink-000);

  /* ---------- Lines. The system is built from lines, not boxes ---------- */
  --line-hair: #E2DDD0; /* 1px dividers, table rules */
  --line: #CFC9BA; /* component borders */
  --line-strong: var(--ink-000); /* emphasis rules, graph edges */
  --line-accent: var(--green-500);
  --line-alert: var(--coral-500);
  --line-inverse: rgba(247, 244, 237, 0.22);

  /* ---------- Node fills (graph language) ---------- */
  --node-default: var(--ink-000);
  --node-open: var(--paper);
  --node-mapped: var(--green-500);
  --node-changed: var(--coral-500);

  /* ---------- States ---------- */
  --focus-ring: var(--green-500);
  --state-hover-ink: rgba(11, 11, 10, 0.05);
  --state-press-ink: rgba(11, 11, 10, 0.1);
  --state-hover-inverse: rgba(247, 244, 237, 0.12);
  --state-disabled-text: var(--ink-400);

  /* ---------- Status ---------- */
  --status-live: var(--green-500);
  --status-review: var(--coral-500);
  --status-draft: var(--ink-400);
  --status-retired: var(--ink-300);
}

/* Inverse scope: any element carrying data-theme="inverse" flips the
   semantic aliases. Used for footers, dark hero panels, code surfaces. */
[data-theme="inverse"] {
  --surface-page: var(--ink-000);
  --surface-card: var(--ink-900);
  --surface-sunken: #060605;
  --surface-accent: rgba(0, 200, 127, 0.12);
  --surface-alert: rgba(232, 69, 44, 0.14);
  --text-primary: var(--paper);
  --text-secondary: var(--ink-300);
  --text-tertiary: var(--ink-500);
  --text-inverse: var(--ink-000);
  --text-accent: var(--green-300);
  --text-alert: #F19980;
  --text-link: var(--paper);
  --line-hair: rgba(247, 244, 237, 0.14);
  --line: rgba(247, 244, 237, 0.24);
  --line-strong: var(--paper);
  --node-default: var(--paper);
  --node-open: var(--ink-000);
}
