/* =========================================================================
   StratusWorks — 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.

   Practice theming: set data-practice="cloudlift" | "clarustech" 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 */

  /* ---- 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 ---- */
[data-practice="cloudlift"] {
  --accent:           #1D5C86;  /* 6.6:1 on --surface */
  --accent-hover:     #164A6D;
  --accent-tint:      #E6EFF6;
  --accent-tint-line: #C2D9E9;
  --accent-fill:      #1D5C86;
  --inverse-accent:       #74AED6;  /* 7.4:1 on graphite */
  --inverse-accent-hover: #93C2E2;
  --inverse-accent-contrast: #0F1214;
}
[data-practice="clarustech"] {
  --accent:           #1F6B4A;  /* 5.9:1 on --surface */
  --accent-hover:     #17553A;
  --accent-tint:      #E5F2EB;
  --accent-tint-line: #BFDECD;
  --accent-fill:      #1F6B4A;
  --inverse-accent:       #6FC49A;  /* 8.5:1 on graphite */
  --inverse-accent-hover: #8FD6B2;
  --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);
  }
  :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;
  }
  :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;
  }
}

: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="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;
}
: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;
}

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