/* ==========================================================================
   TRJ Technology — site styles
   Depends on tokens.css. No literal colour value appears below this line.
   Recreated from design-reference/. Order: fonts → reset → base → utilities
   → layout → chrome → components → pages.
   ========================================================================== */

/* ---------------------------------------------------------------- fonts -- */
/* Self-hosted, subset to Latin plus typographic punctuation. Both are variable
   and cover 400–600, so one request per family serves every weight the design
   uses. Source Serif keeps its optical-size axis; IBM Plex has its width axis
   pinned to 100. Nothing is requested from Google. */
@font-face {
  font-family: "Source Serif 4";
  src: url("../fonts/source-serif-4-variable.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/ibm-plex-sans-variable.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-height) + var(--space-4));
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--text-body-dense);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  /* Both faces are lining-tabular by default; this makes the intent explicit
     and survives a future font swap. Mismatched zeros are why an earlier
     direction was rejected. */
  font-variant-numeric: lining-nums tabular-nums;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd, ol, ul { margin: 0; }
ol, ul { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; margin: 0; }
hr { border: 0; border-top: var(--rule); margin: 0; }

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--duration) var(--ease);
}

a:hover { color: var(--ink); }

/* Colour alone is not enough to mark a link inside a block of text. The design
   already underlines its in-text links ("Scoped with you", "Start with the
   assessment") with a 1px accent rule; this applies the same idiom to every
   link that sits in running copy. */
.card__body a,
.base__body a,
.also__body a,
.bio a,
.fact__body a,
.assessment__credit a,
.received__body a,
.form__note a,
.fastest-path__body a,
.record__line a,
.consent__text a,
.namecard__meta a,
.legal p a,
.legal li a,
.legal dd a {
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}

/* ----------------------------------------------------------- typography -- */
.display,
.h2,
.h3,
.serif {
  font-family: var(--font-serif);
}

.display {
  font-family: var(--font-serif);
  font-size: var(--text-display);
  line-height: var(--leading-display);
  letter-spacing: var(--track-display);
  font-weight: var(--weight-medium);
  text-wrap: pretty;
  margin: 0;
}

.h2 {
  font-family: var(--font-serif);
  font-size: var(--text-h2);
  line-height: var(--leading-h2);
  letter-spacing: var(--track-h2);
  font-weight: var(--weight-medium);
  margin: 0;
  text-wrap: pretty;
}

/* Per-section heading modifiers — size only. The measure caps that used to be
   here made every heading stop at a different fraction of the space available
   to it, which is what made the page read as bunched to the left. A full-width
   heading now runs to the content column; a heading inside a two-column split
   is already constrained by its column and needs no cap of its own. */
.h2--broken { font-size: clamp(1.75rem, 3.4vw, 2.5rem); line-height: 1.12; }
.h2--record { font-size: clamp(1.875rem, 3.8vw, 2.75rem); }
.h2--assessment { font-size: clamp(1.75rem, 3.6vw, 2.75rem); line-height: 1.08; }
.h2--contact { font-size: clamp(1.75rem, 3.4vw, 2.5rem); }
.h1--about { font-size: clamp(2.125rem, 4.4vw, 3.125rem); max-width: 22ch; }
.h1--contact { font-size: clamp(1.875rem, 3.8vw, 2.625rem); line-height: 1.08; max-width: 20ch; }

.h3 {
  font-family: var(--font-serif);
  font-size: var(--text-h3);
  line-height: var(--leading-h3);
  font-weight: var(--weight-semibold);
  margin: 0;
}

/* Eyebrow — decorative. Never a substitute for a heading. */
.eyebrow {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.eyebrow--accent { color: var(--accent); }
.eyebrow--dark { color: var(--dark-muted); }

/* Label — the caps text above a control. This IS the label, not a placeholder. */
.label {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
}

.label--accent { color: var(--accent); }
.label--ink { color: var(--ink); }
.label--lift { color: var(--accent-lift); }
.label--paper { color: var(--paper); }
.label--error { color: var(--error); }

.lead {
  font-size: var(--text-lead);
  line-height: var(--leading-body);
  color: var(--muted);
  max-width: var(--measure-flow);
  margin: 0;
}

.prose { max-width: var(--measure-prose); }
.muted { color: var(--muted); }
.fine { font-size: var(--text-fine); line-height: var(--leading-tight-body); color: var(--muted); }
.finer { font-size: var(--text-finer); line-height: var(--leading-tight-body); color: var(--muted); }

/* Figures are data. Serif, tabular, tightly tracked. */
.figure {
  font-family: var(--font-serif);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-display);
  line-height: var(--leading-flush);
  font-variant-numeric: lining-nums tabular-nums;
}


/* ------------------------------------------------------------ utilities -- */
/* Viewport copy variants. The mobile prototype shortens most strings; static
   HTML cannot swap text by width without shipping both. `display: none` keeps
   the inactive one out of the accessibility tree entirely, so a screen reader
   announces exactly one. The cost is duplicated strings in the source — see
   docs/SEO.md. */
.copy-narrow { display: none; }

@media (max-width: 46.875rem) {
  .copy-wide { display: none; }
  .copy-narrow { display: revert; }
}

/* Keeps a hyphenated phrase from breaking across lines. At display sizes a
   line ending in "full-" reads as a mistake rather than a hyphenation. */
.nowrap { white-space: nowrap; }

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

/* -------------------------------------------------------------- layout -- */
.wrap {
  width: 100%;
  max-width: var(--measure-page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  border-top: var(--rule);
  padding-block: var(--section-y);
}

.section--tight { padding-block: var(--section-y-tight); }
.section--subtle { background: var(--subtle); }
.section--paper { background: var(--paper); }

.section--dark {
  background: var(--dark-ground);
  color: var(--paper);
}

.section__head { margin-bottom: var(--gap-intro-content); }
.section__head .h2 { margin-top: var(--gap-eyebrow-heading); }
.section__head .lead { margin-top: var(--gap-heading-intro); }
.section__head--flush { margin-bottom: 0; }

/* A heading that follows an eyebrow directly, outside a .section__head. */
.h2--after-eyebrow { margin-top: var(--gap-eyebrow-heading); }

/* Section that supplies its own vertical padding (the ALSO band). */
.section--flush { padding-block: 0; }

/* Flush at the top only. The About page's portrait is meant to begin directly
   under the nav, so that section takes --flush — but --flush zeroes both ends,
   and its call to action finished 1px above the ALSO band's hairline. A button
   sitting on a rule reads as a collision, not as a boundary. */
.section--flush-top { padding-block: 0 var(--section-y); }

/* --------------------------------------------------------- skip / focus -- */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: var(--z-skip);
  transform: translateY(-250%);
  background: var(--ink);
  color: var(--paper);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-control);
  font-size: var(--text-small);
  transition: transform var(--duration) var(--ease);
}

.skip-link:focus-visible {
  transform: translateY(0);
  color: var(--paper);
}

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

.section--dark :focus-visible { outline-color: var(--accent-lift); }
:focus:not(:focus-visible) { outline: none; }

/* ----------------------------------------------------------------- nav -- */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: var(--nav-ground);
  backdrop-filter: blur(8px);
  border-bottom: var(--rule);
}

@supports not (backdrop-filter: blur(1px)) {
  .nav { background: var(--paper); }
}

.nav__inner {
  min-height: var(--nav-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-serif);
  font-size: 1.1875rem;            /* 19 */
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-wordmark);
  color: var(--ink);
  white-space: nowrap;
}

.wordmark:hover { color: var(--ink); }
.wordmark__mark { width: 24px; height: 24px; border-radius: 4px; flex: none; }

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(0.875rem, 3vw, 1.875rem);
}

.nav__link {
  font-size: var(--text-small);
  color: var(--muted);
}

.nav__link:hover { color: var(--ink); }

.nav__link[aria-current="page"] {
  color: var(--ink);
  font-weight: var(--weight-medium);
}

/* The ASSESSMENT chip — low emphasis, hairline box, accent text. */
.chip {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--accent);
  border: var(--rule);
  border-radius: var(--radius-control);
  padding: var(--chip-padding);
  white-space: nowrap;
  transition: border-color var(--duration) var(--ease), color var(--duration) var(--ease);
}

.chip:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 26.5rem) {
  .wordmark { font-size: 1.0625rem; gap: var(--space-2); }
  .wordmark__mark { width: 21px; height: 21px; }
  .nav__links { gap: var(--space-3); }
  .nav__link { font-size: var(--text-fine); }
  .chip { padding: var(--space-2) 0.6875rem; letter-spacing: 0.08em; }
}

/* Below 380px the two text links cannot coexist with the chip. The chip is the
   conversion path, so the links go and the wordmark still reaches the home
   page — nothing becomes unreachable. */
/* Below this the header keeps only the wordmark and the Assessment chip.

   The threshold was 23.75rem when the nav carried three links. A fourth
   (Contact) pushed the row to 458px, so between 381px and about 470px the whole
   page scrolled sideways. Measured rather than estimated: tightening the gap or
   the type in that band recovers roughly 30px of the 77px needed, so the row
   genuinely does not fit and hiding it is the honest fix.

   Nothing becomes unreachable: the footer carries Contact, Privacy, Terms, the
   email address and LinkedIn on every page, and the Assessment chip stays in
   the header at every width. */
@media (max-width: 32rem) {
  .nav__link:not(.chip) { display: none; }
}

/* ------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border-radius: var(--radius-control);
  padding: var(--button-padding);
  font-family: var(--font-sans);
  font-size: var(--text-body-dense);
  font-weight: var(--weight-medium);
  line-height: 1.3;
  cursor: pointer;
  transition: background var(--duration) var(--ease),
              border-color var(--duration) var(--ease),
              color var(--duration) var(--ease);
}

.btn--primary {
  background: var(--accent);
  color: var(--button-text);
  border: 1px solid var(--accent);
}

.btn--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--button-text);
}

.btn--primary:active {
  background: var(--accent-active);
  border-color: var(--accent-active);
}

.btn--primary:disabled {
  background: var(--subtle);
  color: var(--disabled-text);
  border-color: var(--hairline);
  cursor: not-allowed;
}

.btn--secondary {
  background: var(--paper);
  color: var(--ink);
  border: var(--rule);
}

.btn--secondary:hover { border-color: var(--ink); color: var(--ink); }
.btn--secondary:active { background: var(--subtle); border-color: var(--ink); }

.btn--cta { padding: var(--cta-padding); }

/* An underlined ink link with an accent rule — "Scoped with you". */
.link-strong {
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
}

.link-strong:hover { color: var(--accent); }

@media (max-width: 46.875rem) {
  .btn { min-height: var(--tap-target-lg); width: 100%; }
  .btn--inline { width: auto; }
}

/* ---------------------------------------------------------------- hero -- */
/* The eyebrow, the headline, the intro block and the aside are four separate
   grid items rather than a left column plus an aside. That is what lets the
   headline span the full content column instead of being boxed into whatever
   share of the width the aside left it — it was reading as half a page of type
   with an empty right half above the fold.

   Row gap is zero on purpose: the vertical rhythm here comes from each block's
   own margin-top, which is tuned per element. A grid row-gap would stack on top
   of those and space the hero out twice. */
/* The hero is a single column now. It was two, with a "WHO CALLS ME" aside in
   the right one; that sentence moved into the introduction, which says the same
   thing in the first person, so the column it lived in went with it.

   Everything is held to --measure-flow, and the portrait plus its gap plus the
   text column add up to exactly that, so the hero shares one right edge with
   the rest of the page. */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: 0;
  padding-block: var(--section-y-hero-top) var(--section-y);
}

.hero__title { margin-top: clamp(1.625rem, 4vh, 2.25rem); }

/* The opening paragraph runs the full measure on its own. The portrait then
   floats right and the two paragraphs below it wrap around it, so the block
   reads as one column of prose with a photograph set into it rather than as a
   photo-plus-text row. The float sits between paragraph one and paragraph two
   in the markup, which is what gives it something to wrap. */
.hero__intro {
  margin-top: clamp(1.625rem, 4vh, 2.125rem);
  max-width: var(--measure-flow);
}

/* No clear needed: .hero is a grid, so .hero__intro is a grid item, which
   establishes its own formatting context and already contains its float. The
   call to action is a separate grid item the float cannot reach. */

.hero__portrait {
  float: right;
  /* 125px floor, 250px ceiling. 21vw reaches the ceiling at about a 1190px
     viewport, which is roughly where the content column stops growing, so the
     portrait and the column top out together. */
  width: clamp(125px, 21vw, 250px);
  /* The top margin is the same token the paragraphs use, so the portrait's top
     edge lands exactly on the top of the second paragraph beside it. A float is
     placed after the preceding block, not after the following block's margin,
     so without this it sat 14px high. */
  margin: var(--space-4) 0 var(--space-4) clamp(1.125rem, 3vw, 2rem);
}

/* The frame lives on the picture, not the figure. It used to be on the figure,
   but a figure that clips to a 4:5 box with overflow: hidden has nowhere to put
   a caption. */
.hero__portrait picture {
  display: block;
  aspect-ratio: 4 / 5;
  border: var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--subtle);
}

.hero__caption {
  margin-top: 0.625rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.hero__caption-name {
  font-family: var(--font-serif);
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-name);
}

.hero__caption-role {
  font-size: var(--text-finer);
  font-weight: var(--weight-medium);
  /* Slightly tighter than --track-label. At the 125px minimum photo width
     "FRACTIONAL CTO" measured exactly 125px at the standard tracking, which
     leaves nothing for a fallback font to borrow while the webfont loads. */
  letter-spacing: 0.07em;
  text-transform: uppercase;
  /* Muted, not accent. The eyebrow above already sets "FRACTIONAL CTO" in
     accent caps, and repeating the treatment a few lines later reads as an
     echo rather than emphasis. A caption is subordinate to the name it sits
     under. */
  color: var(--muted);
}

.hero__portrait img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* A 125px portrait needs a column beside it to wrap into, and on the very
   narrowest phones there is not one: at a 320px viewport the float leaves 137px,
   about 19 characters, and the paragraph breaks into two- and three-word lines.
   There it stops floating and sits on its own line at full size.

   The threshold is 22rem rather than something more cautious because the wrap
   is what the layout is for, and it survives a narrower column than a character
   count suggests: 375px leaves 26 characters and 390px leaves 28, both of which
   read acceptably against a photograph only six lines tall. Every common phone
   therefore gets the same composition as the desktop. */
@media (max-width: 22rem) {
  .hero__portrait {
    float: none;
    margin: var(--space-4) 0 0;
  }
}

/* The opening line keeps the design's muted lead voice; the paragraphs under it
   are ink, because three paragraphs of muted grey is a wall rather than a lede. */
.hero__sub {
  margin: 0;
  font-size: var(--text-lead);
  line-height: var(--leading-body);
  color: var(--muted);
}

.hero__intro > p:not(.hero__sub) {
  margin-top: var(--space-4);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--ink);
}

/* The action row now lives inside .hero__intro, in the same formatting context
   as the floated portrait. A block-level flex container will not overlap a
   float, and at full width it does not fit beside one, so it needs fit-content
   to shrink into the column that is actually free. That reclaims the empty
   space under the two paragraphs, where the portrait is taller than the text.

   Below 48rem what is left beside the portrait is narrower than the button, so
   it clears and sits underneath instead. */
@media (min-width: 48.0625rem) {
  .hero__actions { width: fit-content; }
}

@media (max-width: 48rem) {
  .hero__actions { clear: both; }
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: clamp(2rem, 5vh, 2.75rem);
}

.hero__note {
  font-size: var(--text-small);
  line-height: 1.5;
  color: var(--muted);
}


@media (max-width: 46.875rem) {
  .hero__actions { flex-direction: column; align-items: stretch; gap: 0.875rem; }
  .hero__note { text-align: center; }
}

/* --------------------------------------------------------------- cards -- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr));
  gap: var(--space-4);
}

.card {
  background: var(--paper);
  border: var(--rule);
  border-radius: var(--radius-card);
  padding: clamp(1.375rem, 3vw, 2.125rem);
}

.card__num {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  color: var(--accent);
  margin-bottom: 1.375rem;
  font-variant-numeric: lining-nums tabular-nums;
}

.card .h3 { margin-bottom: var(--space-3); }

.card__body {
  font-size: var(--text-body-dense);
  line-height: var(--leading-tight-body);
  color: var(--muted);
  max-width: var(--measure-card);
}

@media (max-width: 46.875rem) {
  .cards { gap: var(--space-3); }
  .card__num { margin-bottom: 0.875rem; }
  .card .h3 { font-size: 1.25rem; margin-bottom: var(--space-2); }
  .card__body { font-size: var(--text-small); }
}

/* ------------------------------------------------------- proof / record -- */
.section--dark .h2 { color: var(--paper); }

.dark-intro {
  margin-top: 1.375rem;
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--dark-body);
  max-width: var(--measure-flow);
}

/* Four cells, capped at two columns. A px floor would resolve to three at mid
   widths and orphan the fourth — see the README's layout rules. */
.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 46%), 1fr));
  gap: clamp(1.75rem, 4vh, 2.5rem) clamp(1.5rem, 5vw, 3.5rem);
  margin-block: clamp(2.5rem, 6vh, 3.5rem);
}

.metric { border-top: var(--rule-dark-strong); padding-top: var(--space-4); }

.metric__figure {
  font-family: var(--font-serif);
  font-size: var(--figure-metric);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-display);
  line-height: var(--leading-flush);
  font-variant-numeric: lining-nums tabular-nums;
}

.metric__caption {
  font-size: var(--text-fine);
  color: var(--dark-body);
  margin-top: 0.625rem;
  line-height: 1.5;
  max-width: 24ch;
}

/* Escalation list — role label in the left track, company and body spanning
   the remaining two. Three explicit tracks: the prototype's auto-fit resolves
   to four at desktop width and strands every second role label in a column of
   its own. The README's text is the spec, and it says three. */
.record {
  display: grid;
  grid-template-columns: 1fr 2fr;
  column-gap: clamp(1.5rem, 4vw, 2.75rem);
}

.record__role {
  grid-column: 1;
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--accent-lift);
  padding: 1.625rem 0 var(--space-2);
  border-top: var(--rule-dark);
}

.record__body {
  grid-column: 2;
  min-width: 0;
  padding: 1.625rem 0;
  border-top: var(--rule-dark);
}

.record__org {
  font-family: var(--font-serif);
  font-size: 1.5625rem;            /* 25 */
  font-weight: var(--weight-medium);
  line-height: var(--leading-name);
}

.record__line {
  margin-top: 0.625rem;
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--dark-body);
  max-width: var(--measure-row);
}

/* The final row is the reader's own org — the rule and label lift to accent. */
.record__role--now { color: var(--paper); border-top: var(--rule-lift); }
.record__body--now { border-top: var(--rule-lift); }

.record a { color: var(--accent-lift); border-bottom: 1px solid var(--accent-lift); }
.record a:hover { color: var(--paper); border-bottom-color: var(--paper); }

@media (max-width: 46.875rem) {
  .record { grid-template-columns: 1fr; }
  .record__role { grid-column: 1; padding: var(--space-4) 0 0; }
  .record__body { grid-column: 1; padding: var(--space-2) 0 var(--space-4); border-top: 0; }
  .record__org { font-size: 1.375rem; margin-top: var(--space-2); }
  .record__line { font-size: var(--text-small); line-height: var(--leading-tight-body); }
  .metrics { gap: var(--space-4) 1rem; margin-block: var(--space-5); }
  .metric { padding-top: 0.875rem; }
  .metric__figure { font-size: 2.25rem; }
  .metric__caption { font-size: var(--text-finer); margin-top: var(--space-2); }
  .dark-intro { font-size: var(--text-body-dense); }
}

/* --------------------------------------------------------- how I work -- */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 46%), 1fr));
  gap: clamp(1.75rem, 4vh, 2.5rem) clamp(1.5rem, 5vw, 3.5rem);
  margin-top: clamp(2rem, 5vh, 2.75rem);
}

.fact { border-top: var(--rule-ink); padding-top: var(--space-4); }
.fact__label { margin-bottom: 0.875rem; }
.fact__body { font-size: var(--text-body); line-height: var(--leading-tight-body); }

@media (max-width: 46.875rem) {
  .facts { gap: var(--space-5); margin-top: var(--space-5); }
  .fact { padding-top: 0.875rem; }
  .fact__body { font-size: var(--text-body-dense); }
}

/* ------------------------------------------------------------- pricing -- */
/* One priced entry point, stated on a single ruled line.

   This was a four-track ledger row carrying the `--feature` treatment: cream
   fill, ink rules top and bottom, a 50px day count and a "starting point" flag.
   That component was built to emphasise one row among three. With the tiers
   gone it emphasised nothing, and the empty tracks beside a lone row read as
   options that had been removed — which is exactly how it looked. The section
   now states the entry point the way the rest of the page states things: a
   rule, a line, and prose under it. */
.base {
  border-top: var(--rule-ink);
  padding-top: var(--space-4);
  /* Held to the same measure as the prose beneath it, so the rule, the price
     and every line under them share one right edge. Run to the full column and
     the price ends up alone out at the margin with nothing below it — the same
     stranded-element problem the rest of this page was fixed for. */
  max-width: var(--measure-flow);
}

.base__line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
}

.base__name {
  font-family: var(--font-serif);
  font-size: var(--text-company);
  font-weight: var(--weight-medium);
  line-height: var(--leading-name);
}

.base__meta {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
  margin-top: var(--space-2);
}

/* Deliberately smaller than the $5,000 assessment figure. The assessment is
   what the page asks for; this is the number you arrive at afterwards, and it
   does not need to shout to be found. */
.base__price {
  font-family: var(--font-serif);
  font-size: var(--text-company-lg);
  font-weight: var(--weight-medium);
  line-height: var(--leading-name);
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;
}

.base__unit { font-size: var(--text-small); font-weight: var(--weight-regular); color: var(--muted); }

.base__body {
  margin-top: var(--space-4);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  max-width: var(--measure-flow);
}

/* Everything above the base. Prose, because there is no menu to draw. */
.beyond__body {
  margin-top: var(--space-5);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  max-width: var(--measure-flow);
}

.base__note { margin-top: var(--space-4); max-width: var(--measure-flow); }

@media (max-width: 46.875rem) {
  /* The price drops under the name rather than sitting far across a narrow
     line, where the distance stops reading as a relationship. */
  .base__line { gap: var(--space-3); }
  .base__price { margin-top: var(--space-1); }
  .base__body { font-size: var(--text-body-dense); }
}

/* ---------------------------------------------------------- assessment -- */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.split--contact { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }

.assessment__fee {
  display: flex;
  align-items: baseline;
  gap: 0.875rem;
  margin-top: clamp(1.75rem, 4vh, 2.5rem);
}

.assessment__body { margin-top: var(--space-4); max-width: 52ch; }

.assessment__amount {
  font-family: var(--font-serif);
  font-size: var(--figure-fee);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-display);
  font-variant-numeric: lining-nums tabular-nums;
}

.assessment__credit {
  font-size: var(--text-body-dense);
  color: var(--muted);
  margin-top: var(--space-3);
  max-width: 44ch;
  line-height: var(--leading-tight-body);
}

/* Deliverables — a recessed card whose rows are separated by hairlines. */
.steps {
  background: var(--subtle);
  border: var(--rule);
  border-radius: var(--radius-card);
}

.step {
  display: flex;
  gap: 1rem;
  padding: 1.375rem clamp(1.25rem, 2.5vw, 1.75rem);
  border-bottom: var(--rule);
  font-size: var(--text-body-dense);
  line-height: 1.55;
}

.step:last-child { border-bottom: 0; }

.step__num {
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  /* The steps card sits on --subtle; see the contrast note in tokens.css. */
  color: var(--accent-on-subtle);
  padding-top: 3px;
  font-variant-numeric: lining-nums tabular-nums;
  flex: none;
}

@media (max-width: 46.875rem) {
  .step { padding: 1.125rem; gap: var(--space-3); font-size: var(--text-small); }
}

/* ---------------------------------------------------------------- form -- */
.contact__title { margin-top: var(--gap-eyebrow-heading); }
.contact__body { margin-top: 1.375rem; max-width: 44ch; }

.contact-meta {
  font-size: var(--text-small);
  color: var(--muted);
  margin-top: 1.75rem;
  line-height: 1.9;
}

.form-card {
  background: var(--paper);
  border: var(--rule);
  border-radius: var(--radius-card);
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.form {
  display: grid;
  /* minmax(0, 1fr) rather than the default auto track: a third-party widget
     with a fixed intrinsic width must not be able to widen the column, and
     through it the whole document. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

.field-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr));
  gap: var(--space-4);
  /* Same reason as .field below: this is itself a grid item, and its own
     min-content width is set by the controls inside it. */
  min-width: 0;
}

/* Grid items default to min-width:auto, which resolves to the control's own
   intrinsic minimum — wider than a 320px viewport leaves once the gutter and
   card padding are taken out. Without this the field pair pushes the page
   sideways on the smallest handsets. */
.field { display: block; min-width: 0; }

.field__label {
  display: block;
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--space-2);
}

.field__control {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 1rem;                 /* 16 — never smaller; iOS zooms below it */
  color: var(--ink);
  padding: var(--control-padding);
  border: var(--rule);
  border-radius: var(--radius-control);
  background: var(--input-surface);
  outline: none;
  transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}

.field__control::placeholder { color: var(--muted); opacity: 0.8; }

.field__control:focus {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}

textarea.field__control { line-height: var(--leading-tight-body); resize: vertical; }

select.field__control {
  appearance: none;
  /* Chevron in --ink. The encoded %231B1917 must track the ink token. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%231B1917' stroke-width='1.3'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.875rem center;
  background-size: 12px 8px;
  padding-right: 2.25rem;
}

/* Error: border, label, and helper text all take the error colour. */
.field--invalid .field__label { color: var(--error); }
.field--invalid .field__control { border-color: var(--error); }
.field--invalid .field__control:focus { border-color: var(--error); box-shadow: var(--focus-ring-error); }

.field__required {
  /* Appended to the label only when the field is in its error state. */
  display: none;
}

.field--invalid .field__required { display: inline; }

.field__error {
  display: block;
  font-size: var(--text-fine);
  color: var(--error);
  margin-top: var(--space-2);
  line-height: 1.5;
}

.field__error:empty { display: none; }

/* Honeypot. Hidden from people and from assistive tech, but a real focusable-
   by-nothing input that a naive bot will fill. Not display:none — some bots
   skip those. */
.hp {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

.form__note { font-size: var(--text-fine); color: var(--muted); }

.form__status { line-height: var(--leading-tight-body); }
.form__status:empty { display: none; }

.form__status[data-state] {
  font-size: var(--text-fine);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-control);
  border: var(--rule);
}

.form__status[data-state="error"] { border-color: var(--error); color: var(--error); }
.form__status[data-state="submitting"] { color: var(--muted); }

.form--busy .field__control { opacity: 0.75; pointer-events: none; }

/* Turnstile injects a container with a fixed 300px width — including for its
   own error state, which is wider than a 320px viewport leaves inside the form
   card. Nothing third-party may widen the document, so this one region scrolls
   instead. In practice it never has to: contact-form.js renders the compact
   widget when the column is under 300px. */
.turnstile {
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
}

.turnstile:not(:empty) { margin-top: var(--space-1); }

/* Success replaces the form outright. */
.received {
  border: 1px solid var(--accent);
  border-radius: var(--radius-card);
  padding: clamp(1.75rem, 3vw, 2.5rem);
  background: var(--paper);
}

.received__title {
  font-family: var(--font-serif);
  font-size: 1.625rem;             /* 26 */
  font-weight: var(--weight-medium);
  line-height: 1.25;
  margin: var(--space-4) 0 var(--space-3);
}

.received__body {
  font-size: var(--text-body-dense);
  line-height: var(--leading-body);
  color: var(--muted);
  max-width: 44ch;
}

@media (max-width: 46.875rem) {
  .form { gap: 1rem; }
  .field-pair { gap: 1rem; }
  .field__control { min-height: var(--tap-target); }
  textarea.field__control { min-height: 7.5rem; }
  .form__actions { align-items: stretch; }
}

/* ------------------------------------------------------- also + footer -- */
.also {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem var(--space-5);
  align-items: baseline;
  padding-block: 2.125rem;
}

.also__body {
  font-size: var(--text-body-dense);
  line-height: var(--leading-tight-body);
  color: var(--muted);
  /* A flex item sizes to its content by default, so this line stopped well
     short of its measure while the row still had space. Let it grow to the
     shared edge like every other block. */
  flex: 1 1 auto;
  max-width: var(--measure-flow);
}

.footer {
  border-top: var(--rule);
  background: var(--subtle);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem var(--space-5);
  padding-block: var(--space-5) 3.5rem;
}

.footer__entity {
  font-family: var(--font-serif);
  font-size: var(--text-body);
  color: var(--muted);
}

.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  font-size: var(--text-small);
}

/* The footer ground is --subtle, as is the contact section. */
.footer__links a,
.contact-meta a { color: var(--accent-on-subtle); }
.footer__links a:hover,
.contact-meta a:hover { color: var(--ink); }

@media (max-width: 46.875rem) {
  .footer__inner { flex-direction: column; gap: var(--space-3); padding-block: 1.625rem 2.125rem; }
  .footer__links { flex-direction: column; gap: var(--space-2); }
  .also { padding-block: var(--space-4); }
}

/* ------------------------------------------------------------- consent -- */
.consent {
  position: fixed;
  inset: auto var(--gutter) var(--gutter);
  z-index: var(--z-consent);
  max-width: 34rem;
  margin-inline: auto;
  background: var(--paper);
  border: var(--rule-ink);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  display: grid;
  gap: var(--space-3);
}

.consent__text { font-size: var(--text-fine); line-height: var(--leading-tight-body); color: var(--muted); }
.consent__text strong { color: var(--ink); font-weight: var(--weight-semibold); }
.consent__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.consent__btn {
  flex: 1 1 auto;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-fine);
  min-height: 0;
  width: auto;
}

/* --------------------------------------------------------------- about -- */
.about {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.about__main { min-width: 0; }

@media (min-width: 60rem) {
  .about { grid-template-columns: minmax(280px, 1fr) 2fr; }
}

.portrait {
  aspect-ratio: 4 / 5;
  border: var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--subtle);
}

.portrait img { width: 100%; height: 100%; object-fit: cover; }

.namecard { margin-top: var(--space-4); border-top: var(--rule-ink); padding-top: 1.125rem; }

.namecard__name {
  font-family: var(--font-serif);
  font-size: var(--text-company);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-name);
}

.namecard__meta { font-size: var(--text-small); color: var(--muted); margin-top: var(--space-2); line-height: 1.8; }

.bio {
  margin-top: clamp(1.75rem, 4vh, 2.25rem);
  max-width: var(--measure-prose);
  font-size: var(--text-body);
  line-height: var(--leading-bio);
}

.bio p + p { margin-top: var(--space-4); }

.about__timeline { margin-top: clamp(2.5rem, 6vh, 4rem); }
.about__cta { margin-top: clamp(2rem, 5vh, 2.75rem); }

/* Same three-track rule as the record list, same reason. */
.timeline {
  display: grid;
  grid-template-columns: 1fr 2fr;
  column-gap: clamp(1rem, 3vw, 2rem);
  margin-top: var(--space-4);
  border-top: var(--rule-ink);
}

.timeline__co {
  grid-column: 1;
  font-size: var(--text-caps);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
  padding: 1.375rem 0 0.375rem;
}

.timeline__co--now { color: var(--accent); }

.timeline__entry {
  grid-column: 2;
  min-width: 0;
  padding: 1.375rem 0;
  border-bottom: var(--rule);
}

.timeline__role {
  font-family: var(--font-serif);
  font-size: 1.3125rem;            /* 21 */
  font-weight: var(--weight-medium);
  line-height: var(--leading-name);
}

.timeline__line { font-size: var(--text-body-dense); color: var(--muted); margin-top: 0.375rem; line-height: var(--leading-tight-body); }

@media (max-width: 46.875rem) {
  .timeline { grid-template-columns: 1fr; }
  .timeline__co { grid-column: 1; padding: var(--space-4) 0 0; }
  .timeline__entry { grid-column: 1; padding: var(--space-2) 0 var(--space-4); }
}

/* ------------------------------------------------------------- contact -- */
.fastest-path {
  border: var(--rule);
  border-radius: var(--radius-card);
  background: var(--paper);
  padding: 1.625rem;
  margin-top: var(--space-5);
  max-width: 42ch;
}

.fastest-path__body { font-size: var(--text-body-dense); line-height: var(--leading-body); margin-top: var(--space-3); }

.contact-page { padding-block: var(--section-y); }
.contact-page__body { margin-top: 1.375rem; max-width: 46ch; }

.fastest-path__amount {
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  font-variant-numeric: lining-nums tabular-nums;
}

/* --------------------------------------------------------------- legal -- */
.legal { max-width: var(--measure-prose); }

.legal h2 {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: var(--weight-medium);
  line-height: var(--leading-h3);
  letter-spacing: var(--track-h2);
  margin-top: var(--space-7);
  padding-top: var(--space-4);
  border-top: var(--rule);
  margin-bottom: var(--space-4);
}

.legal h2:first-of-type { margin-top: var(--space-5); }

/* The block does not always open with a heading. When it opens with a
   paragraph, it needs the same clearance from the "last updated" line above
   it, which otherwise sits flush against the first sentence. */
.legal > :first-child { margin-top: var(--space-5); }

.legal h3 {
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  font-weight: var(--weight-semibold);
  margin: var(--space-5) 0 var(--space-3);
}

.legal p { margin-bottom: var(--space-4); font-size: var(--text-body-dense); line-height: var(--leading-bio); }
.legal ul { display: grid; gap: var(--space-3); margin-bottom: var(--space-4); }
/* A hanging dash, set with padding and an absolutely positioned marker rather
   than a two-column grid.

   The grid version worked only for a list item whose entire content was one
   text node. Add any inline markup and each child becomes its own grid item:
   <li><strong>Label:</strong> text</li> put the <strong> in the 1fr column and
   pushed the text after it onto the next row, into the 1.1rem marker column,
   which rendered it one word per line. Measured at 422px tall for a two-line
   item. A block list item has no such rule about its children. */
.legal ul li {
  position: relative;
  padding-left: calc(1.1rem + var(--space-3));
  line-height: var(--leading-tight-body);
  font-size: var(--text-body-dense);
}

.legal ul li::before {
  content: "—";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--muted);
}
.legal dl { display: grid; gap: var(--space-4); margin-bottom: var(--space-4); }
.legal dt { margin-bottom: var(--space-2); }
.legal dd { margin: 0; font-size: var(--text-body-dense); line-height: var(--leading-tight-body); }
.legal code { font-family: var(--font-sans); font-size: 0.95em; background: var(--subtle); padding: 0.1em 0.35em; border-radius: 3px; }
.legal a { border-bottom: 1px solid var(--hairline); }
.legal a:hover { border-bottom-color: var(--accent); }

.legal__updated { margin-top: var(--space-4); }

/* ----------------------------------------------------------------- 404 -- */
/* --------------------------------------------------------- legal pages -- */
.legal-page { padding-block: var(--section-y-tight); }
/* The lede introduces the prose beneath it, so it takes the prose measure,
   not the wider flow measure .lead carries on the home page. An intro that
   overhangs the column it introduces reads as a mistake. */
.legal-page__lede { margin-top: var(--gap-heading-intro); max-width: var(--measure-prose); }

.notfound { padding-block: clamp(4rem, 14vh, 8rem); }
.notfound__lede { margin-top: var(--space-4); }
.notfound__links { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: var(--space-5); }
.notfound__links .btn { width: auto; }

/* --------------------------------------------------------------- print -- */
@media print {
  .nav, .consent, .skip-link, .form-card { display: none !important; }
  .section--dark { background: var(--paper); color: var(--ink); }
}
