/* Layer order for index.html: @layer reset, tokens, layout, components, utilities; */

/* @layer tokens — design token definitions */

@layer tokens {

  /* ─────────────────────────────────────────────
     SELF-HOSTED TYPEFACES
     Design-analysis audit (2026-08-17, Medium, Domain 5): every page loaded
     Cinzel/Spectral render-blocking from fonts.googleapis.com with no local
     fallback, despite @fontsource/cinzel and @fontsource/spectral already
     proven correct in the Session 20 hero-verification harness (lessons.md).
     Self-hosted here for real, replacing the Google Fonts <link> pair on
     every page. font-display: swap preserves the same FOUT behavior the
     Google stylesheet's &display=swap param provided. Files live in /fonts/
     (root-relative -- correct from admin/ too, one directory down) and are
     covered by .htaccess's existing woff2 Cache-Control rule, no .htaccess
     change needed.
     ───────────────────────────────────────────── */

  @font-face {
    font-family: 'Cinzel';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/cinzel-latin-400-normal.woff2') format('woff2');
  }

  @font-face {
    font-family: 'Cinzel';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/cinzel-latin-700-normal.woff2') format('woff2');
  }

  /* Cinzel 900 -- badge/token numerals only (Phase 24c, design-analysis
     audit 2026-08-17 Stage 2, author-greenlit). Typography section is
     LOCKED at 400/700 for body copy and headings; this is a deliberate,
     narrow exception scoped to the crown-socket badge SVGs' <text>
     elements specifically (.sage__emblem-badge, .doctrine__stat-badge) --
     a heavier static weight reads as forged/stamped metal rather than
     typeset text. Never applied to --font-heading or any heading-scale
     element. */
  @font-face {
    font-family: 'Cinzel';
    font-style: normal;
    font-weight: 900;
    font-display: swap;
    src: url('/fonts/cinzel-latin-900-normal.woff2') format('woff2');
  }

  @font-face {
    font-family: 'Spectral';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/spectral-latin-400-normal.woff2') format('woff2');
  }

  @font-face {
    font-family: 'Spectral';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/spectral-latin-400-italic.woff2') format('woff2');
  }

  @font-face {
    font-family: 'Spectral';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/spectral-latin-600-normal.woff2') format('woff2');
  }

  /* ─────────────────────────────────────────────
     REGISTERED CUSTOM PROPERTIES
     Enables transitions on these values and type-checks at parse time.
     ───────────────────────────────────────────── */

  @property --color-accent {
    syntax: '<color>';
    inherits: true;
    initial-value: #C8A97E;
  }

  @property --color-bg {
    syntax: '<color>';
    inherits: true;
    initial-value: #0D0A1A;
  }

  :root {

    /* Session 30 (Phase 23 follow-up, author-reported): native form control
       chrome (the <input type="date"> calendar-picker icon, number-input
       spinner arrows) defaults to a dark/light icon set independent of page
       theme, and read as nearly invisible against this site's near-black
       inputs. color-scheme is the standards-track fix -- it tells the
       browser to render its OWN native widget parts in dark mode, which it
       then does automatically and correctly, no custom icon asset needed.
       Set site-wide here (not scoped to one input) since every native
       control on the site shares the same dark theme and would have the
       identical contrast problem. .form-input's own explicit background/
       text/border colors are unaffected -- this only reaches UA-drawn parts
       that CSS doesn't already override directly. */
    color-scheme: dark;

    /* ─────────────────────────────────────────────
       TIER 1 — PRIMITIVE TOKENS
       Raw values. Never consumed directly by components.
       ───────────────────────────────────────────── */

    /* Color primitives */
    --primitive-gray-950:  #0D0A1A;   /* root background — purple-shifted black */
    --primitive-gray-900:  #1E1530;   /* surface / cards */
    --primitive-gray-800:  #2A1F3D;   /* elevated surface */
    --primitive-gray-700:  #3B2C5A;   /* border / divider */
    --primitive-gray-400:  #9999BB;   /* muted text — nudged from #8888AA for WCAG AAA */
    --primitive-gray-200:  #C8C8D8;   /* secondary text */
    --primitive-gray-100:  #E8E8F0;   /* primary body text */
    --primitive-gold-400:  #C8A97E;   /* Gold: earned warmth -- the color of aged iron and lantern light, not trend or decoration. */
    --primitive-gold-300:  #D9C0A0;   /* accent hover */
    --primitive-gold-200:  #EAD8C0;   /* accent active / pressed */
    --primitive-purple-500: #6B5B95;  /* Structural purple — blockquote borders, chips. Whispers, never shouts. */
    --primitive-moonstone-400: #B9C4DE;  /* Moonstone: the lunar/cyclical half of the sun/moon duality (architecture.md's Deeper Register -- Stoic Logos/ekpyrosis, fire and cyclical renewal as one cosmology, not two). Author sign-off 2026-08-31 (Session 59), per creative_direction/creative-direction_2026-08-31.md Section 5. Contrast on file: ~11.2:1 against --color-bg, ~10.0:1 against --color-surface-raised, both AAA (creative_direction/creative-direction_2026-08-28.md; re-run only if this hex ever changes). No Tier 2/3 alias yet -- same convention gold's own gradient stops already follow (see the "Two golds, two jobs" note below): the Lunar Crest and lunar-phase-strip SVGs hardcode their own three-stop gradient (#5A6684 -> #8B9AC0 -> #B9C4DE) directly in markup, matching how .doctrine__stat-badge's gold gradient is built, so nothing yet consumes this as a live CSS custom property. Gradient-only, per the two-golds rule's own moonstone analog: no flat moonstone UI ladder exists or is scoped (foundry/big-swings-log.md, items 2 and 6) -- add Tier 2/3 aliases only once a real interactive surface in this color is scoped, not ahead of that need. */
    --primitive-white:     #FFFFFF;

    /* ─────────────────────────────────────────────
       TIER 2 — SEMANTIC TOKENS
       Meaning-first aliases of primitive values.
       Theme switching happens at this tier only.
       ───────────────────────────────────────────── */

    --color-bg:          var(--primitive-gray-950);
    --color-surface:     var(--primitive-gray-900);
    --color-surface-raised: var(--primitive-gray-800);
    --color-border:      var(--primitive-gray-700);
    --color-accent:      var(--primitive-gold-400);
    --color-accent-hover: var(--primitive-gold-300);
    --color-accent-active: var(--primitive-gold-200);
    --color-accent-purple: var(--primitive-purple-500);

    --color-text-primary:   var(--primitive-gray-100);
    --color-text-secondary: var(--primitive-gray-200);
    --color-text-muted:     var(--primitive-gray-400);
    --color-text-inverse:   var(--primitive-gray-950);

    /* ─────────────────────────────────────────────
       TYPOGRAPHY TOKENS
       Font assignments locked per brand spec.
       Cinzel → headings only. Spectral → all body.
       ───────────────────────────────────────────── */

    --font-heading: 'Cinzel', 'Trajan Pro', serif;
    --font-body:    'Spectral', 'Georgia', serif;

    /* Fluid type scale — golden ratio (φ = 1.618) anchored at 1rem base.
       clamp(min, preferred-fluid, max) */
    --text-base: 1rem;
    --text-sm:   clamp(0.75rem,  1.5vw,  0.875rem);
    --text-md:   clamp(1.125rem, 2vw,    1.618rem);
    --text-lg:   clamp(1.618rem, 3.5vw,  2.618rem);
    --text-xl:   clamp(2.25rem,  5vw,    4.236rem);
    --text-2xl:  clamp(3rem,     7vw,    6.854rem);

    /* Line heights */
    --leading-tight:  1.2;
    --leading-snug:   1.4;
    --leading-normal: 1.6;
    --leading-loose:  1.8;

    /* Letter spacing */
    --tracking-tight:  -0.02em;
    --tracking-normal:  0;
    --tracking-wide:    0.05em;
    --tracking-wider:   0.1em;
    --tracking-widest:  0.2em;

    /* ─────────────────────────────────────────────
       SPACING — 8PT BASELINE GRID
       All spacing values are multiples of 0.5rem (8px at default root).
       ───────────────────────────────────────────── */

    --space-1:  0.5rem;    /*  8px */
    --space-2:  1rem;      /* 16px */
    --space-3:  1.5rem;    /* 24px */
    --space-4:  2rem;      /* 32px */
    --space-6:  3rem;      /* 48px */
    --space-8:  4rem;      /* 64px */
    --space-12: 6rem;      /* 96px */
    --space-16: 8rem;      /* 128px */
    --space-24: 12rem;     /* 192px */

    /* Breakpoints -- reference values only. Use bare values in @media queries.
       --breakpoint-sm:  640px  (40rem)
       --breakpoint-md:  768px  (48rem)
       --breakpoint-lg: 1024px  (64rem)
       --breakpoint-xl: 1280px  (80rem) */

    /* ─────────────────────────────────────────────
       LAYOUT TOKENS
       ───────────────────────────────────────────── */

    --container-max:     72rem;   /* ~1152px — tight, editorial */
    --container-narrow:  48rem;   /* ~768px  — long-form prose */
    --container-wide:    90rem;   /* ~1440px — full bleed sections */
    /* --container-hero was retired in Session 20. It existed to give the hero
       enough width for the tagline (measured: "Forge the Body." is 10.168em in
       Cinzel 700 at --tracking-wide, so 976px at the 6rem cap), but it was set
       to 68rem while every other section uses --container-max at 72rem, which
       put the hero's text edge 32px inside everyone else's and made the whole
       left margin jog on scroll. --container-max already yields 1088px of
       content box after --space-4 padding, comfortably over the 976px needed,
       so the hero now uses the same measure as the rest of the page and the
       token is gone. If --tracking-wide, the heading weight, or the tagline
       text ever change, re-measure that em value against 1088px. */

    /* ─────────────────────────────────────────────
       Z-INDEX SCALE
       Named, never arbitrary.
       ───────────────────────────────────────────── */

    --z-below:   -1;
    --z-base:     0;
    --z-raised:  10;
    --z-nav:    100;
    --z-overlay: 200;
    --z-modal:  300;

    /* ─────────────────────────────────────────────
       TRANSITION TOKENS
       ───────────────────────────────────────────── */

    --duration-fast:    150ms;
    --duration-base:    250ms;
    --duration-slow:    400ms;
    --duration-reveal:  600ms;

    --ease-out:   cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in:    cubic-bezier(0.4, 0, 1, 1);
    --ease-inout: cubic-bezier(0.4, 0, 0.2, 1);

    --transition-color:     color var(--duration-base) var(--ease-out),
                            background-color var(--duration-base) var(--ease-out),
                            border-color var(--duration-base) var(--ease-out);
    --transition-transform: transform var(--duration-base) var(--ease-out);
    --transition-opacity:   opacity var(--duration-reveal) var(--ease-out);

    /* ─────────────────────────────────────────────
       BORDER TOKENS
       ───────────────────────────────────────────── */

    --border-hairline: 1px solid var(--color-border);
    --border-accent:   1px solid var(--color-accent);
    --radius-sm:  2px;
    --radius-md:  4px;
    --radius-lg:  8px;

    /* ─────────────────────────────────────────────
       TIER 3 — COMPONENT TOKENS
       Component-specific aliases of semantic tokens.
       This is the only tier components should consume.
       ───────────────────────────────────────────── */

    /* Navigation */
    --nav-bg:               var(--color-bg);
    --nav-border:           var(--color-border);
    --nav-link-color:       var(--color-text-secondary);
    --nav-link-color-hover: var(--color-accent);
    --nav-link-color-active: var(--color-text-primary);
    --nav-height:           4rem;

    /* Hero */
    --hero-bg:          var(--color-bg);
    --hero-title-color: var(--color-text-primary);
    --hero-sub-color:   var(--color-accent);

    /* Hero decorative stack (Phase 24a/24b). .hero sets `isolation: isolate`,
       so these index inside the hero's own stacking context only and never
       compete with the global --z-* scale. Named rather than bare integers
       for the same reason that scale is named. */
    /* Photographic texture (design-analysis session, 2026-08-23). The
       backmost layer -- behind the light bloom, so it never competes with
       that gradient's own gold. A real element (.hero__texture in
       index.php), not a third pseudo-element on .hero: .hero::before and
       .hero::after are both already spoken for (bloom, vignette), and an
       element only gets one of each. -1 sits safely below every existing
       value here without renumbering anything else in this family. */
    --hero-z-texture:  -1;   /* fog/forest photo, furthest back of all */
    --hero-z-bloom:     0;   /* radial light source, furthest back */
    /* Hero Smoke Effect (design_analysis/phase-hero-smoke-session-prompt-v2.md).
       Sits above bloom, below the mark -- same slot Concept B occupied in the
       reviewed demo. Mark/veil/content renumbered up by one to make room;
       these are symbolic vars referenced only via var(), never as bare
       integers elsewhere, so renumbering is safe. */
    --hero-z-smoke:     1;   /* atmospheric turbulence, sourced at .hero__rule */
    --hero-z-mark:      2;   /* The Forged Crown at monument scale */
    --hero-z-veil:      3;   /* vignette: darkens the mark's edges, not the type */
    /* Golden embers (design-analysis session, 2026-08-23). Above the veil,
       not below it: unlike bloom/smoke/mark, embers are meant to read as
       small, clear points of light against the darkened field the vignette
       creates -- muting them the same way would work against the point.
       Below content: renumbered content up to 5 to make room, same safe
       renumbering this family already used once for smoke (these vars are
       referenced only via var(), never as bare integers elsewhere). */
    --hero-z-embers:    4;   /* rising spark accents, css/js/hero-smoke.js */
    --hero-z-content:   5;   /* eyebrow, headline, lede, CTAs, scroll cue */

    /* Watermark. Opacity is low enough that Spectral crossing the mark still
       clears the AAA contrast the palette reference locked in, and high
       enough that the crown's facets still read as faceted. */
    --hero-mark-opacity:    0.17;
    --hero-shimmer-opacity: 0.22;

    /* Hero Smoke Effect (design_analysis/phase-hero-smoke-session-prompt-v2.md,
       Concept B). Author-approved default from the reviewed demo's slider
       (range 0.04-0.30, judged live around 0.11). Set slightly above that
       middle value since this build's fade stops thin out earlier (55%/82%
       vs. the demo's 72%/100%), leaving less of the layer visible overall. */
    --hero-smoke-opacity:   0.12;

    /* Golden embers (design-analysis session, 2026-08-23). Deliberately NOT
       in the same low range as the washes above (0.10-0.17) -- those are
       large-area atmosphere meant to be felt more than seen; embers are a
       handful of small individual points meant to actually be seen, so
       they're tuned close to full brightness at their peak rather than
       matched to the wash family's restraint. --hero-ember-color aliases
       the semantic gold rather than a new hex, same as every other hero
       component token in this block. */
    --hero-ember-color:        var(--color-accent);
    --hero-ember-opacity-peak: 0.85;

    /* Rhythm (Session 20). Deliberately BELOW --hero-mark-opacity: the crown is
       static and this moves, and motion draws far more attention than form, so
       matching the crown's 0.17 would make the Move section louder than the
       hero. Tune here, not in the component.
       --rhythm-period is locked to move-callout-pulse's 3s. The Move section
       has two gold things animating in it and they must read as one heartbeat
       with two expressions rather than as two effects on separate clocks. */
    --rhythm-opacity:       0.10;
    --rhythm-opacity-peak:  0.14;
    --rhythm-period:        3s;
    --rhythm-travel:        24s;   /* time-based fallback only; see components.css */

    /* Cards */
    --card-bg:          var(--color-surface);
    --card-border:      var(--color-border);
    --card-border-hover: var(--color-accent);
    --card-padding:     var(--space-4);

    /* Buttons */
    --btn-accent-bg:          var(--color-accent);
    --btn-accent-bg-hover:    var(--color-accent-hover);
    --btn-accent-text:        var(--color-text-inverse);
    --btn-ghost-text:         var(--color-accent);
    --btn-ghost-border:       var(--color-accent);
    --btn-ghost-bg-hover:     color-mix(in srgb, var(--color-accent) 10%, transparent);
    --btn-padding-y:          var(--space-2);
    --btn-padding-x:          var(--space-4);

    /* Forms */
    --input-bg:           var(--color-surface);
    --input-border:       var(--color-border);
    --input-border-focus: var(--color-accent);
    --input-text:         var(--color-text-primary);
    --input-placeholder:  var(--color-text-muted);
    --input-padding-y:    var(--space-2);
    --input-padding-x:    var(--space-3);

    /* Discipline section */
    --discipline-grid-min: 280px;
    --discipline-card-accent: var(--color-accent);

    /* Stats / doctrine */
    /* --stat-numeral-color removed Phase 24c: the numeral moved into the
       badge SVG's own gradient fill (see .doctrine__stat-badge), no longer
       a plain-text token consumer. */
    --stat-label-color:   var(--color-text-muted);

    /* Footer */
    --footer-bg:      var(--color-surface);
    --footer-border:  var(--color-border);
    --footer-text:    var(--color-text-muted);

  } /* :root */

} /* @layer tokens */
