/* Site developed and built by sitethreesixty.com */

/* ============================================================
   tokens.css — Brand tokens + @font-face
   The ONLY file that defines CSS custom properties.

   @font-face sits above the tokens deliberately: the browser
   parses top-down, so the font request goes out before it has
   read a single variable (Rules/Claude.md, Parse Order §1).
   ============================================================ */

/* 'Jakarta Round' is our own build: Plus Jakarta Sans with the period changed
   from a rectangle to a circle. Sources pulled from the upstream GitHub repo,
   the period glyph rebuilt as a quadratic circle, family renamed, then subset.
   Upstream declares NO Reserved Font Name, so renaming was not compulsory — done
   because a modified font sharing the upstream name misleads. SIL OFL 1.1;
   the licence travels with the font at fonts/OFL.txt. Advance widths are
   untouched, so text metrics match stock Plus Jakarta Sans exactly. */

@font-face {
  font-family: 'Jakarta Round';
  src: url('../fonts/jakarta-round-300.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Jakarta Round';
  src: url('../fonts/jakarta-round-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Jakarta Round';
  src: url('../fonts/jakarta-round-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* IBM Plex Mono carries the labels. Owner ruling 28, 18 Aug 2026.
   The system stack it replaces (ui-monospace/SFMono/Menlo/Consolas) resolved to a different
   face on every OS, so its weight and rendering could not be controlled — the labels went
   thin and there was no way to fix it from here.

   ⚠️ Shipped EXACTLY as Google distributes the latin subset — not re-subsetted. Plex carries
   a Reserved Font Name, and a subset is a Modified Version, which under OFL 1.1 may not keep
   the name. Cutting to the ~30 glyphs the labels use would save ~7KB per weight and cost a
   rename; 10KB each is not worth that. Licence travels at fonts/IBMPlex-OFL.txt.
   ⛔ Do not run this one through scripts/build-font.py. */

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/plex-mono-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/plex-mono-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {

  /* ============================================================
     ⛔ HOW THIS SET WAS DECIDED, AND WHY IT IS NOW CLOSED
     Owner ruling, 17 Aug 2026.

     THE SITE DEFINES ITS OWN TOKENS. The master template does not dictate
     values — it supplies the canonical NAMES (which gate A5 checks) and a set
     of standards to fall back on.

       1. The design specifies it  -> the design's value wins.
       2. The design is silent     -> take the template's standard.

     The design sets the SIZE of the set, not just the values: a design calling
     for five colours and no shades gets five colours plus whatever shades the
     template brings; a design calling for nine colours and ten specific shade
     levels gets exactly that.

     ⛔ ONCE SET, THAT IS IT — NOTHING CAN BE ADDED. Any category. A value may
     still be CHANGED on a built site, and realistically that will be a colour;
     but no new token is ever born, in any group below. Needing one means the
     design decision is wrong, not the palette or the scale.

     ⛔ WHY: TO STOP DESIGN CREEP. A builder who can mint a token mid-build can
     drift the site away from the design that was signed off, one defensible
     value at a time — and every step looks reasonable on its own. Freezing the
     set is what makes the signed-off design the thing that actually ships.
     ============================================================ */

  /* ---- Brand palette ----
     Ratios below are measured, not estimated. --brand-accent clears AA on the
     dark ground only; the design also paints .signal-dot with it on light and
     muted grounds (3.17:1 / 2.96:1) — carried over unchanged and reported in
     COMPLETION-DECLARATION.md rather than silently recoloured. */
  --brand-primary: #A83512;      /* LIGHT-GROUND ONLY — 6.01:1 on --bg-light, 2.55:1 on --bg-dark ✗ */
  --brand-accent: #F4511E;       /* DARK-GROUND ONLY  — 4.84:1 on --bg-dark,  3.17:1 on --bg-light ✗ */
  --brand-accent-on-light: #BC3F17; /* LIGHT-GROUND ONLY — 4.95:1 on --bg-light, 4.62:1 on --bg-muted, 3.10:1 on --bg-dark ✗ */
  --brand-accent-muted: #F0805C; /* decoration only — the ghost dot, 2.25:1 on --bg-muted */
  --brand-secondary: #253532;

  /* ---- Backgrounds ---- */
  --bg-light: #F7F4EE;
  --bg-dark: #10201E;
  --bg-muted: #E8EEEB;
  --bg-accent: #A83512;

  /* ---- Text colours ---- */
  --text-on-light: #10201E;      /* 15.34:1 on --bg-light, 14.32:1 on --bg-muted */
  --text-on-dark: #F7F4EE;       /* 15.34:1 on --bg-dark */
  --text-muted-light: #596765;   /* LIGHT-GROUND ONLY — 5.38:1 on --bg-light, 2.85:1 on --bg-dark ✗ */
  --text-muted-dark: #A7B3B0;    /* DARK-GROUND ONLY  — 7.79:1 on --bg-dark,  1.97:1 on --bg-light ✗ */

  /* ---- Locked neutrals ----
     --grey-mid and --grey-lightest are the design's two alpha-on-text values
     composited to solids: identical rendered colour, no transparency on text
     (checklist A8). Computed against their actual ground, not assumed. */
  --white: #f8f8fd;
  --grey-light: #D6D9D5;         /* rules and borders on light grounds */
  --grey-mid: #9FA39F;           /* compass strip — ink @ 38% over --bg-light */
  --grey-lightest: #CCD3D0;      /* ghost wordmark — ink @ 13% over --bg-muted */
  --grey-darkest: #344340;       /* rules and borders on dark grounds */

  /* ---- Font families ---- */
  --font-heading: 'Jakarta Round', 'Avenir Next', system-ui, sans-serif;
  --font-body: 'Jakarta Round', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  /* ⬆ 23 Aug 2026: body was a SYSTEM stack, so every paragraph rendered in a
     different typeface per OS — San Francisco on Mac, Segoe UI on Windows, with
     different x-heights and line wrapping. Uncontrollable, and the reason body
     copy looked thin off-Mac. Jakarta Round 400 was built for this (≈6KB, same
     family already shipped for headings). The system faces remain as fallback
     only, for the window before the font loads. */
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  /* ---- Font sizes ----
     Rationalised from the 37 freehand values in the delivered design down to
     22 steps. The micro band alone carried 12 values inside 2.7px, which is
     noise rather than intent — it collapses to three. Drift is recorded in
     DRIFT-REPORT.md, per owner ruling 7.

     Sourced per the ruling at the top of this file: each step is a design value,
     or a template standard where the design was silent. Closed set. */
  /* ⬆ Floor raised to 11px — owner ruling 26, 18 Aug 2026. Was .58/.62/.68 (9.28/9.92/
     10.88px). Owner's test: "if I can't see it on a huge screen with glasses on, it's too
     small." VALUES changed, no token added — ruling 12 permits exactly this.

     ⚠️ These three now sit within 1px of each other, so they read as one size. That is the
     honest consequence of an 11px floor under a 12px --font-label, and it is not a loss:
     DRIFT-REPORT.md already found the design's micro band was 12 freehand values inside a
     2.7px range. The names are kept because rules across four pages reference them, and
     renaming them buys nothing. --font-label stays 12px, so eyebrows keep their tier. */
  /* ⬆⬆ Floor raised AGAIN to 12.5px — owner ruling 29, 19 Aug 2026. Was
     .71/.73/.76/.82 (11.36/11.68/12.16/13.12px). VALUES changed, no token added.

     ⚠️ Ruling 26 raised the floor and ruling 27 raised the eyebrow and nav tiers, and it
     STILL came back too small — because raising values does not stop a builder reaching for
     the smallest one. On the six pages built after ruling 27, --font-micro had been used
     47 times as a general small-label size, when its own comment calls it a last resort.
     592 of the 600 visible text nodes under 14px were mono labels at the floor.

     So this ruling does two things at once: the values go up, AND 30 of those 47 rules were
     reassigned to --font-label / --font-label-sm, because most were ordinary status badges
     and qualification prose, not dense instrument chrome. scripts/legibility.py now fails
     below 12px so the next occurrence is caught by a gate rather than by eye. */
  --font-micro: .78rem;        /* 12.48px — the floor. FINE PRINT / INSTRUMENT CHROME ONLY.
                                  Owner ruling 22 Aug: the rest of the mono ladder was bumped;
                                  this one deliberately was NOT — nothing else on the page may be
                                  this small. Never prose, never an eyebrow, never a badge. */
  --font-caption: .875rem;     /* 14.00px — bumped from .80rem, owner ruling 22 Aug */
  --font-label-sm: .90rem;     /* 14.40px — bumped from .83rem. Qualification and terms prose */
  --font-label: .975rem;       /* 15.60px — bumped from .88rem. Eyebrows, status badges */
  --font-small: 1.02rem;       /* 16.32px — bumped from .95rem. Nav, Login, CTA */
  --font-body-size: 1.075rem;  /* 17.2px — bumped from 1rem, owner ruling 22 Aug.
                                  Body prose was 16px while the mono labels above it were
                                  15.6px: near-identical, so the copy read as small. Prose
                                  must sit clearly ABOVE the label ladder, not level with it. */
  --font-body-lg: clamp(1.125rem, 1.5vw, 1.4rem);
  --font-h6: 1.25rem;
  --font-h5: 1.4rem;
  --font-h4: clamp(1.05rem, 1.6vw, 1.35rem);
  --font-h4-lg: clamp(1.15rem, 1.95vw, 1.5rem);
  --font-h3-sm: clamp(1.35rem, 2.2vw, 2.2rem);
  --font-h3: clamp(1.45rem, 2.4vw, 2.2rem);
  --font-h2: clamp(2.6rem, 5vw, 5.5rem);
  --font-h1: clamp(2.2rem, 3.8vw, 4.25rem);
  --font-display: clamp(3.4rem, 6vw, 6.5rem);
  --font-display-view: clamp(3.375rem, 7vw, 6.5rem);   /* 360view h1. Owner-ruled 21 Aug: --font-display's 6vw renders 14% smaller at desktop (‑14.4px @1440) — not near enough to reuse, so a new token per the "nearest, or make one" rule. */
  --font-display-xs: clamp(1.35rem, 2.2vw, 2.1rem);   /* closing lines — was 43.2px at 1920, owner: too big */
  --font-display-sm: clamp(1.65rem, 3.2vw, 3rem);
  --font-display-md: clamp(2.6rem, 5.5vw, 6rem);
  --font-display-lg: clamp(5rem, 9vw, 9rem);
  --font-display-xl: clamp(5rem, 11vw, 9rem);
  --font-display-2xl: min(10rem, 17cqi);   /* watermark: fits its column on one line */
  --font-display-3xl: clamp(7rem, 16vw, 14rem);
  --font-display-4xl: clamp(9rem, 19vw, 17rem);

  /* Added 2026-08-17 for comparison.html, owner ruling 23: extend the display
     tier ABOVE the previous 272px top only — everything below it snaps to the
     frozen scale. The page's value watermarks are the largest type on the site;
     nothing else needed a new step. */
  --font-display-5xl: clamp(10rem, 22vw, 24rem);
  --font-display-6xl: clamp(11rem, 24vw, 27rem);

  /* ---- Font weights ----
     Only 300 and 600 ship as .woff2, so only those two are declared. Requesting
     a weight the family does not carry is forbidden — it invites synthetic bold.

     --weight-medium carries 300 because the owner asked for Plus Jakarta Sans
     LIGHT: every heading and display numeral reads it, so this is where "Light"
     is set. Note it also reaches the nav links and login, which are body-font,
     so those lighten too — flagged rather than special-cased. */
  --weight-regular: 400;         /* body copy — system font stack, not the heading face */
  --weight-medium: 300;          /* Light — the heading weight */
  --weight-semibold: 600;        /* wordmark, watermark, buttons, text links */

  /* ---- Line heights ----
     Kept finer at the display end on purpose: a .05 change on a 17rem numeral
     moves its line box by ~14px, while the same change on body copy is
     invisible. The small-text values merge; the display ones don't. */
  --leading-crush: .65;
  --leading-none: .7;
  --leading-solid: .9;
  --leading-tight: .94;
  --leading-flush: 1;
  --leading-display: 1.02;
  --leading-flat: 1.15;
  --leading-snug: 1.35;
  --leading-normal: 1.62;

  /* ---- Letter spacing ---- */
  --tracking-crush: -.075em;
  --tracking-tight: -.055em;
  --tracking-snug: -.035em;
  --tracking-normal: 0;
  --tracking-wide: .05em;
  --tracking-caps: .08em;
  --tracking-caps-lg: .12em;

  /* ---- Spacing scale ----
     The template's six steps double each time (4·8·16·32·64·128). The design
     also uses the four half-steps between them, so those are named for the
     pair they sit between rather than renumbering a scale other sites share. */
  --space-xs: .25rem;
  --space-sm: .5rem;
  --space-sm-md: .75rem;
  --space-md: 1rem;
  --space-md-plus: 1.25rem;
  --space-md-lg: 1.5rem;
  --space-lg: 2rem;
  --space-lg-xl: 3rem;
  --space-xl: 4rem;
  --space-xl-2xl: 6rem;
  --space-2xl: 8rem;

  /* ---- Fluid gaps ----
     Section rhythm and column gutters. Fixed spacing steps can't do this job:
     these have to shrink with the accordion, and each floor is what stops
     mobile collapsing to nothing. Ten steps, down from the design's 24. */
  --gap-2xs: clamp(.9rem, 1.7vw, 1.8rem);
  --gap-xs: clamp(1rem, 2vw, 2rem);
  --gap-xs-sm: clamp(1.2rem, 2.6vw, 2rem);
  --gap-sm: clamp(1.4rem, 2.8vw, 2.4rem);
  --gap-md: clamp(1.8rem, 4vw, 2.8rem);
  --gap-lg: clamp(2rem, 5vw, 5rem);
  --gap-xl: clamp(1.5rem, 5vw, 6rem);
  --gap-2xl: clamp(3rem, 6vw, 5.5rem);
  --gap-3xl: clamp(2.5rem, 7vw, 8rem);
  --gap-4xl: clamp(3rem, 8vw, 9rem);
  --gap-5xl: clamp(3rem, 9vw, 10rem);

  /* ---- Zone rhythm ----
     Zone 1 and the closing zone carry more air than the standard band, so
     they get their own padding rather than an override written inline. */
  --zone-pad-hero: clamp(8rem, 11vw, 12rem);
  --zone-pad-final: clamp(5rem, 10vw, 10rem);

  /* ---- Border radius ---- */
  --radius-sm: .75rem;
  --radius-md: 1.5rem;
  --radius-lg: 2rem;
  --radius-full: 999px;

  /* ---- Border widths ---- */
  --border-thin: 1px;
  --border-medium: 2px;
  --border-thick: 3px;

  /* ---- Shadows ---- */
  --shadow-lg: 0 24px 80px color-mix(in srgb, var(--bg-dark) 12%, transparent);

  /* ---- Transitions ---- */
  --ease-default: cubic-bezier(.2, .8, .2, 1);
  --speed-fast: 180ms;
  --speed-normal: 320ms;
  --speed-slow: 680ms;

  /* ---- Z-index scale ---- */
  --z-base: 1;
  --z-above: 2;
  --z-header: 20;
  --z-overlay: 30;

  /* ---- Opacity ----
     Every other alpha in the delivered design was a background or border, and
     those use color-mix() against a token at the point of use instead of a
     shared opacity step.

     ⛔ COMMENT CORRECTED 19 Aug 2026 — value unchanged, nothing added or
     removed. --opacity-half previously read "nav + footer link hover", which
     documented an A8 HARD FAIL as if it were the intended use: A8 bans the
     opacity property on text, and says of tokens explicitly that
     `opacity: var(--opacity-half)` is exactly as banned as `opacity: .58`.
     Those hovers are now underlines. The token is retained but UNUSED, per
     ruling 12 (the set is closed, so it is not deleted) — and must not be
     reinstated on text. */
  --opacity-half: .58;           /* ⛔ UNUSED — never on text (A8) */
  --opacity-heavy: .85;          /* SSL ring — an empty <i>, decoration, not text */

  /* ---- Grid config ---- */
  --grid-columns: 12;
  --container-pad: clamp(1.25rem, 3vw, 3rem);
  --zone-pad: clamp(4rem, 8vw, 7rem);
}

/* https://www.sitethreesixty.com */
