/* =========================================================================
   Mandar Bhoyar / UX Research & Strategy
   Design language: research apparatus. A claim column carries the argument,
   a margin column carries the evidence that backs it. The layout performs
   the thesis rather than describing it.
   ========================================================================= */

/* ---------- Tokens ---------------------------------------------------- */

/* =========================================================================
   Night is the default. Diwali is light against darkness, so the resting
   state of this site is a deep indigo evening with lamplight in it, and the
   sandstone day is the alternate a reader can choose.
   ========================================================================= */

:root {
  color-scheme: dark;

  /* ---- Grounds. Evening indigo, not a tint of the daylight ground. ---- */
  --paper: oklch(0.186 0.030 305);
  --paper-sunk: oklch(0.156 0.032 305);
  --paper-deep: oklch(0.128 0.030 305);

  /* The terminal pavilion inverts against the page, so it needs its own pair
     rather than borrowing --ink and --paper, which swap between themes. */
  --pavilion-bg: oklch(0.112 0.028 300);
  --pavilion-fg: oklch(0.945 0.014 80);

  --ink: oklch(0.945 0.014 80);
  --ink-2: oklch(0.808 0.020 76);
  --ink-3: oklch(0.702 0.024 74);
  --ink-quiet: oklch(0.560 0.032 300);

  --rule: oklch(0.300 0.030 300);
  --rule-strong: oklch(0.408 0.036 298);

  /* Terracotta carries identity and every data mark. --rust-deep is the accent
     *text* colour, so it is light on this ground and dark under the day theme. */
  --rust: #c9793a;
  --rust-deep: oklch(0.812 0.108 62);
  --rust-wash: oklch(0.285 0.055 48);
  --on-accent: oklch(0.155 0.028 55);

  /* Brass. On the evening ground it finally clears the text threshold, so it
     is allowed to carry small type here. */
  --brass: #dcb45f;
  --brass-line: rgba(220, 180, 95, 0.42);

  /* Malachite. Comparison charts only. Validated CVD dE 13.7 (deutan). */
  --verdigris: #12a897;

  /* Sequential ramp for the friction matrix, dark -> light on one hue. */
  --ramp-a: oklch(0.285 0.050 50);
  --ramp-b: oklch(0.375 0.072 48);
  --ramp-c: oklch(0.495 0.098 46);
  --ramp-d: #c9793a;
  --ramp-fg: oklch(0.952 0.014 80);
  --ramp-fg-strong: oklch(0.155 0.028 55);

  /* Surface texture. Lattice and lamplight are tuned per theme. */
  --jaali: rgba(220, 180, 95, 0.045);
  --grain: 0.05;
  --lamp-glow: oklch(0.42 0.10 62 / 0.24);
  --floor-glow: oklch(0.34 0.09 318 / 0.30);
  --carve-shadow: rgba(0, 0, 0, 0.45);

  /* Card surfaces. A raised plane reads as a card without needing a border. */
  --card: oklch(0.216 0.030 303);
  --card-edge: oklch(0.318 0.032 300);
  --card-lift: 0 1px 0 oklch(0.34 0.03 300 / 0.5), 0 10px 28px rgba(0, 0, 0, 0.42);
  --card-lift-hover: 0 1px 0 oklch(0.40 0.04 300 / 0.6), 0 18px 44px rgba(0, 0, 0, 0.52);

  /* ---- Type ---- */
  --display: 'Newsreader', 'Iowan Old Style', 'Charter', Georgia, serif;
  --sans: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Set a step larger throughout. Minimum body-safe floor of ~14px. */
  --t--2: 0.875rem;   /* ~14px — comfortably readable label text */
  --t--1: 1.0625rem;  /* ~17px — body-safe minimum for UI elements */
  --t-0: 1.25rem;     /* ~20px — standard body reading size */
  --t-1: 1.5rem;
  --t-2: 1.9375rem;
  --t-3: 2.625rem;
  --t-4: 3.625rem;
  --t-5: clamp(2.875rem, 6.6vw, 4.75rem);

  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);

  /* Measure. Widened with the type so the caps, not the column, set the line. */
  --claim: 43rem;
  --apparatus: 15rem;
  --gutter: clamp(1.25rem, 5vw, 3.5rem);
}

/* =========================================================================
   Day. Quarried sandstone: the surface carries iron in it. Chosen, never
   assumed — the reader has to ask for daylight.
   ========================================================================= */

[data-theme='light'] {
  color-scheme: light;

  /* Sandstone that has been standing in the sun, not bleached paper. The
     ground carries real chroma and steps down through three warm values, so
     the day has the same depth the evening does. */
  --paper: oklch(0.945 0.021 74);
  --paper-sunk: oklch(0.906 0.030 68);
  --paper-deep: oklch(0.858 0.038 64);

  --pavilion-bg: oklch(0.252 0.034 48);
  --pavilion-fg: oklch(0.955 0.014 80);

  --ink: oklch(0.215 0.028 50);
  --ink-2: oklch(0.396 0.022 52);
  --ink-3: oklch(0.454 0.020 58);
  --ink-quiet: oklch(0.548 0.024 62);

  --rule: oklch(0.836 0.024 70);
  --rule-strong: oklch(0.736 0.032 66);

  --rust: #a84222;
  --rust-deep: oklch(0.412 0.128 40);
  --rust-wash: oklch(0.906 0.052 54);
  --on-accent: oklch(0.963 0.012 78);

  /* Brass measures 2.34:1 on sandstone, so on this ground it is a line and an
     ornament only, never text. */
  --brass: #b98a34;
  --brass-line: rgba(185, 138, 52, 0.58);

  --verdigris: #00a37f;

  --ramp-a: oklch(0.925 0.038 56);
  --ramp-b: oklch(0.878 0.060 52);
  --ramp-c: oklch(0.802 0.096 46);
  --ramp-d: #a84222;
  --ramp-fg: oklch(0.298 0.095 38);
  --ramp-fg-strong: oklch(0.963 0.012 78);

  --jaali: rgba(120, 74, 40, 0.085);
  --grain: 0.046;

  /* Daylight comes over the top edge the way lamplight does at night. Without
     this the day theme is a flat field and the night theme is a room. */
  --lamp-glow: oklch(0.86 0.075 68 / 0.62);
  --floor-glow: oklch(0.83 0.062 42 / 0.5);
  --carve-shadow: rgba(120, 74, 40, 0.22);

  /* A card is lifted off the sandstone by being lighter than it, which is the
     same move the night theme makes in the other direction. */
  --card: oklch(0.978 0.014 78);
  --card-edge: oklch(0.862 0.026 68);
  --card-lift: 0 1px 0 oklch(1 0 0 / 0.8), 0 10px 26px rgba(120, 74, 40, 0.14);
  --card-lift-hover: 0 1px 0 oklch(1 0 0 / 0.9), 0 18px 42px rgba(120, 74, 40, 0.2);
}

/* ---------- Reset ----------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-0);
  line-height: 1.62;
  font-feature-settings: 'kern', 'liga', 'calt';
  letter-spacing: -0.003em;
  overflow-wrap: break-word;
  hanging-punctuation: first last;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

img,
svg {
  max-width: 100%;
  display: block;
}

a {
  color: var(--rust-deep);
  text-decoration-color: color-mix(in oklch, var(--rust-deep) 32%, transparent);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}

@media (hover: hover) and (pointer: fine) {
  a:hover {
    text-decoration-color: var(--rust-deep);
  }
}

:focus-visible {
  outline: 2px solid var(--rust-deep);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection {
  background: var(--rust-wash);
  color: var(--ink);
}

/* Available to assistive tech, absent from the visual composition. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Skip link ------------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--rule-strong);
  padding: 0.75rem 1.25rem;
  font: 600 var(--t--1) / 1 var(--sans);
  z-index: 100;
}

.skip:focus {
  left: 0.5rem;
  top: 0.5rem;
}

/* ---------- Shell ----------------------------------------------------- */

.shell {
  width: min(100% - (var(--gutter) * 2), 68rem);
  margin-inline: auto;
}

/* The gated case studies arrive as fragments that already carry .shell on
   their own sections, and they are injected into a host page that has one
   too. Left alone, the gutter is applied twice and the two strongest studies
   render in a narrower column than every other page on the site. */
.shell .shell {
  width: 100%;
}

/* The signature grid: argument on the left, its evidence on the right. */
.spread {
  display: grid;
  grid-template-columns: minmax(0, var(--claim)) var(--apparatus);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.spread > .claim {
  grid-column: 1;
  min-width: 0;
}

.spread > .apparatus {
  grid-column: 2;
  min-width: 0;
}

/* Full-bleed within the shell, for figures that need the room. */
.wide {
  grid-column: 1 / -1;
}

@media (max-width: 62rem) {
  .spread {
    grid-template-columns: minmax(0, 1fr);
  }

  .spread > .claim,
  .spread > .apparatus,
  .wide {
    grid-column: 1;
  }
}

/* ---------- Masthead -------------------------------------------------- */
/* No animation here. Navigation is used repeatedly; motion would only slow it. */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 20;
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem 2rem;
  padding-block: 0.9rem;
  flex-wrap: wrap;
}

.wordmark {
  font: 500 var(--t-1) / 1 var(--display);
  font-optical-sizing: auto;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: 0.01em;
}

.wordmark span {
  font-family: var(--mono);
  font-size: var(--t--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-left: 0.7rem;
}

.masthead nav ul {
  display: flex;
  gap: clamp(1rem, 3vw, 2.25rem);
  font-size: var(--t--1);
}

.masthead nav a {
  color: var(--ink-2);
  text-decoration: none;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid transparent;
}

@media (hover: hover) and (pointer: fine) {
  .masthead nav a:hover {
    color: var(--ink);
    border-bottom-color: var(--rule-strong);
  }
}

.masthead nav a[aria-current='page'] {
  color: var(--ink);
  border-bottom-color: var(--rust);
}

/* ---------- Typography ------------------------------------------------ */

.display {
  font-family: var(--display);
  font-weight: 400;
  font-optical-sizing: auto;
  line-height: 1.08;
  letter-spacing: -0.014em;
  text-wrap: balance;
}

/* Optical correction: the larger the setting, the tighter it wants to be. */
.display.t-4,
.display.t-5 {
  line-height: 1.02;
  letter-spacing: -0.021em;
}

.t-5 {
  font-size: var(--t-5);
}
.t-4 {
  font-size: var(--t-4);
}
.t-3 {
  font-size: var(--t-3);
}
.t-2 {
  font-size: var(--t-2);
}

.lede {
  font-size: var(--t-1);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 34ch;
  text-wrap: pretty;
}

.prose p + p {
  margin-top: 1.1em;
}

.prose p {
  max-width: 60ch;
  text-wrap: pretty;
}

/* Section marker: a small mono label with a hairline that runs to the edge. */
.marker {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 1rem;
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.75rem;
}

.marker::after {
  content: '';
  height: 1px;
  background: var(--rule);
}

.eyebrow {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--rust-deep);
}

/* ---------- Apparatus column ------------------------------------------ */
/* The evidence rail. Mono, small, precise. It is deliberately quiet: the
   point is that it is always there, not that it shouts. */

.apparatus {
  font-family: var(--mono);
  font-size: var(--t--2);
  line-height: 1.55;
  color: var(--ink-3);
}

.apparatus dl {
  margin: 0;
  display: grid;
  gap: 0.9rem;
}

.apparatus dt {
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-size: var(--t--2);
}

.apparatus dd {
  margin: 0.15rem 0 0;
  color: var(--ink);
  font-size: var(--t--2);
}

.apparatus dd b {
  font-weight: 600;
  color: var(--rust-deep);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 62rem) {
  .apparatus {
    border-top: 1px solid var(--rule);
    padding-top: 1.1rem;
    margin-top: 0.5rem;
  }

  .apparatus dl {
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1rem 1.5rem;
  }
}

/* Inline evidence tag, e.g. 17/25 or P08. */
.tag {
  font-family: var(--mono);
  font-size: var(--t--2);
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.14em 0.45em;
  box-shadow: 1.5px 1.5px 0 var(--rule);
}

.tag--strong {
  color: var(--rust-deep);
  background: var(--rust-wash);
  border-color: color-mix(in oklch, var(--rust) 22%, transparent);
}

/* ---------- Hero ------------------------------------------------------ */

/* Tighter at the top than a hero usually wants to be. The ledger below the
   statement is the part that has to be on screen before anyone scrolls, so
   the whitespace above it is budget, not breathing room. */
.hero {
  padding-block: clamp(2.5rem, 6vw, 5.5rem) clamp(3rem, 7vw, 5rem);
}

.hero__id {
  font: 500 var(--t-2) / 1.1 var(--display);
  font-optical-sizing: auto;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin-bottom: 0.4rem;
}

.hero__role {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: clamp(1.5rem, 3.5vw, 2.5rem);
}

/* The positioning statement leads the page. Display face, generous measure,
   no decorative frame: the sentence is the design. */
.statement {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(1.85rem, 4.4vw, 3rem);
  line-height: 1.14;
  letter-spacing: -0.019em;
  color: var(--ink);
  max-width: none;
  text-wrap: balance;
}

.statement em {
  font-style: italic;
  font-weight: 500;
  color: var(--rust-deep);
}

/* The second half of the positioning, stepped down so the first half can lead
   without the whole thing becoming a wall of display type. */
.statement-coda {
  margin-top: 1.5rem;
  font-size: var(--t-1);
  line-height: 1.45;
  color: var(--ink-2);
  max-width: 40ch;
  text-wrap: pretty;
}

/* Set after the ledger rather than before it, so the newest piece of work
   lands as a postscript to the pattern instead of another claim ahead of it.
   Wider measure, because it now sits under a full-width table. */
.statement-coda--after {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  max-width: 62ch;
}

@media (min-width: 48rem) {
  .statement {
    max-width: 21ch;
  }
}

/* ---------- Actions --------------------------------------------------- */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2.5rem;
}

.btn {
  font: 500 var(--t--1) / 1 var(--sans);
  padding: 0.8rem 1.35rem;
  border-radius: 4px;
  text-decoration: none;
  border: 1px solid transparent;
  transition: transform 160ms var(--ease-out), background-color 180ms ease,
    border-color 180ms ease, color 180ms ease;
}

.btn:active {
  transform: scale(0.97);
}

.btn--solid {
  background: var(--ink);
  color: var(--paper);
}

.btn--ghost {
  border-color: var(--rule-strong);
  color: var(--ink);
}

@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover {
    background: var(--rust-deep);
  }

  .btn--ghost:hover {
    border-color: var(--ink);
    background: var(--paper-sunk);
  }
}

/* ---------- Pillars --------------------------------------------------- */
/* Not three matching cards. A numbered argument on hairline rules, with the
   third given extra weight because it is the differentiator. */

.pillars {
  border-top: 1px solid var(--rule);
}

.pillar {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: 0 clamp(1rem, 3vw, 2rem);
  padding-block: clamp(1.75rem, 4vw, 2.5rem);
  border-bottom: 1px solid var(--rule);
}

.pillar__num {
  font: 400 var(--t-3) / 0.9 var(--display);
  color: var(--ink-quiet);
  font-variant-numeric: lining-nums;
}

.pillar__name {
  font: 600 var(--t-1) / 1.3 var(--sans);
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
}

.pillar__body {
  font-size: var(--t--1);
  line-height: 1.62;
  color: var(--ink-2);
  max-width: 56ch;
  text-wrap: pretty;
}

.pillar--lead .pillar__num {
  color: var(--rust);
}

/* A commitment nobody can check is a slogan. Each one names the study that
   would prove it wrong, and links there. */
.pillar__proof {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.8rem;
  margin-top: 0.9rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--rule);
  max-width: 56ch;
  font-size: var(--t--2);
  line-height: 1.55;
  color: var(--ink-3);
}

/* Deliberately allowed to wrap. Holding this on one line overflowed the
   narrow layout, and a wrapped link costs less than a horizontal scrollbar. */
.pillar__proof a {
  font-family: var(--mono);
  letter-spacing: 0.04em;
  color: var(--rust-deep);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 180ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .pillar__proof a:hover {
    border-bottom-color: var(--rust-deep);
  }
}

/* ---------- Work index ------------------------------------------------ */
/* Four studies as four plates. Not a 2×2: the first is given a full row
   because it is the argument the rest support, and the remaining three sit
   in a row beneath it. The stagger is what stops it reading as a template. */

.work {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(1rem, 2.4vw, 1.75rem);
  margin-top: clamp(1.5rem, 3vw, 2rem);
}

.work__item {
  position: relative;
  grid-column: span 2;
  display: flex;
}

/* The lead study takes the width of the row above the other three. */
.work__item:first-child {
  grid-column: span 6;
}

.work__link {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  width: 100%;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border: 1px solid var(--card-edge);
  border-radius: 14px;
  background: var(--card);
  box-shadow: var(--card-lift);
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: transform 320ms var(--ease-out), box-shadow 320ms var(--ease-out),
    border-color 320ms var(--ease-out);
}

/* The lead card is a two-column plate, so its extra width buys layout rather
   than only a longer line. */
.work__item:first-child .work__link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0 clamp(1.25rem, 3vw, 2.25rem);
  padding-block: clamp(2rem, 4vw, 3rem);
}

@media (hover: hover) and (pointer: fine) {
  .work__link:hover {
    transform: translateY(-3px);
    box-shadow: var(--card-lift-hover);
    border-color: var(--brass);
  }
}

.work__link:focus-visible {
  outline: 2px solid var(--rust-deep);
  outline-offset: 3px;
}

/* A terracotta wash rises from the bottom of the plate on approach. It is the
   whole card answering, not a line under it. */
.work__link::before {
  content: '';
  position: absolute;
  inset: auto 0 0;
  height: 3px;
  background: var(--rust);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 360ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .work__link:hover::before {
    transform: scaleX(1);
  }
}

.work__link:focus-within::before {
  transform: scaleX(1);
}

@media (max-width: 62rem) {
  .work__item,
  .work__item:first-child {
    grid-column: span 3;
  }
}

@media (max-width: 44rem) {
  .work__item,
  .work__item:first-child {
    grid-column: span 6;
  }

  .work__item:first-child .work__link {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
}

.work__index {
  font: 500 var(--t--2) / 1.9 var(--mono);
  letter-spacing: 0.1em;
  color: var(--ink-3);
}

.work__pillar,
.work__title,
.work__hook {
  display: block;
}

.lock-glyph {
  width: 13px;
  height: 12px;
  margin-right: 0.35em;
  vertical-align: -1px;
}

.lock-glyph path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

.lock-glyph circle {
  fill: currentColor;
}

.work__org {
  display: block;
  font: 500 var(--t-0) / 1.3 var(--display);
  font-optical-sizing: auto;
  letter-spacing: 0.005em;
  color: var(--rust-deep);
  margin-bottom: 0.35rem;
}

.work__item:first-child .work__org {
  font-size: var(--t-1);
}

.work__pillar {
  display: flex;
  align-items: center;
  gap: 0.45em;
  font: 500 var(--t--2) / 1.35 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rust-deep);
  margin-bottom: 0.6rem;
}

.work__pillar .lock-glyph {
  margin-right: 0;
  flex: none;
}

.work__title {
  font: 400 clamp(1.375rem, 2.2vw, 1.75rem) / 1.12 var(--display);
  font-optical-sizing: auto;
  letter-spacing: -0.016em;
  margin-bottom: 0.6rem;
  max-width: 20ch;
  text-wrap: balance;
  transition: color 200ms var(--ease-out);
}

.work__item:first-child .work__title {
  font-size: clamp(1.75rem, 3.4vw, 2.5rem);
  max-width: 22ch;
}

.work__hook {
  color: var(--ink-2);
  font-size: var(--t--1);
  line-height: 1.55;
  max-width: 48ch;
  text-wrap: pretty;
}

@media (hover: hover) and (pointer: fine) {
  .work__link:hover .work__title {
    color: var(--rust-deep);
  }
}

/* The count sits at the foot of the plate, pushed there so every card ends on
   the same note however long its hook runs. */
.work__meta {
  margin-top: auto;
  padding-top: 1.25rem;
  font: 400 var(--t--2) / 1.7 var(--mono);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.work__item:first-child .work__meta {
  margin-top: 0;
  padding-top: 0;
  text-align: right;
  white-space: nowrap;
}

@media (max-width: 44rem) {
  .work__item:first-child .work__meta {
    margin-top: auto;
    padding-top: 1.25rem;
    text-align: left;
  }
}

/* ---------- Case-study page furniture --------------------------------- */

.case-head {
  padding-block: clamp(3rem, 8vw, 5.5rem) clamp(2rem, 5vw, 3rem);
  border-bottom: 1px solid var(--rule);
}

.case-head__title {
  font-size: clamp(2.25rem, 5.5vw, 3.5rem);
  line-height: 1.04;
  letter-spacing: -0.021em;
  margin: 0.85rem 0 1rem;
  max-width: 18ch;
}

/* Each movement of a case study is its own plate, set down on the page with
   air around it rather than divided from its neighbour by a hairline. The
   gap between plates is what does the separating, so it has to be larger
   than any gap inside one. */
section.band {
  position: relative;
  margin-block: clamp(1.75rem, 4vw, 3rem);
  padding: clamp(2.5rem, 5.5vw, 4rem) clamp(1.75rem, 4vw, 3.25rem);
  border: 1px solid var(--card-edge);
  border-radius: 14px;
  background-color: var(--card);
  box-shadow: var(--card-lift);
  border-bottom: none;
}

/* A sunk plate is recessed rather than raised: the same card, pressed into
   the page instead of lifted off it, which is what makes an alternating
   sequence read as rhythm rather than as two unrelated treatments. */
section.band--sunk {
  background: var(--paper-sunk);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.16);
}

section.band--last {
  border-bottom: none;
}

/* The case head is the one full-bleed moment: it belongs to the page, not to
   a plate, so it keeps its ground and only the movements below it are cards. */
.case-head {
  border-bottom: none;
}

/* The strategic reframe. The single loudest moment on a case-study page. */
.reframe {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-size: clamp(1.5rem, 3.2vw, 2.25rem);
  line-height: 1.2;
  letter-spacing: -0.017em;
  max-width: 26ch;
  text-wrap: pretty;
}

.reframe__before {
  display: block;
  font: 500 var(--t--1) / 1.5 var(--mono);
  letter-spacing: 0.02em;
  color: var(--ink-3);
  text-transform: none;
  margin-bottom: 1rem;
  max-width: 40ch;
}

.reframe__before s {
  text-decoration-color: var(--rust);
  text-decoration-thickness: 1px;
}

/* Method chips: what was done, sitting under why it was done. */
.method {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.5rem;
}

.method li {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font: 400 var(--t--2) / 1 var(--mono);
  color: var(--ink-2);
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  padding: 0.5em 0.85em 0.5em 0.7em;
  background: var(--paper);
}

/* A single shared mark, a step notch, rather than a per-item icon guess.
   Consistent recognizability beats a fragile keyword-to-icon mapping. */
.method li::before {
  content: '';
  flex: none;
  width: 9px;
  height: 9px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1 6.2 L4 9 L9 1.2' fill='none' stroke='%23a84222' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
}

/* ---------- Findings -------------------------------------------------- */

.findings {
  counter-reset: finding;
  display: grid;
  gap: clamp(2rem, 5vw, 3rem);
}

.finding {
  counter-increment: finding;
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  gap: 0 clamp(0.75rem, 2vw, 1.5rem);
}

.finding::before {
  content: counter(finding, decimal-leading-zero);
  font: 500 var(--t--1) / 1.6 var(--mono);
  color: var(--rust);
  font-variant-numeric: tabular-nums;
}

.finding__title {
  font: 600 var(--t-1) / 1.3 var(--sans);
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
  text-wrap: pretty;
}

.finding__support {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.85rem;
}

.finding__body {
  color: var(--ink-2);
  max-width: 56ch;
  text-wrap: pretty;
}

/* Verbatim evidence. Indented, in the display face, attributed in mono. */
.verbatim {
  margin-top: 1.1rem;
  padding-left: 1.25rem;
  border-left: 1px solid var(--rule-strong);
}

.verbatim p {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-size: var(--t-1);
  line-height: 1.4;
  letter-spacing: -0.008em;
  color: var(--ink);
  max-width: 46ch;
  text-wrap: pretty;
}

.verbatim cite {
  display: block;
  margin-top: 0.6rem;
  font: 400 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
  font-style: normal;
}

.why {
  margin-top: 1.1rem;
  font-size: var(--t--1);
  color: var(--ink);
  max-width: 58ch;
}

.why b {
  font-family: var(--mono);
  font-size: var(--t--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rust-deep);
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 500;
}

/* Demoted findings: real, recorded, but not given the same air. */
.secondary-findings {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  display: grid;
  gap: 0.85rem;
}

.secondary-findings li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.75rem;
  align-items: baseline;
  font-size: var(--t--1);
  color: var(--ink-2);
  max-width: 68ch;
}

/* ---------- Principles ------------------------------------------------ */

.principles {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
}

.principles li {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: 0.35rem clamp(1rem, 3vw, 2.5rem);
  padding-block: 1.1rem;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}

.principles b {
  font: 600 var(--t-0) / 1.4 var(--sans);
  color: var(--ink);
}

/* This list is full-bleed within the shell, so column two needs its own measure;
   without it the decision tests run to ~95 characters. */
.principles span {
  font-size: var(--t--1);
  color: var(--ink-2);
  max-width: 56ch;
  text-wrap: pretty;
}

@media (max-width: 40rem) {
  .principles li {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Compact principle grid, no boxes, just rhythm. */
.tenets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1.25rem 2rem;
  margin-top: 1.5rem;
}

.tenets li {
  font-size: var(--t--1);
  color: var(--ink-2);
  padding-top: 0.75rem;
  border-top: 1px solid var(--rule);
}

.tenets b {
  display: block;
  font-weight: 600;
  color: var(--ink);
  font-size: var(--t-0);
  margin-bottom: 0.15rem;
}

/* ---------- Journey diagram ------------------------------------------- */

.journey {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 5px;
  overflow: hidden;
  margin-top: 1.5rem;
}

.journey li {
  background: var(--paper);
  padding: 1.1rem 1rem 1.25rem;
  display: grid;
  align-content: start;
  gap: 0.4rem;
}

.journey__step {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.16em;
  color: var(--rust-deep);
  font-variant-numeric: tabular-nums;
}

.journey__name {
  font: 600 var(--t--1) / 1.25 var(--sans);
  color: var(--ink);
}

.journey__note {
  font-size: var(--t--2);
  line-height: 1.45;
  color: var(--ink-3);
}

@media (max-width: 60rem) {
  .journey {
    grid-auto-flow: row;
    grid-auto-columns: auto;
  }
}

.diagnostic {
  margin-top: 1.1rem;
  font-size: var(--t--1);
  color: var(--ink-2);
  max-width: 62ch;
}

.diagnostic b {
  color: var(--ink);
  font-weight: 600;
}

/* ---------- Figures and charts ---------------------------------------- */

.figure {
  margin-top: 2rem;
}

.figure__title {
  font: 600 var(--t-0) / 1.4 var(--sans);
  margin-bottom: 0.25rem;
}

.figure__note {
  font-size: var(--t--1);
  color: var(--ink-3);
  max-width: 56ch;
  margin-bottom: 1.5rem;
}

.figure figcaption {
  margin-top: 1rem;
  font-size: var(--t--2);
  font-family: var(--mono);
  color: var(--ink-3);
  max-width: 62ch;
  line-height: 1.6;
}

/* Horizontal bar chart, built from grid rows rather than SVG so the labels
   stay real text at any width. */
.bars {
  display: grid;
  gap: 0.7rem;
}

.bars__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.3rem;
}

.bars__label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: var(--t--1);
  color: var(--ink);
}

.bars__value {
  font-family: var(--mono);
  font-size: var(--t--2);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  white-space: nowrap;
}

.bars__track {
  height: 10px;
  background: var(--paper-deep);
  border-radius: 5px;
  overflow: hidden;
}

.bars__fill {
  height: 100%;
  width: var(--w);
  background: var(--rust);
  border-radius: 5px;
  transform-origin: left center;
  transition: clip-path 760ms var(--ease-out);
  transition-delay: var(--d, 0ms);
}

/* Filled is the resting state. Only a bar that is still below the fold is
   wound back, and only once script has confirmed it can wind it forward again. */
.bars__fill.is-pending {
  clip-path: inset(0 100% 0 0);
}

.bars__fill--quiet {
  background: var(--ink-3);
}

.bars__fill--alt {
  background: var(--verdigris);
}

.bars__row--lead .bars__label {
  font-weight: 600;
}

/* Grouped bars for a two-series comparison. */
.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-bottom: 1.25rem;
  font-family: var(--mono);
  font-size: var(--t--2);
  color: var(--ink-2);
}

.legend li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.legend i {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  display: block;
}

.swatch-rust {
  background: var(--rust);
}
.swatch-alt {
  background: var(--verdigris);
}
.swatch-quiet {
  background: var(--ink-3);
}

.swatch-rule {
  background: transparent;
  box-shadow: inset 0 0 0 2px var(--ink-quiet);
}

/* A hollow mark for the value that is being measured against, so the pair
   reads as one reading and its comparison rather than as two categories. */
.swatch-ring {
  background: var(--paper);
  border: 2.5px solid var(--rust);
  border-radius: 50%;
}

/* Two bars set against each other, each directly labelled. */
.delta {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  margin-top: 1.5rem;
}

.delta__unit {
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
}

.delta__head {
  font: 600 var(--t--1) / 1.4 var(--sans);
  margin-bottom: 0.9rem;
  color: var(--ink);
}

.delta__gap {
  font-family: var(--mono);
  font-size: var(--t--2);
  color: var(--rust-deep);
  margin-top: 0.75rem;
  font-variant-numeric: tabular-nums;
}

/* Ranked priority list, numbers doing the work. */
.ranked {
  counter-reset: rank;
  display: grid;
  border-top: 1px solid var(--rule);
}

.ranked li {
  counter-increment: rank;
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr) auto;
  gap: 0.75rem 1rem;
  align-items: baseline;
  padding-block: 0.9rem;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t--1);
}

.ranked li::before {
  content: counter(rank);
  grid-column: 1;
  grid-row: 1;
  font: 500 var(--t--1) / 1.5 var(--mono);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.ranked b {
  grid-column: 2;
  grid-row: 1;
  font: 600 var(--t-0) / 1.4 var(--sans);
  margin-bottom: 0.1rem;
}

.ranked span {
  grid-column: 2;
  grid-row: 2;
  color: var(--ink-2);
  max-width: 62ch;
  text-wrap: pretty;
}

.ranked em {
  grid-column: 3;
  grid-row: 1;
  font-family: var(--mono);
  font-style: normal;
  font-size: var(--t--2);
  color: var(--ink-3);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.ranked li:first-child b {
  color: var(--rust-deep);
}

.ranked li:first-child::before {
  color: var(--rust);
}

@media (max-width: 40rem) {
  .ranked li {
    grid-template-columns: 2.25rem minmax(0, 1fr);
  }

  .ranked em {
    grid-column: 2;
    grid-row: 3;
  }
}

/* ---------- Forward-looking close ------------------------------------- */

/* The terminal pavilion. An arcade of cusped arches sits on the top edge and a
   jaali lattice is cut into the ground, both drawn as line work rather than
   applied as decoration. Nothing here clips: the arcade is an overlay strip, so
   focus rings on any control inside stay intact. */
.close {
  position: relative;
  background: var(--pavilion-bg);
  color: var(--pavilion-fg);
  border-radius: 3px;
  padding: clamp(2.25rem, 5.5vw, 3.25rem) clamp(1.75rem, 5vw, 2.75rem)
    clamp(1.75rem, 5vw, 2.75rem);
  background-image: repeating-linear-gradient(
      45deg,
      transparent 0 13px,
      rgba(196, 154, 69, 0.05) 13px 14px
    ),
    repeating-linear-gradient(-45deg, transparent 0 13px, rgba(196, 154, 69, 0.05) 13px 14px);
  overflow: hidden;
}

.close::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 13px;
  background-image: radial-gradient(
    circle at 10px 11px,
    transparent 0 6.5px,
    var(--brass) 6.5px 7.5px,
    transparent 8px
  );
  background-size: 20px 13px;
  background-repeat: repeat-x;
  opacity: 0.85;
}

.close .eyebrow {
  color: var(--brass);
}

.close p {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-size: clamp(1.3rem, 2.6vw, 1.75rem);
  line-height: 1.3;
  letter-spacing: -0.012em;
  margin-top: 1rem;
  max-width: 40ch;
  text-wrap: pretty;
}

/* ---------- Resume ---------------------------------------------------- */

.role {
  padding-block: clamp(1.75rem, 4vw, 2.5rem);
  border-bottom: 1px solid var(--rule);
}

.role__head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem 1.5rem;
  margin-bottom: 1rem;
}

.role__org {
  font: 400 var(--t-2) / 1.16 var(--display);
  font-optical-sizing: auto;
  letter-spacing: -0.016em;
}

.role__title {
  font-size: var(--t--1);
  color: var(--ink-2);
  margin-top: 0.2rem;
}

.role__dates {
  font: 400 var(--t--2) / 1 var(--mono);
  color: var(--ink-3);
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.duties {
  display: grid;
  gap: 0.7rem;
}

/* A duty is a sentence, so it stays a block of flowing text. Making the row a
   flex or grid container turns every inline <strong> into its own track and
   collapses the line into a column one word wide. The mark hangs in the
   padding instead, which keeps the text aligned to the heading above it. */
.duties li {
  position: relative;
  padding-left: 1.05rem;
  color: var(--ink-2);
  max-width: 64ch;
  font-size: var(--t--1);
  line-height: 1.6;
  text-wrap: pretty;
}

.duties li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.66em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--rust-deep);
}

.duties strong {
  color: var(--ink);
  font-weight: 600;
}

.duties strong {
  color: var(--ink);
  font-weight: 600;
}

.subhead {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 1.5rem 0 0.75rem;
}

.subhead:first-of-type {
  margin-top: 0;
}

/* Competency columns */
.columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(1.5rem, 4vw, 2.75rem);
  margin-top: 1.5rem;
}

.columns section > h3 {
  font: 600 var(--t-0) / 1.4 var(--sans);
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--rule-strong);
  margin-bottom: 0.85rem;
}

.columns p {
  font-size: var(--t--1);
  color: var(--ink-2);
  text-wrap: pretty;
}

.inline-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1rem;
}

.inline-list li {
  font: 400 var(--t--2) / 1 var(--mono);
  color: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.45em 0.6em;
  background: var(--paper);
}

/* ---------- Footer ---------------------------------------------------- */

.colophon {
  border-top: 1px solid var(--rule-strong);
  padding-block: clamp(2.5rem, 6vw, 4rem) 2.5rem;
  margin-top: clamp(3rem, 8vw, 5rem);
}

.colophon__statement {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-size: clamp(1.25rem, 2.6vw, 1.75rem);
  line-height: 1.24;
  letter-spacing: -0.014em;
  max-width: 26ch;
  margin-bottom: 2rem;
  text-wrap: pretty;
}

.colophon__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1.5rem 2rem;
  font-family: var(--mono);
  font-size: var(--t--2);
  color: var(--ink-3);
}

.colophon__grid h2 {
  font-size: var(--t--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.5rem;
  font-weight: 500;
}

/* These stack as a list rather than sitting in a sentence, so they get no
   inline exception from the 24px target minimum. At the base line-height they
   landed exactly on it; the extra padding buys margin instead of parity. */
.colophon__grid a {
  color: var(--ink);
  display: block;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  width: fit-content;
  padding-block: 0.2rem;
}

@media (hover: hover) and (pointer: fine) {
  .colophon__grid a:hover {
    border-bottom-color: var(--rust);
  }
}

/* ---------- Reveal ---------------------------------------------------- */
/* One-time entrance, built so that it can only ever add motion, never remove
   content. Visible is the resting state; script hides an element only after
   confirming it is below the fold and that it will be able to show it again.
   If script, IntersectionObserver, or the animation timeline fails, the page
   simply renders. */

.reveal {
  transition: opacity 560ms var(--ease-out), transform 560ms var(--ease-out), filter 560ms var(--ease-out);
  transition-delay: var(--d, 0ms);
  will-change: opacity, transform;
}

.reveal.is-pending {
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  filter: blur(1.5px);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .reveal.is-pending {
    opacity: 1;
    transform: none;
    filter: none;
  }

  .bars__fill,
  .bars__fill.is-pending {
    clip-path: none;
  }
}

/* ---------- Print ----------------------------------------------------- */

@media print {
  .masthead,
  .actions,
  .skip {
    display: none;
  }

  /* Pure black on pure white is wrong on screen but right on paper: the tinted
     neutrals waste ink and the warm ground prints as a muddy grey. */
  body {
    background: #fff;
    color: #000;
    font-size: 10.5pt;
  }

  .reveal,
  .reveal.is-pending {
    opacity: 1;
    transform: none;
  }

  .bars__fill,
  .bars__fill.is-pending {
    clip-path: none;
  }

  .close {
    background: none;
    color: #000;
    border: 1px solid #999;
  }
}


/* =========================================================================
   Evidence chain
   The site claims that a finding is only a finding once it is tied to its
   source. This component states that literally: transcript on the left, the
   principle it produced on the right, the participant code as the hinge.
   ========================================================================= */

.chain {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule-strong);
  margin-top: 1.5rem;
}

.chain__link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 4.5rem minmax(0, 1fr);
  align-items: center;
  background: var(--paper);
}

.chain__source {
  padding: 1.5rem clamp(1rem, 2.5vw, 1.75rem);
}

.chain__source p {
  font-family: var(--display);
  font-optical-sizing: auto;
  font-size: var(--t-1);
  line-height: 1.34;
  letter-spacing: -0.008em;
  color: var(--ink);
  margin-top: 0.65rem;
  max-width: 34ch;
  text-wrap: pretty;
}

/* The hinge: a rule that crosses the gap and terminates in a brass keystone. */
.chain__joint {
  position: relative;
  align-self: stretch;
  background: var(--paper-sunk);
}

.chain__joint::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 50%;
  height: 1px;
  background: var(--rule-strong);
}

.chain__joint::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--brass);
}

.chain__result {
  padding: 1.5rem clamp(1rem, 2.5vw, 1.75rem);
  background: var(--paper-sunk);
  align-self: stretch;
  display: grid;
  align-content: center;
  gap: 0.5rem;
}

.chain__result b {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rust-deep);
}

.chain__result p {
  font: 600 var(--t-0) / 1.35 var(--sans);
  color: var(--ink);
  max-width: 32ch;
  text-wrap: pretty;
}

.chain__result span {
  justify-self: start;
}

@media (max-width: 52rem) {
  .chain__link {
    grid-template-columns: minmax(0, 1fr);
  }

  .chain__joint {
    height: 2.25rem;
  }

  .chain__joint::before {
    inset-inline: auto;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 1px;
    height: auto;
  }
}

/* =========================================================================
   Friction matrix
   A sequential ramp on one hue, and every cell carries its own count, so the
   reading never depends on colour alone. Cells with no measurement are left
   empty on purpose rather than filled with a guess.
   ========================================================================= */

.matrix {
  margin-top: 1.5rem;
  overflow-x: auto;
}

.matrix table {
  border-collapse: separate;
  border-spacing: 2px;
  width: 100%;
  min-width: 40rem;
}

.matrix caption {
  caption-side: bottom;
  margin-top: 1rem;
  font: 400 var(--t--2) / 1.6 var(--mono);
  color: var(--ink-3);
  text-align: left;
  max-width: 62ch;
}

.matrix th {
  font: 500 var(--t--2) / 1.3 var(--mono);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-align: left;
  padding: 0.7rem 0.6rem;
  vertical-align: bottom;
  font-weight: 500;
}

.matrix th[scope='row'] {
  background: var(--paper);
  border: 1px solid var(--rule);
  color: var(--ink);
  white-space: nowrap;
  vertical-align: middle;
}

.matrix td {
  padding: 0.7rem 0.6rem;
  text-align: center;
  font: 500 var(--t--1) / 1 var(--mono);
  font-variant-numeric: tabular-nums;
  border: 1px solid transparent;
  border-radius: 2px;
}

/* The dash means "not measured", which is a reading, so it has to clear the
   text threshold. The pale ground is what makes the cell recede, not faint ink. */
.matrix .lv-na {
  background: var(--paper);
  border-color: var(--rule);
  color: var(--ink-3);
  font-weight: 400;
}

.matrix .lv-5 {
  background: var(--ramp-a);
  color: var(--ramp-fg);
}

.matrix .lv-6 {
  background: var(--ramp-b);
  color: var(--ramp-fg);
}

.matrix .lv-7 {
  background: var(--ramp-c);
  color: var(--ramp-fg);
}

.matrix .lv-8 {
  background: var(--ramp-d);
  color: var(--ramp-fg-strong);
}

/* =========================================================================
   Decision gates
   Deliberately not a row of big-numeral tiles. These are pass/fail thresholds,
   so they are set as an instrument: mono values, rule-separated, read across.
   ========================================================================= */

.gates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  border-top: 1px solid var(--rule-strong);
  margin-top: 1.5rem;
}

.gates > li {
  padding: 1.1rem 1.25rem 1.25rem 0;
  border-bottom: 1px solid var(--rule);
}

.gates dfn {
  display: block;
  font: 500 var(--t-1) / 1 var(--mono);
  font-variant-numeric: tabular-nums;
  font-style: normal;
  color: var(--rust-deep);
  margin-bottom: 0.45rem;
}

.gates b {
  display: block;
  font: 600 var(--t--1) / 1.35 var(--sans);
  color: var(--ink);
  margin-bottom: 0.2rem;
}

.gates span {
  font-size: var(--t--2);
  font-family: var(--mono);
  line-height: 1.5;
  color: var(--ink-3);
  display: block;
  max-width: 30ch;
}

/* =========================================================================
   Layers: grain, lattice, lamplight
   Three planes sit behind the content. None intercept the pointer, and each
   is tuned by theme token rather than duplicated per theme.
   ========================================================================= */

body::before {
  content: '';
  position: fixed;
  inset: -20%;
  z-index: 0;
  pointer-events: none;
  opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Light spilling in from above the fold: lamplight at night, and the same
   warmth from a higher, wider source by day. Both themes get a source, so
   neither reads as an untinted field. The second, weaker pool low on the
   right keeps a long case-study scroll from flattening out below the fold. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(70vw 46vh at 50% -6vh, var(--lamp-glow), transparent 72%),
    radial-gradient(90vw 44vh at 88% 104%, var(--floor-glow), transparent 70%);
}

main,
.masthead,
.colophon {
  position: relative;
  z-index: 1;
}

/* A jaali screen: overlapping arcs on a square repeat, which is how the real
   lattices are struck. Drawn from tokens, so it re-tints with the theme. */
.band--sunk {
  background-image: radial-gradient(circle at 0 0, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 100% 0, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 0 100%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 100% 100%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 50% 50%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px);
  background-size: 30px 30px;
  box-shadow: inset 0 1px 0 var(--brass-line), inset 0 -1px 0 var(--brass-line);
}

/* Carved rather than dropped: a hard offset, no blur. */
.journey,
.matrix table,
.chain {
  box-shadow: 3px 3px 0 var(--carve-shadow);
}

/* =========================================================================
   The lamp: theme toggle
   ========================================================================= */

/* A segmented switch, not a mystery glyph. Both destinations are named and
   visible at once, and a thumb slides to the one you are in, so the control
   explains itself without anyone needing to recognise a diya first. The diya
   stays: it is what "night" is labelled with, which is the part worth keeping. */

.lamp {
  appearance: none;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: stretch;
  flex: none;
  padding: 2px;
  gap: 0;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  background: var(--paper-sunk);
  cursor: pointer;
  color: var(--ink-2);
  transition: border-color 200ms ease, background-color 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .lamp:hover {
    border-color: var(--brass);
  }
}

/* The thumb. One element that travels, so the movement reads as one switch
   rather than two independent buttons lighting up. */
.lamp::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: 2px;
  bottom: 2px;
  left: 2px;
  width: calc(50% - 2px);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
  transition: transform 320ms var(--ease-out), background-color 200ms ease;
}

[data-theme='dark'] .lamp::before {
  transform: translateX(100%);
  background: color-mix(in oklch, var(--brass) 22%, var(--paper-deep));
}

.lamp__seg {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.3rem 0.5rem;
  border-radius: 999px;
  font: 500 0.6875rem / 1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-3);
  transition: color 220ms ease;
}

.lamp__seg svg {
  width: 13px;
  height: 13px;
  flex: none;
  overflow: visible;
}

/* Whichever segment the thumb is under becomes the readable one. */
.lamp__seg--day {
  color: var(--ink);
}

[data-theme='dark'] .lamp__seg--day {
  color: var(--ink-3);
}

.lamp__seg--night {
  color: var(--ink-3);
}

[data-theme='dark'] .lamp__seg--night {
  color: var(--brass);
}

.lamp__sun {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

/* The diya, kept from the original mark. Its flame is only alight on the side
   of the switch that means night. */
.lamp__diya .lamp__bowl {
  fill: currentColor;
}

.lamp__diya .lamp__flame {
  fill: var(--brass);
  transform-origin: 23px 16px;
  transform: scale(0);
  opacity: 0;
  transition: transform 320ms var(--ease-out), opacity 260ms ease;
}

[data-theme='dark'] .lamp__diya .lamp__flame {
  transform: scale(1);
  opacity: 1;
  filter: drop-shadow(0 0 5px var(--brass));
}

@media (prefers-reduced-motion: no-preference) {
  [data-theme='dark'] .lamp__diya .lamp__flame {
    animation: flicker 2.8s ease-in-out infinite;
  }
}

/* On a narrow screen the words go and the two marks carry it, which still
   shows both states and which one is active. */
@media (max-width: 34rem) {
  .lamp__seg span {
    display: none;
  }

  .lamp__seg {
    padding: 0.45rem 0.75rem;
  }
}

.masthead__end {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2.5vw, 1.75rem);
}

/* The nav underline needs room beneath the text; the control must not sit in
   that room. Both are centred, and the nav keeps its own descender space. */
.masthead nav ul {
  align-items: center;
}

/* =========================================================================
   Diwali transition
   Going to night, a shell rises and bursts. Returning to day, a diya lifts and
   its glow opens out. The theme flips at the burst, not at the end of the
   sequence, so the interface never feels like it is waiting on the animation.
   ========================================================================= */

.fx {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  overflow: hidden;
  --apex: 56vh;
}

.fx,
.fx * {
  transition: none !important;
}

.fx--burst {
  --hot: oklch(0.97 0.06 92);
  --glow: oklch(0.78 0.17 62);
}

.fx--diya {
  --hot: oklch(0.94 0.11 84);
  --glow: oklch(0.83 0.14 70);
}

.fx__shell {
  position: absolute;
  left: var(--ox, 50vw);
  bottom: 0;
  width: 7px;
  height: 7px;
  margin-left: -3.5px;
  border-radius: 50%;
  background: var(--hot);
  box-shadow: 0 0 14px 5px var(--glow);
  animation: shell-rise 400ms cubic-bezier(0.18, 0.72, 0.32, 1) forwards;
}

@keyframes shell-rise {
  from {
    transform: translateY(0) scale(0.5);
    opacity: 0;
  }
  18% {
    opacity: 1;
  }
  to {
    transform: translateY(calc(-1 * var(--apex))) scale(1);
    opacity: 1;
  }
}

.fx__burstpoint {
  position: absolute;
  left: var(--ox, 50vw);
  bottom: var(--apex);
}

.fx__spark {
  position: absolute;
  width: 5px;
  height: 5px;
  margin: -2.5px;
  border-radius: 50%;
  background: var(--hot);
  box-shadow: 0 0 8px 2px var(--glow);
  animation: spark 700ms 395ms cubic-bezier(0.12, 0.85, 0.28, 1) both;
}

@keyframes spark {
  0% {
    transform: rotate(var(--a)) translateY(0) scale(1);
    opacity: 1;
  }
  100% {
    transform: rotate(var(--a)) translateY(calc(-1 * var(--d))) scale(0.15);
    opacity: 0;
  }
}

.fx__bloom {
  position: absolute;
  left: var(--ox, 50vw);
  bottom: var(--apex);
  width: 14px;
  height: 14px;
  margin: 0 0 -7px -7px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--glow), transparent 68%);
  animation: bloom 820ms 380ms var(--ease-out) both;
}

.fx--diya .fx__bloom {
  animation-delay: 330ms;
}

/* Light does emanate from a point, but starting at exactly zero pops for a
   frame. It ignites over the first instant instead. */
@keyframes bloom {
  0% {
    transform: scale(0.04);
    opacity: 0;
  }
  9% {
    opacity: 0.85;
  }
  55% {
    opacity: 0.5;
  }
  100% {
    transform: scale(120);
    opacity: 0;
  }
}

/* The diya: a bowl that lifts, then catches. */
.fx__lamp {
  position: absolute;
  left: var(--ox, 50vw);
  bottom: 0;
  width: 52px;
  height: 38px;
  margin-left: -26px;
  animation: lamp-rise 900ms cubic-bezier(0.2, 0.75, 0.3, 1) both;
}

@keyframes lamp-rise {
  0% {
    transform: translateY(48px);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  62% {
    transform: translateY(calc(-1 * var(--apex)));
    opacity: 1;
  }
  100% {
    transform: translateY(calc(-1 * var(--apex) - 34px));
    opacity: 0;
  }
}

.fx__lamp svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.fx__lamp .bowl {
  fill: var(--glow);
}

.fx__lamp .flame {
  fill: var(--hot);
  transform-origin: 26px 16px;
  animation: catch 420ms 250ms var(--ease-out) both;
}

@keyframes catch {
  from {
    transform: scale(0.2);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

/* Embers drifting off the lamp. */
.fx__ember {
  position: absolute;
  left: var(--ox, 50vw);
  bottom: 12vh;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--glow);
  animation: ember 950ms var(--delay, 0ms) ease-out both;
}

@keyframes ember {
  0% {
    transform: translate(0, 0) scale(1);
    opacity: 0.9;
  }
  100% {
    transform: translate(var(--dx), calc(-1 * var(--dy))) scale(0.3);
    opacity: 0;
  }
}

/* Surfaces wash rather than snap, but only for the duration of the swap. */
/* The swap suppresses transitions rather than adding them.
   A custom-property change does not reliably drive an already-declared
   `color` transition to its new value in Blink: the longhand is left frozen
   at the pre-swap colour while --ink itself updates underneath it. Every
   element carrying `transition: color` — buttons, work titles, links —
   therefore kept its evening cream after a flip to daylight and rendered
   cream-on-cream until the next reload. Snapping is the fix, and the flip is
   timed to the firework burst, where a snap reads as the burst causing it. */
html.theming body,
html.theming body *:not(.fx) {
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .fx {
    display: none;
  }

  .lamp__flame {
    animation: none;
  }
}

/* =========================================================================
   Password gate: the jharokha screen
   A latticed window a visitor has to be let through, rather than a generic
   SaaS lock modal. The screen sits inline in the page, framed by the same
   cusped arch used in the pavilion, with the jaali pattern struck into its
   ground.
   ========================================================================= */

[data-gate] {
  padding-block: clamp(3rem, 8vw, 5rem);
}

.gate {
  max-width: 30rem;
  margin-inline: auto;
  text-align: center;
  padding: clamp(2.25rem, 6vw, 3.25rem) clamp(1.5rem, 5vw, 2.5rem) clamp(2rem, 5vw, 2.75rem);
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  background-color: var(--paper-sunk);
  background-image: radial-gradient(circle at 0 0, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 100% 0, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 0 100%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 100% 100%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px),
    radial-gradient(circle at 50% 50%, transparent 10px, var(--jaali) 10px 11px, transparent 11.5px);
  background-size: 30px 30px;
  position: relative;
}

.gate::before,
.gate::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--brass-line);
}

.gate::before {
  top: 0;
}

.gate::after {
  bottom: 0;
}

.gate__arch {
  width: 84px;
  height: 66px;
  margin: 0 auto 1.25rem;
  display: block;
  color: var(--brass);
}

.gate__arch path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

.gate__arch circle {
  fill: currentColor;
}

.gate .eyebrow {
  justify-content: center;
}

.gate__title {
  font-size: var(--t-2);
  margin: 0.75rem 0 0.6rem;
}

.gate .lede {
  margin-inline: auto;
  max-width: 34ch;
}

.gate__form {
  display: flex;
  gap: 0.6rem;
  margin-top: 1.75rem;
  justify-content: center;
  flex-wrap: wrap;
}

.gate__input {
  font: 500 var(--t--1) / 1 var(--mono);
  letter-spacing: 0.08em;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: 4px;
  padding: 0.75rem 1rem;
  min-width: 12rem;
  flex: 1 1 12rem;
  max-width: 16rem;
  transition: border-color 180ms ease, box-shadow 180ms ease;
}

.gate__input::placeholder {
  color: var(--ink-3);
  letter-spacing: normal;
  font-family: var(--sans);
}

/* The wash on its own measured 1.3:1 against the field it sits on, which is a
   glow rather than a focus indicator — and `outline: none` had removed the one
   that worked. The site's standard ring is restored over the top; the brass
   border and the wash stay as the decorative part of the state. */
.gate__input:focus-visible {
  outline: 2px solid var(--rust-deep);
  outline-offset: 2px;
  border-color: var(--brass);
  box-shadow: 0 0 0 3px var(--rust-wash);
}

.gate__error {
  margin-top: 1rem;
  font-size: var(--t--1);
  color: var(--rust-deep);
}

.gate__hint {
  margin-top: 1.5rem;
  font-size: var(--t--2);
  color: var(--ink-3);
}

.gate__hint a {
  color: var(--ink-2);
}

/* A short, sharp shake reads as "no" without being alarming. Transform only,
   so it stays off the layout-affecting properties. */
@keyframes gate-deny {
  0%,
  100% {
    transform: translateX(0);
  }
  20%,
  60% {
    transform: translateX(-6px);
  }
  40%,
  80% {
    transform: translateX(6px);
  }
}

.gate.is-shaking {
  animation: gate-deny 360ms var(--ease-in-out);
}

/* The content revealed once the code is accepted. Visible is still the
   resting state of everything inside it; this wrapper is the one exception,
   because its whole purpose is to stay hidden until the gate opens. */
.gate__content {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}

.gate__content.is-shown {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .gate.is-shaking {
    animation: none;
  }

  .gate__content {
    transition: none;
  }
}

/* =========================================================================
   Photo frames
   Two ornamental treatments for real project photography, not decoration
   applied after the fact: a cusped arch for portrait images (personas,
   single field shots), and brass corner brackets, the manuscript-page
   convention, for anything wider (storyboards, field strips, screenshots).
   ========================================================================= */

.arch-photo {
  position: relative;
  aspect-ratio: 4 / 5;
  width: 100%;
  overflow: hidden;
  background: var(--paper-deep);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 130'%3E%3Cpath d='M2 130 V46 C2 28 8 16 18 12 C24 10 24 6 20 4 C30 0 70 0 80 4 C76 6 76 10 82 12 C92 16 98 28 98 46 V130 Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 130'%3E%3Cpath d='M2 130 V46 C2 28 8 16 18 12 C24 10 24 6 20 4 C30 0 70 0 80 4 C76 6 76 10 82 12 C92 16 98 28 98 46 V130 Z'/%3E%3C/svg%3E");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.arch-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The brass outline is a second, unmasked layer traced from the identical
   path, so it lines up with the mask exactly at any size. */
.arch-photo__line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.arch-photo__line path {
  fill: none;
  stroke: var(--brass);
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
}

.frame-corners {
  position: relative;
  padding: 9px;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

.frame-corners img,
.frame-corners video {
  display: block;
  width: 100%;
  height: auto;
}

.frame-corners i {
  position: absolute;
  width: 13px;
  height: 13px;
  pointer-events: none;
}

.frame-corners i:nth-child(2) {
  top: -1px;
  left: -1px;
  border-top: 2px solid var(--brass);
  border-left: 2px solid var(--brass);
}

.frame-corners i:nth-child(3) {
  top: -1px;
  right: -1px;
  border-top: 2px solid var(--brass);
  border-right: 2px solid var(--brass);
}

.frame-corners i:nth-child(4) {
  bottom: -1px;
  left: -1px;
  border-bottom: 2px solid var(--brass);
  border-left: 2px solid var(--brass);
}

.frame-corners i:nth-child(5) {
  bottom: -1px;
  right: -1px;
  border-bottom: 2px solid var(--brass);
  border-right: 2px solid var(--brass);
}

/* A caption riding just under the frame, mono, quiet. */
.frame-cap {
  margin-top: 0.6rem;
  font: 400 var(--t--2) / 1.5 var(--mono);
  color: var(--ink-3);
}

/* A gallery of framed photos, evidence rather than decoration: varying
   spans so it does not read as a repeated card grid. */
.gallery {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-flow: dense;
  gap: clamp(0.75rem, 2vw, 1.25rem);
  margin-top: 1.75rem;
}

.gallery > figure {
  grid-column: span 3;
}

.gallery > figure:nth-child(4n + 1) {
  grid-column: span 4;
}

.gallery > figure:nth-child(4n + 2),
.gallery > figure:nth-child(4n + 3) {
  grid-column: span 2;
}

@media (max-width: 40rem) {
  .gallery {
    grid-template-columns: 1fr 1fr;
  }

  .gallery > figure,
  .gallery > figure:nth-child(4n + 1) {
    grid-column: span 1;
  }
}

/* Persona: portrait frame beside a compact fact rail, the same claim /
   apparatus logic the rest of the site uses for argument and evidence. */
.persona {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2rem);
  align-items: start;
  padding-block: 1.75rem;
  border-bottom: 1px solid var(--rule);
}

.persona:last-child {
  border-bottom: 0;
}

.persona__name {
  font: 400 var(--t-1) / 1.2 var(--display);
  margin-bottom: 0.3rem;
}

.persona__role {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rust-deep);
  margin-bottom: 0.85rem;
}

.persona__body {
  color: var(--ink-2);
  font-size: var(--t--1);
  max-width: 52ch;
}

@media (max-width: 40rem) {
  .persona {
    grid-template-columns: 8rem minmax(0, 1fr);
  }
}

/* =========================================================================
   Scroll padding for sticky masthead — keeps anchor targets clear of nav
   ========================================================================= */

html {
  scroll-padding-top: 80px;
}

/* =========================================================================
   Brand-logos: Honda, Nationwide, e-Turn marks on case study pages
   ========================================================================= */

/* A corporate mark is supplied at a fixed colour, so it cannot be re-tinted
   with the page. It gets a plate of its own instead: a small, constant, light
   ground that works under either theme and reads as a credential badge rather
   than as an image someone forgot to style. */
.brand-plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 2.5rem;
  padding: 0.4rem 0.7rem;
  border-radius: 6px;
  background: oklch(0.968 0.006 80);
  box-shadow: inset 0 0 0 1px oklch(0.86 0.012 75);
  vertical-align: middle;
  margin-right: 0.6rem;
  flex: none;
}

.brand-plate img,
.brand-plate svg {
  display: block;
  height: 100%;
  width: auto;
  max-width: 8rem;
  object-fit: contain;
}

/* The Honda mark is square-ish, so at a shared plate height it would read as
   half the size of the wide Nationwide lockup. It gets its own scale. */
.brand-plate--honda svg {
  height: 78%;
}

/* The Honda mark is drawn, not supplied, so it takes a colour rather than a
   plate colour: the marque red on its own light ground. */
.brand-plate--honda {
  color: #cc0000;
  padding: 0.35rem 0.7rem;
}

.brand-mark {
  display: block;
  max-height: 34px;
  width: auto;
  margin-bottom: 0.9rem;
}

/* A standalone mark on a page ground needs the same plate logic. */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.5rem 0.9rem 0.5rem 0.55rem;
  border: 1px solid var(--card-edge);
  border-radius: 10px;
  background: var(--card);
}

.brand-lockup__cap {
  font: 500 var(--t--2) / 1.35 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.brand-lockup__cap b {
  display: block;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t--1);
}

/* =========================================================================
   Inline stat strips — replace charbagh/apparatus as headline stats
   ========================================================================= */

.inline-stat {
  font-family: var(--mono);
  font-size: var(--t--1);
  color: var(--ink-3);
  margin-top: 1.5rem;
  letter-spacing: 0.04em;
}

.inline-stat b {
  color: var(--rust-deep);
  font-weight: 600;
  font-size: 1.2em;
}

/* =========================================================================
   Resume role cards — distinct visual containers for each role entry
   ========================================================================= */

.role-card {
  background-color: var(--paper);
  border-radius: 10px;
  box-shadow: 0 1px 2px var(--carve-shadow),
              0 4px 12px color-mix(in oklch, var(--ink) 3%, transparent);
  padding: clamp(1.75rem, 4vw, 2.5rem) clamp(1.5rem, 3vw, 2.25rem);
}

[data-theme='dark'] .role-card {
  box-shadow: inset 0 1px 0 var(--rule-strong),
              0 2px 8px rgba(0, 0, 0, 0.35);
}

/* =========================================================================
   Enhanced CTA button hover — subtle lift + glow
   ========================================================================= */

@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover {
    background: var(--rust-deep);
    transform: translateY(-1px);
    box-shadow: 0 2px 8px color-mix(in oklch, var(--rust-deep) 35%, transparent);
  }

  .btn--ghost:hover {
    border-color: var(--ink);
    background: var(--paper-sunk);
    transform: translateY(-1px);
  }
}

/* =========================================================================
   Section transition dividers — gradient rule between bands
   ========================================================================= */

.divider--gradient {
  height: clamp(1.5rem, 4vw, 3rem);
  margin-inline: auto;
  max-width: 68rem;
  background: linear-gradient(180deg, transparent 0%, var(--brass-line) 40%, transparent 100%);
}

/* =========================================================================
   Storyboard lightbox / modal
   ========================================================================= */

.lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 3vw, 3rem);
  opacity: 0;
  pointer-events: none;
  transition: opacity 320ms var(--ease-out);
}

.lightbox-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}

.lightbox-overlay img {
  max-width: min(90vw, 1400px);
  max-height: 85vh;
  object-fit: contain;
  border-radius: 6px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  transform: scale(0.92) translateY(12px);
  transition: transform 360ms var(--ease-out);
}

.lightbox-overlay.is-open img {
  transform: scale(1) translateY(0);
}

.lightbox-overlay__close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1.25rem);
  right: clamp(0.75rem, 2vw, 1.25rem);
  width: 40px;
  height: 40px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border-radius: 50%;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 1.2rem;
  transition: background-color 160ms ease;
}

.lightbox-overlay__close:hover {
  background: rgba(255, 255, 255, 0.18);
}

.lightbox-overlay__caption {
  position: absolute;
  bottom: clamp(0.75rem, 2vw, 1.5rem);
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.85);
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.06em;
  text-align: center;
  max-width: 60ch;
}

/* =========================================================================
   Storyboard gallery: larger display + zoom cursor
   ========================================================================= */

.gallery--board > figure,
.gallery--board > figure:nth-child(4n + 1),
.gallery--board > figure:nth-child(4n + 2),
.gallery--board > figure:nth-child(4n + 3) {
  grid-column: span 3;
}

@media (max-width: 56rem) {
  .gallery--board figure { grid-column: span 6; }
}

.gallery--board .frame-corners img {
  cursor: zoom-in;
  transition: transform 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .gallery--board .frame-corners img:hover {
    transform: scale(1.03);
  }
}

/* =========================================================================
   Persona cards: stacked vertically with rust accent top-bar
   ========================================================================= */

.plate--arch {
  margin-top: clamp(2rem, 5vw, 3rem);
}

.plate--arch .arch-photo {
  aspect-ratio: 4 / 5;
  width: min(100%, 28rem);
  margin-inline: auto;
}

.plate--arch .frame-corners {
  border-top: 3px solid var(--rust);
}

.plate--arch .plate__note {
  text-align: center;
  max-width: 48ch;
  margin-inline: auto;
  margin-top: 1rem;
  font-size: var(--t-1);
  color: var(--ink-2);
}

.plate--arch .plate__note b {
  display: block;
  color: var(--rust-deep);
  font-size: var(--t-0);
  margin-bottom: 0.35rem;
}

/* =========================================================================
   Asymmetric spread utilities — alternate column direction
   ========================================================================= */

.spread--reverse {
  grid-template-columns: var(--apparatus) minmax(0, var(--claim));
}

.spread--reverse > .claim {
  grid-column: 2;
}

.spread--reverse > .apparatus,
.spread--reverse > .evidence {
  grid-column: 1;
}

/* =========================================================================
   Centered content blocks for rhythm
   ========================================================================= */

/* Centres the block on the page without centring the text inside it. A
   paragraph of this length set centred has a ragged left edge, and the eye
   loses the start of every line. */
.content--center {
  margin-inline: auto;
  max-width: 62ch;
}

.content--center p {
  text-align: left;
}
/* The meta row carries a brand plate on the studies that have one, so it has
   to be a row rather than a run of text. */
.work__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem 0;
}

/* The sigil sits above the card's text rather than beside it, so the plate
   reads top-down like a page rather than left-right like a table row. */
.work__link > .sigil {
  margin-bottom: 1rem;
}

.work__item:first-child .work__link > .sigil {
  margin-bottom: 0;
  grid-row: 1 / span 3;
  align-self: center;
}

.work__item:first-child .work__pillar { grid-column: 2; }
.work__item:first-child .work__title  { grid-column: 2; }
.work__item:first-child .work__hook   { grid-column: 2; }
.work__item:first-child .work__meta   { grid-column: 3; grid-row: 1 / span 3; }

@media (max-width: 44rem) {
  .work__item:first-child .work__link > .sigil { margin-bottom: 1rem; }
}

/* =========================================================================
   Case head lead
   The head is the one place a page is allowed to be asymmetric on purpose:
   a wide claim on the left, the plate of numbers beneath it, and neither
   centred. Centring everything is what made the previous pass feel static.
   ========================================================================= */

.case-head__lead {
  max-width: 46rem;
}

.case-head__lead .brand-lockup {
  margin-bottom: 1.5rem;
}

.case-head__lead .case-head__title {
  max-width: 16ch;
}

.case-head__lead .lede {
  max-width: 44ch;
}

/* A value that has to sit inside a sentence rather than above it. */
.charbagh__inline {
  display: inline !important;
  font: inherit !important;
  font-weight: 600 !important;
  color: var(--rust-deep) !important;
  margin: 0 !important;
}


/* =========================================================================
   Plain bands
   A section that hosts its own cards must not be a card itself. Nested cards
   read as a container someone forgot to remove.
   ========================================================================= */

section.band--plain {
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  padding-inline: 0;
  padding-block: clamp(1.5rem, 3.5vw, 2.5rem);
}

/* A role is the card on the resume, so it carries the lift and the air. */
.role-card {
  padding: clamp(1.75rem, 4vw, 2.5rem);
  border: 1px solid var(--card-edge);
  border-radius: 12px;
  background: var(--card);
  box-shadow: var(--card-lift);
  border-bottom: 0;
}

.role-card + .role-card {
  margin-top: clamp(1.25rem, 3vw, 2rem);
}

/* Education entries are single lines, so they stay a list rather than
   becoming four more cards. */
section.band--plain .role:not(.role-card) {
  padding-block: 1.15rem;
  border-bottom: 1px solid var(--rule);
}

/* The employer mark sits with the employer name, which is where a reader
   looks for it, rather than floating at the top of the page. */
.role__ident {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  min-width: 0;
}

.role__brand {
  margin-right: 0;
  flex: none;
}


/* A gated study says so where the reader is already looking for its numbers. */
.work__lock {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.3em 0.6em;
  margin-right: 0.6rem;
  border: 1px solid var(--brass-line);
  border-radius: 999px;
  color: var(--rust-deep);
  white-space: nowrap;
}

.work__lock .lock-glyph {
  margin-right: 0;
  flex: none;
}

/* The lead plate stacks its label and title against the mark, so the meta row
   needs to sit with them rather than in a column of its own on narrow screens. */
.work__item:first-child .work__meta {
  display: grid;
  justify-items: end;
  gap: 0.5rem;
}

/* =========================================================================
   Even work grid
   Where two studies carry equal weight, neither takes the lead plate. The
   stagger on the home page is an editorial judgement about that set, not a
   property of the component.
   ========================================================================= */

.work--even {
  grid-template-columns: repeat(2, 1fr);
}

.work--even .work__item,
.work--even .work__item:first-child {
  grid-column: span 1;
}

.work--even .work__item:first-child .work__link {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.work--even .work__item:first-child .work__link > .sigil {
  margin-bottom: 1rem;
  grid-row: auto;
  align-self: flex-start;
}

.work--even .work__item:first-child .work__org,
.work--even .work__item:first-child .work__title,
.work--even .work__item:first-child .work__hook,
.work--even .work__item:first-child .work__meta {
  grid-column: auto;
  grid-row: auto;
}

.work--even .work__item:first-child .work__org { font-size: var(--t-0); }
.work--even .work__item:first-child .work__title { font-size: clamp(1.375rem, 2.2vw, 1.75rem); }

.work--even .work__item:first-child .work__meta {
  display: flex;
  justify-items: start;
  margin-top: auto;
  padding-top: 1.25rem;
  text-align: left;
  white-space: normal;
}

@media (max-width: 44rem) {
  .work--even {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* =========================================================================
   Five-plate work grid
   The default stagger — one wide plate, then a row of three — leaves a fifth
   study stranded alone on a third row with four empty columns beside it. With
   five, the lead plate keeps its full width and the remaining four sit as a
   two-by-two beneath it, which is a composition rather than a remainder.
   ========================================================================= */

.work--five .work__item:not(:first-child) {
  grid-column: span 3;
}

@media (max-width: 62rem) {
  .work--five .work__item:not(:first-child) {
    grid-column: span 3;
  }
}

@media (max-width: 44rem) {
  .work--five .work__item:not(:first-child) {
    grid-column: span 6;
  }
}

/* =========================================================================
   Case head credit
   The employer is named in type rather than shown as a mark. A supplied logo
   arrives at a fixed colour and a fixed shape and has to be given a plate to
   sit on, which reads as a sticker on a page that is otherwise all one
   material. A name does not have that problem.
   ========================================================================= */

.case-head__org {
  font: 500 var(--t-1) / 1.2 var(--display);
  font-optical-sizing: auto;
  letter-spacing: 0.004em;
  color: var(--rust-deep);
}

.case-head__role {
  margin-top: 0.3rem;
  font: 400 var(--t--1) / 1.4 var(--mono);
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

.case-head__lead .case-head__title {
  margin-top: 1.1rem;
}

/* An outbound link that leaves the site says so. */
.ext {
  display: inline-block;
  margin-left: 0.2em;
  font-size: 0.9em;
  line-height: 1;
}

/* The hero and every page head share one left edge and one measure, so the
   eye finds the start of a line in the same place on every page. */
.hero__lead {
  max-width: 46rem;
}

.hero__lead .statement-coda {
  max-width: 44ch;
}

.resume-contact {
  margin-top: 1rem;
  font: 400 var(--t--1) / 1.5 var(--mono);
  letter-spacing: 0.02em;
  color: var(--ink-2);
}

/* =========================================================================
   LEDGER
   The hero's evidence rather than its decoration. Every study on this site
   began with a brief that was not the question worth answering, so the
   ledger shows that happening four times instead of claiming it once.
   Struck on the left, live on the right; the pattern is legible before a
   single row has been read.
   ========================================================================= */

.ledger {
  margin-top: clamp(2rem, 4.5vw, 3rem);
  border-top: 1px solid var(--rule);
}

.ledger__head {
  display: none;
}

.ledger__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.4rem;
  padding-block: clamp(1rem, 2.4vw, 1.35rem);
  border-bottom: 1px solid var(--rule);
}

/* --ink-quiet would be the natural choice for a label this quiet, but at 14px
   it measures 4.0:1 on the evening ground. --ink-3 clears AA and still reads
   as subordinate. */
.ledger__where {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* The strike is drawn in the accent so the correction reads as an act, not
   as damage. */
.ledger__brief {
  font-size: var(--t--1);
  line-height: 1.5;
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-color: var(--rust);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0;
}

.ledger__real {
  font: 500 var(--t-0) / 1.34 var(--sans);
  letter-spacing: -0.008em;
  color: var(--ink);
  text-wrap: pretty;
}

.ledger__turn {
  display: none;
  color: var(--rust);
  font-size: var(--t-0);
  line-height: 1.34;
}

@media (min-width: 56rem) {
  .ledger__head,
  .ledger__row {
    grid-template-columns: 9.5rem minmax(0, 17rem) 1.5rem minmax(0, 1fr);
    align-items: baseline;
    gap: 0 clamp(0.8rem, 2vw, 1.5rem);
  }

  .ledger__head {
    display: grid;
    padding-bottom: 0.55rem;
    border-bottom: 1px solid var(--rule);
    font: 500 var(--t--2) / 1 var(--mono);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-3);
  }

  .ledger__head > :nth-child(2) {
    grid-column: 2;
  }

  .ledger__head > :nth-child(3) {
    grid-column: 4;
  }

  .ledger__turn {
    display: block;
  }
}

/* =========================================================================
   DOT MATRIX
   One mark per person. A proportion drawn in units rather than in a bar,
   because the argument here is about how few of them there were, and a
   2-of-37 bar is a sliver nobody can read.
   ========================================================================= */

.dots {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  max-width: 30rem;
}

/* The unhighlighted marks are not decoration — they are the other 35 people,
   and the reader has to be able to see them to read the proportion.
   Solid against hollow rather than one colour against another: on the evening
   ground the accent and any sufficiently visible grey sit within 1.4:1 of each
   other, so a purely chromatic split would carry the whole chart on hue. */
.dots__unit {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  background: transparent;
  box-shadow: inset 0 0 0 2px var(--ink-quiet);
  flex: none;
}

.dots__unit--on {
  background: var(--rust);
  box-shadow: none;
}

.dots__key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
  margin-top: 1.1rem;
  font-size: var(--t--1);
  color: var(--ink-2);
}

.dots__key li {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
}

.dots__key i {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  display: block;
  flex: none;
  transform: translateY(2px);
}

.dots__key b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 500;
}

/* =========================================================================
   SPLIT BAR
   One hundred percent of something, divided. Used where the shares only
   mean anything against each other, so they share a single track instead of
   being given a row each.
   ========================================================================= */

.split {
  display: flex;
  width: 100%;
  height: 2.4rem;
  border-radius: 5px;
  overflow: hidden;
  background: var(--paper-deep);
}

.split__seg {
  width: var(--w);
  height: 100%;
  background: var(--ink-3);
  transition: clip-path 760ms var(--ease-out);
  transition-delay: var(--d, 0ms);
}

.split__seg.is-pending {
  clip-path: inset(0 100% 0 0);
}

.split__seg--lead {
  background: var(--rust);
}

/* A share that is itself three phases added together is hatched, so it is
   never mistaken for a single one. */
.split__seg--composite {
  background: repeating-linear-gradient(
    -45deg,
    var(--ink-3) 0 6px,
    var(--paper-deep) 6px 8px
  );
}

.split__key {
  display: grid;
  gap: 0.75rem;
  margin-top: 1.1rem;
}

.split__key li {
  display: grid;
  grid-template-columns: 14px auto minmax(0, 1fr);
  align-items: baseline;
  gap: 0 0.7rem;
  font-size: var(--t--1);
  color: var(--ink-2);
}

.split__key i {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  display: block;
  transform: translateY(2px);
}

.split__key b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--ink);
}

.swatch-hatch {
  background: repeating-linear-gradient(
    -45deg,
    var(--ink-3) 0 4px,
    var(--paper-deep) 4px 5.5px
  );
}

/* =========================================================================
   DUMBBELL
   Two readings of the same thing, joined. Where the argument is about the
   distance between two values rather than either value alone, the gap has
   to be the thing drawn.
   ========================================================================= */

.dumbbell {
  display: grid;
  gap: 1.5rem;
  margin-top: 0.5rem;
}

.dumbbell__row {
  display: grid;
  gap: 0.5rem;
}

.dumbbell__name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font: 500 var(--t--1) / 1.3 var(--sans);
  color: var(--ink);
}

.dumbbell__row--lead .dumbbell__name {
  font-weight: 600;
}

.dumbbell__name .g {
  color: var(--rust-deep);
  font-size: 1.1rem;
}

/* Gridlines every 20% put a scale point at each integer from 1 to 5 without
   needing axis labels that collide at this width. */
.dumbbell__track {
  position: relative;
  height: 14px;
  border-radius: 3px;
  background: var(--paper-deep);
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 calc(20% - 1px),
    var(--rule) calc(20% - 1px) 20%
  );
}

.dumbbell__span {
  position: absolute;
  top: 50%;
  left: var(--a);
  width: calc(var(--b) - var(--a));
  height: 3px;
  transform: translateY(-50%);
  background: var(--rust-wash);
}

.dumbbell__pt {
  position: absolute;
  top: 50%;
  left: var(--p);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

.dumbbell__pt--a {
  background: var(--paper);
  border: 2.5px solid var(--rust);
}

.dumbbell__pt--b {
  background: var(--verdigris);
}

.dumbbell__read {
  font-family: var(--mono);
  font-size: var(--t--2);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}

.dumbbell__read b {
  font-weight: 500;
  color: var(--ink);
}

.dumbbell__read em {
  font-style: normal;
  color: var(--rust-deep);
}

/* =========================================================================
   PIPELINE
   A study drawn as the sequence of instruments it was actually built from,
   with the sample each one carried. Used where the shape of the method is
   the evidence of range.
   ========================================================================= */

.pipeline {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 1px;
  margin-top: 1.5rem;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 5px;
  overflow: hidden;
}

.pipeline li {
  background: var(--paper);
  padding: 1.25rem 1.1rem 1.4rem;
  display: grid;
  align-content: start;
  gap: 0.35rem;
}

.band--sunk .pipeline li {
  background: var(--paper-sunk);
}

.pipeline__n {
  font: 400 var(--t-3) / 0.95 var(--display);
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--rust-deep);
  letter-spacing: -0.02em;
}

.pipeline__n small {
  display: block;
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 0.45rem;
}

.pipeline__name {
  font: 600 var(--t--1) / 1.3 var(--sans);
  color: var(--ink);
  margin-top: 0.2rem;
}

.pipeline__note {
  font-size: var(--t--2);
  line-height: 1.5;
  color: var(--ink-3);
}

/* The last stage is the only one that is an outcome rather than a method, so
   it is the only one lit. */
.pipeline li.pipeline--out {
  background: var(--rust-wash);
}

.band--sunk .pipeline li.pipeline--out {
  background: var(--rust-wash);
}

.pipeline--out .pipeline__note a {
  color: var(--ink);
  text-underline-offset: 3px;
}

@media (max-width: 60rem) {
  .pipeline {
    grid-auto-flow: row;
    grid-auto-columns: auto;
  }
}

/* =========================================================================
   SEAMS
   A journey drawn with its joints showing. Both vehicle studies found the
   same thing — friction lives between the stages, not inside any one of
   them — so a row of equal plates draws the wrong claim. Here the stage is
   a node on a spine and the seam is a marked element in its own right,
   which makes the diagram state the finding instead of illustrating it.
   ========================================================================= */

.seams {
  position: relative;
  display: grid;
  margin-top: 1.5rem;
}

.seams::before {
  content: '';
  position: absolute;
  left: 1.35rem;
  top: 1.6rem;
  bottom: 1.6rem;
  width: 1px;
  background: var(--rule-strong);
}

.seams__stage,
.seams__joint {
  position: relative;
  display: grid;
  grid-template-columns: 2.7rem minmax(0, 1fr);
  gap: 0 clamp(0.9rem, 2.5vw, 1.5rem);
  align-items: start;
}

.seams__stage {
  padding-block: 0.7rem;
}

/* The node has to carry its own ground, because the spine runs behind it. */
.seams__node {
  display: grid;
  place-items: center;
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  font: 500 var(--t--2) / 1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.band--sunk .seams__node {
  background: var(--paper-sunk);
}

.seams__name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font: 600 var(--t-0) / 1.3 var(--sans);
  color: var(--ink);
  margin-top: 0.3rem;
}

.seams__name .g {
  color: var(--rust-deep);
  font-size: 1.15rem;
}

.seams__note {
  margin-top: 0.3rem;
  font-size: var(--t--1);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 58ch;
  text-wrap: pretty;
}

/* The seam itself. Set in the accent and lifted off the ground, because it
   is the finding rather than the connective tissue. */
.seams__joint {
  padding-block: 0.15rem;
}

.seams__mark {
  justify-self: center;
  width: 13px;
  height: 13px;
  margin-top: 0.3rem;
  border-radius: 2px;
  background: var(--rust);
  transform: rotate(45deg);
}

.seams__fail {
  padding: 0.55rem 0.9rem;
  background: var(--rust-wash);
  border-radius: 5px;
  font-size: var(--t--1);
  line-height: 1.5;
  color: var(--ink);
  max-width: 54ch;
  text-wrap: pretty;
}

.seams__fail b {
  display: block;
  margin-bottom: 0.15rem;
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rust-deep);
}

/* Where a journey has no named seams to draw, one stage can still be marked:
   the stage the brief was about, so the caption can say the evidence went
   somewhere else. */
.journey li.is-assumed {
  background: var(--rust-wash);
}

.journey li.is-assumed .journey__step {
  color: var(--rust-deep);
}


/* =========================================================================
   PLOT
   A statistical figure that was actually produced in matplotlib, inlined as
   SVG rather than linked as a file. A referenced SVG is an isolated document,
   so a var() inside it never resolves and the chart would be stuck in one
   theme while the page moved underneath it. Inlined, every mark is painted
   from the same tokens as the type around it.
   ========================================================================= */

.plot {
  margin-top: clamp(1.5rem, 3.5vw, 2.25rem);
}

/* Below about 33rem the labels would be too small to read if the figure kept
   scaling down, so the figure holds its size and the container scrolls. */
.plot__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 0.25rem;
}

.plot .viz {
  display: block;
  width: 100%;
  min-width: 33rem;
  height: auto;
}

.plot figcaption {
  margin-top: 1rem;
  font: 400 var(--t--2) / 1.6 var(--mono);
  color: var(--ink-3);
  max-width: 62ch;
}

/* A figure that is a drawing rather than a measurement says so in its own
   corner, not only in the caption underneath it. */
.plot__kind {
  display: inline-block;
  margin-bottom: 0.6rem;
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.4em 0.75em;
}

.plot__kind--drawn {
  color: var(--rust-deep);
  border-color: color-mix(in oklch, var(--rust) 30%, transparent);
  background: var(--rust-wash);
}

/* =========================================================================
   ATTEND
   The looking-time instrument, drawn as the instrument. A baby cannot be
   asked what it expected, so the whole method rests on one fact: attention
   runs longer when something does not match. The two tracks fill at the same
   rate and one of them keeps going, which is the finding before a single
   number has been read.
   ========================================================================= */

.attend {
  position: relative;
  isolation: isolate;
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
  padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1.25rem, 4vw, 2.5rem)
    clamp(1.25rem, 3vw, 1.75rem);
  border: 1px solid var(--card-edge);
  border-radius: 12px;
  background: var(--paper-sunk);
  overflow: hidden;
}

/* A pool of lamplight behind the tracks, from the same source the page is
   lit by. */
.attend::before {
  content: '';
  position: absolute;
  inset: -40% 30% auto -10%;
  height: 150%;
  z-index: -1;
  background: radial-gradient(50% 42% at 22% 30%, var(--lamp-glow), transparent 70%);
  pointer-events: none;
}

.attend__caption {
  font: 500 var(--t--2) / 1 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.4rem;
}

.attend__row {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr) 5.5rem;
  align-items: center;
  gap: 0.5rem clamp(0.85rem, 2.5vw, 1.5rem);
}

.attend__row + .attend__row {
  margin-top: 0.9rem;
}

.attend__name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font: 500 var(--t--1) / 1.3 var(--sans);
  color: var(--ink-2);
}

.attend__row--lead .attend__name {
  font-weight: 600;
  color: var(--ink);
}

.attend__name .g {
  font-size: 1.05rem;
  color: var(--ink-3);
}

.attend__row--lead .attend__name .g {
  color: var(--rust-deep);
}

.attend__track {
  position: relative;
  display: block;
  height: 1.5rem;
  border-radius: 4px;
  background: var(--paper-deep);
  overflow: hidden;
}

/* Both of these are spans, so they have to be blockified explicitly: an inline
   box ignores width and height outright. */
.attend__fill {
  position: relative;
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: 4px;
  background: var(--ink-quiet);
}

.attend__row--lead .attend__fill {
  background: var(--rust);
}

/* This one runs on load rather than on scroll: it sits in the page head, above
   the fold, so the entrance observer would never hold it — and the whole point
   of the component is watching the two tracks accumulate at the same rate and
   one of them keep going. Filled is still the resting state, so a browser that
   ignores the animation shows the finished measurement.

   Linear, and each row given a duration in proportion to its own length: an
   eased fill, or one duration shared by both, would draw the two tracks
   finishing together, which is the opposite of what was measured. */
@media (prefers-reduced-motion: no-preference) {
  .attend__fill {
    animation: attend-fill var(--dur, 1900ms) linear 300ms both;
  }
}

@keyframes attend-fill {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0);
  }
}

/* The gaze passing over the track. Slow, low-contrast, and only on the lit
   row, so it reads as attention resting there rather than as a progress bar. */
@media (prefers-reduced-motion: no-preference) {
  .attend__row--lead .attend__fill::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
      90deg,
      transparent 0%,
      color-mix(in oklch, var(--brass) 60%, transparent) 48%,
      transparent 100%
    );
    opacity: 0.55;
    animation: attend-gaze 4.6s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  }
}

@keyframes attend-gaze {
  0%,
  8% {
    transform: translateX(-100%);
  }
  58%,
  100% {
    transform: translateX(100%);
  }
}

.attend__read {
  font: 500 var(--t--1) / 1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  text-align: right;
}

.attend__row--lead .attend__read {
  color: var(--rust-deep);
}

/* The distance between the two tracks is the measurement, so it is drawn as
   its own mark rather than left for the reader to subtract. */
.attend__gap {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: var(--t--1);
  color: var(--ink-2);
  text-wrap: pretty;
}

.attend__gap b {
  font: 500 var(--t-1) / 1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--rust-deep);
  flex: none;
}

@media (max-width: 40rem) {
  .attend__row {
    grid-template-columns: minmax(0, 1fr) 5rem;
  }

  .attend__name {
    grid-column: 1 / -1;
  }
}

/* =========================================================================
   PAPERS
   A citation list set as a citation list: year in the margin, the reference
   in full, and the author's own name the only thing given weight, because
   position in an author list is a real piece of information.
   ========================================================================= */

.papers {
  display: grid;
  border-top: 1px solid var(--rule);
  margin-top: 1.5rem;
}

.paper {
  display: grid;
  grid-template-columns: 4.25rem minmax(0, 1fr);
  gap: 0.3rem clamp(1rem, 3vw, 1.75rem);
  padding-block: clamp(1.1rem, 2.6vw, 1.5rem);
  border-bottom: 1px solid var(--rule);
}

.paper__year {
  font: 500 var(--t--2) / 1.75 var(--mono);
  letter-spacing: 0.08em;
  color: var(--rust-deep);
  font-variant-numeric: tabular-nums;
}

.paper__cite {
  font-size: var(--t--1);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 66ch;
  text-wrap: pretty;
}

.paper__cite b {
  font-weight: 600;
  color: var(--ink);
}

.paper__cite i {
  font-style: italic;
}

.paper__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.85rem;
  margin-top: 0.6rem;
  font: 400 var(--t--2) / 1.5 var(--mono);
  color: var(--ink-3);
}

.paper__meta .tag {
  box-shadow: none;
}

@media (max-width: 34rem) {
  .paper {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* An outbound index of the same list, kept apart from the list itself so it
   does not read as one more entry. */
.scholar {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.5rem;
  padding: 0.6rem 1rem 0.6rem 0.85rem;
  border: 1px solid var(--brass-line);
  border-radius: 999px;
  font: 500 var(--t--1) / 1.2 var(--sans);
  color: var(--ink);
  text-decoration: none;
  background: var(--paper);
  transition: border-color 200ms ease, transform 200ms var(--ease-out);
}

.scholar .g {
  color: var(--rust-deep);
  font-size: 1.15rem;
  flex: none;
}

.scholar span {
  font-family: var(--mono);
  font-size: var(--t--2);
  color: var(--ink-3);
}

@media (hover: hover) and (pointer: fine) {
  .scholar:hover {
    border-color: var(--brass);
    transform: translateY(-1px);
  }
}

/* =========================================================================
   PORTRAIT HEAD
   A face at 120px square is an ID photo. The site already owns a portrait
   frame — the cusped arch it uses for personas — so the résumé head becomes
   a two-column composition and the photograph gets the size a photograph
   needs in order to read as one.
   ========================================================================= */

.portrait-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 15rem);
  gap: clamp(1.75rem, 5vw, 3.5rem);
  align-items: center;
}

.portrait-head__lead {
  max-width: 42rem;
}

.portrait {
  position: relative;
  width: 100%;
  margin: 0;
}

.portrait .arch-photo {
  aspect-ratio: 4 / 5;
}

.portrait figcaption {
  margin-top: 0.85rem;
  font: 400 var(--t--2) / 1.5 var(--mono);
  color: var(--ink-3);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  .portrait .arch-photo img {
    transition: transform 900ms var(--ease-out);
  }

  .portrait:hover .arch-photo img {
    transform: scale(1.035);
  }
}

@media (max-width: 52rem) {
  .portrait-head {
    grid-template-columns: minmax(0, 1fr);
  }

  .portrait {
    max-width: 15rem;
  }

  .portrait figcaption {
    text-align: left;
  }
}

/* =========================================================================
   APPROACH SPLIT
   Replaces an inline grid that was scoped with a `div[style*=...]` attribute
   selector — a rule that matched every inline grid on the page and would
   have collapsed the next one added.
   ========================================================================= */

.approach-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 3rem);
  align-items: center;
}

@media (max-width: 48rem) {
  .approach-split {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* A figure that scrolls has to say so. Cover gradients scroll with the content
   and shadow gradients stay pinned to the container, so each edge shadow is
   revealed only while there is more figure in that direction and hides itself
   at the end of the travel. */
.plot__scroll {
  --plot-ground: var(--card);
  background-image: linear-gradient(to right, var(--plot-ground), transparent),
    linear-gradient(to left, var(--plot-ground), transparent),
    radial-gradient(farthest-side at 0 50%, var(--carve-shadow), transparent),
    radial-gradient(farthest-side at 100% 50%, var(--carve-shadow), transparent);
  background-position: left center, right center, left center, right center;
  background-size: 2.5rem 100%, 2.5rem 100%, 0.9rem 100%, 0.9rem 100%;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}

.band--sunk .plot__scroll {
  --plot-ground: var(--paper-sunk);
}

.plot__scroll:focus-visible {
  outline: 2px solid var(--rust-deep);
  outline-offset: 4px;
  border-radius: 4px;
}

/* =========================================================================
   STUDY NAME
   The title of a study inside a section, which is a level the site did not
   have one for: below the threshold marker, above the chart titles. Set in
   the display face rather than at a bumped sans size, because the previous
   pass had it at 1.5rem against 1.25rem body and 1.25rem figure titles —
   three steps close enough together that none of them led.
   ========================================================================= */

.study__name {
  font: 400 var(--t-2) / 1.16 var(--display);
  font-optical-sizing: auto;
  letter-spacing: -0.016em;
  color: var(--ink);
  margin-bottom: 0.9rem;
  max-width: 24ch;
  text-wrap: balance;
}
