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

:root {
  --bg: #0c0c0d;
  --text: #f1f0ec;
  --body: #b3b2ad;
  --muted: #8b8b85;
  --accent: #d8a05a;
  --rule: rgba(255, 255, 255, 0.10);

  /* the layout grid: a label rail, a gap, and one column of prose.
     the prose measure is a property of this grid, not of any element,
     so no rule can quietly invent a second one. */
  --rail: 172px;
  --gap: 44px;

  /* the vertical rhythm: every band uses the same space above and below,
     so the page reads as equal chapters rather than one long scroll */
  --band: 120px;

  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
}

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg);
  color: var(--body);
  font-family: var(--sans);
  font-size: 18px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--accent); color: #0c0c0d; }

a { color: inherit; }

.container {
  max-width: 900px;
  margin: 0 auto;
  padding: 0 40px;
}

/* ---------- the grid ---------- */

.grid {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gap);
}

.grid > * { grid-column: 1 / -1; }
.grid > .rail { grid-column: 1; }
.grid > .col { grid-column: 2; }

/* rows keep the same two tracks, so a label and its text line up
   with the section label and the prose column above them */
.row {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gap);
}

/* ---------- nav ---------- */

nav {
  padding: 30px 0;
  border-bottom: 1px solid var(--rule);
}

.nav-inner {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
}

.nav-name {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
}

.nav-contact {
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s;
}

.nav-contact:hover { color: var(--text); }

/* ---------- shared ---------- */

section { border-top: 1px solid var(--rule); }

/* every label on the page is the same piece of type */
h2,
.eyebrow,
.contact-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.7;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

/* a section label is a level above the item labels below it, so the gap
   under it is larger than the 12px an item label uses above its own text.
   in the single-row sections this margin sets row height only, not spacing. */
h2 { margin-bottom: 28px; }

/* a label sits beside the first line of its text, so it is nudged down
   to share that line's baseline, and never stretches to the row height */
.grid > .rail { align-self: start; }

.grid > .rail { padding-top: 6px; }

/* prose never ends on a stranded word; the browser rebalances the
   last few lines rather than letting "month." sit alone */
p { text-wrap: pretty; }

p + p { margin-top: 1.35em; }

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

.hero {
  border-top: 0;
  padding: 128px 0 120px;
}

.portrait {
  display: block;
  width: 88px;
  height: 88px;
  border-radius: 3px;
  filter: saturate(0.85);
  margin-bottom: 48px;
}

.eyebrow {
  color: var(--accent);
  margin-bottom: 28px;
}

.hero h1 {
  font-size: clamp(2rem, 4.8vw, 3.3rem);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--text);
  text-wrap: balance;
  max-width: 17ch;
  margin-bottom: 60px;
}

.lede {
  font-size: 21px;
  line-height: 1.55;
  color: var(--text);
  text-wrap: pretty;
  margin-bottom: 34px;
}

/* ---------- what I do ---------- */

.doing { padding: var(--band) 0; }

.work-list > .row {
  padding: 36px 0;
  border-top: 1px solid var(--rule);
}

.work-list > .row:first-child { border-top: 0; padding-top: 0; }
.work-list > .row:last-child { padding-bottom: 0; }

.work-list dt {
  align-self: start;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.7;
  color: var(--text);
  letter-spacing: -0.01em;
  padding-top: 2px;
}

/* ---------- where the AI runs ---------- */

.ai { padding: var(--band) 0; }

/* ---------- projects ---------- */

.projects { padding: var(--band) 0; }

.project-list { list-style: none; }

/* a name in the rail and its description beside it: the same two tracks as the
   what-I-do rows, so the names line up with the section label above them and
   with the dt labels in the list above that. baseline rather than start so the
   first line of the description sits on the name's baseline, not the box's. */
.project {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gap);
  align-items: baseline;
  padding-top: 36px;
  border-top: 1px solid var(--rule);
}

.project:first-child { border-top: 0; padding-top: 0; }

.project + .project { margin-top: 60px; }

/* the hover rule hangs on text-decoration, not a border. a border rides the
   bottom of the box, so it follows the box rather than the text: as a grid cell
   it stretches to the column and the rule floats away from the word. an
   underline is anchored to the baseline, so it keeps its distance from the
   letters whatever the box does.

   justify-self is the other half, and it is not cosmetic. a grid item's box is the
   track, not the word: without it the anchor measured 172 x 89 (the full rail,
   the full row) and where the rule lands inside that box is the engine's
   business -- chrome decorated the text run and looked fine, while the 27 oct
   screenshot showed it spanning the whole rail a long way below the word. start
   makes the box the word, so the rule is 74.7px and 1.5px under the letters in
   both, and the hover area and focus ring get the same box the word has.

   offset 0 puts the rule on the baseline, hard against the letters, and each px
   of offset is a px of air below it: measured on the word "Humans" at 20px, 0,
   1, 4 and 6 give rules at 0, 1, 4 and 6px below the baseline. so the gap is a
   choice, and 4px is the smallest that reads as a rule under the word rather
   than a line through its feet. (the 0.66em the email link uses is 13px at this
   size, far enough down to read as a detached rule, which is the complaint this
   whole rule exists to answer. `from-font` was tried and does nothing here:
   chromium resolves it to `auto` and the px value wins, so it sat below the px
   looking like an override while changing nothing.) */
.project-name {
  justify-self: start;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: text-decoration-color 0.15s;
}

.project-name:hover { text-decoration-color: var(--accent); }

.project-desc { grid-column: 2; }

/* ---------- contact ---------- */

.contact { padding: var(--band) 0; }

.contact-label { padding-top: 21px; }

.contact-email {
  display: inline-block;
  justify-self: start;
  font-size: clamp(1.35rem, 3.4vw, 1.9rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 6px;
  transition: color 0.15s;
}

.contact-email:hover { color: var(--accent); }

.contact-note {
  margin-top: 32px;
  color: var(--muted);
}

/* ---------- footer ---------- */

footer { border-top: 1px solid var(--rule); padding: 32px 0; }

footer .nav-inner {
  flex-wrap: wrap;
  gap: 10px 28px;
}

footer p { font-size: 14px; color: var(--muted); }

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

/* ---------- mobile ---------- */

@media (max-width: 760px) {
  .container { padding: 0 22px; }

  /* one column: the rail moves above its content */
  .grid,
  .row,
  .project { grid-template-columns: 1fr; }

  .grid > .rail,
  .grid > .col { grid-column: 1 / -1; }

  .grid > .rail { padding-top: 0; margin-bottom: 18px; }
  h2 { margin-bottom: 0; }

  .hero { padding: 72px 0 80px; }
  .portrait { width: 72px; height: 72px; margin-bottom: 40px; }
  .hero h1 { max-width: none; margin-bottom: 40px; }
  .lede { font-size: 19px; margin-bottom: 28px; }

  /* the same rhythm, scaled to the screen rather than re-invented */
  .doing, .ai, .projects, .contact { padding: calc(var(--band) * 0.72) 0; }

  .work-list > .row { padding: 28px 0; row-gap: 12px; }
  .work-list dt { padding-top: 0; }

  .project + .project { margin-top: 44px; }
  .project-desc { grid-column: 1; margin-top: 14px; }

  .contact-label { padding-top: 0; }
  .contact-note { margin-top: 26px; }

  footer { padding: 28px 0; }
  footer .nav-inner { flex-direction: column; gap: 6px; }
}
