/* =========================================================================
   ClarusTech — design tokens
   Generated from DESIGN.md (chain: DESIGN.md -> tokens.json -> this file).
   One file, three practices, two themes. Nothing in the codebase should
   contain a colour, size, or spacing literal that is not defined here.

   Shared verbatim with the StratusWorks build so token fixes port in both
   directions. The base :root accent is the StratusWorks amber; ClarusTech is a
   practice override, which is the mechanism the design handover specifies. Every
   page therefore MUST carry data-practice="clarustech" on <html> — without it the
   site silently renders in the parent's hue. tools/checks.sh asserts it per page.

   Practice theming: set data-practice="clarustech" | "cloudlift" on <html>.
   Colour scheme: prefers-color-scheme by default, overridden by the footer
   appearance control — three radios (#th-auto | #th-light | #th-dark) read with
   :has(), so the override ships as CSS and no script is served (S1, S5). CSS
   has no storage, so the choice lasts for the page it was made on and the
   control's label says so; persisting it needs a cookie, which S7 forbids.
   The data-theme hooks are the same override by attribute.
   ========================================================================= */

/* ---- self-hosted faces, latin subset, no third-party origin (S3) ---- */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/archivo-600-v1.woff2') format('woff2');
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/archivo-700-v1.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/instrument-sans-400-v1.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/instrument-sans-600-v1.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-400-v1.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-500-v1.woff2') format('woff2');
}

html {
  color-scheme: light dark;
}

/* An explicit choice has to move the UA's own surfaces too — scrollbars, the
   canvas behind an overscroll, the date picker — or the page and the browser
   chrome around it disagree. Both selectors outrank the bare `html` above on
   specificity, so source order here is not load-bearing. */
html:has(#th-light:checked) {
  color-scheme: light;
}
html:has(#th-dark:checked) {
  color-scheme: dark;
}

:root {
  /* ---- neutral ramp — light (warm, paper-based) ---- */
  --surface-raised:   #FFFEFB;
  --surface:          #F7F5F1;
  --surface-sunken:   #ECE8E0;
  --line:             #D8D3C9;
  --line-strong:      #B9B3A7;
  --text-muted:       #5C564C;  /* 6.6:1 on --surface — one step up from #6B6459,
                                   which was comfortable only on a good display */
  --text-secondary:   #4A4F55;  /* 7.6:1 on --surface */
  --text:             #16181A;
  --connector:        #A8815F;  /* diagram rules only */

  /* ---- accent — StratusWorks (amber), light theme ---- */
  --accent:           #A44E13;  /* 5.2:1 on --surface, 4.7:1 on --surface-sunken */
  --accent-hover:     #8A400E;
  --accent-contrast:  #F7F5F1;  /* text on an accent ground */
  --accent-tint:      #F6EADD;
  --accent-tint-line: #E4CDB4;
  --accent-fill:      #C4611C;  /* strata fills, nodes — no contrast minimum */

  /* ---- inverse ground — the graphite emphasis band and the footer ----
     Light theme: a graphite island on a paper page. The accent switches to its
     light-ground partner because #A44E13 on graphite measures 3.1:1 and fails;
     #E08A3C measures 6.7:1. This is the "every accent is a pair" rule, applied
     within a single theme rather than between two. */
  --inverse-surface:         #16181A;
  --inverse-raised:          #202427;
  --inverse-line:            #303335;
  --inverse-text:            #DDE2E4;
  --inverse-secondary:       #AEB5B9;
  --inverse-muted:           #A7AEB2;
  --inverse-accent:          #E08A3C;
  --inverse-accent-hover:    #F0A45C;
  --inverse-accent-contrast: #16181A;

  /* ---- status — shared by all practices ---- */
  --positive:         #2C6E32;
  --caution:          #7A5E0F;
  --critical:         #A03530;

  /* ---- type ---- */
  --font-display: 'Archivo', system-ui, sans-serif;
  --font-body:    'Instrument Sans', system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;

  --text-display: clamp(2.1875rem, 1.329rem + 3.52vw, 4.5rem); /* 35 → 72 */
  --text-h2:      clamp(1.8125rem, 1.557rem + 1.05vw, 2.5rem); /* 29 → 40 */
  --text-h3:      clamp(1.1875rem, 1.12rem + 0.3vw, 1.375rem); /* 19 → 22 */
  --text-lead:    clamp(1.0625rem, 1rem + 0.28vw, 1.25rem);    /* 17 → 20 */
  --text-body:    1.0625rem;   /* 17px — fixed, never fluid, every device */
  --text-small:   0.9375rem;   /* 15px */
  --text-code:    0.8125rem;   /* 13px mono */
  --text-marker:  0.71875rem;  /* 11.5px mono, 0.16em tracking, uppercase */
  --text-metric:  1.75rem;     /* 28px mono — the "after" value of a metric pair */

  --leading-display: 1.02;
  --leading-h2:      1.12;
  --leading-h3:      1.2;
  --leading-body:    1.6;
  --tracking-display: -0.04em;
  --tracking-h2:      -0.032em;
  --tracking-h3:      -0.025em;
  --tracking-marker:   0.16em;
  --measure: 32em;  /* ≈64 characters — em, never px */

  /* ---- spacing — 8px base, ten steps, no value outside them ---- */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  24px;
  --space-6:  32px;
  --space-7:  48px;
  --space-8:  64px;
  --space-9:  96px;
  --space-10: 128px;

  /* section rhythm — the measures that shrink with the viewport.
     Values match the handover table at 1440 / 768 / 390. */
  --container: 1240px;
  --section-padding: clamp(40px, 5.6vw, 80px); /* 80 / 56 / 40 — 17% tighter
                                                  than the handover table; the hero
                                                  keeps the original via --hero-padding */
  --hero-padding: clamp(48px, 7vw, 96px);      /* 96 / 64 / 48 */
  --container-margin: clamp(20px, 3vw, 32px);  /* 32 / 24 / 20 */
  --gutter: clamp(16px, 2vw, 32px);            /* 32 / 20 / 16 */
  --head-gap: clamp(24px, 3.5vw, 48px);        /* 48 / 32 / 24 */
  --card-padding: clamp(20px, 2.5vw, 24px);    /* 24 / 24 / 20 */
  --grid-gap: clamp(12px, 1.5vw, 16px);        /* 16 / 16 / 12 */

  /* ClarusTech's two signature measures. The hanging label column is what makes
     this practice's pages read as a review document rather than a brochure: the
     section number sits BESIDE the heading instead of above it. Both are fixed
     px on purpose — they size a label, not a column of prose, so they must not
     grow with the viewport. They collapse instead, below 900px. */
  --margin-label: 190px;  /* section number column, left of the heading */
  --term-column:  170px;  /* mono term column of the review-document table */

  /* ---- other ---- */
  --radius: 0;                 /* there is no border radius in this system */
  --shadow: none;              /* there are no shadows either */
  --focus-ring: 2px solid var(--text);
  --focus-offset: 2px;
  --duration-state: 120ms;
  --duration-reveal: 400ms;
  --easing: cubic-bezier(.2,.7,.3,1);
  --target-min: 44px;
}

/* ---- practice hues, light theme ----
   The base :root above already carries the StratusWorks amber, so restating it
   here looks redundant — it is not. On a page whose <html> sets
   data-practice="clarustech", the override wins at :root and every descendant
   inherits blue, which makes data-practice="stratusworks" on a nested sibling
   lockup a no-op. The parent practice needs a selector of its own to be
   reachable from inside a themed page. Any change to the amber values above must
   be made here too; tools/checks.sh asserts the two agree. */
[data-practice="stratusworks"] {
  --accent:           #A44E13;
  --accent-hover:     #8A400E;
  --accent-tint:      #F6EADD;
  --accent-tint-line: #E4CDB4;
  --accent-fill:      #C4611C;
  --connector:        #A8815F;
  --inverse-accent:       #E08A3C;
  --inverse-accent-hover: #F0A45C;
  --inverse-accent-contrast: #16181A;
}
[data-practice="clarustech"] {
  --accent:           #1F6B4A;  /* 5.9:1 on --surface */
  --accent-hover:     #17553A;
  --accent-tint:      #E5F2EB;
  --accent-tint-line: #BFDECD;
  --accent-fill:      #1F6B4A;
  /* The warm tan connector belongs to the amber practice; beside a green accent it
     reads as a second colour system. Retuned to the same VISIBILITY, not the same
     hue: 3.43:1 on paper against StratusWorks' 3.23:1 and CloudLift's 3.39:1. The
     handover supplies no connector for this practice at all, and the one it does
     supply for CloudLift measures 1.77:1 and disappears at 1px, so matching a
     measured ratio rather than a published hex is the rule here. */
  --connector:        #57906F;
  --inverse-accent:       #6FC49A;  /* 8.0:1 on graphite */
  --inverse-accent-hover: #8FD6B2;
  --inverse-accent-contrast: #0F1214;
}
[data-practice="cloudlift"] {
  --accent:           #1D5C86;  /* 5.9:1 on --surface */
  --accent-hover:     #164A6D;
  --accent-tint:      #E6EFF6;
  --accent-tint-line: #C2D9E9;
  --accent-fill:      #1D5C86;
  --connector:        #5F8AA8;
  --inverse-accent:       #74AED6;  /* 8.5:1 on graphite */
  --inverse-accent-hover: #93C2E2;
  --inverse-accent-contrast: #0F1214;
}

/* =========================================================================
   Dark theme — authored, not inverted.
   Cooler neutrals; text stops short of paper-white to cut halation;
   elevation reverses (raised surfaces move toward light).

   The two identical value sets below are the Widely Available pattern:
   one for the system preference, one for an explicit choice (data-theme, or
   the footer control's #th-dark radio, which is the same override by another
   hook). light-dark() would dedupe them but is only Newly Available.

   :not(:has(#th-light:checked)) makes choosing Light stop this block from
   applying, so the base :root palette shows through. Restating the light values
   here would put a third copy of them in the file to drift against.
   ========================================================================= */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not(:has(#th-light:checked)) {
    --surface-raised:   #202427;
    --surface:          #16181A;
    --surface-sunken:   #0C0E0F;  /* a wider step from --surface: dark needs more
                                     separation than light to read as a ground change */
    --line:             #303335;  /* neutral, not the blue-grey that read as a
                                     second colour system at the top of the page */
    --line-strong:      #454A4D;
    --text-muted:       #A7AEB2;  /* 8.0:1 on --surface */
    --text-secondary:   #AEB5B9;  /* lifted: 6.96:1 cleared AA but read heavy at 20px */
    --text:             #DDE2E4;
    --connector:        #8A6A3E;  /* #6A4E2E measured ~1.6:1 — invisible at 1px */

    --accent:           #E08A3C;  /* 6.7:1 on --surface */
    --accent-hover:     #F0A45C;  /* hover LIGHTENS on dark */
    --accent-contrast:  #16181A;
    --accent-tint:      #2A1B0F;
    --accent-tint-line: #4A3116;
    --accent-fill:      #E08A3C;

    --positive:         #7FCB86;
    --caution:          #D9B44A;
    --critical:         #E8918B;

    /* The page is already graphite, so the band cannot invert — but it must not
       recede onto --surface-sunken either, or the emphasis band and the
       alternating bands become the same colour and the page loses a ground.
       It rises instead, which is the same direction elevation moves on dark. */
    --inverse-surface:  #202427;
    --inverse-raised:   #2A2F33;
    --inverse-line:     #454A4D;

    --focus-ring: 2px solid var(--text);
  }
  /* A DESCENDANT selector, not :root itself: the amber has to land on a nested
     sibling lockup. It still carries the same two :not() guards as every other
     block here — without them it would outrank the light values above on source
     order alone and the sibling mark would stay dark after choosing Light. */
  :root:not([data-theme="light"]):not(:has(#th-light:checked)) [data-practice="stratusworks"] {
    --accent:           #E08A3C;
    --accent-hover:     #F0A45C;
    --accent-contrast:  #16181A;
    --accent-tint:      #2A1B0F;
    --accent-tint-line: #4A3116;
    --accent-fill:      #E08A3C;
    --connector:        #8A6A3E;
  }
  /* Each practice needs TWO selectors: the compound one for when the practice is
     the page's own (data-practice on <html>), and the descendant one for a nested
     sibling lockup. Without the descendant form, a footer lockup marked
     data-practice="cloudlift" falls through to the LIGHT cloudlift block above
     and renders a light-theme green on a dark page. That shipped as a live defect
     in the sibling build, where the footer nests two practice lockups and neither
     followed the dark theme; it was invisible because each hue still looked
     plausible on its own. Keep both selectors for every practice. */
  :root:not([data-theme="light"]):not(:has(#th-light:checked))[data-practice="clarustech"],
  :root:not([data-theme="light"]):not(:has(#th-light:checked)) [data-practice="clarustech"] {
    --accent:           #6FC49A;
    --accent-hover:     #8FD6B2;
    --accent-contrast:  #0F1214;
    --accent-tint:      #0E2820;
    --accent-tint-line: #1B4534;
    --accent-fill:      #6FC49A;
    --connector:        #417F60;  /* 3.75:1 on --surface, matching the amber 3.57:1 */
  }
  :root:not([data-theme="light"]):not(:has(#th-light:checked))[data-practice="cloudlift"],
  :root:not([data-theme="light"]):not(:has(#th-light:checked)) [data-practice="cloudlift"] {
    --accent:           #74AED6;
    --accent-hover:     #93C2E2;
    --accent-contrast:  #0F1214;
    --accent-tint:      #0F2635;
    --accent-tint-line: #1C4257;
    --accent-fill:      #74AED6;
    --connector:        #4A7699;
  }
}

:root[data-theme="dark"],
:root:has(#th-dark:checked) {
  --surface-raised:   #202427;
  --surface:          #16181A;
  --surface-sunken:   #0C0E0F;
  --line:             #303335;
  --line-strong:      #454A4D;
  --text-muted:       #A7AEB2;
  --text-secondary:   #AEB5B9;
  --text:             #DDE2E4;
  --connector:        #8A6A3E;

  --accent:           #E08A3C;
  --accent-hover:     #F0A45C;
  --accent-contrast:  #16181A;
  --accent-tint:      #2A1B0F;
  --accent-tint-line: #4A3116;
  --accent-fill:      #E08A3C;

  --positive:         #7FCB86;
  --caution:          #D9B44A;
  --critical:         #E8918B;

  --inverse-surface:  #202427;
  --inverse-raised:   #2A2F33;
  --inverse-line:     #454A4D;

  --focus-ring: 2px solid var(--text);
}
:root[data-theme="dark"] [data-practice="stratusworks"],
:root:has(#th-dark:checked) [data-practice="stratusworks"] {
  --accent:           #E08A3C;
  --accent-hover:     #F0A45C;
  --accent-contrast:  #16181A;
  --accent-tint:      #2A1B0F;
  --accent-tint-line: #4A3116;
  --accent-fill:      #E08A3C;
  --connector:        #8A6A3E;
}
:root[data-theme="dark"][data-practice="clarustech"],
:root:has(#th-dark:checked)[data-practice="clarustech"],
:root[data-theme="dark"] [data-practice="clarustech"],
:root:has(#th-dark:checked) [data-practice="clarustech"] {
  --accent:           #6FC49A;
  --accent-hover:     #8FD6B2;
  --accent-contrast:  #0F1214;
  --accent-tint:      #0E2820;
  --accent-tint-line: #1B4534;
  --accent-fill:      #6FC49A;
  --connector:        #417F60;
}
:root[data-theme="dark"][data-practice="cloudlift"],
:root:has(#th-dark:checked)[data-practice="cloudlift"],
:root[data-theme="dark"] [data-practice="cloudlift"],
:root:has(#th-dark:checked) [data-practice="cloudlift"] {
  --accent:           #74AED6;
  --accent-hover:     #93C2E2;
  --accent-contrast:  #0F1214;
  --accent-tint:      #0F2635;
  --accent-tint-line: #1C4257;
  --accent-fill:      #74AED6;
  --connector:        #4A7699;
}

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