:root {
  --paper: #ffffff;
  --ink: #1b1d21;
  --muted: #646a73;
  --rule: #e3e5e8;
  --accent: #2f4fd8;
  /* Type scale: body, lede, display. Tracking tightens as size grows. */
  --text: 1rem;
  --text-lede: 1.125rem;
  --text-display: clamp(2rem, 1.25rem + 3vw, 2.75rem);
  --label: 9rem;
  --gap: 2.5rem;
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #141619;
    --ink: #e9eaec;
    --muted: #9aa0a8;
    --rule: #2c2f35;
    --accent: #8ea2ff;
  }
}

* { box-sizing: border-box; }

html {
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Rethink Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: var(--text);
  line-height: 1.55;
  font-kerning: normal;
  font-feature-settings: "kern", "liga", "calt";
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

.page {
  max-width: 46rem;
  margin: 0 auto;
  padding: clamp(4rem, 12vw, 8rem) 1.5rem 6rem;
}

h1, h2, p, ul, dl, dd { margin: 0; }
ul { padding: 0; list-style: none; }
p { text-wrap: pretty; }

/* Links */
a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 28%, transparent);
  text-decoration-skip-ink: auto;
  text-underline-offset: 0.22em;
  transition: text-decoration-color 0.15s;
}
a:hover { text-decoration-color: currentColor; }
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Intro */
.intro { margin-bottom: clamp(4rem, 10vw, 6rem); }

/* Small screens: chat-list row — avatar, then name over a muted title */
.name {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  margin-bottom: 1.75rem;
}
.who { min-width: 0; }
.name h1 {
  margin-bottom: 0;
  font-size: 1.25rem;
  line-height: 1.25;
  letter-spacing: -0.02em;
}
.role {
  margin-top: 0.125rem;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--muted);
}

.avatar {
  flex: none;
  display: block;
  position: relative;
  cursor: zoom-in;
  /* Long press opens the photo: no iOS callout, selection or drag */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.avatar:focus-visible { border-radius: 50%; }
/* Green "available" dot on the top-left edge, gently pulsing */
.avatar::before,
.avatar::after {
  content: "";
  position: absolute;
  top: 0.2rem;
  left: 0.2rem;
  width: 0.5625rem;
  height: 0.5625rem;
  border-radius: 50%;
  background: #54b67c;
  /* The img's view-transition-name makes it a stacking context that paints
     over earlier positioned siblings, so lift the dot above it. */
  z-index: 1;
}
/* The dot, with a paper-colored ring */
.avatar::before { box-shadow: 0 0 0 2px var(--paper); }
/* Pulse layer above the ring: grows from the dot's edge through the ring */
.avatar::after {
  opacity: 0;
  animation: pulse 3s ease-out infinite;
}
@keyframes pulse {
  0%   { transform: scale(1);   opacity: 0.35; }
  80%  { transform: scale(2.3); opacity: 0; }
  100% { transform: scale(2.3); opacity: 0; }
}
/* Circular avatar from a square photo */
.avatar img {
  display: block;
  width: 3.5rem;
  height: auto;
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
  background: var(--rule);
}

h1 {
  font-size: var(--text-display);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.035em;
  text-wrap: balance;
  margin-bottom: 1.25rem;
}

.lede {
  max-width: 32em;
  font-size: var(--text-lede);
  line-height: 1.45;
  letter-spacing: -0.011em;
}

.links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin-top: 1.75rem;
  font-weight: 500;
}

/* Sections: label column + content column */
.section {
  display: grid;
  grid-template-columns: var(--label) minmax(0, 1fr);
  gap: 0.75rem var(--gap);
  align-items: baseline;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.section + .section { margin-top: 4rem; }

/* Section labels: body size, muted. Hierarchy from color, not size. */
h2 {
  font-size: inherit;
  font-weight: 400;
  line-height: inherit;
  color: var(--muted);
}

/* Projects: title over a muted one-liner */
.projects { display: grid; gap: 1.5rem; }
.projects li { display: grid; gap: 0.125rem; justify-items: start; }
.projects a { font-weight: 500; }
.projects p { color: var(--muted); max-width: 34em; line-height: 1.5; }

/* Definition lists (stack, project facts) */
.facts {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: 0.5rem 1.5rem;
  line-height: 1.5;
}
.facts dt { color: var(--muted); }

/* Project pages */
.back {
  display: inline-block;
  margin-bottom: clamp(3rem, 8vw, 5rem);
  color: var(--muted);
  text-decoration: none;
}
.back:hover { color: var(--ink); }

/* Wide screens: photo hangs in the left margin, outside the content column */
@media (min-width: 64rem) {
  /* Out of flow so the text column doesn't move; centered on the
     name + title block, sized close to its height. */
  .name { position: relative; }
  .name { margin-bottom: 1.5rem; }
  .name h1 { font-size: 2.75rem; line-height: 1.04; letter-spacing: -0.035em; }
  .role { margin-top: 0.375rem; font-size: var(--text-lede); letter-spacing: -0.011em; }
  .avatar {
    position: absolute;
    top: 50%;
    right: calc(100% + 1.5rem);
    transform: translateY(-50%);
  }
  .avatar img { width: 5rem; }
  .avatar::before,
  .avatar::after {
    top: 0.375rem;
    left: 0.375rem;
    width: 0.625rem;
    height: 0.625rem;
  }
}

/* Wider than a phone: step body and lede up one notch */
@media (min-width: 40rem) {
  :root { --text: 1.0625rem; --text-lede: 1.25rem; }
}

@media (max-width: 40rem) {
  .section { grid-template-columns: 1fr; }
  .facts { grid-template-columns: 1fr; gap: 0; }
  .facts dd + dt { margin-top: 0.875rem; }
}

@media (prefers-reduced-motion: reduce) {
  a { transition: none; }
  .avatar::after { animation: none; }
}

/* Photo overlay on the home page: circle over the blurred page */
html.photo-open { overflow: hidden; }
.lightbox {
  inset: 0;
  width: 100vw;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-out;
}
.lightbox[open] {
  display: grid;
  place-items: center;
}
.lightbox:focus { outline: none; }
.lightbox picture { display: contents; }
.lightbox source { display: none; }
.lightbox::backdrop {
  background: color-mix(in srgb, var(--paper) 45%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

/* No-JS fallback page (/photo) */
.viewer-stage {
  --pad: clamp(1rem, 4vw, 3rem);
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--pad);
  cursor: zoom-out;
}
.viewer-stage picture { display: contents; }
/* Otherwise <source> becomes an empty grid row and pushes the photo down */
.viewer-stage source { display: none; }
/* Stays a circle, with room around it on every side */
.viewer-photo {
  display: block;
  width: min(76vw, 34rem, 72dvh);
  height: auto;
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
  /* Square window centered on the figure: hair to elbows inside the circle */
  object-position: 50% 42%;
}
/* View transition: the avatar circle grows into the full photo and back.
   Cross-page opt-in (@view-transition) is only in index.html and photo.html,
   so navigating to project pages stays instant. */
.avatar img,
.viewer-photo { view-transition-name: portrait; }
/* Names must be unique: while the overlay is open, its photo owns the name */
html.photo-open .avatar img { view-transition-name: none; }

::view-transition-group(portrait) {
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
}
/* Circle the whole way: the box only grows/shrinks */
::view-transition-image-pair(portrait) { overflow: hidden; border-radius: 50%; }
/* Both snapshots fill the morphing box, framed near the face */
::view-transition-old(portrait),
::view-transition-new(portrait) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 10%;
}
/* Quick crossfade so the two framings don't ghost during the morph */
::view-transition-old(portrait) { animation: vt-fade-out 0.2s ease-out both; }
::view-transition-new(portrait) { animation: vt-fade-in 0.2s ease-out both; }

@keyframes vt-fade-in  { from { opacity: 0; } }
@keyframes vt-fade-out { to   { opacity: 0; } }
