/*
  site/assets/css/site.css -- every style for the DevBuildZero site.

  Composite home page: mission-control's palette, type, and backgrounds,
  with What we do and Radiation effects from prime and Recent work from
  sidebar.

  The sections came from three designs, so everything shared is a token
  and every section reads the same ones. A section that sets its own size,
  margin, or accent color is the seam showing again.

  Invariants a later editor must keep:
  - Type sizes come ONLY from the --t-* tokens (seven). Readout numerals
    are Plex Mono at --t-num or --t-h2, everything else is Plex Sans.
  - Spacing comes ONLY from the --s-* 8px scale.
  - Amber appears in three places only: the brand (logo mark, the hero's
    "development build zero"), primary actions (buttons), and data marks
    (readout bars, the beam spot). No amber on borders, bullets, labels,
    or numbering.
  - Blue is links and focus only.
  - Section backgrounds are one of .bg-grid, .bg-light, .bg-dark, and no
    two adjacent sections share one.
  - None of the owners' machine-page tells: no NN / LABEL decorators, no
    uppercase tracked mono labels, no status bar, no pills, no corner
    brackets outside the beam illustration, no glowing dots, no index
    labels on readouts, no frosted nav.
  - The two animations are namespaced, circuit classes as c2-* and its
    keyframes as c2-k-*, rad ids as r3-*. A bare class or id added to
    either collides with the page's own rules.
  - The rad title is the one sanctioned exception to the tracked-caps
    rule, approved by the owners in the R3 v3 review.
  These were checked during mockup review by a scratch script (uppercase,
  tracking, radius, font-size, and amber-usage sweeps) that did NOT ship.
  No gate in this repo checks them yet. scripts/check_site.py and
  tests/test_site.py (Phase 2 of .plans/deploy-redesign.md) cover assets,
  copy, nav offsets, motion, and the form, not these style rules.
*/

/* --- fonts --- */
/* Self-hosted rather than Google Fonts: a third-party font request is one
   that lab and prime proxies sometimes block, and it hands visitor IPs to
   a third party.
   Sans is IBM's variable build, one file for 400/500/600. The static
   IBMPlexSans-Regular/Medium/SemiBold cuts were tried first (197 KB for
   three files) and rasterized differently from the Google-served face the
   mockup was approved on: 1.2% of pixels at 1440 differed on text edges,
   against 25 pixels with this file. Google serves the same variable
   outlines, so this is the face the owners signed off on.
   "complete" builds, not IBM's unicode-range "split" set, so a glyph
   outside Latin-1 cannot silently fall back to Helvetica. Weights are the
   ones the page sets: Sans 400/500/600, Mono 400/500. No italics, since
   the hero's em is font-style: normal. A Mono weight added here without a
   rule using it is a download for nothing, and a rule using an absent
   Mono weight gets a synthesized one.
   Sources (SIL OFL 1.1, license in assets/fonts/LICENSE.txt):
   https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-sans-variable%400.2.0/plex-sans-variable.zip
     fonts/complete/woff2/IBM Plex Sans Var-Roman.woff2
   https://github.com/IBM/plex/releases/download/%40ibm%2Fplex-mono%402.5.0/ibm-plex-mono.zip
     ibm-plex-mono/fonts/complete/woff2/IBMPlexMono-{Regular,Medium}.woff2 */
@font-face {
  font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/IBMPlexSansVar-Roman.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("../fonts/IBMPlexMono-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("../fonts/IBMPlexMono-Medium.woff2") format("woff2");
}

:root {
  --bg: #070c13;
  --bg-2: #0a111c;
  --panel: #0d1624;
  --panel-2: #111c2d;
  --line: rgba(142, 169, 232, 0.16);
  --line-strong: rgba(142, 169, 232, 0.32);
  --grid: rgba(142, 169, 232, 0.05);
  --fg: #e8edf4;
  --fg-2: #b4c0d2;
  --fg-3: #8b9ab0;
  --signal: #e8a33d;
  --signal-hi: #f2b457;
  --link: #7dbdff;
  --sans: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* --- type scale, seven sizes --- */
  --t-display: clamp(36px, 4.6vw, 60px);
  --t-num: clamp(44px, 4.4vw, 60px);
  --t-h2: clamp(30px, 3.4vw, 42px);
  --t-h3: 21px;
  --t-lede: 20px;
  --t-body: 18px;
  --t-small: 16px;

  /* --- spacing, 8px scale --- */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 32px;
  --s-6: 48px;
  --s-8: 64px;
  --s-12: 96px;

  --wrap: 1240px;
  --gutter: clamp(16px, 4vw, 48px);
  --nav-h: 72px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
a { color: var(--link); text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.mono { font-family: var(--mono); }
h1, h2, h3 { font-weight: 600; letter-spacing: -0.01em; line-height: 1.15; margin: 0; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.3; }
p { margin: 0 0 var(--s-2); }
p:last-child { margin-bottom: 0; }
.lede { font-size: var(--t-lede); color: var(--fg-2); max-width: 46em; }
.sub { color: var(--fg-2); }
/* Keeps a hyphenated figure such as 64-bit on one line. */
.nb { white-space: nowrap; }
/* The section's key claim. Body face at lede size and 600 weight in --fg,
   so it outranks the lede without competing with the h2. */
.claim { font-size: var(--t-lede); font-weight: 600; color: var(--fg); max-width: 40em; margin-top: var(--s-3); }

/* --- section backgrounds and the one heading treatment --- */
section { border-bottom: 1px solid var(--line); }
.sec { padding: var(--s-12) 0; }
.bg-dark { background: var(--bg); }
.bg-light { background: var(--bg-2); }
.bg-grid {
  background-color: var(--bg);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 32px 32px;
}
.head { margin-bottom: var(--s-6); max-width: 50em; }
.head h2 { margin-bottom: var(--s-2); }

/* --- buttons --- */
.btn {
  display: inline-block; font-family: var(--sans); font-size: var(--t-small);
  font-weight: 600; text-decoration: none; padding: var(--s-2) var(--s-3);
  border-radius: 3px; border: 0; cursor: pointer; line-height: 1.2;
}
.btn.primary { background: var(--signal); color: #120c02; }
.btn.primary:hover { background: var(--signal-hi); }
.btn.ghost { color: var(--fg); box-shadow: inset 0 0 0 1px var(--line-strong); }
.btn.ghost:hover { box-shadow: inset 0 0 0 1px var(--fg-3); }

/* --- nav --- */
/* Opaque rather than mission-control's backdrop blur. A frosted header is
   on the owners' banned list (recorded in prime.html). */
/* The header box itself is --nav-h tall with its border INSIDE it, and the
   wrap fills what is left. html scroll-padding-top reads the same property,
   so an anchor target lands exactly at the nav's bottom edge. Sizing the
   wrap to --nav-h instead put the 1px border outside it, and every target
   landed 1px under the nav. */
header.nav {
  position: sticky; top: 0; z-index: 10; height: var(--nav-h);
  background: rgba(7, 12, 19, 0.97);
  border-bottom: 1px solid var(--line);
}
header.nav .wrap {
  display: flex; align-items: center; justify-content: space-between;
  height: 100%;
}
.brand {
  display: flex; align-items: center; gap: var(--s-2);
  flex-shrink: 0; margin-right: var(--s-3); text-decoration: none;
}
/* The mark is the owners' logo, devbuildzero_dark_transparent.png, 906x625
   with a transparent ground. Height sets the size and the width follows the
   aspect. Explicit width and height attributes hold the box open if the
   file fails to load. */
.brand .mark { height: 48px; width: auto; }
nav.links { display: flex; align-items: center; gap: var(--s-1); }
nav.links a {
  font-size: var(--t-small); color: var(--fg-2); text-decoration: none;
  padding: var(--s-1) 10px; border-radius: 3px; white-space: nowrap;
}
nav.links a:hover { color: var(--fg); background: var(--panel-2); }
.menu-btn {
  display: none; font: 500 var(--t-small)/1 var(--sans); color: var(--fg);
  background: none; border: 1px solid var(--line-strong); border-radius: 3px;
  padding: 10px 14px; cursor: pointer;
}

/* --- hero --- */
.hero { padding: var(--s-12) 0; overflow: hidden; }
.hero .wrap {
  display: grid; grid-template-columns: 1.15fr 0.85fr; gap: var(--s-8);
  align-items: center;
}
.hero .tag {
  font-size: var(--t-display); font-weight: 600; line-height: 1.08;
  letter-spacing: -0.02em; margin: 0 0 var(--s-4);
}
.hero .tag em {
  font-style: normal; color: var(--signal); font-family: var(--mono);
  font-weight: 500; letter-spacing: -0.03em;
}
.hero .cta { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
/* Capped at 453px, half the 906px source width, so a 2x display still
   gets one source pixel per device pixel. Wider would upscale the pixel
   lettering and blur its edges. */
.hero .mark-lg { justify-self: center; width: min(100%, 453px); height: auto; }

/* --- customers strip --- */
.strip { padding: var(--s-4) 0; }
.strip p { color: var(--fg-2); margin-bottom: var(--s-2); }
/* Separate boxes on the .devices gap (16px, 12px at 600px and under) and
   its column steps below 900px, at the owners' request. The v8 strip was
   one bordered bar with shared dividers. With a gap, a shared divider
   would leave a stray line in the gutter, so each box carries its own. */
.cells {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-2);
}
.cells div {
  padding: var(--s-2) var(--s-3); border: 1px solid var(--line);
  font-weight: 500;
}

/* --- what we do (from prime) --- */
.intro-2 {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-8);
  align-items: center;
}
.intro-2 .head { margin-bottom: 0; }
/* Every image slot (circuit, beam scene, team photo) shares one frame,
   1px --line-strong, so the three read as one system. */
.photo { aspect-ratio: 4 / 3; overflow: hidden; background: var(--panel); border: 1px solid var(--line-strong); }
.photo img { width: 100%; height: 100%; object-fit: cover; }
.list-2 {
  display: grid; grid-template-columns: 1fr 1fr;
  column-gap: var(--s-8); row-gap: var(--s-6);
  margin: var(--s-8) 0 0; padding: 0; list-style: none;
}
.list-2 li { padding-top: var(--s-3); border-top: 1px solid var(--line-strong); }
.list-2 h3 { margin-bottom: var(--s-1); }
.list-2 p { color: var(--fg-2); max-width: 34em; }

/* --- radiation effects (prime's structure) --- */
.rad-body {
  display: grid; grid-template-columns: 5fr 7fr; gap: var(--s-8);
  align-items: start;
}
.rad-body .scope { border: 1px solid var(--line-strong); }
.steps { list-style: none; margin: var(--s-2) 0 0; padding: 0; }
.steps li {
  display: grid; grid-template-columns: 11em 1fr; gap: var(--s-4);
  padding: var(--s-3) 0; border-top: 1px solid var(--line);
}
.steps li:last-child { border-bottom: 1px solid var(--line); }
.steps p { color: var(--fg-2); }
.inbeam { margin-top: var(--s-8); }
.inbeam h3 { margin-bottom: var(--s-2); }
/* Square boxes, NOT the rounded chips mission-control used. The owners
   ruled pills out as a tell but found boxes caught the eye better than
   prime's run-on sentence. Text stays verbatim from the copy file, and
   ::first-letter capitalizes it for display, which is why the box is a
   block and NOT a flex container (::first-letter skips flex boxes). */
.devices {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-2);
  list-style: none; margin: var(--s-2) 0 var(--s-3); padding: 0;
}
.devices li {
  border: 1px solid var(--line-strong); background: var(--panel);
  padding: var(--s-2) var(--s-3); font-weight: 500; line-height: 1.4;
  min-height: 80px;
}
.devices li::first-letter { text-transform: uppercase; }

/* --- time-to-beam readout --- */
.ttb { margin-top: var(--s-8); border: 1px solid var(--line); background: var(--panel); }
.ttb-cap { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); margin: 0; color: var(--fg-2); }
.row {
  display: grid; grid-template-columns: 1.2fr 1.6fr 240px; gap: var(--s-4);
  align-items: center; padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--line);
}
.row.colhead { padding-top: var(--s-2); padding-bottom: var(--s-2); color: var(--fg-3); font-size: var(--t-small); }
.row.colhead span:last-child { text-align: right; }
.row .name { font-weight: 500; }
.row .val {
  font-family: var(--mono); font-size: var(--t-h2); font-weight: 500;
  letter-spacing: -0.02em; text-align: right; line-height: 1; white-space: nowrap;
}
.row .val span { font-size: var(--t-body); color: var(--fg-3); letter-spacing: 0; margin-left: var(--s-1); font-weight: 400; }
/* Bar scale is 28 days = full track, so widths are days / 28:
   3 d = 10.7%, 14 d = 50%, 21 d = 75%, 28 d = 100%. No axis and no week
   ticks, by owner decision, since every row prints its value. The shared
   track outline is what keeps the bars reading as one scale. */
.track { position: relative; height: 12px; border: 1px solid var(--line); }
.row:last-child { border-bottom: 0; }
.track i { position: absolute; top: 2px; bottom: 2px; left: 0; background: var(--signal); }

/* --- recent work (from sidebar) --- */
.work { list-style: none; margin: 0; padding: 0; border-bottom: 1px solid var(--line); }
.work li {
  display: grid; grid-template-columns: 220px minmax(0, 46em); gap: var(--s-4);
  padding: var(--s-4) 0; border-top: 1px solid var(--line);
}
.fig .n {
  display: block; font-family: var(--mono); font-size: var(--t-num);
  font-weight: 500; line-height: 1; letter-spacing: -0.03em;
}
.fig .u { display: block; margin-top: var(--s-1); font-family: var(--mono); color: var(--fg-3); line-height: 1.35; }
/* Balanced so a two-line title on phone splits evenly instead of
   leaving one word, such as orbit. or kit., alone on the second line. */
.work h3 { margin-bottom: var(--s-1); text-wrap: balance; }
.work p { color: var(--fg-2); }

/* --- how we work --- */
.principles { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-4); }
.principle .num {
  font-family: var(--mono); font-size: var(--t-h2); font-weight: 500;
  color: var(--fg-3); line-height: 1; margin-bottom: var(--s-2);
}
.principle h3 { margin-bottom: var(--s-1); }
.principle p { color: var(--fg-2); }

/* --- team --- */
/* Bio, photo, bio in DOM order so the stack is Hunter, photo, Willie with
   no reordering. The tracks must NOT be plain 1fr. A 1fr track is
   minmax(auto, 1fr), so it cannot shrink below its content's min-content,
   and a broken img contributes its 1335px width attribute as min-content.
   With the photo missing that grid measured 132px / 1334px / 115px and
   pushed Willie off the page. The middle track floors at 0, and at 1.25fr
   of 3.25 it stays near 38% of the row, under half. The bios floor at a
   readable 16em. */
.team {
  display: grid; gap: var(--s-6); align-items: start;
  grid-template-columns: minmax(16em, 1fr) minmax(0, 1.25fr) minmax(16em, 1fr);
}
.bio h3 { margin-bottom: 2px; }
.bio .role { color: var(--fg-3); margin-bottom: var(--s-2); }
.bio p.text { color: var(--fg-2); }
.team figure { margin: 0; min-width: 0; }
/* Explicit ratio so the box keeps its shape with or without the file.
   4:5 crops the 4:3 frame to the founders, who stand left of center. */
.team figure img {
  display: block; width: 100%; max-width: 100%; height: auto;
  aspect-ratio: 4 / 5; object-fit: cover; object-position: 30% 50%;
  background: var(--panel); border: 1px solid var(--line-strong);
  color: var(--fg-3); font-size: var(--t-small);
}
.team figcaption { margin-top: var(--s-1); font-size: var(--t-small); color: var(--fg-3); }

/* --- doing business --- */
.biz { display: grid; grid-template-columns: 1fr 1.5fr; gap: var(--s-6); }
.claims { font-size: var(--t-h3); font-weight: 500; margin-bottom: var(--s-3); }
.claims span { display: block; padding: 12px 0; border-bottom: 1px solid var(--line); }
dl.kv { margin: 0; border: 1px solid var(--line); background: var(--panel); }
dl.kv > div {
  display: grid; grid-template-columns: 120px 1fr; gap: var(--s-3);
  padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line);
}
dl.kv > div:last-child { border-bottom: 0; }
dl.kv dt { font-family: var(--mono); color: var(--fg-3); }
dl.kv dd { margin: 0; color: var(--fg-2); }
dl.kv dd.code { font-family: var(--mono); font-size: var(--t-h3); color: var(--fg); }
dl.kv dd .n { font-family: var(--mono); color: var(--fg); }

/* --- contact --- */
.contact { display: grid; grid-template-columns: 1fr 1.2fr; gap: var(--s-8); }
.lines { margin-top: var(--s-4); border-top: 1px solid var(--line); }
.lines div {
  display: grid; grid-template-columns: 90px 1fr; gap: var(--s-2);
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.lines .k { color: var(--fg-3); }
form {
  border: 1px solid var(--line); background: var(--panel); padding: var(--s-4);
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3);
}
form .full { grid-column: 1 / -1; }
form label span { display: block; margin-bottom: var(--s-1); font-size: var(--t-small); color: var(--fg-2); font-weight: 500; }
input, textarea {
  width: 100%; font: inherit; color: var(--fg); background: var(--bg);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 12px 14px;
}
textarea { min-height: 150px; resize: vertical; }
input:focus, textarea:focus { outline: 2px solid var(--link); outline-offset: 0; border-color: transparent; }
form .btn { justify-self: start; }
/* Formspree's _gotcha honeypot. display: none rather than off-screen
   positioning, so it takes no grid cell and the layout matches v8. Bots
   that fill every input still fill it, which is all it needs. */
form .hp { display: none; }

footer { padding: var(--s-4) 0 var(--s-6); }
footer .wrap { display: flex; justify-content: space-between; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
footer img { height: 20px; width: auto; }
footer span { font-size: var(--t-small); color: var(--fg-3); }

/* --- what we do animation (circuit-2-v3) --- */
/* Same box as the PCB photo it replaced, so the .photo rule carries the
   4:3 ratio, --panel fill, and --line border. */
.photo svg { display: block; width: 100%; height: 100%; }
.photo { --c2-loop: 12s; }
/* --- board --- */
.c2-board { fill: var(--panel-2); stroke: var(--line-strong); stroke-width: 1; }
.c2-hole { fill: var(--bg); }
.c2-ring { fill: none; stroke: var(--fg-3); stroke-opacity: .45; stroke-width: 2; }
.c2-tr { fill: none; stroke: var(--line-strong); stroke-linejoin: round; }
.c2-tr2 { fill: none; stroke: var(--line); stroke-width: 1.4; stroke-linejoin: round; }
.c2-body { fill: var(--bg); stroke: var(--line-strong); stroke-width: 1; }
.c2-pad { fill: var(--fg-3); fill-opacity: .5; }
.c2-padl { fill: var(--fg-3); fill-opacity: .22; }
.c2-ep { fill: var(--fg-3); fill-opacity: .18; }
.ball { fill: var(--fg-3); fill-opacity: .28; }
.c2-pbody { fill: var(--bg-2); }
.c2-pin1 { fill: var(--fg-3); fill-opacity: .6; }
.pin1m { fill: var(--fg-3); fill-opacity: .45; }
.c2-silko { fill: none; stroke: var(--fg-3); stroke-opacity: .3; stroke-width: 1; }
.c2-keep { fill: none; stroke: var(--fg-3); stroke-opacity: .3; stroke-width: 1; stroke-dasharray: 3 3; }
.c2-via { fill: var(--panel-2); stroke: var(--fg-3); stroke-opacity: .45; stroke-width: 1.6; }
.c2-lbl { fill: var(--fg-2); font-family: var(--sans); font-size: 20px; font-weight: 500; }
.c2-big { fill: var(--bg); stroke: var(--line-strong); }

/* --- data --- */
/* Opacity under 1 keeps the trains ambient beside the adjacent copy. The
   bus trains are dimmer again because 24 of them sit side by side. */
.c2-q { fill: none; stroke: var(--signal); stroke-linecap: butt; stroke-linejoin: round; }
.c2-bus { stroke-opacity: .55; }
.c2-b0 { stroke-dasharray: 2 4; }
.c2-b1 { stroke-dasharray: 3 5; }
.c2-b2 { stroke-dasharray: 4 8; }
.c2-b3 { stroke-dasharray: 3 7; }
.c2-ser { stroke-dasharray: 5 13; stroke-opacity: .8; }
.c2-out { stroke-dasharray: 5 19; stroke-opacity: .85; }
@keyframes c2-k-b0 { to { stroke-dashoffset: -48; } }
@keyframes c2-k-b1 { to { stroke-dashoffset: -80; } }
@keyframes c2-k-b2 { to { stroke-dashoffset: -132; } }
@keyframes c2-k-b3 { to { stroke-dashoffset: -100; } }
@keyframes c2-k-ser { to { stroke-dashoffset: -180; } }
@keyframes c2-k-out { to { stroke-dashoffset: -312; } }
@media (prefers-reduced-motion: no-preference) {
  .c2-q {
    animation-duration: var(--c2-loop); animation-timing-function: linear;
    animation-iteration-count: infinite;
  }
  .c2-b0 { animation-name: c2-k-b0; }
  .c2-b1 { animation-name: c2-k-b1; }
  .c2-b2 { animation-name: c2-k-b2; }
  .c2-b3 { animation-name: c2-k-b3; }
  .c2-ser { animation-name: c2-k-ser; }
  .c2-out { animation-name: c2-k-out; }
  .c2-b1 { animation-delay: -4.3s; }
  .c2-b2 { animation-delay: -7.9s; }
  .c2-b3 { animation-delay: -2.6s; }
  .c2-s1 { animation-delay: -0.5s; }
}

/* --- rad animation (rad-3-v3) --- */
/* Border stays the composite's .rad-body .scope rule. The preview's
   fixed 450px width is dropped so the drawing fills its 5fr track. */
.rad-body .scope { width: 100%; height: auto; aspect-ratio: 1; }

/* --- narrow layouts --- */
@media (max-width: 1180px) {
  .menu-btn { display: inline-block; }
  nav.links {
    display: none; position: absolute; top: var(--nav-h); left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--bg-2); border-bottom: 1px solid var(--line-strong);
    padding: var(--s-1) var(--gutter) var(--s-2);
  }
  nav.links.open { display: flex; }
  nav.links a { font-size: var(--t-body); padding: 12px 4px; border-bottom: 1px solid var(--line); border-radius: 0; }
  nav.links a:last-child { border-bottom: 0; }
}
@media (max-width: 1080px) {
  .principles { grid-template-columns: repeat(2, 1fr); }
  .team { grid-template-columns: minmax(0, 1fr); }
  .team figure img { aspect-ratio: 4 / 3; object-position: 50% 50%; }
}
@media (max-width: 900px) {
  .hero .wrap, .intro-2, .rad-body, .biz, .contact { grid-template-columns: 1fr; }
  .hero .wrap { gap: var(--s-6); }
  /* The approved v8 mockup had `start`, which left-justified the logo
     under the text once the grid collapses to one column. Centered on
     purpose. Pinned by test_hero_logo_centered_in_column_at_every_width. */
  .hero .mark-lg { justify-self: center; width: min(60%, 260px); }
  .rad-body .scope { max-width: 460px; }
  .list-2 { grid-template-columns: 1fr; }
  .devices, .cells { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row { grid-template-columns: 1fr auto; gap: 10px var(--s-3); }
  .row .track { grid-column: 1 / -1; grid-row: 2; }
  .row.colhead span:nth-child(2) { display: none; }
  .work li { grid-template-columns: 1fr; gap: var(--s-2); }
}
@media (max-width: 600px) {
  :root { --t-body: 17px; --t-lede: 18px; --nav-h: 64px; }
  .brand { gap: 12px; margin-right: var(--s-2); }
  .sec { padding: var(--s-8) 0; }
  .hero { padding: var(--s-8) 0; }
  .cells { gap: 12px; }
  .cells div { padding: 12px var(--s-2); }
  .principles { grid-template-columns: 1fr; }
  .steps li { grid-template-columns: 1fr; gap: var(--s-1); }
  .devices { gap: 12px; }
  .devices li { padding: 12px var(--s-2); min-height: 0; }
  .ttb-cap { padding: var(--s-2) var(--s-3); }
  .row { padding: var(--s-2) var(--s-3); }
  dl.kv > div { grid-template-columns: 1fr; gap: 4px; }
  form { grid-template-columns: 1fr; padding: var(--s-3); }
  .hero .btn, form .btn { width: 100%; text-align: center; }
}
