/* ============================================================================
   Vector Analytics - one stylesheet for the whole site.

   Six pages. One file is easier to keep honest than five, and every colour
   has to come from a token, never from a literal.
   Depends on tokens.css and fonts.css.

   Order: reset, typography, chrome, page furniture, components, responsive.
   ============================================================================ */

/* ══ Reset ════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-relaxed);
  color: var(--fg-1);
  background: var(--surface-1);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Short pages still put the footer at the bottom of the window instead of
     leaving a band of paper under it. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
body > main { flex: 1 0 auto; }

/* The hidden attribute is only a user-agent default, so any author rule that
   sets display defeats it silently. */
[hidden] { display: none !important; }

img, svg { max-width: 100%; }
img { height: auto; }
a { color: inherit; }
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; }
figure { margin: 0; }
table { border-collapse: collapse; border-spacing: 0; }
code, kbd, samp, pre { font-family: var(--font-mono); }

button {
  font: inherit; color: inherit;
  background: none; border: 0; padding: 0;
  cursor: pointer;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  color: var(--fg-1);
  text-wrap: balance;
}

/* ══ Focus ════════════════════════════════════════════════════════════════
   One ring everywhere. On the deep surfaces it switches to the bright accent,
   which is the shade cleared for that background. */
:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.section--deep :focus-visible,
.site-header :focus-visible,
.site-footer :focus-visible,
.hero :focus-visible {
  outline-color: var(--accent-bright);
}

/* The skip link comes to rest over the header, which is --surface-deep on
   every page, so it is a solid affordance on a deep surface and takes the
   same colourway the buttons there take. */
.skip {
  position: absolute;
  top: 0; left: 0;
  z-index: var(--z-skip);
  transform: translateY(-130%);
  padding: 10px var(--space-sm);
  background: var(--accent-solid-bright);
  color: var(--surface-deep);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-semi);
  text-decoration: none;
  border-radius: 0 0 var(--radius-md) 0;
  transition: transform var(--duration-fast) var(--ease-default);
}
.skip:focus { transform: translateY(0); }
.skip:hover { background: var(--accent-hover-bright); }
.skip:focus-visible {
  outline-color: var(--accent-bright);
  box-shadow: inset 0 0 0 2px var(--surface-deep);
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ══ Header ═══════════════════════════════════════════════════════════════
   Solid deep bar on every page. On the home page it meets the hero, which is
   the same surface, so the two read as one field. */
.site-header {
  background: var(--surface-deep);
  color: var(--fg-on-deep-1);
  border-bottom: 1px solid var(--border-on-deep-2);
}

.site-header-in {
  max-width: var(--width-page);
  margin: 0 auto;
  padding: var(--space-sm) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--space-lg);
}

.site-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  text-decoration: none;
  margin-right: auto;
}
.site-logo-mark { width: 34px; height: auto; display: block; }
.site-logo-word {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-on-deep-1);
}

.site-nav ul {
  list-style: none;
  padding: 0;
  display: flex;
  gap: var(--space-md);
}
.site-nav a {
  display: inline-block;
  padding: var(--space-3xs) 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-wide);
  color: var(--fg-on-deep-2);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: color var(--duration-fast) var(--ease-default);
}
.site-nav a:hover { color: var(--fg-on-deep-1); }
/* The current page is the brightened ink plus an underline in that same ink:
   a navigation state, not a link, so it carries no accent. 15.39:1 on the
   deep header against the 3:1 floor a UI component owes. */
.site-nav a[aria-current="page"] {
  color: var(--fg-on-deep-1);
  border-bottom-color: var(--fg-on-deep-1);
}

.nav-toggle {
  display: none;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-3xs) var(--space-2xs);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--fg-on-deep-1);
  border: 1px solid var(--border-on-deep-1);
  border-radius: var(--radius-md);
}
.nav-toggle-bars {
  position: relative;
  width: 15px; height: 2px;
  background: currentColor;
}
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: ""; position: absolute; left: 0;
  width: 15px; height: 2px; background: currentColor;
}
.nav-toggle-bars::before { top: -5px; }
.nav-toggle-bars::after  { top:  5px; }

/* ══ Sections ═════════════════════════════════════════════════════════════ */
.section {
  padding: var(--section-top) 0 var(--section-bottom);
}
.section-in {
  max-width: var(--width-page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.section--tint { background: var(--surface-2); }
.section--deep {
  background: var(--surface-deep);
  color: var(--fg-on-deep-1);
}
.section--deep h2, .section--deep h3 { color: var(--fg-on-deep-1); }
.section--tight { padding: var(--space-2xl) 0; }

.eyebrow {
  display: block;
  margin: 0 0 var(--space-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--label);
}
.section--deep .eyebrow { color: var(--label-bright); }

h1 { font-size: var(--text-h1); }
h2 { font-size: var(--text-h2); }
h3 { font-size: var(--text-h3); font-weight: var(--weight-semi); }

/* A heading and the sentence under it are one unit, so the gap between them
   is smaller than the gap to whatever follows. */
h1 + .lede, h2 + .lede, h3 + .lede,
h1 + .prose, h2 + .prose, h3 + .prose { margin-top: var(--space-sm); }
.lede + .prose { margin-top: var(--space-md); }

.lede {
  max-width: var(--measure);
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
  color: var(--fg-2);
}
/* The hero is a deep surface without the class, so it has to be named. It
   was not, and the home page's opening paragraph was painting --fg-2, a
   light-surface ink, on the navy at 2.36:1. Found by the luminance ceiling
   in backgrounds.js, which reads what a section actually paints and had
   nothing left to give the field once it had read this. */
.section--deep .lede, .hero .lede { color: var(--fg-on-deep-2); }

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--space-md); }
.prose a {
  color: var(--accent-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.prose a:hover { color: var(--accent-hover); }
.section--deep .prose { color: var(--fg-on-deep-2); }
.section--deep .prose a { color: var(--accent-bright); }

/* ══ Buttons ══════════════════════════════════════════════════════════════
   One call to action across the site, so one button style carries it, in two
   colourways: the palette's solid emphasis shade on light paper, and a
   near-white fill on a deep section. Every button the site paints today is on
   a deep section - the home hero and the closing section of the other four
   pages - so the second is the one a reader actually sees; the first is what
   a button on light paper would get, and what the deep rules are written as a
   change from.

   The reason for the pair is that --accent-solid is dark by construction. It
   has to carry white text at 4.5:1 and read as ink on --surface-3, and a hex
   that does both is a hex that leaves 3.13:1 against a deep surface: a dark
   shape on a dark ground, at the floor WCAG 1.4.11 sets for a control's edge
   rather than anywhere above it. --accent-solid-bright inverts the button
   instead of dimming the ground. It is near-white, its ink is --surface-deep
   itself, and both readings that matter - the ink on the fill and the fill
   against the section behind it - come out together at 16.84:1.
   tokens.css carries the arithmetic. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: 13px var(--space-md);
  background: var(--accent-solid);
  color: #fff;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-wide);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: background var(--duration-fast) var(--ease-default);
}
.btn:hover { background: var(--accent-hover); }
.btn svg { flex: none; }

/* The deep colourway. --surface-deep is the ink, so the button carries the
   section's own colour and nothing new is introduced to the palette. The
   hover is the signal hue one step down from the fill, 1.45:1 under it,
   because a white button cannot hover lighter. */
.section--deep .btn,
.hero .btn {
  background: var(--accent-solid-bright);
  color: var(--surface-deep);
}
.section--deep .btn:hover,
.hero .btn:hover { background: var(--accent-hover-bright); }

/* Two rings, because no single colour clears 3:1 against a near-white fill
   and a near-black section at once. --accent-bright is the shade already
   cleared for --surface-deep and it sits outside the button, in the offset;
   the collar inside the edge is --surface-deep, which is the fill's own ink
   ratio again. Together they read as a focus state from either side. */
.section--deep .btn:focus-visible,
.hero .btn:focus-visible {
  outline-color: var(--accent-bright);
  box-shadow: inset 0 0 0 2px var(--surface-deep);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
  margin-top: var(--space-lg);
}
.cta-note {
  font-size: var(--text-base);
  color: var(--fg-2);
}
.section--deep .cta-note, .hero .cta-note { color: var(--fg-on-deep-2); }

/* ══ Hero ═════════════════════════════════════════════════════════════════ */
.hero {
  position: relative;
  background: var(--surface-deep);
  color: var(--fg-on-deep-1);
  padding: var(--space-3xl) 0 var(--space-2xl);
  overflow: hidden;
}
.hero h1 { color: var(--fg-on-deep-1); font-size: var(--text-hero); max-width: 19ch; }
.hero .lede { margin-top: var(--space-md); max-width: var(--measure-short); }

.hero-in {
  position: relative;
  z-index: var(--z-content);
  max-width: var(--width-page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ══ Animated section backgrounds ═════════════════════════════════════════
   A deep section marked .section--field, and the home page's hero, carries
   one animated field behind its content. assets/js/backgrounds.js draws it
   and the long comment at the head of that file is where the contrast
   argument lives; what belongs here is the three things CSS owns.

   1. The host is painted --surface-deep in its own right, so with scripting
      off, with that file blocked, or before it runs, the section is the flat
      colour it has always been rather than a hole.
   2. The scrim. A luminance ceiling reads foregrounds, and the solid call to
      action is a fill, so it sits outside the ceiling. The scrim paints the
      content side of the section back to the flat surface colour, so the
      button and the display type sit on exactly the paper they were measured
      on. It is no longer the only thing keeping that button's edge over its
      floor - the fill there is near-white now and clears 16:1 - but it is
      still what makes every measurement over a deep section a measurement
      against the paper it is painted on. The second gradient does the same at
      the foot, so the field dissolves into the section edge instead of being
      cut off by it.
   3. Where the field is not drawn at all: under 901px, on paper, and under a
      forced-colours palette. Canvas pixels are not repainted by a
      forced-colours mode while the text over them is, so a field left up
      there would be the one surface on the site still navy under a reader's
      white canvas. */
.va-bg {
  position: absolute;
  inset: 0;
  z-index: var(--z-bg);
  background: var(--surface-deep);
  pointer-events: none;
}
.va-bg-canvas { display: block; width: 100%; height: 100%; }
.va-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--surface-deep) 0 32%, transparent 76%),
    linear-gradient(to bottom, transparent 56%, var(--surface-deep) 100%);
}

/* The two section shapes a field is allowed to sit in. Both have to clip it
   and both have to lift their own content over it. */
.hero, .section--field { position: relative; overflow: hidden; }
.section--field > .section-in { position: relative; z-index: var(--z-content); }

@media (max-width: 900px) {
  /* Below this the content column is the viewport, so there is no part of
     the section a field could occupy that is not under the text and the
     button. The phone is spared the canvas as well as the composition. */
  .va-bg { display: none; }
}

/* ══ Capability cards ═════════════════════════════════════════════════════ */
.cards {
  list-style: none;
  padding: 0;
  margin: var(--space-xl) 0 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
}
.card {
  padding: var(--space-md) var(--space-md) var(--space-lg);
  background: var(--surface-1);
  border: 1px solid var(--border-1);
  border-top: 3px solid var(--mark);
  border-radius: var(--radius-md);
}
/* Five cards in a two-column grid leave one on its own, so the odd last one
   takes the full width and the row reads as deliberate. */
.cards > li:last-child:nth-child(odd) { grid-column: 1 / -1; }
.section--tint .card { background: var(--surface-1); }
.card h3 { margin-bottom: var(--space-2xs); }
.card p { color: var(--fg-2); font-size: var(--text-base); }
/* The claim each card makes, before the evidence for it. Same size as the body
   so the card reads as one voice, but it carries the weight of the heading. */
.card-claim {
  color: var(--fg-1);
  font-weight: var(--weight-semi);
  margin-bottom: var(--space-2xs);
}
.card-index {
  display: block;
  margin-bottom: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-widest);
  color: var(--fg-2);
}

/* ══ Plain lists ══════════════════════════════════════════════════════════ */
.list-plain {
  list-style: none;
  padding: 0;
  margin-top: var(--space-md);
}
.list-plain > li {
  position: relative;
  padding-left: var(--space-md);
  margin-top: var(--space-2xs);
  color: var(--fg-2);
}
.list-plain > li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 7px; height: 7px;
  background: var(--mark);
}
.section--deep .list-plain > li { color: var(--fg-on-deep-2); }
.section--deep .list-plain > li::before { background: var(--mark-bright); }

/* ══ Contact link ═════════════════════════════════════════════════════════
   The contact page has no button, so this link is that page's one action. It
   therefore reads --accent-solid rather than --accent-text: the emphasis
   colour and the link colour deliberately come apart in this palette, and
   this is the emphasis.

   The element qualifier is load-bearing. This link sits inside .prose, and
   `.prose a` is (0,1,1) against a bare `.mail-big`'s (0,1,0), so the plain
   class rule never carried the colour at all. That was invisible while both
   rules resolved to the same hex and showed up the moment they stopped.

   /contact/ is not in the navigation and is not in the deploy payload, but
   the page is still built and still checked, so its one rule stays here.
   build/tools/make-payload.js is the list of what actually ships. */
a.mail-big {
  display: inline-block;
  margin-top: var(--space-md);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--accent-solid);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  overflow-wrap: anywhere;
}
a.mail-big:hover { color: var(--accent-hover); }

/* ══ Capability block ═════════════════════════════════════════════════════
   The heading sits in its own column so the eye can run down the names in a
   run of these without reading the bodies. */
.cap {
  display: grid;
  grid-template-columns: minmax(12rem, 0.8fr) 1.6fr;
  gap: var(--space-2xl);
  align-items: start;
}
.cap-head .eyebrow { color: var(--fg-2); }
.cap-body > .lede { max-width: var(--measure); }
.cap-body > * + * { margin-top: var(--space-md); }

/* ══ Bio ══════════════════════════════════════════════════════════════════
   The About page opens with a photograph beside the text. The picture column
   is fixed in a range rather than a fraction so that the paragraphs keep a
   readable measure at every width the two columns survive at. */
.bio {
  display: grid;
  grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr);
  gap: var(--space-xl);
  align-items: start;
  margin-top: var(--space-lg);
}
.bio-photo { margin: 0; }
.bio-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}
.bio-photo figcaption {
  margin-top: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--fg-2);
}
.bio-text { max-width: var(--measure); }

/* ══ Credential list ══════════════════════════════════════════════════════ */
.cv {
  display: grid;
  grid-template-columns: minmax(9rem, 0.6fr) 2fr;
  gap: 0 var(--space-xl);
  margin: var(--space-xl) 0 0;
  max-width: 54rem;
}
.cv dt {
  padding: var(--space-sm) 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--label);
  border-top: 1px solid var(--border-1);
}
.cv dd {
  margin: 0;
  padding: var(--space-sm) 0;
  color: var(--fg-2);
  border-top: 1px solid var(--border-1);
}

/* ══ Page title ═══════════════════════════════════════════════════════════
   The FAQ has no hero, so its h1 sits directly above the first group's
   heading. Without the rule under it the two read as one two-line title. */
.page-title {
  padding-bottom: var(--space-md);
  margin-bottom: var(--space-2xl);
  border-bottom: 1px solid var(--border-1);
}

/* ══ Question and answer ══════════════════════════════════════════════════
   The FAQ's three groups reuse the capability block, so the group name sits
   beside its questions rather than above a narrow column in a wide page. That
   puts .qa inside .cap-body, whose `* + *` rule is more specific than .qa's
   own margin, so the gap between two questions is restated here. */
.qa { margin-top: var(--space-xl); max-width: var(--measure); }
.cap-body > .qa { margin-top: var(--space-xl); }
.cap-body > .qa:first-child { margin-top: 0; }
.qa h3 { margin-bottom: var(--space-sm); }
.qa-note {
  margin-top: var(--space-2xs);
  font-size: var(--text-base);
  color: var(--fg-2);
}

/* ══ Footer ═══════════════════════════════════════════════════════════════
   One band: the practice on the left, its five links inline in the middle,
   the address on the right. The links used to stack in a column, which was
   most of the footer's height and bought nothing. A narrow screen wraps the
   band a row at a time, and all five links still fit one row at 390px.

   The hairline mirrors the header's border-bottom. Every page ends on a deep
   call to action painted in the shade the footer takes, so the rule is what
   tells the foot of the page from the bottom of that section. */
.site-footer {
  background: var(--surface-deep);
  color: var(--fg-on-deep-2);
  border-top: 1px solid var(--border-on-deep-2);
  padding: var(--space-lg) 0;
}
.site-footer-in {
  max-width: var(--width-page);
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-lg);
}
.site-footer-id {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-display);
  font-weight: var(--weight-semi);
  color: var(--fg-on-deep-1);
}
.site-footer-mark { width: 22px; height: auto; display: block; }
.site-footer-nav ul {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-sm);
}
.site-footer-nav a, .site-footer-mail a {
  color: var(--fg-on-deep-2);
  font-size: var(--text-base);
  text-decoration: none;
}
.site-footer-nav a:hover, .site-footer-mail a:hover {
  color: var(--fg-on-deep-1);
  text-decoration: underline;
}

/* ══ Spacing utility ══════════════════════════════════════════════════════
   One of them, for the places where a block needs more air than its component
   rule gives it. The alternative is an inline style, which no page carries. */
.stack-sm { margin-top: var(--space-sm); }

/* ══ Responsive ═══════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .cap { grid-template-columns: 1fr; gap: var(--space-md); }
}

@media (max-width: 700px) {
  /* Gated on `js` so that with scripting off there is no toggle button
     sitting above a nav that is already open and already works. */
  .js .nav-toggle { display: inline-flex; }

  .site-header-in { flex-wrap: wrap; gap: var(--space-sm); }

  /* Full width in both states, so that with scripting off the nav wraps to
     its own row under the logo instead of stacking in a narrow column beside
     it. Closed by default only once the toggle is live. */
  .site-nav { width: 100%; }
  .js .site-nav { display: none; }
  .js .site-nav.is-open { display: block; }
  .site-nav ul { flex-direction: column; gap: var(--space-2xs); width: 100%; }
  .site-nav a { padding: var(--space-2xs) 0; }

  .cards { grid-template-columns: 1fr; }
  .bio { grid-template-columns: 1fr; gap: var(--space-lg); }
  .bio-photo { max-width: 14rem; }
  .hero { padding-top: var(--space-2xl); }
}

@media (max-width: 520px) {
  /* The two-column term/definition pairing stops working once the terms wrap,
     so below this width each term sits on its own line above its answer. */
  .cv { grid-template-columns: 1fr; gap: 0; }
  .cv dt { padding-bottom: 0; }
  .cv dd { padding-top: var(--space-3xs); border-top: 0; }
  .mail-big { font-size: var(--text-xl); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ══ Print ════════════════════════════════════════════════════════════════
   A browser drops background colours when it prints, and every deep section
   on this site is light text on a painted navy field. Printed as drawn, the
   home page headline measures 1.16:1 on white paper and the call to action
   goes missing entirely.

   The fix is at the token layer rather than in the rules that paint those
   sections: for the length of the print run the on-deep shades point at the
   ink shades, so anything that reads --fg-on-deep-1 gets --fg-1 and every
   pairing contrast-check.js already holds still holds. */
@media print {
  :root {
    --surface-deep: #ffffff;
    --fg-on-deep-1: var(--fg-1);
    --fg-on-deep-2: var(--fg-2);
    --accent-bright: var(--accent-text);
    --mark-bright: var(--mark);
    --label-bright: var(--label);
    --secondary-bright: var(--secondary);
    --color-ok-on-deep: var(--color-ok);
    --color-warn-on-deep: var(--color-warn);
    --color-alert-on-deep: var(--color-alert);
    --border-on-deep-1: var(--border-1);
    --border-on-deep-2: var(--border-1);

    /* The sheet carries its own margin, and a hundred points of section
       padding costs a page. */
    --gutter: 0px;
    --section-top: 28px;
    --section-bottom: 28px;
  }

  /* Furniture with nothing to do on paper. The nav is a set of words with no
     destinations, and an animated field is decoration a printer would render
     as grey haze over the sentence a reader kept the sheet for. */
  .skip, .nav-toggle, .site-nav, .va-bg { display: none; }

  .site-header { border-bottom: 1px solid var(--border-1); }
  .site-footer { border-top: 1px solid var(--border-1); }
  .hero { padding: var(--space-lg) 0 var(--space-md); overflow: visible; }
  .section--tight { padding: var(--space-lg) 0; }

  /* On screen the button is a painted block carrying text in the colour of
     whatever it is painted on. With the paint gone that text would be white
     on white in either colourway - the deep sections are white paper here,
     and the deep colourway's ink is the deep surface - so on paper the button
     becomes its own outline. The deep selectors are repeated because they
     outrank a bare .btn and would otherwise keep their screen ink. */
  .btn,
  .section--deep .btn,
  .hero .btn {
    padding: 6px var(--space-sm);
    background: none;
    color: var(--accent-text);
    border: 1px solid var(--accent-text);
  }

  /* Keep a heading with what it introduces, and keep a card whole. */
  h1, h2, h3, .eyebrow, caption { break-after: avoid; }
  .card, .cv > *, figure, li, tr { break-inside: avoid; }
}

/* ══ Forced colours ═══════════════════════════════════════════════════════
   A reader running Windows high contrast, or any forced-colours mode, gets
   their own two or three colours in place of every colour a stylesheet sets.
   The substitution is deliberate and the page should mostly welcome it: the
   deep sections come back as the reader's ink on the reader's canvas, which
   is what they want.

   What it takes with it is any shape drawn in background colour and nothing
   else, because that background is replaced by the colour of the page it
   sits on. Three of those are here. The map and its key are in demos.css. */
@media (forced-colors: active) {
  /* A canvas is raster, so a forced-colours mode leaves its pixels alone
     while it repaints the text over them. A field left up would be the one
     surface on the site still navy under a reader's white canvas, with the
     reader's own ink on top of it. The section keeps the colours the reader
     asked for instead. */
  .va-bg { display: none; }

  /* A bullet and the toggle's three bars are paint on an empty box, so they
     came out the colour of the paper. CanvasText is whatever the reader has
     chosen to read with. */
  .list-plain > li::before,
  .section--deep .list-plain > li::before,
  .nav-toggle-bars,
  .nav-toggle-bars::before,
  .nav-toggle-bars::after { background: CanvasText; }

  /* A solid button is a shape made of background colour too, so the site's
     one call to action arrived as a line of link text with no edge on it.
     The border is the part that survives, and the padding hands back the
     two pixels it takes so the button stays the size it was. */
  .btn {
    border: 2px solid ButtonText;
    padding: 11px calc(var(--space-md) - 2px);
  }
}
