/* =============================================================================
   jangulo.com — design system (v2, light ground)
   -----------------------------------------------------------------------------
   Hand-written, dependency-free. Replaces the compiled-Tailwind stylesheet for
   the home page: every colour on the page resolves through the token block
   below, so the whole theme flips by editing the six *-rgb primitives — nothing
   downstream hardcodes a colour.

   Tokens are stored as space-separated RGB channels so any rule can take an
   alpha:  rgb(var(--ink-rgb) / .12)
   ========================================================================== */

:root {
  /* --- primitives: the only place a literal colour appears -----------------
     Values are the Nocturne palette, inverted to a light ground. The violet
     ramp is #F4F4FF · #E7E4FF · #D2CDFF · #B6AAFF · #978AE0 · #796DBC ·
     #5D5294 · #423A6A; the accent below is the step with contrast on this
     ground, and the console's accent is the step with contrast on Nocturne's
     own dark ground. Contrast ratios are measured, not estimated. */
  --ground-rgb:        243 245 254;   /* #F3F5FE — light lavender-grey, not white  */
  --surface-rgb:       255 255 255;   /* raised cards                              */
  --ink-rgb:            41  43  49;   /* #292B31 — body text (13.0:1 on ground)    */
  --ink-muted-rgb:      89  93 108;   /* #595D6C — secondary text (6.0:1)          */
  --accent-rgb:         93  82 148;   /* #5D5294 — Nocturne violet (6.2:1)         */
  --on-accent-rgb:     255 255 255;   /* text on accent fills (6.8:1)              */
  --accent-wash-rgb:   231 228 255;   /* #E7E4FF — ramp step 2, the stat-band ground */

  /* Console island: a terminal keeps Nocturne's own dark ground on the light
     page. Still tokens — flipping the page theme leaves these coherent. */
  --console-rgb:        22  24  38;   /* #161826 — Nocturne ground                 */
  --console-2-rgb:      35  37  50;   /* #232532 — Nocturne surface                */
  --console-3-rgb:      46  48  64;
  --console-ink-rgb:   233 233 237;   /* #E9E9ED (14.5:1)                          */
  --console-muted-rgb: 149 152 166;   /* #9598A6 (6.1:1)                           */
  --console-accent-rgb:182 170 255;   /* #B6AAFF — Nocturne violet, light step     */

  /* --- semantic aliases ---------------------------------------------------- */
  --ground:      rgb(var(--ground-rgb));
  --surface:     rgb(var(--surface-rgb));
  --ink:         rgb(var(--ink-rgb));
  --ink-muted:   rgb(var(--ink-muted-rgb));
  --accent:      rgb(var(--accent-rgb));
  --on-accent:   rgb(var(--on-accent-rgb));
  --accent-soft: rgb(var(--accent-rgb) / .09);
  /* The raised-card surface. Same value as the stat band, so the band and the
     cards read as one material rather than two accidents. */
  --surface-wash: rgb(var(--accent-wash-rgb));
  --accent-line: rgb(var(--accent-rgb) / .28);
  --rule:        rgb(var(--ink-rgb) / .12);
  --rule-soft:   rgb(var(--ink-rgb) / .07);
  --shadow-sm:   0 1px 2px rgb(var(--ink-rgb) / .04), 0 8px 24px -16px rgb(var(--ink-rgb) / .18);
  --shadow-md:   0 2px 4px rgb(var(--ink-rgb) / .04), 0 24px 48px -28px rgb(var(--ink-rgb) / .28);

  /* --- type --------------------------------------------------------------- */
  --sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- measure ------------------------------------------------------------ */
  --wrap: 72rem;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-y: clamp(3rem, 5.5vw, 5rem);
  --radius: 14px;
}

/* -----------------------------------------------------------------------------
   To ship the dark theme instead, swap the primitives above for these — nothing
   else in this file, and no markup, needs to change:

     --ground-rgb: 22 24 38;   --surface-rgb: 35 37 50;   --ink-rgb: 233 233 237;
     --ink-muted-rgb: 149 152 166;  --accent-rgb: 182 170 255;
     --on-accent-rgb: 22 24 38;     --accent-wash-rgb: 46 48 64;

   — i.e. Nocturne as originally designed, with no other change anywhere.
   -------------------------------------------------------------------------- */

/* ============================ base ======================================== */

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

html { scroll-behavior: smooth; scroll-padding-top: 5rem; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 400 clamp(1rem, .97rem + .15vw, 1.06rem)/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "cv05" 1, "ss01" 1;
}

img, svg { display: block; max-width: 100%; }
h1, h2, h3, h4, p, figure, blockquote, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

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

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--ground);
  padding: .7rem 1.1rem; border-radius: 0 0 8px 0; font-size: .9rem;
}
.skip:focus { left: 0; }

/* zero-size targets that keep older deep links (#expertise, #credentials) alive */
.anchor-alias { display: block; height: 0; }

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

/* ======================= layout primitives ================================ */

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

.section { padding-block: var(--section-y); }
.section--ruled { border-top: 1px solid var(--rule-soft); }

.eyebrow {
  font: 500 .7rem/1 var(--mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
}

.h1 {
  font-size: clamp(2.3rem, 1.2rem + 4.6vw, 4.15rem);
  line-height: 1.03;
  letter-spacing: -.035em;
  font-weight: 600;
  text-wrap: balance;
}
.h2 {
  font-size: clamp(1.65rem, 1.15rem + 1.9vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -.03em;
  font-weight: 600;
  text-wrap: balance;
}
.h3 { font-size: 1.13rem; line-height: 1.3; letter-spacing: -.015em; font-weight: 600; }

.lede { font-size: clamp(1.02rem, .97rem + .3vw, 1.19rem); line-height: 1.6; color: var(--ink-muted); }
/* Progressive: browsers without `pretty` fall back to `wrap` and lose only the
   orphan control. Applied to running text, never to the display sizes, which
   already balance. */
p, li, dd, blockquote, figcaption, .card__desc, .artifact__desc { text-wrap: pretty; }
.muted { color: var(--ink-muted); }
.accent { color: var(--accent); }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.small { font-size: .875rem; line-height: 1.6; }

/* vertical rhythm inside a section: eyebrow → heading → lede/body */
.eyebrow + .h2 { margin-top: 1.25rem; }
.h2 + .lede, .h2 + .bench__body { margin-top: 1.5rem; }

/* measure caps */
.mw-xs { max-width: 20ch; }
.mw-sm { max-width: 24ch; }
.mw-md { max-width: 46ch; }
.mw-lg { max-width: 64ch; }

/* underline-on-hover text link */
.link {
  color: var(--accent);
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size .3s ease;
  padding-bottom: 1px;
}
.link:hover, .link:focus-visible { background-size: 100% 1px; }
.link--quiet { color: var(--ink-muted); background-image: linear-gradient(currentColor, currentColor); }
.link--quiet:hover { color: var(--ink); }

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font: 500 .9rem/1 var(--sans);
  padding: .85rem 1.35rem;
  border-radius: 999px;
  border: 1px solid var(--accent);
  color: var(--accent);
  background: transparent;
  cursor: pointer;
  transition: background-color .22s ease, color .22s ease, transform .22s ease;
}
.btn:hover { background: var(--accent); color: var(--on-accent); }
.btn--solid { background: var(--accent); color: var(--on-accent); }
.btn--solid:hover { background: var(--ink); border-color: var(--ink); }
.btn--quiet { border-color: var(--rule); color: var(--ink); }
.btn--quiet:hover { background: var(--ink); border-color: var(--ink); color: var(--ground); }

/* ============================= header ===================================== */

.site-head {
  position: sticky; top: 0; z-index: 40;
  background: rgb(var(--ground-rgb) / .82);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s ease;
}
.site-head[data-stuck="true"] { border-bottom-color: var(--rule-soft); }
/* zero-size probe the header watches to know it has left the top of the page */
.stuck-sentinel { position: absolute; top: 0; width: 1px; height: 1px; }

.site-head .wrap {
  height: 4.25rem;
  display: flex; align-items: center; gap: 1.5rem;
}
.brand { font-weight: 600; letter-spacing: -.02em; font-size: 1rem; margin-right: auto; }
.brand span { color: var(--accent); }

.site-nav { display: flex; align-items: center; gap: 1.75rem; }
/* :not(.btn) matters — a bare `.site-nav a` rule (0,1,1) outranks the .btn--solid
   colour (0,1,0) and would repaint the button's label. */
.site-nav a:not(.btn) { font-size: .9rem; color: var(--ink-muted); transition: color .2s ease; }
.site-nav a:not(.btn):hover { color: var(--ink); }
.site-nav .btn { padding: .6rem 1.05rem; font-size: .85rem; }

@media (max-width: 46rem) {
  .site-nav a:not(.btn) { display: none; }
}

/* ============================== hero ====================================== */

.hero { padding-block: clamp(3.5rem, 7vw, 6.5rem) clamp(2.5rem, 5vw, 4rem); }

.hero__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 60rem) {
  .hero__grid { grid-template-columns: minmax(0, 1.35fr) minmax(0, .8fr); }
}

.hero__eyebrow { margin-bottom: 1.5rem; }
.hero__sub { margin-top: 1.6rem; max-width: 46ch; }
.hero__cta { margin-top: 2.25rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }

.hero__portrait {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-md);
  aspect-ratio: 341 / 410;
}
.hero__portrait img { width: 100%; height: 100%; object-fit: cover; }
.hero figcaption {
  margin-top: .9rem;
  font: 400 .72rem/1.5 var(--mono);
  color: var(--ink-muted);
  letter-spacing: .01em;
}
@media (max-width: 59.99rem) {
  .hero__portrait { max-width: 20rem; }
}

/* The repositioning sentence: quieter than the lede, but structurally marked
   so the domain-to-method transfer is read, not skimmed past. */
.hero__transfer {
  margin-top: 1.4rem;
  max-width: 46ch;
  padding-left: 1.15rem;
  border-left: 2px solid var(--accent-line);
  font-size: .93rem; line-height: 1.65;
  color: var(--ink-muted);
}

.hero__note {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule-soft);
  font: 400 .84rem/1.6 var(--mono);
  color: var(--ink-muted);
}
.hero__note b { color: var(--ink); font-weight: 500; }

/* =========================== stat band ==================================== */

.stats { border-block: 1px solid var(--accent-line); background: rgb(var(--accent-wash-rgb)); }
.stats .wrap {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 2.5rem;
  padding-block: clamp(2rem, 4vw, 2.75rem);
}
@media (min-width: 52rem) { .stats .wrap { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.stat { display: block; }
.stat__fig { display: block; font: 500 clamp(1.6rem, 1.3rem + 1vw, 2.1rem)/1 var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.stat__fig { white-space: nowrap; }
.stat__label { display: block; margin-top: .65rem; font-size: .82rem; line-height: 1.45; color: var(--ink-muted); max-width: 24ch; }
a.stat .stat__label { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px; transition: text-decoration-color .25s ease, color .25s ease; }
a.stat:hover .stat__label { color: var(--ink); text-decoration-color: var(--accent-line); }

/* ============================ practice ==================================== */

.practice__grid {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  display: grid;
  gap: clamp(2rem, 4vw, 2.75rem) 2.25rem;
  grid-template-columns: 1fr;
}
.practice__item { border-top: 1px solid var(--rule); padding-top: clamp(1.25rem, 2.5vw, 1.75rem); }
@media (min-width: 40rem) { .practice__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 68rem) { .practice__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.practice__num { font: 500 .72rem/1 var(--mono); letter-spacing: .12em; color: var(--accent); }
.practice__item h3 { margin-top: 1.1rem; }
.practice__item p { margin-top: .65rem; font-size: .9rem; line-height: 1.6; color: var(--ink-muted); }

/* =========================== research agenda ==============================
   The page's forward-looking block, and deliberately not built from `.card`:
   planned work must not borrow the visual language of shipped work. A full
   accent rule marks the two primary questions; the applied arm gets the
   hairline instead, so the demotion is legible without a caveat sentence. */

.agenda {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  display: grid;
  gap: clamp(2rem, 4vw, 2.5rem) 2.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .agenda { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 66rem) { .agenda { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.agenda__item { border-top: 2px solid var(--accent); padding-top: 1.35rem; }
.agenda__item--arm { border-top-color: var(--accent-line); }
.agenda__n {
  display: block;
  font: 500 clamp(1.45rem, 1.2rem + .7vw, 1.85rem)/1 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--accent);
}
/* Measured, not estimated: .55 alpha put the demoted numeral at 2.41:1 on the
   ground. .75 reads as the same demotion and clears 3.58:1 — AA for text this
   size (≥23px, 500 weight). */
.agenda__item--arm .agenda__n { color: rgb(var(--accent-rgb) / .75); }
.agenda__k {
  margin-top: .8rem;
  font: 600 1.04rem/1.35 var(--sans);
  letter-spacing: -.015em;
}
.agenda__tag {
  display: inline-block; vertical-align: .15em;
  margin-left: .5rem;
  font: 500 .6rem/1 var(--mono);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-muted);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .3rem .5rem;
}
.agenda__body { margin-top: .85rem; font-size: .91rem; line-height: 1.62; color: var(--ink-muted); }

/* ========================= what I work on =================================
   Six domains on the rule-topped column that `.pillar` established, at two
   thirds the weight: this is the taxonomy a screener scans, not a pitch. */

.domains {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  display: grid;
  gap: clamp(2rem, 4vw, 2.5rem) 2.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .domains { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 68rem) { .domains { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.domain { border-top: 1px solid var(--rule); padding-top: clamp(1.15rem, 2.2vw, 1.5rem); }
.domain__k { font: 500 .71rem/1.5 var(--mono); letter-spacing: .11em; text-transform: uppercase; color: var(--accent); }
.domain__body { margin-top: .85rem; font-size: .89rem; line-height: 1.62; color: var(--ink-muted); }
.domain__body code { font-size: .95em; color: var(--ink); }
.domain__ev { margin-top: .85rem; font-size: .84rem; }

/* ============================= pillars ====================================
   The three pillars that replace the numbered services grid. Same rule-topped
   column as .practice__item — this is that component with evidence under it,
   not a new one — with the shared .bullets list carrying the evidence. */

.pillars {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  display: grid;
  gap: clamp(2.25rem, 4.5vw, 3rem) 2.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 66rem) { .pillars { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.pillar { border-top: 1px solid var(--rule); padding-top: clamp(1.25rem, 2.5vw, 1.75rem); }
.pillar__k { font: 500 .72rem/1 var(--mono); letter-spacing: .12em; color: var(--accent); }
.pillar h3 { margin-top: 1.1rem; }
.pillar__body { margin-top: .7rem; font-size: .9rem; line-height: 1.6; color: var(--ink-muted); }
.pillar__ev {
  margin-top: 1.35rem; padding-top: 1.15rem;
  border-top: 1px solid var(--rule-soft);
  font-size: .86rem;
}
.pillar__ev li { font-size: inherit; }
.pillar__ev code { font-size: .95em; }

/* Everything deliberately off the scan path — domain applications, governance,
   the linguistics background, the leadership record — kept on the page and out
   of the first screen. */
.practice__also {
  margin-top: clamp(2.25rem, 4.5vw, 3rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule-soft);
  font-size: .88rem; line-height: 1.62; color: var(--ink-muted); max-width: 82ch;
  display: grid; gap: .9rem;
}
.practice__also b { color: var(--ink); font-weight: 500; }

/* =========================== benchmark ==================================== */

.bench__grid {
  margin-top: clamp(2rem, 4vw, 3rem);
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 62rem) { .bench__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

.bench__grid .h2 { margin-top: 0; }
.bench__body { font-size: clamp(1rem, .95rem + .25vw, 1.13rem); line-height: 1.6; }
.bench__cta { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: .85rem; }
.bench__more { margin-top: 1.1rem; font-size: .9rem; }

.figure-card {
  background: var(--surface-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 2rem);
  box-shadow: var(--shadow-sm);
}
.figure-card svg { width: 100%; height: auto; }
.figure-card figcaption {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule-soft);
  font: 400 .74rem/1.55 var(--mono);
  color: var(--ink-muted);
}

/* Taxonomy SVG — every fill and stroke comes from a token, so the figure
   re-themes with the page instead of being a baked-in raster. The four leakage
   paths are told apart by numbered badge and line style, not by hue, so the
   single-accent rule holds and the figure survives greyscale printing. */
.tax__grid  { stroke: rgb(var(--ink-rgb) / .05); }
.tax__node  { fill: rgb(var(--surface-rgb)); stroke: var(--rule); }
.tax__node--src { fill: var(--accent-soft); stroke: var(--accent-line); }
.tax__label { font: 500 9.5px var(--mono); fill: rgb(var(--ink-rgb)); letter-spacing: .09em; }
.tax__sub   { font: 400 8px var(--mono); fill: rgb(var(--ink-muted-rgb)); }
.tax__spine { stroke: rgb(var(--ink-rgb) / .26); stroke-width: 1.25; fill: none; }
.tax__edge  { stroke: rgb(var(--ink-rgb) / .32); stroke-width: 1.25; fill: none; }
.tax__edge--leak   { stroke: var(--accent); stroke-width: 1.5; }
.tax__edge--dotted { stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 1 4; stroke-linecap: round; }
.tax__arrow { fill: rgb(var(--ink-rgb) / .42); stroke: none; }
.tax__arrow--leak { fill: var(--accent); stroke: none; }
.tax__ring  { fill: rgb(var(--surface-rgb)); stroke: var(--accent); stroke-width: 2; }
.tax__badge { fill: var(--accent); }
.tax__badgetxt { font: 500 9px var(--mono); fill: rgb(var(--on-accent-rgb)); }
.tax__key   { font: 400 9px var(--mono); fill: rgb(var(--ink-muted-rgb)); }
.tax__cap   { font: 400 10px var(--mono); fill: rgb(var(--ink-muted-rgb)); }

/* --- taxonomy v1.1 additions: two regimes, five types --------------------- */
.tax__zone {
  font: 500 11px var(--mono); letter-spacing: .16em;
  fill: var(--accent);
}
.tax__divide { stroke: var(--accent-line); stroke-width: 1; stroke-dasharray: 2 5; fill: none; }
/* The benchmark and the answer key are the objects the five types are about, so
   they carry the accent wash; every other node is a plain surface. */
.tax__node--key { fill: rgb(var(--accent-rgb) / .1); stroke: var(--accent-line); }
.tax__label--quiet { fill: rgb(var(--ink-muted-rgb)); letter-spacing: .16em; }
.tax__sandbox { fill: none; stroke: var(--accent-line); stroke-width: 1.5; stroke-dasharray: 5 4; }
.tax__spine--dash { stroke-dasharray: 3 4; }
.tax__label { font-size: 11px; }
.tax__sub { font-size: 9.5px; }

/* A wide diagram scrolls rather than shrinking to illegibility — the same
   device the publications table uses, and focusable for WCAG 2.1.1. */
.figure-scroll { overflow-x: auto; }
.figure-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.figure-scroll > .tax { min-width: 46rem; }

.tax-figure { margin-top: clamp(1.5rem, 3vw, 2rem); }

/* Standalone diagram page: a back link above the fold and a real button at the
   end, so the way out is never more than a glance away. */
.backlink { font-size: .88rem; margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem); }
.backlink--end { margin: clamp(2rem, 4vw, 3rem) 0 0; }
/* On its own page the diagram has the full measure, so it can be taller before
   the scroll container has to take over. */
.tax-page .figure-scroll > .tax { min-width: 52rem; }

/* The key is HTML, not SVG: it reflows, find-in-page reaches it, and a screen
   reader gets a list instead of a wall of <text>. */
.tax-key {
  margin: clamp(1.5rem, 3vw, 2rem) 0 0;
  padding: 0; list-style: none;
  display: grid; gap: 1.15rem;
  grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .tax-key { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 68rem) { .tax-key { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tax-key__item { border-top: 1px solid var(--accent-line); padding-top: .9rem; }
.tax-key__item--mark { border-top-width: 2px; border-top-color: var(--accent); }
.tax-key__k { font: 500 .78rem/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--accent); display: flex; align-items: center; gap: .5rem; }
.tax-key__n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  font-size: .68rem; letter-spacing: 0;
}
.tax-key__body { margin-top: .7rem; font-size: .85rem; line-height: 1.55; color: var(--ink); }
.tax-key__sub { display: block; margin-top: .35rem; font: 400 .74rem/1.5 var(--mono); color: var(--ink-muted); }
.tax-key__miss { margin-top: .5rem; font-size: .78rem; line-height: 1.5; color: var(--ink-muted); }

/* ====================== cohort stratification ============================
   Three part-to-whole rows, each summing to the same 1,047. No colour
   encoding: segments are told apart by a 2px surface gap and a direct label,
   and full accent is reserved for the stratum that carries the contamination
   signal. A sequential ramp across four unordered disease categories would be
   encoding order that is not in the data. */
.cohort { display: grid; gap: 1.4rem; }
/* `.figure-card figcaption` is styled for a caption below the figure — top rule,
   top padding. This one leads the figure, so it opts out of all three. */
.figure-card .cohort__head { margin: 0; padding-top: 0; border-top: 0; display: grid; gap: .45rem; }
.cohort__head b { font-family: var(--sans); font-size: 1rem; font-weight: 600; letter-spacing: -.015em; }
.cohort__head span { font: 400 .74rem/1.6 var(--mono); color: var(--ink-muted); }
.cohort__head span b { font-size: inherit; font-weight: 500; color: var(--ink); }

.cohort__row { display: grid; gap: .55rem; }
.cohort__k { font: 500 .72rem/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
.cohort__k span { display: block; margin-top: .3rem; letter-spacing: .02em; text-transform: none; font-weight: 400; color: var(--ink-muted); }

.cohort__bar { display: flex; gap: 2px; height: 1.4rem; }
.cohort__seg {
  display: block; min-width: 3px;
  background: var(--surface);
  border: 1px solid var(--accent-line);
  border-radius: 3px;
}
.cohort__seg--on { background: var(--accent); border-color: var(--accent); }

.cohort__lab { display: flex; gap: .5rem 1.25rem; flex-wrap: wrap; font-size: .78rem; color: var(--ink-muted); }
.cohort__lab b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 500; }
.cohort__lab--on b { color: var(--accent); }
.cohort__lab--four { gap: .35rem 1rem; font-size: .74rem; }

.cohort__foot {
  margin-top: .3rem; padding-top: 1rem;
  border-top: 1px solid var(--rule-soft);
  font-size: .82rem; line-height: 1.6; color: var(--ink-muted);
}
.cohort__foot b { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 500; }
/* `.bench__stats` went with the figure: the four facts it carried (1,047 / 49 /
   415 / 2 DOIs) are all in the figure now, with the context that makes them
   mean something, and the two DOIs are the section's own buttons. */

/* ============================== work ====================================== */

.work__more { margin-top: clamp(1.75rem, 3.5vw, 2.25rem); }

.cards {
  margin-top: clamp(2.25rem, 4vw, 3rem);
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 56rem) { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.card {
  display: flex; flex-direction: column;
  background: var(--surface-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.85rem);
  box-shadow: var(--shadow-sm);
  transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.card:hover, .card:focus-within { border-color: var(--accent); box-shadow: var(--shadow-md); transform: translateY(-2px); }

.card__tags { font: 400 .69rem/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-muted); }
.card__title { margin-top: .85rem; font-size: 1.22rem; letter-spacing: -.02em; font-weight: 600; }
.card__title a:hover { color: var(--accent); }
.card__desc { margin-top: .75rem; font-size: .9rem; line-height: 1.62; color: var(--ink-muted); }
.card__links {
  margin-top: auto; padding-top: 1.35rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.25rem;
  font-size: .84rem;
}
.card__links a { position: relative; z-index: 1; }
.card__primary { font-weight: 500; color: var(--accent); }
.card__secondary { color: var(--ink-muted); }
.card__secondary:hover { color: var(--ink); }

/* Currently unused — the only card carrying one ("Gene Safety Benchmark for LLMs")
   was removed 31 Aug 2026. Kept because it encodes a non-obvious fix: the white
   fill is deliberate, since the original 9%-accent fill vanished once cards moved
   onto the accent wash. Re-deriving that costs more than twelve lines of CSS. */
.chip {
  display: inline-block;
  font: 500 .64rem/1 var(--mono);
  letter-spacing: .12em; text-transform: uppercase;
  padding: .38rem .55rem;
  border-radius: 999px;
  color: var(--accent);
  background: var(--surface);
  border: 1px solid var(--accent-line);
  align-self: flex-start;
  margin-bottom: .9rem;
}

/* =========================== publications ================================= */

/* Horizontally scrollable on narrow screens, and focusable so it can be
   scrolled from the keyboard (WCAG 2.1.1 for scrollable regions). */
.table-scroll { margin-top: clamp(2rem, 4vw, 2.75rem); overflow-x: auto; }
.table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Application-venue papers: a compact index, not a feature. The stack column
   is the widest of the three and is allowed one unwrapped line — a two-line
   mono cell was doubling every row's height and giving the weakest section on
   the page the most vertical weight. Everything here is a step smaller than
   the reference-list entries above it, on purpose.

   The three columns together need ~57rem of max-content, so `min-width` is set
   to that rather than to a round number: below it the wrapper scrolls, above it
   every row is one line. The work titles carry the shrink — dropping them a
   step is what buys the stack column the width it needs at 1024px, where the
   titles used to wrap to two lines *and* the stack still overflowed the
   measure. Column padding is tighter here than in the reference list for the
   same reason. */
.pubs { width: 100%; border-collapse: collapse; min-width: 57rem; }
.pubs th {
  text-align: left;
  font: 500 .62rem/1 var(--mono);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-muted);
  padding: 0 1rem .7rem 0;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.pubs th:last-child, .pubs td:last-child { text-align: right; padding-right: 0; }
.pubs td { padding: .8rem 1rem .8rem 0; border-bottom: 1px solid var(--rule-soft); vertical-align: baseline; }
.pubs tr:last-child td { border-bottom: 0; }
.pubs__work { font-size: .82rem; font-weight: 500; }
.pubs__venue { color: var(--ink-muted); font-size: .8rem; white-space: nowrap; }
/* No max-width and no wrap: the column takes the width it needs, and the
   `.table-scroll` wrapper is what handles a viewport too narrow for it. */
.pubs__stack { font-family: var(--mono); font-size: .73rem; line-height: 1.45; white-space: nowrap; color: var(--ink-muted); }
.pubs tbody tr { transition: background-color .2s ease; }
.pubs tbody tr:hover { background: rgb(var(--surface-rgb) / .7); }

/* Reference-list entries for preprints and software: an academic record reads
   as a list, not as a card grid, and the descriptions are too long for cards. */
.subhead {
  margin-top: clamp(2.75rem, 5vw, 3.75rem);
  font: 500 .68rem/1 var(--mono);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-muted);
}
.subhead:first-of-type { margin-top: clamp(2.25rem, 4vw, 3rem); }
.subhead + .table-scroll { margin-top: clamp(1.5rem, 3vw, 2rem); }

.artifacts { margin-top: clamp(1.25rem, 2.5vw, 1.75rem); }
.artifact { border-top: 1px solid var(--rule); padding-block: clamp(1.35rem, 2.5vw, 1.75rem); }
.artifact + .artifact { border-top-color: var(--rule-soft); }
.artifact__k { font: 400 .69rem/1.5 var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
.artifact__title { margin-top: .7rem; font-size: 1.1rem; line-height: 1.35; letter-spacing: -.02em; font-weight: 600; max-width: 62ch; }
.artifact__desc { margin-top: .75rem; font-size: .9rem; line-height: 1.62; color: var(--ink-muted); max-width: 76ch; }
.artifact__desc code { font-size: .92em; color: var(--ink); }
.artifact__links {
  margin-top: 1.1rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.25rem;
  font-size: .84rem;
}

.talk + .talk { margin-top: 1.25rem; }

.talk {
  margin-top: 2rem; display: block;
  border-left: 2px solid var(--accent-line);
  padding: .35rem 0 .35rem 1.25rem;
  max-width: 68ch;
}
.talk:hover { border-left-color: var(--accent); }
.talk__k { font: 500 .68rem/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.talk p { margin-top: .6rem; font-size: .9rem; line-height: 1.6; color: var(--ink-muted); }

/* Full-bleed band on the accent wash — the same recipe as .stats, so the two
   bands bracket the research section as one device. The band edge replaces the
   rule and the top margin the block used to carry inside .wrap. */
.creds-band { border-block: 1px solid var(--accent-line); background: var(--surface-wash); }
.creds-band .wrap { padding-block: clamp(2.5rem, 5vw, 3.75rem); }

.creds {
  display: grid; gap: 2.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) { .creds { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.creds h3 { font: 500 .68rem/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); }
.creds ul { margin-top: 1.1rem; display: flex; flex-direction: column; gap: .8rem; }
.creds li { font-size: .89rem; line-height: 1.5; padding-left: 1rem; position: relative; }
.creds li::before { content: ""; position: absolute; left: 0; top: .6em; width: 4px; height: 1px; background: var(--accent); }
.creds__also {
  margin-top: 2.25rem; padding-top: 1.25rem;
  border-top: 1px solid var(--accent-line);
  font-size: .82rem; line-height: 1.6; color: var(--ink-muted); max-width: 80ch;
}

/* ============================= console ==================================== */

.console-section { padding-block: var(--section-y); }

.console {
  margin-top: clamp(2rem, 4vw, 2.75rem);
  background: rgb(var(--console-rgb));
  color: rgb(var(--console-ink-rgb));
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 40px 80px -40px rgb(var(--console-rgb) / .6);
  font-family: var(--mono);
}

.console__bar {
  display: flex; align-items: center; gap: .75rem;
  padding: .8rem 1.1rem;
  background: rgb(var(--console-2-rgb));
  border-bottom: 1px solid rgb(var(--console-ink-rgb) / .1);
  font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgb(var(--console-muted-rgb));
}
.console__dot { width: 7px; height: 7px; border-radius: 50%; background: rgb(var(--console-accent-rgb)); flex: 0 0 auto; }
.console__turn { margin-left: auto; font-variant-numeric: tabular-nums; letter-spacing: .1em; }

.console__body { display: grid; grid-template-columns: 1fr; }
@media (min-width: 56rem) { .console__body { grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr); } }

.console__probes {
  padding: 1.25rem;
  border-bottom: 1px solid rgb(var(--console-ink-rgb) / .1);
  display: flex; flex-direction: column; gap: .6rem;
}
@media (min-width: 56rem) {
  .console__probes { border-bottom: 0; border-right: 1px solid rgb(var(--console-ink-rgb) / .1); }
}
.console__probes-k { font-size: .64rem; letter-spacing: .16em; text-transform: uppercase; color: rgb(var(--console-muted-rgb)); margin-bottom: .35rem; }

.probe {
  text-align: left;
  font: 400 .8rem/1.5 var(--mono);
  color: rgb(var(--console-ink-rgb));
  background: rgb(var(--console-ink-rgb) / .04);
  border: 1px solid rgb(var(--console-ink-rgb) / .12);
  border-radius: 9px;
  padding: .7rem .85rem;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease;
}
.probe:hover { background: rgb(var(--console-accent-rgb) / .12); border-color: rgb(var(--console-accent-rgb) / .45); }
.probe[aria-pressed="true"] { background: rgb(var(--console-accent-rgb) / .16); border-color: rgb(var(--console-accent-rgb) / .6); }
.probe:focus-visible { outline-color: rgb(var(--console-accent-rgb)); }
.probe__k { display: block; font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; color: rgb(var(--console-muted-rgb)); margin-bottom: .35rem; }

.console__out { padding: 1.25rem; }
@media (min-width: 56rem) { .console__out { min-height: 18rem; } }

.verdict {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem .75rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid rgb(var(--console-ink-rgb) / .1);
}
.verdict__tag {
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 500;
  padding: .3rem .55rem; border-radius: 5px;
  color: rgb(var(--console-rgb)); background: rgb(var(--console-accent-rgb));
}
.verdict__tag[data-state="pass"] { color: rgb(var(--console-ink-rgb)); background: rgb(var(--console-ink-rgb) / .14); }
.verdict__where { font-size: .78rem; color: rgb(var(--console-muted-rgb)); }

.trace { margin-top: 1rem; display: flex; flex-direction: column; gap: .45rem; font-size: .76rem; line-height: 1.5; }
.trace__row { display: grid; grid-template-columns: 3.6rem minmax(0, 1fr); gap: .75rem; align-items: baseline; }
.trace__st { font-size: .66rem; letter-spacing: .1em; font-weight: 500; }
.trace__row[data-st="ok"]    .trace__st { color: rgb(var(--console-ink-rgb) / .75); }
.trace__row[data-st="block"] .trace__st { color: rgb(var(--console-accent-rgb)); }
.trace__row[data-st="skip"]  .trace__st { color: rgb(var(--console-muted-rgb) / .7); }
.trace__row[data-st="skip"]  .trace__txt { color: rgb(var(--console-muted-rgb) / .8); }
.trace__txt { color: rgb(var(--console-muted-rgb)); overflow-wrap: anywhere; }
.trace__txt b { color: rgb(var(--console-ink-rgb)); font-weight: 500; }

.reply {
  margin-top: 1.1rem; padding-top: .9rem;
  border-top: 1px solid rgb(var(--console-ink-rgb) / .1);
  font: 400 .8rem/1.65 var(--sans);
  color: rgb(var(--console-ink-rgb) / .85);
}
.reply__k { display: block; font: 500 .62rem/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: rgb(var(--console-muted-rgb)); margin-bottom: .5rem; }

.console__idle { font-family: var(--sans); color: rgb(var(--console-muted-rgb)); font-size: .84rem; line-height: 1.6; max-width: 52ch; }

.console__foot { margin-top: 1.25rem; font-size: .84rem; color: var(--ink-muted); max-width: 72ch; }

/* =========================== testimonials ================================= */

.quotes {
  margin-top: clamp(2rem, 4vw, 3rem);
  display: grid; gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 56rem) { .quotes { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.quote {
  background: var(--surface-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.85rem);
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-sm);
}
.quote blockquote { font-size: 1.02rem; line-height: 1.55; letter-spacing: -.01em; }
.quote figcaption { margin-top: auto; padding-top: 1.4rem; font-size: .82rem; color: var(--ink-muted); }
.quote figcaption b { display: block; color: var(--ink); font-weight: 500; }
.quotes__note { margin-top: 1.5rem; }

/* Four quotes in a 2 x 2 grid. Two columns rather than the base three, so the
   set reads as a considered selection instead of a row-plus-orphan. The
   eight-quote scroll-snap carousel it replaces (`.quotes__head`,
   `.carousel__*`, `.quotes-track`) is in git history along with its script. */
@media (min-width: 56rem) { .quotes--grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.quote::before {
  content: "";
  display: block; width: 1.5rem; height: 2px;
  background: var(--accent); margin-bottom: 1.1rem;
}

/* ============================= contact ==================================== */

.contact { background: var(--surface); border-top: 1px solid var(--rule-soft); }

.contact__grid {
  display: grid; gap: clamp(2.25rem, 5vw, 4rem);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 60rem) { .contact__grid { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); } }

.contact__links { margin-top: 1.75rem; display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; font-size: .92rem; }
.contact__links + .contact__links { margin-top: .6rem; }
/* Inline separator between links. Generic — the benchmark section's link row
   uses it too, so it is no longer scoped to .contact__links. */
.sep { color: var(--ink-muted); opacity: .5; }
.contact__cta { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: .85rem; }

.form { display: grid; gap: 1.1rem; }
.form__row { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 32rem) { .form__row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.form label { display: block; font: 500 .66rem/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: .55rem; }
.form input, .form textarea {
  width: 100%;
  font: 400 .95rem/1.5 var(--sans);
  color: var(--ink);
  background: var(--ground);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: .8rem .95rem;
  transition: border-color .2s ease, background-color .2s ease;
}
.form input::placeholder, .form textarea::placeholder { color: rgb(var(--ink-muted-rgb) / .65); }
.form input:focus, .form textarea:focus { outline: none; border-color: var(--accent); background: var(--surface); }
.form textarea { resize: vertical; min-height: 8rem; }

/* ============================== footer ==================================== */

.site-foot { border-top: 1px solid var(--rule-soft); background: var(--ground); }
.site-foot .wrap {
  /* extra bottom room so the fixed "Ask about my work" launcher never sits on the links */
  padding-block: 2.25rem 5.5rem;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem;
  font-size: .84rem; color: var(--ink-muted);
}
.site-foot nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.site-foot a:hover { color: var(--ink); }

/* ============================== motion ==================================== */

/* The page's single orchestrated moment: a staggered fade-up on hero load. */
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

.rise { opacity: 0; animation: rise .7s cubic-bezier(.22, .8, .36, 1) forwards; }
.rise:nth-child(1) { animation-delay: .04s; }
.rise:nth-child(2) { animation-delay: .1s; }
.rise:nth-child(3) { animation-delay: .16s; }
.rise:nth-child(4) { animation-delay: .22s; }
.rise:nth-child(5) { animation-delay: .28s; }
.rise:nth-child(6) { animation-delay: .34s; }
.hero figure.rise { animation-delay: .3s; }
.hero__note.rise { animation-delay: .42s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .rise { opacity: 1; transform: none; }
  .card:hover, .card:focus-within { transform: none; }
}

/* =============================================================================
   Shared subpage components — /disclosure and /cv draw on the same tokens and
   primitives as the home page, so the three pages read as one site.
   ========================================================================== */

.split { display: grid; gap: clamp(2rem, 5vw, 3.5rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 60rem) {
  .split--wide-first { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
  .split--wide-last  { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
  .split--even       { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.grid-2 { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 56rem) { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.band { background: var(--surface); border-block: 1px solid var(--rule-soft); }
/* single-column document hero (subpages): a wider measure than the home split */
.doc-lede { margin-top: 1.6rem; max-width: 58ch; }
.doc-lede + .doc-lede { margin-top: 1.1rem; }
.pull { font-size: clamp(1.35rem, 1rem + 1.5vw, 2rem); line-height: 1.3; letter-spacing: -.02em; font-weight: 600; max-width: 36ch; }

/* numbered concept card (taxonomy types) */
.tx {
  background: var(--surface-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.85rem);
  box-shadow: var(--shadow-sm);
}
.tx__num { display: block; font: 500 .7rem/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--accent); margin-bottom: .75rem; }
.tx h3 { font-size: 1.15rem; line-height: 1.3; letter-spacing: -.015em; font-weight: 600; }
.tx p { margin-top: .7rem; font-size: .9rem; line-height: 1.62; color: var(--ink-muted); }

.bullets { display: flex; flex-direction: column; gap: .75rem; }
.bullets li { position: relative; padding-left: 1.1rem; font-size: .9rem; line-height: 1.5; color: var(--ink-muted); }
.bullets li::before { content: ""; position: absolute; left: 0; top: .62em; width: 5px; height: 1px; background: var(--accent); }

/* the disclosure form — that page's signature object, deliberately form-like */
.dform { background: var(--surface); border: 2px solid var(--ink); border-radius: 6px; }
.dform__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: 1.1rem 1.5rem; border-bottom: 2px solid var(--ink);
}
.dform__head .eyebrow { color: var(--ink); }
.dform__head .eyebrow + .eyebrow { color: var(--ink-muted); }
.dform__row {
  display: grid; grid-template-columns: 13rem minmax(0, 1fr); gap: 1.25rem;
  padding: 1.35rem 1.5rem; border-bottom: 1px dotted rgb(var(--ink-rgb) / .3);
}
.dform__row:last-child { border-bottom: 0; }
.dform__k { font-weight: 600; font-size: .95rem; letter-spacing: -.01em; }
.dform__v { font: 400 .85rem/1.6 var(--mono); color: var(--ink-muted); }
.dform__v em { font-style: normal; font-weight: 500; color: var(--accent); }
@media (max-width: 44rem) {
  .dform__row { grid-template-columns: 1fr; gap: .4rem; padding: 1.1rem; }
  .dform__head { padding: .9rem 1.1rem; flex-direction: column; gap: .3rem; }
}

/* Code / BibTeX. Deliberately NOT the console's dark surface: the guardrail
   console is an instrument you operate, this is a document you copy from, and a
   black slab reads as a foreign object on a light page. A violet wash off the
   accent keeps it distinct from the page without shouting. */
.codecard {
  background: rgb(var(--accent-rgb) / .07);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 1.75rem);
  overflow-x: auto;
}
.codecard .eyebrow { color: var(--accent); margin-bottom: 1rem; }
.cite { margin: 0; font: 400 .8rem/1.7 var(--mono); white-space: pre-wrap; word-break: break-word; color: var(--ink); }

/* ============================== print =====================================
   Screeners print. The page has to survive it: the sticky header, the dark
   console island, the agent launcher and the form are all screen furniture,
   and links are worth nothing on paper unless their target is spelled out. */
@media print {
  html { scroll-behavior: auto; }
  body { background: #fff; color: #000; font-size: 10.5pt; }
  .site-head, .site-foot nav, .form, .console, .console__foot,
  .hero__cta, .skip, .talk__k { display: none !important; }
  .section, .stats .wrap, .creds-band .wrap { padding-block: 1.1rem; }
  .section--ruled { border-top: 1px solid #ccc; }
  .card, .quote, .figure-card, .tx, .stats, .creds-band, .contact {
    background: #fff !important; box-shadow: none !important; border-color: #ccc !important;
  }
  .h1 { font-size: 24pt; }
  .h2 { font-size: 15pt; }
  .card, .quote, .artifact, .agenda__item, .domain, .figure-card { break-inside: avoid; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8pt; color: #555; word-break: break-all; }
  .card__links a[href^="http"]::after, .artifact__links a[href^="http"]::after { content: ""; }
  .rise { opacity: 1 !important; transform: none !important; animation: none !important; }
}
