@layer base, catalogue, product, responsive;
@layer catalogue {
/* Correctness only. Palette, type and spacing come from the site.
   Every interactive element here takes its height from the box rather than from
   inline padding: padding on a short nav link makes it paint past its <nav>,
   measured on the live site. */
.skip-link {
  position: fixed;
  inset-block-start: .75rem;
  inset-inline-start: .75rem;
  z-index: 20;
  padding: .65rem .9rem;
  transform: translateY(-160%);
  transition: transform .2s ease;
}
.skip-link:focus { transform: translateY(0); }

.site-header {
  width: min(100% - 2rem, 88rem);
  min-block-size: 5.5rem;
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
nav { display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.5rem); }

/* 44px minimum, from the box. WCAG 2.5.8 exempts an inline anchor inside a <p>
   or <li> and nothing else. */
.site-header nav a, .site-header .brand, footer a, footer .brand {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
}

footer {
  width: min(100% - 2rem, 88rem);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2rem;
}
.footer-links { display: flex; flex-wrap: wrap; align-items: start; gap: 1.4rem; }
.copyright { grid-column: 1 / -1; }

@media (max-width: 38rem) {
  .site-header { min-block-size: 4.5rem; }
  footer { grid-template-columns: 1fr; }
}

/* The art is sized against its own grid column, never the viewport. `47vw` is
   unrelated to the track it sits in; at 834px and 1280px it grew past the column
   and the hero's overflow clipped it. Firefox reported it, the other two engines
   hid it behind the same clip. */
.hero {
  width: min(100% - 2rem, 88rem);
  min-block-size: min(49rem, calc(100vh - 5.5rem));
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(22rem, .95fr);
  align-items: center;
  gap: 2rem;
  overflow: hidden;
}
.hero-art { width: min(100%, 38rem); justify-self: center; }
.hero-art svg { overflow: visible; }

@media (max-width: 60rem) {
  .hero {
    grid-template-columns: 1fr;
    min-block-size: 0;
    padding-block-end: 2rem;
    text-align: start;
  }
  /* Copy first, art after. Caught by looking at the frame: with the art in row
     one it took the whole first screen of an iPhone and pushed the headline,
     the lead and the call to action below the fold -- the exact anti-pattern
     this block exists to prevent, in the block itself. It is decoration; it
     goes last and it shrinks first. */
  .hero-art { grid-row: 2; width: min(70vw, 26rem); justify-self: start; }
}
@media (max-width: 38rem) {
  /* Measured: a 3rem headline wrapped to three lines at 390px and pushed the
     whole page down with it. */
  .hero h1 { font-size: 2.5rem; }
  .hero-art { width: min(56vw, 15rem); }
}

/* The form is the layout. `form-heading` spans every column so the title reads
   as the form's own header rather than a separate section above it. */
.tool-section {
  position: relative;
  isolation: isolate;
  padding: clamp(5rem, 10vw, 9rem) max(1rem, calc((100vw - 88rem) / 2));
  overflow: hidden;
}
.tool-form {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.4rem;
}
.form-heading { grid-column: 1 / -1; max-width: 49rem; margin-block-end: 2.1rem; }
.form-action { grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; margin-block-start: 1.2rem; }
/* Reserve the message line so showing it never moves the button. */
.form-error { min-block-size: 1.5rem; }

fieldset { min-inline-size: 0; }

@media (max-width: 52rem) {
  .tool-form { grid-template-columns: 1fr; }
}

/* The field must work with no spinner affordance: Mobile Safari does not draw
   one. Removing it elsewhere keeps typing, paste and the mobile inputmode as
   the only interaction contract on every engine. */
.numeric-field { min-inline-size: 0; }
.numeric-field-control {
  min-inline-size: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
}
.numeric-field input[type="number"] {
  -moz-appearance: textfield;
  inline-size: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
  min-block-size: 44px;
  box-sizing: border-box;
  font: inherit;
  font-variant-numeric: tabular-nums;
}
.numeric-field input[type="number"]::-webkit-inner-spin-button,
.numeric-field input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.numeric-field-unit {
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
  padding-inline: .65rem;
  white-space: nowrap;
}
.numeric-field-unit:empty { display: none; }

/* Reserve the message line so showing it never moves the button. */
.form-error { min-block-size: 1.5rem; }

.breadcrumb-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .15rem .45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.breadcrumb-list li { display: inline-flex; min-inline-size: 0; align-items: center; }
.breadcrumb-list li + li::before { content: "/"; margin-inline-end: .45rem; }
.breadcrumb-list a { display: inline-flex; min-block-size: 44px; align-items: center; }
.breadcrumb-list span { overflow-wrap: anywhere; }

/* The zero minimum is structural. Without it, a long token in an answer gives
   the grid item an intrinsic minimum wider than its column and the page grows
   beyond a phone viewport. */
.faq-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-card, 1.25rem);
}
.faq-item { min-inline-size: 0; }
.faq-item p { overflow-wrap: anywhere; }

@media (max-width: 44rem) {
  .faq-list { grid-template-columns: minmax(0, 1fr); }
}

.sitemap-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: var(--space-section, 2rem);
}
.sitemap-group { min-inline-size: 0; }
.sitemap-group ul { margin: 0; padding: 0; list-style: none; }
.sitemap-group li { min-inline-size: 0; }
.sitemap-group a {
  display: inline-flex;
  min-block-size: 44px;
  align-items: center;
  overflow-wrap: anywhere;
}
.sitemap-group p { overflow-wrap: anywhere; }

/* 44px is the documented minimum. Inline anchors inside a <p> or <li> are
   exempt (WCAG 2.5.8) because padding them wrecks the surrounding line height. */
.text-button, nav a, footer a {
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
}

/* `[hidden]` LOSES TO AN AUTHOR `display` AT EQUAL SPECIFICITY.
 *
 * The user-agent rule is `[hidden] { display: none }`. An author rule such as
 * `.card { display: grid }` has the SAME specificity (0,1,0) and comes from a
 * later origin, so the element stays on screen with the attribute set. The DOM
 * inspector shows `hidden`. Every unit test that reads the markup passes. It is
 * visible in the browser and nowhere else.
 *
 * That cost one site three separate defects in one build:
 *
 *   1. a page-range field with `display: grid` stayed on screen in "every page"
 *      mode, in all three engines, with `hidden` set;
 *   2. a featured card with `display: grid` stayed on screen in every filtered
 *      view that excluded it -- caught in the first phone screenshot, not by any
 *      test;
 *   3. a group heading with `display: block` re-declared inside
 *      `@media (min-width: 64rem)` stayed on screen under a filter, because the
 *      site-wide guard had EQUAL specificity and appeared EARLIER in the file.
 *
 * Number 3 is the one that makes this a stylesheet rather than a habit: writing
 * the guard once at the top does not survive a media query.
 *
 * This declaration is the whole fix, and `!important` is the point of it -- it
 * is the one place in a stylesheet where a blanket win is the correct answer,
 * because there is no legitimate reading of `hidden` other than "not rendered".
 * A site that prefers per-class guards may do that instead; the block's
 * invariants accept either, and require the LIST OF HIDEABLE CLASSES TO BE
 * ASSERTED BY NAME, because remembering it is what failed three times. */
[hidden] { display: none !important; }

.table-wrap { max-inline-size: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-wrap:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
table { inline-size: 100%; border-collapse: collapse; }
caption { text-align: start; color: var(--ink-muted); padding-block-end: .5rem; }
/* Cells WRAP. `white-space: nowrap` used to be set on every cell here, which is
   right for a figure and wrong for a sentence: it clipped a prose column behind
   the wrapper's own scrollbar at 390px AND at 1280px, so widening the window did
   not reveal it. A prose column generally does not belong in a table at all --
   but when one is there, the table must not hide it. */
th, td { padding: .7rem .9rem; text-align: start; border-block-end: 1px solid var(--line); }
/* Figures must not dance as they change, and columns must not resize per row, so
   `nowrap` belongs here: scoped to the cells that carry a measurement. */
td.figure, th.figure, .table-wrap .figure { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Legal pages are long prose; the only rule that keeps them correct is measure.
   Anything past ~70 characters a line becomes unreadable, and these are the
   pages a reviewer actually reads. */
.legal-page { max-inline-size: 44rem; }
.legal-page h2 { margin-block-start: 2.5rem; }
.legal-page p + p { margin-block-start: 1rem; }

}
/* quietvin.com.
 *
 * THE IDENTITY IS AN INSTRUMENT PANEL READ IN DAYLIGHT, and the divergence from
 * every other site in this fleet is deliberate rather than decorative. This one
 * has one claim — that nothing leaves the device — and a page that looks like a
 * marketing site undermines a claim of that shape. So: a cool grey ground, ink
 * that is nearly black, hairline rules instead of card shadows, one teal accent
 * used only for actions, one amber used only for a caveat, and tabular figures
 * wherever a number appears so a changing digit never shifts the one beside it.
 *
 * No gradient, no glow, no shadow, no web font, no image request. The single
 * decorative element on the site is one inline SVG dial in the hero.
 */

@layer base {
  :root {
    --ground: #f2f4f5;
    --raised: #ffffff;
    --ink: #14181b;
    --ink-soft: #454d52;
    --ink-faint: #6c757b;
    --rule: #d3d9dc;
    --rule-strong: #adb6ba;
    --accent: #0d5c63;        /* gauge teal: actions and links only */
    --accent-soft: #e2eeef;
    --warn: #8a4b06;          /* the amber of a dashboard caution lamp */
    --warn-soft: #fbf1e3;
    --focus: #0d5c63;
    --ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
    --measure: 66ch;
    --space-card: 1.25rem;
    --space-section: 2rem;
  }

  * { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; }

  body {
    margin: 0;
    background: var(--ground);
    color: var(--ink);
    font-family: var(--ui);
    font-size: 1rem;
    line-height: 1.55;
  }

  h1, h2, h3 { line-height: 1.18; font-weight: 650; letter-spacing: -0.011em; }
  h1 { font-size: clamp(1.75rem, 1.25rem + 2.2vw, 2.6rem); margin: 0 0 0.7rem; }
  h2 { font-size: clamp(1.2rem, 1rem + 1vw, 1.5rem); margin: 2.2rem 0 0.6rem; }
  h3 { font-size: 1.05rem; margin: 1.4rem 0 0.4rem; }
  p, li { max-width: var(--measure); }
  a { color: var(--accent); text-underline-offset: 0.18em; }
  a:hover { color: var(--ink); }
  /* `overflow-wrap: anywhere` is not defensive tidiness. Wave 2 put
     `vPICList_lite_2026_08.plain.zip` and `/data/vpic-2026-08.bin.gz` into the
     prose of /how-it-works/, and the responsive matrix measured WebKit on an
     iPhone SE spilling that CODE 6px past its parent for a document
     scrollWidth of 321 against a 320 viewport. A page overflows on its longest
     unbreakable WORD, not on its longest sentence, and a monospace file name is
     the longest word this site has. */
  code { font-family: var(--mono); font-size: 0.92em; background: var(--accent-soft); padding: 0 0.22em; border-radius: 2px; overflow-wrap: anywhere; }

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

  /* Every number on this site is tabular. A result panel whose figures shift
     sideways as they change reads as unstable, and these are figures somebody
     is about to make a purchase against. */
  .result-headline, .result-line__value, .field__control input, .tool-card__name + * {
    font-variant-numeric: tabular-nums;
  }

  .visually-hidden {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}

@layer product {
  /* `page-shell` insets its own header and footer but not <main>, so without
     this the h1 sits flush against the screen edge under an inset header.
     Nothing measures it — there is no overflow and no small target — it is
     simply wrong, and it is invisible until somebody looks at a real frame. */
  main {
    width: min(100% - 2rem, 76rem);
    margin-inline: auto;
    padding-block-end: 3rem;
  }
  .lede { font-size: 1.1rem; color: var(--ink-soft); }
  .page__footnote { margin-block-start: 2rem; color: var(--ink-soft); font-size: 0.95rem; }

  .site-header { background: var(--raised); border-block-end: 1px solid var(--rule-strong); }
  footer { border-block-start: 1px solid var(--rule-strong); margin-block-start: 3rem; padding-block: 1.5rem; }
  .brand { font-weight: 700; letter-spacing: -0.02em; text-decoration: none; color: var(--ink); }
  .brand-mark {
    inline-size: 1.1rem; block-size: 1.1rem; margin-inline-end: 0.5rem;
    border: 2px solid var(--accent); border-radius: 50%; display: inline-block;
  }
  .copyright { color: var(--ink-faint); font-size: 0.9rem; }
  .skip-link { background: var(--accent); color: #fff; text-decoration: none; }

  /* ------------------------------------------------------------------ hero */

  /* The catalogue's `.hero` insets itself with `min(100% - 2rem, 88rem)`, which
     is right for a hero that sits directly in <body> and wrong here, where
     <main> has already taken its own gutter — the two inset one inside the
     other and the hero ends up 2rem narrower than every section under it. It
     also reserves most of a viewport in height, which is the fleet's
     atmospheric shape; this page has to reach the calculators. */
  .hero { width: 100%; min-block-size: 0; padding-block: clamp(1.5rem, 5vw, 3rem); }
  .hero-copy .eyebrow, .eyebrow {
    text-transform: uppercase; letter-spacing: 0.09em; font-size: 0.76rem;
    font-weight: 700; color: var(--accent); margin: 0 0 0.5rem;
  }
  .hero-lead { font-size: 1.15rem; color: var(--ink-soft); }
  .privacy-note { color: var(--ink-faint); font-size: 0.9rem; }
  .hero-art { color: var(--rule-strong); }
  .hero-art svg { inline-size: 100%; block-size: auto; }

  .button {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
    min-block-size: 44px; padding-inline: 1.1rem;
    border: 1px solid var(--accent); border-radius: 3px;
    font: inherit; font-weight: 600; text-decoration: none; cursor: pointer;
    background: var(--raised); color: var(--accent);
  }
  .button-primary, .button--primary { background: var(--accent); color: #fff; }
  .button--quiet { border-color: var(--rule-strong); color: var(--ink-soft); }
  .button:disabled { opacity: 0.55; cursor: progress; }

  /* --------------------------------------------------------------- notices */

  .notice {
    border: 1px solid var(--rule-strong); border-inline-start: 4px solid var(--accent);
    background: var(--raised); padding: var(--space-card); margin-block: var(--space-section);
  }
  .notice--build h2 { margin-block-start: 0; }
  .notice--warn { border-inline-start-color: var(--warn); background: var(--warn-soft); }

  /* ----------------------------------------------------------- tool cards */

  .tool-grid {
    list-style: none; padding: 0; margin: var(--space-section) 0 0;
    display: grid; gap: 1px; background: var(--rule);
    border: 1px solid var(--rule);
  }
  .tool-card { max-width: none; min-inline-size: 0; }
  .tool-card a {
    display: block; background: var(--raised); padding: var(--space-card);
    min-block-size: 44px; block-size: 100%; text-decoration: none; color: inherit;
  }
  .tool-card a:hover { background: var(--accent-soft); }
  .tool-card__name { display: block; font-weight: 650; color: var(--accent); text-decoration: underline; }
  .tool-card__what { display: block; margin-block-start: 0.35rem; font-size: 0.92rem; color: var(--ink-soft); }

  /* ---------------------------------------------------------- the workspace */

  .tool-workspace {
    background: var(--raised); border: 1px solid var(--rule-strong);
    margin-block: var(--space-section); padding: var(--space-card);
  }
  /* The catalogue's `.tool-form` is a three-track grid for a centred hero form.
     This one is a stack of a heading, a field grid and an action row, so the
     tracks are collapsed here rather than fought with inside the fields. */
  .tool-section, .tool-form { padding: 0; grid-template-columns: 1fr; gap: 1rem; }
  .form-heading { margin-block-end: 0.5rem; }
  .form-heading h2 { margin-block-start: 0.2rem; }
  .form-action { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 0.75rem; }
  .form-error, .field__error { color: var(--warn); font-weight: 600; }
  .form-error { min-block-size: 1.5rem; }

  .field-grid { display: grid; gap: 1rem; }
  .field { min-inline-size: 0; }
  .field label { display: block; font-weight: 600; margin-block-end: 0.3rem; }
  .field__control {
    display: flex; align-items: stretch; min-inline-size: 0;
    border: 1px solid var(--rule-strong); background: var(--raised); border-radius: 3px;
  }
  .field__control:focus-within { outline: 3px solid var(--focus); outline-offset: 1px; }
  .field__control input {
    flex: 1 1 auto; min-inline-size: 0; min-block-size: 44px;
    border: 0; background: transparent; font: inherit; color: inherit;
    padding-inline: 0.6rem;
  }
  .field__control input:focus { outline: none; }
  .field__unit {
    display: inline-flex; align-items: center; min-block-size: 44px;
    padding-inline: 0.6rem; color: var(--ink-faint); white-space: nowrap;
    background: var(--ground);
  }
  .field__unit--lead { border-inline-end: 1px solid var(--rule); }
  .field__unit:not(.field__unit--lead) { border-inline-start: 1px solid var(--rule); }
  .field__hint { font-size: 0.88rem; color: var(--ink-faint); margin: 0.3rem 0 0; }
  .field__error { margin: 0.3rem 0 0; font-size: 0.9rem; }
  input[aria-invalid="true"] { color: var(--warn); }
  .field:has(input[aria-invalid="true"]) .field__control { border-color: var(--warn); }

  /* ----------------------------------------------------------- the result */

  .result-panel {
    margin-block-start: var(--space-section); border-block-start: 1px solid var(--rule-strong);
    padding-block-start: var(--space-card);
  }
  .result-panel__title { margin-block-start: 0; }
  .result-panel__idle, .result-panel__working, .result-panel__error { color: var(--ink-soft); }
  .result-caption { color: var(--ink-faint); font-size: 0.9rem; margin: 0; }
  .result-headline {
    font-family: var(--mono); font-size: clamp(2rem, 1.4rem + 3vw, 3rem);
    font-weight: 600; margin: 0.2rem 0 0; line-height: 1.1;
  }
  .result-headline__label { color: var(--ink-soft); margin: 0.2rem 0 1rem; }
  .result-lines { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
  .result-line {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.2rem 1rem; background: var(--raised); padding: 0.7rem var(--space-card);
  }
  .result-line--strong { background: var(--accent-soft); }
  .result-line__label { font-weight: 600; min-inline-size: 0; }
  .result-line__value { font-family: var(--mono); font-weight: 600; text-align: end; overflow-wrap: anywhere; }
  .result-line__note { grid-column: 1 / -1; font-size: 0.88rem; color: var(--ink-soft); max-width: var(--measure); }
  .result-assumptions { margin-block-start: var(--space-card); }
  .result-assumptions summary { min-block-size: 44px; display: flex; align-items: center; font-weight: 600; cursor: pointer; }
  /* The attribution NHTSA is owed, and the release the answer came from. It is
     part of the answer rather than a footer: a decode is only as current as the
     monthly dump behind it, and a reader deserves to see which one that was
     without leaving the result. */
  .result-source { margin-block-start: var(--space-card); font-size: 0.88rem; color: var(--ink-soft); max-width: var(--measure); }
  /* The retry the payload failure offers (docs/build-spec.md §7) sits under its
     own message rather than beside it, so the 44px control never shares a line
     with wrapping prose on a phone. */
  .result-panel__error { display: flex; flex-direction: column; align-items: flex-start; gap: 0.8rem; }
  .result-panel__error[hidden] { display: none; }
  .result-panel__error-text { max-width: var(--measure); }

  /* ------------------------------------------------------------ the decoder */

  /* A VIN IS READ CHARACTER BY CHARACTER OFF A DOORFRAME, so the field that
     takes one is monospaced and letter-spaced: it is the difference between
     spotting a transposed pair and not. Upper case is display only — the engine
     normalises the value itself, so a lower-case paste still decodes. */
  [data-tool="vinDecode"] .text-field, [data-tool="checkDigit"] .text-field {
    font-family: var(--mono); text-transform: uppercase; letter-spacing: 0.08em;
  }
  /* A decoded headline is words, not a figure. "MOTOR COACH INDUSTRIES 102C3
     Intercity" at the calculators' 3rem monospace is 320px of overflow on the
     narrowest phone still in use, which is the defect this site already paid
     for once in its header. Smaller, and allowed to break. */
  [data-tool="vinDecode"] .result-headline {
    font-family: inherit; font-size: clamp(1.5rem, 1.1rem + 2vw, 2.2rem); overflow-wrap: anywhere;
  }
  .result-headline { overflow-wrap: anywhere; }
  /* Two short reference tables read as one pair on a laptop and as two stacked
     blocks on a phone. Each still scrolls inside its own `table-wrap`, so
     neither can drag the document sideways. */
  .table-pair { display: grid; gap: var(--space-card); margin-block: var(--space-card); }

  /* ------------------------------------------------------- prose and lists */

  .page--prose h2 { border-block-start: 1px solid var(--rule); padding-block-start: 1.2rem; }
  .faq { margin-block-start: var(--space-section); }
  .faq-item h3 { margin-block-start: 0; }
  .breadcrumbs { margin-block: 1rem 0.5rem; font-size: 0.9rem; }
  .breadcrumb-list li { color: var(--ink-faint); }
  .html-sitemap h2 { margin-block-start: 1.4rem; }
  .sitemap-group ul { padding: 0; }
  .sitemap-group p { font-size: 0.9rem; color: var(--ink-soft); margin: 0 0 1rem; }
}

@layer responsive {
  /* THE 320px HEADER, MEASURED RATHER THAN GUESSED.
     `page-shell` lays the header out as one flex row — wordmark, then the four
     primary destinations — and at a 320px viewport those four names do not fit
     beside the wordmark. site-responsive-check reported the same failure in
     Chromium, WebKit and Firefox on every route: `NAV` painting 18px past its
     own header and the document's scrollWidth at 322 against a 320 viewport.
     Nothing in the shell wraps, because at every wider device it fits.
     Letting the header and the nav wrap below 26rem costs one row of height on
     the narrowest phones still in use and nothing anywhere else; the link boxes
     keep their 44px minimum, so the touch targets are unchanged. */
  @media (max-width: 26rem) {
    .site-header { flex-wrap: wrap; gap: 0 1rem; padding-block: 0.4rem; }
    .site-header nav { inline-size: 100%; flex-wrap: wrap; gap: 0 1rem; }
  }

  @media (min-width: 40rem) {
    .table-pair { grid-template-columns: 1fr 1fr; align-items: start; }
    .field-grid { grid-template-columns: 1fr 1fr; }
    .tool-grid { grid-template-columns: 1fr 1fr; }
    .tool-workspace { padding: var(--space-section); }
  }
  @media (min-width: 64rem) {
    .tool-grid { grid-template-columns: repeat(3, 1fr); }
  }

  /* Reduced motion is honoured by having almost nothing to reduce: the only
     transition on the site is the skip link sliding into view, and it is turned
     off here along with any scroll behaviour a browser would add on its own. */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }

  @media print {
    .site-header nav, .form-action, footer, .breadcrumbs, .skip-link { display: none; }
    body { background: #fff; }
    .tool-workspace, .notice { border: 1px solid #999; }
  }
}
