/* ==========================================================================
   Masimo Chemicals South Africa
   Design system: graphite + acid yellow, sharp geometry, Archivo variable.
   Theme is locked dark for the whole site. Sections tint within the graphite
   family; nothing flips to a light surface mid-scroll.
   ========================================================================== */

/* --- 1. fonts ------------------------------------------------------------ */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('../fonts/archivo-latin-1.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('../fonts/archivo-latin-ext-0.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/plexmono-latin-1.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/plexmono-latin-3.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/plexmono-latin-5.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- 2. tokens ----------------------------------------------------------- */

/* Brand palette. Values are sampled from the live masimochem.com homepage, so
   they match production exactly. Documented in docs/brand-colours.md, which is
   the source of truth: no colour appears here that is not named there.

     navy    the ground. Nav, footer, section bands, headings, hero overlays
     green   interaction. Links, buttons, hovers, pressed and current states
     yellow  brand mark, section dividers, footer column headings, focus rings

   Yellow is never text on a light surface. It scores 1.2:1 on white, so it is
   only ever ink on navy or a non-text stroke. Green never sits as text on navy
   at --green-500 (3.7:1); --green-300 is the navy-surface variant. */
:root {
  /* navy */
  --navy-900: #02112E;
  --navy-800: #021A48;
  --navy-600: #022F68;
  --navy-500: #2A4878;
  --navy-400: #5C7BA8;
  --navy-300: #8A9CBE;
  --navy-200: #AEC0DC;
  --navy-050: #E8EEF7;

  /* green */
  --green-600: #2E6B2A;
  --green-500: #3C8637;
  --green-300: #7FD07A;

  /* yellow */
  --yellow-400: #FCEE0F;

  /* neutrals */
  --white: #FFFFFF;
  --grey-700: #595959;
  /* The muted tier is measured against --navy-050, not against white: the tinted
     bands are the darkest light ground on the site, and a grey chosen on white
     lands at 4.07:1 there. #696969 holds 4.7:1 on navy-050 and 5.5:1 on white. */
  --grey-600: #696969;
  /* Control borders are measured against --navy-050 as well. A white input on a
     navy-050 band differs from its ground by 1.2:1, so the border is the only
     thing delineating the control and it has to carry the whole 3:1 itself.
     #888888 gives 3.0:1 on navy-050 and 3.6:1 on white. */
  --grey-400: #888888;
  --grey-300: #BFBFBF;
  --grey-200: #D8D8D8;
  --grey-100: #F2F2F2;

  /* utility */
  --rust-600: #C4551F;

  /* Semantic aliases. Component CSS reaches for these, not the raw scale. */
  --colour-surface: var(--white);
  --colour-surface-alt: var(--navy-050);
  --colour-surface-inverse: var(--navy-800);
  --colour-text: var(--grey-700);
  --colour-heading: var(--navy-800);
  --colour-text-inverse: var(--white);
  --colour-link: var(--green-600);
  --colour-link-inverse: var(--green-300);
  --colour-accent: var(--yellow-400);
  --colour-warning: var(--rust-600);

  /* Surface roles.

     The site has two grounds, white and navy, and a block has to work on
     either: the CTA band, the footer and the page headers are navy, the content
     sections are white. Rather than writing every component twice, each one
     reads these five and the SURFACE decides what they resolve to. :root holds
     the light values; the navy list below swaps them. That is why a hairline
     inside .foot comes out navy-500 and the same hairline inside .sec comes out
     grey-200 with no component-level override.

       --s-strong   headings, values, input text, the emphatic tier
       --s-text     body copy
       --s-muted    labels, captions, meta, the quiet tier
       --s-line     default hairline
       --s-line-2   stronger divider, control borders
       --s-raise    the next surface up: row hover, card fill, menu ground
       --s-link     interaction on this surface: links, hovers, current state
       --s-on-link  the ink that sits on --s-link when it becomes a fill

   The two link tokens are the reason green never fails a contrast check. On
   white it resolves to --green-600 (6.5:1); on navy to --green-300 (9.0:1).
   --green-500 as text on navy is 3.7:1 and is not reachable from here. */
  --s-bg: var(--white);
  --s-strong: var(--navy-800);
  --s-text: var(--grey-700);
  --s-muted: var(--grey-600);
  --s-line: var(--grey-200);
  --s-line-2: var(--grey-300);
  --s-raise: var(--grey-100);
  --s-link: var(--green-600);
  --s-on-link: var(--white);

  /* sharp geometry, one radius system */
  --r: 2px;
  --r-lg: 3px;

  --shell: 1360px;
  --gut: clamp(1.25rem, 4vw, 3.5rem);
  --sec-y: clamp(4.75rem, 8.5vw, 8rem);
  --sec-y-end: clamp(5.5rem, 9.5vw, 9rem);

  /* Scale is planned against the measure it sits in, not chosen for impact.
     Display holds the hero to two lines; h1 holds a section head to three in
     the narrow sticky column. */
  --fs-display: clamp(2.4rem, 5.1vw, 4.4rem);
  --fs-h1: clamp(1.95rem, 3.5vw, 2.95rem);
  --fs-h2: clamp(1.65rem, 2.7vw, 2.35rem);
  --fs-h3: clamp(1.1rem, 1.4vw, 1.35rem);
  --fs-body: clamp(1rem, 0.35vw + 0.92rem, 1.09rem);
  --fs-sm: 0.9375rem;
  --fs-mono: 0.75rem;
  --fs-mono-lg: 0.8125rem;
  --fs-chip: 0.6875rem;
  --fs-pill: 0.625rem;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.4, 0, 0.2, 1);

  /* z-scale, documented, no ad-hoc values anywhere else */
  --z-base: 0;
  --z-raise: 10;
  --z-nav: 40;
  --z-sheet: 50;

  color-scheme: light;
}

/* The navy surfaces. Listed once, here, so adding a band means adding it to
   this list and nothing else. [data-surface] is honoured too, for a block that
   needs to flip without earning its own class. */
.nav,
.sheet,
.foot,
.hero,
.phead,
.rail,
.flow,
.cta,
.sec--hseq,
.pcard,
.icard,
[data-surface='navy'] {
  --s-bg: var(--navy-800);
  --s-strong: var(--white);
  --s-text: var(--navy-200);
  --s-muted: var(--navy-300);
  --s-line: var(--navy-500);
  --s-line-2: var(--navy-400);
  --s-raise: var(--navy-600);
  --s-link: var(--green-300);
  --s-on-link: var(--navy-800);
}

[data-surface='white'] {
  --s-bg: var(--white);
  --s-strong: var(--navy-800);
  --s-text: var(--grey-700);
  --s-muted: var(--grey-600);
  --s-line: var(--grey-200);
  --s-line-2: var(--grey-300);
  --s-raise: var(--grey-100);
  --s-link: var(--green-600);
  --s-on-link: var(--white);
}

/* Uppercase mono at wide tracking is harder to read small, and a handheld screen
   sits further from the eye than a monitor does. Labels, chips and doc pills all
   step up on a narrow viewport or a coarse pointer. The pointer query is the
   part that matters: it catches a tablet in portrait at 768 or 1024, which a
   width breakpoint alone leaves on desktop sizes. */
@media (max-width: 900px), (pointer: coarse) {
  :root {
    --fs-mono: 0.8125rem;
    --fs-mono-lg: 0.875rem;
    --fs-chip: 0.8125rem;
    --fs-pill: 0.75rem;
  }
}

/* --- 3. reset ------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 7rem;
  /* `clip`, never `hidden`. `overflow-x: hidden` makes the element a scroll
     container, which breaks position: sticky and programmatic scrolling. */
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  background: var(--colour-surface);
  color: var(--colour-text);
  font-family: 'Archivo', system-ui, sans-serif;
  font-size: var(--fs-body);
  font-weight: 400;
  font-stretch: 100%;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
img, video { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }

/* Body copy is the grey tier; headings are navy on white and white on navy, and
   they get there through --s-strong so a heading dropped into the footer or the
   CTA band needs no override. */
h1, h2, h3, h4, h5, h6,
.d-1, .d-2, .d-3, .h-4 { color: var(--s-strong); }

/* Focus rings are yellow, the one colour that can sit on navy and on white
   without being mistaken for content. Yellow alone is 1.2:1 on white though,
   which is not a perceivable indicator, so a navy keyline carries the contrast
   on light surfaces and vanishes into the ground on navy ones. The ring reads
   yellow on both. */
:focus-visible {
  outline: 3px solid var(--colour-accent);
  outline-offset: 2px;
  border-radius: var(--r);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--navy-800) 60%, transparent);
}

::selection { background: var(--colour-accent); color: var(--navy-800); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.u-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip {
  position: fixed; top: 0; left: 50%; translate: -50% -120%;
  z-index: var(--z-sheet);
  background: var(--colour-accent); color: var(--navy-800);
  padding: 0.7rem 1.2rem; border-radius: 0 0 var(--r) var(--r);
  font-weight: 600; font-size: var(--fs-sm);
  transition: translate 0.2s var(--ease);
}
/* :focus as well as :focus-visible, so the skip link also reveals itself when
   focus is moved programmatically rather than by keyboard heuristics */
.skip:focus, .skip:focus-visible { translate: -50% 0; }

/* The film-grain layer that used to sit here is gone. It was a dark-editorial
   device: an overlay blend of noise does almost nothing on white and only
   muddies the navy bands, and the brand is flat colour throughout. */

/* --- 4. type ------------------------------------------------------------- */

.d-1, .d-2, .d-3 {
  font-family: 'Archivo', sans-serif;
  font-stretch: 112%;
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.d-1 { font-size: var(--fs-display); letter-spacing: -0.034em; }
.d-2 { font-size: var(--fs-h1); }
.d-3 { font-size: var(--fs-h2); }

.h-4 {
  font-family: 'Archivo', sans-serif;
  font-stretch: 106%;
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.25;
  letter-spacing: -0.014em;
}

.lede {
  font-size: clamp(1.06rem, 0.6vw + 0.95rem, 1.3rem);
  line-height: 1.55;
  color: var(--s-text);
  max-width: 46ch;
  text-wrap: pretty;
}

.prose { max-width: 64ch; color: var(--s-text); text-wrap: pretty; }
.prose > * + * { margin-top: 1.05em; }
.prose strong { color: var(--s-strong); font-weight: 600; }

.mono {
  font-family: 'Plex Mono', ui-monospace, monospace;
  font-size: var(--fs-mono);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* the small caps label above a section headline. Rationed on purpose:
   never more than one per three sections across a page. */
.eyebrow {
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--s-strong);
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
/* 3px, not the 1px this was. A hairline of yellow on white reads as muddy olive
   rather than as the brand colour, which is the defect the old site had under
   every section title. Thickened, it reads as yellow on both grounds. */
.eyebrow::before {
  content: '';
  width: 1.75rem; height: 3px;
  background: var(--colour-accent);
  flex: none;
}

.num {
  font-family: 'Plex Mono', monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* --- 5. layout ---------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.sec { padding-block: var(--sec-y) var(--sec-y-end); position: relative; }
/* The light alternation. Navy-050 is the only tint content sections take: the
   ground stays white and the band is a wash of the brand navy, never a grey. */
/* On a navy-050 band the next surface up is white, not a grey, so row hovers and
   raised panels inside a tinted section resolve upward instead of muddying. */
.sec--tint { background: var(--colour-surface-alt); --s-raise: var(--white); }
.sec--tint-2 { background: var(--grey-100); }
.sec--edge { border-top: 1px solid var(--s-line); }

/* HSEQ is a navy band, the commitment surface. It follows the supply-chain
   section, which is also navy, so the two are separated by a hard 3px yellow
   rule rather than a hairline: adjacent navy bands with a 1px divider read as
   one long dark region. */
.sec--hseq {
  background: var(--s-bg);
  border-top: 3px solid var(--colour-accent);
}
.sec--hseq .commit__row:hover { background: var(--s-raise); }
.sec--hseq .commit__k svg { width: 20px; height: 20px; }

.rule { height: 1px; background: var(--s-line); border: 0; }

/* --- 6. controls -------------------------------------------------------- */

/* Green owns interaction, so the primary action is a green fill. It is the one
   control that does NOT read the surface: --green-500 with white ink looks
   identical on white and on navy, which is what you want of the primary action
   when the same button appears in the nav, in the hero and in the footer CTA. */
.btn {
  --btn-bg: var(--green-500);
  --btn-fg: var(--white);
  --btn-bd: var(--green-500);
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.85rem 1.4rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--r);
  font-weight: 600;
  font-stretch: 104%;
  font-size: var(--fs-sm);
  letter-spacing: 0.005em;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s var(--ease-io), border-color 0.2s var(--ease-io),
    translate 0.12s var(--ease-io), color 0.2s var(--ease-io);
}
/* darker on hover, not lighter: --green-600 takes white ink from 4.5:1 to 6.5:1,
   so the label gets more legible under the pointer rather than less */
.btn:hover { --btn-bg: var(--green-600); --btn-bd: var(--green-600); }
.btn:active { translate: 0 1px; }
.btn svg { width: 1.05em; height: 1.05em; flex: none; }

/* Secondary. Outlined in the surface's green, filling on hover. --s-on-link is
   what makes one rule work on both grounds: white ink on --green-600 over
   white, navy ink on --green-300 over navy. */
.btn--line {
  --btn-bg: transparent;
  --btn-fg: var(--s-strong);
  --btn-bd: var(--s-link);
}
.btn--line:hover {
  --btn-bg: var(--s-link);
  --btn-bd: var(--s-link);
  --btn-fg: var(--s-on-link);
}

.btn--sm { padding: 0.6rem 1rem; font-size: 0.875rem; }

/* text-level action, third tier so the page is not all filled buttons */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--s-link);
  padding-block: 0.2rem;
  border-bottom: 1px solid color-mix(in srgb, var(--s-link) 34%, transparent);
  transition: border-color 0.2s var(--ease-io), gap 0.2s var(--ease-io);
}
.tlink:hover { border-color: var(--s-link); gap: 0.6rem; }
/* flex: none or the arrow shrinks to zero width in a tight flex row, which is
   exactly what happened in .pcard__foot at 320px */
.tlink svg { width: 0.95em; height: 0.95em; flex: none; }

/* --- 7. navigation ------------------------------------------------------ */

.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: color-mix(in srgb, var(--navy-800) 84%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  /* 3px reserved from the start, transparent until the bar sticks. Animating
     border-WIDTH would reflow the document on every frame; only the colour
     moves. */
  border-bottom: 3px solid transparent;
  transition: border-color 0.25s var(--ease-io), background 0.25s var(--ease-io);
}
@media (prefers-reduced-transparency: reduce) {
  .nav { background: var(--navy-800); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
/* Stuck state earns the yellow rule. Below the navy bar sits a white page, so a
   navy-on-navy hairline says nothing here; the brand divider does. */
.nav[data-stuck='true'] {
  border-bottom-color: var(--colour-accent);
  background: var(--navy-800);
}

/* Bar height is derived from the wordmark, not chosen first. The lockup is a
   near-square three-line stack (~1.15:1), and it stops being legible below about
   56px tall, so the bar is sized to hold that with clearance. */
/* Client asked for a larger mark and authorised a taller bar to carry it, so the
   bar runs past the 80px that suits a horizontal wordmark. That is deliberate:
   this lockup is a near-square three-line stack and needs the height. */
.nav {
  --logo-h: clamp(62px, 5.6vw, 72px);
  --nav-h: calc(var(--logo-h) + 22px);
}
.nav[data-stuck='true'] {
  --logo-h: clamp(52px, 4.7vw, 60px);
  --nav-h: calc(var(--logo-h) + 20px);
}

.nav__in {
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
}
/* The bar tightens when it sticks, but the change is not transitioned: .nav is
   in flow, so animating its height reflows the whole document on every frame.
   Snapping once at the threshold costs one reflow instead of fifteen, and the
   hairline and background above still transition, which carries the state. */

.brand { display: flex; align-items: center; flex: none; margin-right: auto; }

/* Sized by HEIGHT, never width. A width rule on a near-square lockup puts an
   unpredictable height into a fixed-height bar, and the mark spills out of the
   header. Height is the axis the bar constrains, so it is the axis to set. */
.brand img {
  height: var(--logo-h, 52px);
  width: auto;
  max-width: none;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 1.8vw, 1.9rem);
}
.nav__link {
  position: relative;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--s-text);
  padding-block: 0.4rem;
  white-space: nowrap;
  transition: color 0.18s var(--ease-io);
}
.nav__link:hover { color: var(--s-strong); }
.nav__link[aria-current='page'] { color: var(--s-strong); }
/* Current page is a state the visitor arrived at by acting, so it is green, not
   the brand yellow. --s-link is --green-300 here, 9.0:1 on the navy bar. */
.nav__link[aria-current='page']::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -0.15rem;
  height: 2px;
  background: var(--s-link);
}

/* products dropdown */
.nav__group { position: relative; }
.nav__toggle {
  display: inline-flex; align-items: center; gap: 0.35rem;
  background: none; border: 0; padding: 0.4rem 0;
  font-size: var(--fs-sm); font-weight: 500; color: var(--s-text);
  cursor: pointer;
  transition: color 0.18s var(--ease-io);
}
.nav__toggle:hover, .nav__group[data-open='true'] .nav__toggle { color: var(--s-strong); }
.nav__toggle svg { width: 0.85em; height: 0.85em; transition: rotate 0.2s var(--ease-io); }
.nav__group[data-open='true'] .nav__toggle svg { rotate: 180deg; }

/* The menu is a raised panel on an already-navy bar, so it re-bases the surface:
   its own ground is navy-600 and the next step up is navy-500. Without this,
   --s-raise still resolves to navy-600 and the row hover would be invisible. */
.nav__menu {
  --s-bg: var(--navy-600);
  --s-raise: var(--navy-500);
  position: absolute;
  top: calc(100% + 0.7rem);
  left: -0.9rem;
  min-width: 268px;
  background: var(--s-bg);
  border: 1px solid var(--s-line);
  border-radius: var(--r-lg);
  padding: 0.4rem;
  box-shadow: 0 24px 48px -12px color-mix(in srgb, var(--navy-900) 55%, transparent),
    inset 0 1px 0 color-mix(in srgb, var(--white) 8%, transparent);
  opacity: 0;
  translate: 0 -6px;
  visibility: hidden;
  transition: opacity 0.18s var(--ease-io), translate 0.18s var(--ease-io),
    visibility 0.18s;
}
.nav__group[data-open='true'] .nav__menu {
  opacity: 1; translate: 0 0; visibility: visible;
}
.nav__menu a {
  display: block;
  padding: 0.6rem 0.75rem;
  border-radius: var(--r);
  transition: background 0.15s var(--ease-io);
}
.nav__menu a:hover { background: var(--s-raise); }
.nav__menu strong {
  display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--s-strong);
}
.nav__menu span {
  display: block; font-size: 0.8125rem; color: var(--s-muted); line-height: 1.4;
}

.nav__cta { flex: none; }

.burger {
  display: none;
  background: none; border: 1px solid var(--s-line);
  border-radius: var(--r);
  width: 42px; height: 42px;
  align-items: center; justify-content: center;
  cursor: pointer; color: var(--s-strong);
}
.burger svg { width: 22px; height: 22px; }

/* mobile sheet */
.sheet {
  position: fixed; inset: 0;
  z-index: var(--z-sheet);
  background: var(--s-bg);
  padding: 1.25rem var(--gut) 2rem;
  display: flex; flex-direction: column;
  translate: 0 -100%;
  visibility: hidden;
  /* visibility switches with an explicit 0s step, delayed on the way out so the
     panel stays visible while it slides. Interpolating visibility leaves the
     computed value ambiguous on the frame the panel opens, and focus() is
     silently ignored on a hidden element. */
  transition: translate 0.34s var(--ease), visibility 0s linear 0.34s;
  overflow-y: auto;
}
.sheet[data-open='true'] {
  translate: 0;
  visibility: visible;
  transition: translate 0.34s var(--ease), visibility 0s linear 0s;
}
/* same derivation as the bar, so the mark cannot spill here either */
.sheet { --logo-h: clamp(62px, 5.6vw, 72px); }
.sheet__top { display: flex; align-items: center; height: calc(var(--logo-h) + 20px); }
.sheet__top .brand { margin-right: auto; }
.sheet nav { margin-top: 1.5rem; border-top: 1px solid var(--s-line); }
.sheet nav a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.05rem 0;
  border-bottom: 1px solid var(--s-line);
  font-family: 'Archivo', sans-serif;
  font-stretch: 108%;
  font-size: 1.3rem; font-weight: 600;
  letter-spacing: -0.015em;
  /* explicit: an <a> inherits the body grey, which is the white-surface tier */
  color: var(--s-strong);
}
.sheet nav a[data-sub] {
  font-size: 1.02rem; font-weight: 500; font-stretch: 100%;
  color: var(--s-text); padding-left: 1.15rem;
}
.sheet nav a svg { width: 1rem; height: 1rem; color: var(--s-muted); }
.sheet__foot { margin-top: auto; padding-top: 2rem; display: grid; gap: 0.75rem; }
.sheet__foot .btn { justify-content: center; }

@media (max-width: 1023px) {
  .nav__links, .nav__cta { display: none; }
  .burger { display: inline-flex; }
}

/* --- 8. hero ------------------------------------------------------------ */

.hero {
  position: relative;
  min-height: min(94dvh, 820px);
  display: flex;
  align-items: flex-end;
  padding-block: clamp(4rem, 9vh, 6rem) clamp(2.5rem, 6vh, 4rem);
  overflow: hidden;
  isolation: isolate;
}
.hero__media {
  position: absolute; inset: 0;
  z-index: -2;
}
.hero__media video, .hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
  /* the source footage is a night plant, so lift it enough that the site does
     not read as a black box with a photograph peeking in at one corner */
  filter: brightness(1.32) contrast(1.04) saturate(1.06);
}
/* Scrim graded across the diagonal so the copy side holds AAA contrast while the
   plant stays legible on the open side. This is the one kind of gradient the
   brand keeps: it is a legibility scrim in a single navy, not a two-colour
   brand gradient, and white type over photography cannot be done without it.
   --scrim is navy-800, so the overlay is the same ink as the nav above it. */
.hero__scrim {
  --scrim: var(--navy-800);
  position: absolute; inset: 0;
  z-index: -1;
  background:
    linear-gradient(78deg,
      color-mix(in srgb, var(--scrim) 95%, transparent) 6%,
      color-mix(in srgb, var(--scrim) 84%, transparent) 36%,
      color-mix(in srgb, var(--scrim) 42%, transparent) 68%,
      color-mix(in srgb, var(--scrim) 62%, transparent) 100%),
    linear-gradient(to top, var(--scrim) 2%, transparent 40%);
}

/* Copy sits left over the video and stops well short of the right edge, so the
   plant footage stays legible as the second half of the composition. */
/* Sized in rem, not ch: `ch` here resolves against the body font, which would
   squeeze the display headline into a measure meant for body copy. */
.hero__copy {
  display: grid;
  gap: clamp(1.15rem, 2vw, 1.65rem);
  width: min(100%, 54rem);
  justify-items: start;
}
.hero h1 { text-wrap: balance; }
/* The emphasised words in the headline are the one place yellow is allowed to be
   type, and it is allowed because the ground is navy: 14.0:1. The same rule on a
   white section would be 1.2:1, which is why nothing outside a navy surface
   reaches for --colour-accent as a text colour. */
.hero h1 em, .sec--hseq .d-2 em { font-style: normal; color: var(--colour-accent); }
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

@media (max-width: 900px) {
  .hero { align-items: center; min-height: min(100dvh, 760px); }
  .hero__scrim {
    background:
      linear-gradient(to top, var(--scrim) 4%,
        color-mix(in srgb, var(--scrim) 88%, transparent) 48%,
        color-mix(in srgb, var(--scrim) 66%, transparent) 100%);
  }
}

/* --- 9. figures rail (under hero, no card boxes) ------------------------ */

/* Yellow marks every seam where a navy band meets the white page. That is the
   brand's divider role and the only structural job yellow has here. 3px because
   a hairline of yellow against white reads as olive rather than as the mark.
   Stated once, applied to each band's outward edge:

     .rail  .phead      bottom edge, handing off to content
     .flow  .cta  .foot  .sec--hseq   top edge, arriving from content
     .nav[data-stuck]    bottom edge, once the bar detaches */
.rail, .phead { border-bottom: 3px solid var(--colour-accent); }
.flow, .cta, .foot, .sec--hseq { border-top: 3px solid var(--colour-accent); }

/* Every navy block that takes its ground from photography states that ground
   explicitly. The page is white now: a block relying on an image to be dark
   would render white-on-white for as long as the image is missing or still in
   flight, which on the dark build was impossible and here is one 404 away. */
.hero, .phead, .flow, .cta, .pcard, .icard { background: var(--s-bg); }

.rail {
  border-top: 1px solid var(--s-line);
  background: var(--s-bg);
}
.rail__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.rail__cell {
  padding: clamp(1.6rem, 3vw, 2.4rem) clamp(1rem, 2vw, 1.75rem);
  border-left: 1px solid var(--s-line);
}
.rail__cell:first-child { border-left: 0; padding-left: 0; }
.rail__grid { padding-inline: var(--gut); }
.rail__n {
  font-family: 'Archivo', sans-serif;
  font-stretch: 116%;
  font-weight: 700;
  font-size: clamp(2.1rem, 3.6vw, 3.1rem);
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--s-strong);
}
.rail__n sub {
  font-size: 0.34em; font-weight: 600; bottom: 0;
  color: var(--colour-accent); margin-left: 0.14em; letter-spacing: 0;
}
.rail__t { margin-top: 0.65rem; color: var(--s-muted); line-height: 1.5; }

@media (max-width: 860px) {
  .rail__grid { grid-template-columns: repeat(2, 1fr); }
  .rail__cell:nth-child(3) { border-left: 0; padding-left: 0; }
  .rail__cell:nth-child(-n+2) { border-bottom: 1px solid var(--s-line); }
}
@media (max-width: 460px) {
  .rail__grid { grid-template-columns: 1fr; }
  .rail__cell { border-left: 0; padding-left: 0; border-bottom: 1px solid var(--s-line); }
  .rail__cell:last-child { border-bottom: 0; }
}

/* --- 10. editorial split with sticky heading --------------------------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 5vw, 5.5rem);
  align-items: start;
}
.split__head { position: sticky; top: 8.5rem; display: grid; gap: 1.4rem; }
.split__body { display: grid; gap: clamp(1.75rem, 3vw, 2.5rem); }

@media (max-width: 940px) {
  .split { grid-template-columns: 1fr; gap: 2.25rem; }
  .split__head { position: static; }
}

/* image that breaks the container to the right edge */
.bleed-r {
  position: relative;
  margin-right: calc(-1 * var(--gut));
}
.bleed-r img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--r-lg);
}
@media (min-width: 1400px) { .bleed-r { margin-right: 0; } }

.figure { display: grid; gap: 0.85rem; }
.figure img { border-radius: var(--r-lg); width: 100%; object-fit: cover; }
.figure figcaption { color: var(--s-muted); font-size: 0.875rem; line-height: 1.5; }

/* facts as hairline rows, grouped, not a bordered table */
.facts { display: grid; gap: 0; border-top: 1px solid var(--s-line); }
.facts > div {
  display: grid;
  /* label column sized to the longest mono label, not to an even split, so the
     value starts close to its label instead of across a dead gutter */
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 2fr);
  gap: 1rem 1.5rem;
  padding-block: 1.05rem;
  border-bottom: 1px solid var(--s-line);
  align-items: baseline;
}
.facts dt { color: var(--s-muted); }
.facts dd { color: var(--s-strong); }
@media (max-width: 620px) {
  .facts > div { grid-template-columns: 1fr; gap: 0.3rem; }
}

/* --- 11. product bento (3 items, 3 cells, asymmetric) ------------------ */

.bento {
  display: grid;
  grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr);
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.4vw, 1.15rem);
}
.bento > :first-child { grid-row: span 2; }

.pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 292px;
  padding: clamp(1.35rem, 2.4vw, 2.1rem);
  border: 1px solid var(--s-line);
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  transition: border-color 0.3s var(--ease-io);
}
.bento > :first-child.pcard { min-height: 420px; }
.pcard:hover { border-color: var(--s-line-2); }

.pcard__bg { position: absolute; inset: 0; z-index: -2; }
.pcard__bg img {
  width: 100%; height: 100%; object-fit: cover;
  transition: scale 0.7s var(--ease);
}
.pcard:hover .pcard__bg img { scale: 1.045; }
.pcard::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--navy-900) 95%, transparent) 6%,
    color-mix(in srgb, var(--navy-900) 80%, transparent) 46%,
    color-mix(in srgb, var(--navy-900) 45%, transparent) 100%);
}

.pcard__ico {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--colour-accent) 42%, transparent);
  border-radius: var(--r);
  color: var(--colour-accent);
  margin-bottom: auto;
}
.pcard__ico svg { width: 21px; height: 21px; }

.pcard h3 { margin-top: 1.5rem; }
.pcard p { color: var(--s-text); font-size: var(--fs-sm); margin-top: 0.55rem; max-width: 40ch; }

.pcard__grades {
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  margin-top: 1.15rem;
}
.pcard__grades li {
  border: 1px solid var(--s-line-2);
  border-radius: var(--r);
  padding: 0.28rem 0.5rem;
  background: color-mix(in srgb, var(--navy-900) 58%, transparent);
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-chip);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--s-text);
}
.pcard__grades li:last-child { border-color: transparent; color: var(--s-muted); }

.pcard__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-top: 1.4rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--s-line);
}
.pcard__count { color: var(--s-muted); }

@media (max-width: 780px) {
  .bento { grid-template-columns: 1fr; grid-template-rows: none; }
  .bento > :first-child { grid-row: auto; }
  .bento > :first-child.pcard { min-height: 340px; }
}

/* --- 12. industries: four featured, rest as a grouped index ----------- */

.ind-feat {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(0.75rem, 1.4vw, 1.1rem);
}
.icard {
  position: relative;
  min-height: 234px;
  padding: 1.15rem;
  display: flex; flex-direction: column; justify-content: flex-end;
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
}
/* deliberately uneven: cells 2 and 4 sit lower so the row is not a stripe */
.ind-feat > :nth-child(2n) { margin-top: clamp(1rem, 3vw, 2.75rem); }
.icard__bg { position: absolute; inset: 0; z-index: -2; }
.icard__bg img { width: 100%; height: 100%; object-fit: cover; }
.icard::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--navy-900) 94%, transparent) 4%,
    color-mix(in srgb, var(--navy-900) 38%, transparent) 78%);
}
.icard h3 { font-size: 1.02rem; }
.icard p { color: var(--s-text); font-size: 0.875rem; margin-top: 0.35rem; }

.ind-index {
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  border-top: 1px solid var(--s-line);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 clamp(1.5rem, 3vw, 3rem);
}
.ind-index__g { padding-top: 1.6rem; }
.ind-index__g > .mono { color: var(--s-muted); }
.ind-index__g ul { margin-top: 0.9rem; display: grid; gap: 0.55rem; }
.ind-index__g li {
  display: flex; gap: 0.6rem; align-items: baseline;
  font-size: var(--fs-sm);
}
.ind-index__g li::before {
  content: '';
  width: 0.5rem; height: 1px;
  background: var(--s-line-2);
  translate: 0 -0.32em;
  flex: none;
}
.ind-index__g b { font-weight: 500; color: var(--s-strong); }
.ind-index__g span { color: var(--s-muted); }

@media (max-width: 1000px) { .ind-feat { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 860px) { .ind-index { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) {
  .ind-feat { grid-template-columns: 1fr; }
  .ind-feat > :nth-child(2n) { margin-top: 0; }
  .ind-index { grid-template-columns: 1fr; }
}

/* --- 13. supply chain flow (scroll-drawn progress line) --------------- */

.flow {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  /* top edge comes from the shared yellow seam rule in section 9 */
}
.flow__media { position: absolute; inset: 0; z-index: -2; }
.flow__media video, .flow__media img {
  width: 100%; height: 100%; object-fit: cover;
}
.flow__media::after {
  content: '';
  position: absolute; inset: 0;
  /* flat navy, both stops. The yellow radial glow that used to sit on top of
     this went with the dark theme: the brand is flat colour, and a tinted
     bloom is the kind of decorative gradient the palette rules out. */
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--navy-800) 94%, transparent),
    color-mix(in srgb, var(--navy-800) 90%, transparent));
}

.flow__steps {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1rem, 2vw, 2rem);
}
/* the connecting line lives behind the markers */
.flow__steps::before {
  content: '';
  position: absolute;
  top: 13px; left: 0; right: 0;
  height: 1px;
  background: var(--s-line-2);
}
/* Drawn with a transform rather than an animated width, so the line is composited
   instead of relaid out on each frame. --flow-progress is a unitless 0 to 1. */
.flow__steps::after {
  content: '';
  position: absolute;
  top: 13px; left: 0;
  height: 1px;
  width: 100%;
  background: var(--colour-accent);
  transform: scaleX(var(--flow-progress, 0));
  transform-origin: left center;
  transition: transform 1.2s var(--ease);
  will-change: transform;
}
.fstep { display: grid; gap: 0.9rem; }
.fstep__dot {
  width: 27px; height: 27px;
  display: grid; place-items: center;
  border: 1px solid var(--s-line-2);
  border-radius: 50%;
  background: var(--s-bg);
  color: var(--s-muted);
  font-family: 'Plex Mono', monospace;
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  position: relative;
  transition: border-color 0.4s var(--ease-io), color 0.4s var(--ease-io);
}
/* the drawn line and the step it reaches are brand wayfinding, not something
   the visitor clicked, so they stay yellow. Both sit on navy. */
.fstep.is-lit .fstep__dot { border-color: var(--colour-accent); color: var(--colour-accent); }
.fstep h3 { font-size: 1.02rem; }
.fstep p { color: var(--s-text); font-size: 0.9rem; }
.fstep__meta { color: var(--s-muted); }

@media (max-width: 900px) {
  .flow__steps { grid-template-columns: 1fr; gap: 0; }
  .flow__steps::before { top: 0; bottom: 0; left: 13px; right: auto; width: 1px; height: auto; }
  .flow__steps::after {
    top: 0; left: 13px; right: auto;
    width: 1px; height: 100%;
    transform: scaleY(var(--flow-progress, 0));
    transform-origin: center top;
  }
  .fstep { grid-template-columns: 27px 1fr; column-gap: 1.1rem; row-gap: 0.4rem; padding-bottom: 2.25rem; }
  .fstep__dot { grid-row: span 4; }
}

/* --- 14. HSEQ split definition list ----------------------------------- */

.commit { display: grid; gap: 0; border-top: 1px solid var(--s-line); }
.commit__row {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 0.95fr) minmax(0, 2fr);
  gap: 1rem clamp(1rem, 2vw, 1.75rem);
  padding-block: clamp(1.15rem, 2vw, 1.5rem);
  border-bottom: 1px solid var(--s-line);
  align-items: start;
  transition: background 0.28s var(--ease-io);
}
.commit__row:hover { background: var(--s-raise); }
.commit__n { color: var(--s-muted); padding-top: 0.32em; }
.commit__row:hover .commit__n { color: var(--colour-accent); }
.commit__k { display: flex; align-items: center; gap: 0.7rem; }
.commit__k { color: var(--s-strong); }
.commit__k svg { width: 18px; height: 18px; color: var(--colour-accent); flex: none; }
.commit__v { color: var(--s-text); font-size: var(--fs-sm); }

@media (max-width: 760px) {
  .commit__row { grid-template-columns: 2rem minmax(0, 1fr); }
  .commit__v { grid-column: 2; }
}

/* --- 15. grade index (filterable) ------------------------------------- */

.gx__bar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.65rem;
  padding-bottom: 1.4rem;
}
.gx__search {
  position: relative; flex: 1 1 240px; min-width: 0;
}
.gx__search svg {
  position: absolute; left: 0.8rem; top: 50%; translate: 0 -50%;
  width: 17px; height: 17px; color: var(--s-muted); pointer-events: none;
}
.field {
  width: 100%;
  background: var(--white);
  /* grey-400, not the grey-200 the brand doc names for input borders. A control
     boundary needs 3:1 against its surroundings (WCAG 1.4.11) and grey-200 is
     1.4:1, so the resting border would be decorative rather than perceivable. */
  border: 1px solid var(--grey-400);
  border-radius: var(--r);
  padding: 0.7rem 0.9rem;
  color: var(--s-strong);
  font-size: var(--fs-sm);
  transition: border-color 0.18s var(--ease-io), background 0.18s var(--ease-io);
}
.field::placeholder { color: var(--s-muted); opacity: 1; }
.field:hover { border-color: var(--grey-700); }
.field:focus-visible { border-color: var(--s-link); outline-offset: 1px; }
.gx__search .field { padding-left: 2.35rem; }

.chip {
  background: transparent;
  border: 1px solid var(--s-line-2);
  border-radius: var(--r);
  padding: 0.55rem 0.85rem;
  color: var(--s-text);
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-chip);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.18s var(--ease-io);
}
.chip:hover { border-color: var(--s-muted); color: var(--s-strong); }
.chip[aria-pressed='true'] {
  background: var(--green-500); border-color: var(--green-500); color: var(--white);
  font-weight: 500;
}

.gx__table { border-top: 1px solid var(--s-line); }
.gx__row {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 0.7fr) minmax(0, 2.45fr) 122px;
  gap: 0.5rem 1.5rem;
  align-items: center;
  padding-block: 0.95rem;
  border-bottom: 1px solid var(--s-line);
  transition: background 0.2s var(--ease-io);
}
.gx__row:hover { background: var(--s-raise); }
.gx__row[hidden] { display: none; }
.gx__name {
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-mono-lg);
  letter-spacing: 0.02em;
  color: var(--s-strong);
  text-transform: uppercase;
}
.gx__fam { color: var(--s-strong); }
.gx__use { color: var(--s-muted); font-size: 0.875rem; }
.gx__docs { display: flex; gap: 0.35rem; justify-content: flex-end; }
.gx__docs span {
  border: 1px solid var(--s-line-2);
  border-radius: var(--r);
  padding: 0.16rem 0.4rem;
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-pill);
  letter-spacing: 0.06em;
  color: var(--s-muted);
}
.gx__head > span:last-child { text-align: right; }
.gx__head {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 0.7fr) minmax(0, 2.45fr) 122px;
  gap: 1.5rem;
  padding-bottom: 0.8rem;
  color: var(--s-muted);
}
.gx__empty {
  padding: clamp(2.5rem, 5vw, 4rem) 1rem;
  text-align: center;
  border-bottom: 1px solid var(--s-line);
}
.gx__empty svg { width: 30px; height: 30px; color: var(--s-muted); margin-inline: auto; }
.gx__empty p { color: var(--s-text); margin-top: 0.9rem; }
.gx__empty button { margin-top: 1.15rem; }
.gx__count { color: var(--s-muted); padding-top: 1.15rem; }

@media (max-width: 880px) {
  .gx__head { display: none; }
  .gx__row {
    grid-template-columns: 1fr auto;
    gap: 0.3rem 1rem;
    padding-block: 1.05rem;
  }
  .gx__fam { grid-row: 2; grid-column: 1; }
  .gx__use { grid-column: 1 / -1; }
  .gx__docs { grid-row: 1; grid-column: 2; }
}

/* --- 16. forms -------------------------------------------------------- */

.form { display: grid; gap: 1.15rem; }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.15rem; }
.fgroup { display: grid; gap: 0.5rem; }
.fgroup label { font-size: 0.875rem; font-weight: 500; color: var(--s-strong); }
/* the required marker is an attention mark, not brand emphasis, and yellow is
   1.2:1 on white. Rust carries it at 4.5:1. */
.fgroup label span { color: var(--colour-warning); }
.fgroup .hint { font-size: 0.8125rem; color: var(--s-muted); }
.fgroup textarea { resize: vertical; min-height: 118px; }
.fgroup .err {
  display: none;
  font-size: 0.8125rem;
  color: var(--colour-warning);
  align-items: center; gap: 0.4rem;
}
.fgroup[data-invalid='true'] .err { display: flex; }
.fgroup[data-invalid='true'] .field { border-color: var(--colour-warning); }
.fgroup .err svg { width: 14px; height: 14px; flex: none; }

.form__note { color: var(--s-muted); font-size: 0.8125rem; }
/* State is carried by the icon, not by a coloured side edge. Nothing else in
   this system uses a side accent, and the icon already says which state it is. */
.form__status {
  display: none;
  gap: 0.6rem; align-items: flex-start;
  padding: 0.9rem 1rem;
  border: 1px solid var(--s-line-2);
  border-radius: var(--r);
  background: var(--white);
  font-size: var(--fs-sm);
}
.form__status[data-show='true'] { display: flex; }
/* success is an affirmation, which is the one non-interactive job green keeps.
   --green-600 is the white-surface variant, 6.5:1. */
.form__status svg { width: 17px; height: 17px; color: var(--green-600); flex: none; margin-top: 0.15rem; }
.form__status[data-state='error'] svg { color: var(--colour-warning); }
.btn[data-busy='true'] { pointer-events: none; opacity: 0.72; }

@media (max-width: 620px) { .form__row { grid-template-columns: 1fr; } }

/* --- 17. contact panel ----------------------------------------------- */

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.cblock { display: grid; gap: 0; border-top: 1px solid var(--s-line); }
.cblock > a, .cblock > div {
  display: flex; align-items: flex-start; gap: 0.9rem;
  padding-block: 1.15rem;
  border-bottom: 1px solid var(--s-line);
  transition: background 0.2s var(--ease-io);
}
.cblock > a:hover { background: var(--s-raise); }
/* each of these rows is a tel: or mailto: link, so the icon is interaction */
.cblock svg { width: 19px; height: 19px; color: var(--s-link); flex: none; margin-top: 0.22rem; }
.cblock dt, .cblock .k { display: block; color: var(--s-muted); font-family: 'Plex Mono', monospace; font-size: var(--fs-mono); letter-spacing: 0.09em; text-transform: uppercase; }
.cblock .v { display: block; margin-top: 0.3rem; font-weight: 500; }
.cblock .v small { display: block; font-weight: 400; color: var(--s-text); font-size: 0.9rem; margin-top: 0.15rem; }

@media (max-width: 900px) { .contact { grid-template-columns: 1fr; } }

/* --- 18. page header (interior pages) -------------------------------- */

.phead {
  position: relative;
  padding-block: clamp(6.5rem, 12vh, 9rem) clamp(3rem, 6vw, 4.5rem);
  overflow: hidden;
  isolation: isolate;
  /* bottom edge comes from the shared yellow seam rule in section 9 */
}
.phead__bg { position: absolute; inset: 0; z-index: -2; }
.phead__bg img { width: 100%; height: 100%; object-fit: cover; }
.phead__bg::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(84deg, var(--navy-800) 12%,
      color-mix(in srgb, var(--navy-800) 91%, transparent) 52%,
      color-mix(in srgb, var(--navy-800) 72%, transparent) 100%),
    linear-gradient(to top, var(--navy-800) 1%, transparent 55%);
}
.phead__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: end;
}
.phead h1 { max-width: 22ch; }
.phead .lede { max-width: 48ch; }
@media (max-width: 880px) { .phead__grid { grid-template-columns: 1fr; gap: 1.5rem; } }

.crumbs { display: flex; align-items: center; gap: 0.55rem; color: var(--s-muted); margin-bottom: 1.3rem; }
.crumbs a { transition: color 0.18s var(--ease-io); }
.crumbs a:hover { color: var(--s-link); }
.crumbs svg { width: 11px; height: 11px; opacity: 0.6; flex: none; }
.crumbs [aria-current] { color: var(--s-text); }

/* --- 19. grade detail groups (product pages) ------------------------- */

.gset { display: grid; gap: clamp(2.5rem, 5vw, 4rem); }
.ggroup { display: grid; gap: 1.5rem; }
/* Grid, not flex: a flex item with basis 100% still shrinks onto the first
   line, which produced a headline-plus-corner-paragraph split header. The
   description belongs on its own row under the title. */
.ggroup__head {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 0.9rem 1.1rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--s-line-2);
}
.ggroup__head h2 { font-size: clamp(1.35rem, 2vw, 1.75rem); }
.ggroup__head > .mono { justify-self: start; }
.ggroup__head p {
  grid-column: 1 / -1;
  color: var(--s-muted);
  font-size: var(--fs-sm);
  max-width: 74ch;
}

/* auto-fit, so a group of four fills one row and a group of two or one collapses
   the spare tracks instead of leaving blank cells. The card max-width stops a
   lone grade from stretching the width of the page. */
.gcards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 258px), 1fr));
  gap: clamp(0.75rem, 1.4vw, 1rem);
}
.gcard {
  display: grid; gap: 0.85rem; max-width: 620px;
  padding: clamp(1.15rem, 2vw, 1.5rem);
  /* the card is the tinted step and the hover lifts it to white, so a grid of
     these reads as panels on the white section rather than as a second grey */
  background: var(--colour-surface-alt);
  border: 1px solid var(--s-line);
  border-radius: var(--r-lg);
  transition: border-color 0.24s var(--ease-io), background 0.24s var(--ease-io);
}
.gcard:hover { border-color: var(--s-line-2); background: var(--white); }
.gcard__name {
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-mono-lg);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--s-strong);
  line-height: 1.45;
}
.gcard__alt { color: var(--s-muted); font-size: 0.8125rem; line-height: 1.5; }
.gcard__uses { display: grid; gap: 0.4rem; margin-top: auto; padding-top: 0.4rem; }
.gcard__uses li {
  display: flex; gap: 0.55rem; align-items: baseline;
  font-size: 0.875rem; color: var(--s-text);
}
/* affirmation, so green rather than the action yellow */
/* affirmation: the confirmed use. Green keeps this job on every grade card. */
.gcard__uses svg { width: 12px; height: 12px; color: var(--green-600); flex: none; translate: 0 0.22em; }
.gcard__docs {
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  padding-top: 1rem; margin-top: 0.25rem;
  border-top: 1px solid var(--s-line);
}
.gcard__docs a {
  display: inline-flex; align-items: center; gap: 0.35rem;
  border: 1px solid var(--s-line-2);
  border-radius: var(--r);
  padding: 0.3rem 0.55rem;
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-pill); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--s-text);
  transition: all 0.18s var(--ease-io);
}
.gcard__docs a:hover { border-color: var(--s-link); color: var(--s-link); }
/* every inline icon needs an explicit box: a <use> of a 256-unit symbol with no
   size renders at its intrinsic size and swallows the component */
.gcard__docs a svg { width: 12px; height: 12px; flex: none; }

/* --- 19b. standards table (real tabular data, not decoration) -------- */

.tw { overflow-x: auto; }
.dtable {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.dtable caption {
  text-align: left;
  color: var(--s-muted);
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-mono);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  padding-bottom: 0.9rem;
}
.dtable th, .dtable td {
  text-align: left;
  padding: 0.85rem 1rem 0.85rem 0;
  border-bottom: 1px solid var(--s-line);
  vertical-align: baseline;
}
.dtable thead th {
  color: var(--s-muted);
  font-family: 'Plex Mono', monospace;
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  border-bottom-color: var(--s-line-2);
}
.dtable tbody th {
  font-family: 'Archivo', sans-serif;
  font-stretch: 106%;
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.012em;
  white-space: nowrap;
  padding-right: 1.5rem;
  /* a row header is the emphatic tier, not the body grey it would inherit */
  color: var(--s-strong);
}
.dtable td { color: var(--s-text); font-size: var(--fs-sm); }
.dtable tbody tr:hover { background: var(--s-raise); }
.dtable td em { font-style: normal; color: var(--s-strong); }
.dtable + .tnote { margin-top: 1.1rem; color: var(--s-muted); font-size: 0.8125rem; max-width: 72ch; }

/* --- 20. call to action band ---------------------------------------- */

.cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  /* top edge comes from the shared yellow seam rule in section 9 */
}
.cta__bg { position: absolute; inset: 0; z-index: -2; opacity: 0.2; }
.cta__bg img { width: 100%; height: 100%; object-fit: cover; }
.cta::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  /* flat navy across, no yellow bloom. Same reasoning as .flow__media. */
  background: linear-gradient(to right, var(--navy-800) 26%,
    color-mix(in srgb, var(--navy-800) 88%, transparent) 100%);
}
.cta__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
}
.cta__grid > div:last-child { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: flex-end; }
@media (max-width: 860px) {
  .cta__grid { grid-template-columns: 1fr; }
  .cta__grid > div:last-child { justify-content: flex-start; }
}

/* --- 21. footer ----------------------------------------------------- */

.foot { background: var(--s-bg); }
.foot__top {
  padding-block: clamp(3rem, 6vw, 4.5rem);
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
}
.foot__brand { display: grid; gap: 1.25rem; align-content: start; }
.foot__brand img { width: 154px; }
.foot__brand p { color: var(--s-muted); font-size: 0.9rem; max-width: 40ch; }
.foot__col { display: grid; gap: 0.25rem; align-content: start; }
/* Footer column headings are yellow. This is the third and last place yellow is
   allowed to be type, and like the other two the ground is navy: 14.0:1. */
.foot__col > .mono { color: var(--colour-accent); margin-bottom: 0.55rem; }
.foot__col a { color: var(--s-link); font-size: var(--fs-sm); }
.foot__col span { color: var(--s-text); font-size: var(--fs-sm); }
/* padded so each link clears a 40px touch target without adding visible chrome */
.foot__col a {
  transition: color 0.18s var(--ease-io);
  width: fit-content;
  padding-block: 0.5rem;
  line-height: 1.45;
}
.foot__col span { padding-block: 0.5rem; line-height: 1.6; }
.foot__col a:hover { color: var(--s-strong); text-decoration: underline; }

/* The copyright strip is the deepest ground in the palette. It needs its own
   full-bleed wrapper because .foot__bar carries .shell, which is a centred
   1360px box: a background on that would paint an inset strip, not a band. */
.foot__legal { background: var(--navy-900); }
.foot__bar {
  padding-block: 1.4rem;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.75rem 1.5rem;
  color: var(--s-muted);
}
.foot__bar nav { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; margin-left: auto; }
.foot__bar nav a { padding-block: 0.5rem; }
.foot__bar a:hover { color: var(--s-strong); text-decoration: underline; }

@media (max-width: 820px) {
  .foot__top { grid-template-columns: 1fr 1fr; }
  .foot__brand { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .foot__top { grid-template-columns: 1fr; }
  .foot__bar nav { margin-left: 0; }
}

/* --- 22. 404 -------------------------------------------------------- */

.nf {
  min-height: calc(100dvh - 72px);
  display: grid; place-items: center;
  padding-block: clamp(4rem, 10vw, 8rem);
  text-align: left;
}
.nf__in { display: grid; gap: 1.5rem; max-width: 56ch; }
.nf__code {
  font-family: 'Archivo', sans-serif;
  font-stretch: 118%; font-weight: 700;
  font-size: clamp(4.5rem, 14vw, 9rem);
  line-height: 0.86; letter-spacing: -0.05em;
  color: var(--s-strong);
}
.nf__links { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* --- 23. legal / long-form page ------------------------------------- */

.legal { max-width: 74ch; }
.legal h2 {
  font-family: 'Archivo', sans-serif; font-stretch: 108%; font-weight: 600;
  font-size: clamp(1.2rem, 1.8vw, 1.5rem);
  letter-spacing: -0.014em;
  margin-top: 2.75rem; padding-top: 1.5rem;
  border-top: 1px solid var(--s-line);
}
.legal h2:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
.legal p, .legal li { color: var(--s-text); }
.legal p + p, .legal ul { margin-top: 1rem; }
.legal ul { display: grid; gap: 0.55rem; }
.legal li { display: flex; gap: 0.65rem; }
.legal li::before { content: ''; width: 0.5rem; height: 1px; background: var(--s-line-2); translate: 0 0.75em; flex: none; }
.legal a { color: var(--s-link); border-bottom: 1px solid color-mix(in srgb, var(--s-link) 34%, transparent); }

/* --- 24. section heading block -------------------------------------- */

.shead { display: grid; gap: 1.15rem; max-width: 60ch; margin-bottom: clamp(2.25rem, 4.5vw, 3.5rem); }
.shead--wide { max-width: none; }
.shead p { color: var(--s-text); max-width: 58ch; }

/* --- 25. motion ---------------------------------------------------- */

/* Reveal on scroll. Motivated: sections carry a narrative order (what we do,
   what we sell, where it goes) and the stagger matches that reading order.
   Driven by IntersectionObserver, never a scroll listener. */
[data-rise] {
  opacity: 0;
  translate: 0 18px;
  transition: opacity 0.72s var(--ease), translate 0.72s var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-rise].is-in { opacity: 1; translate: 0 0; }

.no-js [data-rise] { opacity: 1; translate: 0 0; }

@media (prefers-reduced-motion: reduce) {
  [data-rise] { opacity: 1 !important; translate: none !important; transition: none !important; }
  .flow__steps::after { transition: none; will-change: auto; }
  .pcard__bg img, .pcard:hover .pcard__bg img { scale: 1; transition: none; }
  .hero__media video { display: none; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}

/* --- 26. print ----------------------------------------------------- */

@media print {
  .nav, .sheet, .hero__media, .flow__media, .cta__bg, .skip { display: none !important; }
  /* Yellow does not print. It is 1.2:1 on paper, so every accent, seam rule and
     footer heading resolves to navy for the duration. */
  :root { --colour-accent: var(--navy-800); }
  /* the navy bands are already ink-heavy on screen; on paper they would empty a
     toner cartridge, so every surface flattens to white with navy type */
  .hero, .phead, .flow, .cta, .foot, .rail, .sec--hseq, .pcard, .icard {
    --s-bg: var(--white);
    --s-strong: var(--navy-800);
    --s-text: var(--grey-700);
    --s-muted: var(--grey-600);
    --s-line: var(--grey-200);
    --s-line-2: var(--grey-300);
    --s-raise: var(--grey-100);
    --s-link: var(--green-600);
    background: var(--white) !important;
  }
  .hero__scrim, .pcard::after, .icard::after, .phead__bg, .cta::before { display: none !important; }
  /* logo-reversed.svg is near-white type; on a white footer it would be a blank
     rectangle. The copyright line carries the company name on paper. */
  .foot__brand img { display: none !important; }
  .foot__legal { background: var(--white); }
  body { background: var(--white); color: var(--grey-700); }
  a { text-decoration: underline; }
}
