@import url('/assets/fonts.css');

/* ==========================================================================
   EMS-Trade Cooling - design-tokens.css
   --------------------------------------------------------------------------
   The single authoritative stylesheet for the whole site.
   Hard constraint 54: a class selector may be defined in this file only.
   A second stylesheet that redefines a class already defined here is a FAIL.

   Every value below is inherited from source/docs/site-design-language.md
   (frozen 2026-09-19, style card 01 "Instrument Panel - concentric annulus").
   Colour, type, surface treatment, grid, icon language, image character and
   conversion shape are locked. Do not introduce a new colour, a new radius,
   a new shadow or a new aspect ratio anywhere in the site.

   Surface rules enforced here and checked by script:
     - zero shadow anywhere. Depth comes from hairlines and the panel colour.
     - one radius only: 2px (var(--radius)). Nothing else, no pills, no circles.
     - hairlines are 1px solid var(--rule).
     - image containers use aspect-ratio 3/2, 2/3, 1/1 or 3/4 and nothing else.
     - every grid child carries min-width:0 so a table or select cannot push a
       1fr column past the viewport.

   Fonts: build/assets/fonts.css is pulled in by the @import on line 1 and is
   the only font source. Three families, all self-hosted:
     Archivo (display), Inter (body), IBM Plex Mono (utility).
   Pages may instead carry <link rel="stylesheet" href="/assets/fonts.css">
   before this file; if they do, delete the @import above only if that link is
   present on every page. Exactly one of the two, never both, never neither.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* ---- colour: the frozen seven ---------------------------------------- */
  --ground:      #EEF1F4;   /* page background, cool steel near-white       */
  --panel:       #FFFFFF;   /* cards, table heads, form fields              */
  --ink:         #0E1319;   /* body text, headings, hairlines that matter   */
  --muted:       #5A646E;   /* secondary text, captions, units, meta        */
  --rule:        #D3DAE1;   /* 1px hairline, table rule, dividers           */
  --accent:      #1B5FC1;   /* primary button, eyebrow, one word in a head  */
  --accent-ink:  #FFFFFF;   /* text on the accent fill                      */

  /* ---- colour: dark variant, derived from the same seven ---------------
     A dark band is the frozen palette inverted, not a second palette.
     --dark-ground is --ink, --dark-panel sits one step above it, and the
     text colours are the ground and muted values at readable contrast
     (measured: 16.4:1 for --dark-ink, 8.7:1 for --dark-muted on the ground).
     The accent is NOT used for text on a dark ground: #1B5FC1 measures
     3.8:1 there, under the 4.5:1 small-text floor. Dark bands therefore take
     a panel-filled button and a light eyebrow instead.                   */
  --dark-ground: #0E1319;
  --dark-panel:  #1A2029;
  --dark-ink:    #EEF1F4;
  --dark-muted:  #A7B2BE;
  --dark-rule:   #33404F;

  /* ---- type families ---------------------------------------------------- */
  --font-display: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-body:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  --font-util:    'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* ---- type scale: design language section 2 --------------------------- */
  --fs-h1: 40px;      --fs-h1-m: 29px;
  --fs-h2: 27px;      --fs-h2-m: 22px;
  --fs-h3: 18px;      --fs-h3-m: 16.5px;
  --fs-lead: 18px;    --fs-lead-m: 16.5px;
  --fs-body: 16px;
  --fs-data: 15px;    --fs-data-m: 14px;
  --fs-eyebrow: 11px;
  --fs-figure: 32px;  --fs-figure-m: 26px;
  --fs-small: 14px;
  --fs-min: 11px;     /* nothing on the site is set below this */

  --lh-h1: 1.14;
  --lh-h2: 1.2;
  --lh-h3: 1.3;
  --lh-lead: 1.58;
  --lh-body: 1.62;
  --lh-eyebrow: 1.2;
  --lh-data: 1.35;
  --lh-figure: 1.1;

  --mb-h1: 20px;
  --mb-h2: 18px;
  --mb-h3: 16px;
  --mb-lead: 20px;
  --mb-body: 14px;
  --mb-eyebrow: 10px;
  --mb-figure: 6px;

  --track-eyebrow: 0.09em;   /* eyebrow letter-spacing */
  --track-display: -0.02em;  /* Archivo headings sit tighter than default */

  /* ---- spacing: 4px base ------------------------------------------------ */
  --sp: 4px;
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px;  --sp-6: 24px;  --sp-7: 28px;  --sp-8: 32px;
  --sp-9: 40px;  --sp-10: 48px; --sp-11: 56px; --sp-12: 72px;
  --sp-13: 96px;

  /* ---- grid ------------------------------------------------------------- */
  --container: 1180px;
  --grid-cols: 12;
  --gutter: 28px;            /* column gap */
  --pad-x: 24px;             /* container side padding */
  --section-y: 72px;         /* section rhythm, desktop. Floor, not a target. */

  /* ---- surface ---------------------------------------------------------- */
  --radius: 2px;             /* the only radius on the site */

  /* ---- motion: level 2 --------------------------------------------------
     Hover and focus shifts at 200ms, a 12px fade-up on reveal. Nothing
     moves on its own: no parallax, no scroll hijack, no carousel, no
     autoplay, no cursor follower, no staggered entrance.                 */
  --dur: 200ms;
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --reveal-shift: 12px;

  /* ---- control sizing --------------------------------------------------- */
  --tap: 44px;               /* minimum touch target */
}

/* ==========================================================================
   2. RESET
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 104px;   /* clears the sticky masthead on anchor jumps */
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
svg,
video { max-width: 100%; }

img { display: block; height: auto; border: 0; }

hr {
  height: 1px;
  margin: var(--sp-8) 0;
  border: 0;
  background: var(--rule);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  border-radius: var(--radius);
  -webkit-appearance: none;
  appearance: none;
}

table { border-collapse: collapse; border-spacing: 0; }

ul, ol { margin: 0 0 var(--mb-body); padding-left: 1.15em; }

li { margin-bottom: 6px; }

figure { margin: 0; }

[hidden] { display: none !important; }

/* ==========================================================================
   3. TYPOGRAPHY
   Real sizes, weights and leading from design language section 2.
   ========================================================================== */

h1, h2, h3, h4 {
  margin: 0 0 var(--mb-h3);
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: var(--track-display);
  color: var(--ink);
  overflow-wrap: break-word;
}

h1 {
  margin-bottom: var(--mb-h1);
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
}

h2 {
  margin-bottom: var(--mb-h2);
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
}

h3, h4 {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
}

p {
  margin: 0 0 var(--mb-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

p:last-child,
ul:last-child,
ol:last-child { margin-bottom: 0; }

strong, b { font-weight: 600; }

small { font-size: var(--fs-small); line-height: 1.5; }

/* In-text link: a hairline underline, not a colour. The accent is spent on
   the primary button, the eyebrow and one word per heading, so a link cannot
   take it as well. The underline is the same hairline system as every rule. */
a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur) var(--ease);
}

a:hover { text-decoration-color: var(--ink); }

.lead {
  margin-bottom: var(--mb-lead);
  font-size: var(--fs-lead);
  font-weight: 400;
  line-height: var(--lh-lead);
  color: var(--muted);
}

.prose { max-width: 68ch; }

.prose > p,
.prose > ul,
.prose > ol { margin-bottom: var(--sp-4); }

.prose h2 { margin-top: var(--sp-10); }
.prose h3 { margin-top: var(--sp-8); }

.prose ul,
.prose ol { padding-left: 1.2em; }

.prose li { margin-bottom: var(--sp-2); }

/* The one emphasised word allowed inside a heading. */
.accent-word { color: var(--accent); }

/* Eyebrow. Design language: a 1px hairline sits above every section eyebrow,
   which is what separates one band from the next. Nothing else does. */
.eyebrow {
  display: block;
  margin: 0 0 var(--mb-eyebrow);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: var(--lh-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}

.eyebrow--bare {
  padding-top: 0;
  border-top: 0;
}

/* Utility label: mono metadata that is not a section opener. */
.meta {
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.data {
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
  line-height: var(--lh-data);
}

.figure-value {
  display: block;
  margin-bottom: var(--mb-figure);
  font-family: var(--font-display);
  font-size: var(--fs-figure);
  font-weight: 600;
  line-height: var(--lh-figure);
  letter-spacing: var(--track-display);
}

.unit {
  font-family: var(--font-util);
  font-size: 0.62em;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-left: 3px;
}

/* ==========================================================================
   4. UTILITIES
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--pad-x);
  top: -64px;
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-4);
  background: var(--panel);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  text-decoration: none;
  transition: top var(--dur) var(--ease);
}

.skip-link:focus { top: var(--sp-3); }

/* Grid children must never be able to push a 1fr track wider than its share.
   A wide table or a long part number inside a grid cell is the usual cause of
   horizontal overflow at 375px. */
.grid-12 > *,
.split > *,
.card-grid > *,
.stat-band > *,
.icon-strip > *,
.badge-row > *,
.datasheet-list--cards > * { min-width: 0; }

/* ==========================================================================
   5. SECTION RHYTHM AND THE 12-COLUMN GRID
   ========================================================================== */

.section {
  padding-block: var(--section-y);
}

.section--dark {
  background: var(--dark-ground);
  color: var(--dark-ink);
}

.section--ruled {
  border-top: 1px solid var(--rule);
}

.section__head {
  max-width: 760px;
  margin-bottom: var(--sp-9);
}

.section__head--wide { max-width: none; }

.block-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-7);
}

.block-head h2,
.block-head h3 { margin-bottom: 0; }

.block-head__more {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  margin-left: auto;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2px;
}

.block-head__more:hover { border-bottom-color: var(--ink); }

.grid-12 {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  gap: var(--gutter);
}

.col-3  { grid-column: span 3; }
.col-4  { grid-column: span 4; }
.col-5  { grid-column: span 5; }
.col-6  { grid-column: span 6; }
.col-7  { grid-column: span 7; }
.col-8  { grid-column: span 8; }
.col-9  { grid-column: span 9; }
.col-12 { grid-column: span 12; }

/* Hero split. 52 / 48, text left, figure right, one full-height hairline
   between the columns. The figure never escapes the container. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 52fr) minmax(0, 48fr);
  align-items: stretch;
}

.split__text {
  padding-right: var(--gutter);
  align-self: center;
}

.split__media {
  position: relative;
  min-height: 280px;
  /* The media box stretches to the row (.split is align-items: stretch), and its
     .ratio-* aspect-ratio then transfers that height back into a width that can
     exceed its own column — which pushed documentElement wider than the viewport
     at 1440 and 1024. min-width: 0 on the grid item does not stop a transferred
     size; capping the width does. The height: 100% + object-fit: cover image
     below still fills whatever box results. */
  max-width: 100%;
  background: var(--ground);
  border-left: 1px solid var(--rule);
  overflow: hidden;
}

.split__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.split--media-left { grid-template-columns: minmax(0, 48fr) minmax(0, 52fr); }

.split--media-left .split__media {
  order: -1;
  border-left: 0;
  border-right: 1px solid var(--rule);
}

.split--media-left .split__text {
  padding-right: 0;
  padding-left: var(--gutter);
}

.split--form { grid-template-columns: minmax(0, 48fr) minmax(0, 52fr); }

.split--form .split__text { padding-right: var(--gutter); }

.split__aside {
  padding-left: var(--gutter);
  border-left: 1px solid var(--rule);
}

/* ==========================================================================
   6. FIGURES AND CAPTIONS
   The caption chip sits under or beside the image. Design language: no text
   is ever placed on top of a photograph.
   ========================================================================== */

.figure {
  position: relative;
  background: var(--ground);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Self-drawn diagrams. The width and height attributes on the element carry the
   intrinsic ratio; this rule lets it fill its column without an inline style,
   which style-src 'self' would block. Below the threshold width the drawing
   renders at its authored size inside a horizontal scroller instead of being
   scaled until its 11px labels are unreadable. Wrappers are added by
   _scripts/wrap-diagrams.py. */
.diagram-scroll { overflow-x: auto; }

.diagram-svg {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 760px) {
  .diagram-scroll > .diagram-svg {
    width: auto;
    max-width: none;
  }
}

.figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The only four container ratios allowed anywhere on the site. */
.ratio-3-2 { aspect-ratio: 3/2; }
.ratio-2-3 { aspect-ratio: 2/3; }
.ratio-1-1 { aspect-ratio: 1/1; }
.ratio-3-4 { aspect-ratio: 3/4; }

.figure__caption {
  display: inline-block;
  padding: 6px 10px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.figure__caption--below { margin-top: var(--sp-2); }

.caption {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
}

/* ==========================================================================
   7. BUTTONS AND ACTION LINKS
   Primary is the accent fill. Secondary is a hairline. Hover inverts to ink,
   which spends no colour beyond the frozen seven.
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: 11px var(--sp-5);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  color: var(--accent-ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.btn:hover,
.btn:active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--panel);
}

.btn--secondary {
  background: transparent;
  border-color: var(--rule);
  color: var(--ink);
}

.btn--secondary:hover,
.btn--secondary:active {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}

.btn--small {
  min-height: 36px;
  padding: 7px var(--sp-4);
  font-size: var(--fs-small);
}

.btn--block {
  width: 100%;
}

.btn[disabled],
.btn[aria-busy='true'] {
  opacity: 0.62;
  cursor: progress;
}

/* Standalone action link with an arrow glyph. Kept at the touch minimum so a
   row of them is tappable. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid var(--rule); /* hit area: 44px wide without moving the text */
  padding-inline: 9px;
  margin-inline: -9px;
}

.link-arrow:hover { border-bottom-color: var(--ink); }

.link-arrow .icon { color: var(--ink); }

/* A row of actions. Use this instead of letting two buttons sit on one line
   with nothing between them. */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

.actions:last-child { margin-bottom: 0; }

/* ==========================================================================
   8. CARDS
   ========================================================================== */

/* No height: 100% here, deliberately. A card that declares a percentage height
   makes its grid track's size depend on the card, while the card's size depends
   on the track. The percentage is therefore treated as auto while the track is
   being sized, so a cell holding a card *plus* a table below it contributed only
   the card's height to a row that then stretched the card back to that height —
   and the table was laid out below its own cell, painted through the next
   section's eyebrow. Left at auto the card still fills its grid area
   (align-self: stretch is the grid default), and the row sizes to the tallest
   cell's real content. */
.card {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

.card__icon {
  display: block;
  margin-bottom: var(--sp-4);
  color: var(--ink);
}

.card__media {
  border-bottom: 1px solid var(--rule);
  background: var(--ground);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--sp-6);
}

.card__title { margin-bottom: var(--sp-2); }

.card__text {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--muted);
}

/* A part number is one token. Without this, narrow card copy breaks it at its
   own hyphen: "EMS-TL-STC" renders as "EMS-TL-" / "STC" on two lines and the
   two inline runs' union boxes overlap in the rendered-text sweep. The tables
   already declare nowrap for .code; card copy needs the same rule. */
.card__text .code { white-space: nowrap; }

.card__meta {
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.card__foot {
  padding: var(--sp-4) var(--sp-6);
  border-top: 1px solid var(--rule);
}

/* A card that is entirely one link. */
a.card,
.card--linked { text-decoration: none; transition: border-color var(--dur) var(--ease); }

a.card:hover,
.card--linked:hover { border-color: var(--ink); }

a.card:hover .card__title,
.card--linked:hover .card__title { text-decoration: underline; }

/* card-grid: the item count must be a whole multiple of the column count.
   No three-then-one last rows. */
.card-grid {
  display: grid;
  gap: var(--gutter);
}

.card-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.card-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.card-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ==========================================================================
   9. TABLES
   Horizontal hairlines only. No vertical rules, no zebra striping.
   ========================================================================== */

.spec-table {
  width: 100%;
  font-size: var(--fs-data);
  line-height: var(--lh-data);
  text-align: left;
}

.spec-table caption {
  caption-side: top;
  padding-bottom: var(--sp-3);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
  text-align: left;
}

/* A guide link inside a table caption is a real tap target, so it has to clear
   the 24px minimum. Padding grows the hit box. The claim that vertical padding
   does not enter the line box only holds for a non-replaced INLINE box — and it
   does not hold for the reported rect either: an inline box with
   padding-block: 4px measures 27px against a 20.25px line-height, so its box
   reached 2.75px into the thead cell below and the rendered-text sweep called it
   a collision. inline-block puts the padding outside the line box for real: the
   caption does not move, the hit area keeps its 4px, and the boxes separate. */
caption a {
  display: inline-block;
  padding-block: 4px;
}

.spec-table th,
.spec-table td {
  padding: 12px var(--sp-3);
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

.spec-table thead th {
  padding-top: var(--sp-2);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--ink);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.spec-table tbody th {
  font-weight: 500;
  color: var(--ink);
}

/* .num still holds a short reading together, but it is not allowed to decide how
   wide the table gets. A .num cell in this build holds whole sentences
   ("81.65 kg; 22.7 kg with a 0.13 mm blade"), and an unbreakable minimum content
   width is what pushed tables out of their columns and onto the next column's
   figure caption. Short values are one line either way; long ones wrap instead
   of overflowing. .code stays nowrap: a part number must never break. */
.spec-table .num,
.data-table-wide .num,
.spec-table .code,
.data-table-wide .code {
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
}

.spec-table .code { letter-spacing: 0.03em; }

.spec-table--compact th,
.spec-table--compact td { padding: 9px var(--sp-2); }

.spec-table--ruled tbody tr:last-child th,
.spec-table--ruled tbody tr:last-child td { border-bottom: 1px solid var(--ink); }

/* Wrap any table that might not fit: the container scrolls, the page never
   does. No forced min-width here, so a table that does fit simply fits. */
.table-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* A table does not get to be wider than the box it was put in. A cell whose
   content cannot break (.num and .code are nowrap by design, thead th too) sets
   the table's minimum content width, and a table ignores max-width: 100% when
   that minimum is larger — it simply paints outside its column. Inside a .col-*
   cell that put the overflow on top of the next column's figure caption.
   display: block makes the table itself the scroll container, which is exactly
   what .table-scroll already achieves with a wrapper element: same result, no
   wrapper required, and a table that fits is untouched because a block with
   width: 100% is its container's width either way. */
.spec-table,
.data-table-wide {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table-scroll--wide > table { min-width: 980px; }

.data-table-wide {
  width: 100%;
  font-size: var(--fs-data);
  line-height: var(--lh-data);
  text-align: left;
}

.data-table-wide th,
.data-table-wide td {
  padding: 10px var(--sp-3);
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

.data-table-wide thead th {
  border-bottom: 1px solid var(--ink);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.data-table-wide tbody tr:nth-child(even) { background: var(--panel); }

.data-table-wide .num,
.data-table-wide .code {
  font-family: var(--font-util);
  font-weight: 500;
  white-space: nowrap;
}

/* Declared after every nowrap rule above, including this one, so the wrap it
   asks for is not silently undone by a later equal-specificity declaration. */
.spec-table .num,
.data-table-wide .num { white-space: normal; overflow-wrap: anywhere; }

.spec-table .code,
.data-table-wide .code { white-space: nowrap; }

/* Row icon: the icon sits inside the row header, never as decoration. */
.cell-icon {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

/* ==========================================================================
   10. STAT BAND
   ========================================================================== */

.stat-band {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.stat-band--2up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stat-band--3up { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stat-band--4up { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.stat {
  padding: var(--sp-6) var(--sp-5);
  border-left: 1px solid var(--rule);
}

.stat:first-child { border-left: 0; }

.stat__label {
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
}

.stat__value {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-figure);
  font-weight: 600;
  line-height: var(--lh-figure);
  letter-spacing: var(--track-display);
  color: var(--ink);
}

.stat__note {
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
}

.section--dark .stat-band { border-color: var(--dark-rule); }
.section--dark .stat { border-left-color: var(--dark-rule); }
.section--dark .stat__value { color: var(--dark-ink); }
.section--dark .stat__label,
.section--dark .stat__note { color: var(--dark-muted); }

/* ==========================================================================
   11. ICON STRIP
   The block is the icon. Each cell carries a label, never a bare glyph.
   ========================================================================== */

.icon-strip {
  display: grid;
  gap: var(--sp-6) var(--gutter);
}

.icon-strip--3up { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.icon-strip--4up { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.icon-strip--6up { grid-template-columns: repeat(6, minmax(0, 1fr)); }

.icon-strip__item {
  padding-top: var(--sp-4);
  border-top: 1px solid var(--rule);
}

.icon-strip__item .icon { color: var(--ink); margin-bottom: var(--sp-3); }

.icon-strip__label {
  display: inline-flex;
  align-items: center;
  min-height: 44px;

  
  margin-bottom: var(--sp-1);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
}

.icon-strip__note {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
}

.section--dark .icon-strip__item { border-top-color: var(--dark-rule); }
.section--dark .icon-strip__item .icon { color: var(--dark-ink); }
.section--dark .icon-strip__note { color: var(--dark-muted); }

/* ---- icon sizing ---------------------------------------------------------
   The sprite is drawn on a 24px grid at 1.5px stroke. Sizes are kept on that
   grid so the drawn weight scales predictably. */
.icon {
  display: inline-block;
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  vertical-align: middle;
}

.icon--16 { width: 16px; height: 16px; }
.icon--20 { width: 20px; height: 20px; }
.icon--28 { width: 28px; height: 28px; }
.icon--32 { width: 32px; height: 32px; }
.icon--48 { width: 48px; height: 48px; }

.icon--inline { vertical-align: -0.22em; }

/* ==========================================================================
   12. CTA BAND
   ========================================================================== */

.cta-band {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-6) var(--sp-8);
  padding: var(--sp-9);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.cta-band__text { min-width: 0; }

.cta-band__text h2,
.cta-band__text h3 { margin-bottom: var(--sp-2); }

.cta-band__text p {
  max-width: 62ch;
  color: var(--muted);
}

.cta-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.cta-band--dark {
  background: var(--dark-panel);
  border-color: var(--dark-rule);
  color: var(--dark-ink);
}

.cta-band--dark h2,
.cta-band--dark h3 { color: var(--dark-ink); }

.cta-band--dark p { color: var(--dark-muted); }

.cta-band--stacked { grid-template-columns: minmax(0, 1fr); }

/* A dark CTA band is a dark surface without being a whole dark section, so it
   has to carry the same overrides for whatever a band can hold. Without this
   the secondary button keeps ink text on a dark panel and disappears. */
.cta-band--dark .btn--secondary {
  background: transparent;
  border-color: var(--dark-rule);
  color: var(--dark-ink);
}

.cta-band--dark .btn--secondary:hover,
.cta-band--dark .btn--secondary:active {
  background: transparent;
  border-color: var(--dark-ink);
  color: var(--dark-ink);
}

.cta-band--dark .link-arrow {
  color: var(--dark-ink);
  border-bottom-color: var(--dark-rule);
}

.cta-band--dark .link-arrow:hover { border-bottom-color: var(--dark-ink); }

.cta-band--dark .link-arrow .icon { color: var(--dark-ink); }

.cta-band--dark a:not(.btn) { text-decoration-color: var(--dark-rule); }
.cta-band--dark a:not(.btn):hover { text-decoration-color: var(--dark-ink); }

/* ==========================================================================
   13. REQUISITION STRIP (the sitewide conversion block)
   One shape sitewide: an anchored inline form, never a modal, never a
   separate page. The band carries id="request" on every page.
   ========================================================================== */

.requisition {
  border-top: 1px solid var(--rule);
}

.requisition__grid {
  display: grid;
  grid-template-columns: minmax(0, 48fr) minmax(0, 52fr);
  align-items: start;
}

.requisition__text { padding-right: var(--gutter); }

.requisition__form {
  position: relative;
  padding-left: var(--gutter);
  border-left: 1px solid var(--rule);
}

.requisition__list {
  margin: var(--sp-5) 0 0;
  padding: 0;
  list-style: none;
}

.requisition__list li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  padding: var(--sp-3) 0;
  border-top: 1px solid var(--rule);
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--muted);
}

.requisition__list .icon { color: var(--ink); margin-top: 2px; }

.form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4);
}

.form-row > * { min-width: 0; }

.field {
  display: block;
  margin-bottom: var(--sp-4);
}

.field__label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.field__label .optional {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.02em;
}

.field__input,
.field__area {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 10px var(--sp-3);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);   /* 16px: also stops iOS zooming on focus */
  line-height: 1.4;
  transition: border-color var(--dur) var(--ease);
}

.field__input::placeholder,
.field__area::placeholder { color: var(--muted); }

.field__input:focus,
.field__area:focus {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.field__area {
  min-height: 112px;
  resize: vertical;
}

.field__hint {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--muted);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-2);
}

.form-actions .promise {
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Honeypot. Not rendered anywhere a person or a screen reader can reach it:
   moved out of the viewport, clipped, and removed from the tab order and the
   accessibility tree in the markup. */
.hp {
  position: absolute;
  top: 0;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  padding: var(--sp-6);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.form-status__title {
  display: block;
  margin-bottom: var(--sp-2);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
}

.form-status__ref {
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
  letter-spacing: 0.04em;
}

.form-status__body {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--muted);
}

.form-status--error { border-color: var(--ink); }

.form-error {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: var(--panel);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  font-size: var(--fs-body);
  line-height: 1.5;
}

/* ==========================================================================
   14. FAQ
   ========================================================================== */

.faq {
  border-top: 1px solid var(--rule);
}

.faq__item {
  border-bottom: 1px solid var(--rule);
}

.faq__q { margin: 0; }

.faq__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  width: 100%;
  min-height: 56px;
  padding: var(--sp-4) 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-h3);
  text-align: left;
  cursor: pointer;
}

.faq__trigger:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.faq__mark {
  flex: 0 0 auto;
  color: var(--ink);
  transition: transform var(--dur) var(--ease);
}

.faq__trigger[aria-expanded='true'] .faq__mark { transform: rotate(45deg); }

.faq__panel {
  padding: 0 var(--sp-10) var(--sp-6) 0;
}

.faq__panel > p { color: var(--muted); }

.faq__panel > p:last-child { margin-bottom: 0; }

.faq--two-column {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--gutter);
  border-top: 0;
}

.faq--two-column > * { min-width: 0; }

.section--dark .faq,
.section--dark .faq__item { border-color: var(--dark-rule); }
.section--dark .faq__trigger { color: var(--dark-ink); }
.section--dark .faq__mark { color: var(--dark-ink); }
.section--dark .faq__panel > p { color: var(--dark-muted); }

/* ==========================================================================
   15. BREADCRUMB
   ========================================================================== */

.breadcrumb {
  padding-block: var(--sp-4);
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.breadcrumb li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.breadcrumb li + li::before {
  content: '/';
  color: var(--rule);
}

.breadcrumb a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.breadcrumb a:hover { border-bottom-color: var(--ink); }

.breadcrumb [aria-current='page'] { color: var(--ink); }

/* ==========================================================================
   16. DATASHEET LIST
   ========================================================================== */

.datasheet-list {
  border-top: 1px solid var(--rule);
  margin: 0;
  padding: 0;
  list-style: none;
}

.datasheet-list li { margin: 0; }

.datasheet-row {
  display: grid;
  grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--rule);
}

.datasheet-row > * { min-width: 0; }

.datasheet-row__model {
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
  letter-spacing: 0.04em;
  overflow-wrap: anywhere;
}

.datasheet-row__title {
  font-size: var(--fs-body);
  line-height: 1.45;
}

.datasheet-row__note {
  display: block;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--muted);
}

.datasheet-list--cards {
  display: grid;
  gap: var(--gutter);
  border-top: 0;
}

.datasheet-list--cards--2up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.datasheet-list--cards--3up { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.datasheet-list--inline .datasheet-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

/* .link-arrow above widens its own hit area with padding-inline: 9px and then
   cancels it with margin-inline: -9px, which is right in a text flow but wrong
   as a grid item: the grid's content box is 9px narrower than the row, and the
   row reported scrollWidth 464 against a clientWidth of 455 at 1440px. The
   padding stays, so the 44px tap target is untouched; only the negative margin
   goes, and only inside a datasheet row. */
.datasheet-row .link-arrow {
  margin-inline: 0;
}

/* ==========================================================================
   17. BADGE (certification card)
   Certification names only. No numbers, no scans, no award graphics.
   ========================================================================== */

.badge-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
}

.badge {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--sp-6);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.badge__mark {
  display: block;
  margin-bottom: var(--sp-4);
  color: var(--ink);
}

.badge__name {
  margin-bottom: var(--sp-2);
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.badge__text {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--muted);
}

.badge__note {
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--rule);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
}

.section--dark .badge {
  background: var(--dark-panel);
  border-color: var(--dark-rule);
}

.section--dark .badge__mark,
.section--dark .badge__name { color: var(--dark-ink); }

.section--dark .badge__text,
.section--dark .badge__note { color: var(--dark-muted); }

.section--dark .badge__note { border-top-color: var(--dark-rule); }

/* ==========================================================================
   18. DARK BAND OVERRIDES
   ========================================================================== */

.section--dark .eyebrow {
  color: var(--dark-ink);
  border-top-color: var(--dark-rule);
}

.section--dark h1,
.section--dark h2,
.section--dark h3,
.section--dark h4 { color: var(--dark-ink); }

.section--dark p,
.section--dark .lead { color: var(--dark-muted); }

.section--dark .meta,
.section--dark .caption,
.section--dark .field__label,
.section--dark .field__hint,
.section--dark .stat__label { color: var(--dark-muted); }

.section--dark a { text-decoration-color: var(--dark-rule); }
.section--dark a:hover { text-decoration-color: var(--dark-ink); }
.section--dark .accent-word { color: var(--dark-ink); }

/* The accent fill is kept for the primary button: white on #1B5FC1 measures
   6.1:1, which clears 4.5:1 for button text. The label is what has to be
   readable, and it is. */
.section--dark .btn { border-color: var(--accent); }

.section--dark .btn--secondary {
  background: transparent;
  border-color: var(--dark-rule);
  color: var(--dark-ink);
}

.section--dark .btn--secondary:hover,
.section--dark .btn--secondary:active {
  background: transparent;
  border-color: var(--dark-ink);
  color: var(--dark-ink);
}

.section--dark .card {
  background: var(--dark-panel);
  border-color: var(--dark-rule);
}

.section--dark .card__title { color: var(--dark-ink); }
.section--dark .card__text { color: var(--dark-muted); }
.section--dark .card__meta { color: var(--dark-muted); border-top-color: var(--dark-rule); }
.section--dark .card__media { border-bottom-color: var(--dark-rule); background: var(--dark-ground); }
.section--dark .card__foot { border-top-color: var(--dark-rule); }

.section--dark .spec-table th,
.section--dark .spec-table td,
.section--dark .data-table-wide th,
.section--dark .data-table-wide td { border-bottom-color: var(--dark-rule); }

.section--dark .spec-table tbody th { color: var(--dark-ink); }

.section--dark .spec-table thead th,
.section--dark .data-table-wide thead th {
  border-bottom-color: var(--dark-ink);
  color: var(--dark-muted);
}

.section--dark .data-table-wide tbody tr:nth-child(even) { background: var(--dark-panel); }

.section--dark .datasheet-list,
.section--dark .datasheet-row { border-color: var(--dark-rule); }
.section--dark .datasheet-row__note { color: var(--dark-muted); }

.section--dark .form-status,
.section--dark .form-error,
.section--dark .field__input,
.section--dark .field__area {
  background: var(--dark-panel);
  border-color: var(--dark-rule);
  color: var(--dark-ink);
}

.section--dark .cta-band { background: var(--dark-panel); border-color: var(--dark-rule); }
.section--dark .cta-band p { color: var(--dark-muted); }

/* ==========================================================================
   18b. DARK SURFACE COMPLETION
   Any class that sets its own colour needs a counterpart on both dark
   contexts, or it keeps a light-ground colour on a dark panel. These were
   found by measuring the rendered page, not by reading the sheet.
   ========================================================================== */

.section--dark .unit,
.cta-band--dark .unit { color: var(--dark-muted); }

.section--dark .promise,
.cta-band--dark .promise { color: var(--dark-muted); }

.section--dark .form-status__body,
.section--dark .form-status__ref,
.cta-band--dark .form-status__body { color: var(--dark-muted); }

.section--dark .form-status__title { color: var(--dark-ink); }

.section--dark .form-error,
.cta-band--dark .form-error { border-color: var(--dark-ink); }

.section--dark .breadcrumb li { color: var(--dark-muted); }
.section--dark .breadcrumb [aria-current='page'] { color: var(--dark-ink); }

.section--dark .link-arrow,
.cta-band--dark .link-arrow { border-bottom-color: var(--dark-rule); }

.section--dark .link-arrow .icon { color: var(--dark-ink); }

.section--dark .block-head__more,
.cta-band--dark .block-head__more { border-bottom-color: var(--dark-rule); color: var(--dark-ink); }

.section--dark .icon-gallery__id,
.section--dark .swatch__role { color: var(--dark-muted); }

/* ==========================================================================
   19. MOTION
   Reveal is a 12px fade-up and nothing else. The hidden state is applied
   only once the script has confirmed it will run, so a page without script
   shows every element.
   ========================================================================== */

html.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
}

html.js-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity 400ms var(--ease), transform 400ms var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }

  html.js-reveal [data-reveal] {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   20. FOCUS
   A 2px accent ring on every focusable element. Outline, not a shadow.
   ========================================================================== */

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.section--dark a:focus-visible,
.section--dark button:focus-visible,
.section--dark input:focus-visible,
.section--dark textarea:focus-visible {
  outline-color: var(--dark-ink);
}

/* ==========================================================================
   21. MASTHEAD
   Two hairline-ruled rows: the lockup and the conversion action on top, the
   ten primary destinations underneath in mono caps. The site's single email
   address is not here; it appears in the footer and on the contact page.
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ground);
  border-bottom: 1px solid var(--rule);
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 60px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--tap);
  text-decoration: none;
}

.brand__mark {
  display: block;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  color: var(--ink);
}

.brand__lockup { display: block; }

.brand__word {
  display: block;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.025em;
}

.brand__sub {
  display: block;
  margin-top: 4px;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);   /* 11px: the site floor */
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}

.topbar__spacer { flex: 1 1 auto; }

.topbar__meta {
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.topbar .btn { flex: 0 0 auto; }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink);
  cursor: pointer;
}

.nav-toggle:hover { border-color: var(--ink); }

.masthead-nav {
  border-top: 1px solid var(--rule);
}

.nav-list {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-list li { margin: 0; }

.nav-list a {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 2px;
  border-bottom: 1px solid transparent;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  color: var(--muted);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.nav-list a:hover { color: var(--ink); }

.nav-list a.is-current,
.nav-list a[aria-current='page'] {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--ink);
}

/* ==========================================================================
   22. FOOTER
   ========================================================================== */

.site-footer {
  margin-top: var(--section-y);
  background: var(--panel);
  border-top: 1px solid var(--rule);
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr)) minmax(0, 1.2fr);
  gap: var(--sp-8) var(--gutter);
  padding-block: var(--sp-12) var(--sp-9);
}

.footer-grid > * { min-width: 0; }

.footer-col__title {
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink);
}

.footer-nav {
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-nav li { margin: 0; }

.footer-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  font-size: var(--fs-small);
  line-height: 1.4;
  text-decoration: none;
  color: var(--muted);
}

.footer-nav a:hover { color: var(--ink); text-decoration: underline; }

.footer-note {
  margin-top: var(--sp-5);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--muted);
  max-width: 46ch;
}

.footer-mail {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}

.footer-cta { margin-top: var(--sp-4); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  align-items: baseline;
  padding-block: var(--sp-5);
  border-top: 1px solid var(--rule);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--muted);
}

.footer-bottom__spacer { flex: 1 1 auto; }

/* ==========================================================================
   23. SPECIMEN CLASSES
   Used only by build/components.html, the internal reference page that is
   not deployed. Kept in the single authoritative stylesheet because a
   specimen page may not carry an inline style attribute either.
   ========================================================================== */

.swatch-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.swatch-row > * { min-width: 0; }

.swatch { margin: 0; }

.swatch__chip {
  height: 80px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.swatch__chip--ground { background: var(--ground); }
.swatch__chip--panel  { background: var(--panel); }
.swatch__chip--ink    { background: var(--ink); }
.swatch__chip--muted  { background: var(--muted); }
.swatch__chip--rule   { background: var(--rule); }
.swatch__chip--accent { background: var(--accent); }
.swatch__chip--accent-ink { background: var(--accent-ink); }
.swatch__chip--dark   { background: var(--dark-ground); }

.swatch__value {
  display: block;
  margin-top: var(--sp-2);
  font-family: var(--font-util);
  font-size: var(--fs-data);
  font-weight: 500;
}

.swatch__role {
  display: block;
  font-size: var(--fs-small);
  line-height: 1.4;
  color: var(--muted);
}

.icon-gallery {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

.icon-gallery > * { min-width: 0; }

.icon-gallery__cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  margin: 0;
  padding: var(--sp-5) var(--sp-3);
  background: var(--panel);
  text-align: center;
}

.icon-gallery__id {
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* Labels the empty image slot on the specimen page. A real page puts an
   <img> here and a caption chip below or beside the frame, never on it. */
.slot-label {
  position: absolute;
  left: var(--sp-4);
  bottom: var(--sp-4);
  z-index: 1;
  font-family: var(--font-util);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.specimen-note {
  padding: var(--sp-5) var(--sp-6);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-left: 2px solid var(--ink);
  border-radius: var(--radius);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--muted);
}

.specimen-note strong { color: var(--ink); }

.code-block {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-5);
  overflow-x: auto;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--ink);
  tab-size: 2;
}

/* ==========================================================================
   24. RESPONSIVE
   375px must not scroll sideways, body text stays at 16px, touch targets
   stay at 44px, and every grid collapses to a column count that still
   divides the item count exactly.
   ========================================================================== */

@media (max-width: 1100px) {
  html.nav-js .masthead-nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    display: none;
    max-height: calc(100vh - 60px);
    overflow-y: auto;
    background: var(--ground);
    border-top: 1px solid var(--rule);
    border-bottom: 1px solid var(--rule);
  }

  html.nav-js .masthead-nav.is-open { display: block; }

  html.nav-js .nav-toggle { display: inline-flex; }

  .nav-list {
    flex-direction: column;
    gap: 0;
    padding: var(--sp-1) 0 var(--sp-3);
  }

  .nav-list a {
    min-height: 48px;
    padding-inline: 0;
    border-bottom: 0;
    border-top: 1px solid var(--rule);
    font-size: 14px;
  }

  .nav-list a.is-current,
  .nav-list a[aria-current='page'] {
    border-top-color: var(--ink);
    border-bottom-color: transparent;
  }

  .nav-list li:last-child a { border-bottom: 1px solid var(--rule); }

  .nav-panel-cta {
    padding: var(--sp-4) 0 var(--sp-5);
  }
}

/* The mobile panel action exists only inside the opened panel. */
.nav-panel-cta { display: none; }

@media (max-width: 1100px) {
  html.nav-js .nav-panel-cta { display: block; }
}

@media (max-width: 980px) {
  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 860px) {
  :root {
    --section-y: 48px;
    --pad-x: 20px;
    --gutter: 20px;
    --fs-h1: var(--fs-h1-m);
    --fs-h2: var(--fs-h2-m);
    --fs-h3: var(--fs-h3-m);
    --fs-lead: var(--fs-lead-m);
    --fs-data: var(--fs-data-m);
    --fs-figure: var(--fs-figure-m);
  }

  html { scroll-padding-top: 76px; }

  .topbar__meta { display: none; }

  .grid-12 { grid-template-columns: minmax(0, 1fr); }

  .col-3, .col-4, .col-5, .col-6,
  .col-7, .col-8, .col-9, .col-12 { grid-column: span 1; }

  .split,
  .split--media-left,
  .split--form { grid-template-columns: minmax(0, 1fr); }

  .split__text,
  .split--media-left .split__text,
  .split--form .split__text {
    padding-right: 0;
    padding-left: 0;
  }

  .split__media,
  .split--media-left .split__media {
    order: 0;
    min-height: 220px;
    margin-top: var(--sp-6);
    border-left: 0;
    border-right: 0;
    border-top: 1px solid var(--rule);
  }

  .split__aside {
    padding-left: 0;
    margin-top: var(--sp-6);
    border-left: 0;
    border-top: 1px solid var(--rule);
    padding-top: var(--sp-6);
  }

  .requisition__grid { grid-template-columns: minmax(0, 1fr); }

  .requisition__text { padding-right: 0; }

  .requisition__form {
    padding-left: 0;
    margin-top: var(--sp-8);
    border-left: 0;
    border-top: 1px solid var(--rule);
    padding-top: var(--sp-8);
  }

  .form-row { grid-template-columns: minmax(0, 1fr); }

  .card-grid--2,
  .card-grid--3 { grid-template-columns: minmax(0, 1fr); }

  .card-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .icon-strip--3up { grid-template-columns: minmax(0, 1fr); }
  .icon-strip--4up,
  .icon-strip--6up { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .stat-band--2up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-band--3up { grid-template-columns: minmax(0, 1fr); }
  .stat-band--4up { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .stat { padding: var(--sp-5) var(--sp-4); }
  .stat-band--2up .stat:nth-child(odd),
  .stat-band--4up .stat:nth-child(odd) { border-left: 0; }
  .stat-band--2up .stat:nth-child(n + 3),
  .stat-band--4up .stat:nth-child(n + 3) { border-top: 1px solid var(--rule); }
  .stat-band--3up .stat { border-left: 0; }
  .stat-band--3up .stat + .stat { border-top: 1px solid var(--rule); }

  .badge-row { grid-template-columns: minmax(0, 1fr); }

  .datasheet-list--cards--2up,
  .datasheet-list--cards--3up { grid-template-columns: minmax(0, 1fr); }

  .datasheet-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-2);
  }

  .cta-band {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--sp-6);
  }

  .faq--two-column { grid-template-columns: minmax(0, 1fr); }

  .faq__panel { padding-right: var(--sp-6); }

  .footer-grid { grid-template-columns: minmax(0, 1fr); padding-block: var(--sp-10) var(--sp-8); }

  .footer-nav a { min-height: var(--tap); }

  .swatch-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .icon-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .specimen-note { border-left-width: 1px; }

  .breadcrumb a,
  .breadcrumb li { min-height: var(--tap); }

  .link-arrow { min-height: var(--tap); }

  /* A small button is a desktop affordance. On a touch screen every control
     returns to the 44px minimum. */
  .btn--small { min-height: var(--tap); }

  /* Cells stop forcing a single line, so a three-column table can still fit
     inside 375px. Anything wider belongs in .table-scroll. */
  .spec-table thead th,
  .spec-table .num,
  .spec-table .code,
  .data-table-wide thead th,
  .data-table-wide .num,
  .data-table-wide .code { white-space: normal; }

  .spec-table th,
  .spec-table td,
  .data-table-wide th,
  .data-table-wide td { overflow-wrap: anywhere; }

  .prose { max-width: none; }
}

@media (max-width: 640px) {
  .topbar { min-height: 56px; }

  .topbar .btn { display: none; }

  .brand__word { font-size: 15px; }
}

/* A page that cannot load images still shows a ruled, sized container rather
   than a collapsed box. */
.figure img[alt='']:not([src]),
.card__media img:not([src]) { min-height: 1px; }
