/* ==========================================================================
   EXEMED PHARMACEUTICALS — HOME PAGE
   Typography and colour per Exemed Brand Guidelines 2026, v1.0.

   That document states it supersedes all earlier versions, so it supersedes
   the palette and type direction this file used to carry. What was here
   before was Sora at weight 400 on a warm off-white canvas, with a blue and
   a green sampled off the wordmark by eye. None of that was brand. It was a
   reasonable reading of the logo in the absence of a guideline; the
   guideline has now arrived.

   WHAT THE GUIDELINE FIXES
   ------------------------
   Colour (s12, s13)   Navy #1F4585 leads, Green #0E8544 accents only,
                       neutrals Ink / Slate / Light / White. Canvas is cool
                       white, not warm paper. Green is barred from small
                       text: 4.16:1 on Light fails AA outright.
   Type (s14, s15)     Inter. H1 600/60, H2 700/26 caps, body 400/17,
                       caption 700/11 caps.
   Headings (s28)      "Lead with navy."

   THE DUAL-COLOUR HEADING
   -----------------------
   The logo is a navy wordmark whose "x" crossbar and swoosh are green. Every
   heading repeats that relationship: navy carries the sentence, .hl puts the
   one phrase it turns on in green. One accent per heading. See section 2.

   TWO POINTS WHERE THE GUIDELINE CONTRADICTS ITSELF
   -------------------------------------------------
   1. s14 names Inter and the guideline PDF embeds nothing else, but s15
      labels H1 "SERIF" without naming or embedding one. Read as a labelling
      slip; Inter is used throughout. A real display serif is a one-line
      change in --sans.
   2. s05 says "headings use sentence case", s15 sets H2 in caps. Read as
      sentence-case *writing* with a caps *treatment* on H2 only, which is
      how both can hold at once. H1 stays sentence case.

   Both are flagged for Exemed to rule on.

   DEVICES CARRIED OVER
   --------------------
   1. The lens        — washed field with a sharp circular crop. Section 7.
   2. Periodic grid   — portfolio as element cells. Section 9.
   3. Annotation      — asterisked footnotes as the small-print voice. .note
   4. Eyebrow + rule  — caps label over a hairline. .code
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* ---- BRAND, Exemed Brand Guidelines 2026 v1.0, section 12 --------------
     These five are the palette. Nothing else is a brand colour. Navy leads,
     green accents, and the three neutrals carry everything else.           */
  --navy: #1F4585;
  /* Pantone 7686 C  — LEAD */
  --green: #0E8544;
  /* Pantone 7740 C  — ACCENT ONLY */
  --ink: #1A2230;
  --slate: #5A6676;
  --light: #EEF1F4;
  --white: #FFFFFF;

  /* Tints, sanctioned by section 13. Derived, not invented: each is the
     named colour mixed with white at the stated percentage. */
  --navy-80: #4C6A9D;
  --navy-20: #D2DAE7;
  /* type on navy surfaces */
  --navy-12: #E4E9F0;
  /* hairline */
  --green-40: #9FCEB4;
  /* accent on navy surfaces */
  --navy-dk: #163364;
  /* interaction state only */

  /* ---- ROLE TOKENS ------------------------------------------------------
     The palette above is the source of truth. Everything below points at it
     so no component carries a raw hex. */

  /* Surfaces. Cool now, not warm: the brand canvas is White with Light for
     tinted bands. The previous #FBF9F8 warm paper was borrowed from a
     reference site and is off-brand. */
  --paper: var(--white);
  --paper-2: var(--white);
  --paper-3: var(--light);
  --deep: var(--navy);
  /* closing panel, the "reversed on navy" variation */
  --deep-2: var(--ink);
  /* footer */

  /* Ink. The brand names exactly two greys, so hierarchy below Slate is
     carried by size and weight rather than a third, lighter grey, which
     would have had to be invented and would have failed AA anyway. */
  --ink-2: var(--slate);
  /* 5.84:1 on white — body */
  --ink-3: var(--slate);
  /* 5.84:1 — muted, notes, labels */

  /* --blue is kept as a name so components do not all have to change, but
     it is Navy. There is no other blue in this brand. */
  --blue: var(--navy);
  /*  9.35:1 on white, AAA */
  --blue-dk: var(--navy-dk);
  --blue-lt: var(--navy-20);
  /*  6.64:1 on navy */
  --green-lt: var(--green-40);
  /* 5.27:1 on navy */

  /* Rules — hairlines are structural here, not decorative */
  --rule: var(--navy-12);
  --rule-2: var(--light);
  --rule-dark: rgba(255, 255, 255, 0.18);

  /* ---- TYPE, section 14 and 15 -----------------------------------------
     Inter. It is the only family named on the typography page and the only
     one embedded in the guideline PDF — all ten font subsets in that file
     are Inter. Section 15 labels H1 "SERIF", but no serif is named anywhere
     in the document and none is embedded, so that reads as a labelling
     slip. Montserrat is scoped to film supers in section 21, not to web.
     If Exemed does hold a display serif, it is a one-line change here.

     Section 15 sets the scale: H1 600/60, H2 700/26 caps, body 400/17,
     caption 700/11 caps. Those are the numbers below.                      */
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --fs-hero: clamp(2.1rem, 1.0rem + 4.2vw, 3.75rem);
  /* 60px */
  --fs-h2: clamp(1.15rem, 0.95rem + 0.85vw, 1.625rem);
  /* 26px */
  --fs-h3: clamp(1.06rem, 1.0rem + 0.3vw, 1.25rem);
  /* 20px */
  --fs-lede: clamp(1.06rem, 1.0rem + 0.26vw, 1.2rem);
  --fs-body: 1.0625rem;
  /* 17px */
  --fs-sm: 0.9375rem;
  /* 15px */
  --fs-xs: 0.8125rem;
  /* 13px */
  --fs-label: 0.6875rem;
  /* 11px */

  /* Space */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 72px;
  --sec-y: clamp(64px, 8vw, 132px);

  /* Layout */
  --wrap: 1340px;
  --gut: clamp(20px, 5vw, 60px);
  --head-h: 84px;

  --r1: 0px;
  /* the grid is drawn with hairlines, not corners */
  --r2: 4px;
  /* controls only */

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  --t: 260ms;
  --t-slow: 720ms;
}

/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--head-h) + 16px);
  -webkit-text-size-adjust: 100%;
  background: var(--paper);
}

body {
  font-family: var(--sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.62;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* No overflow-x here. It computes overflow-y to auto, which makes <body> a
     scroll container and silently disables position:sticky for everything
     inside it — the products deck and the about aperture both. Horizontal
     overflow is prevented at the component level instead. */
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: var(--blue);
  text-decoration: none;
}

a:hover {
  color: var(--blue-dk);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* HEADINGS LEAD WITH NAVY — governance section 28, "lead with navy".
   The previous rule set display type at weight 400 in near-black and called
   that "the whole direction". Section 15 asks for 600 on H1 and 700 on H2,
   so that direction is replaced rather than adjusted. */
h1,
h2,
h3,
h4 {
  color: var(--navy);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.011em;
}

/* THE DUAL-COLOUR HEADING.
   The logo is a navy wordmark whose "x" crossbar and swoosh are green. This
   is that relationship in type: navy carries the sentence, green carries the
   one phrase the sentence is really about. One accent per heading, never two.

   Green is ACCENTS ONLY (section 12) and section 13 restricts it to large
   text, so .hl is only ever applied inside a heading. At H2's 26px/700 and
   H1's 60px/600 it clears AA large on both white and Light with room. */
.hl {
  color: var(--green);
}

.hl-light {
  color: var(--green-lt);
}

/* the same device on navy panels */

ul,
ol {
  list-style: none;
}

:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}

.skip {
  position: absolute;
  left: var(--s4);
  top: -100px;
  z-index: 300;
  background: var(--navy);
  color: var(--white);
  padding: 12px 18px;
  font-size: var(--fs-sm);
}

.skip:focus {
  top: var(--s4);
  color: #fff;
}

/* --------------------------------------------------------------------------
   3. TYPE PRIMITIVES
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.section {
  padding-block: var(--sec-y);
}

.section-tint {
  background: var(--paper-3);
}

/* DEVICE 4 — eyebrow over a full-width hairline.
   Replaces the mono "001-00 ABOUT US ————" code. Same job, quieter, and it
   spans the container rather than trailing off after 200px. */
/* CAPTION, section 15: sans 700 / 11px caps. */
.code {
  display: block;
  padding-bottom: var(--s3);
  margin-bottom: var(--s6);
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

/* Was green. At 11px green is small text, which section 13 rules out on
   white and which fails outright on Light. Navy carries it instead. */
.code span {
  color: var(--navy);
}

.code-light {
  color: rgba(255, 255, 255, 0.7);
  border-bottom-color: var(--rule-dark);
}

.code-light span {
  color: var(--green-lt);
}

/* H2, section 15: sans 700 / 26px caps. The tracking is opened because caps
   set at their default fit are hard to read at this size. */
.h2 {
  font-size: var(--fs-h2);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.045em;
  line-height: 1.28;
  max-width: 24ch;
}

.h2-wide {
  max-width: 32ch;
}

.h2-light {
  color: var(--white);
}

.lede {
  font-size: var(--fs-lede);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 56ch;
}

.lede-light {
  color: rgba(255, 255, 255, 0.78);
}

/* DEVICE 3 — the annotation voice. Anything qualifying, sourcing or
   footnoting a claim is set as an asterisked note rather than body copy, so
   the page separates what it asserts from what it qualifies. */
.note {
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--ink-3);
  max-width: 100%;
}

.note::before {
  content: "*";
  margin-right: 2px;
}

.mono {
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Buttons ---------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 48px;
  padding: 12px 30px;
  border: 1px solid var(--navy);
  border-radius: var(--r2);
  background: transparent;
  color: var(--navy);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  /* a button label must never wrap */
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  text-align: center;
  transition: background var(--t) var(--ease), color var(--t) var(--ease), border-color var(--t) var(--ease);
}

.btn:hover {
  background: var(--navy);
  color: var(--white);
}

.btn-solid {
  background: var(--navy);
  color: var(--white);
}

.btn-solid:hover {
  background: var(--navy-dk);
  border-color: var(--navy-dk);
  color: var(--white);
}

.btn-light {
  border-color: rgba(255, 255, 255, 0.5);
  color: var(--white);
}

.btn-light:hover {
  background: var(--white);
  color: var(--navy);
  border-color: var(--white);
}

.btn-lg {
  min-height: 54px;
  padding-inline: 36px;
}

.btn-block {
  width: 100%;
}

/* Arrow link. The diagonal glyph is the reference's, and it reads as
   "opens elsewhere" rather than "continues here". */
.arrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--navy);
}

.arrow span::after {
  content: "\2197";
  display: inline-block;
  transition: transform var(--t) var(--ease);
}

.arrow:hover {
  color: var(--green);
}

.arrow:hover span::after {
  transform: translate(3px, -3px);
}

.arrow-inline {
  text-transform: none;
  letter-spacing: normal;
  font-size: var(--fs-sm);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chips li {
  padding: 4px 11px;
  border: 1px solid var(--rule);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   4. MASTHEAD + DRAWER
   -------------------------------------------------------------------------- */
.exmmast {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 200;
  border-bottom: 1px solid transparent;
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease),
    transform 380ms var(--ease-io);
}

.exmmast.is-stuck {
  background: rgba(255, 255, 255, 0.92);
  /* White, per s12 */
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom-color: var(--rule);
}

.exmmast.is-away {
  transform: translateY(-100%);
}

.exmmast-bar {
  display: flex;
  align-items: center;
  gap: var(--s4);
  height: var(--head-h);
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.exmmast-logo {
  flex: none;
  display: inline-flex;
}

.exmmast-logo img {
  width: 122px;
  height: auto;
}

/* BREAKPOINT 1220 — measured, not chosen.
   The bar needs logo 122 + gap 16 + nav 781 + gap 16 + button 160 = 1095px
   of content, and the gutter is 5vw a side below 1200. 1095 <= 0.9W solves
   to W >= 1217. At 1140 the Contact Us label wrapped to two lines.
   This number is repeated in the .exmmenu rule below and in the matchMedia
   query in script.js. Change all three together. */
.exmmast-nav {
  display: none;
  margin-inline: auto;
}

@media (min-width: 1220px) {
  .exmmast-nav {
    display: block;
  }
}

.exmnav {
  display: flex;
  align-items: center;
  gap: 2px;
}

.exmnav>li {
  position: relative;
}

.exmnav a {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 13px;
  font-size: 15px;
  color: var(--ink-2);
  white-space: nowrap;
  transition: color var(--t) var(--ease);
}

.exmnav a:hover {
  color: var(--blue);
}

/* Caret. Only the two parents that actually have children carry one. */
.exmnav-c {
  width: 6px;
  height: 6px;
  flex: none;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--t) var(--ease);
}

/* DROPDOWNS — no script.
   :focus-within is what makes these keyboard-operable; without it a tab into
   the parent link would open nothing and the children would be unreachable. */
.exmnav-sub {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1;
  min-width: 208px;
  padding: 6px 0;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  box-shadow: 0 24px 44px -32px rgba(14, 32, 42, 0.4);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease), visibility var(--t);
}

.exmnav-has:hover .exmnav-sub,
.exmnav-has:focus-within .exmnav-sub {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.exmnav-has:hover>a .exmnav-c,
.exmnav-has:focus-within>a .exmnav-c {
  transform: translateY(-4px) rotate(225deg);
}

.exmnav-sub a {
  padding: 9px 16px;
  font-size: var(--fs-sm);
}

.exmnav-sub a:hover {
  background: var(--paper-3);
  color: var(--blue);
}

.exmmast-end {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-left: auto;
}

.exmmast-end .btn {
  display: none;
}

@media (min-width: 640px) {
  .exmmast-end .btn {
    display: inline-flex;
  }
}

/* Square menu button, as on the reference */
.exmmenu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 16px;
  border: 1px solid var(--navy);
  background: var(--navy);
  color: var(--white);
  cursor: pointer;
  transition: background var(--t) var(--ease), color var(--t) var(--ease);
}

.exmmenu:hover {
  background: transparent;
  color: var(--navy);
}

.exmmenu-label {
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.exmmenu-plus {
  position: relative;
  width: 14px;
  height: 14px;
  flex: none;
  transition: transform 380ms var(--ease-io);
}

.exmmenu-plus::before,
.exmmenu-plus::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
}

.exmmenu-plus::before {
  width: 14px;
  height: 1px;
  transform: translate(-50%, -50%);
}

.exmmenu-plus::after {
  width: 1px;
  height: 14px;
  transform: translate(-50%, -50%);
}

.exmmenu[aria-expanded="true"] .exmmenu-plus {
  transform: rotate(135deg);
}

/* Above the nav breakpoint the whole menu is already in the bar, so the
   button has nothing left to reveal. Keep in step with .exmmast-nav. */
@media (min-width: 1220px) {
  .exmmenu {
    display: none;
  }
}

/* DRAWER — the small-screen menu.
   Replaces the full-screen overlay: a panel that hangs off the header and
   stops at the content it needs, rather than a takeover screen with 2rem
   numbered entries. Same destinations, no theatre. */
.exmdrawer {
  position: fixed;
  inset: var(--head-h) 0 auto 0;
  z-index: 190;
  max-height: calc(100svh - var(--head-h));
  overflow-y: auto;
  background: var(--paper-2);
  border-bottom: 1px solid var(--rule);
  box-shadow: 0 30px 60px -40px rgba(14, 32, 42, 0.45);
  animation: drawerIn 240ms var(--ease-io) both;
}

.exmdrawer[hidden] {
  display: none;
}

@keyframes drawerIn {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.exmdrawer-in {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--s4) var(--gut) var(--s6);
}

.exmdrawer-in a {
  display: flex;
  align-items: center;
  min-height: 46px;
  border-bottom: 1px solid var(--rule-2);
  color: var(--ink);
  font-size: var(--fs-sm);
  transition: color var(--t) var(--ease);
}

.exmdrawer-in a:hover {
  color: var(--blue);
}

.exmdrawer-g {
  margin-top: var(--s5);
  padding-bottom: var(--s2);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
}

/* --------------------------------------------------------------------------
   5. HERO
   Statement on paper, footage below it at full strength, proof row beneath.
   The type never crosses the video, so the video never has to be dimmed.
   -------------------------------------------------------------------------- */
.exmhero {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: clamp(24px, 3vw, 40px);
  /* No inline padding on the section. That is what lets the footage run edge
     to edge without a 100vw trick, which would have measured the scrollbar
     in and put the document back into horizontal scroll. The gutter moves
     onto the text children instead — the same shape as the .wrap class the
     rest of the page uses, so the hero copy now aligns with every section
     below it.

     Still no min-height: 100svh. The band is the anchor; forcing a
     full-viewport section would only push it below the fold.

     No bottom padding either. The figures row ends the hero flush against
     the approvals band below it, so the two read as one ruled block rather
     than a row and then a separate strip 96px later. */
  padding: calc(var(--head-h) + clamp(24px, 3vw, 44px)) 0 0;
  background: var(--paper);
}

/* The media is excluded because it is deliberately full bleed. */
.exmhero>*:not(.exmhero-media) {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.exmhero-head {
  display: grid;
  gap: var(--s4);
}

@media (min-width: 1100px) {

  /* Statement left, proof line and actions right, sharing one band of
     vertical space so the footage sits higher on the page. */
  .exmhero-lead {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
    gap: var(--s8);
    align-items: end;
  }

  .exmhero-foot {
    margin-top: 0;
  }
}

/* THE FOOTAGE — shown as shot.
   No opacity wash, no saturate/contrast filter, no gradient veil, and no
   text laid over it. Those existed only to stop the copy fighting the frame;
   with the copy moved off the video there is nothing left to defend against.
   Do not reintroduce any of them. */
.exmhero-media {
  position: relative;
  margin: 0;
  width: 100%;
  aspect-ratio: 1280 / 620;
  /* Edge to edge, so on a wide monitor the natural 2.06:1 height runs away
     from the source: 1920 wide would want 931px against a 620px encode.
     The cap holds the upscale near 1.5x and crops top and bottom instead. */
  max-height: min(76svh, 760px);
  overflow: hidden;
  background: var(--paper-3);

  /* THE EXPAND.
     The element is always full bleed and the footage is always drawn at full
     bleed size. What changes is the window onto it: --x runs 0 to 1 as the
     band comes up the viewport and the clip opens from the text column out
     to both edges. Nothing is scaled, so the framing never shifts and the
     video never resamples mid-scroll — you are opening a shutter, not
     resizing a box.

     clip-path also costs no layout. Animating width or margin here would
     reflow the whole hero on every frame.

     --ix is the horizontal inset at rest, measured in JS off the copy
     column so the closed state lines up with the headline exactly. --iy is
     a proportion of the band's own height rather than a ratio of --ix: the
     gutter collapses to 20px on a phone, and a vertical inset derived from
     it would have been 7px, which reads as nothing.
     Defaults leave it full bleed, which is what a no-JS visitor gets. */
  --x: 1;
  --ix: 0px;
  --iy: 0px;
  clip-path: inset(calc(var(--iy) * (1 - var(--x))) calc(var(--ix) * (1 - var(--x))));
}

@media (prefers-reduced-motion: reduce) {
  .exmhero-media {
    clip-path: none;
  }
}

.exmhero-still,
.exmhero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmhero-still {
  opacity: 1;
}

.exmhero-video {
  opacity: 0;
  transition: opacity 700ms var(--ease);
}

.exmhero-video.is-playing {
  opacity: 1;
}

/* Portrait viewports: the 2.06:1 band gets very short, so crop to a taller
   window rather than letting it become a letterboxed sliver. */
@media (max-width: 700px) {
  .exmhero-media {
    aspect-ratio: 4 / 3;
    max-height: 62svh;
  }
}

.exmhero-h {
  font-size: var(--fs-hero);
  color: var(--navy);
  max-width: 16ch;
}

.exmhero-h .ln {
  display: block;
}

.ln-accent {
  color: var(--green);
}

.exmhero-foot {
  margin-top: var(--s6);
  display: grid;
  gap: var(--s5);
}

.exmhero-lede {
  font-size: var(--fs-lede);
  color: var(--ink-2);
  max-width: 46ch;
}

.exmhero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

/* Four equal columns, ruled like a spec table rather than spaced like a row
   of flex items — with flex the widest label ("APIs in commercial supply")
   set the rhythm and the four figures landed at four arbitrary positions.
   Two columns below 720px so the labels never set on one word per line. */
.exmhero-meta {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* The rule is a pseudo-element inset by the gutter, not a border. A border
   would be drawn on the element's border box, which includes the gutter
   padding, so it overhung the figures by 60px a side and did not line up
   with the identical rule on the band below. */
.exmhero-meta::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gut);
  right: var(--gut);
  height: 1px;
  background: var(--rule);
}

@media (min-width: 720px) {
  .exmhero-meta {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.exmhero-meta li {
  /* Symmetric block padding so the figures sit centred between their two
     rules — the row is now the top half of a single ruled block with the
     approvals band, not a loose row with a gap under it. */
  padding: var(--s5) var(--s5) var(--s5) 0;
  border-left: 1px solid var(--rule);
  padding-left: var(--s5);
}

/* The first cell in each row sits flush with the text column beside it. */
.exmhero-meta li:nth-child(odd) {
  border-left: 0;
  padding-left: 0;
}

@media (min-width: 720px) {
  .exmhero-meta li:nth-child(odd) {
    border-left: 1px solid var(--rule);
    padding-left: var(--s5);
  }

  .exmhero-meta li:first-child {
    border-left: 0;
    padding-left: 0;
  }
}

.exmhero-meta b {
  display: flex;
  align-items: baseline;
  font-weight: 600;
  font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2.4rem);
  color: var(--navy);
  line-height: 1.1;
  /* Tabular figures so the digits do not jitter sideways while counting. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum"1;
}

.exmhero-meta b i {
  font-style: normal;
  color: var(--green);
}

.exmhero-meta>li>span {
  display: block;
  margin-top: var(--s2);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* The vertical SCROLL cue is gone. It was anchored to the bottom-right of a
   100svh hero; with the section sized by its content it landed inside the
   fourth figure of the stats row and read as a stray rule. The full-bleed
   band already tells anyone there is more page below it. */

/* --------------------------------------------------------------------------
   6. CERTIFICATION BAND
   Runs straight on from the hero's figures with no gap between them: one
   ruled block, figures over approvals. The hero's bottom padding is zero
   for exactly this reason — see section 5.
   -------------------------------------------------------------------------- */
.exmcertband {
  background: var(--paper);
}

.exmcertband-in {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4) var(--s7);
  padding-block: var(--s5);
}

/* Same inset-rule treatment as .exmhero-meta so the two align exactly. On the
   section itself these ran the full width of the viewport, which read as a
   separate band rather than the second half of one. */
.exmcertband-in::before,
.exmcertband-in::after {
  content: "";
  position: absolute;
  left: var(--gut);
  right: var(--gut);
  height: 1px;
  background: var(--rule);
}

.exmcertband-in::before {
  top: 0;
}

.exmcertband-in::after {
  bottom: 0;
}

.exmcertband-k {
  color: var(--ink-3);
  flex: none;
}

.exmcertband-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s4) var(--s7);
  margin-left: auto;
}

.exmcertband-row li {
  display: flex;
  align-items: center;
  gap: 12px;
}

.exmcertband-row img {
  height: 34px;
  width: auto;
  filter: grayscale(1);
  opacity: 0.5;
  transition: filter var(--t) var(--ease), opacity var(--t) var(--ease);
}

.exmcertband-row li:hover img {
  filter: grayscale(0);
  opacity: 1;
}

.exmcertband-row span {
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

@media (max-width: 860px) {
  .exmcertband-row {
    margin-left: 0;
  }

  .exmcertband-row span {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   7. ABOUT — DEVICE 1, THE LENS
   A washed field of the crystallisation image across the whole section, with
   a sharp saturated circular crop of the same file over it. One asset, two
   treatments, and the section reads as a slide under an eyepiece rather than
   a stock photo in a box.
   -------------------------------------------------------------------------- */
/* No overflow:hidden here. It makes this section a scroll container, which
   silently disables position:sticky on the aperture inside it. The field is
   absolutely positioned to inset:0 so it cannot overflow anyway. */
.exmabx {
  position: relative;
  isolation: isolate;
  background: var(--paper);
}

.exmabx-field {
  position: absolute;
  inset: 0;
  z-index: -2;
}

/* The scrim colours were the old warm paper and left a visible warm cast on
   a white canvas. They are White now, matching the section behind them.

   The opacity drop is legibility, not taste: this plate is a cyan and pink
   micrograph, so on white it reads far stronger than it did on warm paper,
   and on a phone the body copy sits directly over it. The real fix is
   section 20, a navy to green duotone grade. Until that is done this keeps
   the copy clean. */
.exmabx-field img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.3;
}

@media (max-width: 900px) {
  .exmabx-field img {
    opacity: 0.16;
  }
}

.exmabx-field::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(110% 80% at 72% 50%, rgba(255, 255, 255, 0) 20%, rgba(255, 255, 255, 0.9) 72%, var(--white) 100%);
}

.exmabx-inner {
  position: relative;
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--sec-y) var(--gut);
  display: grid;
  gap: var(--s8);
  align-items: center;
}

@media (min-width: 980px) {
  .exmabx-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  }
}

.exmabx-copy p+p {
  margin-top: var(--s4);
}

.exmabx-copy .arrow {
  margin-top: var(--s6);
}

.exmabout-p {
  color: var(--ink-2);
  max-width: 52ch;
}

/* THE APERTURE — the reference's hero device.

   Measured off marity.qodeinteractive.com: their lens is position:fixed with
   the image as a background whose background-position-y tracks scrollY 1:1
   negatively. The aperture is anchored to the viewport, the image to the
   document, so the specimen slides through a held eyepiece rather than the
   whole picture drifting.

   Two deliberate departures:
     · The clip is an organic blob via border-radius rather than a copied SVG
       path. Their bezier is their asset; a perfect circle read too generic.
     · Travel is scaled to 0.42 of scroll, not 1:1. At 1:1 the background
       would need ~2400px of height and the source is 866px, which meant a
       2.8x upscale and visible mush. At 1200px it is a 1.4x upscale and the
       specimen still crosses the full aperture over the section's passage.

   background-position-y is set by script.js. With JS off the specimen
   simply sits at its start position and the section still reads. */
.exmlens {
  position: relative;
  width: min(100%, 460px);
  aspect-ratio: 1;
  margin-inline: auto;
  border-radius: 62% 38% 46% 54% / 54% 47% 53% 46%;
  overflow: hidden;
  background-image: url("../img/about-specimen.webp");
  background-repeat: no-repeat;
  background-size: auto 1400px;
  /* 67% not 50%: the two specimens sit right of centre on the plate, so a
     centred window shows paper down one side. Derived from the rendered
     plate width (1075px) against the 460px aperture — and it lands on the
     same value the reference uses, which is a good sign the read was right. */
  background-position: 67% 0;
  box-shadow: 0 40px 80px -50px rgba(14, 32, 42, 0.28);
}

/* Field stop, the way an eyepiece edge falls off */
.exmlens::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(14, 32, 42, 0.10);
  pointer-events: none;
}

.exmlens-cap {
  margin-top: var(--s5);
  text-align: center;
}

/* Held while the section passes, which is what gives the specimen something
   to travel against. The column stretches so there is room to stick. */
@media (min-width: 980px) {

  /* Sticky sits on the whole aside, not on .exmlens alone. With it on the lens,
     the caption stayed in flow and the aperture slid down over the top of it.
     align-self:start keeps the item at content height inside a stretched grid
     area, which is what gives the stick somewhere to travel. */
  .exmabx-inner {
    align-items: stretch;
  }

  .exmabx-aside {
    align-self: start;
    position: sticky;
    top: calc(var(--head-h) + 48px);
  }
}

.exmfacts {
  margin-top: var(--s7);
  border-top: 1px solid var(--rule);
}

@media (min-width: 620px) {
  .exmfacts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s7);
  }
}

.exmfacts>div {
  display: grid;
  gap: 2px;
  padding: var(--s4) 0;
  border-bottom: 1px solid var(--rule);
}

.exmfacts dt {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmfacts dd {
  font-size: 1.05rem;
  color: var(--ink);
}

.exmfacts-marked dt {
  display: flex;
  align-items: center;
  gap: 9px;
}

/* --------------------------------------------------------------------------
   8. PRODUCTS — the scroll-stacked deck, re-toned
   Behaviour is unchanged: sticky cards with a stepped offset, gathering into
   a deck. Only the surface treatment moves to paper.
   -------------------------------------------------------------------------- */
/* THE HEADER'S RIGHT COLUMN — section 16 molecule, section 17 grid.
   isolation, not overflow. A stacking context is what lets the grid sit at
   z-index -1 behind the copy without falling behind the section's own
   background. overflow:hidden here would have been the obvious reflex and
   would have silently killed the sticky deck below, since a scroll container
   disables position:sticky in every descendant. */
.exmpshead,
.exmshead {
  position: relative;
  isolation: isolate;
}

/* The brand grid, faded out before it reaches the copy so it never sits
   under running text. */
.exmpshead::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -12% 0 -12% 44%;
  background-image: radial-gradient(circle at center, var(--navy) 1.1px, transparent 1.2px);
  background-size: 26px 26px;
  opacity: 0.1;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 74%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 30%, #000 74%, transparent);
  pointer-events: none;
}

.exmsfx {
  position: absolute;
  z-index: -1;
  right: 1%;
  top: 50%;
  transform: translateY(-50%);
  width: min(42%, 430px);
  height: auto;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}

.exmsfx-l {
  stroke: var(--navy);
  stroke-width: 1.6;
  opacity: 0.22;
}

.exmsfx-n {
  fill: var(--navy);
  opacity: 0.3;
}

/* The core is the only thing here allowed to carry weight, and the only
   green: "crossing bonds, green core". */
.exmsfx-k {
  stroke: var(--green);
  stroke-width: 2.4;
  fill: var(--green);
  opacity: 0.62;
}

/* ONE MARK PER SECTION, EACH A DIFFERENT MEANING.
   Section 16 defines the system as "one calm system, five meanings" and says
   to use it sparingly. So no section repeats another's, and the four in use
   are spread down the page rather than stacked:

     Products        molecule, fused ring with a green core  INTEGRATED
     Portfolio       HPLC trace, main peak green             PRECISION
     Principles      the swoosh, section 17                  forward movement
     Accreditations  graticule, one market node green        GLOBALLY PROVEN

   Sizes differ because the drawings do. A wide chromatogram and a round
   graticule cannot share one width and both sit right. */
/* No min-height. A mark must never reserve vertical space: it is background,
   so it either fits the room the copy already leaves or it is anchored to a
   corner and allowed to bleed. */
/* Anchored to a top corner of the header and pushed clear of it, so the
   drawing sits wholly in the section's own padding band. It reserves no
   height and never touches a word. Swap left/right below to move it. */
.exmsfx-struct {
  /* Sized off the section padding rather than off the column, so the drawing
     can never be taller than the band it lives in. The viewBox is 246x122,
     so height = width / 2.02; solving for "height + gap <= --sec-y" gives
     this. 244px wide at 1440, 147px at 1041, and it fits both. */
  width: min(calc((var(--sec-y) - 10px) * 2), 250px);
  left: auto;
  right: 0;
  top: 0;
  transform: translateY(calc(-100% - 8px));
}

/* Type inside a drawing. The atom labels are part of the diagram, not page
   copy, so they carry the drawing's own scale rather than the type scale.
   The group is inside an aria-hidden SVG. */
.exmsfx-t text {
  fill: var(--navy);
  stroke: none;
  font-size: 17px;
  font-weight: 500;
  text-anchor: middle;
  dominant-baseline: middle;
}

.exmsfx-t .sub {
  font-size: 11px;
}

.exmsfx-t {
  opacity: 0.42;
}

/* A mark that lives in a band of section padding rather than a column.
   left/right rather than a width, so it spans the content box exactly and
   lines up with the rule under the eyebrow beneath it. */
.wrap-marked {
  position: relative;
  isolation: isolate;
}

.exmsfx-rule {
  top: auto;
  bottom: 100%;
  left: var(--gut);
  right: auto;
  /* An explicit width, not left+right. An absolutely positioned SVG with
     width:auto takes its intrinsic size from the viewBox and drops `right`
     as over-constrained, which is why it first rendered 929px wide instead
     of spanning the column. */
  width: calc(100% - 2 * var(--gut));
  height: auto;
  transform: none;
  margin-bottom: clamp(8px, 1vw, 14px);
}

/* Below this there is no spare column, and a decoration under the copy is
   worse than no decoration. */
@media (max-width: 1040px) {

  .exmsfx,
  .exmpshead::after {
    display: none;
  }
}

/* The section field turns navy then green under the deck. If the header is
   still in view when that happens, navy strokes on navy vanish. */
.exmpstack.is-deck-2 .exmsfx-l,
.exmpstack.is-deck-3 .exmsfx-l {
  stroke: var(--white);
  opacity: 0.26;
}

.exmpstack.is-deck-2 .exmsfx-n,
.exmpstack.is-deck-3 .exmsfx-n {
  fill: var(--white);
  opacity: 0.3;
}

.exmpstack.is-deck-2 .exmsfx-k {
  stroke: var(--green-lt);
  fill: var(--green-lt);
}

.exmpstack.is-deck-3 .exmsfx-k {
  stroke: var(--white);
  fill: var(--white);
}

.exmpstack.is-deck-2 .exmpshead::after,
.exmpstack.is-deck-3 .exmpshead::after {
  background-image: radial-gradient(circle at center, #fff 1.1px, transparent 1.2px);
  opacity: 0.16;
}

.exmsfx-l,
.exmsfx-n,
.exmsfx-k {
  transition: stroke var(--t-slow) var(--ease), fill var(--t-slow) var(--ease), opacity var(--t-slow) var(--ease);
}

.exmpstack {
  background: var(--paper);
  transition: background-color var(--t-slow) var(--ease);
}

.exmpstack.is-deck-1 {
  background-color: var(--white);
}

.exmpstack.is-deck-2 {
  background-color: var(--navy);
}

.exmpstack.is-deck-3 {
  background-color: var(--green);
}

/* The section header sits on that field, so it has to flip when the field
   goes dark. Without this the navy H2 lands on navy at deck 2 and vanishes.
   White on navy is 9.35:1; white on green is 4.71:1, and the H2 is 26px/700,
   which WCAG counts as large text. */
.exmpstack.is-deck-2 .code,
.exmpstack.is-deck-3 .code {
  color: rgba(255, 255, 255, 0.72);
  border-bottom-color: var(--rule-dark);
}

.exmpstack.is-deck-2 .h2,
.exmpstack.is-deck-3 .h2 {
  color: var(--white);
}

.exmpstack.is-deck-2 .lede,
.exmpstack.is-deck-3 .lede {
  color: rgba(255, 255, 255, 0.86);
}

.exmpstack.is-deck-2 .hl {
  color: var(--green-lt);
}

.exmpstack.is-deck-3 .hl {
  color: var(--navy-20);
}

/* green on green would vanish */
.exmpstack .code,
.exmpstack .h2,
.exmpstack .lede,
.exmpstack .hl {
  transition: color var(--t-slow) var(--ease);
}

.exmpstack-list {
  --bar: 48px;
  margin-top: var(--s7);
}

/* The cards are the readable surface floating on that field, so all three
   are White. Depth comes from the stepped bars and the shadow, not from
   tinting each card a different shade of off-white. */
.exmpcard {
  background: var(--white);
  border: 1px solid var(--rule);
  box-shadow: 0 -20px 44px -30px rgba(26, 34, 48, 0.45);
}

.exmpcard+.exmpcard {
  margin-top: var(--s4);
}

.exmpcard-no {
  display: flex;
  align-items: center;
  gap: 16px;
  height: var(--bar);
  padding: 0 clamp(20px, 3vw, 40px);
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
}

.exmpcard-lbl {
  color: var(--slate);
}

.exmpcard-body {
  display: grid;
  gap: var(--s5);
  padding: clamp(28px, 3.4vw, 52px) clamp(20px, 3vw, 40px);
}

@media (min-width: 860px) {
  .exmpcard-body {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(28px, 3.5vw, 64px);
    align-items: start;
  }

  .exmpcard-n,
  .exmpcard-d,
  .exmpcard .arrow {
    grid-column: 1;
  }

  .exmpcard-spec {
    grid-column: 2;
    grid-row: 1 / span 2;
  }
}

.exmpcard-n {
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.2rem);
  color: var(--navy);
}

.exmpcard-d {
  color: var(--ink-2);
  max-width: 44ch;
}

.exmpcard-spec {
  border-top: 1px solid var(--rule);
}

.exmpcard-spec>div {
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}

.exmpcard-spec dt {
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 3px;
}

.exmpcard-spec dd {
  font-size: var(--fs-sm);
  color: var(--ink);
}

@media (min-width: 760px) and (prefers-reduced-motion: no-preference) {
  .exmpcard {
    position: sticky;
    min-height: min(56vh, 520px);
  }

  .exmpcard:nth-child(1) {
    top: calc(var(--head-h) + 24px);
  }

  .exmpcard:nth-child(2) {
    top: calc(var(--head-h) + 24px + var(--bar));
  }

  .exmpcard:nth-child(3) {
    top: calc(var(--head-h) + 24px + 2 * var(--bar));
  }

  .exmpcard+.exmpcard {
    margin-top: clamp(48px, 9vh, 104px);
  }

  .exmpcard-body {
    align-content: start;
    min-height: calc(min(56vh, 520px) - var(--bar));
  }

  /* Real in-flow room, not padding: a sticky box is bounded by its containing
     block's CONTENT box, so padding here would give the last card a
     zero-length stuck range and it would slide straight past its line. */
  .exmpstack-list::after {
    content: "";
    display: block;
    height: 56vh;
  }
}

@media (max-width: 759px) and (min-height: 760px) and (prefers-reduced-motion: no-preference) {
  .exmpcard {
    position: sticky;
  }

  .exmpcard:nth-child(1) {
    top: 64px;
  }

  .exmpcard:nth-child(2) {
    top: calc(64px + var(--bar));
  }

  .exmpcard:nth-child(3) {
    top: calc(64px + 2 * var(--bar));
  }

  .exmpcard+.exmpcard {
    margin-top: clamp(36px, 6vh, 72px);
  }

  .exmpstack-list::after {
    content: "";
    display: block;
    height: 34vh;
  }
}

/* --------------------------------------------------------------------------
   9. PORTFOLIO — DEVICE 2, THE PERIODIC GRID
   The API portfolio as element cells. Index number top left, a two-letter
   symbol as the display glyph, the molecule name beneath, and the
   therapeutic class as an asterisked note at the foot of the cell.

   [VERIFY] the symbols are a typographic device, not IUPAC or any registered
   notation. They are derived from each molecule's own name and carry no
   external meaning. Molecule names and classes are the only sourced data
   here; nothing about CAS, DMF or filing status is claimed.
   -------------------------------------------------------------------------- */
.exmptable {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-top: 1px solid var(--rule);
  border-left: 1px solid var(--rule);
  margin-top: var(--s7);
}

@media (min-width: 720px) {
  .exmptable {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .exmptable {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.exmpt {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 208px;
  padding: var(--s4) var(--s4) var(--s5);
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  transition: background var(--t) var(--ease);
}

.exmpt:hover {
  background: var(--paper-2);
}

.exmpt.exmpt-dev:hover {
  background: #f2f2f2;
}

.exmpt-dev {
  background: #f2f2f2;
}

.exmpt-no {
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  color: var(--ink-3);
}

.exmpt-sym {
  margin-top: var(--s5);
  font-size: clamp(2.2rem, 1.4rem + 2.2vw, 3.2rem);
  line-height: 1;
  color: var(--ink);
}

.exmpt-dev .exmpt-sym {
  color: var(--ink-3);
}

.exmpt-name {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmpt-note {
  margin-top: auto;
  padding-top: var(--s4);
}

/* Status marker, top right of the cell */
.exmpt-tag {
  position: absolute;
  top: var(--s4);
  right: var(--s4);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
}

.exmpt-dev .exmpt-tag {
  background: transparent;
  border: 1px solid var(--ink-3);
}

/* THE LIVE PULSE — commercial supply only.
   The core dot stays solid and still. What moves is a halo expanding out of
   it and fading, which is the "on air" indicator rather than a blink: an
   on/off flash of seven dots at once would strobe, and a dot that spends
   half its time invisible stops reading as a status.

   Only transform and opacity animate, so all seven run on the compositor and
   cost no layout. The halo is drawn by a pseudo-element rather than a
   box-shadow so it can scale without the core scaling with it. */
.exmpt:not(.exmpt-dev) .exmpt-tag::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--green);
  animation: ptLive 2.4s var(--ease-io) infinite;
  pointer-events: none;
}

@keyframes ptLive {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }

  70% {
    transform: scale(3.4);
    opacity: 0;
  }

  100% {
    transform: scale(3.4);
    opacity: 0;
  }
}

/* Staggered, so the grid ripples instead of flashing in unison. The offsets
   are not a sequence: adjacent cells never share a delay. */
.exmpt:nth-child(2) .exmpt-tag::after {
  animation-delay: 0.9s;
}

.exmpt:nth-child(3) .exmpt-tag::after {
  animation-delay: 0.35s;
}

.exmpt:nth-child(4) .exmpt-tag::after {
  animation-delay: 1.5s;
}

.exmpt:nth-child(5) .exmpt-tag::after {
  animation-delay: 0.6s;
}

.exmpt:nth-child(6) .exmpt-tag::after {
  animation-delay: 1.85s;
}

.exmpt:nth-child(7) .exmpt-tag::after {
  animation-delay: 1.15s;
}

/* The legend dot carries the same state, so it carries the same signal. */
.exmptable-key i:not(.is-dev) {
  position: relative;
}

.exmptable-key i:not(.is-dev)::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--green);
  animation: ptLive 2.4s var(--ease-io) infinite;
}

.exmptable-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
  margin-top: var(--s5);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

.exmptable-key span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.exmptable-key i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
}

.exmptable-key i.is-dev {
  background: transparent;
  border: 1px solid var(--ink-3);
}

/* --------------------------------------------------------------------------
   10. PRINCIPLES
   -------------------------------------------------------------------------- */
.exmcreed {
  background: var(--paper-3);
}

.exmcreed-grid {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: var(--s7);
}

@media (min-width: 760px) {
  .exmcreed-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmcreed-card {
  background: var(--paper);
  padding: var(--s6) var(--s5) var(--s7);
}

.exmcreed-no {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  color: var(--navy);
}

.exmcreed-t {
  margin: var(--s5) 0 var(--s3);
  font-size: var(--fs-h3);
}

.exmcreed-d {
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   11. MANUFACTURING
   -------------------------------------------------------------------------- */
.exmsites {
  background: var(--paper);
}

.exmsites-head {
  margin-bottom: var(--s8);
}

/* --------------------------------------------------------------------------
   THE SITE COMPARISON
   Three columns: the label once on the left, then a column per site. Every
   row lines up across both, which is the only reason to put two facilities
   next to each other in the first place.

   The markup is one block per facility, since that is the only order that
   works on a phone. display:contents is what lets the same markup become a
   table here: each block removes itself from the layout and its cells land
   directly on the parent grid, so both sites share one set of rows. Giving
   each block its own grid instead would produce columns that never agree.

   grid-auto-flow: column then fills the labels down track 1, Vadodara down
   track 2 and Vapi down track 3, with no per-cell placement. It does mean
   the row count is stated once, below: a sixth fact per site needs
   repeat(6, auto).
   -------------------------------------------------------------------------- */
.exmcmp {
  display: grid;
}

/* --- Under 900px: one facility after another, each value labelled -------- */
/* The shared label column has nothing to align to at this width. */
.exmcmp-labs {
  display: none;
}

.exmcmp-col+.exmcmp-col {
  margin-top: var(--s7);
  padding-top: var(--s7);
  border-top: 1px solid var(--rule);
}

.exmcmp-site {
  padding-bottom: var(--s5);
}

.exmcmp-v {
  padding-block: var(--s5);
  border-top: 1px solid var(--rule);
}

.exmcmp-k {
  display: block;
  margin-bottom: 4px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

@media (min-width: 900px) {
  .exmcmp {
    grid-template-columns: 148px minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: repeat(5, auto);
    grid-auto-flow: column;
    column-gap: var(--s7);
  }

  .exmcmp-labs,
  .exmcmp-col {
    display: contents;
  }

  .exmcmp-col+.exmcmp-col {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }

  /* The rules live on the cells, since the blocks no longer generate boxes.
     Cells stretch to the row, so a bottom border rules the whole row. */
  .exmcmp-site {
    padding-bottom: var(--s6);
    border-bottom: 1px solid var(--rule);
  }

  .exmcmp-lab,
  .exmcmp-v {
    padding-block: var(--s5);
    border-top: 0;
    border-bottom: 1px solid var(--rule);
  }

  .exmcmp-lab-head {
    border-bottom: 1px solid var(--rule);
  }

  /* Announced, not shown: at this width the left column already says it. */
  .exmcmp-k {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.exmcmp-lab {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmcmp-v {
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmcmp-no {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
}

.exmcmp-name {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: var(--s4) 0 var(--s2);
  font-size: clamp(1.8rem, 1.2rem + 1.8vw, 2.6rem);
  color: var(--navy);
}

/* The mark scales with the name it sits beside rather than staying 20px
   against a 42px word. */
.exmcmp-name .ic {
  width: 0.72em;
  height: 0.72em;
  stroke-width: 1.35;
}

.exmcmp-role {
  font-size: var(--fs-sm);
  color: var(--slate);
}

.exmcmp-text {
  margin-top: var(--s4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  max-width: 42ch;
}

/* Approvals read as marks to scan for, not a sentence to read through. */
.exmcmp .chips {
  margin-top: 2px;
}

/* --------------------------------------------------------------------------
   ICONS — Brand Guidelines 2026, section 18.
   "A 24px grid in a single 1.6px weight, with rounded joins. Navy by default,
   green only to mark an active or key state."

   The weight is set once here, not per icon, so it cannot drift. Stroke takes
   currentColor, so the same sprite serves navy on white, white on navy and
   green at the QC gate without a second definition.
   -------------------------------------------------------------------------- */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.ic {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--navy);
}

.exmcreds {
  display: grid;
  gap: var(--s5);
  margin-top: var(--s7);
}

@media (min-width: 620px) {
  .exmcreds {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .exmcreds {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.exmcreds li {
  padding-top: var(--s4);
  border-top: 1px solid var(--ink);
  font-size: var(--fs-sm);
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   12. COMPLIANCE
   -------------------------------------------------------------------------- */
.exmcompliance {
  background: var(--paper-3);
}

.exmcompliance-head {
  display: grid;
  gap: var(--s5);
}

@media (min-width: 980px) {
  .exmcompliance-head {
    grid-template-columns: 1.1fr 1fr;
    gap: var(--s8);
    align-items: end;
  }
}

.exmcompliance-aside {
  display: grid;
  gap: var(--s5);
  justify-items: start;
}

.exmapprovals {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: var(--s7);
}

@media (min-width: 700px) {
  .exmapprovals {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .exmapprovals {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmap {
  background: var(--paper);
  padding: var(--s6) var(--s5);
}

.exmap-no {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  color: var(--navy);
}

.exmap-n {
  margin: var(--s5) 0 4px;
  font-size: var(--fs-h3);
}

.exmap-site {
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}

.exmap-d {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   13. CLIENTELE
   -------------------------------------------------------------------------- */
.exmpartners {
  background: var(--paper);
}

.exmpartners-head {
  display: grid;
  gap: var(--s5);
}

@media (min-width: 900px) {
  .exmpartners-head {
    grid-template-columns: 1.1fr 1fr;
    gap: var(--s8);
    align-items: end;
  }
}

.exmcgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: var(--s7);
}

@media (min-width: 700px) {
  .exmcgrid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .exmcgrid {
    grid-template-columns: repeat(8, minmax(0, 1fr));
  }
}

.exmcgrid li {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 128px;
  padding: var(--s4) var(--s3);
  background: var(--paper);
  text-align: center;
}

.exmcgrid img {
  width: 100%;
  max-width: 100px;
  height: 100px;
  object-fit: contain;
  /* filter: grayscale(1); 
  opacity: 0.55; */
  transition: filter var(--t) var(--ease), opacity var(--t) var(--ease);
}

.exmcgrid li:hover img {
  filter: grayscale(0);
  opacity: 1;
}

.exmcgrid span {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  line-height: 1.3;
  display: none;
}

.exmindex-note {
  margin-top: var(--s6);
}

/* --------------------------------------------------------------------------
   BLOG
   Three cards on the same hairline grid the client register and the approvals
   use, so the page keeps one way of drawing a set of things rather than
   inventing a fourth.

   The whole card is the link, not just the title: a 300px target beats a
   four-word one, and it means the category and standfirst are part of the
   link's accessible name rather than dead text beside it.
   -------------------------------------------------------------------------- */
.exmblog {
  background: var(--paper-3);
}

.exmblog-head {
  display: grid;
  gap: var(--s5);
}

@media (min-width: 900px) {
  .exmblog-head {
    grid-template-columns: 1.1fr 1fr;
    gap: var(--s8);
    align-items: end;
  }
}

.exmblog-aside {
  display: grid;
  gap: var(--s5);
  justify-items: start;
}

.exmposts {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: var(--s7);
}

@media (min-width: 760px) {
  .exmposts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* flex on the item and flex:1 on the link, rather than height:100% on the
   link. The card has to fill the row whatever the tallest standfirst does,
   and a percentage height needs a definite one to resolve against. */
.exmpost {
  display: flex;
  background: var(--paper);
}

.exmpost-link {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--s6) var(--s5) var(--s6);
  color: inherit;
  transition: background var(--t) var(--ease);
}

.exmpost-link:hover {
  background: var(--paper-2);
  color: inherit;
}

.exmpost-k {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmpost-k .ic {
  width: 17px;
  height: 17px;
}

.exmpost-t {
  margin: var(--s5) 0 var(--s3);
  font-size: var(--fs-h3);
  color: var(--navy);
  transition: color var(--t) var(--ease);
}

/* Not green on hover: at 20px/600 this is not large text by WCAG, and s13
   keeps green off anything that is not. */
.exmpost-link:hover .exmpost-t {
  color: var(--navy-dk);
}

.exmpost-d {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmpost-go {
  margin-top: auto;
  padding-top: var(--s6);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--navy);
}

.exmpost-go::after {
  content: " \2197";
  display: inline-block;
  transition: transform var(--t) var(--ease);
}

.exmpost-link:hover .exmpost-go::after {
  transform: translate(3px, -3px);
}

/* --------------------------------------------------------------------------
   14. CONTACT — the one deep panel, as a close
   -------------------------------------------------------------------------- */
.exmcontact {
  background: var(--deep);
  color: rgba(255, 255, 255, 0.78);
}

.exmcontact-grid {
  display: grid;
  gap: var(--s8);
}

@media (min-width: 980px) {
  .exmcontact-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 480px);
    align-items: start;
  }
}

.ticks {
  margin-top: var(--s6);
  display: grid;
  gap: var(--s3);
}

.ticks li {
  padding-left: var(--s5);
  position: relative;
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.82);
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 10px;
  height: 1px;
  background: var(--green-lt);
}

.exmcontact-addr {
  margin-top: var(--s6);
  font-style: normal;
  font-size: var(--fs-sm);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.7);
}

.exmcontact-addr a {
  color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}

.exmcontact-addr a:hover {
  color: var(--green-lt);
  border-bottom-color: currentColor;
}

.exmform {
  background: var(--paper);
  padding: var(--s7) var(--s6);
}

.exmform-t {
  font-size: var(--fs-h3);
  color: var(--navy);
  margin-bottom: var(--s6);
}

.exmfld {
  margin-bottom: var(--s5);
}

.exmfld label {
  display: block;
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0;
}

.exmfld input,
.exmfld select,
.exmfld textarea {
  width: 100%;
  padding: 12px 0;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  color: var(--ink);
  font-size: var(--fs-sm);
  transition: border-color var(--t) var(--ease);
}

.exmfld textarea {
  resize: vertical;
  min-height: 84px;
}

.exmfld input:focus,
.exmfld select:focus,
.exmfld textarea:focus {
  outline: none;
  border-bottom-color: var(--blue);
}

.exmfld input::placeholder,
.exmfld textarea::placeholder {
  color: #A8B0B5;
}

.exmfld-h {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  margin-top: 6px;
}

.exmform-l {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  margin-top: var(--s4);
  text-align: center;
}

/* --------------------------------------------------------------------------
   15. FOOTER
   -------------------------------------------------------------------------- */
.exmfoot {
  background: var(--deep-2);
  color: rgba(255, 255, 255, 0.66);
  font-size: var(--fs-sm);
}

.exmfoot-top {
  display: grid;
  gap: var(--s7) var(--s6);
  padding-block: var(--s8);
}

@media (min-width: 700px) {
  .exmfoot-top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .exmfoot-top {
    grid-template-columns: 1.6fr repeat(4, minmax(0, 1fr));
  }
}

.exmfoot-brand img {
  width: 128px;
  height: auto;
  background: #fff;
  padding: 8px 12px;
}

.exmfoot-brand p {
  margin-top: var(--s5);
  max-width: 32ch;
  line-height: 1.7;
}

.exmfoot-col .mono {
  display: block;
  color: #fff;
  margin-bottom: var(--s4);
}

.exmfoot-col ul {
  display: grid;
  gap: 10px;
}

/* recruitment@exemedpharma.com is 28 unbreakable characters and it does not
   fit its track between roughly 1040 and 1200px, which pushed the whole
   document into horizontal scroll. `anywhere` only breaks when the word
   genuinely cannot fit, so nothing else in the footer is affected. */
.exmfoot-col a,
.exmfoot address a {
  color: rgba(255, 255, 255, 0.66);
  overflow-wrap: anywhere;
}

.exmfoot-col a:hover,
.exmfoot address a:hover {
  color: #fff;
}

.exmfoot address {
  font-style: normal;
  line-height: 1.7;
}

.exmfoot address+ul {
  margin-top: var(--s4);
}

.exmfoot-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding-block: var(--s5);
  border-top: 1px solid var(--rule-dark);
  font-size: var(--fs-xs);
}

.exmfoot-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
}

/* These inherited the global navy link colour, which on the Ink footer is
   1.71:1. Everything else in the footer was already overridden; this row
   was not. */
.exmfoot-end a {
  color: rgba(255, 255, 255, 0.72);
}

.exmfoot-end a:hover {
  color: var(--white);
}

/* --------------------------------------------------------------------------
   16. REVEAL + REDUCED MOTION
   Softer than the previous build: 14px rather than 26px. Weightless type
   should not arrive with a thump.
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  /* iteration-count matters as much as duration here. Without it an infinite
     animation at 0.01ms keeps cycling flat out, which is the opposite of
     what the preference asked for. */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .exmpt-tag::after,
  .exmptable-key i::after {
    animation: none !important;
    opacity: 0 !important;
  }

  [data-reveal] {
    opacity: 1;
    transform: none;
  }

  .exmhero-video {
    display: none;
  }
}

@media print {

  .exmmast,
  .exmdrawer,
  .exmhero-media,
  .exmform {
    display: none !important;
  }

  body,
  .exmcontact,
  .exmfoot {
    background: #fff !important;
    color: #000 !important;
  }

  .h2-light,
  .lede-light {
    color: #000 !important;
  }
}

/* Visually hidden, still announced. Used for the portfolio grid's supply
   status, which is carried visually by a dot that a screen reader cannot
   interpret. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Headings carry no bottom margin of their own so each block can set its own
   rhythm, but a lede or paragraph following one directly needs the gap. */
h2+.lede,
h2+p,
.h2+.lede,
.h2+p {
  margin-top: var(--s5);
}

/* ==========================================================================
   17. INNER PAGES
   Components the inner pages need that the home page does not. Every value
   here comes from the tokens in section 1. Nothing above is overridden.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.1 PAGE HERO — copy left, image right
   The image is a real frame, not a background wash: it sits in its own
   column with a navy fact plate overlapping its lower left corner, so the
   proof (established, sites, approvals) is read against the picture rather
   than floating beside it. Type never crosses the image.
   -------------------------------------------------------------------------- */
.exmphero {
  position: relative;
  isolation: isolate;
  padding: calc(var(--head-h) + clamp(28px, 4vw, 64px)) 0 clamp(40px, 5vw, 72px);
  background: var(--paper);
}

.exmphero-in {
  display: grid;
  gap: var(--s7);
  align-items: center;
}

@media (min-width: 980px) {
  .exmphero-in {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(40px, 5vw, 88px);
  }
}

/* Breadcrumb — the caption voice, section 15. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--s6);
}

.crumbs a,
.crumbs span {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.crumbs a:hover {
  color: var(--navy);
}

.crumbs li+li::before {
  content: "/";
  margin-right: 10px;
  color: var(--navy-20);
  font-weight: 400;
}

.crumbs li:last-child span {
  color: var(--navy);
}

.exmphero-h {
  font-size: clamp(2rem, 1.1rem + 3.4vw, 3.5rem);
  color: var(--navy);
  max-width: 16ch;
  line-height: 1.08;
}

.exmphero-lede {
  margin-top: var(--s5);
}

.exmphero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

/* Inline proof under the actions: three small figures on one hairline. */
.exmphero-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4) var(--s7);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.exmphero-row div {
  display: grid;
  gap: 2px;
}

.exmphero-row b {
  font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  font-weight: 600;
  line-height: 1;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

.exmphero-row b i {
  font-style: normal;
  color: var(--green);
}

.exmphero-row>div>span {
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* The image column */
.exmphero-fig {
  margin: 0;
}

.exmphero-frame {
  position: relative;
}

.exmphero-img {
  position: relative;
  overflow: hidden;
  aspect-ratio: 5 / 4;
  background: var(--paper-3);
}

@media (min-width: 980px) {
  .exmphero-img {
    aspect-ratio: 4 / 4.4;
  }
}

.exmphero-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A brand-grid strip behind the frame's top-right so the picture is
   pinned to the page rather than pasted on it. */
.exmphero-frame::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -22px;
  right: -22px;
  width: 58%;
  height: 58%;
  background-image: radial-gradient(circle at center, var(--navy) 1.1px, transparent 1.2px);
  background-size: 22px 22px;
  opacity: 0.16;
}

/* Fact plate — navy, over the frame's lower-left corner */
.exmphero-plate {
  position: absolute;
  left: 0;
  bottom: 0;
  transform: translate(calc(-1 * clamp(0px, 3vw, 36px)), clamp(16px, 3vw, 36px));
  display: grid;
  gap: var(--s3);
  padding: var(--s5) var(--s6);
  background: var(--navy);
  color: var(--white);
  min-width: 220px;
}

.exmphero-plate dt {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

.exmphero-plate dd {
  font-size: var(--fs-sm);
  color: var(--white);
}

.exmphero-plate dd b {
  font-weight: 600;
  color: var(--green-lt);
}

@media (max-width: 979px) {
  .exmphero-plate {
    position: static;
    transform: none;
    margin-top: 1px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s4) var(--s6);
  }
}

.exmphero-cap {
  margin-top: clamp(28px, 4vw, 52px);
}

@media (max-width: 979px) {
  .exmphero-cap {
    margin-top: var(--s3);
  }
}

/* --------------------------------------------------------------------------
   17.2 SUB-NAVIGATION — in-page anchors on a hairline, sticky at the top.
   The masthead hides itself on downward scroll, so once a reader is moving
   down the page this bar is what remains; z-index sits under the masthead.
   -------------------------------------------------------------------------- */
.exmsubnav {
  position: sticky;
  top: 0;
  z-index: 150;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.exmsubnav-in {
  display: flex;
  align-items: center;
  gap: var(--s5);
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
  overflow-x: auto;
  scrollbar-width: none;
}

.exmsubnav-in::-webkit-scrollbar {
  display: none;
}

.exmsubnav-k {
  flex: none;
  color: var(--navy);
  font-weight: 700;
}

.exmsubnav-list {
  display: flex;
  gap: 2px;
  margin-left: auto;
}

.exmsubnav-list a {
  display: block;
  position: relative;
  padding: 16px 12px;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  white-space: nowrap;
  transition: color var(--t) var(--ease);
}

.exmsubnav-list a::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 2px;
  background: var(--navy);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease);
}

.exmsubnav-list a:hover,
.exmsubnav-list a.is-on {
  color: var(--navy);
}

.exmsubnav-list a.is-on::after {
  transform: scaleX(1);
}

@media (max-width: 700px) {
  .exmsubnav-k {
    display: none;
  }

  .exmsubnav-list {
    margin-left: 0;
  }
}

[data-sub] {
  scroll-margin-top: 72px;
}

/* --------------------------------------------------------------------------
   17.3 STORY — sticky label column, running copy, one pull-quote, and the
   old site's isometric laboratory illustration under the copy.
   -------------------------------------------------------------------------- */
.exmstory-grid {
  display: grid;
  gap: var(--s6);
}

@media (min-width: 900px) {
  .exmstory-grid {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr);
    gap: var(--s8);
    align-items: start;
  }

  .exmstory-side {
    position: sticky;
    top: 96px;
  }
}

.exmstory-body p+p {
  margin-top: var(--s4);
}

.exmstory-body p {
  max-width: 62ch;
  color: var(--ink-2);
}

.exmstory-body .lede {
  color: var(--ink);
}

.exmstory-illo {
  margin: var(--s7) 0 0;
  padding: var(--s6);
  background: var(--paper-3);
  border: 1px solid var(--rule);
}

.exmstory-illo img {
  width: 100%;
  max-width: 560px;
  height: auto;
  margin-inline: auto;
}

.exmstory-illo figcaption {
  margin-top: var(--s4);
  text-align: center;
}

.pull {
  margin: var(--s7) 0;
  padding-left: var(--s5);
  border-left: 2px solid var(--green);
  font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.7rem);
  font-weight: 600;
  line-height: 1.32;
  letter-spacing: -0.011em;
  color: var(--navy);
  max-width: 30ch;
}

.pull cite {
  display: block;
  margin-top: var(--s3);
  font-style: normal;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

/* --------------------------------------------------------------------------
   17.4 MILESTONE RAIL
   -------------------------------------------------------------------------- */
.exmtl {
  background: var(--paper-3);
}

.exmtl-list {
  display: grid;
  margin-top: var(--s7);
}

.exmtl-i {
  position: relative;
  padding: 0 0 var(--s7) var(--s6);
}

.exmtl-i::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 0;
  width: 1px;
  background: var(--navy-20);
}

.exmtl-i:last-child::before {
  display: none;
}

.exmtl-i::after {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--white);
  border: 1.6px solid var(--navy);
}

.exmtl-i-key::after {
  background: var(--green);
  border-color: var(--green);
}

@media (min-width: 760px) {
  .exmtl-list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--s5);
  }

  .exmtl-i {
    padding: 28px var(--s4) 0 0;
  }

  .exmtl-i::before {
    left: 0;
    right: calc(-1 * var(--s5));
    top: 5px;
    bottom: auto;
    width: auto;
    height: 1px;
  }

  .exmtl-i:last-child::before {
    display: block;
    right: calc(100% - 6px);
  }

  .exmtl-i::after {
    top: 0;
    left: 0;
  }
}

.exmtl-y {
  display: block;
  font-size: clamp(2.2rem, 1.4rem + 2.6vw, 3.6rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

.exmtl-i-key .exmtl-y {
  color: var(--green);
}

.exmtl-t {
  margin-top: var(--s4);
  font-size: var(--fs-h3);
  color: var(--navy);
}

.exmtl-d {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  max-width: 30ch;
}

.exmtl-tag {
  display: inline-block;
  margin-top: var(--s3);
  padding: 3px 9px;
  border: 1px solid var(--rule);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  background: var(--white);
}

/* --------------------------------------------------------------------------
   17.5 PRINCIPLES — the illustrated triptych (option B)
   Mission, Vision and Values as three cells on the hairline grid, each led
   by the old site's isometric illustration. Hover: the cell goes Navy, the
   type goes white, and the illustration is flattened to a white silhouette
   (brightness 0 + invert) so the picture reads on the dark ground.
   -------------------------------------------------------------------------- */
.exmtri {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 760px) {
  .exmtri {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmtri-cell {
  background: var(--paper);
  padding: var(--s6) var(--s5) var(--s7);
  transition: background var(--t) var(--ease), color var(--t) var(--ease);
}

.exmtri-cell img {
  height: 104px;
  width: auto;
  margin-bottom: var(--s5);
  transition: filter var(--t) var(--ease);
}

/* Inline icon set — fixed 40x40, inherits colour from the cell so the hover
   inversion is a colour change, not a filter hack. */
.exmtri-i {
  display: block;
  width: 50px;
  height: 50px;
  margin-bottom: var(--s5);
  color: var(--navy);
  transition: color var(--t) var(--ease);
}

.exmtri-k {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
  transition: color var(--t) var(--ease);
}

.exmtri-d {
  margin-top: var(--s3);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  transition: color var(--t) var(--ease);
}

.exmtri-cell:hover {
  background: var(--navy);
}

.exmtri-cell:hover .exmtri-k {
  color: var(--white);
}

.exmtri-cell:hover .exmtri-d {
  color: rgba(255, 255, 255, 0.84);
}

.exmtri-cell:hover img {
  filter: brightness(0) invert(1);
}

.exmtri-cell:hover .exmtri-i {
  color: var(--white);
}

.exmtri-sub {
  margin-top: var(--s8);
}

/* Core values as one ruled row: icon, title, one line. No hover — static. */
.exmstrow {
  display: grid;
  gap: var(--s4);
}

@media (min-width: 620px) {
  .exmstrow {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .exmstrow {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.exmstrow li {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: var(--s4);
  align-items: start;
  padding: var(--s4) var(--s4) var(--s5);
  border-top: 1px solid var(--ink);
  color: var(--ink-2);
  font-size: var(--fs-xs);
}

.exmstrow img {
  width: 64px;
  height: 64px;
  object-fit: contain;
}

.exmstrow b {
  display: block;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--navy);
  margin-bottom: 4px;
}

/* --------------------------------------------------------------------------
   17.7 GLOBAL REACH — stated, not mapped. A heading and six region cells on
   the hairline grid; the approval that opens each market sits under it.
   -------------------------------------------------------------------------- */
.exmreach {
  margin-top: var(--s8);
}

.exmreach-head {
  display: grid;
  gap: var(--s3);
}

.exmreach-t {
  font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.9rem);
  color: var(--navy);
  max-width: 30ch;
}

.exmreach-grid {
  display: grid;
  gap: 1px;
  margin-top: var(--s6);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 620px) {
  .exmreach-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .exmreach-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmreach-grid li {
  position: relative;
  background: var(--paper);
  padding: var(--s5) var(--s5) var(--s6) calc(var(--s5) + 18px);
}

.exmreach-grid li::before {
  content: "";
  position: absolute;
  left: var(--s5);
  top: calc(var(--s5) + 9px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green);
}

.exmreach-grid b {
  display: block;
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--navy);
}

.exmreach-grid span {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   17.8 SITES — two facility cards
   -------------------------------------------------------------------------- */
.exmsites2 {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 860px) {
  .exmsites2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmsite {
  background: var(--paper);
  padding: var(--s6) var(--s5) var(--s7);
}

.exmsite-no {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
}

.exmsite-n {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: var(--s4) 0 var(--s1);
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.2rem);
  color: var(--navy);
}

.exmsite-n .ic {
  width: 0.72em;
  height: 0.72em;
  stroke-width: 1.35;
}

.exmsite-role {
  font-size: var(--fs-sm);
  color: var(--slate);
}

.exmsite-d {
  margin-top: var(--s4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  max-width: 44ch;
}

.exmsite-spec {
  margin-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.exmsite-spec>div {
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}

.exmsite-spec dt {
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 4px;
}

.exmsite-spec dd {
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmsite .arrow {
  margin-top: var(--s5);
}

/* --------------------------------------------------------------------------
   17.9 MANAGEMENT — two full profiles. Monogram in place of a portrait
   until one is supplied; the biography runs in full from the old site.
   -------------------------------------------------------------------------- */
.exmleaders {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 900px) {
  .exmleaders {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmlead {
  background: var(--paper);
  padding: var(--s6) var(--s5) var(--s7);
}

.exmlead-head {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr);
  gap: var(--s5);
  align-items: center;
}

.exmlead-mono {
  width: 84px;
  height: 84px;
  display: grid;
  place-items: center;
  background: var(--navy);
  color: var(--white);
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.exmlead-mono img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmlead-n {
  font-size: clamp(1.3rem, 1.1rem + 0.8vw, 1.7rem);
  color: var(--navy);
}

.exmlead-r {
  margin-top: 4px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmlead-bio {
  margin-top: var(--s5);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.exmlead-bio p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  max-width: 58ch;
}

.exmlead-bio p+p {
  margin-top: var(--s3);
}

.exmlead-meta {
  margin-top: var(--s5);
  display: grid;
  gap: 1px;
}

.exmlead-meta div {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: var(--s4);
  padding: 10px 0;
  border-top: 1px solid var(--rule);
}

.exmlead-meta dt {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 3px;
}

.exmlead-meta dd {
  font-size: var(--fs-sm);
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   17.10 CSR — copy on the left, the three photographs from the old site on
   the right in a two-up: one portrait frame beside two landscapes stacked.
   -------------------------------------------------------------------------- */
.exmcsr {
  background: var(--paper-3);
}

.exmcsr-grid {
  display: grid;
  gap: var(--s7);
  margin-top: var(--s7);
}

@media (min-width: 980px) {
  .exmcsr-grid {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: var(--s8);
    align-items: start;
  }
}

.exmcsr-copy p {
  color: var(--ink-2);
  max-width: 56ch;
}

.exmcsr-copy p+p {
  margin-top: var(--s4);
}

.exmsdg {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--s5);
}

.exmsdg li {
  padding: 5px 12px;
  border: 1px solid var(--navy-20);
  background: var(--white);
  font-size: var(--fs-xs);
  color: var(--navy);
}

.exmcsr-list {
  margin-top: var(--s6);
  border-top: 1px solid var(--ink);
}

.exmcsr-list li {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: var(--s4);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmcsr-list li b {
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  color: var(--navy);
  padding-top: 4px;
}

.exmcsr-gal {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s3);
}

.exmcsr-gal figure {
  margin: 0;
  overflow: hidden;
  background: var(--white);
  border: 1px solid var(--rule);
}

.exmcsr-gal img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--ease);
}

.exmcsr-gal figure:hover img {
  transform: scale(1.03);
}

.exmcsr-gal .is-tall {
  grid-row: span 2;
}

.exmcsr-gal .is-tall img {
  aspect-ratio: auto;
  height: 100%;
}

.exmcsr-gal .is-wide {
  aspect-ratio: 4 / 3;
}

.exmcsr-gal figcaption {
  padding: 8px 12px;
  border-top: 1px solid var(--rule);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  background: var(--white);
}

.exmcsr-gal figure {
  display: flex;
  flex-direction: column;
}

.exmcsr-gal figure img {
  flex: 1;
  min-height: 0;
}

/* --------------------------------------------------------------------------
   17.11 EHS — policy statement left, commitments as a numbered register right
   -------------------------------------------------------------------------- */
.exmehs-grid {
  display: grid;
  gap: var(--s6);
}

@media (min-width: 900px) {
  .exmehs-grid {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr);
    gap: var(--s8);
    align-items: start;
  }

  .exmehs-side {
    position: sticky;
    top: 96px;
  }
}

.exmehs-side p {
  margin-top: var(--s5);
  color: var(--ink-2);
  max-width: 44ch;
}

.exmreg {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 620px) {
  .exmreg {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmreg li {
  background: var(--paper);
  padding: var(--s5) var(--s5) var(--s6);
}

.exmreg-no {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  color: var(--navy);
}

.exmreg-t {
  margin-top: var(--s3);
  font-size: var(--fs-h3);
  color: var(--navy);
}

.exmreg-d {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmreg li.is-key .exmreg-no {
  color: var(--green);
}

.exmehs-band {
  margin-top: var(--s6);
  padding: var(--s5) var(--s6);
  background: var(--navy);
  color: rgba(255, 255, 255, 0.86);
  display: grid;
  gap: var(--s2);
}

.exmehs-band b {
  color: var(--white);
  font-weight: 600;
  font-size: var(--fs-h3);
}

.exmehs-band span {
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   17.12 SUSTAINABILITY — a statement, then two columns: social on the left,
   climate-smart practices on the right, each a ruled list.
   -------------------------------------------------------------------------- */
.exmsus {
  background: var(--paper-3);
}

.exmsus-cols {
  display: grid;
  gap: var(--s6);
  margin-top: var(--s7);
}

@media (min-width: 860px) {
  .exmsus-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s7);
  }
}

.exmsus-col {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: var(--s6) var(--s5) var(--s7);
}

.exmsus-k {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmsus-t {
  margin-top: var(--s3);
  font-size: var(--fs-h3);
  color: var(--navy);
}

.exmsus-col>p {
  margin-top: var(--s3);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmsus-list {
  margin-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.exmsus-list li {
  position: relative;
  padding: 12px 0 12px var(--s5);
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmsus-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.15em;
  width: 10px;
  height: 1px;
  background: var(--green);
}

/* The report row: document glyph, title and meta, one solid button. */
.exmreport {
  display: grid;
  gap: var(--s5);
  align-items: center;
  margin-top: var(--s7);
  padding: var(--s6) var(--s6);
  background: var(--navy);
  color: rgba(255, 255, 255, 0.78);
}

@media (min-width: 860px) {
  .exmreport {
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--s7);
  }
}

.exmreport-doc {
  position: relative;
  width: 72px;
  height: 92px;
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.35);
  display: grid;
  place-items: center;
}

.exmreport-doc .ic {
  width: 28px;
  height: 28px;
  color: var(--green-lt);
}

.exmreport-pages {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  text-align: center;
  font-size: 9px;
  line-height: 1.1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

.exmreport-k {
  color: var(--green-lt);
  font-weight: 700;
}

.exmreport-t {
  margin-top: var(--s2);
  font-size: var(--fs-h3);
  color: var(--white);
}

.exmreport-d {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  max-width: 60ch;
}

.exmreport-btn {
  background: var(--white);
  border-color: var(--white);
  color: var(--navy);
}

.exmreport-btn:hover {
  background: var(--navy-20);
  border-color: var(--navy-20);
  color: var(--navy);
}

.exmsus-pledge {
  margin-top: var(--s7);
  display: grid;
  gap: var(--s5);
  padding: var(--s6);
  background: var(--white);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--green);
}

@media (min-width: 860px) {
  .exmsus-pledge {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }
}

.exmsus-pledge p {
  font-size: clamp(1.1rem, 1rem + 0.5vw, 1.35rem);
  font-weight: 600;
  color: var(--navy);
  max-width: 40ch;
  line-height: 1.35;
}

/* --------------------------------------------------------------------------
   17.13 CALL TO ACTION — one compact navy band
   Headline and a line on the left, two buttons on the right, a single rule
   of padding. Reads as a closing line, not another section.
   -------------------------------------------------------------------------- */
.exmcta {
  background: var(--deep);
  color: rgba(255, 255, 255, 0.78);
}

.exmcta-in {
  display: grid;
  gap: var(--s5);
  padding-block: clamp(36px, 4.5vw, 56px);
}

@media (min-width: 900px) {
  .exmcta-in {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s8);
  }
}

.exmcta-h {
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2rem);
  font-weight: 600;
  line-height: 1.2;
  color: var(--white);
  letter-spacing: -0.011em;
}

.exmcta-copy p {
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  max-width: 60ch;
}

.exmcta-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

.btn-white {
  background: var(--white);
  border-color: var(--white);
  color: var(--navy);
}

.btn-white:hover {
  background: var(--navy-20);
  border-color: var(--navy-20);
  color: var(--navy);
}

/* Section header pairs: heading left, lede + link right. */
.exmshead2 {
  display: grid;
  gap: var(--s5);
}

@media (min-width: 900px) {
  .exmshead2 {
    grid-template-columns: 1.1fr 1fr;
    gap: var(--s8);
    align-items: end;
  }
}

.exmshead2-aside {
  display: grid;
  gap: var(--s5);
  justify-items: start;
}


/* ==========================================================================
   17.14+  PRODUCT PAGES (products-api / -formulations / -ethical-division)
   A second family of inner components, deliberately unlike the About page.
   Tokens only; nothing above is overridden.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.14 NOTICE — the old site's "NOTE:" block kept as a block. A navy label
   column, the numbered notes verbatim, the catalogue link inline.
   -------------------------------------------------------------------------- */
.exmnotice {
  display: grid;
  margin-top: var(--s8);
  border: 1px solid var(--rule);
  background: var(--paper);
}

@media (min-width: 760px) {
  .exmnotice {
    grid-template-columns: 160px minmax(0, 1fr);
  }
}

.exmnotice-k {
  display: grid;
  place-items: center;
  padding: var(--s5);
  background: var(--navy);
  color: var(--white);
  font-size: var(--fs-h3);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.exmnotice ol {
  margin: 0;
  padding: var(--s5) var(--s6);
  counter-reset: n;
  list-style: none;
}

.exmnotice li {
  position: relative;
  counter-increment: n;
  padding: 12px 0 12px 40px;
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmnotice li:last-child {
  border-bottom: 0;
}

.exmnotice li::before {
  content: counter(n) ".";
  position: absolute;
  left: 0;
  top: 12px;
  font-weight: 700;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

.exmnotice li a.arrow {
  margin-left: 10px;
}

/* --------------------------------------------------------------------------
   17.15 TILES ON NAVY — a short navy band with white tiles. Used for the
   API intermediates: name, then the specification lines.
   -------------------------------------------------------------------------- */
.exmtband {
  background: var(--navy);
  color: var(--white);
}

.exmtband .code {
  color: rgba(255, 255, 255, 0.7);
  border-bottom-color: rgba(255, 255, 255, 0.25);
}

.exmtband .code span {
  color: var(--green-lt);
}

.exmtband .h2 {
  color: var(--white);
}

.exmtband .h2 .hl {
  color: var(--green-lt);
}

.exmtband .lede {
  color: rgba(255, 255, 255, 0.78);
}

.exmtiles {
  display: grid;
  gap: var(--s4);
  margin-top: var(--s7);
}

@media (min-width: 760px) {
  .exmtiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s5);
  }
}

.exmtile {
  padding: var(--s5) var(--s5) var(--s6);
  background: var(--white);
  color: var(--ink);
  border-top: 2px solid var(--green);
}

.exmtile-no {
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  color: var(--ink-3);
}

.exmtile-n {
  margin-top: var(--s4);
  font-size: var(--fs-h3);
  color: var(--navy);
}

.exmtile dl {
  margin-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.exmtile dl div {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr);
  gap: var(--s3);
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}

.exmtile dt {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 2px;
}

.exmtile dd {
  font-size: var(--fs-sm);
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   17.16 PORTHOLE HERO — the product pages' hero (approved design).
   Navy, full-bleed, faint dot-grid fading in from the right. Copy on the
   left: breadcrumb, eyebrow, H1, lede, two buttons, a meta line. On the
   right the photograph in a circular porthole with a thin ring of text
   (approvals and sites) turning slowly around it. The masthead gets
   .exmmast-solid so it has its white ground over the navy from the start.
   -------------------------------------------------------------------------- */
.exmmast-solid {
  background: var(--white);
  border-bottom-color: var(--rule);
}

.exmphero2 {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding: calc(var(--head-h) + clamp(40px, 6vw, 96px)) 0 clamp(48px, 6vw, 96px);
}

.exmphero2::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.18) 1px, transparent 1.2px);
  background-size: 24px 24px;
  -webkit-mask-image: linear-gradient(90deg, transparent 45%, #000 100%);
  mask-image: linear-gradient(90deg, transparent 45%, #000 100%);
  opacity: 0.6;
}

.exmphero2-in {
  display: grid;
  gap: var(--s7);
  align-items: center;
}

@media (min-width: 980px) {
  .exmphero2-in {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(40px, 6vw, 96px);
  }
}

.exmphero2 .crumbs a,
.exmphero2 .crumbs span {
  color: rgba(255, 255, 255, 0.6);
}

.exmphero2 .crumbs a:hover,
.exmphero2 .crumbs li:last-child span {
  color: var(--white);
}

.exmphero2 .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmphero2-k {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--green-lt);
  font-weight: 700;
}

.exmphero2-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmphero2-h {
  margin-top: var(--s4);
  font-size: clamp(2.3rem, 1.2rem + 4.2vw, 4.5rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 13ch;
}

.exmphero2-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmphero2-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.78);
  max-width: 46ch;
}

.exmphero2-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

.exmphero2-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s6);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.7);
}

.exmphero2-meta b {
  color: var(--white);
  font-weight: 600;
}

.exmport {
  position: relative;
  width: min(100%, 520px);
  aspect-ratio: 1;
  margin: 0 auto;
}

.exmport-ph {
  position: absolute;
  inset: 12%;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
  background: var(--navy-dk);
}

.exmport-ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  animation: portKb 20s var(--ease-io) infinite alternate;
}

@keyframes portKb {
  from {
    transform: scale(1);
  }

  to {
    transform: scale(1.08);
  }
}

.exmport-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  animation: portSpin 40s linear infinite;
}

@keyframes portSpin {
  to {
    transform: rotate(360deg);
  }
}

.exmport:hover .exmport-ring {
  animation-play-state: paused;
}

.exmport-ring text {
  font-family: Inter, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 3.4px;
  fill: rgba(255, 255, 255, 0.85);
}

.exmport-ring circle {
  fill: none;
  stroke: rgba(255, 255, 255, 0.25);
}

.exmport-cap {
  position: absolute;
  left: 50%;
  bottom: 2%;
  transform: translateX(-50%);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {

  .exmport-ring,
  .exmport-ph img {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   17.17 BENTO — the product list as an asymmetric grid (approved design).
   One lead tile (navy, 2×2) carries the flagship and its headline figure;
   standard tiles carry index, name, one spec line and the CAS; a wide grey
   tile groups the pipeline. On products-formulations the tiles are the 14
   categories, each with its product list (.exmbtile-list).
   -------------------------------------------------------------------------- */
.exmbento {
  display: grid;
  gap: var(--s4);
  margin-top: var(--s7);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 760px) {
  .exmbento {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-rows: minmax(150px, auto);
  }
}

.exmbtile {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s5);
  border: 1px solid var(--rule);
  background: var(--paper);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}

.exmbtile:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 30px rgba(31, 69, 133, 0.08);
}

.exmbtile-no {
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}

.exmbtile-n {
  margin-top: auto;
  padding-top: var(--s5);
  font-size: clamp(1.1rem, 1rem + 0.4vw, 1.35rem);
  font-weight: 600;
  line-height: 1.15;
  color: var(--navy);
}

.exmbtile-use {
  margin-top: 4px;
  font-size: var(--fs-xs);
  color: var(--slate);
}

.exmbtile-cas {
  margin-top: 8px;
  font-size: var(--fs-xs);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.exmbtile-cas b {
  font-weight: 700;
  color: var(--slate);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-right: 6px;
}

.exmbtile-dot {
  position: absolute;
  right: var(--s5);
  top: var(--s5);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green);
}

.exmbtile-lead {
  grid-column: span 2;
  grid-row: span 2;
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
  padding: var(--s6);
}

.exmbtile-lead .exmbtile-no {
  color: var(--green-lt);
}

.exmbtile-num {
  margin-top: var(--s5);
  font-size: clamp(3rem, 2rem + 4vw, 5.5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

.exmbtile-num small {
  font-size: var(--fs-sm);
  font-weight: 400;
  color: rgba(255, 255, 255, 0.75);
  letter-spacing: 0;
  margin-left: 10px;
}

.exmbtile-lead .exmbtile-n {
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.4rem);
  color: var(--white);
}

.exmbtile-lead .exmbtile-use,
.exmbtile-lead .exmbtile-cas {
  color: rgba(255, 255, 255, 0.78);
}

.exmbtile-lead .exmbtile-cas b {
  color: rgba(255, 255, 255, 0.6);
}

.exmbtile-wide {
  grid-column: span 2;
}

.exmbtile-dev {
  background: var(--paper-3);
}

.exmbtile-dev .exmbtile-n {
  color: var(--slate);
}

.exmbtile-dev .exmbtile-dot {
  background: transparent;
  border: 1px solid var(--slate);
}

.exmbento-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
  margin-top: var(--s5);
  font-size: var(--fs-xs);
  color: var(--slate);
}

.exmbento-key i {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  margin-right: 8px;
  vertical-align: middle;
}

.exmbento-key i.is-dev {
  background: transparent;
  border: 1px solid var(--slate);
}

/* Category tiles (formulations): the list of products inside a tile. */
.exmbtile-list {
  margin-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.exmbtile-lead .exmbtile-list {
  border-top-color: rgba(255, 255, 255, 0.22);
}

.exmbtile-list li {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmbtile-lead .exmbtile-list li {
  border-bottom-color: rgba(255, 255, 255, 0.16);
  color: var(--white);
}

.exmbtile-list b {
  font-weight: 600;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.exmbtile-list span {
  font-size: var(--fs-xs);
  color: var(--slate);
  text-align: right;
  flex: 0 1 auto;
  max-width: 48%;
  padding-top: 2px;
}

.exmbtile-lead .exmbtile-list span {
  color: rgba(255, 255, 255, 0.72);
}

.exmbtile-list img {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 2px;
}

.exmbtile-lead .exmbtile-list img {
  filter: brightness(0) invert(1);
}

.exmbtile-cat .exmbtile-n {
  margin-top: var(--s4);
  padding-top: 0;
}

.exmbtile-cat .exmbtile-list {
  margin-top: auto;
  padding-top: var(--s4);
}


/* ==========================================================================
   17.18+  ACCREDITATIONS PAGE (accreditations.html)
   A third family — "the register". The page is a dossier: seals, a statement,
   an approvals board, a certificate archive and a policy file. Nothing here
   reuses the About kit or the product porthole/bento. Tokens only.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.18 DOSSIER HERO — navy, full-bleed. Copy on the left; on the right the
   certificates themselves: four of the real documents fanned out like
   papers on a desk, each a white sheet with its own shadow, the fan opening
   a little further on hover (still under reduced-motion). Across the foot
   of the hero a white strip carries the eight regulator marks as a slow
   ticker (paused on hover, static under reduced-motion). The masthead
   takes .exmmast-solid so it is white over the navy from the top.
   -------------------------------------------------------------------------- */
.exmahero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(36px, 5vw, 80px));
}

.exmahero::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: radial-gradient(80% 70% at 85% 20%, rgba(255, 255, 255, 0.10), transparent 60%), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.045) 0 1px, transparent 1px 96px);
}

.exmahero-in {
  display: grid;
  gap: var(--s7);
  align-items: center;
  padding-bottom: clamp(40px, 6vw, 88px);
}

@media (min-width: 980px) {
  .exmahero-in {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(40px, 5vw, 96px);
  }
}

.exmahero .crumbs a,
.exmahero .crumbs span {
  color: rgba(255, 255, 255, 0.6);
}

.exmahero .crumbs a:hover,
.exmahero .crumbs li:last-child span {
  color: var(--white);
}

.exmahero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmahero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--green-lt);
  font-weight: 700;
}

.exmahero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmahero-h {
  margin-top: var(--s4);
  font-size: clamp(2.3rem, 1.2rem + 4.2vw, 4.5rem);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 12ch;
}

.exmahero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmahero-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.78);
  max-width: 50ch;
}

.exmahero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

/* Table of contents — each link is a count and a name, on one hairline. */
.toc {
  display: flex;
  flex-wrap: wrap;
  margin-top: var(--s7);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

.toc a {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 14px 18px 14px 0;
  margin-right: 18px;
  border-bottom: 2px solid transparent;
  color: rgba(255, 255, 255, 0.7);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  transition: color var(--t) var(--ease), border-color var(--t) var(--ease);
}

.toc a b {
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--white);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.toc a:hover {
  color: var(--white);
  border-bottom-color: var(--green-lt);
}

/* The fan of documents. Four real first pages, white sheets on navy. */
.exmfan {
  position: relative;
  width: min(100%, 560px);
  aspect-ratio: 10 / 9;
  margin: 0 auto 48px;
}

.exmfan-pg {
  position: absolute;
  left: 50%;
  bottom: 6%;
  width: 46%;
  margin: 0;
  transform-origin: 50% 110%;
  transform: translateX(-50%) rotate(var(--r, 0deg)) translateY(var(--y, 0));
  transition: transform var(--t-slow) var(--ease);
  background: var(--white);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.35), 0 2px 6px rgba(0, 0, 0, 0.25);
}

.exmfan-pg img {
  display: block;
  width: 100%;
  height: auto;
}

.exmfan-pg:nth-child(1) {
  --r: -16deg;
  --y: 6%;
}

.exmfan-pg:nth-child(2) {
  --r: -5deg;
  --y: 2%;
}

.exmfan-pg:nth-child(3) {
  --r: 5deg;
  --y: 2%;
}

.exmfan-pg:nth-child(4) {
  --r: 16deg;
  --y: 6%;
}

.exmfan:hover .exmfan-pg:nth-child(1) {
  --r: -22deg;
  --y: 8%;
}

.exmfan:hover .exmfan-pg:nth-child(2) {
  --r: -8deg;
}

.exmfan:hover .exmfan-pg:nth-child(3) {
  --r: 8deg;
}

.exmfan:hover .exmfan-pg:nth-child(4) {
  --r: 22deg;
  --y: 8%;
}

.exmfan-pg figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 10px;
  background: var(--navy);
  color: var(--white);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.exmfan-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -48px;
  text-align: center;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

@media (max-width: 979px) {
  .exmfan {
    aspect-ratio: 10 / 7.6;
  }
}

@media (prefers-reduced-motion: reduce) {
  .exmfan-pg {
    transition: none;
  }
}

/* The strip of regulator marks at the foot of the hero. */
.exmahero-strip {
  background: var(--white);
  color: var(--ink);
  border-top: 1px solid var(--rule);
  overflow: hidden;
}

.exmticker {
  display: flex;
  width: max-content;
  animation: tick 46s linear infinite;
}

.exmahero-strip:hover .exmticker {
  animation-play-state: paused;
}

@keyframes tick {
  to {
    transform: translateX(-50%);
  }
}

.exmticker ul {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.exmticker li {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 18px 40px;
  border-right: 1px solid var(--rule);
}

.exmticker img {
  height: 44px;
  width: auto;
  max-width: 120px;
  object-fit: contain;
}

.exmticker span {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
  white-space: nowrap;
}

.exmticker span b {
  display: block;
  color: var(--navy);
  font-weight: 700;
  letter-spacing: 0.08em;
  font-size: var(--fs-xs);
  text-transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .exmticker {
    animation: none;
    flex-wrap: wrap;
    width: auto;
  }

  .exmticker ul+ul {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   17.19 OATH — the statement. One sentence set large in navy on the left,
   the supporting paragraph on the right, a single green rule between them.
   -------------------------------------------------------------------------- */
.exmoath {
  display: grid;
  gap: var(--s6);
}

@media (min-width: 900px) {
  .exmoath {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(40px, 6vw, 96px);
  }
}

.exmoath-q {
  font-size: clamp(1.4rem, 1.05rem + 1.5vw, 2.35rem);
  font-weight: 500;
  line-height: 1.22;
  letter-spacing: -0.015em;
  color: var(--navy);
}

.exmoath-b {
  position: relative;
  padding-left: var(--s6);
  font-size: var(--fs-body);
  color: var(--ink-2);
  align-self: center;
}

.exmoath-b::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--green);
}

.exmoath-b p+p {
  margin-top: var(--s4);
}

/* --------------------------------------------------------------------------
   17.20 BOARD — the approvals, one row per product line. The row key is a
   navy cell carrying the count and the name; the marks follow in white
   cells on the hairline grid, each captioned with the regulator.
   -------------------------------------------------------------------------- */
.exmboard {
  margin-top: var(--s7);
  border: 1px solid var(--rule);
}

.exmboard-row {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border-top: 1px solid var(--rule);
}

.exmboard-row:first-child {
  border-top: 0;
}

@media (min-width: 760px) {
  .exmboard-row {
    grid-template-columns: 200px repeat(6, minmax(0, 1fr));
  }
}

@media (max-width: 759px) {
  .exmboard-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .exmboard-k {
    grid-column: 1 / -1;
  }
}

.exmboard-k {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s5);
  padding: var(--s5);
  background: var(--navy);
  color: var(--white);
}

.exmboard-k b {
  font-size: clamp(2.2rem, 1.6rem + 2vw, 3.4rem);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.03em;
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

.exmboard-k span {
  font-size: var(--fs-h3);
  font-weight: 600;
}

.exmboard-k small {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}

.exmboard-c {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: var(--s3);
  padding: var(--s5);
  background: var(--paper);
  min-height: 170px;
  margin: 0;
}

.exmboard-c img {
  justify-self: center;
  align-self: center;
  max-width: 120px;
  max-height: 72px;
  width: auto;
  height: auto;
  object-fit: contain;
}

.exmboard-c figcaption {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
  border-top: 1px solid var(--rule);
  padding-top: 10px;
}

.exmboard-c-empty {
  background: repeating-linear-gradient(135deg, var(--rule) 0 1px, var(--paper-3) 1px 12px);
  min-height: 0;
}

@media (max-width: 759px) {
  .exmboard-c-empty {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   17.21 ARCHIVE — the company certificates as documents, not buttons. Each
   card shows the first page of the real PDF clipped at the top, a running
   number, the title, the issuing authority, and a View link that opens the
   PDF. The whole card is the link.
   -------------------------------------------------------------------------- */
.exmarch {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 760px) {
  .exmarch {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .exmarch {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.exmdoc {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: inherit;
  text-decoration: none;
}

.exmdoc-pg {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--paper-3);
  border-bottom: 1px solid var(--rule);
}

.exmdoc-pg img {
  position: absolute;
  left: 12%;
  top: 10%;
  width: 76%;
  height: auto;
  box-shadow: 0 8px 24px rgba(31, 69, 133, 0.14), 0 0 0 1px var(--rule);
  transition: transform var(--t-slow) var(--ease);
}

.exmdoc:hover .exmdoc-pg img {
  transform: translateY(-6%);
}

.exmdoc-no {
  position: absolute;
  left: 14px;
  top: 12px;
  z-index: 1;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--navy);
  background: var(--paper);
  padding: 4px 8px;
  border: 1px solid var(--rule);
  font-variant-numeric: tabular-nums;
}

.exmdoc-b {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--s4) var(--s4) var(--s5);
}

.exmdoc-t {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.3;
  color: var(--navy);
}

.exmdoc-by {
  margin-top: 6px;
  font-size: var(--fs-xs);
  color: var(--slate);
}

.exmdoc-m {
  margin-top: auto;
  padding-top: var(--s4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
}

.exmdoc-m .arrow {
  font-size: var(--fs-label);
}

.exmdoc:hover .exmdoc-t {
  color: var(--navy-dk);
}

.exmdoc:hover .arrow {
  color: var(--green);
}

.exmdoc:hover .arrow span::after {
  transform: translate(3px, -3px);
}

.exmdoc:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: -2px;
}

/* Lead card — the first certificate at 2x2 so thirteen cards fill the grid. */
@media (min-width: 1100px) {
  .exmdoc-lead {
    grid-column: span 2;
    grid-row: span 2;
  }

  .exmdoc-lead .exmdoc-pg {
    aspect-ratio: auto;
    flex: 1;
    min-height: 360px;
  }

  .exmdoc-lead .exmdoc-b {
    flex: none;
  }

  .exmdoc-lead .exmdoc-pg img {
    left: 22%;
    width: 56%;
    top: 8%;
  }

  .exmdoc-lead .exmdoc-t {
    font-size: var(--fs-h3);
  }
}

@media (min-width: 760px) and (max-width: 1099px) {
  .exmdoc-lead {
    grid-column: span 3;
  }

  .exmdoc-lead .exmdoc-pg {
    aspect-ratio: 3 / 1;
  }

  .exmdoc-lead .exmdoc-pg img {
    left: 30%;
    width: 40%;
  }
}

@media (max-width: 759px) {
  .exmdoc-lead {
    grid-column: span 2;
  }
}

/* --------------------------------------------------------------------------
   17.22 FILE — the policies. Six numbered rows in a ruled list, each a
   small portrait of the document's first page beside the title. Sits on
   the tint band so it reads as a different register from 17.21.
   -------------------------------------------------------------------------- */
.file {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 760px) {
  .file {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .file {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmpol {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: var(--s4);
  align-items: center;
  padding: var(--s4) var(--s5);
  background: var(--paper);
  color: inherit;
  text-decoration: none;
  min-height: 120px;
}

.exmpol-pg {
  width: 64px;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--paper-3);
  box-shadow: 0 0 0 1px var(--rule);
}

.exmpol-pg img {
  width: 100%;
  height: auto;
  display: block;
}

.exmpol-no {
  display: block;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}

.exmpol-t {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.3;
  color: var(--navy);
}

.exmpol .arrow {
  display: inline-flex;
  margin-top: 8px;
  font-size: var(--fs-label);
}

.exmpol:hover .exmpol-t {
  color: var(--navy-dk);
}

.exmpol:hover .arrow {
  color: var(--green);
}

.exmpol:hover .arrow span::after {
  transform: translate(3px, -3px);
}

.exmpol:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: -2px;
}


/* ==========================================================================
   17.23+  CLIENTELE PAGE (clientele.html)
   A fourth, small register family. The old page publishes nothing but the
   heading "Our Clientele" and sixteen company marks, so the page is built
   as exactly that: the register on a hairline wall keyed by a navy count
   cell (the same grammar as the accreditations board, so proof pages read
   as one system). Hero history (20 Aug 2026): a static 2x2 logo "quad" and
   a static names roster were both rejected; the approved treatment is the
   17.24 ledger hero - a photograph plus the marks in motion.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.23 WALL — the register itself. A navy key cell (count + name of the
   register) spanning 2x2, then sixteen captioned mark cells. 5 columns on
   desktop and 4 on tablet both close exactly (4 + 16 = 20); on mobile the
   key goes full-width and the marks pair up (16 = 2 x 8). Static cells —
   the client rejected hover play on rows like these.
   -------------------------------------------------------------------------- */
.exmwall {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 760px) {
  .exmwall {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .exmwall {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.exmwall-k {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s6);
  padding: var(--s5);
  background: var(--navy);
  color: var(--white);
}

@media (min-width: 760px) {
  .exmwall-k {
    grid-column: span 2;
    grid-row: span 2;
  }
}

.exmwall-k b {
  font-size: clamp(3rem, 2rem + 3.4vw, 5.2rem);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.03em;
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

.exmwall-k span {
  font-size: var(--fs-h3);
  font-weight: 600;
  max-width: 16ch;
}

.exmwall-k small {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}

.exmwall-c {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: var(--s4);
  padding: var(--s5);
  background: var(--paper);
  min-height: 168px;
  margin: 0;
}

.exmwall-c img {
  justify-self: center;
  align-self: center;
  max-width: 116px;
  max-height: 64px;
  width: auto;
  height: auto;
  object-fit: contain;
}

.exmwall-c figcaption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  border-top: 1px solid var(--rule);
  padding-top: 10px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
  line-height: 1.4;
}

.exmwall-no {
  color: var(--navy-20);
  font-variant-numeric: tabular-nums;
}


/* --------------------------------------------------------------------------
   17.25 REG--LIVE — the "why they stay" register (the EHS .exmreg pattern with
   a little life): on hover a green rule draws across the top of the cell,
   the number turns green and the title deepens. Off under reduced motion.
   -------------------------------------------------------------------------- */
.exmreg-live {
  margin-top: var(--s7);
}

.exmreg-live li {
  position: relative;
  overflow: hidden;
}

.exmreg-live li::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  height: 2px;
  width: 0;
  background: var(--green);
  transition: width 480ms var(--ease);
}

.exmreg-live li:hover::after {
  width: 100%;
}

.exmreg-live .exmreg-no,
.exmreg-live .exmreg-t {
  transition: color var(--t) var(--ease);
}

.exmreg-live li:hover .exmreg-no {
  color: var(--green);
}

.exmreg-live li:hover .exmreg-t {
  color: var(--navy-dk);
}

@media (prefers-reduced-motion: reduce) {
  .exmreg-live li::after {
    transition: none;
  }
}


/* --------------------------------------------------------------------------
   17.24 LEDGER HERO — the clientele hero. Navy full-bleed with a faint dot
   grid: copy and the three figures on the left, a photograph framed on the
   right, and across the foot the client marks themselves — two lines of
   white chips running in opposite directions, both edges masked so the
   ledger reads as continuous rather than cut. The marks move, nothing else
   does; the ledger pauses on hover and is completely still under
   prefers-reduced-motion (one wrapped line, no second row). The masthead
   takes .exmmast-solid so it keeps its white ground over the navy. The
   ledger carries no label of its own (client, 20 Aug 2026) - the marks
   speak for themselves and the register section names them.
   -------------------------------------------------------------------------- */
.exmchero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(32px, 4.5vw, 68px));
}

.exmchero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.16) 1px, transparent 1.2px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(120% 90% at 15% 0%, #000, transparent 70%);
  mask-image: radial-gradient(120% 90% at 15% 0%, #000, transparent 70%);
  opacity: 0.5;
}

.exmchero-in {
  display: grid;
  gap: var(--s6);
  align-items: center;
  padding-bottom: clamp(32px, 4.5vw, 60px);
}

@media (min-width: 980px) {
  .exmchero-in {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(40px, 6vw, 88px);
  }
}

.exmchero .crumbs a,
.exmchero .crumbs span {
  color: rgba(255, 255, 255, 0.6);
}

.exmchero .crumbs a:hover,
.exmchero .crumbs li:last-child span {
  color: var(--white);
}

.exmchero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmchero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--green-lt);
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.exmchero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmchero-h {
  margin-top: var(--s4);
  font-size: clamp(2.2rem, 1.2rem + 3.9vw, 4.2rem);
  font-weight: 600;
  line-height: 1.03;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 15ch;
}

.exmchero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmchero-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.78);
  max-width: 48ch;
}

.exmchero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

/* Three figures on one rule under the actions. */
.exmchero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4) var(--s7);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

.exmchero-facts div {
  display: grid;
  gap: 2px;
}

.exmchero-facts b {
  font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2rem);
  font-weight: 600;
  line-height: 1;
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

.exmchero-facts span {
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.7);
}

/* The photograph: framed, with a thin white hairline instead of a shadow. */
.exmchero-fig {
  margin: 0;
}

.exmchero-img {
  position: relative;
  overflow: hidden;
  aspect-ratio: 5 / 4;
  background: var(--navy-dk);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.28);
}

@media (min-width: 980px) {
  .exmchero-img {
    aspect-ratio: 4 / 3.6;
  }
}

.exmchero-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmchero-cap {
  margin-top: var(--s3);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

/* ==========================================================================
   17.26+  CAREERS PAGE (careers.html)
   The fifth component family. The live /home/careers page is four
   paragraphs and two flat lists of vacancies, so the page is built as
   exactly that - but the two things a careers page is actually read for
   (who you would be working alongside, and what is open) each get their
   own component.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.26 BADGE HERO - the careers hero. Navy full-bleed over a faint ruled
   column field (a roster sheet, not the dot grid the product and clientele
   heroes use). Copy and three figures on the left; on the right the
   photograph is set in a site ID badge hanging from a hairline lanyard that
   fades out at the top of the frame. The badge sways very slowly on its
   clip - a degree and a half, and nothing else on the page moves - it stops
   on hover and is completely still under prefers-reduced-motion. The
   masthead takes .exmmast-solid so it keeps its white ground over the navy.
   -------------------------------------------------------------------------- */
.exmkhero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(32px, 4.5vw, 68px));
}

/* Ruled column field - vertical hairlines every 96px, faded out to the right. */
.exmkhero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.16) 0 1px, transparent 1px 96px);
  -webkit-mask-image: linear-gradient(100deg, #000 6%, rgba(0, 0, 0, 0.25) 54%, transparent 88%);
  mask-image: linear-gradient(100deg, #000 6%, rgba(0, 0, 0, 0.25) 54%, transparent 88%);
}

.exmkhero-in {
  display: grid;
  gap: var(--s7);
  align-items: center;
  padding-bottom: clamp(40px, 5vw, 76px);
}

@media (min-width: 980px) {
  .exmkhero-in {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    gap: clamp(40px, 6vw, 92px);
  }
}

.exmkhero .crumbs a,
.exmkhero .crumbs span {
  color: rgba(255, 255, 255, 0.6);
}

.exmkhero .crumbs a:hover,
.exmkhero .crumbs li:last-child span {
  color: var(--white);
}

.exmkhero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmkhero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--green-lt);
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.exmkhero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmkhero-h {
  margin-top: var(--s4);
  font-size: clamp(2.2rem, 1.2rem + 3.9vw, 4.2rem);
  font-weight: 600;
  line-height: 1.03;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 14ch;
}

.exmkhero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmkhero-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.78);
  max-width: 50ch;
}

.exmkhero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

.exmkhero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4) var(--s7);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}

.exmkhero-facts div {
  display: grid;
  gap: 2px;
}

.exmkhero-facts b {
  font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2rem);
  font-weight: 600;
  line-height: 1;
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

.exmkhero-facts span {
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.7);
}

/* ---- the badge --------------------------------------------------------- */
.exmbadge {
  position: relative;
  margin: 0 auto;
  padding-top: 104px;
  max-width: 392px;
}

/* The lanyard: two hairlines running off the top of the frame into a clip.
   The top of the run is masked away so it reads as continuing, not cut. */
.exmbadge-strap {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 258px;
  height: 112px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 60%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 60%);
  pointer-events: none;
}

.exmbadge-strap svg {
  display: block;
  width: 100%;
  height: 100%;
}

.exmbadge-strap path {
  fill: none;
  stroke: rgba(255, 255, 255, 0.5);
  stroke-width: 1;
}

.exmbadge-strap rect {
  fill: none;
  stroke: rgba(255, 255, 255, 0.7);
  stroke-width: 1;
}

/* The card. Hairline and white, no shadow, hung a degree and a half off true. */
.exmbadge-card {
  position: relative;
  background: var(--white);
  padding: 14px 14px 0;
  transform-origin: 50% -52px;
  transform: rotate(-1.5deg);
  animation: badge-sway 9s var(--ease-io) infinite alternate;
}

@keyframes badge-sway {
  from {
    transform: rotate(-2.2deg);
  }

  to {
    transform: rotate(-0.6deg);
  }
}

.exmbadge:hover .exmbadge-card,
.exmbadge:focus-within .exmbadge-card {
  animation-play-state: paused;
}

/* The punched slot the lanyard passes through. */
.exmbadge-slot {
  width: 64px;
  height: 8px;
  margin: 2px auto 12px;
  background: var(--light);
  box-shadow: inset 0 0 0 1px var(--rule);
}

.exmbadge-ph {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--light);
}

.exmbadge-ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmbadge-foot {
  display: grid;
  gap: 4px;
  padding: 14px 2px 16px;
}

.exmbadge-co {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--navy);
}

.exmbadge-ln {
  font-size: var(--fs-xs);
  color: var(--ink-2);
}

.exmbadge-ln a {
  color: var(--navy);
  font-weight: 500;
}

/* A code strip along the foot of the card - drawn, not an image. */
.exmbadge-code {
  height: 20px;
  margin-top: 10px;
  background-image: repeating-linear-gradient(90deg,
      var(--navy) 0 2px, transparent 2px 5px,
      var(--navy) 5px 6px, transparent 6px 11px,
      var(--navy) 11px 14px, transparent 14px 16px);
  opacity: 0.7;
}

.exmbadge-cap {
  margin-top: var(--s4);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .exmbadge-card {
    animation: none;
    transform: rotate(-1.5deg);
  }
}

/* --------------------------------------------------------------------------
   17.27 VACANCY INDEX - open vacancies (client-approved design C, 20 Aug
   2026). No panels: the two hiring employers are a key on the left and the
   vacancies a ruled index on the right, with the experience each role asks
   for set as the large figure that anchors its row.

   The key is also the control. Each employer is a tab; picking one shows
   that employer's vacancies and hides the other's. It is done with two
   radio inputs and sibling selectors, so it needs no script and works with
   JavaScript off - the first tab is checked in the markup.

   Every row's Apply link points at #apply, the application form further
   down the page. Where JavaScript is available it also pre-selects that
   vacancy in the form's Position field (see the careers block at the end
   of script.js); with JavaScript off the link still lands on the
   form and the applicant picks the vacancy themselves.
   -------------------------------------------------------------------------- */
.exmidx {
  position: relative;
  margin-top: var(--s7);
}

/* The radios themselves are never seen; the labels are the tabs. Kept in
   the flow (not display:none) so they stay focusable and operable by
   arrow key like any radio group. */
.exmidx-r {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.exmidx-grid {
  display: grid;
  gap: var(--s6);
}

@media (min-width: 900px) {
  .exmidx-grid {
    grid-template-columns: minmax(0, .74fr) minmax(0, 1.72fr);
    gap: var(--s8);
    align-items: start;
  }

  .exmidx-key {
    position: sticky;
    top: 96px;
  }
}

/* ---- the key, which is the tab list ---------------------------------- */
.exmidx-tab {
  display: block;
  position: relative;
  padding: var(--s4) var(--s4) var(--s4) var(--s5);
  border-top: 1px solid var(--rule);
  cursor: pointer;
  transition: background var(--t) var(--ease);
}

.exmidx-key>.exmidx-tab:first-of-type {
  border-top: 1px solid var(--ink);
}

/* The marker that fills in when the tab is current. */
.exmidx-tab::before {
  content: "";
  position: absolute;
  left: 0;
  top: -1px;
  bottom: 0;
  width: 2px;
  background: transparent;
  transition: background var(--t) var(--ease);
}

.exmidx-tab b {
  display: block;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink-2);
  transition: color var(--t) var(--ease);
}

.exmidx-tab span {
  display: block;
  margin-top: 3px;
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

.exmidx-tab:hover {
  background: var(--paper-3);
}

/* Current tab: green marker, navy name, tinted cell. */
#idx-luna:checked~.exmidx-grid .exmidx-tab-luna,
#idx-oneiro:checked~.exmidx-grid .exmidx-tab-oneiro {
  background: var(--paper-3);
}

#idx-luna:checked~.exmidx-grid .exmidx-tab-luna::before,
#idx-oneiro:checked~.exmidx-grid .exmidx-tab-oneiro::before {
  background: var(--green);
}

#idx-luna:checked~.exmidx-grid .exmidx-tab-luna b,
#idx-oneiro:checked~.exmidx-grid .exmidx-tab-oneiro b {
  color: var(--navy);
}

#idx-luna:focus-visible~.exmidx-grid .exmidx-tab-luna,
#idx-oneiro:focus-visible~.exmidx-grid .exmidx-tab-oneiro {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* ---- the index ------------------------------------------------------- */
.exmidx-p {
  display: none;
}

#idx-luna:checked~.exmidx-grid .exmidx-p-luna,
#idx-oneiro:checked~.exmidx-grid .exmidx-p-oneiro {
  display: block;
}

.exmidx-p li {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  padding: var(--s5) 0;
  border-top: 1px solid var(--rule);
}

.exmidx-p li:first-child {
  border-top: 1px solid var(--ink);
}

@media (min-width: 700px) {
  .exmidx-p li {
    grid-template-columns: minmax(0, 1fr) 128px 82px;
    gap: var(--s5);
    align-items: center;
  }
}

.exmidx-t {
  font-size: clamp(1.15rem, 1rem + .6vw, 1.4rem);
  font-weight: 600;
  line-height: 1.24;
  color: var(--navy);
}

.exmidx-m {
  margin-top: 4px;
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

.exmidx-x {
  font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  font-weight: 600;
  line-height: 1;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.exmidx-x small {
  margin-left: 5px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* The one vacancy the live site states no experience for. Said in words
   rather than drawn as an empty figure, so it cannot read as a rendering
   fault. */
.exmidx-x-na {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: normal;
}

.exmidx-a {
  justify-self: start;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--navy);
  transition: color var(--t) var(--ease);
}

@media (min-width: 700px) {
  .exmidx-a {
    justify-self: end;
  }
}

.exmidx-a::after {
  content: "";
  width: 16px;
  height: 1px;
  background: currentColor;
  transition: width var(--t) var(--ease);
}

.exmidx-a:hover,
.exmidx-a:focus-visible {
  color: var(--green);
}

.exmidx-a:hover::after {
  width: 26px;
}

.exmidx-note {
  margin-top: var(--s5);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmidx-note a {
  font-weight: 600;
  border-bottom: 1px solid var(--rule);
}

@media (prefers-reduced-motion: reduce) {

  .exmidx-tab,
  .exmidx-tab::before,
  .exmidx-tab b,
  .exmidx-a,
  .exmidx-a::after {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   17.28 APPLICATION FORM - the careers application. Statement column on the
   left, the form as one hairline panel on the right, fields two-up inside
   it: the layout the client approved.

   It is sized so the whole section sits on one screen without scrolling
   (client, 20 Aug 2026) - eight fields in five rows, a shorter band than a
   normal .section, and a tighter field rhythm than the home page form.
   Controls are still the home page .exmform / .exmfld grammar (section 14), so
   there is one field vocabulary across the site.

   The markup is written to be lifted straight into WordPress: every control
   carries a stable name= a WP handler (or a WPForms / CF7 field mapping) can
   read, the form is multipart so the CV upload works, and there is a hidden
   honeypot plus a slot for wp_nonce_field(). See the WORDPRESS block in the
   careers.html head comment.
   -------------------------------------------------------------------------- */
.section-apply {
  padding-block: clamp(40px, 4.2vw, 60px);
}

.exmappl-grid {
  display: grid;
  gap: var(--s6);
  margin-top: var(--s5);
}

@media (min-width: 900px) {
  .exmappl-grid {
    grid-template-columns: minmax(0, 0.66fr) minmax(0, 1.74fr);
    gap: var(--s7);
    align-items: start;
  }
}

.exmappl-side .h2 {
  margin-top: var(--s3);
}

.exmappl-side p {
  margin-top: var(--s4);
  max-width: 34ch;
  font-size: var(--fs-sm);
}

.exmappl-addr {
  display: inline-block;
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--navy);
}

/* The panel. */
.exmappl-form {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: var(--s5);
}

@media (min-width: 700px) {
  .exmappl-form {
    padding: var(--s5) var(--s6) var(--s6);
  }
}

.exmappl-row {
  display: grid;
  gap: 0 var(--s6);
}

@media (min-width: 620px) {
  .exmappl-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmfld-2 {
  grid-column: 1 / -1;
}

/* Tighter rhythm than the home page form - this one has to fit a screen. */
.exmappl-form .exmfld {
  margin-bottom: var(--s3);
}

/* One height for every control so the underlines in a row line up. */
.exmappl-form .exmfld input,
.exmappl-form .exmfld select {
  height: 40px;
  padding: 9px 0;
}

.exmappl-form .exmfld textarea {
  min-height: 46px;
  padding: 9px 0;
}

.exmappl-form .exmfld-file input[type="file"] {
  height: auto;
  padding: 7px 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* Required marker - navy, never green (green is barred from small text). */
.req {
  color: var(--navy);
  text-decoration: none;
  font-weight: 700;
}

.exmfld-file input[type="file"]::file-selector-button {
  margin-right: var(--s4);
  padding: 7px 14px;
  border: 1px solid var(--navy);
  background: transparent;
  color: var(--navy);
  font-family: inherit;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--t) var(--ease), color var(--t) var(--ease);
}

.exmfld-file input[type="file"]::file-selector-button:hover {
  background: var(--navy);
  color: var(--white);
}

/* Foot: consent on the left, the submit and its note on the right. */
.exmappl-foot {
  display: grid;
  gap: var(--s4) var(--s6);
  margin-top: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
}

@media (min-width: 760px) {
  .exmappl-foot {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }
}

.exmappl-consent {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: var(--s4);
  align-items: start;
  max-width: 56ch;
  font-size: var(--fs-xs);
  color: var(--ink-2);
}

.exmappl-consent input {
  width: 18px;
  height: 18px;
  margin-top: 1px;
  accent-color: var(--navy);
}

.exmappl-acts {
  display: grid;
  gap: 6px;
  justify-items: start;
}

@media (min-width: 760px) {
  .exmappl-acts {
    justify-items: end;
  }
}

.exmappl-acts .note {
  margin: 0;
}

/* Honeypot - off screen, never focusable, never announced. */
.exmappl-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Server messages, if the WordPress handler redirects back with a status. */
.exmappl-msg {
  margin-bottom: var(--s5);
  padding: var(--s4) var(--s5);
  border-left: 2px solid var(--green);
  background: var(--paper-3);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.exmappl-msg-err {
  border-left-color: var(--navy);
}


/* ==========================================================================
   17.29+  LIFE @ EXEMED  (gallery.html)
   The sixth component family. The live /home/gallery page is a heading and
   twenty-four photographs - no body copy at all - so the page is built as a
   photographic page and nothing else: the photographs open it, the
   photographs are the page, and any one of them opens full size.

   Nothing here repeats another page's hero. The product pages have the
   porthole, accreditations the dossier fan, clientele the ledger, careers
   the badge. This one is the frame: one photograph, full bleed.

   No counts, no chapter titles, no captions (client, 20 Aug 2026). The
   photographs carry the page on their own.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.29 SPLIT HERO - the Life @ Exemed hero (client picked design A of four,
   20 Aug 2026). Copy on the left over a navy field ruled with faint
   horizontal hairlines - the register of a contact sheet, and not the dot
   grid the product and clientele heroes use nor the vertical columns the
   careers hero uses. On the right one photograph runs off the right edge of
   the screen, and a second, smaller photograph overlaps its bottom corner.
   Both are live: each opens its own lightbox (17.31), so the page shows what
   it does before the reader has scrolled.

   Nothing moves. The only motion is the hover: the big photograph draws a
   green rule across its head, the small one lifts.

   Needs .exmmast-solid on the masthead.
   -------------------------------------------------------------------------- */
.exmghero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(28px, 3.4vw, 56px));
  /* Deep enough that the overlapping photograph clears the foot, no deeper. */
  padding-bottom: clamp(56px, 5.4vw, 80px);
}

/* Horizontal rule field, faded away to the right so it never runs under the
   photograph. */
.exmghero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: repeating-linear-gradient(180deg, rgba(255, 255, 255, 0.14) 0 1px, transparent 1px 84px);
  -webkit-mask-image: linear-gradient(100deg, #000 4%, rgba(0, 0, 0, 0.22) 44%, transparent 72%);
  mask-image: linear-gradient(100deg, #000 4%, rgba(0, 0, 0, 0.22) 44%, transparent 72%);
}

.exmghero-in {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-left: var(--gut);
  display: grid;
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}

@media (min-width: 980px) {
  .exmghero-in {
    grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  }
}

.exmghero .crumbs a,
.exmghero .crumbs span {
  color: rgba(255, 255, 255, 0.62);
}

.exmghero .crumbs a:hover,
.exmghero .crumbs li:last-child span {
  color: var(--white);
}

.exmghero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmghero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: var(--s6);
  color: var(--green-lt);
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.exmghero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmghero-h {
  margin-top: var(--s4);
  font-size: clamp(2.2rem, 1.1rem + 4vw, 4.1rem);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.022em;
  color: var(--white);
}

.exmghero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmghero-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.8);
  max-width: 42ch;
}

.exmghero-acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
}

/* ---- the two photographs ------------------------------------------------
   The figure is pulled out to the right edge of the viewport. 100vw counts
   the scrollbar, so it overshoots by a few pixels - .exmghero clips that, which
   is the only reason it is overflow:hidden.
   ------------------------------------------------------------------------- */
.exmghero-fig {
  position: relative;
  margin-right: calc(-1 * max(0px, (100vw - var(--wrap))) / 2);
}

.exmghero-main {
  position: relative;
  display: block;
  aspect-ratio: 5 / 4;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-right: 0;
  background: rgba(255, 255, 255, 0.05);
}

.exmghero-main img,
.exmghero-sub img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmghero-main img {
  transition: transform var(--t-slow) var(--ease);
}

.exmghero-main::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: 0;
  height: 2px;
  background: var(--green-lt);
  transition: width 420ms var(--ease);
}

.exmghero-main:hover img,
.exmghero-main:focus-visible img {
  transform: scale(1.03);
}

.exmghero-main:hover::after,
.exmghero-main:focus-visible::after {
  width: 100%;
}

.exmghero-sub {
  position: absolute;
  left: clamp(-58px, -4vw, -34px);
  bottom: -40px;
  z-index: 2;
  display: block;
  width: clamp(148px, 15vw, 214px);
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--navy);
  border: 1px solid rgba(255, 255, 255, 0.7);
  transition: transform var(--t) var(--ease), border-color var(--t) var(--ease);
}

.exmghero-sub:hover,
.exmghero-sub:focus-visible {
  transform: translateY(-9px);
  border-color: var(--white);
}

.exmghero-main:focus-visible,
.exmghero-sub:focus-visible {
  outline: 2px solid var(--green-lt);
  outline-offset: 3px;
}

@media (max-width: 979px) {
  .exmghero-in {
    padding-right: var(--gut);
  }

  .exmghero-fig {
    margin-right: 0;
  }

  .exmghero-main {
    border-right: 1px solid rgba(255, 255, 255, 0.24);
    aspect-ratio: 4 / 3;
  }

  /* No room to overlap beside the copy - the small photograph sits in the
     sheet below like every other one. */
  .exmghero-sub {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {

  .exmghero-main img,
  .exmghero-main::after,
  .exmghero-sub {
    transition: none;
  }

  .exmghero-main:hover img,
  .exmghero-main:focus-visible img,
  .exmghero-sub:hover,
  .exmghero-sub:focus-visible {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   17.30 CONTACT SHEET - the twenty-four photographs as one hairline mosaic.
   No headings, no counts, no captions: two photographs run at four times
   the area and two more at twice the width, and the rest at one, so the
   sheet has a rhythm rather than being a uniform grid. Every cell is a link
   into the lightbox (17.31); on hover the photograph lifts a little under a
   navy veil with an open cue.

   The order of the cells is what makes the mosaic tile exactly - it runs in
   six bands, each of which consumes the four columns whole, so plain
   auto-placement fills it with no holes and no explicit coordinates.
   -------------------------------------------------------------------------- */
.exmframes {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: clamp(96px, 8.6vw, 118px);
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

.exmfr {
  position: relative;
  display: block;
  grid-row: span 2;
  overflow: hidden;
  background: var(--light);
  color: inherit;
}

.exmfr-lead {
  grid-column: span 2;
  grid-row: span 4;
}

.exmfr-wide {
  grid-column: span 2;
  grid-row: span 2;
}

.exmfr img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease);
}

/* The navy veil. At zero opacity until the cell is hovered or focused, so
   the sheet itself stays photographic. */
.exmfr::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(22, 51, 100, 0.86) 0%, rgba(22, 51, 100, 0.3) 48%, rgba(22, 51, 100, 0) 80%);
  opacity: 0;
  transition: opacity var(--t) var(--ease);
}

/* The green rule draws across the head of the cell on hover. */
.exmfr::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  width: 0;
  height: 2px;
  background: var(--green-lt);
  transition: width 420ms var(--ease);
}

.exmfr-go {
  position: absolute;
  left: 14px;
  bottom: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--white);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease);
}

/* The open cue: a hairline square with a plus, drawn rather than iconed. */
.exmfr-go::before {
  content: "";
  width: 22px;
  height: 22px;
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.7);
  background-image:
    linear-gradient(to right, var(--white) 0 100%),
    linear-gradient(to bottom, var(--white) 0 100%);
  background-size: 9px 1px, 1px 9px;
  background-position: center, center;
  background-repeat: no-repeat;
}

.exmfr:hover img,
.exmfr:focus-visible img {
  transform: scale(1.045);
}

.exmfr:hover::after,
.exmfr:focus-visible::after {
  opacity: 1;
}

.exmfr:hover::before,
.exmfr:focus-visible::before {
  width: 100%;
}

.exmfr:hover .exmfr-go,
.exmfr:focus-visible .exmfr-go {
  opacity: 1;
  transform: none;
}

.exmfr:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: -3px;
}

@media (max-width: 979px) {
  .exmframes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: clamp(88px, 12vw, 132px);
  }
}

@media (max-width: 560px) {
  .exmframes {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
  }

  .exmfr,
  .exmfr-lead,
  .exmfr-wide {
    grid-column: span 1;
    grid-row: auto;
  }

  .exmfr {
    aspect-ratio: 4 / 3;
  }

  .exmfr-wide {
    aspect-ratio: 16 / 9;
  }

}

/* Touch has no hover, so the cue stays visible - but the veil does not, or
   every photograph on the sheet would sit under navy. */
@media (hover: none) {
  .exmfr-go {
    opacity: 1;
    transform: none;
    text-shadow: 0 1px 14px rgba(22, 51, 100, 0.9);
  }
}

@media (prefers-reduced-motion: reduce) {

  .exmfr img,
  .exmfr::before,
  .exmfr-go {
    transition: none;
  }

  .exmfr:hover img,
  .exmfr:focus-visible img {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   17.31 LIGHTBOX - selecting a photograph opens it full size. Built on
   :target, so it is pure CSS: the cell is an <a> pointing at the overlay id,
   the overlay close link points back at the cell own id, and the two arrows
   point at the neighbouring overlays. It therefore works with JavaScript
   off, is operable from the keyboard as ordinary links, and leaves the
   reader exactly where they were when they close it. The script adds
   Escape and the arrow keys on top of that, nothing more.
   -------------------------------------------------------------------------- */
.exmlbox {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: grid;
  place-items: center;
  padding: clamp(52px, 7vh, 84px) clamp(14px, 5vw, 76px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 240ms var(--ease), visibility 0s linear 240ms;
}

.exmlbox:target {
  opacity: 1;
  visibility: visible;
  transition: opacity 240ms var(--ease), visibility 0s;
}

.exmlbox-scrim {
  position: absolute;
  inset: 0;
  background: rgba(22, 51, 100, 0.975);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

.exmlbox-fig {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--s4);
  max-width: min(1180px, 100%);
  transform: translateY(10px);
  transition: transform 320ms var(--ease);
}

.exmlbox:target .exmlbox-fig {
  transform: none;
}

.exmlbox-img {
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: rgba(255, 255, 255, 0.04);
}

.exmlbox-img img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: calc(100vh - clamp(150px, 22vh, 230px));
  margin-inline: auto;
}

.exmlbox-bar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s5);
  padding-top: var(--s3);
  border-top: 1px solid rgba(255, 255, 255, 0.2);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.68);
}

.exmlbox-no {
  color: var(--green-lt);
  font-variant-numeric: tabular-nums;
}

/* Close, top right of the viewport. */
.exmlbox-x {
  position: absolute;
  top: clamp(14px, 2.6vh, 26px);
  right: clamp(14px, 3vw, 40px);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border: 1px solid rgba(255, 255, 255, 0.34);
  color: var(--white);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease);
}

.exmlbox-x::after {
  content: "";
  width: 13px;
  height: 13px;
  background-image:
    linear-gradient(to right, var(--white) 0 100%),
    linear-gradient(to bottom, var(--white) 0 100%);
  background-size: 13px 1px, 1px 13px;
  background-position: center, center;
  background-repeat: no-repeat;
  transform: rotate(45deg);
}

.exmlbox-x:hover,
.exmlbox-x:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--white);
  color: var(--white);
}

/* Previous / next. Hairline squares at the edges of the viewport. */
.exmlbox-nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: clamp(42px, 4vw, 54px);
  height: clamp(42px, 4vw, 54px);
  margin-top: -27px;
  border: 1px solid rgba(255, 255, 255, 0.34);
  color: var(--white);
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease);
}

.exmlbox-nav::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 11px;
  height: 11px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
}

.exmlbox-nav-prev {
  left: clamp(8px, 1.6vw, 22px);
}

.exmlbox-nav-next {
  right: clamp(8px, 1.6vw, 22px);
}

.exmlbox-nav-prev::before {
  transform: translate(-35%, -50%) rotate(-135deg);
}

.exmlbox-nav-next::before {
  transform: translate(-65%, -50%) rotate(45deg);
}

.exmlbox-nav:hover,
.exmlbox-nav:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--white);
  color: var(--white);
}

@media (max-width: 560px) {
  .exmlbox-nav {
    top: auto;
    bottom: 14px;
    margin-top: 0;
  }

  .exmlbox-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s2);
  }
}

@media (prefers-reduced-motion: reduce) {

  .exmlbox,
  .exmlbox-fig {
    transition: none;
  }

  .exmlbox-fig {
    transform: none;
  }
}



/* ==========================================================================
   17.32+  SUPPLIERS  (suppliers.html)

   Seventh component family. The live /home/suppliers page is a heading, one
   sub-heading, one paragraph, one note and one button that leaves the site
   for the eSupplier registration tool. That is the whole page, so the page
   is built around that one action and carries nothing else.

   NO PHOTOGRAPHS ON THIS PAGE (client, 20 Aug 2026). Four photographic hero
   designs were built and shown - the gate (three photographs as the leaves
   of a gate), the quad, the column and the plate - and the client rejected
   all four along with the twelve-photograph field that ran below them. None
   of those are in this stylesheet; do not rebuild them. Four image-free
   designs were then shown as an artifact - the mark, the register plate, the
   lattice and a light band carrying the client's own old-site artwork.

   17.32 .exmshero  MARK HERO - navy full-bleed over a faint DIAGONAL HATCH.
                 The hatch is what separates this hero from every other one
                 on the site: the product and clientele heroes use a dot
                 grid, the gallery hero horizontal rules, the careers hero
                 vertical columns. The heading only on the left - no lede and
                 no button, both by the client's instruction; on the right the
                 Exemed wordmark inside three arcs struck from the swoosh
                 beneath it. It loads one 35 KB PNG and nothing else. Needs
                 .exmmast-solid on the masthead.
   17.36 .exmbuy    WHAT WE BUY - the procurement requirements as cells of one
                 hairline grid. Runs LAST on the page and carries NO buttons
                 (client, 20 Aug 2026): the one registration button lives in
                 17.37 above it.
   17.37 .exmbrief  THE BRIEF - the two paragraphs and the single Supplier
                 Registration button, set plain. This replaced the registration
                 dock, which the client asked to be removed in favour of
                 "simple write first, paragraph, then button".

   REMOVED FROM THIS STYLESHEET, do not rebuild: 17.33 the offset photograph
   field, 17.34 .dock the registration dock (navy panel with the note beside
   the button), 17.35 .cta--hatch. All three were built, shown and dropped by
   the client on 20 Aug 2026.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   17.32 MARK HERO
   -------------------------------------------------------------------------- */
.exmshero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(28px, 3.4vw, 56px));
  padding-bottom: clamp(56px, 5.4vw, 84px);
}

/* The hatch. Faded off to the right so it never runs under the mark. */
.exmshero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.10) 0 1px, transparent 1px 15px);
  -webkit-mask-image: linear-gradient(105deg, #000 2%, rgba(0, 0, 0, 0.26) 46%, transparent 74%);
  mask-image: linear-gradient(105deg, #000 2%, rgba(0, 0, 0, 0.26) 46%, transparent 74%);
}

.exmshero-in {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
  display: grid;
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}

@media (min-width: 980px) {
  .exmshero-in {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

.exmshero .crumbs a,
.exmshero .crumbs span {
  color: rgba(255, 255, 255, 0.62);
}

.exmshero .crumbs a:hover,
.exmshero .crumbs li:last-child span {
  color: var(--white);
}

.exmshero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmshero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: var(--s6);
  color: var(--green-lt);
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.exmshero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmshero-h {
  margin-top: var(--s4);
  font-size: clamp(2.05rem, 1.05rem + 3.6vw, 3.6rem);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.022em;
  color: var(--white);
}

.exmshero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

/* ---- the mark -----------------------------------------------------------
   Three arcs struck from the swoosh under the wordmark, at three weights and
   three colours, with the wordmark itself reversed to white at the centre.
   The arcs run off the right edge of the hero, which is what stops it
   reading as a badge. Decorative: aria-hidden, and the wordmark carries the
   alt text.                                                                */
.exmmark {
  position: relative;
  height: clamp(300px, 32vw, 430px);
}

.exmmark-ring {
  position: absolute;
  border-radius: 50%;
  border: 2px solid var(--green-40);
  border-right-color: transparent;
  border-bottom-color: transparent;
  transform: rotate(38deg);
}

.exmmark-ring-1 {
  inset: -34px -170px -34px 34px;
  border-color: rgba(255, 255, 255, 0.42);
  border-right-color: transparent;
  border-bottom-color: transparent;
}

.exmmark-ring-2 {
  inset: 28px -104px 28px 104px;
  border-width: 1px;
  border-color: rgba(255, 255, 255, 0.28);
  border-right-color: transparent;
  border-bottom-color: transparent;
}

.exmmark-ring-3 {
  inset: 90px -42px 90px 166px;
  border-width: 3px;
  border-color: var(--green);
  border-right-color: transparent;
  border-bottom-color: transparent;
}

/* The wordmark reversed to white and set straight on the navy, inside the
   arcs - the hero as the client approved it (design G, 20 Aug 2026). A white
   plate was tried behind the logo so the green swoosh would show in its own
   colour; the client asked for the previous design back, so the plate is gone
   and is not in this stylesheet. The proportion is the artwork's own, 464x180. */
.exmmark-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(58%, 300px);
  height: auto;
  filter: brightness(0) invert(1);
  opacity: 0.94;
}

/* Under 980px the mark sits BELOW the copy, so the arcs may not reach up over
   the buttons: every inset is kept at or inside the top and bottom edges of
   .exmmark. They still run off the right, which the hero clips. */
@media (max-width: 979px) {
  .exmmark {
    height: clamp(230px, 46vw, 320px);
  }

  .exmmark-ring-1 {
    inset: 0 -90px 0 10px;
  }

  .exmmark-ring-2 {
    inset: 24px -52px 24px 62px;
  }

  .exmmark-ring-3 {
    inset: 56px -20px 56px 106px;
  }
}

@media (max-width: 560px) {
  .exmmark-ring-3 {
    inset: 44px -14px 44px 76px;
  }
}

/* --------------------------------------------------------------------------
   17.36 WHAT WE BUY - the procurement requirements. Client supplied the copy
   on 20 Aug 2026; this is what the Suppliers page is actually for.

   Pattern per ui-ux-pro-max (--domain landing / product, 20 Aug 2026): B2B
   Service reads as "Trust & Authority + Minimal" - navy and grey carry it,
   the accent is spent on the call to action only, and the section order runs
   hero -> overview -> clear CTA path. So each requirement is a cell in one
   hairline grid, its stated figures pulled out as chips so a supplier can
   scan them without reading the paragraph, and each cell ends in its own
   route to the registration tool rather than making the reader hunt for one.

   The chips are the client's OWN figures, lifted word for word out of the
   paragraph below them - "24 Inch x 36 Inch", "7000 per month approx". No
   figure is derived, rounded or converted.

   Green appears once per cell, as the rule that draws across its head on
   hover. Under reduced motion it does not draw.
   -------------------------------------------------------------------------- */
.exmbuy {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 900px) {
  .exmbuy {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmbuy-c {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  padding: clamp(28px, 3.2vw, 52px);
  background: var(--paper);
}

.exmbuy-c::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease);
}

.exmbuy-c:hover::after,
.exmbuy-c:focus-within::after {
  transform: scaleX(1);
}

.exmbuy-n {
  font-size: clamp(1.45rem, 1.1rem + 1.3vw, 2.05rem);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--navy);
}

.exmbuy-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.exmbuy-chips li {
  padding: 7px 12px;
  border: 1px solid var(--rule);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--navy);
  white-space: nowrap;
}

.exmbuy-t {
  font-size: var(--fs-body);
  line-height: 1.62;
  color: var(--ink-2);
  max-width: 46ch;
}

/* The action sits on the floor of the cell, so both cells line up however
   long their paragraphs run. */
.exmbuy-c .btn {
  align-self: flex-start;
  margin-top: auto;
}

@media (prefers-reduced-motion: reduce) {
  .exmbuy-c::after {
    transition: none;
  }

  .exmbuy-c:hover::after {
    transform: scaleX(0);
  }
}


/* --------------------------------------------------------------------------
   17.37 THE BRIEF - the second section: both of the client's paragraphs, then
   the one button on the page.

   This replaced the registration dock (17.34, removed). The client's
   instruction on 20 Aug 2026 was "simple write first set paragraph and button
   add button" - so there is no panel, no navy cell and no ornament here. Just
   a measured column of text and the action under it, which is also the
   plainest thing to hand to WordPress.

   The whole block is CENTRED (client, 20 Aug 2026) in a 74ch column, so the
   two paragraphs and the button sit on one axis down the middle of the page.

   The second paragraph is the live page's NOTE. It is set a step down from the
   first and marked with a short green rule above it, because it is procedural
   rather than descriptive - it is the line that tells a supplier not to email
   - and a reader needs to see that it is a different kind of sentence.
   Nothing about its wording changes.
   -------------------------------------------------------------------------- */
.exmbrief {
  max-width: 74ch;
  margin-inline: auto;
  text-align: center;
}

.exmbrief-t {
  font-size: var(--fs-lede);
  line-height: 1.62;
  color: var(--ink);
}

/* Centred, the note cannot hang off a rule on its left - the rule would sit
   away from the text and read as a stray mark. It takes a short green rule
   centred above it instead, which says the same thing: this sentence is a
   different kind of sentence. */
.exmbrief-note {
  position: relative;
  margin-top: var(--s7);
  padding-top: var(--s5);
  font-size: var(--fs-body);
  line-height: 1.62;
  color: var(--ink-2);
}

.exmbrief-note::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 48px;
  height: 3px;
  background: var(--green);
}

.exmbrief-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s4);
  margin-top: var(--s7);
}

.exmbrief-meta {
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

@media (max-width: 560px) {
  .exmbrief-acts .btn {
    width: 100%;
    justify-content: center;
  }
}


/* ==========================================================================
   17.38+  CONTACT US  (contact-us.html)
   --------------------------------------------------------------------------
   Eighth component family. Three new blocks, plus the shared application form
   (17.28), which the build spec asks this page to reuse rather than redesign.

   17.38 .exmnhero   LOCATOR HERO - navy full-bleed over a faint field of
                  CONCENTRIC RINGS. The four navy grounds already in use are
                  taken: the dot grid (products, clientele), vertical ruled
                  columns (careers), horizontal hairlines (gallery) and the
                  diagonal hatch (suppliers). Rings are the fifth, and they
                  are the right figure for this page - they read as a locator
                  struck around the place the photograph shows. Copy on the
                  left with the two live e-mail routes; on the right the
                  photograph in a hairline frame with the corporate address on
                  a white plate over its bottom left corner. Nothing moves.
                  Needs .exmmast-solid.
   17.39 .exmrooms   THE ADDRESSES - the corporate office and the two plants as
                  cells of one hairline grid: number, name, address, and the
                  route out of the cell. Static - the client rejected hover on
                  the equivalent row (.exmstrow), so there is none here.
   17.40 .exmlocate  THE MAP - the one map on this site. Global presence is still
                  stated as text (.exmreach, 17.7) and that is not reopened here;
                  this is a single street location for a visitor who has to
                  arrive at a gate, which is a different job. The three
                  addresses are the key on the left AND the control: each is a
                  tab, built the way the careers vacancy index (17.27) is -
                  radio inputs plus sibling selectors, so there is no script,
                  it works with JavaScript off, and it is an ordinary
                  keyboard-operable radio group. Every pane also carries a
                  plain link out to the map, so the page still works where a
                  third-party frame is blocked.
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.38 LOCATOR HERO
   -------------------------------------------------------------------------- */
.exmnhero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--navy);
  color: var(--white);
  padding-top: calc(var(--head-h) + clamp(28px, 3.4vw, 56px));
  padding-bottom: clamp(56px, 5.4vw, 88px);
}

/* The rings. Struck from a point behind the photograph and faded off to the
   left so they never run under the copy. */
.exmnhero::before {
  content: "";
  position: absolute;
  inset: -30% -10%;
  z-index: -1;
  background-image: repeating-radial-gradient(circle at 74% 50%,
      rgba(255, 255, 255, 0.13) 0 1px,
      transparent 1px 38px);
  -webkit-mask-image: linear-gradient(255deg, #000 6%, rgba(0, 0, 0, 0.30) 52%, transparent 82%);
  mask-image: linear-gradient(255deg, #000 6%, rgba(0, 0, 0, 0.30) 52%, transparent 82%);
}

.exmnhero-in {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
  display: grid;
  gap: clamp(40px, 4.4vw, 64px);
  align-items: center;
}

@media (min-width: 980px) {
  .exmnhero-in {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr);
  }
}

.exmnhero .crumbs a,
.exmnhero .crumbs span {
  color: rgba(255, 255, 255, 0.62);
}

.exmnhero .crumbs a:hover,
.exmnhero .crumbs li:last-child span {
  color: var(--white);
}

.exmnhero .crumbs li+li::before {
  color: rgba(255, 255, 255, 0.35);
}

.exmnhero-k {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: var(--s6);
  color: var(--green-lt);
  font-weight: 700;
  font-size: var(--fs-label);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.exmnhero-k::before {
  content: "";
  width: 28px;
  height: 1px;
  background: var(--green-lt);
}

.exmnhero-h {
  margin-top: var(--s4);
  font-size: clamp(2.05rem, 1.05rem + 3.6vw, 3.6rem);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.022em;
  color: var(--white);
}

.exmnhero-h .hl {
  color: var(--green-lt);
  font-weight: 400;
}

.exmnhero-lede {
  margin-top: var(--s5);
  font-size: var(--fs-lede);
  color: rgba(255, 255, 255, 0.8);
  max-width: 44ch;
}

/* The two live e-mail routes, as a two-cell hairline register on the navy. */
.exmnhero-routes {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.18);
  max-width: 540px;
}

@media (min-width: 560px) {
  .exmnhero-routes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.exmnhero-routes li {
  background: var(--navy);
  padding: var(--s4) var(--s5) var(--s5);
}

.exmnhero-routes .mono {
  color: rgba(255, 255, 255, 0.6);
}

.exmnhero-routes a {
  display: inline-block;
  margin-top: var(--s2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--white);
  text-decoration: none;
  border-bottom: 1px solid var(--green-40);
  padding-bottom: 2px;
  transition: color var(--t) var(--ease);
}

.exmnhero-routes a:hover {
  color: var(--green-lt);
}

/* ---- the photograph and its address plate ------------------------------ */
.exmnhero-fig {
  position: relative;
  margin: 0;
}

.exmnhero-frame {
  border: 1px solid rgba(255, 255, 255, 0.24);
  padding: 8px;
  overflow: hidden;
}

.exmnhero-frame img {
  display: block;
  width: 100%;
  height: clamp(260px, 30vw, 420px);
  object-fit: cover;
}

/* White plate over the bottom left corner, carrying the corporate address.
   It is the one place in the hero where type sits on white, so the address a
   visitor has to copy down reads at body size rather than reversed out. */
.exmnhero-plate {
  background: var(--white);
  color: var(--ink);
  padding: var(--s5);
  border-left: 3px solid var(--green);
  max-width: 340px;
}

@media (min-width: 720px) {
  .exmnhero {
    padding-bottom: clamp(80px, 7vw, 116px);
  }

  .exmnhero-plate {
    position: absolute;
    left: -1px;
    bottom: -28px;
    margin: 0;
  }
}

@media (max-width: 719px) {
  .exmnhero-plate {
    margin-top: -1px;
    max-width: none;
  }
}

.exmnhero-plate .mono {
  color: var(--ink-3);
}

.exmnhero-plate address {
  margin-top: var(--s3);
  font-style: normal;
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   17.39 THE ADDRESSES - the corporate office and the two plants as cells of
   one hairline grid. Static: no hover, no motion. Each cell ends on its own
   route out, and the routes line up across all three however long an address
   runs.
   -------------------------------------------------------------------------- */
.exmrooms {
  display: grid;
  gap: 1px;
  margin-top: var(--s7);
  background: var(--rule);
  border: 1px solid var(--rule);
}

@media (min-width: 760px) {
  .exmrooms {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.exmroom {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  padding: var(--s6) var(--s5) var(--s5);
}

.exmroom-n {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--green);
}

.exmroom-t {
  margin-top: var(--s4);
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--navy);
}

.exmroom-a {
  margin-top: var(--s4);
  font-style: normal;
  font-size: var(--fs-sm);
  line-height: 1.62;
  color: var(--ink-2);
}

.exmroom-spec {
  margin-top: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

.exmroom-go {
  margin-top: auto;
  padding-top: var(--s5);
}

/* --------------------------------------------------------------------------
   17.40 THE MAP - one street location at a time. The key on the left is the
   control: three radios and sibling selectors, exactly as the careers index
   (17.27) does it, so the block needs no script and stays keyboard-operable.
   Each pane carries a plain link out to the map as well as the embed, so the
   address is still reachable where a third-party frame is blocked.
   -------------------------------------------------------------------------- */
.exmlocate {
  position: relative;
  margin-top: var(--s7);
  border: 1px solid var(--rule);
}

/* Never seen; the labels are the tabs. Kept in the flow so they remain
   focusable and arrow-key operable like any radio group. */
.exmlocate-r {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.exmlocate-in {
  display: grid;
  gap: 1px;
  background: var(--rule);
}

@media (min-width: 900px) {
  .exmlocate-in {
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.68fr);
  }
}

.exmlocate-key {
  background: var(--paper);
  display: grid;
  align-content: start;
}

.exmlocate-tab {
  position: relative;
  display: block;
  padding: var(--s5) var(--s5) var(--s5) var(--s6);
  border-top: 1px solid var(--rule);
  cursor: pointer;
  transition: background var(--t) var(--ease);
}

.exmlocate-key>.exmlocate-tab:first-of-type {
  border-top: 0;
}

.exmlocate-tab::before {
  content: "";
  position: absolute;
  left: 0;
  top: -1px;
  bottom: 0;
  width: 2px;
  background: transparent;
  transition: background var(--t) var(--ease);
}

.exmlocate-tab b {
  display: block;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink-2);
  transition: color var(--t) var(--ease);
}

.exmlocate-tab span {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--ink-3);
}

.exmlocate-tab:hover {
  background: var(--paper-3);
}

#loc-hq:checked~.exmlocate-in .exmlocate-tab-hq,
#loc-luna:checked~.exmlocate-in .exmlocate-tab-luna,
#loc-vapi:checked~.exmlocate-in .exmlocate-tab-vapi {
  background: var(--paper-3);
}

#loc-hq:checked~.exmlocate-in .exmlocate-tab-hq::before,
#loc-luna:checked~.exmlocate-in .exmlocate-tab-luna::before,
#loc-vapi:checked~.exmlocate-in .exmlocate-tab-vapi::before {
  background: var(--green);
}

#loc-hq:checked~.exmlocate-in .exmlocate-tab-hq b,
#loc-luna:checked~.exmlocate-in .exmlocate-tab-luna b,
#loc-vapi:checked~.exmlocate-in .exmlocate-tab-vapi b {
  color: var(--navy);
}

#loc-hq:focus-visible~.exmlocate-in .exmlocate-tab-hq,
#loc-luna:focus-visible~.exmlocate-in .exmlocate-tab-luna,
#loc-vapi:focus-visible~.exmlocate-in .exmlocate-tab-vapi {
  outline: 2px solid var(--navy);
  outline-offset: -2px;
}

/* ---- the panes --------------------------------------------------------- */
.exmlocate-map {
  position: relative;
  background: var(--paper);
}

.exmlocate-pane {
  display: none;
}

#loc-hq:checked~.exmlocate-in .exmlocate-pane-hq,
#loc-luna:checked~.exmlocate-in .exmlocate-pane-luna,
#loc-vapi:checked~.exmlocate-in .exmlocate-pane-vapi {
  display: block;
}

.exmlocate-frame {
  display: block;
  width: 100%;
  height: clamp(320px, 38vw, 480px);
  border: 0;
  /* The tinted band behind the frame keeps the block from flashing white
     while the embed loads, and is what shows if it never does. */
  background: var(--paper-3);
}

.exmlocate-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3) var(--s5);
  padding: var(--s4) var(--s5);
  border-top: 1px solid var(--rule);
}

.exmlocate-bar address {
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* ==========================================================================
   17.41+  BLOG  (blogs.html, blog-detail.html)
   --------------------------------------------------------------------------
   Ninth component family. The first build of these two pages used the shared
   white hero (17.1) over the text-only card grid from CSS 13, with the
   two-column register (17.11) on the article. Correct reuse of the kit, and
   it read badly: a headline over three grey text boxes. A blog is the one
   place on this site where the PHOTOGRAPH is the entry point, .exmposts has
   no image slot at all, and the 24 real plant photographs downloaded for
   Life @ Exemed were sitting unused.

   THE LISTING FOLLOWS A REFERENCE THE CLIENT SUPPLIED
   ---------------------------------------------------
   tunatheme.com/tf/html/vicodin-preview/vicodin/blog-grid.html, given as
   "this type". Taken from it: page banner with breadcrumb and heading, a
   three-column grid with no sidebar, and pagination. Card order: featured
   image, title, standfirst, date, Read more.

   Dropped from it at the client's instruction: the "by: Admin / Services"
   meta line above the title. The title sits direct under the photograph.
   That also removes the two slots this site had nothing true to put in - no
   author is published anywhere on exemedpharma.com, and the categories were
   furniture.

   The one slot left with no Exemed content is the DATE, and process.md 2.1
   bars inventing one. It is built and sits in the markup with its WordPress
   call in a comment beside it; `.exmcard-date:empty` collapses it so the foot
   row carries no hole until real dates arrive.

   What is NOT taken is the reference's skin. That template is rounded
   corners, drop shadows, an orange accent and two display families; this site
   is hairlines, square corners, Navy leading, Green accenting and Inter alone
   (process.md 3).

   THE ARTICLE
   -----------
   The cover (17.44) is APPROVED - client, 26 Aug 2026: "the detail page hero
   section is proper, do not change". Everything below it was then stripped
   back on the client's instruction, in their words: remove the "In this note"
   section, do not use the "In short" panel, show the steps as a simple
   numbered list, do not use a blockquote, keep the images at a sensible size
   and carry no captions.

   So the article is the cover, then ONE column at ONE measure running
   straight down: prose, one image, the numbered list, prose, close. There is
   no sub-navigation, no reading-progress rail, no summary panel, no
   pull-quote and no figcaption anywhere on the page.

   /ui-ux-pro-max was run first for the structural pattern (process.md 8). Its
   UX rules are honoured - a 65-75ch reading measure, sequential h1/h2/h3,
   descriptive alt text, aspect-ratio reserved on every image so CLS stays
   flat, lazy loading below the fold, hover transitions inside 150-300ms, 48px
   pagination targets, prefers-reduced-motion respected. Its palette
   (editorial black plus accent pink #EC4899), its fonts (Libre Bodoni /
   Public Sans), its drop caps and its newsletter sign-up block are rejected:
   the brand guideline names Navy, Green and Inter, and the Suppliers page
   already settled that this site does not add forms.

   THE BLOCKS
   ----------
   17.41 .exmjhero  LISTING HERO - the index banner. A photograph with a Navy
                  scrim carrying the eyebrow, the H1, the lede and a hairline
                  of facts. It is NOT 17.44: an article cover states one title
                  and gets out of the way, but a listing has to say what the
                  whole section is before a reader will start down a grid of
                  posts. Same photographic treatment so the pair still matches;
                  different job, so different copy.
   17.42 .exmgrid
         .exmcard   THE GRID - photograph, title direct, standfirst, date slot,
                  Read more. auto-fit, so the row fills at two posts or at
                  thirty. The whole card is the link, not just the title: a
                  380px target beats a six-word one, and it puts the standfirst
                  inside the link's accessible name. No <span> anywhere in it -
                  the card is <figure>, <div>, <h3>, <p> and <b>, which is
                  valid inside an <a> and is what the markup means.
   17.43 .exmpage   PAGINATION - numbered cells with previous / next arrows.
                  48px cells, so every target clears the 44px minimum.
   17.44 .exmacov   ARTICLE COVER - a photograph full width, with the category
                  and the H1 reversed out of a Navy scrim. The title and
                  nothing else. APPROVED; do not redesign.
   17.45 .exmread   THE READ - one column, one 72ch measure, top to bottom.
                  Carries .exmread-fig (an image at the measure and no wider,
                  no caption) and .exmsteps (the sequence as a plain <ul> of
                  points, number typed by hand into .exmsteps-no).

   Motion is one thing: the card photograph scales slowly on hover. It is
   dropped under prefers-reduced-motion. Both pages work with JavaScript off;
   the only script hook is the shared [data-reveal].
   ========================================================================== */

/* --------------------------------------------------------------------------
   17.41 LISTING HERO — the index banner

   The article cover (17.44) states one title and gets out of the way, which is
   right for a post and wrong for an index: a reader landing on /blogs has to
   be told what the whole section is before they will start down a grid of
   posts. So this takes the SAME photographic treatment - photograph, Navy
   scrim, white type - and carries the eyebrow, the H1, the lede and a hairline
   of facts on it.

   min-height rather than aspect-ratio. The copy is the tall thing here, and an
   aspect box would either clip it on a phone or leave a metre of empty
   photograph on a desktop; a minimum lets the banner grow to whatever the copy
   needs and no further.
   -------------------------------------------------------------------------- */
.exmjhero {
  background: var(--paper);
  padding-top: calc(var(--head-h) + clamp(24px, 3vw, 44px));
  padding-bottom: clamp(28px, 4vw, 52px);
}

.exmjhero-shot {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  margin-top: var(--s5);
  min-height: clamp(420px, 42vw, 600px);
  background: var(--navy);
}

.exmjhero-shot>img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Navy at 94% falling to nothing - white on Navy is 9.35:1, so every line
   clears AA over any photograph in the set, and the banner stays inside the
   five brand colours rather than introducing a sixth grey. The scrim is
   deeper than 17.44's because there is more copy standing on it. */
.exmjhero-shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top,
      rgba(31, 69, 133, 0.95) 0%,
      rgba(31, 69, 133, 0.9) 38%,
      rgba(31, 69, 133, 0.52) 68%,
      rgba(31, 69, 133, 0.1) 88%,
      rgba(31, 69, 133, 0) 100%);
}

.exmjhero-copy {
  position: relative;
  z-index: 2;
  width: 100%;
  padding: clamp(24px, 3.5vw, 56px);
}

.exmjhero-k {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--green-lt);
}

.exmjhero-k .ic {
  width: 17px;
  height: 17px;
  color: var(--green-lt);
}

.exmjhero-h {
  margin-top: var(--s4);
  font-size: clamp(1.8rem, 1.05rem + 2.9vw, 3.25rem);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 18ch;
}

.exmjhero-lede {
  margin-top: var(--s5);
  color: rgba(255, 255, 255, 0.85);
  max-width: 52ch;
}

/* The facts, on one hairline under the lede. Two cells side by side from
   620px, stacked below it - a definition list, because that is what they
   are. */
.exmjhero-meta {
  display: grid;
  gap: var(--s4) clamp(32px, 5vw, 72px);
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, 0.28);
}

@media (min-width: 620px) {
  .exmjhero-meta {
    grid-auto-flow: column;
    justify-content: start;
  }
}

.exmjhero-meta div {
  display: grid;
  gap: 3px;
}

.exmjhero-meta dt {
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.66);
}

.exmjhero-meta dd {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--white);
}

/* --------------------------------------------------------------------------
   17.42 THE GRID
   -------------------------------------------------------------------------- */
.exmgrid {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  margin-top: var(--s7);
  /* auto-fit rather than repeat(3): three across inside a 1340px wrap, and
     the row still fills at two posts or at thirty. 320px is the floor. */
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

@media (max-width: 439px) {
  .exmgrid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* flex on the item and flex:1 on the link, rather than height:100% on the
   link. The card has to fill the row whatever the tallest standfirst does,
   and a percentage height needs a definite one to resolve against. */
.exmcard {
  display: flex;
  background: var(--paper);
}

.exmcard-link {
  display: flex;
  flex-direction: column;
  flex: 1;
  color: inherit;
  transition: background var(--t) var(--ease);
}

.exmcard-link:hover {
  background: var(--paper-3);
  color: inherit;
}

.exmcard-fig {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--paper-3);
  aspect-ratio: 3 / 2;
}

.exmcard-fig img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 900ms var(--ease);
}

.exmcard-link:hover .exmcard-fig img {
  transform: scale(1.05);
}

.exmcard-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--s6) var(--s5);
}

/* NO META LINE. The reference card opens with "by: Admin" and a category
   above the title; the client asked for the title direct, and both of those
   slots were the ones with nothing true to put in them anyway. */
.exmcard-t {
  margin: 0 0 var(--s3);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.26;
  letter-spacing: -0.01em;
  color: var(--navy);
  transition: color var(--t) var(--ease);
}

/* Not green on hover: at 20px/600 this is not large text by WCAG, and the
   brand guideline keeps green off anything that is not. */
.exmcard-link:hover .exmcard-t {
  color: var(--navy-dk);
}

.exmcard-d {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.exmcard-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
  margin-top: auto;
  padding-top: var(--s5);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* The date slot, empty until the client supplies real dates. It collapses so
   the foot row does not carry a hole, and takes its place back the moment a
   <time> is put in it. */
.exmcard-date:empty {
  display: none;
}

.exmcard-go {
  position: relative;
  margin-left: auto;
  padding-bottom: 3px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--navy);
}

/* The green accent, on a 2px rule under "Read more" that draws in on hover.
   Green on a rule is not text, so it is not bound by the small-text bar. */
.exmcard-go::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease);
}

.exmcard-link:hover .exmcard-go::before {
  transform: scaleX(1);
}

.exmcard-go::after {
  content: " \2197";
  display: inline-block;
  transition: transform var(--t) var(--ease);
}

.exmcard-link:hover .exmcard-go::after {
  transform: translate(3px, -3px);
}

@media (prefers-reduced-motion: reduce) {

  .exmcard-fig img,
  .exmcard-link:hover .exmcard-fig img {
    transition: none;
    transform: none;
  }

  .exmcard-go::before {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   17.43 PAGINATION
   -------------------------------------------------------------------------- */
.exmpage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  margin-top: var(--s7);
}

.exmpage-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
}

/* 48px, so every target clears the 44px minimum with room to spare. */
.exmpage a,
.exmpage span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  height: 48px;
  padding-inline: 12px;
  border: 1px solid var(--rule);
  background: var(--paper);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--navy);
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease);
}

.exmpage a:hover {
  background: var(--paper-3);
  border-color: var(--navy-20);
  color: var(--navy);
}

.exmpage [aria-current="page"] {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
}

/* An ellipsis is a marker, not a control: no border, no box. */
.exmpage-gap {
  border: 0;
  background: none;
  color: var(--ink-3);
  min-width: 24px;
}

/* An arrow with nowhere to go is stated, not hidden, so the control row keeps
   its shape on the first and the last page. */
.exmpage [aria-disabled="true"] {
  color: var(--navy-20);
  border-color: var(--rule);
  background: var(--paper);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   17.44 THE COVER — APPROVED by the client, 26 Aug 2026: "the detail page hero
   section is proper, do not change". Do not redesign it.

   A photograph full width, with the category and the H1 reversed out of a Navy
   scrim. The title and nothing else: the standfirst and the provenance line
   were both taken out at the client's instruction the same day.

   This one is the article cover only. The index has its own banner (17.41):
   it takes the same photographic treatment, so the pair matches, but it
   carries the lede and the facts as well, because a listing has to say what
   the section is before a reader will start down a grid of posts.
   -------------------------------------------------------------------------- */
.exmacov {
  background: var(--paper);
  padding-top: calc(var(--head-h) + clamp(24px, 3vw, 44px));
  padding-bottom: clamp(28px, 4vw, 52px);
}

.exmacov-shot {
  position: relative;
  overflow: hidden;
  margin-top: var(--s5);
  background: var(--navy);
  aspect-ratio: 3 / 4;
}

@media (min-width: 620px) {
  .exmacov-shot {
    aspect-ratio: 16 / 10;
  }
}

@media (min-width: 1000px) {
  .exmacov-shot {
    aspect-ratio: 21 / 9;
  }
}

.exmacov-shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* THE SCRIM. Navy, not black and not a blur: white on Navy is 9.35:1, so the
   title clears AA over any photograph in the set, and the cover stays inside
   the five brand colours rather than introducing a sixth grey. */
.exmacov-shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top,
      rgba(31, 69, 133, 0.94) 0%,
      rgba(31, 69, 133, 0.88) 26%,
      rgba(31, 69, 133, 0.42) 58%,
      rgba(31, 69, 133, 0.06) 82%,
      rgba(31, 69, 133, 0) 100%);
}

.exmacov-copy {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  padding: clamp(20px, 3.5vw, 56px);
}

.exmacov-k {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--green-lt);
}

.exmacov-k .ic {
  width: 17px;
  height: 17px;
  color: var(--green-lt);
}

.exmacov-h {
  margin-top: var(--s4);
  font-size: clamp(1.7rem, 1.05rem + 2.6vw, 3rem);
  font-weight: 600;
  line-height: 1.07;
  letter-spacing: -0.02em;
  color: var(--white);
  max-width: 22ch;
}

/* THE BANNER CARRIES THE TITLE AND NOTHING ELSE - client, 26 Aug 2026. The
   standfirst and the provenance line that used to sit under it are both gone:
   the standfirst is still the excerpt and the meta description, so it is doing
   its work on the index and in search, and the site and line are already said
   in the first paragraph of the article. Repeating either over the photograph
   only pushed the title up the frame. */

/* --------------------------------------------------------------------------
   17.45 THE READ
   -------------------------------------------------------------------------- */
/* The cover already puts a band of air above this, so the section's own
   --sec-y on top of it left a hole. Trimmed here rather than on .section,
   which every other page relies on. */
.exmread {
  padding-top: clamp(32px, 4vw, 56px);
}

.exmread-in {
  max-width: 72ch;
  margin-inline: auto;
}

/* Prose lives inside the article's <section> elements, so the paragraph
   rhythm is scoped to those rather than set loose on the column. */
.exmread-in section p {
  margin-bottom: var(--s5);
}

.exmread-in section p:last-child {
  margin-bottom: 0;
}

.exmread-in .lede {
  max-width: none;
  color: var(--ink);
}

.exmread-h {
  margin: var(--s8) 0 var(--s5);
  font-size: clamp(1.25rem, 1.1rem + 0.8vw, 1.6rem);
  font-weight: 600;
  line-height: 1.22;
  letter-spacing: -0.015em;
  color: var(--navy);
}

/* The cover already sets the article's top edge - the first heading does not
   need the inter-section gap on top of it as well. */
.exmread-in>section:first-child .exmread-h {
  margin-top: 0;
}

/* IMAGES IN THE COPY -----------------------------------------------------
   At the measure and nowhere wider - the client asked for no big image. One
   fixed 16:9 band so the column keeps its rhythm whatever shape the
   photograph is, and so the space is reserved before it loads. No caption:
   the alt text carries the description, and the article carries no
   footnotes. */
.exmread-fig {
  display: block;
  overflow: hidden;
  margin: var(--s7) 0;
  background: var(--paper-3);
  border: 1px solid var(--rule);
  aspect-ratio: 16 / 9;
}

.exmread-fig img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exmread-fig:first-child {
  margin-top: 0;
}

/* THE SEQUENCE -----------------------------------------------------------
   A plain list of points, client 26 Aug 2026: "step showing simple, number or
   point, not other" and "ul li, set point". So no ruled rows, no sub-headings
   and no register - just the number in green and the step beside it, sitting
   inside the reading column like any other paragraph.

   MARKUP: <ul class="exmsteps"> and one <li> per step, and NO <span> anywhere
   in it (client, same day). Each <li> holds exactly two elements:

     <b class="exmsteps-no">01</b>   the number, typed by the developer
     <p>…</p>                        the step

   The number is not generated by a counter on purpose. The client asked to
   enter it by hand, which also means a step can be renumbered, skipped or
   labelled "01a" without touching this file. */
.exmsteps {
  display: grid;
  gap: var(--s4);
  margin: var(--s6) 0 0;
}

.exmsteps li {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  gap: var(--s4);
}

.exmsteps-no {
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--green);
}

/* Scoped to the paragraph so it cannot reach .exmsteps-no, which is a <b>
   too and carries its own colour and weight. */
.exmsteps p {
  margin: 0;
  color: var(--ink-2);
}

.exmsteps p b {
  color: var(--navy);
  font-weight: 600;
}

/* .exmread-in section p sets a bottom margin on every paragraph in the
   article. The steps set their own rhythm with the grid gap, so that margin
   is taken back off here rather than the list carrying a double gap. */
.exmread-in section .exmsteps p {
  margin-bottom: 0;
}
