/* Normwerk, Rev. B: design tokens. Single source of truth for every page. */

:root {
  /* Color: each accent has exactly one meaning */
  --paper: #f4f1ea;        /* global background */
  --ink: #141311;          /* primary text, CTA labels */
  --graphite: #57544c;     /* secondary text, captions */
  --hairline: #d9d5ca;     /* rules, table borders */
  --werk-orange: #e8520a;  /* action only: CTA blocks, hovers, large numerals */
  --orange-ink: #a33a00;   /* small action text, links, footnote markers */
  --approved: #1e6b43;     /* status only: Available, Shipped, Billable */
  --review: #7a5700;       /* pending only: Manual review, In Development */
  --ink-2: var(--orange-ink); /* page-scoped accent; LV2XL overrides to Ledger Blue #2f4e9e */
  --press-black: #161512;  /* full-section inversion band. See "on dark" below */
  --mount: #fbfaf7;        /* near-white mount inside figure plates */

  /* On dark: the inversion set. Paper stays the page ground; these are for full-bleed
     press-black bands only (proof, studio plate module, closing CTA). Every pairing is
     measured against --press-black:
       paper 16.5:1 · dim 7.3:1 · orange 5.0:1 · approved 6.7:1 · review 5.4:1        */
  --on-dark: var(--paper);       /* primary text on press-black */
  --on-dark-dim: #a8a294;        /* secondary text on press-black */
  --on-dark-rule: #3a372f;       /* hairlines on press-black, non-text boundary */
  --on-dark-orange: #f0670f;     /* action colour lifted to clear AA on press-black */
  --on-dark-approved: #4fae7c;   /* status green, lifted for dark bands */
  --on-dark-review: #c9a227;     /* pending amber, lifted for dark bands */

  /* The living grid. Ambient decoration, never a component, so it is exempt
     from the orange-is-action-only rule.
     Rev. D: 0.045 was invisible at real screen brightness, which is why Max
     said the grid "still has not been added". Doubled to 0.085.
     Rev. F: 0.085 is "too strong", and he asked for minus 60 percent. Taken
     literally that is 0.034, which measures 14 percent WEAKER than the 0.045
     he already rejected: it would reproduce the Rev. D bug one revision later.
     Measured on the real render, loudness is driven by line DENSITY as much as
     by alpha, so the reduction is split across both levers:
       alpha 0.085 -> 0.055  (line ink -35%)
       cell   64px -> 96px   (line population -39%)
     Net field darkening 0.613 -> 0.253, which is 59 percent quieter, the
     reduction he actually asked for. But each individual line still renders 20
     percent ABOVE the rejected 0.045 point, so the grid stays legible AS lines.
     The rule this encodes: pick ambient values against rendered contrast, never
     against authored alpha. --grid-cell is consumed only by .bg-grid; no layout
     aligns to it. */
  --grid-line: rgba(20, 19, 17, 0.055);
  --grid-cell: 96px;
  --grid-blur: 0.4px;

  /* The cursor patch. Rev. F: the interaction was built in Rev. C2 and has been
     running correctly ever since, but it painted ONLY on the 1px grid lines,
     which cover about 3 percent of the surface. Measured, it changed 2.98% of
     pixels in the patch and shifted mean luminance by 0.14 percent, which is
     why Max reported it as never built. Raising the alpha cannot fix a ceiling
     that is structural: at nearly 3x the value it still touched only 6 percent
     of the patch.
     Rev. F added --grid-halo, a soft radial wash that tints the PAPER between
     the lines, so the patch changes area instead of hairlines.

     Rev. G, after Max reported it as broken for the THIRD time: "either FIX the
     interactive cursor animation for GOOOOOD, or you just remove the grid".
     Measured on the Rev. F build with a real pointer at 1440x900: 8.01% of
     pixels changed, mean absolute RGB delta 0.919 out of 765. That is 0.12
     percent of range, which is under the just-noticeable difference on a warm
     paper field. Rev. F was not wrong about the mechanism and it was still
     invisible, which is the whole lesson: measuring that a thing CHANGED is not
     the same as measuring that a person can SEE it. The acceptance test is a
     number a human threshold can be compared against, not a ratio against the
     previous build.

     Three changes, and the third is the one that carries it:
     1. Halo roughly 2x, because the wash is what gives the eye an area.
     2. Hot lines up, so the drafting character survives the stronger wash.
     3. --grid-sub, a finer grid at a quarter cell that exists ONLY inside the
        patch. Lines APPEARING where there were none is a categorically bigger
        perceptual event than existing lines getting warmer, and subdividing on
        close inspection is what drafting paper actually does.

     Values tuned against the render, not against the numbers. At hot 0.62 the
     measurement passed and the four 96px lines crossing the patch read as a
     saturated orange CROSS laid over the copy rather than as a patch of warmed
     paper, because those lines run the full diameter while everything else
     falls off radially. Pulled back to 0.40, with the quarter-cell grid raised
     to carry the character instead. Costs a little measured mean and fixes the
     shape, which is the trade the render is there to catch. */

  /* Rev. H.1, and this is the third time the values have moved. Max, on the
     Rev. H build: "the interactive cursor hover animation is ok, but a little
     too big and too rich in color. Can we reduce its contrast by 30% and the
     size by 40%. If we could have some more motion WITHIN it, it will be
     better. Rather than just having a round shaped element, but something that
     changes shape too as we move the cursor."

     Size: --grid-radius 300 -> 180, which is the 40 percent he asked for on the
     dimension he can see (the diameter), not on area.

     Contrast: cut against the MEASURED mean inside the new radius, never
     against the authored alpha, because the smaller patch changes what the same
     alpha measures. Measured at r=180, sheet 03 at y=0: the Rev. G values give
     mean 14.65/765 and these give 10.35, which is 29.4 percent down. Two other
     candidates were measured and rejected, 0.33/0.215/0.093/0.040 at -22.8
     percent and 0.26/0.175/0.074/0.031 at -37.2.
     The floor in measure-grid.mjs is 8.0, so this sits above it deliberately
     and there is not much room left: one more cut of this size puts the effect
     back under the threshold Max reported as "not built" three revisions
     running. Say that out loud before cutting it again.

     Colour: the wash also loses a little saturation (163,58,0 -> 150,72,28).
     "Too rich in colour" is not the same complaint as "too strong", and alpha
     alone answers only the second one. */
  --grid-line-hot: rgba(163, 58, 0, 0.30);
  --grid-sub: rgba(163, 58, 0, 0.20);
  --grid-halo: rgba(150, 72, 28, 0.085);
  --grid-halo-soft: rgba(150, 72, 28, 0.036);
  --grid-radius: 180px;
  --grid-cell-sub: 24px;
  /* Runtime shape. js/grid.js writes these from pointer velocity, so the patch
     stretches along the direction of travel and eases back to round when the
     pointer stops. Unset is the resting circle, which is what a no-JS or
     reduced-motion visitor gets. */
  /* Tuned by looking, not by taste. At 0.55 / 0.28 a full-speed sweep drew a
     216 by 161 ellipse, a 1.34 ratio, which on a soft-edged wash is a shape
     change you can measure and not one you can see. At 0.70 / 0.34 the same
     sweep hits the 1.7R cap at 306 by 119, a 2.6 ratio, and it is unmistakable.
     The patch is still far smaller than the Rev. G circle even at full stretch:
     that ellipse is 112,000 square px against 283,000. */
  --grid-stretch: 0.70; /* how far the travelling axis grows */
  --grid-squeeze: 0.34; /* how far the other one narrows, so it reads as a stretch */
  --grid-parallax: 0.06; /* sub-grid slide per pixel of pointer travel */

  /* Rev. D palette extension. The old system had exactly two surfaces and one
     accent, which is why every section looked like the same section. Three
     additions, each with one job. Orange stays action-only. */
  --tint-sand: #ece7dc;   /* section surface, one step down from paper */
  --tint-sky: #e3e8f1;    /* diagram and data surfaces only */
  --blue: #2f4e9e;        /* diagrams, process, anything measured. 7.4:1 on paper */
  --blue-dim: #6a7aa4;    /* diagram hairlines, non-text. 3:1 on paper */

  /* Section rhythm. ONE rule: every top-level section is preceded by --sec-gap of
     page ground. Inversion bands included: a band's own padding is not a substitute
     for the gap, which is how the hero CTA ended up touching the black band. */
  --sec-gap: var(--sec-pad);

  /* Type */
  --font-display: "Archivo", "Archivo-fallback", Arial, sans-serif;
  --font-mono: "Fragment Mono", "FragmentMono-fallback", "Courier New", monospace;
  --fs-13: 0.8125rem;
  --fs-16: 1rem;
  --fs-18: 1.125rem;
  --fs-24: 1.5rem;
  --fs-32: 2rem;
  --fs-48: 3rem;
  --fs-64: 4rem;
  --fs-96: 6rem;
  --fs-display: clamp(3rem, 7.4vw, 7.75rem);
  --track-label: 0.08em;

  /* Space: fixed ramp on an 8px base */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 40px;
  --s-5: 64px;
  --s-6: 96px;
  --s-7: 160px;
  --sec-pad: var(--s-7);

  /* Grid */
  --cols: 12;
  --gutter: 24px;
  --margin: clamp(20px, 4vw, 64px);
  --max-w: 1680px;
  --rule-w: 1px;
  --rule-inset: 14px; /* frame rules sit outboard of the content edge */
  --hairline-strong: #8d887b; /* input underlines: 3:1 non-text boundary on Paper */

  /* Motion: three eases, no defaults */
  --ease-rule: cubic-bezier(0.16, 1, 0.3, 1);      /* draws and reveals, 700ms */
  --ease-carriage: cubic-bezier(0.85, 0, 0.15, 1); /* moves and collapses, 450ms */
  --ease-stamp: cubic-bezier(0.34, 1.56, 0.64, 1); /* small marks, 180 to 260ms */
  --ease-micro: cubic-bezier(0.3, 0, 0, 1);        /* micro fades, 240ms */
  --t-rule: 700ms;
  --t-carriage: 450ms;
  --t-stamp: 240ms;
  --t-micro: 240ms;

  /* Focus */
  --focus-ring: 2px solid var(--orange-ink);
}

@media (max-width: 749px) {
  :root {
    --cols: 4;
    --gutter: 16px;
    --sec-pad: var(--s-6);
    --rule-inset: 8px;
  }
}
