/* ============================================================================
   Vector Analytics - design tokens
   ----------------------------------------------------------------------------
   Every colour, size and duration the site uses is named here. Nothing
   downstream hard-codes a hex value or a pixel size that belongs to a scale.

   The file has two halves, both in :root.

   1. Scale tokens. Type, space, layout, radii, motion.
   2. Colour tokens. The palette is "brand-slate": a near-neutral slate
      ground, grey furniture, a quiet blue ink, and the logo's own colours
      spent one job each. It lives in :root beside the scale, so every
      visitor gets it from the stylesheet with no attribute and no script.
      It was chosen from ten candidate palettes; the other nine, and the
      picker that compared them on real pages, were removed once the choice
      settled. They are recoverable from git history.

   Downstream CSS only ever reads the semantic names.

   ── The accent rule ────────────────────────────────────────────────────────
   The palette carries three shades of its accent and they are not
   interchangeable:

     --accent          display only, and the one emphasis mark a screen is
                       allowed. Cleared for 3:1 on every surface it can sit
                       on, including --surface-deep, but not for 4.5:1, so it
                       may not carry body text.
     --accent-text     body-size text on a light surface. Cleared for 4.5:1 on
                       --surface-1, --surface-2, --surface-3 and --accent-soft.
     --accent-bright   anything on --surface-deep. Cleared for 4.5:1 there.

   --accent-solid is the emphasis shade on light paper: the fill behind white
   text where the page's one action sits on a light surface, and the ink of
   that action where it is set as text rather than as a button, which is what
   the contact page's mail link is. --accent-hover is the same on hover. Both
   clear 4.5:1 against white and against every light surface, since they do
   both jobs.

   ── The solid affordance on a deep surface ────────────────────────────────
   The fill is paired the same way the ink is, and for the same reason. Every
   solid call to action this site paints today sits on --surface-deep: the
   home hero and the closing section of the other four pages. A dark fill
   there is a dark shape on a dark ground. The old arrangement painted
   --accent-solid on the deep surface and held its edge to the 3:1 WCAG 1.4.11
   asks of a UI component boundary, clearing it by 0.22 or less. Three to one
   is a floor, not a call to action.

     --accent-solid-bright   the fill on --surface-deep. A near-white mixed
                             from the signal's own hue at HSL lightness 97%,
                             with --surface-deep itself as its ink.
     --accent-hover-bright   the same hue at the lightness that puts it 1.45:1
                             under the fill, so the hover is a step down into
                             the teal rather than a lighter white.

   Because the ink of that button is the surface behind it, one number covers
   both directions: the ink on the fill and the fill against the deep surface
   are the same ratio, 16.84:1, against a 4.5 floor for the text and a 3
   floor for the edge. The hovered fill is read the same way, 11.60:1.

   The focus ring on that button is two rings, because one colour cannot clear
   3:1 against a near-white fill and a near-black surface at once: --accent-
   bright outside it, which is the shade already cleared for --surface-deep,
   and a --surface-deep collar inside its edge, which is the fill's own ink
   ratio again.

   What remains of --accent-solid's old window is its cap. Being legible as
   ink on --surface-3 still wants it dark:

     cap  (surface-3 + 0.05) / 4.55 - 0.05

   The floor that used to pull the other way - 3.08 x (deep + 0.05) - 0.05,
   the button's own edge on the hero - is gone with the dark fill that needed
   it. The deep surface is left where it is: it is measured against
   everything else the section paints and nothing here asks it to move.

   --accent-solid is deliberately not --accent-text, and that separation is
   the mechanism the palette is built on: the link colour is a quiet ink and
   the emphasis colour is the screen's one signal, so a page can carry a
   saturated call to action without going saturated.

   ── The current tab ────────────────────────────────────────────────────────
   Both navigations mark the page you are on in the ground's own slate rather
   than in a logo colour. On the deep header the current link is
   --fg-on-deep-1 with a 2px underline in the same ink, one reading, 15.39:1.
   On the demos rail the current link is a filled field with a bar down its
   edge, and that field has to hold a third step of tone: the rail's ground
   is --surface-2 and its hover is --surface-3, which sit 1.10:1 apart, so a
   field at hover's own lightness would leave the current page and the row
   under the cursor indistinguishable. The surface ramp has no step below
   --surface-3, so the pair below adds it:

     --slate-soft    the current-tab field, 1.22:1 under --surface-3, which
                     is a bigger tonal step than rest-to-hover. --fg-1 is the
                     ink on it, 11.58:1; --fg-2 measures 4.32:1 there and may
                     not carry the number, which is why the current row's
                     number is --fg-1 too.
     --slate-solid   the current-tab bar, non-text: 5.93:1 on its own field
                     and 7.94:1 on the rail ground.

   ── Marks and labels ───────────────────────────────────────────────────────
   Two families exist so that the furniture can stay grey while the
   affordances carry colour:

     --mark / --mark-bright    quiet structural marks: the 3px rule on a
                               capability card, the square on a list item, the
                               left rule on a callout or a demo note. Non-text,
                               held to 3:1 on every surface each can sit on.
     --label / --label-bright  eyebrow labels, CV term labels, the display key
                               on a proof figure. Body-size text, so 4.5:1.

   Both point at greys mixed from the ground's own hue, so the furniture
   carries the temperature of the paper and none of the accent.

   ── Data colours ───────────────────────────────────────────────────────────
   The colours that paint data - map fills, chart marks, the non-data fills -
   are a separate family from the page's chrome. They come from the palette
   guide (VA-DV-2026-08, the branding repository) and are declared under the
   --viz- prefix, because a data colour is bound to the surface a chart sits
   on, and the charts here sit on the palette's near-white paper. The --viz-
   block below says which guide values are carried and where this site
   departs from the guide's own table, and why.

   The --alert (alarm) ramp is single-hue and luminance-monotonic with at
   least 0.05 of relative luminance between neighbouring classes. No accent,
   mark, label or secondary hex may equal a data colour: a brand colour
   inside a map fill reads as data.

   build/tools/contrast-check.js parses this file and asserts every pairing
   named above, with no exemptions. It fails the build rather than warning,
   and it asserts that it measured a non-empty set, so it cannot pass by
   finding nothing.
   ============================================================================ */

:root {

  /* ══ Scale: type families ═════════════════════════════════════════════ */
  --font-display:  'Montserrat', system-ui, -apple-system, sans-serif;
  --font-body:     'Sora', system-ui, -apple-system, sans-serif;
  --font-mono:     'JetBrains Mono', 'Fira Code', ui-monospace, monospace;

  /* ══ Scale: type ══════════════════════════════════════════════════════
     Fixed steps for UI and prose; fluid steps for display headings. */
  --text-2xs:   11px;
  --text-xs:    12px;
  --text-sm:    13px;
  --text-base:  15px;
  --text-body:  16px;
  --text-lg:    18px;
  --text-xl:    22px;
  --text-2xl:   28px;
  --text-h3:    clamp(20px, 1.8vw, 24px);
  --text-h2:    clamp(30px, 3.4vw, 44px);
  --text-h1:    clamp(32px, 4.2vw, 52px);
  --text-hero:  clamp(36px, 5vw, 64px);

  --leading-tight:    1.1;
  --leading-snug:     1.35;
  --leading-normal:   1.5;
  --leading-relaxed:  1.65;

  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semi:     600;
  --weight-bold:     700;
  --weight-black:    800;

  --tracking-tighter: -0.035em;
  --tracking-tight:   -0.025em;
  --tracking-normal:   0;
  --tracking-wide:     0.02em;
  --tracking-wider:    0.06em;
  --tracking-widest:   0.12em;

  --measure:        62ch;
  --measure-short:  46ch;

  /* ══ Scale: spacing ═══════════════════════════════════════════════════
     4px base. Named rather than numbered so a jump between steps shows in
     a diff. */
  --space-3xs:  4px;
  --space-2xs:  8px;
  --space-xs:   12px;
  --space-sm:   16px;
  --space-md:   24px;
  --space-lg:   32px;
  --space-xl:   48px;
  --space-2xl:  64px;
  --space-3xl:  96px;
  --space-4xl:  128px;

  /* ══ Scale: layout ════════════════════════════════════════════════════ */
  --width-page:      1160px;
  --width-prose:     740px;
  --gutter:          56px;
  --section-top:     104px;
  --section-bottom:  112px;

  /* ══ Scale: radii ═════════════════════════════════════════════════════ */
  --radius-sm:    3px;
  --radius-md:    6px;
  --radius-lg:    10px;
  --radius-full:  9999px;

  /* ══ Scale: motion ════════════════════════════════════════════════════ */
  --duration-fast:    120ms;
  --duration-normal:  200ms;
  --ease-default:  cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out:      cubic-bezier(0, 0, 0.2, 1);

  --z-bg:      0;
  --z-content: 2;
  --z-header:  40;
  --z-skip:    100;

  /* ══════════════════════════════════════════════════════════════════════════
     BRAND-SLATE - Slate + logo teal signal. The palette.

     This is the palette the site ships, so it lives in :root beside the
     scale: every visitor gets it out of the stylesheet, with no attribute
     and nothing for a script to apply.

     The idea is restraint wearing the brand's own colours: rather than
     dressing the whole page in the logo palette, it asks what is left of the
     identity when the palette is only allowed where a saturated colour has
     exactly one job per screen.

     The ground is a near-neutral slate with grey furniture and quiet
     hairlines, so nothing here carries a cast and nothing but the signal is
     saturated. Each logo colour gets exactly one job:

       teal  #208ea0   the signal. --accent is the logo teal untouched and
                       --accent-solid is the same hue darkened for the fill.
       blue  #2d60ba   the ink. Darkened one step to #2c5db5, where a link
                       reads as text with an underline rather than as a
                       colour.
       mint  #71ccba   the field behind the deep sections, through
                       --secondary-bright. It is the only place a bright brand
                       colour can go on this site without becoming furniture,
                       an affordance or a map class.

     Each of the three needed measuring rather than assuming:

       --accent    #208ea0 measures 3.77 / 3.45 / 3.15:1 on the three light
                   surfaces and 4.58:1 on the deep one. It clears the 3:1
                   display floor on all four unmodified, so the logo teal
                   itself is the display shade here and no derived stand-in is
                   needed. It fails 4.5:1 on white, which is why the fill below
                   it is a different hex.

       --accent-solid  the same hue at HSL lightness 30% instead of 37.6%.
                   It is the fill on light paper and the ink of the action
                   where that action is set as text, and its cap is being
                   legible as ink on --surface-3:

                     cap  (surface-3 + 0.05) / 4.55 - 0.05  =  0.1384

                   #197180 sits at 0.1358, just under it. It no longer paints
                   on the deep surface: --accent-solid-bright does that, and
                   the pair below is the reason.

       --accent-solid-bright / --accent-hover-bright  the action where it
                   sits on --surface-deep, which on this site is every one of
                   them: the home hero and the closing section of the other
                   four pages. #f2fbfc is the logo teal's own hue at HSL
                   lightness 97%, and --surface-deep is its ink, so the ink on
                   the fill and the fill against the surface behind it are one
                   reading, 16.84:1. The hover is the same hue at lightness
                   74.5%, 11.60:1 read the same way and 1.45:1 under the fill,
                   which is a step down into the teal rather than a lighter
                   white. What was painted here before was #197180 at 3.13:1,
                   a dark teal on a dark ground.

       --accent-bright  the brief for this theme proposed the mint here, and
                   the mint does clear it: #71ccba measures 9.31:1 on #131826.
                   It is not what is painted. --accent-bright is the ink on the
                   deep surface - deep-prose links and the focus ring - and a
                   link that is blue on paper and mint on the hero is two link
                   colours, not one. So the blue is carried across instead, at
                   HSL lightness 72%, and the mint takes the one deep-surface
                   job that is not ink. The current-page underline in the
                   header is not this shade: a navigation state is not a link
                   colour, so it is drawn in --fg-on-deep-1, the same ink as
                   the text it underlines.

     The map and the charts are painted in the --viz- data colours below,
     which the palette guide fixes. The alarm ramp is an orange-red, 174
     degrees off the signal.
     ══════════════════════════════════════════════════════════════════════════ */

  --surface-deep:        #131826;
  --surface-1:           #fcfcfd;
  --surface-2:           #f1f2f6;
  --surface-3:           #e6e8ee;

  --fg-1:                #171a24;   /* 16.93 / 15.52 / 14.17 */
  --fg-2:                #575e70;   /* 6.32 / 5.79 / 5.29 */
  --fg-3:                #838b9e;   /* 3.33 / 3.05 */

  --fg-on-deep-1:        #edeff4;   /* 15.39 */
  --fg-on-deep-2:        #a8afbf;   /* 8.05 */

  --accent:              #208ea0;   /* logo teal, 3.77 / 3.45 / 3.15 light, 4.58 deep */
  --accent-text:         #2c5db5;   /* logo blue at L 44%, 6.13 / 5.62 / 5.13 */
  --accent-bright:       #8cace3;   /* same hue at L 72%, 7.69 on deep */
  --accent-solid:        #197180;   /* logo teal at L 30%: white on it 5.65, */
                                    /* as ink 5.51 / 5.05 / 4.61 */
  --accent-hover:        #145b66;   /* white on it 7.73, as ink 7.54 / 6.91 / 6.31 */
  --accent-solid-bright: #f2fbfc;   /* the on-deep fill, 16.84 both ways */
  --accent-hover-bright: #93dde9;   /* hovered, 11.60 both ways, 1.45 on the fill */
  --accent-soft:         #e2f1f4;   /* the ink on it 5.43, --fg-1 on it 14.98 */

  --slate-soft:          #ced3df;   /* the current-tab field: 1.22 under --surface-3, --fg-1 on it 11.58 */
  --slate-solid:         #3f4a61;   /* the current-tab bar: 5.93 on its field, 7.94 on --surface-2 */

  --mark:                #767d8e;   /* 4.02 / 3.68 / 3.36 - C's grey furniture */
  --mark-bright:         #7a8398;   /* 4.66 on deep */
  --label:               #4e5a72;   /* 6.76 / 6.20 / 5.66 */
  --label-bright:        #949db4;   /* 6.53 on deep */

  --secondary:           #26695c;   /* logo mint at L 28%, 6.29 / 5.76 */
  --secondary-bright:    #71ccba;   /* the mint itself, 9.31 on deep */

  --color-ok:            #2d7831;
  --color-warn:          #975c07;
  --color-alert:         #c92a2a;
  --color-ok-bg:         #e6f1e7;
  --color-warn-bg:       #f5ecdd;
  --color-alert-bg:      #f9e7e7;
  --color-ok-on-deep:    #6fcf75;
  --color-warn-on-deep:  #ffd43b;
  --color-alert-on-deep: #ff8a80;

  --border-1:            #dcdee6;
  --border-2:            #858b97;   /* 3.34 / 3.06 */
  --border-on-deep-1:    rgba(255,255,255,0.14);
  --border-on-deep-2:    rgba(255,255,255,0.08);

  /* ══ Data colours, from the palette guide ═════════════════════════════
     VA-DV-2026-08. A data colour belongs to the paper the chart sits on,
     not to the page's chrome, so this family is fixed by the guide rather
     than derived from the palette.

     The sequential ramps are seq-teal. The guide prints one ladder per class
     count and every ladder opens on #e9fafc, which sits under 3.5 dE00 off
     the paper this site draws its maps on: on a map whose counties are
     stroked in the paper colour, a county in that class is a hole rather
     than a class, and build/tools/map-check.js holds the palest fill a full
     class-step off the paper. So a k-class map here takes rungs 2 to k+1 of
     the guide's own (k+1)-class ladder: every hex is a guide hex, the
     equal-lightness spacing survives, and the near-paper rung stays off the
     map. BUILDLOG entry 34 carries the measurements. */
  --viz-seq3-1: #85bdc9;
  --viz-seq3-2: #008296;
  --viz-seq3-3: #004452;

  --viz-seq4-1: #9eccd5;
  --viz-seq4-2: #4da0b1;
  --viz-seq4-3: #007285;
  --viz-seq4-4: #004452;

  --viz-seq5-1: #add5dd;
  --viz-seq5-2: #70b1bf;
  --viz-seq5-3: #1b8ea3;
  --viz-seq5-4: #00687a;
  --viz-seq5-5: #004452;

  --viz-seq6-1: #b7dbe2;
  --viz-seq6-2: #85bdc9;
  --viz-seq6-3: #4da0b1;
  --viz-seq6-4: #008296;
  --viz-seq6-5: #006274;
  --viz-seq6-6: #004452;

  /* The categorical set, in the guide's order. The charts on the demos page
     carry at most two series, so only the first two travel; a chart that
     grows a third series takes the guide's moss #8b9f39 next. Each fill
     ships with the darkened edge the guide gives it. */
  --viz-cat-1:      #008ea1;
  --viz-cat-1-edge: #005e6b;
  --viz-cat-2:      #5f401d;
  --viz-cat-2-edge: #2e1b00;

  /* A greyscale data pair, which the guide does not print because the guide
     does not draw a plot whose only colour is the selection. The dashboard's
     funnel gives its one accent to the county being read and paints the
     other eleven hundred in these, so a reader can see at a glance which
     mark carries meaning. The guide's three greys below cannot do this job:
     a suppressed cell and a county with a published rate are different
     things and must not share an ink. Both are measured against the paper
     they are drawn on in contrast-check.js. */
  --viz-mono:      #7f889c;   /* 3.47 / 3.18 on the two light surfaces */
  --viz-mono-deep: #414c63;   /* 8.40 / 7.70 */

  /* The non-data fills. A cell that is not an estimate is never painted in
     a ramp colour, and colour alone is never the channel: the 45-degree
     hatch is what says suppressed and the dot stipple is what says
     unreliable, both drawn in the non-data ink. These are fills on the map,
     not surfaces, and each owes the paper the same CIEDE2000 distance two
     neighbouring classes owe each other; map-check.js measures both. */
  --viz-nd-suppressed: #b6bcc4;
  --viz-nd-unreliable: #d4d8de;
  --viz-nd-ink:        #55637a;

  --alert-1: #fcefec;  --alert-1-on: var(--fg-1);
  --alert-2: #f3d1ca;  --alert-2-on: var(--fg-1);
  --alert-3: #e5aba1;  --alert-3-on: var(--fg-1);
  --alert-4: #d08174;  --alert-4-on: var(--fg-1);
  --alert-5: #bb4a39;  --alert-5-on: #ffffff;
  --alert-6: #8d2a1d;  --alert-6-on: #ffffff;

  --shadow-1:  0 1px 2px rgba(19,24,38,0.06), 0 2px 8px rgba(19,24,38,0.05);
  --shadow-2:  0 2px 6px rgba(19,24,38,0.08), 0 12px 28px rgba(19,24,38,0.10);
}

/* Responsive layout tokens. Redefining the token beats overriding twenty
   padding rules further down the cascade. */
@media (max-width: 1100px) {
  :root { --gutter: 40px; --section-top: 88px;  --section-bottom: 96px; }
}
@media (max-width: 900px) {
  :root { --gutter: 28px; --section-top: 72px;  --section-bottom: 80px; }
}
@media (max-width: 640px) {
  :root { --gutter: 20px; --section-top: 56px;  --section-bottom: 64px; }
}
