/* ==========================================================================
   Design tokens for /product.

   This file is the whole vocabulary. product.css may use these custom
   properties and may not invent colours, sizes, durations or easings of its
   own — if a value is worth using twice it belongs here, and if it is only
   used once it is probably a mistake.

   DELIBERATELY ISOLATED FROM THE REST OF THE SITE
   -----------------------------------------------
   public/style.css has its own token set and follows the OS light/dark
   preference. This page does not: it is one committed dark art direction, the
   way a printed cover is. The two files share no custom property names on
   purpose, so neither can re-grade the other by accident if one is ever loaded
   alongside the other.

   THE VISUAL SYSTEM: "ISOMETRIC ASSAY"
   ------------------------------------
   One idea, applied everywhere. The product judges a message by passing it
   through a row of checks, so the page draws exactly that: a machined bench,
   a row of upright gate plates, and one beam of light that crosses every plate
   and comes out dimmer than it went in. The beam's remaining brightness IS the
   score.

   Everything on the page is drawn in the same isometric projection — the
   hand-authored SVG diagrams (public/product/iso.js), the generated artwork,
   and the real-time hero, which uses an ORTHOGRAPHIC camera precisely so it
   sits in the same projected world as the flat drawings rather than looking
   like a separate asset that happens to share a palette.

   CONTRAST
   --------
   Every text colour below carries its measured ratio against the ground it is
   used on. WCAG AA is 4.5:1 for body text and 3:1 for large text (>=24px, or
   >=18.7px bold). Values here were computed, not eyeballed; two of them were
   darkened-by-eye first drafts that failed outright.
   ========================================================================== */

:root {
  /* ── Ground ──────────────────────────────────────────────────────────────
     Four steps, and they are steps rather than a gradient. Surfaces in this
     system are machined plates stacked in space, so they differ by a
     discrete, visible amount — a continuous blur between them would read as
     the soft glassmorphism the art direction is explicitly not. */
  --ink:        #07070B;   /* the page itself */
  --ink-2:      #0C0D12;   /* a plate resting on it */
  --ink-3:      #12131A;   /* a plate on that one */
  --ink-4:      #191B24;   /* the highest surface: inputs, active states */

  /* Hairlines. The system draws edges, not shadows — a machined part is
     defined by where it stops, and 1px of light along that boundary says
     "precisely made" far more cheaply than a blur does. */
  --edge:       #1E202A;
  --edge-2:     #2A2D3A;
  --edge-lit:   #3A3F52;   /* an edge catching the key light */

  /* ── Text ────────────────────────────────────────────────────────────────
     Three weights of voice, and no more. */
  --ivory:      #F2EFE7;   /* 15.9:1 on --ink — headlines and body */
  --ivory-dim:  #C9C6BE;   /* 10.9:1 on --ink — de-emphasised body */
  --gray:       #8C93A4;   /*  6.6:1 on --ink — secondary text, captions */
  --gray-dim:   #787E8E;   /*  4.9:1 on --ink — meta only. The first draft of
                              this was #6E7382, which measured 4.25:1 and
                              failed AA. Do not darken it back. */

  /* ── Accent ──────────────────────────────────────────────────────────────
     Violet is the signal — the beam, the live value, the primary action. It
     is never decoration, and nothing else on the page is allowed to be violet.

     Two violets, because one cannot do both jobs: --violet is the graphic
     value used in fills, beams and shader output, and it measures 4.47:1 on
     --ink, which is a FAIL for body text by a hair. --violet-lift is the same
     hue lifted until it passes, and it is the only one that may carry text. */
  --violet:      #7A5AF8;  /*  4.5:1 — graphics only, never text */
  --violet-lift: #8E72FF;  /*  5.8:1 on --ink — text, links, focus rings */
  --violet-deep: #4A34B8;  /* the beam where it has been attenuated */
  --violet-wash: #16122B;  /* a violet-tinted surface, still nearly black */

  /* Cyan is the counter-signal: the cold edge on glass, and the colour of
     evidence as opposed to action. Used on edges and data, never on a CTA. */
  --cyan:        #56C4DE;  /* 10.0:1 on --ink */
  --cyan-deep:   #1E5C6B;

  /* Warm silver. The one warm note in the system, and it earns its place by
     being the only thing that makes the metal read as metal rather than as
     grey plastic. Used on machined highlights and on the display face. */
  --silver:      #C7BFB0;  /* 11.1:1 on --ink */

  /* ── Verdict colours ─────────────────────────────────────────────────────
     The interactive scorer needs pass/warn/fail, and they must not simply be
     green/amber/red dropped into an otherwise disciplined palette. Pass is the
     system's own cyan; fail is a desaturated signal red that sits in the same
     tonal family as everything else. Colour is never the only carrier — every
     verdict also has a label and a distinct mark. */
  --pass:       #5FD3A6;   /* 9.9:1 on --ink */
  --warn:       #E0B45F;   /* 10.3:1 on --ink */
  --fail:       #F2708B;   /*  7.4:1 on --ink */

  /* ── Type ────────────────────────────────────────────────────────────────
     Two families doing two jobs, plus mono for anything a machine produced.

     --sans is a neo-grotesk and carries the interface. --display is a
     high-contrast serif used ONLY for the page's few real statements — the
     core-value line and the closing line — which is what keeps the page
     editorial rather than merely dark. Used more often it would read as a
     magazine pastiche; used here it reads as emphasis.

     Both families are declared in product.html with metric-matched fallbacks,
     so the webfont swap is a repaint rather than a reflow. */
  --sans:    'Instrument Sans', 'Instrument Sans Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display: 'Instrument Serif', 'Instrument Serif Fallback', Georgia, 'Times New Roman', serif;
  --mono:    'IBM Plex Mono', 'IBM Plex Mono Fallback', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* A fluid scale. Each step interpolates between a phone and a 1440 desktop
     and then stops — an unbounded vw-based size keeps growing on a 5K display
     until the headline is absurd. The clamp()s below all top out. */
  --t-display: clamp(2.75rem, 1.30rem + 6.20vw, 6.50rem);  /* hero headline */
  --t-h1:      clamp(2.25rem, 1.35rem + 3.85vw, 4.25rem);  /* section titles */
  --t-h2:      clamp(1.60rem, 1.20rem + 1.70vw, 2.50rem);
  --t-h3:      clamp(1.20rem, 1.05rem + 0.65vw, 1.55rem);
  --t-lede:    clamp(1.06rem, 0.98rem + 0.38vw, 1.31rem);  /* section ledes */
  --t-body:    1rem;
  --t-sm:      0.9375rem;
  --t-xs:      0.8125rem;
  --t-eyebrow: 0.75rem;

  --lh-tight:  1.02;   /* display only — anything smaller collides */
  --lh-snug:   1.16;
  --lh-body:   1.62;

  /* Tracking. Large type needs negative tracking to hold together and small
     caps need positive tracking to stay legible; both are set here so the
     relationship stays deliberate. */
  --tr-display: -0.035em;
  --tr-h:       -0.022em;
  --tr-body:    -0.006em;
  --tr-eyebrow:  0.16em;

  /* ── Space ───────────────────────────────────────────────────────────────
     A 4px base on a roughly 1.5x rhythm. Sections use --sp-section, which is
     fluid, because fixed vertical rhythm that works on a laptop is oppressive
     on a phone and mean on a large display. */
  --sp-1:  0.25rem;
  --sp-2:  0.5rem;
  --sp-3:  0.75rem;
  --sp-4:  1rem;
  --sp-5:  1.5rem;
  --sp-6:  2rem;
  --sp-7:  3rem;
  --sp-8:  4rem;
  --sp-9:  6rem;
  --sp-10: 8rem;
  --sp-section: clamp(5rem, 3.2rem + 7.5vw, 9.5rem);

  /* ── Grid ────────────────────────────────────────────────────────────────
     12 columns, and the gutter is the same value as the page's side padding
     so the outer columns align with the page edge rather than floating. */
  --grid-cols: 12;
  --gutter:    clamp(1.25rem, 0.9rem + 1.6vw, 2rem);
  --measure:   72ch;    /* the widest a paragraph may ever be */
  --page-max:  82.5rem; /* 1320px */

  /* ── Radius ──────────────────────────────────────────────────────────────
     Small, and smaller than fashion suggests. Machined parts have a chamfer,
     not a pill. */
  --r-sm: 3px;
  --r-md: 5px;
  --r-lg: 8px;

  /* ── Motion ──────────────────────────────────────────────────────────────
     Durations are in two families: UI feedback, which must feel instant, and
     reveals, which are allowed to take their time because the visitor is not
     waiting on them.

     --ease-out is the workhorse. --ease-entrance decelerates hard and is what
     makes a reveal feel like an object arriving rather than a value changing.
     Nothing here bounces: an overshoot on a page about precision instruments
     is a contradiction. */
  --d-fast:   140ms;
  --d-base:   240ms;
  --d-slow:   480ms;
  --d-reveal: 900ms;

  --ease-out:      cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-entrance: cubic-bezier(0.16, 1, 0.30, 1);
  --ease-inout:    cubic-bezier(0.65, 0, 0.35, 1);

  /* ── Isometric projection ────────────────────────────────────────────────
     The constants that put the CSS and the SVG in the same world.

     True isometric, 30 degrees. public/product/iso.js projects with
       sx = (x - y) * cos(30deg)
       sy = (x + y) * sin(30deg) - z
     and these are the same numbers, exposed so a CSS transform that has to
     agree with a drawing (a card lifting along the isometric up-axis, say)
     can use them instead of a hand-tuned guess that drifts. */
  --iso-cos30: 0.8660254;
  --iso-sin30: 0.5;

  /* ── Layering ────────────────────────────────────────────────────────────
     Named, ordered, and exhaustive. An unnamed z-index somewhere in
     product.css is how stacking bugs start. */
  --z-canvas:  0;
  --z-content: 1;
  --z-sticky:  20;
  --z-nav:     30;
}

/* The page commits to dark. Declaring it means form controls, scrollbars and
   the UA's own focus styling are drawn for a dark ground rather than inverted
   at the last moment. */
:root { color-scheme: dark; }
