/* ===========================================================================
   TACHON SYSTEMS - public site
   ---------------------------------------------------------------------------
   DIRECTION: the site of an industrial automation supplier. Light, structural,
   photographic, calm. The reference class is Beckhoff, SMC, Festo, igus: a
   white ground, one accent used for meaning rather than atmosphere, generous
   measure, and technical data set in a mono face so numbers line up.

   It is not a consumer app landing page, and it is not a terminal. Deliberately
   absent, because each reads as generated rather than designed:
     - black as the page's default ground, and neon glow anywhere
     - AI-purple or multi-hop gradients
     - three identical feature cards in a row
     - section-number eyebrows (01 / 02 / 03) and an eyebrow on every heading
     - em-dashes as a typographic flourish
     - scroll cues, locale and weather strips, version stamps
     - hairline borders on every row of every list

   Present instead: an editorial 12-column grid, real photography slots at fixed
   aspect ratios, one blue, tinted shadows at low elevation, and restrained
   motion that stages a section rather than decorating it.

   TOKENS AND THEME
     - ACCENT is inherited from the product design system (robotHMI/DESIGN.md).
       Signal Blue #3a63e0 for fills and links: 5.2:1 on white, so it passes
       WCAG AA at body size and needs no darker variant to be legible.
       DESIGN.md permits exactly one accent and reserves amber, red and green
       for machine state, so amber appears here on the safety notice only.
     - GROUND is off-white, never #ffffff as the page. Pure white is reserved
       for raised surfaces so elevation reads without a heavy shadow.
     - NEUTRALS keep the documented cool cast. One gray family, no warm grays.
     - TYPE is Archivo (industrial grotesque, tabular figures) with IBM Plex
       Mono for data, labels and code. Both self-hosted, both OFL.
     - SCALE uses the marketing-* steps (13/15/17/20/28/32/40/56). Do not
       invent a size that is not a documented step.
     - RADIUS has exactly two steps and one rule: 4px for anything you can
       click or type into, 8px for anything that contains content. Nothing else.
     - BLACK is chrome and punctuation, not a second theme. The header and the
       footer are dark, and they bracket the page so the light content sits
       inside a frame. Between them a dark band is used only where emphasis is
       earned: the numbers bar under the hero, and one statement per page. Two
       content bands is the ceiling, and everything else stays light, so a band
       reads as a raised voice rather than as the page changing its mind
       halfway down. On any dark surface the accent steps up to DESIGN.md's
       documented dark-substrate blue; that is one accent stated for two
       grounds, not two accents. The exception is a solid button, which keeps
       the light-ground blue because white on the brighter blue is only 3.7:1.
   =========================================================================== */

/* ------------------------------------------------------------------ 0. font */

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

/* ---------------------------------------------------------------- 1. tokens */

:root {
  --font-sans: "Archivo", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: "IBM Plex Mono", "Cascadia Mono", Consolas, ui-monospace, monospace;

  /* Ground. Off-white page, pure white for raised surfaces, two tint steps for
     alternating bands. Elevation is carried by tone first, shadow second. */
  --bg:     #fbfbfc;
  --paper:  #ffffff;
  --tint:   #f2f4f7;
  --tint-2: #e9edf2;

  --ink:   #0f1319;   /* headings        19.0:1 on --bg */
  --ink-2: #49515d;   /* body             8.0:1 on --bg */
  --ink-3: #6b7482;   /* meta, captions   4.6:1 on --bg */

  --line:   #e4e8ee;  /* hairlines between content */
  --line-2: #ccd3dc;  /* stronger separation, figure edges */
  --control-line: #98a1af;  /* 3.0:1 on white, WCAG 1.4.11 for control borders */

  /* One accent. 5.2:1 on white, so it is legal as body-size link text. */
  --accent:      #3a63e0;
  --accent-deep: #2c4bb0;
  --accent-soft: #eef2fd;
  --accent-line: #ccd8f9;

  /* The black bands. Near-black rather than #000, and the same value as --ink,
     so the bands read as the page's own ink turned into a surface rather than
     as a second palette. On these bands the accent steps up to DESIGN.md's
     documented dark-substrate blue: still one accent, stated for two grounds.
     #4f7cff is 4.9:1 on the band, so it stays legal as link text. */
  --band-ink:        #0f1319;
  --on-dark:         #ffffff;
  --on-dark-2:       #b6bcc6;   /*  9.2:1 on the band */
  --on-dark-3:       #8891a0;   /*  5.2:1 on the band */
  --line-on-dark:    #262b31;
  --line-on-dark-2:  #3c424b;
  --accent-on-dark:  #4f7cff;

  /* Hazard. Amber is reserved for machine state by DESIGN.md, so on this
     surface it appears only on the safety notice, and only as a rule and a
     wash. The text inside stays --ink, never amber, so the meaning never
     depends on colour alone. */
  --hazard:      #b8700f;
  --hazard-rule: #e0961f;
  --hazard-bg:   #fdf7ec;
  --hazard-line: #f0dfbd;

  /* Code, GitHub Light. A Python file reads the way an editor shows it. */
  --code-bg:       #f6f8fa;
  --code-fg:       #1f2328;
  --code-comment:  #59636e;
  --code-keyword:  #cf222e;
  --code-function: #8250df;
  --code-string:   #0a3069;
  --code-number:   #0550ae;

  /* Elevation, tinted to the cool neutral. Never pure black. */
  --shadow-sm: 0 1px 2px rgba(15, 19, 25, .04), 0 1px 3px rgba(15, 19, 25, .05);
  --shadow-md: 0 2px 4px rgba(15, 19, 25, .04), 0 8px 24px rgba(15, 19, 25, .07);

  /* For something raised off a dark surface, such as the open mobile menu.
     The two above are tinted with --band-ink itself, so they vanish against
     it. This keeps the same cool cast and simply goes darker than the band. */
  --shadow-dark: 0 12px 24px rgba(3, 5, 8, .5);

  /* Two radii, one rule: 4px for controls, 8px for containers. */
  --r-control: 4px;
  --r-panel:   8px;

  --maxw: 1200px;
  --gut:  24px;

  --ease: cubic-bezier(.16, 1, .3, 1);

  /* Systemic layers only. Nothing else gets a z-index. */
  --z-nav:  20;
  --z-menu: 30;
  --z-skip: 40;

  color-scheme: light;
}

/* -------------------------------------------------------------- 2. baseline */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Column flex so the footer, which is a black band, is pinned to the bottom of
   the viewport on a short page instead of ending mid-screen with light ground
   showing underneath it. */
body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main { flex: 1 0 auto; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; color: var(--ink); text-wrap: balance; }
h1 { font-size: clamp(28px, 3.6vw, 48px); line-height: 1.06; letter-spacing: -.026em; }
h2 { font-size: clamp(28px, 2.9vw, 40px); line-height: 1.12; letter-spacing: -.022em; }
h3 { font-size: 20px;                     line-height: 1.32; letter-spacing: -.012em; }
h4 { font-size: 15px;                     line-height: 1.40; letter-spacing: 0; }
p  { margin: 0; text-wrap: pretty; }
p + p { margin-top: 14px; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 3px; }

strong { font-weight: 600; color: var(--ink); }

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

::selection { background: var(--accent-soft); color: var(--ink); }

.skip {
  position: absolute;
  left: -9999px;
  z-index: var(--z-skip);
  padding: 10px 16px;
  background: var(--accent);
  color: #fff;
  border-radius: var(--r-control);
  font-size: 15px;
  font-weight: 500;
}
.skip:focus { left: 16px; top: 16px; color: #fff; text-decoration: none; }

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gut);
}
.wrap-narrow { max-width: 820px; }

/* Shared text roles. .lede is the one paragraph allowed under a headline. */
.lede { font-size: 20px; color: var(--ink-2); max-width: 62ch; line-height: 1.55; }
.small { font-size: 15px; }

/* An eyebrow is rationed: at most one per three sections on a page, and it
   never carries a number. Most sections do without one entirely. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}

/* ------------------------------------------------------------------ 3. nav */

/* The header is dark chrome. With the footer it brackets the page, so the
   light content sits inside a frame rather than running to the window edge. */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: var(--band-ink);
  border-bottom: 1px solid var(--line-on-dark);
}
.nav > .wrap {
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

/* The logo is artwork, not type. Header and footer both sit on --band-ink,
   so both take the light (white) lockup. The width and height attributes on
   the image element carry the intrinsic ratio, so height alone drives the
   size here and nothing reflows while the file loads. */
.wordmark { display: inline-flex; align-items: center; }
.wordmark img {
  display: block;
  width: auto;
  height: 34px;
}
.wordmark:hover { text-decoration: none; }

.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links a {
  padding: 8px 14px;
  border-radius: var(--r-control);
  font-size: 15px;
  font-weight: 500;
  color: var(--on-dark-2);
  white-space: nowrap;
  transition: color 140ms var(--ease), background-color 140ms var(--ease);
}
.nav-links a:hover {
  color: var(--on-dark);
  background: rgba(255, 255, 255, .07);
  text-decoration: none;
}
.nav-links a[aria-current="page"] { color: var(--on-dark); }


.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line-on-dark-2);
  border-radius: var(--r-control);
  color: var(--on-dark);
  cursor: pointer;
  transition: background-color 140ms var(--ease);
}
.nav-toggle:hover { background: rgba(255, 255, 255, .07); }

@media (max-width: 920px) {
  .nav > .wrap { height: 64px; }
  .nav-toggle { display: inline-flex; }
  .nav-links {
    position: absolute;
    z-index: var(--z-menu);
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 12px var(--gut) 20px;
    background: var(--band-ink);
    border-bottom: 1px solid var(--line-on-dark);
    box-shadow: var(--shadow-dark);
  }
  .nav-links a { padding: 12px 14px; font-size: 17px; }
  .nav-links .btn { margin: 8px 0 0; justify-content: center; }
  .nav-links[hidden] { display: none; }
}

/* --------------------------------------------------------------- 4. buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  white-space: nowrap;
  padding: 12px 22px;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 160ms var(--ease), border-color 160ms var(--ease),
              color 160ms var(--ease), transform 90ms var(--ease),
              box-shadow 160ms var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }

.btn-primary { background: var(--accent); color: #fff; box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--accent-deep); color: #fff; }
.btn-primary[disabled] { opacity: .6; cursor: progress; transform: none; }

.btn-quiet {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--line-2);
  box-shadow: var(--shadow-sm);
}
.btn-quiet:hover { background: var(--tint); color: var(--ink); border-color: var(--control-line); }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* -------------------------------------------------------------- 5. sections */

.band { padding: clamp(56px, 7vw, 96px) 0; }
.band-tint { background: var(--tint); }
.band-tight { padding: clamp(40px, 5vw, 64px) 0; }

/* ---- black bands -------------------------------------------------------- */

/* Used as punctuation, not as a theme: the numbers bar, one statement band per
   page, and the footer. Everything between them stays on the light ground, so
   a band reads as emphasis rather than as the page changing its mind. Two per
   page plus the footer is the ceiling. */
.band-dark {
  background: var(--band-ink);
  color: var(--on-dark-2);
}
.band-dark h1,
.band-dark h2,
.band-dark h3,
.band-dark h4,
.band-dark strong { color: var(--on-dark); }
.band-dark p,
.band-dark li,
.band-dark .lede { color: var(--on-dark-2); }
.band-dark .eyebrow { color: var(--accent-on-dark); }
.band-dark a { color: var(--accent-on-dark); }
.band-dark a:hover { color: var(--on-dark); }
.band-dark .kicker,
.band-dark .small,
.band-dark figcaption { color: var(--on-dark-3); }

/* The numbers bar. Rules between the figures, nothing around them. */
.band-dark .metrics > div { border-left-color: var(--line-on-dark-2); }
.band-dark .metric-n { color: var(--on-dark); }
.band-dark .metric-l { color: var(--on-dark-2); }

.band-dark .col li::before { background: var(--accent-on-dark); }
.band-dark .col h3 { border-bottom-color: var(--line-on-dark-2); }

/* Spec cards on a band lose their fill and keep only their outline, so the
   band stays one surface instead of becoming a tray of white tiles. */
.band-dark .spec > div {
  background: transparent;
  border-color: var(--line-on-dark);
}
.band-dark .spec dt { color: var(--on-dark-3); }
.band-dark .spec dd { color: var(--on-dark-2); }
.band-dark .spec dd strong { color: var(--on-dark); }
.band-dark .spec-group > h3 { border-bottom-color: var(--line-on-dark-2); }

/* Buttons keep their shapes. The solid one keeps the light-ground blue so the
   primary action looks identical everywhere; the quiet one inverts. */
.band-dark .btn-quiet {
  background: transparent;
  color: var(--on-dark);
  border-color: var(--line-on-dark-2);
  box-shadow: none;
}
.band-dark .btn-quiet:hover {
  background: rgba(255, 255, 255, .07);
  color: var(--on-dark);
  border-color: var(--on-dark-3);
}

/* A statement band: one sentence, set large, with room around it. The measure
   is set on the sentence, not on the wrap, so the band's left edge stays on the
   same grid line as every other section. */
.statement { padding: clamp(56px, 8vw, 104px) 0; }
.statement p {
  max-width: 900px;
  font-size: clamp(20px, 2.6vw, 32px);
  line-height: 1.32;
  letter-spacing: -.02em;
  color: var(--on-dark);
  text-wrap: balance;
}

.band-head { max-width: 62ch; margin-bottom: clamp(32px, 4vw, 48px); }
.band-head .lede { margin-top: 16px; }

/* ------------------------------------------------------------------ 6. hero */

.hero { padding: clamp(40px, 5vw, 72px) 0 clamp(48px, 6vw, 80px); }
.hero > .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6.5fr) minmax(0, 5.5fr);
  gap: clamp(32px, 5vw, 56px);
  align-items: center;
}
/* The headline is capped at the 40px step and left to wrap on its own, because
   a forced <br> plus a 48px setting pushed it to three lines in this column.
   text-wrap: balance then evens the two lines. */
.hero-copy { max-width: 52ch; }
.hero-copy h1 { font-size: clamp(28px, 3.2vw, 40px); margin-bottom: 20px; }
.hero-copy .lede { margin-bottom: 28px; max-width: 46ch; }

@media (max-width: 900px) {
  .hero > .wrap { grid-template-columns: minmax(0, 1fr); }
  .hero-copy { max-width: none; }
  .hero .figure { max-width: 340px; }
}

/* The interior pages open with a header rather than a hero: no asset, no CTA
   pair, just the one sentence that says what the page is for. */
.page-head {
  padding: clamp(44px, 6vw, 76px) 0 clamp(36px, 4vw, 56px);
  border-bottom: 1px solid var(--line);
}
/* The wrap stays at the page container width so the header's left edge lines
   up with the content below it. The headline is measured instead, which is
   what actually needed constraining. */
.page-head h1 { max-width: 900px; }
.page-head .lede { margin-top: 20px; }

/* --------------------------------------------------------------- 7. figures */

/* Every figure is a real photograph slot at a fixed ratio. Until the photograph
   exists the slot is a plain tinted panel naming the shot it is waiting for, so
   the page is honest about what is missing rather than dressing the gap up with
   a gradient or a decorative blueprint grid. */
.figure {
  margin: 0;
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.figure img, .figure video {
  display: block;
  width: 100%;
  height: auto;
}

/* The hero clip is 4:5, because the phone shot it upright and everything below
   the work surface is bare desk. So the panel hugs the clip and sits centred in
   its column instead of stretching the full grid track. */
.hero .figure { max-width: 460px; margin-inline: auto; }

/* It autoplays and loops for longer than five seconds, which WCAG 2.2.2 says
   needs a way to stop it. The control sits on the clip, dark enough to hold
   white over any frame in it. */
.figure-demo { position: relative; }
.vid-toggle {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: var(--r-control);
  background: rgba(15, 19, 25, .72);
  color: #fff;
  cursor: pointer;
  transition: background .15s var(--ease);
}
.vid-toggle:hover { background: rgba(15, 19, 25, .92); }
.vid-toggle svg { display: block; }
.figure-demo[data-playing="true"] .i-play,
.figure-demo[data-playing="false"] .i-pause { display: none; }
.figure-slot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  aspect-ratio: 16 / 9;
  padding: 24px;
  text-align: center;
  background: var(--tint);
  color: var(--ink-3);
}
.figure-slot[data-ratio="4-3"] { aspect-ratio: 4 / 3; }
.figure-slot[data-ratio="3-2"] { aspect-ratio: 3 / 2; }
.figure-slot .cap {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.figure-slot small { font-size: 13px; max-width: 34ch; line-height: 1.5; }
.figure figcaption {
  padding: 14px 18px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-3);
}

/* --------------------------------------------------------------- 8. metrics */

/* Four numbers across a tinted band. Vertical rules between, not a border on
   every row. Mono with tabular figures so the digits align optically. */
.metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.metrics > div { padding: 4px clamp(16px, 2.4vw, 32px); border-left: 1px solid var(--line-2); }
.metrics > div:first-child { padding-left: 0; border-left: none; }
.metric-n {
  font-family: var(--font-mono);
  font-size: clamp(28px, 2.6vw, 32px);
  font-weight: 500;
  letter-spacing: -.02em;
  color: var(--ink);
  font-feature-settings: "tnum";
  line-height: 1.1;
}
.metric-l { margin-top: 8px; font-size: 15px; color: var(--ink-2); line-height: 1.45; }

@media (max-width: 860px) {
  .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 0; }
  .metrics > div:nth-child(odd) { padding-left: 0; border-left: none; }
}
@media (max-width: 460px) {
  .metrics { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .metrics > div { padding-left: 0; border-left: none; }
}

/* ---------------------------------------------------------------- 9. panels */

/* Asymmetric, never three identical columns: one lead panel carrying a
   photograph, and a stack of two beside it. */
.lead-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 20px;
  align-items: start;
}
.lead-stack { display: grid; gap: 20px; }

.panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: clamp(22px, 2.6vw, 30px);
  box-shadow: var(--shadow-sm);
}
.panel h3 { margin-bottom: 10px; }
.panel p { color: var(--ink-2); }
.panel-lead { padding: 0; overflow: hidden; }
.panel-lead .panel-body { padding: clamp(22px, 2.6vw, 30px); }
.panel-lead .figure-slot { border-bottom: 1px solid var(--line); }

.kicker {
  display: block;
  margin-bottom: 12px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

@media (max-width: 900px) { .lead-grid { grid-template-columns: minmax(0, 1fr); } }

/* --------------------------------------------------------------- 11. bento */

/* Exactly as many cells as there is content for, with real visual variation:
   one cell carries a diagram, one carries code, two carry prose. */
/* Cells hug their content rather than stretching to the tallest in the row.
   Forcing equal heights left a large dead area inside the taller-row partner
   whenever one cell carried a diagram and the other did not. */
.bento {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 20px;
  align-items: start;
}
.cell {
  --cell-pad: clamp(22px, 2.6vw, 30px);
  grid-column: span 6;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: var(--cell-pad);
  box-shadow: var(--shadow-sm);
}
.cell h3 { margin-bottom: 10px; }
.cell p { color: var(--ink-2); }
.cell-lead  { grid-column: span 7; }
.cell-side  { grid-column: span 5; }
.cell-tint { background: var(--accent-soft); border-color: var(--accent-line); box-shadow: none; }

/* A cell whose content sets its own padding, such as the code block. */
.cell-flush { padding: 0; overflow: hidden; }

.diagram { display: block; width: 100%; height: auto; margin: 20px 0 4px; }

@media (max-width: 900px) {
  .bento { grid-template-columns: minmax(0, 1fr); }
  .cell, .cell-lead, .cell-side { grid-column: auto; }
}

/* ----------------------------------------------------------------- 12. code */

.code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-3);
}
.code {
  margin: 0;
  padding: 20px 18px;
  background: var(--code-bg);
  color: var(--code-fg);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.7;
  white-space: pre;
  overflow-x: auto;
  tab-size: 4;
  flex: 1;
}
.code b  { color: var(--code-keyword);  font-weight: 400; }
.code i  { color: var(--code-function); font-style: normal; }
.code u  { color: var(--code-string);   text-decoration: none; }
.code em { color: var(--code-number);   font-style: normal; }
.code q  { color: var(--code-comment); }
.code q::before, .code q::after { content: none; }

/* -------------------------------------------------------------- 13. columns */

.cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 44px);
}
.col h3 { margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--line-2); }
.col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.col li { position: relative; padding-left: 22px; color: var(--ink-2); font-size: 17px; }
.col li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 10px;
  height: 2px;
  background: var(--accent);
}

@media (max-width: 800px) {
  .cols { grid-template-columns: minmax(0, 1fr); gap: 32px; }
}

/* -------------------------------------------------------- 14. spec, grouped */

/* Specifications are grouped into a small number of clusters and set as cards.
   Never a long table with a hairline under every row. */
.spec-group + .spec-group { margin-top: 36px; }
.spec-group > h3 {
  margin-bottom: 18px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line-2);
}
.spec {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin: 0;
}
.spec > div {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: 20px 22px;
}
/* No uppercase transform here. These labels carry SI units, and uppercasing
   turns "200 kHz" into "200 KHZ", which is wrong in front of this audience. */
.spec dt {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--ink-3);
  margin-bottom: 8px;
}
.spec dd { margin: 0; color: var(--ink-2); font-size: 17px; }
.spec dd strong { color: var(--ink); }

/* The caveat that closes a spec block, or a notice that follows a grid. */
.note-after { margin-top: 28px; max-width: 70ch; }

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

/* --------------------------------------------------------------- 15. notice */

.notice {
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--r-panel);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.notice-head {
  padding: 12px 24px;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.notice-body { padding: clamp(24px, 3vw, 34px); }
.notice-body h3 { margin-bottom: 14px; }
.notice-body p { color: var(--ink-2); }

/* Hazard is the one place amber appears. It is carried by a solid header band,
   which is how a real machinery safety label is built, rather than by a thin
   accent stripe down one edge of a card. The body text stays ink, so the
   warning never depends on colour to be read. Ink on the band is 7.4:1. */
.notice-hazard {
  background: var(--hazard-bg);
  border-color: var(--hazard-line);
}
.notice-hazard .notice-head {
  background: var(--hazard-rule);
  border-bottom-color: var(--hazard-rule);
  color: var(--ink);
  font-weight: 600;
  letter-spacing: .1em;
}

/* ---------------------------------------------------------------- 16. chain */

/* The host-to-controller chain on the technology page. Three stages, with the
   link protocol named on the rule between them. */
.chain {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: stretch;
  gap: 12px;
}
.chain-node {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: 22px;
  box-shadow: var(--shadow-sm);
}
.chain-node:last-child {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  box-shadow: none;
}
.chain-node h4 { margin-bottom: 6px; font-size: 17px; font-weight: 600; }
.chain-node p { font-size: 15px; color: var(--ink-2); }
.chain-link {
  align-self: center;
  min-width: 76px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-3);
  white-space: nowrap;
  text-align: center;
}
.chain-link::before {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  margin-bottom: 8px;
  background: var(--line-2);
}

@media (max-width: 900px) {
  .chain { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .chain-link { text-align: left; }
  .chain-link::before { width: 28px; }
}

/* --------------------------------------------------------------- 17. closer */

.closer {
  padding: clamp(56px, 7vw, 88px) 0;
  background: var(--tint);
  border-top: 1px solid var(--line);
}
.closer .wrap { max-width: 720px; text-align: center; }
.closer .lede { margin: 16px auto 28px; }
.closer .btn-row { justify-content: center; }

/* --------------------------------------------------------------- 19. footer */

/* The footer is the last black band. It closes the page the way the numbers
   bar opened it, so the two dark surfaces bracket the light content. */
.foot {
  background: var(--band-ink);
  color: var(--on-dark-2);
  padding: clamp(44px, 5vw, 60px) 0 36px;
}
.foot .wordmark img { height: 38px; }
.foot-top {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 3fr) minmax(0, 3fr);
  gap: clamp(28px, 4vw, 48px);
  padding-bottom: 32px;
}
.foot-top > div:first-child { max-width: 42ch; }
.foot-top > div:first-child p { margin-top: 14px; font-size: 15px; color: var(--on-dark-2); }
.foot h4 {
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-dark-3);
}
.foot nav { display: grid; gap: 10px; }
.foot nav a { font-size: 15px; color: var(--on-dark-2); }
.foot nav a:hover { color: var(--on-dark); }
.foot-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  justify-content: space-between;
  align-items: center;
  padding-top: 24px;
  border-top: 1px solid var(--line-on-dark);
  font-size: 13px;
  color: var(--on-dark-3);
}
/* On 404 there is no link block above it, so it needs no separating rule. */
.foot-bottom:first-child { padding-top: 0; border-top: none; }

@media (max-width: 760px) {
  .foot-top { grid-template-columns: 1fr 1fr; }
  .foot-top > div:first-child { grid-column: span 2; }
}

/* ------------------------------------------------------------------ 20. 404 */

.gone { padding: clamp(72px, 12vw, 140px) 0; }
.gone .wrap { max-width: 620px; }
.gone .code-n {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 16px;
}
.gone p { margin: 16px 0 28px; }

/* --------------------------------------------------------------- 21. motion */

/* One motion idea: a section resolves as it arrives, so the eye lands on the
   headline before the detail under it. Transform and opacity only. The hero is
   never revealed, because it is already on screen when the page loads. */
.reveal { opacity: 0; transform: translateY(14px); }
.reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.in { opacity: 1; transform: none; transition: none; }
  .btn:active { transform: none; }
}

/* ---------------------------------------------------------------- 22. print */

@media print {
  .nav, .skip, .closer, .btn { display: none; }
  body { background: var(--paper); color: var(--ink); font-size: 11pt; }
  .reveal { opacity: 1; transform: none; }
  .panel, .cell, .figure, .notice { box-shadow: none; }
}
