/* Company TuneUp — design tokens
 *
 * Hex values and the type scale are taken from docs/companytuneup-onepager.html,
 * which is the canonical source. The NAMES are ours: the one-pager names colours
 * by appearance (--navy, --bg, --line) and this system names them by role, so a
 * palette change is an edit here rather than a search for every place a colour
 * was used for a reason its name did not record.
 *
 * TWO TIERS, and the distinction is load-bearing:
 *
 *   --ct-c-*    primitives. The raw ramp. NOT for use in page CSS.
 *   everything else  roles. This is what pages use.
 *
 * A page that reaches for a primitive has named a colour by how it looks, which
 * is the thing this file exists to stop. If no role fits, the missing thing is a
 * role, not permission to use the primitive.
 */

:root {
  /* ---- Tier 1: primitives. Do not use directly. ------------------------- */

  /* Slate ramp, complete at 100/200/300/400/500/700.
   * 300 is #CBD5E1. An earlier brief gave #CBDE51 — a transposition, resolved
   * against the one-pager, which uses #CBD5E1 in both places it appears. If you
   * find #CBDE51 anywhere in this repo it is that error, not a second colour. */
  --ct-c-slate-100: #F5F7FA;
  --ct-c-slate-200: #E2E8F0;
  --ct-c-slate-300: #CBD5E1;
  --ct-c-slate-400: #94A3B8;
  --ct-c-slate-500: #64748B;
  --ct-c-slate-700: #334155;

  --ct-c-deep:      #0B1D2D;
  --ct-c-blue:      #1E4FA3;
  --ct-c-teal:      #00A3A3;
  --ct-c-green:     #33B24A;

  /* #7FD3E8 is deliberately NOT here.
   * It exists only as --ct-accent-on-inverse below, because it is legible on the
   * deep ground and effectively disappears on white. A primitive would let
   * someone reach for it on a light surface and get an invisible element that
   * looks fine to whoever picked it. The role name is the guard rail. */

  /* #8F98A3 is also not here. It is the print sheet's page surround — the grey
   * behind the paper — and is not a colour of this site. */

  /* ---- Tier 2: roles. Use these. ---------------------------------------- */

  /* Surfaces */
  --ct-surface:         var(--ct-c-slate-100);
  --ct-surface-raised:  #FFFFFF;
  --ct-surface-inverse: var(--ct-c-deep);
  --ct-border:          var(--ct-c-slate-200);

  /* Text on light surfaces */
  --ct-text-strong: var(--ct-c-deep);
  --ct-text:        var(--ct-c-slate-700);
  --ct-text-muted:  var(--ct-c-slate-500);

  /* Text on the inverse surface */
  --ct-text-inverse:        #FFFFFF;
  --ct-text-inverse-muted:  var(--ct-c-slate-300);
  --ct-text-inverse-subtle: var(--ct-c-slate-400);

  /* Accents */
  --ct-accent-primary:    var(--ct-c-blue);   /* emphasis, links, the paid tier */
  --ct-accent-secondary:  var(--ct-c-teal);   /* enumerators, list markers */
  --ct-accent-positive:   var(--ct-c-green);  /* the mark, the free tier (NOT the Strong band since #56) */
  --ct-accent-on-inverse: #7FD3E8;            /* on the deep ground ONLY */

  /* ---- Type ------------------------------------------------------------- */

  --ct-font-display: 'Montserrat', system-ui, sans-serif;
  --ct-font-text:    'Source Sans 3', system-ui, sans-serif;

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

  /* Scale, from the one-pager. Named for what each step does, not its size,
   * so a scale change does not leave every rule referring to an old number. */
  --ct-size-wordmark: 34px;
  --ct-size-hook:     20px;
  --ct-size-lead:     15px;
  --ct-size-body:     14.5px;
  --ct-size-body-sm:  13px;
  --ct-size-ui:       12.5px;
  --ct-size-meta:     11.5px;
  --ct-size-label:    11px;
  --ct-size-micro:    10.5px;

  --ct-track-descriptor: 2.4px;
  --ct-track-section:    1.8px;
  --ct-track-step:       1.4px;
  --ct-track-micro:      1.2px;
}

/* ---- Fonts: self-hosted, no runtime third-party request ------------------
 *
 * Both are variable fonts covering the whole weight axis, so one file per family
 * serves every weight above. font-display: swap because a marketing page that
 * shows nothing while a font loads has chosen invisible text over unstyled text.
 * tools/check-assets.py fails the build on any fonts.googleapis.com or
 * fonts.gstatic.com reference under public/. */

@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat-latin.woff2') format('woff2');
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Source Sans 3';
  src: url('../fonts/source-sans-3-latin.woff2') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

/* ---- Score bands ---------------------------------------------------------
 *
 * Thresholds and labels are NOT here. They live in
 * public/assets/vendor/score-bands.js, the single source both free tools read,
 * pending layer8-business-health#9. Duplicating them into CSS would create a
 * second source that drifts.
 *
 * The COLOURS are here, and they are a DELIBERATE PALETTE EXTENSION.
 *
 * The brand was handed over closed: navy, blue, teal, green, a slate ramp and
 * one on-navy accent. It carries no warning hue, and a four-band severity scale
 * needs one. Two amber intensities were added to close that gap.
 *
 * These are REVISABLE. The ruling was "continue and we can alter later", which
 * is not the same as settled — treat the values as a working decision with the
 * reasoning attached, not as brand law.
 *
 * Rejected, with reasons, so neither is re-proposed as an improvement:
 *
 *   Reusing the slate ramp for the lower bands. The ramp has no bad end — it
 *   runs light to dark, not fine to broken. Priority rendered in slate-700 says
 *   "de-emphasised", which is the opposite of what the band means.
 *
 *   Taking the colours from the gauge arcs. The mark sweeps green, teal, blue,
 *   on-navy accent: four things in a row that are not these four things. One is
 *   a decorative sweep, the other is a scale. Mapping between them invents a
 *   meaning neither carries.
 *
 * Blue is deliberately NOT in the band scale. It already carries links and the
 * paid tier, and a colour meaning two things is the same defect as collapsing
 * three absences behind one dash — arriving in the visual layer instead of the
 * data layer.
 *
 * MEASURED, not picked-then-tested. Contrast against #FFFFFF / --ct-surface:
 *
 *   Strong     #389E30   3.44 / 3.21      clears 3:1 non-text (#56)
 *   Watch      #007F7F   4.84 / 4.51      clears 4.5:1, safe as text (#56)
 *   Attention  #B0791C   3.75 / 3.50      clears 3:1 non-text
 *   Priority   #8A4F14   6.54 / 6.10      clears 4.5:1, safe as text
 *
 * #56, 2026-09-23: Strong and Watch were the brand green and brand teal
 * (#33B24A 2.76 / 2.57, #00A3A3 3.10 / 2.89), both below 3:1 on the surface.
 * They are now band-only values; the brand colours are unchanged and still
 * carry the mark, the accents and the free tier everywhere else.
 *
 * Why these two and not the smallest change that clears 3:1. Watch #007F7F is
 * the only darkened teal that widens BOTH neighbouring gaps. Strong then has a
 * ceiling: clearing 3:1 on the surface caps its lightness, so no green can keep
 * today's 1.75:1 from the new Watch or 3.11:1 from the limit plum — those are
 * unreachable by arithmetic, not by choice. Held instead is the PERCEIVED gap
 * (CIE76 ΔE), which is how this scale is told apart anyway: Strong–Watch ΔE 60
 * (today's green against the new Watch: 60), Strong–plum ΔE 117 (was 121), at
 * today's hue and chroma (muted, as above). #3CA233 would reach Strong–Watch
 * 1.48:1 but clears the surface at 3.05:1; #389E30 trades 0.07 of that for a
 * 3.21:1 margin.
 *
 * Muted rather than saturated, on purpose: the positioning is
 * findings-with-evidence, and a red-alert scorecard would fight the copy on
 * every page. For scale, a saturated amber (#FFBF00) manages 1.65:1 on white —
 * it is both louder and less legible, which is the usual trade nobody measures.
 *
 * KNOWN LIMIT — luminance separation is poor ACROSS THE WHOLE SCALE, and this
 * is not introduced by the ambers:
 *
 *   Strong vs Watch      1.41:1   ΔE 60   (was 1.12:1)
 *   Watch vs Attention   1.29:1   ΔE 77   (was 1.21:1)
 *   Attention vs Priority 1.74:1  ΔE 21
 *   Strong vs Attention  1.09:1   ΔE 65   (not adjacent; was 1.36:1)
 *
 * The bands are distinguished by HUE, not by lightness. In greyscale, or to a
 * viewer with a red-green deficiency, adjacent bands are close to
 * indistinguishable. THE BAND LABEL MUST THEREFORE ALWAYS ACCOMPANY THE COLOUR
 * — colour is reinforcement here and never the carrier. Card 27 should verify
 * that rather than treating the swatches as sufficient.
 *
 * Bands render on light surfaces. On the inverse ground Priority manages only
 * 2.61:1; if a band ever needs to appear on navy it needs its own treatment. */

:root {
  --ct-band-strong:    #389E30;   /* not --ct-c-green: see #56 above */
  --ct-band-watch:     #007F7F;   /* not --ct-c-teal: see #56 above */
  --ct-band-attention: #B0791C;
  --ct-band-priority:  #8A4F14;
  /* Not a band. The bar of a scorecard row at the answers-only limit
   * (companytuneup-site ADR 0006), whose label is "At the answers-only limit"
   * rather than a band word, so it cannot wear a band colour. MEASURED against
   * everything it sits beside (contrast ratio / CIE76 ΔE):
   *
   *   white 8.59 / 82    surface 8.01 / 79    row rule #E2E8F0 6.97 / 75
   *   not-applicable label #64748B 1.81 / 45   (chroma 46 vs that grey's 15)
   *   Strong 2.50 / 117  Watch 1.78 / 73  Attention 2.29 / 84  Priority 1.31 / 67
   *   (Strong and Watch re-measured after #56)
   *   blue (links, paid tier) 1.11 / 39
   *
   * Plum, not slate, on purpose. The not-applicable row has no bar and a grey
   * label; a dark grey bar is what "greyed out / missing" looks like (card 20),
   * and every slate is the same hue family as that grey. Not blue: blue means
   * links and the paid tier (above). Distinguished from Priority and blue by
   * hue, not lightness, like the rest of this scale — so, like every band, it
   * never renders without its words. */
  --ct-band-limit:     #7A2E6E;

/* ---- Focus -------------------------------------------------------------
 *
 * Card 27 requires a visible focus indicator on every interactive element.
 * Defined here so that card 5 has a token to reach for; without one it would be
 * invented as a raw value inside a page stylesheet, which check-assets.py would
 * then report as a defect rather than having prevented.
 *
 * TWO tokens, because one value cannot serve both grounds. WCAG 1.4.11 wants
 * 3:1 against the adjacent colour, and measured:
 *
 *   blue on white  7.77:1     blue on navy            2.20:1   <- fails
 *   accent on navy 10.09:1    accent on white         1.70:1   <- fails badly
 *
 * A single ring token would therefore be invisible on exactly one of the two
 * surfaces the site actually uses. */

  --ct-focus-ring:         var(--ct-c-blue);
  --ct-focus-ring-inverse: var(--ct-accent-on-inverse);
  --ct-focus-ring-width:   2px;
  --ct-focus-ring-offset:  2px;
}
