/* ============================================================================
   NAVIK ANALYTICS — DESIGN TOKENS
   ----------------------------------------------------------------------------
   PALETTE DIRECTION: "Petrol" — accent revised 2026-08-05.
   (Supersedes "Oxide", locked 2026-08-03. Everything except the accent hue is
   unchanged: the ink chrome, the warm paper and the ink-not-accent buttons all
   survive intact, because none of them was what was wrong.)

   The metaphor is still the engineering document, not the SaaS dashboard: ink
   line work on warm paper with a single annotation mark. That mark is now
   petrol — the dark blue-green of machine enamel and instrument panels. It is
   native to the customer's world in the same way oxide was, but it is far
   darker and far less saturated, and that is the whole point: mid-lightness,
   high-chroma colour reads promotional no matter what hue it is.

   The two earlier rejections still stand and are not reopened by this change.
   Emerald was rejected because green reads "healthy / all clear" against an
   argument that says something is broken and you cannot see it — petrol is
   blue-leaning and near-black, and does not carry that reading. Gold was
   rejected for breaking the single-accent discipline.

   Two layers, deliberately separated so this file can be lifted wholesale into
   the future SaaS product without touching component code:

     Layer 1 — PRIMITIVES.  Raw palette and scale values. Never referenced
               directly by a component. Renaming a brand colour happens here.
     Layer 2 — SEMANTIC.    Role-based tokens (what a thing IS, not what colour
               it is). Components consume only these.

   Contrast ratios noted inline are measured against the stated background and
   are the reason certain pairings are forbidden. Do not "fix" them by eye.
   ============================================================================ */

:root {
  /* ==========================================================================
     LAYER 1 — PRIMITIVES
     ========================================================================== */

  /* --- Ink -----------------------------------------------------------------
     The structural neutral. Carries every piece of primary text, every rule,
     and — unusually — every primary button. Ink buttons are what premium
     software actually does (Apple, Linear, Vercel); it reads more expensive
     than a coloured button and it frees the accent to carry meaning. */
  --ink-900: #16181a;
  --ink-800: #1c1f21;
  --ink-700: #22262a; /* brand primary — 14.09:1 on paper, AAA */
  --ink-600: #33383c;
  --ink-500: #4b5054;

  /* --- Paper ---------------------------------------------------------------
     Warm neutrals. The warmth is doing real work: it reads as stock rather than
     screen, and it stops the ink from feeling clinical. Cold greys sit badly
     against it, which is why the whole neutral ramp is pulled warm. */
  --paper-0: #ffffff; /* cards */
  --paper-25: #fcfbf8;
  --paper-50: #f7f6f2; /* page background */
  --paper-100: #f0eee8; /* sunken wells */
  --paper-200: #e4e2dc; /* standard border */
  --paper-300: #d3d0c8; /* emphasis border, empty-state outline */
  --paper-400: #a8a49b; /* decorative / disabled only — fails AA */
  --paper-500: #6e6b66; /* 4.91:1 on paper — secondary text, AA pass */

  /* --- Petrol --------------------------------------------------------------
     The single accent, and the only hue in the entire chrome. Used sparingly:
     eyebrow rules, link hover, the diagnostic mark, and the "you" series in
     data. If it appears somewhere it is not carrying meaning, remove it.

     REPLACED OXIDE (#A8431F) on 2026-08-05 — the user judged the copper not
     premium enough for a consulting firm, and the diagnosis was lightness and
     chroma rather than hue: oxide sat mid-lightness and highly saturated, which
     is the signature of promotional design (sale badges, alert states). Petrol
     is much darker and far less saturated, which is what actually reads
     expensive. It keeps what oxide was chosen for — it is native to the
     customer's world (machine enamel, instrument panels, works paint) rather
     than to SaaS — while dropping the warmth that made it look like a discount.

     It is NOT the emerald that was rejected in the original palette review.
     That failed because green reads "healthy, all clear" against a message that
     says something is wrong. Petrol is blue-leaning and near-black at the accent
     step; it reads as instrumentation, not as an all-clear. */
  --petrol-50: #f2f7f8;
  --petrol-100: #dde9ec;
  --petrol-200: #b6d0d7;
  --petrol-300: #8ab4be; /* 6.69:1 on ink — accent on dark surfaces */
  --petrol-400: #4f8896;
  --petrol-500: #2f6c7c;
  --petrol-600: #1f4e5f; /* 8.28:1 on paper, AAA — the brand accent */
  --petrol-700: #173c4a; /* hover, darkens */
  --petrol-800: #102c37;
  --petrol-900: #0a1d25;

  /* --- Logo -----------------------------------------------------------------
     The two stops of the wordmark gradient. These are NOT a second accent and
     must never be used as one: their single job is the two-row heading device
     (row 1 teal, row 2 navy), which is why they are exposed as heading tokens
     below and nowhere else. Chrome — buttons, borders, pills, icons, links —
     is petrol. If either of these turns up on a control, it has escaped.

     Recorded because they were previously hard-coded, with !important, in
     components.css and again in Hero.astro, which meant the heading colour
     could not be changed in one place. */
  --logo-teal: #138aac;
  --logo-navy: #000b53;

  /* --- State ramp ----------------------------------------------------------
     DIAGNOSTIC USE ONLY — a five-step red-to-green progression for showing a
     thing moving from bad to good. Added 2026-08-05 at the user's instruction
     for the Ladder section. NEVER use these in chrome: not for buttons, links,
     borders, headings or any surface. The moment a hue from this ramp appears
     somewhere that is not a state, the single-accent discipline is gone.

     They are pulled dark and desaturated on purpose. A literal alert-red and
     mint-green ramp is the house style of every SaaS dashboard, and it would
     drop this section out of the document register the rest of the site is set
     in. These read as printed status marks instead.

     ACCESSIBILITY: red-to-green is the single worst axis for the ~8% of men
     with red-green colour blindness, to whom steps 1 and 5 look near-identical.
     Any component using this ramp MUST also encode the progression in a second,
     non-colour channel. Ladder does it with line style and fill: step 1 is
     dashed and hollow, step 5 is solid and filled. Do not drop that. */
  --state-1: #96302f; /* absent / failing   */
  --state-2: #a55c25; /* moving             */
  --state-3: #7d6b22; /* partway            */
  --state-4: #35704f; /* nearly             */
  --state-5: #1a6040; /* arrived            */

  /* --- Clay ----------------------------------------------------------------
     CHART USE ONLY. Never appears in chrome. Exists solely so a categorical
     series of 5+ can be distinguished once the warm greys run out. Introducing
     it anywhere else breaks the single-accent discipline.

     This slot used to hold a slate blue (#4A6076). That now sits almost on top
     of petrol and would read as a washed-out version of the brand accent rather
     than a separate series, so the escape-hatch hue was moved to the opposite,
     warm side of the wheel where it cannot be confused with the client's mark. */
  --clay-viz: #96634a;
  --clay-viz-light: #bd9683;

  /* --- Typefaces -----------------------------------------------------------
     TYPE DIRECTION: "The Brief" — locked 2026-08-04, replacing Manrope/Inter.

     Instrument Serif carries every heading and every assertion. A serif moves
     the whole site from the SaaS register into the advisory one — which is what
     is actually being sold — and it does not skew the audience: this is a
     contemporary face, not a traditional one. Its italic is the reason it was
     chosen. In a serif, italic is a genuine change of VOICE, so the turn in a
     headline can be carried by the type rather than by a colour change that
     stops working the moment someone reads quickly.

     Instrument Sans is drawn as its companion, so the pairing shares skeletons
     instead of colliding the way a serif bolted onto Inter does.

     JetBrains Mono is RATIONED. It marks only genuine references — the exhibit
     caption, the Q1–Q4 indices. Used any wider than that it becomes costume,
     which is precisely what dated the first version of this direction.

     Note: Instrument Serif ships one weight (400). Never ask for 600 on a
     heading — the browser will synthesise a fake bold and it looks broken. */
  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-body: "Arimo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", monospace;

  /* Montserrat was trialled as a hero-only face on 2026-08-05 and reverted the
     same day. Recorded here so it is not re-proposed: a geometric sans has no
     true italic, only a mechanical oblique, so it cannot carry the headline
     turn that this whole type system is built around. */

  /* Aliases kept so base.css and any existing component keep resolving. */
  --font-heading: var(--font-display);
  --font-numeric: var(--font-mono);

  /* --- Type scale ----------------------------------------------------------
     Rescaled upward for the serif. Instrument Serif has a small x-height and
     high contrast, so it carries display sizes that would be shouting in a
     grotesque — and it needs them to read as confident rather than timid. */
  --text-display: clamp(3rem, 1.6rem + 5.2vw, 5.5rem); /* 48 → 88 */
  --text-h1: clamp(2.75rem, 1.5rem + 4.6vw, 5rem); /*  44 → 80 */
  --text-h2: clamp(2rem, 1.25rem + 2.4vw, 3.125rem); /*  32 → 50 */
  --text-h3: clamp(1.5rem, 1.3rem + 0.9vw, 1.875rem); /*  24 → 30 */
  --text-h4: 1.25rem; /*  20     */
  --text-lead: 1.1875rem; /*  19     */
  --text-body: 1.0625rem; /*  17 — editorial weight, not the default 16 */
  --text-sm: 0.9375rem; /*  15     */
  --text-xs: 0.8125rem; /*  13     */
  --text-eyebrow: 0.75rem; /*  12     */

  --leading-tight: 1.05;
  --leading-snug: 1.2;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;

  --tracking-tight: -0.03em; /* display sizes only — the serif needs more */
  --tracking-snug: -0.015em;
  --tracking-normal: 0;
  --tracking-wide: 0.06em;
  --tracking-eyebrow: 0.12em;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* --- Space ---------------------------------------------------------------
     4px base. Named by step, not by use, so the scale survives redesigns. */
  --space-1: 0.25rem; /*  4 */
  --space-2: 0.5rem; /*  8 */
  --space-3: 0.75rem; /* 12 */
  --space-4: 1rem; /* 16 */
  --space-5: 1.5rem; /* 24 */
  --space-6: 2rem; /* 32 */
  --space-7: 3rem; /* 48 */
  --space-8: 4rem; /* 64 */
  --space-9: 5rem; /* 80 */
  --space-10: 6rem; /* 96 */
  --space-11: 8rem; /* 128 */
  --space-12: 10rem; /* 160 */

  /* --- Radius --------------------------------------------------------------
     Restrained. Large radii read consumer/startup; these read instrument. */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-pill: 999px;

  /* --- Elevation -----------------------------------------------------------
     Tinted with the brand ink rather than pure black, and kept very low.
     Consulting-register interfaces separate with line and space, not shadow. */
  --shadow-sm: 0 1px 2px rgb(34 38 42 / 0.04);
  --shadow-md: 0 2px 8px rgb(34 38 42 / 0.06), 0 1px 2px rgb(34 38 42 / 0.04);
  --shadow-lg: 0 12px 32px rgb(34 38 42 / 0.08), 0 2px 8px rgb(34 38 42 / 0.04);
  --shadow-xl: 0 24px 56px rgb(34 38 42 / 0.1), 0 4px 12px rgb(34 38 42 / 0.05);

  /* --- Layout --------------------------------------------------------------- */
  --container-max: 1280px;
  --container-narrow: 960px;
  --measure: 68ch; /* prose line length ceiling */
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --section-y: clamp(4rem, 8vw, 8rem);
  --header-h: 72px;

  /* --- Motion ---------------------------------------------------------------
     ease-out is a strong decelerating curve: things arrive quickly then settle.
     Reads considered rather than bouncy. */
  --duration-fast: 150ms;
  --duration-base: 250ms;
  --duration-slow: 400ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* --- Layers --------------------------------------------------------------- */
  --z-base: 1;
  --z-sticky: 100;
  --z-header: 200;
  --z-overlay: 300;
  --z-modal: 400;

  /* ==========================================================================
     LAYER 2 — SEMANTIC
     Components reference these only.
     ========================================================================== */

  /* --- Surfaces --- */
  --surface-page: var(--paper-50);
  --surface-raised: var(--paper-0); /* cards */
  --surface-sunken: var(--paper-100); /* inset wells, code blocks */
  --surface-inverse: var(--ink-700); /* dark sections */
  --surface-inverse-deep: var(--ink-900);
  --surface-accent-subtle: var(--petrol-50);

  /* --- Text --- */
  --text-primary: var(--ink-700);
  --text-secondary: var(--paper-500);
  --text-tertiary: var(--paper-400); /* decorative only — fails AA */
  --text-accent: var(--petrol-600);
  --text-accent-hover: var(--petrol-700);

  /* The two-row heading device. Row 1 states, row 2 turns — see the <em>
     convention in base.css. Colour, not weight, carries the turn, because
     Instrument Serif ships one weight. */
  --heading-row-1: var(--logo-teal);
  --heading-row-2: var(--logo-navy);
  --text-on-inverse: var(--paper-0);
  --text-on-inverse-muted: rgb(255 255 255 / 0.68);

  /* --- Borders --- */
  --border-subtle: var(--paper-200);
  --border-strong: var(--paper-300);
  --border-inverse: rgb(255 255 255 / 0.14);
  --border-accent: var(--petrol-600);

  /* --- Actions -------------------------------------------------------------
     Primary actions are PETROL — user decision 2026-08-05.

     This reverses the original rule, which made primary buttons ink (#22262A)
     on the grounds that a colourless button reads more expensive and frees the
     accent to carry meaning. Two things make the reversal safe now that the
     accent is petrol rather than oxide: petrol is dark enough (8.28:1 on paper)
     that the button still reads as a considered mark rather than a promotional
     one, which was the actual worry; and it is the same family as the ink, so
     the chrome does not fragment.

     What the original rule was protecting is still worth watching: the accent
     now appears both as the primary action AND as the diagnostic mark in the
     headline and the exhibit. If petrol starts showing up on the page in places
     where it is neither an action nor a finding, it has gone decorative — take
     it out there, not here. Hover darkens.

     RESTORED 2026-08-09. These two slots had been overwritten with a
     mint-to-navy gradient (#5CDB95 → #05386B) that appears nowhere else in the
     brand — not in the palette, not in the wordmark — and that was additionally
     hard-coded a second and third time in components.css and SiteHeader.astro,
     so the token was doing nothing. Both stops also sat far outside the
     lightness/chroma band this palette is built on, which is the exact failure
     the oxide → petrol revision was made to correct. Hover was a duplicate of
     the base value, so the button had no hover state at all. */
  --action-primary: var(--petrol-600);
  --action-primary-hover: var(--petrol-700);
  --action-primary-text: var(--paper-0);
  --action-secondary-text: var(--ink-700);
  --action-secondary-border: var(--paper-300);
  --action-secondary-hover-bg: var(--paper-100);

  --focus-ring: var(--petrol-600);
  --accent-on-inverse: var(--petrol-300);

  /* --- Data visualisation --------------------------------------------------
     The colour logic mirrors the argument the site makes:
       viz-you      the client — petrol, the only saturated mark on the chart
       viz-other    competitors — warm grey, present but unremarkable
       viz-absent   the gap — an outline, not a fill. Absence must LOOK absent.
     Never colour a competitor series more prominently than the client series. */
  --viz-you: var(--petrol-600);
  --viz-you-soft: var(--petrol-200);
  --viz-other: #8a8781;
  --viz-other-light: #b5b1a8;
  --viz-track: var(--paper-200);
  --viz-absent: var(--paper-300);
  --viz-grid: var(--paper-200);
  --viz-extra-1: var(--clay-viz); /* only when 5+ series demand it */
  --viz-extra-2: var(--clay-viz-light);
}

/* ============================================================================
   INVERSE CONTEXT
   Applied to dark sections. Re-points semantic tokens rather than requiring
   every component to carry a --dark variant. Any component built against the
   semantic layer works inside this scope with no modification.
   ============================================================================ */
.surface-inverse {
  --surface-page: var(--ink-700);
  --surface-raised: var(--ink-600);
  --surface-sunken: var(--ink-800);
  --surface-accent-subtle: rgb(255 255 255 / 0.04);

  --text-primary: var(--paper-0);
  --text-secondary: rgb(255 255 255 / 0.68);
  --text-tertiary: rgb(255 255 255 / 0.45);
  --text-accent: var(--petrol-300);
  --text-accent-hover: var(--petrol-200);

  --border-subtle: rgb(255 255 255 / 0.14);
  --border-strong: rgb(255 255 255 / 0.24);
  --border-accent: var(--petrol-300);

  /* Ink buttons would vanish here, so the accent takes over as primary. */
  --action-primary: var(--petrol-600);
  --action-primary-hover: var(--petrol-500);
  --action-primary-text: var(--paper-0);
  --action-secondary-text: var(--paper-0);
  --action-secondary-border: rgb(255 255 255 / 0.28);
  --action-secondary-hover-bg: rgb(255 255 255 / 0.08);

  --focus-ring: var(--petrol-300);

  --viz-you: var(--petrol-400);
  --viz-other: rgb(255 255 255 / 0.38);
  --viz-other-light: rgb(255 255 255 / 0.22);
  --viz-track: rgb(255 255 255 / 0.1);
  --viz-absent: rgb(255 255 255 / 0.22);
  --viz-grid: rgb(255 255 255 / 0.12);

  background-color: var(--ink-700);
  color: var(--text-primary);
}

/* ============================================================================
   REDUCED MOTION
   Collapse durations at the token level so no component has to remember.
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0.01ms;
    --duration-base: 0.01ms;
    --duration-slow: 0.01ms;
  }
}
