/* ==========================================================================
   Forrest Obnamia — design tokens  v3
   GENERATED from brand/02-identity/tokens.json. Do not edit by hand.
   Import at the very top of every stylesheet.

   v3 CHANGES
   - Space Grotesk replaces Fraunces. Display face is now a proportional sans
     derived from a monospace — the technical feel is structural, not applied.
   - EDGE LAYER added: shape, density, and label treatment as tokens. Level 2
     (medium) is active; 1 and 3 are preserved for a future swap.
   - Panel surface model: page is one step darker/lighter than raised, so panels
     read as raised without leaning on shadow.

   RULE: components reference semantic + edge tokens only. Never the raw palette.
   ========================================================================== */

/* ─── RAW PALETTE — fixed, never themed ─────────────────────────────────── */
:root{
  --ink-950:#08090C; --ink-900:#0B0D10; --ink-800:#12161B; --ink-700:#222A32;
  --ink-600:#333C46; --ink-500:#1A1F26; --ink-400:#7A8595; --ink-200:#A8B2BF;
  --ink-100:#D6DCE4; --ink-000:#F5F7FA;

  --paper-000:#FFFFFF; --paper-100:#EDEFF3; --paper-200:#DFE3E9;
  --paper-300:#C6CDD7; --paper-400:#5F6874; --paper-700:#4A535F; --paper-800:#22282F;

  --brand:#C08D3C; --brand-light:#D9A85C; --brand-dark:#8A6425;

  --money:#3E9E76;    --money-light:#5FBE95;    --money-dark:#2A6E52;
  --water:#4A96C8;    --water-light:#74B4DE;    --water-dark:#31688C;
  --mind:#8E7BD6;     --mind-light:#AB9CE6;     --mind-dark:#63549E;
  --spirit:#C2618F;   --spirit-light:#D986AE;   --spirit-dark:#8E4266;
  --research:#7C8FA6; --research-light:#9DAEC2; --research-dark:#55677C;

  /* ─── TYPE ─── */
  --font-display:'Space Grotesk','Helvetica Neue',Arial,sans-serif;
  --font-body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;

  --text-xs:.80rem; --text-sm:.90rem; --text-base:1rem; --text-lg:1.25rem;
  --text-xl:1.563rem; --text-2xl:1.953rem; --text-3xl:2.441rem;
  --text-4xl:3.052rem; --text-5xl:3.815rem;
  --h1-size:clamp(30px,4.6vw,50px);

  --weight-regular:400; --weight-medium:500; --weight-semibold:600; --weight-bold:700;
  --leading-tight:1.15; --leading-snug:1.3; --leading-normal:1.6; --leading-relaxed:1.75;
  --tracking-tight:-.035em; --tracking-normal:0; --tracking-wide:.06em; --tracking-wider:.14em;
  --measure-prose:68ch; --measure-narrow:52ch; --measure-lede:58ch;

  /* ─── SPACE ─── */
  --space-0:0; --space-1:.25rem; --space-2:.5rem; --space-3:.75rem; --space-4:1rem;
  --space-5:1.5rem; --space-6:2rem; --space-7:3rem; --space-8:4rem;
  --space-9:6rem; --space-10:8rem;

  /* ─── MOTION ─── */
  --duration-fast:120ms; --duration-base:200ms; --duration-slow:360ms;
  --ease-standard:cubic-bezier(.2,0,0,1); --ease-enter:cubic-bezier(0,0,0,1);

  /* ─── LAYOUT ─── */
  --app-max:1340px; --sidebar-w:212px;
  --container-narrow:42rem; --container-base:64rem; --container-wide:80rem;
}

/* ─── EDGE LAYER — level 2 active ───────────────────────────────────────── */
:root{
  --edge-radius:8px;
  --edge-radius-sm:5px;
  --edge-radius-pill:9999px;
  --edge-gap:12px;
  --edge-pad:22px;
  --edge-border:1px;
  --edge-grain:.03;

  --edge-label-family:var(--font-mono);
  --edge-label-size:10px;
  --edge-label-tracking:.14em;
  --edge-label-transform:uppercase;

  --edge-nav-family:var(--font-body);
  --edge-nav-size:14px;
  --edge-nav-transform:none;
  --edge-nav-tracking:0;

  --edge-numeral-family:var(--font-mono);
}
/* Level 1 — minimal. Swap by setting data-edge="1" on <html>. */
[data-edge="1"]{
  --edge-radius:14px; --edge-radius-sm:9px; --edge-gap:16px; --edge-pad:28px; --edge-grain:0;
  --edge-label-family:var(--font-body); --edge-label-size:12px;
  --edge-label-tracking:.02em; --edge-label-transform:none;
  --edge-numeral-family:var(--font-body);
}
/* Level 3 — maximum. */
[data-edge="3"]{
  --edge-radius:0px; --edge-radius-sm:0px; --edge-radius-pill:0px;
  --edge-gap:1px; --edge-pad:20px; --edge-grain:.05;
  --edge-label-size:9px; --edge-label-tracking:.2em;
  --edge-nav-family:var(--font-mono); --edge-nav-size:11px;
  --edge-nav-transform:uppercase; --edge-nav-tracking:.12em;
}

/* ─── SEMANTIC — DARK (default) ─────────────────────────────────────────── */
:root,[data-theme="dark"]{
  color-scheme:dark;
  --surface:var(--ink-950);
  --surface-raised:var(--ink-800);
  --surface-sunken:var(--ink-900);
  --surface-input:var(--ink-500);
  --surface-inverse:var(--paper-100);

  --border:var(--ink-700);
  --border-strong:var(--ink-600);

  --text:var(--ink-100);          /* 14.10:1 */
  --text-strong:var(--ink-000);   /* 18.13:1 */
  --text-muted:var(--ink-200);    /*  9.07:1 */
  --text-faint:var(--ink-400);    /*  5.20:1 */
  --text-inverse:var(--ink-900);

  --accent:var(--brand);
  --accent-hover:var(--brand-light);
  --accent-contrast:var(--ink-900);
  --accent-soft:color-mix(in srgb,var(--accent) 14%,transparent);

  /* Card tint. A pillar card is the surface tinted toward its own accent, so
     one rule paints every pillar and the strength moves with the theme rather
     than being typed into each component.

     Dark is 10%, not the 16% the prototype used. Measured: at 16% the card is
     light enough that accent-coloured link text drops to 4.19:1 against it,
     which fails AA. 10% is the strongest tint that keeps it at 4.5:1. */
  --tint:10%; --tintb:34%;

  --success:#3E9E76; --warning:#D9A441; --danger:#D9534F;

  --shadow-sm:0 1px 2px rgba(0,0,0,.5);
  --shadow-md:0 8px 28px rgba(0,0,0,.35);
  --shadow-lg:0 16px 48px rgba(0,0,0,.55);
  --rule-gradient:linear-gradient(90deg,transparent,var(--accent),transparent);
}

/* ─── SEMANTIC — LIGHT ──────────────────────────────────────────────────── */
[data-theme="light"]{
  color-scheme:light;
  --surface:var(--paper-100);
  --surface-raised:var(--paper-000);
  --surface-sunken:var(--paper-200);
  --surface-input:var(--paper-100);
  --surface-inverse:var(--ink-900);

  --border:var(--paper-200);
  --border-strong:var(--paper-300);

  --text:var(--paper-800);        /* 12.91:1 on page */
  --text-strong:var(--ink-900);   /* 16.90:1 */
  --text-muted:var(--paper-700);  /*  6.77:1 */
  --text-faint:var(--paper-400);  /*  4.91:1 */
  --text-inverse:var(--paper-000);

  --accent:var(--brand-dark);     /*  4.64:1 page · 5.34:1 panel */
  --accent-hover:#6E4F1C;
  --accent-contrast:var(--paper-000);
  --accent-soft:color-mix(in srgb,var(--accent) 10%,transparent);
  --tint:9%; --tintb:26%;

  --success:#2A6E52; --warning:#8A6425; --danger:#B03B37;

  --shadow-sm:0 1px 2px rgba(16,22,30,.05);
  --shadow-md:0 4px 16px rgba(16,22,30,.08);
  --shadow-lg:0 16px 48px rgba(16,22,30,.1);
}

/* OS preference when nothing is stored. Explicit data-theme always wins —
   it is set on <html> before first paint by the inline no-flash script. */
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]):not([data-theme="light"]){
    color-scheme:light;
    --surface:var(--paper-100); --surface-raised:var(--paper-000);
    --surface-sunken:var(--paper-200); --surface-input:var(--paper-100);
    --surface-inverse:var(--ink-900);
    --border:var(--paper-200); --border-strong:var(--paper-300);
    --text:var(--paper-800); --text-strong:var(--ink-900);
    --text-muted:var(--paper-700); --text-faint:var(--paper-400);
    --text-inverse:var(--paper-000);
    --accent:var(--brand-dark); --accent-hover:#6E4F1C;
    --accent-contrast:var(--paper-000);
    --accent-soft:color-mix(in srgb,var(--accent) 10%,transparent);
    --tint:9%; --tintb:26%;
    --success:#2A6E52; --warning:#8A6425; --danger:#B03B37;
    --shadow-sm:0 1px 2px rgba(16,22,30,.05);
    --shadow-md:0 4px 16px rgba(16,22,30,.08);
    --shadow-lg:0 16px 48px rgba(16,22,30,.1);
  }
}

/* ─── PRINT ────────────────────────────────────────────────────────────────
   Paper is white and ink is black. These are not theme colours — they are the
   physical medium, and they do not participate in light/dark. They live here
   rather than in a print block because a colour literal in public.css is a
   build failure, and the reason for that rule holds: a hex in a stylesheet is
   a value nobody can find later. A hex in the token file is the token file
   doing its job.                                                             */
:root { --print-paper:#FFFFFF; --print-ink:#000000; }

/* ─── PILLAR ACCENTS ────────────────────────────────────────────────────────
   data-pillar on a wrapper INSIDE <body>, never on <html>. Both theme variants
   are written explicitly — custom properties resolve on the element where they
   are declared, so a single indirection silently picks the wrong value.        */
[data-pillar="money"]   { --accent:var(--money);   --accent-hover:var(--money-light);   --accent-contrast:var(--ink-900); }
[data-pillar="body"]    { --accent:var(--water);   --accent-hover:var(--water-light);   --accent-contrast:var(--ink-900); }
[data-pillar="mind"]    { --accent:var(--mind);    --accent-hover:var(--mind-light);    --accent-contrast:var(--ink-900); }
[data-pillar="spirit"]  { --accent:var(--spirit);  --accent-hover:var(--spirit-light);  --accent-contrast:var(--ink-900); }
[data-pillar="research"]{ --accent:var(--research);--accent-hover:var(--research-light);--accent-contrast:var(--ink-900); }
/* Two accents named by their TOKEN rather than by a pillar, added in 2.19 for
   ops/modules.yml. Nothing new was invented: `brand` is the default accent
   given a name so a category can ask for it, and `water` is the same token
   [data-pillar="body"] already uses, named so The Bridge and Trading can carry
   distinct colours without either of them pretending to be a pillar. Four
   categories, four colours; two of them were `money` before this. */
/* ─── SERIES ───────────────────────────────────────────────────────────────
   A two-series chart needs a second identity colour. This set has ONE accent
   plus three statuses, and a status colour must never impersonate a series —
   a line that is amber because it is the second series reads as a warning.

   ALIASES, not new values: --series-2 is the existing brand amber, named
   semantically so a chart component never reaches for var(--brand) directly.
   That is the bug this stylesheet's own comment already records — hub
   components aliased palette values, went dark-only unnoticed, and rendered
   at 1.86:1 on the themed shell.

   Measured against --surface-raised in both themes: dark ΔE 19.6 CVD /
   22.1 normal, light ΔE 15.4 / 17.6. Both clear of the 15 floor.           */
[data-pillar="water"]  { --series-1:var(--accent); --series-2:var(--brand);
                         --series-1-soft:color-mix(in srgb,var(--accent) 45%,transparent); }
[data-theme="light"] [data-pillar="water"] { --series-2:var(--brand-dark); }
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) [data-pillar="water"] { --series-2:var(--brand-dark); }
}

[data-pillar="brand"]   { --accent:var(--brand);   --accent-hover:var(--brand-light);   --accent-contrast:var(--ink-900); }
[data-pillar="water"]   { --accent:var(--water);   --accent-hover:var(--water-light);   --accent-contrast:var(--ink-900); }

[data-theme="light"] [data-pillar="money"]   { --accent:var(--money-dark);   --accent-hover:var(--money);   --accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="body"]    { --accent:var(--water-dark);   --accent-hover:var(--water);   --accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="mind"]    { --accent:var(--mind-dark);    --accent-hover:var(--mind);    --accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="spirit"]  { --accent:var(--spirit-dark);  --accent-hover:var(--spirit);  --accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="research"]{ --accent:var(--research-dark);--accent-hover:var(--research);--accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="brand"]   { --accent:var(--brand-dark);   --accent-hover:var(--brand);   --accent-contrast:var(--paper-000); }
[data-theme="light"] [data-pillar="water"]   { --accent:var(--water-dark);   --accent-hover:var(--water);   --accent-contrast:var(--paper-000); }

@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) [data-pillar="money"]   { --accent:var(--money-dark);   --accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="body"]    { --accent:var(--water-dark);   --accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="mind"]    { --accent:var(--mind-dark);    --accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="spirit"]  { --accent:var(--spirit-dark);  --accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="research"]{ --accent:var(--research-dark);--accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="brand"]   { --accent:var(--brand-dark);   --accent-contrast:var(--paper-000); }
  :root:not([data-theme="dark"]) [data-pillar="water"]   { --accent:var(--water-dark);   --accent-contrast:var(--paper-000); }
}

/* ─── THEME TRANSITION ──────────────────────────────────────────────────────
   Colour only. .theme-switching is added for ~240ms by the toggle script so the
   swap animates without every hover also animating.                            */
.theme-switching,.theme-switching *,.theme-switching *::before,.theme-switching *::after{
  transition:background-color var(--duration-base) var(--ease-standard),
             border-color var(--duration-base) var(--ease-standard),
             color var(--duration-base) var(--ease-standard),
             fill var(--duration-base) var(--ease-standard)!important;
}

/* ─── GRAIN ─────────────────────────────────────────────────────────────── */
body::after{
  content:'';position:fixed;inset:0;pointer-events:none;z-index:1;opacity:var(--edge-grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ─── ACCESSIBILITY ─────────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important; animation-iteration-count:1!important;
    transition-duration:.01ms!important; scroll-behavior:auto!important;
  }
  [data-reveal]{opacity:1!important;transform:none!important}
  body::after{display:none}
  .tick{animation:none!important}
}

:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
  border-radius:var(--edge-radius-sm);
}
