/* =========================================================================
   OAT — theme.css
   Canonical design tokens. Source of truth for Claude Code.
   ============================================================================
   Aesthetic premise (from OAT-Design-Brief-for-Claude-Design.md):
     "Expressive at the frame, calm at the core."
     A natural-history museum, not an art gallery.
     Warm grays + sampled logo blue. Green is a rare spice.
   ============================================================================

   FOR CLAUDE CODE — this file is the contract.
   ─────────────────────────────────────────────────────────────────────────
   Every page on the site reads tokens from this file. No component carries
   hardcoded color, spacing, or motion. If you find yourself writing a hex
   or a px value in component CSS, the right move is almost always to
   reach for an existing token, or add one here.

   Token strata (top → bottom of file):
     1. Primitives        brand swatches, raw scale steps (--blue-500, etc)
     2. Semantic aliases  --surface, --text-body, --link  (what components use)
     3. Composition       --focus-ring, --rule-hairline, --card-bg, --density
                          (derived dials, what the user + you negotiate over)
     4. Mode overrides    [data-theme="dark"], [data-palette="linen"], etc

   The "I'm tired of the color scheme" workflow:
     a) The user opens system.html and pulls dials in the Tweaks panel.
        Their session values land in the EDITMODE JSON block inside
        assets/js/system-tweaks.jsx (host rewrites that file on drag).
     b) When the user says "commit my tweaks," read that JSON, follow
        the TWEAK KEY → TOKEN map at the top of system-tweaks.jsx, and
        edit BOTH theme.css (the new permanent values) and the EDITMODE
        block (so the panel's baseline matches).
     c) After committing, every page reflects the new look on next load —
        no component CSS needs to change.

   Composition tokens (the layer 3 dials) are the high-leverage knobs:
   --density rescales every component's padding, --tracking-wide loosens
   every uppercase label, --focus-ring restyles every interactive surface.
   Prefer adding to layer 3 over touching components.
   ============================================================================
*/

/* =========================================================================
   WEBFONTS — self-hosted (Latin subset). Mirrored from Google Fonts on
   2026-05-28 to break the third-party dependency (Doctrine #11 Sovereign
   Vendor Boundary). Fraunces + Source Serif 4 as variable fonts (one file
   each, weight range 300–700), IBM Plex Mono as 3 weight cuts. ~229KB total.
   ========================================================================= */

@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/assets/fonts/fraunces-300-700.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600.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: 'Source Serif 4';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/assets/fonts/source-serif-4-300-700.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;
}

:root {
  /* -- Brand swatches (sampled from the logo PNG) -- */
  --brand-blue-mark:     #1B6FA8;   /* the lit greenhouse blue, used on the logo + signature gradient */
  --brand-blue-deep:     #0E4870;   /* derived for text/link contrast; passes AA on bone */
  --brand-green-spice:   #5BA814;   /* logo leaf green — rare, meaningful */
  --brand-green-deep:    #3F7A0E;   /* darker green for live-data dot text contrast */

  /* -- Blue working scale (derived from --brand-blue-mark) -- */
  --blue-50:  #EEF5FB;
  --blue-100: #D8E8F3;
  --blue-200: #ADCCE2;
  --blue-300: #7AAECF;
  --blue-400: #4990BC;
  --blue-500: #1B6FA8;   /* mark */
  --blue-600: #155A8A;
  --blue-700: #0E4870;   /* text/links */
  --blue-800: #0A3957;
  --blue-900: #062942;

  /* -- Green spice scale -- */
  --green-50:  #F0F7E6;
  --green-300: #9DCB5D;
  --green-500: #5BA814;
  --green-700: #3F7A0E;
  --green-900: #245005;

  /* -- Warm-gray neutrals (stone & ink, never pure) -- */
  /* Bone & Ink (default) — softest paper white, deep warm-black */
  --neutral-50:  #FAF7F2;   /* page surface — "bone" */
  --neutral-100: #F2EEE5;   /* raised surface */
  --neutral-200: #E6E1D6;   /* hairline rules, dividers */
  --neutral-300: #D2CCBE;   /* strong border */
  --neutral-400: #928B7C;   /* offline/hidden values, dashed dividers — 3.17:1 on surface */
  --neutral-500: #7A7468;
  --neutral-600: #57524A;
  --neutral-700: #3C3833;
  --neutral-800: #2A2622;
  --neutral-900: #1A1714;   /* ink */

  /* -- Semantic surfaces & text (light mode) -- */
  --surface:        var(--neutral-50);
  --surface-alt:    var(--neutral-100);
  --surface-raised: #FFFDF8;
  --text-body:      var(--neutral-800);
  --text-heading:   var(--neutral-900);
  --text-muted:     var(--neutral-600);   /* AAA 7.34:1 on surface, AAA 6.78:1 on alt */
  --text-on-primary: #FFFDF8;
  --link:           var(--blue-700);
  --link-hover:     var(--blue-500);
  --border:         var(--neutral-200);
  --border-strong:  var(--neutral-300);

  /* -- Primary/accent aliases -- */
  --primary:        var(--blue-700);
  --primary-dark:   var(--blue-800);
  --primary-darker: var(--blue-900);
  --primary-light:  var(--blue-500);
  --primary-lighter:var(--blue-100);
  --primary-alpha-10: rgba(14, 72, 112, 0.10);
  --primary-alpha-30: rgba(14, 72, 112, 0.30);
  --primary-alpha-50: rgba(14, 72, 112, 0.50);
  --accent:         var(--green-500);
  --accent-light:   var(--green-300);
  --accent-dark:    var(--green-700);

  /* -- Status -- */
  --success:        var(--green-700);
  --success-light:  var(--green-50);
  --warning:        #B58515;
  --warning-light:  #FAF1DC;
  --danger:         #9A3324;
  --danger-light:   #F6E3DE;
  --info:           var(--blue-500);
  --info-light:     var(--blue-50);

  /* -- Signature gradient (use ONLY at the frame, never under text or data) -- */
  --gradient-frame: linear-gradient(110deg, var(--brand-green-spice) 0%, var(--brand-blue-mark) 65%, var(--brand-blue-deep) 100%);
  --gradient-frame-soft: linear-gradient(110deg, rgba(91,168,20,0.10) 0%, rgba(27,111,168,0.12) 100%);

/* =====================================================================
     TYPOGRAPHY
     All-serif system. Two contrasting serifs + functional mono for data.
     Reading: Source Serif (screen-confident at body scale)
     Display: Fraunces (warm, optical, natural-history character)
     Data:    IBM Plex Mono (functional signal, not a third stylistic voice)
     ===================================================================== */
  --font-display: "Fraunces", "Source Serif 4", Georgia, "Times New Roman", serif;
  --font-reading: "Source Serif 4", "Source Serif Pro", Georgia, "Times New Roman", serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, "SF Mono", "Menlo", monospace;

  /* Type scale — modular, ~1.22 ratio; large display steps for set-pieces */
  --size-display-xl: clamp(3.5rem, 7vw, 6.5rem);   /* set-piece hero */
  --size-display-lg: clamp(2.75rem, 5vw, 4.25rem); /* page H1 */
  --size-h1:    clamp(2rem, 3.2vw, 2.75rem);
  --size-h2:    clamp(1.5rem, 2.2vw, 1.875rem);
  --size-h3:    clamp(1.2rem, 1.6vw, 1.375rem);
  --size-h4:    1.0625rem;
  --size-lead:  clamp(1.25rem, 1.6vw, 1.5rem);
  --size-body:  1.0625rem;     /* 17px reading default */
  --size-small: 0.9375rem;     /* 15px */
  --size-tiny:  0.8125rem;     /* 13px */
  --size-button: 1rem;
  --size-eyebrow: 0.75rem;     /* uppercase data labels */

  --weight-display: 380;       /* Fraunces variable — gentle warmth */
  --weight-h1: 500;
  --weight-h2: 500;
  --weight-h3: 600;
  --weight-h4: 600;
  --weight-body: 400;
  --weight-bold: 600;
  --weight-button: 500;

  --lh-display: 1.04;
  --lh-h1: 1.12;
  --lh-h2: 1.2;
  --lh-h3: 1.3;
  --lh-body: 1.65;     /* generous for long-form */
  --lh-tight: 1.3;

  /* Reading measure — narrow column for 10-30k word pages */
  --measure: 68ch;

  /* =====================================================================
     SHAPE
     Small radii. The museum is square-on; rounded is rare.
     ===================================================================== */
  --radius-sm:   3px;
  --radius-base: 6px;
  --radius-lg:   10px;
  --radius-xl:   16px;
  --radius-full: 999px;

  --border-thin:  1px;
  --border-base:  1px;
  --border-heavy: 2px;

  /* Shadows — restrained, paper-not-plastic */
  --shadow-sm: 0 1px 2px rgba(26, 23, 20, 0.04), 0 1px 1px rgba(26,23,20,0.03);
  --shadow-base: 0 2px 6px rgba(26, 23, 20, 0.05), 0 1px 2px rgba(26,23,20,0.04);
  --shadow-md: 0 6px 18px rgba(26, 23, 20, 0.07), 0 2px 4px rgba(26,23,20,0.04);
  --shadow-lg: 0 16px 40px rgba(26, 23, 20, 0.10), 0 4px 10px rgba(26,23,20,0.05);
  --shadow-xl: 0 32px 80px rgba(26, 23, 20, 0.14);
  --shadow-inner: inset 0 1px 2px rgba(26,23,20,0.04);

  /* =====================================================================
     SPACE
     space-1..3 stay raw (tight gaps shouldn't shift with density).
     space-4..7 multiply by --density — these are the "breathing" tokens
     every component padding/gap reaches for. Pull --density (defined in
     COMPOSITION TOKENS below) to inflate or compress the whole site.
     space-8..10 stay raw (structural macro-spacing).
     ===================================================================== */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: calc(1rem    * var(--density, 1));
  --space-5: calc(1.5rem  * var(--density, 1));
  --space-6: calc(2rem    * var(--density, 1));
  --space-7: calc(3rem    * var(--density, 1));
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;

  --spacing-section: calc(clamp(4rem, 8vw, 7rem) * var(--density, 1));
  --spacing-block:   calc(clamp(2rem, 4vw, 3.5rem) * var(--density, 1));
  --spacing-inline:  clamp(1.5rem, 3vw, 2rem);

  --content-width: 72rem;
  --site-width:    84rem;
  --reading-width: 38rem;     /* ~68ch at 17px Source Serif */

  /* =====================================================================
     GLASS — chrome material (frame only, never under reading content)
     Calibrated "subtle" per brief §5/§9.4.
     ===================================================================== */
  --glass-bg:        rgba(250, 247, 242, 0.72);
  --glass-blur:      12px;
  --glass-saturate:  1.1;
  --glass-border:    rgba(27, 111, 168, 0.12);   /* faint logo-blue tint */
  --glass-shadow:    0 1px 0 rgba(255,255,255,0.6) inset, 0 8px 24px rgba(26,23,20,0.06);

  /* =====================================================================
     MOTION — purposeful, never gratuitous.
     ===================================================================== */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.45, 0, 0.55, 1);
  --dur-fast: 140ms;
  --dur-base: 240ms;
  --dur-slow: 480ms;

  /* =====================================================================
     COMPOSITION TOKENS — the design dials components reach for.
     Each composes lower-level primitives. Tune these to change a feeling
     site-wide without touching component CSS. This is where the user +
     CC negotiate look-and-feel.
     ===================================================================== */

  /* Brand RGB triplets — for rgba() composition (focus rings, soft tints) */
  --brand-blue-rgb:  27, 111, 168;
  --brand-green-rgb: 91, 168, 20;
  --ink-rgb:         26, 23, 20;

  /* Tracking (letter-spacing) — pulled out so every named role is tunable */
  --tracking-tight: -0.02em;    /* big display */
  --tracking-snug:  -0.01em;    /* h1 */
  --tracking-base:  -0.005em;   /* h2 / display sub */
  --tracking-flat:   0;          /* body */
  --tracking-loose:  0.04em;    /* small mono numerals */
  --tracking-wide:   0.12em;    /* eyebrow */
  --tracking-mono:   0.14em;    /* tracked mono labels */

  /* Focus ring — every interactive surface reaches for this single dial */
  --focus-ring: 0 0 0 3px rgba(var(--brand-blue-rgb), 0.18);
  --focus-outline: 2px solid var(--brand-blue-mark);
  --focus-offset: 2px;

  /* Rule (border) primitives — the role becomes the token */
  --rule-hairline: 1px solid var(--border);
  --rule-strong:   1px solid var(--border-strong);
  --rule-dashed:   1px dashed var(--border);
  --rule-divider:  1px dashed var(--border-strong);

  /* Card / surface primitives */
  --card-bg:        var(--surface);
  --card-bg-raised: var(--surface-raised);
  --card-border:    var(--rule-hairline);
  --card-pad:       var(--space-5);
  --card-pad-tight: var(--space-4);

  /* Density multiplier — one number, whole-site breathing room.
     1 = default · 0.85 = compact · 1.25 = airy. Components multiply: 
     padding: calc(var(--card-pad) * var(--density)); */
  --density: 1;

  /* Hover primitives */
  --hover-tint:   var(--surface-alt);    /* the bg a hovered card becomes */
  --hover-accent: var(--brand-blue-deep);/* the color hovered text shifts to */
  --hover-shift:  1px;                    /* y-shift on :active */

  /* Code panel theme — one place for the dark-on-warm-gray code aesthetic */
  --code-bg:      var(--neutral-900);
  --code-fg:      #E8E2D6;
  --code-comment: var(--neutral-500);
  --code-accent:  var(--blue-300);
  --code-string:  var(--green-300);

  /* Layer scale — ordered visual hierarchy (e.g. fundamentals stack layers) */
  --layer-1: var(--brand-green-spice);  /* foundational */
  --layer-2: var(--blue-400);            /* derived */
  --layer-3: var(--brand-blue-mark);     /* working */
  --layer-4: var(--brand-blue-deep);     /* terminal */

  /* Status — dark variants (hover, pressed, focused) */
  --danger-dark:  #7E2A1E;
  --warning-dark: #8E6810;
  --success-dark: var(--green-900);

  /* Iconography */
  --icon-stroke: 1.8;
  --icon-sm: 14px;
  --icon-md: 18px;
  --icon-lg: 24px;
}

/* =========================================================================
   DARK MODE — field-glare friendly. Same chroma, inverted lightness.
   ========================================================================= */
[data-theme="dark"] {
  --surface:        #14110E;       /* deep warm-black surface */
  --surface-alt:    #1C1815;
  --surface-raised: #221E1A;
  --text-body:      #E8E2D6;
  --text-heading:   #F6F1E5;
  --text-muted:     #9C9482;
  --text-on-primary:#FFFDF8;
  --link:           #7AAECF;       /* lifted for dark */
  --link-hover:     #ADCCE2;
  --border:         #2D2823;
  --border-strong:  #3F3933;

  --primary:        #7AAECF;
  --accent:         #9DCB5D;
  --accent-dark:    #5BA814;

  --glass-bg:       rgba(28, 24, 21, 0.68);
  --glass-border:   rgba(122, 174, 207, 0.18);
  --glass-shadow:   0 1px 0 rgba(255,255,255,0.04) inset, 0 8px 24px rgba(0,0,0,0.4);

  --gradient-frame-soft: linear-gradient(110deg, rgba(91,168,20,0.10) 0%, rgba(27,111,168,0.16) 100%);

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-base: 0 2px 6px rgba(0,0,0,0.4);
  --shadow-md: 0 6px 18px rgba(0,0,0,0.45);
  --shadow-lg: 0 16px 40px rgba(0,0,0,0.55);

  /* Composition tokens that flip for dark */
  --code-bg:      #0A0907;            /* deeper than surface so it reads "code" */
  --code-fg:      var(--text-body);
  --code-comment: var(--neutral-500);
  --focus-ring:   0 0 0 3px rgba(122, 174, 207, 0.28);
  --hover-tint:   var(--surface-alt);
  --hover-accent: var(--link-hover);
}

/* =========================================================================
   PALETTE VARIANTS — switchable via [data-palette]
   ========================================================================= */
[data-palette="linen"] {
  --neutral-50:  #F7F5F1;
  --neutral-100: #EDEAE3;
  --neutral-200: #DEDAD0;
  --neutral-300: #C7C1B5;
  --neutral-400: #9E988B;
  --neutral-500: #706A5F;
  --neutral-600: #4F4A42;
  --neutral-700: #36322D;
  --neutral-800: #25221E;
  --neutral-900: #161413;
}
[data-palette="parchment"] {
  --neutral-50:  #FBF5E8;
  --neutral-100: #F3EAD4;
  --neutral-200: #E5D8BC;
  --neutral-300: #CFBE9A;
  --neutral-400: #A89572;
  --neutral-500: #786753;
  --neutral-600: #54483A;
  --neutral-700: #3A3127;
  --neutral-800: #28221B;
  --neutral-900: #1A1612;
}

/* =========================================================================
   GLASS INTENSITY VARIANTS
   ========================================================================= */
[data-glass="whisper"]  { --glass-bg: rgba(250,247,242,0.85); --glass-blur: 6px; }
[data-glass="subtle"]   { --glass-bg: rgba(250,247,242,0.72); --glass-blur: 12px; }
[data-glass="tactile"]  { --glass-bg: rgba(250,247,242,0.62); --glass-blur: 20px; }
[data-theme="dark"][data-glass="whisper"]  { --glass-bg: rgba(28,24,21,0.82); }
[data-theme="dark"][data-glass="subtle"]   { --glass-bg: rgba(28,24,21,0.68); }
[data-theme="dark"][data-glass="tactile"]  { --glass-bg: rgba(28,24,21,0.55); }

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
