/* thevudev.site: one stylesheet for every page. Three token layers (primitive, semantic, component) live in :root below. */

/* ========== Base: tokens, layout and components ========== */
  /* Layout: quiet light page, ink-black actions, cobalt accents; five sections: hero, selected work, how I work, about, contact. */
  :root {
    color-scheme: light;

    /* ===== 1. PRIMITIVE: raw values, never used directly in components ===== */
    --cobalt-50: #f0f4ff;
    --cobalt-100: #e6ecff;
    --cobalt-200: #c9d5ff;
    --cobalt-400: #6b8bfa;
    --cobalt-500: #3b63f5;
    --cobalt-600: #2a50e0;
    --cobalt-700: #2140b8;
    --ink-0: #ffffff;
    --ink-25: #fafafa;
    --ink-50: #f4f4f5;
    --ink-100: #e4e4e7;
    --ink-200: #d4d4d8;
    --ink-300: #b4b4bc;
    --ink-400: #a1a1aa;
    --ink-500: #71717a;
    --ink-600: #52525b;
    --ink-800: #27272a;
    --ink-900: #18181b;
    --green-50: #ecfdf3;
    --green-500: #22c55e;
    --green-700: #15803d;
    --amber-50: #fffbeb;
    --amber-700: #b45309;
    --red-50: #fef2f2;
    --red-500: #f24822;
    --red-700: #b91c1c;

    /* ===== 2. SEMANTIC: meaning; components read only from here or layer 3 ===== */
    --surface-page: var(--ink-0);
    --surface-raised: var(--ink-0);
    --surface-sunken: var(--ink-50);
    --surface-inverse: var(--ink-900);
    --surface-highlight: var(--cobalt-100);

    --text-primary: var(--ink-900);
    --text-secondary: var(--ink-600);
    --text-tertiary: var(--ink-500);
    --text-inverse: var(--ink-25);
    --text-accent: var(--cobalt-500);
    --text-accent-on-inverse: var(--cobalt-200);

    --border-subtle: var(--ink-100);
    --border-strong: var(--ink-200);
    --border-accent: var(--cobalt-500);

    --action-primary-bg: var(--ink-900);
    --action-primary-bg-hover: var(--ink-800);
    --action-primary-fg: var(--ink-0);
    --action-secondary-bg: var(--ink-0);
    --action-secondary-border: var(--ink-200);
    --action-secondary-border-hover: var(--ink-900);
    --action-accent-bg: var(--cobalt-500);
    --action-accent-bg-hover: var(--cobalt-600);
    --action-accent-fg: var(--ink-0);

    --status-success-fg: var(--green-700);
    --status-success-bg: var(--green-50);
    --status-warning-fg: var(--amber-700);
    --status-warning-bg: var(--amber-50);
    --status-danger-fg: var(--red-700);
    --status-danger-bg: var(--red-50);

    --focus-ring: var(--cobalt-500);
    --inspect-select: var(--cobalt-500);
    --inspect-measure: var(--red-500);
    --collab-pm: #c2410c;

    /* Preview stand-ins from Google Fonts: Bricolage Grotesque for Clash Display, Geist for Satoshi */
    --font-display: "Bricolage Grotesque", "Clash Display", system-ui, sans-serif;
    --font-body: "Geist", "Satoshi", system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;

    --type-display: 800 clamp(2.5rem, 5.2vw, 4rem)/1.05 var(--font-display);
    --type-heading-1: 700 clamp(2rem, 3.6vw, 3rem)/1.1 var(--font-display);
    --type-heading-2: 700 clamp(1.5rem, 2.4vw, 2rem)/1.15 var(--font-display);
    --type-heading-3: 700 1.125rem/1.25 var(--font-display);
    --type-body-lg: 400 1.125rem/1.6 var(--font-body);
    --type-body: 400 1rem/1.6 var(--font-body);
    --type-caption: 400 0.875rem/1.5 var(--font-body);
    --type-label: 500 0.75rem/1.4 var(--font-mono);
    --tracking-display: -0.02em;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-24: 6rem;
    --space-32: 8rem;

    --radius-xs: 6px;
    --radius-sm: 10px;
    --radius-md: 16px;
    --radius-lg: 24px;
    --radius-full: 999px;

    --elevation-1: 0 1px 2px rgb(24 24 27 / 0.06), 0 12px 32px rgb(24 24 27 / 0.08);
    --elevation-2: 0 2px 4px rgb(24 24 27 / 0.06), 0 24px 56px rgb(24 24 27 / 0.14);

    --duration-fast: 150ms;
    --duration-base: 300ms;
    --duration-slow: 500ms;
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --duration-slower: 700ms;
    --duration-wipe: 900ms;

    --container: 1280px;
    --gutter: 24px;
    --z-base: 0;
    --z-sticky: 10;
    --z-overlay: 20;

    /* ===== 3. COMPONENT ===== */
    --button-height: 48px;
    --button-height-sm: 40px;
    --button-radius: var(--radius-full);

    --card-radius: var(--radius-md);
    --card-padding: var(--space-8);
    --card-shadow: var(--elevation-1);
    --card-shadow-hover: var(--elevation-2);
    --card-border: var(--border-subtle);
    --card-border-hover: var(--border-accent);

    --chip-bg: var(--surface-highlight);
    --chip-fg: var(--text-accent);
    --chip-radius: var(--radius-full);

    /* Project row (Selected work). Radii are concentric: outer = inner + padding */
    --proj-pad: var(--space-4);
    --proj-pad-sm: var(--space-3);
    --proj-media-radius: var(--radius-md);
    --proj-radius: calc(var(--proj-media-radius) + var(--proj-pad));
    --proj-media-pad-top: var(--space-8);
    --proj-media-pad-x: var(--space-3);
    --proj-media-pad-x-sm: var(--space-2);
    --proj-lift: calc(-1 * var(--space-1) / 2);
    --proj-frame-lift: calc(-1 * var(--space-2));
    --proj-rise: var(--space-4);
    --proj-stagger: 110ms;
    --browser-radius: var(--space-3);
    --browser-bar-height: calc(var(--space-6) + var(--space-1));
    --browser-dot: var(--space-2);
    --slide-fade: 360ms;
    --dot-size: var(--space-2);
    --dot-size-active: var(--space-8);
    --dot-hit: var(--space-2);
    --tech-height: calc(var(--space-6) + var(--space-1));
    --tech-icon: 1rem;
    --hit-target: 44px;
    --header-height: calc(var(--space-16) + var(--space-1));
    --header-bg: rgb(255 255 255 / 0.94);
    --header-blur: var(--space-2);
    --section-offset: calc(var(--header-height) + var(--space-3));
    --measure-head: 45rem;
    --arrow-nudge: calc(var(--space-1) / 2);
    --lb-shift: 1.5; /* rem the lightbox screen slides when changing */
    --reveal-shift: var(--space-4);
    --reveal-stagger: 80ms;
    --reveal-blur: 8px;
    --dot-track: rgb(24 24 27 / 0.2);
    --dot-track-hover: rgb(24 24 27 / 0.45);
    --dot-track-active: rgb(24 24 27 / 0.12);
    --step-dot: var(--space-8);
    --step-draw: 1200ms;
    --step-gap: var(--space-8);
    --code-bg: #1e1e1e;
    --code-attr: #9cdcfe;
    --code-string: #ce9178;
    --wipe-glow: rgb(59 99 245 / 0.55);
    --sticky-top: var(--space-24);
    --avatar-w: 15rem;
    --avatar-w-sm: 7.5rem;
    --status-dot: var(--space-2);
    --status-ring: var(--space-1);
    --status-online: var(--green-500);
    --status-online-ring: rgb(34 197 94 / 0.18);
    --flag-w: 1.125rem;
    --flag-radius: 2px;
    --flag-red: #da251d;
    --flag-star: #ffcd00;
    --inverse-fill: rgb(250 250 250 / 0.08);
    --inverse-border: rgb(250 250 250 / 0.2);
    --inverse-divider: rgb(250 250 250 / 0.14);

    /* Overlay (lightbox): light veil, page stays faintly visible behind it */
    --overlay-bg: rgb(250 250 250 / 0.9);
    --overlay-blur: var(--space-3);
    --overlay-bar-bg: rgb(250 250 250 / 0.72);

    /* Floating back-to-top */
    --fab-size: var(--hit-target);
    --fab-offset: var(--space-6);
    --fab-offset-sm: var(--space-4);

    /* About stack + certification chips */
    --stack-icon: 1.125rem;
    --stack-icon-wide: 1.75rem;
    --cert-badge: 1.5rem;

    --focus-ring-width: 2px;
    --focus-ring-offset: 3px;
  }

  * {
    box-sizing: border-box;
  }

  html {
    scroll-behavior: smooth;
  }

  body {
    margin: 0;
    background: var(--surface-page);
    color: var(--text-primary);
    font: var(--type-body);
    -webkit-font-smoothing: antialiased;
  }

  img {
    max-width: 100%;
    display: block;
  }

  main {
    overflow-x: clip;
  }

  a {
    color: inherit;
  }

  :focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: var(--focus-ring-offset);
    border-radius: var(--radius-xs);
  }

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

  h1,
  h2,
  h3 {
    letter-spacing: var(--tracking-display);
    text-wrap: balance;
    margin: 0;
  }

  p {
    margin: 0;
  }

  .label {
    font: var(--type-label);
    letter-spacing: 0.02em;
  }

  /* Buttons */
  .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--button-height);
    padding-inline: var(--space-6);
    border-radius: var(--button-radius);
    font: 600 1rem/1 var(--font-body);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    border: 1px solid transparent;
    transition:
      background var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out),
      border-color var(--duration-fast) var(--ease-out);
  }

  .btn:active {
    transform: translateY(1px) scale(0.98);
  }

  .btn-primary {
    background: var(--action-primary-bg);
    color: var(--action-primary-fg);
  }

  .btn-primary:hover {
    background: var(--action-primary-bg-hover);
  }

  .btn-secondary {
    background: var(--action-secondary-bg);
    color: var(--text-primary);
    border-color: var(--action-secondary-border);
  }

  .btn-secondary:hover {
    border-color: var(--action-secondary-border-hover);
  }

  .btn-accent {
    background: var(--action-accent-bg);
    color: var(--action-accent-fg);
  }

  .btn-accent:hover {
    background: var(--action-accent-bg-hover);
  }

  .btn-sm {
    height: var(--button-height-sm);
    padding-inline: var(--space-4);
    font-size: 0.875rem;
  }

  /* Header */
  .site-header {
    position: sticky;
    top: env(safe-area-inset-top, 0px);
    z-index: var(--z-sticky);
    background: var(--header-bg);
    backdrop-filter: blur(var(--header-blur));
    -webkit-backdrop-filter: blur(var(--header-blur));
  }

  .site-header .wrap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: var(--header-height);
    gap: var(--space-4);
  }

  .brand {
    text-decoration: none;
    font: 700 1.25rem/1 var(--font-display);
    letter-spacing: var(--tracking-display);
    color: var(--text-primary);
  }

  .brand span {
    color: var(--text-accent);
  }

  .nav {
    display: flex;
    align-items: center;
    gap: var(--space-8);
  }

  .nav a:not(.btn) {
    position: relative;
    text-decoration: none;
    color: var(--text-secondary);
    font: var(--type-caption);
    font-weight: 500;
    padding-block: var(--space-2);
    transition: color var(--duration-fast) var(--ease-out);
  }

  .nav a:not(.btn)::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 2px;
    border-radius: 2px;
    background: var(--border-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--duration-base) var(--ease-out);
  }

  .nav a:not(.btn):hover {
    color: var(--text-primary);
  }

  .nav a[aria-current="true"] {
    color: var(--text-primary);
  }

  .nav a[aria-current="true"]::after {
    transform: scaleX(1);
  }

  .site-header.is-scrolled {
    border-bottom: 1px solid var(--border-subtle);
  }

  /* Hero */
  .hero .wrap > * {
    min-width: 0;
  }

  .hero h1 {
    font: var(--type-display);
    letter-spacing: var(--tracking-display);
  }

  .hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
  }

  /* Hero: slogan only. Line 1 set like code, line 2 like design; "pixels" snaps to the grid on load */
  .hero {
    padding-block: clamp(4rem, 11vh, 8rem) clamp(1.5rem, 5vh, 3.5rem);
  }

  .hero .wrap {
    display: block;
  }

  .slogan {
    display: grid;
    gap: var(--space-6);
    margin: 0;
    letter-spacing: 0;
  }

  .s-code,
  .s-design {
    text-box: trim-both cap alphabetic;
  }

  .s-code {
    font: 500 clamp(1.5rem, 3.6vw, 3rem)/1.2 var(--font-mono);
    color: var(--text-secondary);
    letter-spacing: -0.01em;
  }

  .s-design {
    font: 800 clamp(2.75rem, 7.2vw, 6.25rem)/1.02 var(--font-display);
    letter-spacing: -0.035em;
    color: var(--text-primary);
  }

  .px {
    font-style: normal;
    color: var(--text-accent);
    display: inline-block;
    white-space: nowrap;
  }

  .px span {
    display: inline-block;
  }

  @media (prefers-reduced-motion: no-preference) {
    .s-code {
      animation: sf-in var(--duration-slow) var(--ease-out) both;
    }

    .s-design {
      animation: sf-in var(--duration-slow) var(--ease-out) both;
      animation-delay: 120ms;
    }

    .px span {
      animation: px-snap 700ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
      animation-delay: calc(450ms + var(--n) * 45ms);
    }
  }

  @keyframes px-snap {
    from {
      transform: translate(var(--dx), var(--dy));
      opacity: 0.35;
    }
  }

  /* Hero entrance: rise with a soft blur that resolves into focus */
  @keyframes sf-in {
    from {
      opacity: 0;
      transform: translateY(var(--reveal-shift));
      filter: blur(var(--reveal-blur));
    }
  }

  /* Hero motion: typed code line + Figma-style inspect overlay */
  .hero .wrap {
    position: relative;
  }

  .s-code,
  .s-design {
    justify-self: start;
  }

  .typed {
    display: inline-block;
    white-space: nowrap;
    overflow: clip;
    vertical-align: baseline;
  }

  /* caret: a block sized to the cap height, sitting on the baseline like the text */
  .s-code::after {
    content: "";
    display: inline-block;
    width: 0.2em;
    height: 0.73em;
    margin-left: 0.18em;
    vertical-align: baseline;
    background: var(--text-accent);
  }

  @media (prefers-reduced-motion: no-preference) {
    .s-code {
      animation: none;
    }

    /* caret stays solid while typing, then blinks at the end of the line */
    .typed {
      width: 15ch;
      animation: type 850ms steps(15, end) 200ms both;
    }

    .s-code::after {
      animation: caret 1.8s steps(1) 1.1s infinite;
    }
  }

  @keyframes type {
    from {
      width: 0;
    }
  }

  @keyframes caret {
    0% {
      opacity: 1;
    }

    50% {
      opacity: 0;
    }
  }

  .inspect {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  .hero.is-inspect .inspect {
    opacity: 1;
  }

  .ins-box {
    position: absolute;
    border: 1px solid var(--inspect-select);
  }

  .ins-box .h {
    position: absolute;
    width: 7px;
    height: 7px;
    background: var(--surface-raised);
    border: 1px solid var(--inspect-select);
  }

  .ins-box .tl {
    left: -4px;
    top: -4px;
  }

  .ins-box .tr {
    right: -4px;
    top: -4px;
  }

  .ins-box .bl {
    left: -4px;
    bottom: -4px;
  }

  .ins-box .br {
    right: -4px;
    bottom: -4px;
  }

  .ins-size {
    position: absolute;
    left: 50%;
    bottom: -30px;
    transform: translateX(-50%);
    font: 500 11px/1 var(--font-mono);
    white-space: nowrap;
    padding: 4px 6px;
    border-radius: 3px;
    background: var(--inspect-select);
    color: var(--ink-0);
  }

  .ins-gap {
    position: absolute;
    width: 1px;
    background: var(--inspect-measure);
  }

  .ins-gap::before,
  .ins-gap::after {
    content: "";
    position: absolute;
    left: -4px;
    width: 9px;
    height: 1px;
    background: var(--inspect-measure);
  }

  .ins-gap::before {
    top: 0;
  }

  .ins-gap::after {
    bottom: 0;
  }

  .ins-gap-label {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    font: 500 11px/1 var(--font-mono);
    white-space: nowrap;
    padding: 3px 5px;
    border-radius: 3px;
    background: var(--inspect-measure);
    color: var(--ink-0);
  }

  @media (prefers-reduced-motion: reduce) {
    .inspect {
      display: none;
    }
  }

  /* Hero background: Figma-style dot canvas, strongest behind the slogan */
  .hero {
    position: relative;
    isolation: isolate;
  }

  .hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: radial-gradient(circle, var(--ink-300) 1.3px, transparent 1.65px);
    background-size: 16px 16px;
    background-position: 8px 8px;
    -webkit-mask-image:
      linear-gradient(to bottom, #000 45%, transparent 100%),
      radial-gradient(ellipse 70% 80% at 32% 45%, #000 35%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image:
      linear-gradient(to bottom, #000 45%, transparent 100%),
      radial-gradient(ellipse 70% 80% at 32% 45%, #000 35%, transparent 100%);
    mask-composite: intersect;
    opacity: 0.9;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  .hero.is-inspect::before {
    opacity: 1;
    background-image: radial-gradient(circle, var(--ink-400) 1.3px, transparent 1.65px);
  }

  .hero-intro {
    margin-top: var(--space-12);
    max-width: 52ch;
    font: var(--type-body-lg);
    color: var(--text-secondary);
  }

  .hero-cta {
    margin-top: var(--space-8);
    width: fit-content;
  }

  .hero-intro,
  .hero-meta {
    width: fit-content;
  }

  .hero-meta {
    margin-top: var(--space-6);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font: var(--type-label);
    font-size: 0.8125rem;
    color: var(--text-tertiary);
  }

  .hero-meta .hero-dot {
    margin-top: 0;
  }

  @media (prefers-reduced-motion: no-preference) {
    .hero-intro {
      animation: sf-in var(--duration-slow) var(--ease-out) both;
      animation-delay: 700ms;
    }

    .hero-cta {
      animation: sf-in var(--duration-slow) var(--ease-out) both;
      animation-delay: 800ms;
    }

    .hero-meta {
      animation: sf-in var(--duration-slow) var(--ease-out) both;
      animation-delay: 900ms;
    }
  }

  /* DevTools-style inspect for the code line */
  .dt-hl,
  .dt-tip {
    position: absolute;
    display: none;
  }

  .hero.is-devtools .dt-hl,
  .hero.is-devtools .dt-tip {
    display: block;
  }

  .hero.is-devtools .ins-box,
  .hero.is-devtools .ins-gap {
    display: none !important;
  }

  .dt-hl {
    background: rgb(111 168 220 / 0.45);
    outline: 1px dashed rgb(59 99 245 / 0.6);
  }

  .dt-tip {
    min-width: 230px;
    padding: 8px 10px;
    border-radius: 4px;
    background: var(--ink-0);
    color: var(--ink-800);
    box-shadow:
      0 1px 2px rgb(0 0 0 / 0.15),
      0 4px 14px rgb(0 0 0 / 0.12);
    font:
      400 11px/1.5 ui-monospace,
      Menlo,
      Consolas,
      monospace;
  }

  .dt-tip::after {
    content: "";
    position: absolute;
    left: 14px;
    bottom: -6px;
    width: 10px;
    height: 10px;
    background: inherit;
    transform: rotate(45deg);
    box-shadow: 2px 2px 2px rgb(0 0 0 / 0.06);
  }

  .dt-tip.is-below::after {
    bottom: auto;
    top: -6px;
    box-shadow: -2px -2px 2px rgb(0 0 0 / 0.04);
  }

  .dt-head {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding-bottom: 5px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--ink-100);
  }

  .dt-sel {
    color: #881280;
    font-weight: 600;
  }

  .dt-sel em {
    color: #1a1aa6;
    font-style: normal;
  }

  .dt-size {
    color: var(--ink-500);
  }

  .dt-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    color: var(--ink-500);
  }

  .dt-row b {
    color: var(--ink-800);
    font-weight: 400;
  }

  .dt-color {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }

  .dt-color i {
    width: 10px;
    height: 10px;
    border: 1px solid rgb(0 0 0 / 0.2);
  }

  /* Self-playing inspect tour + cursor spotlight on the dot canvas */
  /* Collaboration loop: PM leaves a comment, Vu inspects and resolves it */
  /* The visitor keeps their real cursor; a Figma-style guest label just follows it */
  .guest-tag {
    position: absolute;
    left: 0;
    top: 0;
    opacity: 0;
    transform: translate(var(--gx, -999px), var(--gy, -999px));
    padding: 3px 7px;
    border-radius: 4px 10px 10px 10px;
    background: var(--ink-600);
    color: var(--ink-0);
    font: 600 11px/1.2 var(--font-body);
    white-space: nowrap;
    transition: opacity var(--duration-fast) var(--ease-out);
  }

  @media (hover: hover) {
    .hero.is-guest .guest-tag {
      opacity: 1;
    }
  }

  .pin-area {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    opacity: 0;
    border-radius: 6px;
    border: 1.5px solid var(--collab-pm);
    background: color-mix(in srgb, var(--collab-pm) 8%, transparent);
    transition:
      opacity var(--duration-base) var(--ease-out),
      border-color var(--duration-base) var(--ease-out),
      background var(--duration-base) var(--ease-out);
  }

  .pin-area.is-on {
    opacity: 1;
  }

  .pin-area.is-resolved {
    border-color: var(--status-success-fg);
    background: rgb(21 128 61 / 0.07);
  }

  .collab {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
  }

  .cur {
    position: absolute;
    left: 0;
    top: 0;
    opacity: 0;
    transform: translate(var(--cx, 0px), var(--cy, 0px));
    transition:
      transform var(--duration-slower) var(--ease-in-out),
      opacity var(--duration-base) var(--ease-out);
    filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.2));
  }

  .cur.is-on {
    opacity: 1;
  }

  .cur-vu {
    --c: var(--cobalt-500);
    color: var(--c);
  }

  .cur-pm {
    --c: var(--collab-pm);
    color: var(--c);
  }

  .cur-name {
    position: absolute;
    left: 14px;
    top: 18px;
    padding: 3px 7px;
    border-radius: 4px 10px 10px 10px;
    background: var(--c);
    color: #fff;
    font: 600 11px/1.2 var(--font-body);
    white-space: nowrap;
  }

  .pin {
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    opacity: 0;
    transform: translateY(6px) scale(0.97);
    transform-origin: left bottom;
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out);
  }

  .pin.is-on {
    opacity: 1;
    transform: none;
  }

  .pin.is-flip {
    flex-direction: row-reverse;
    transform-origin: right bottom;
  }

  .pin-marker {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 50% 50% 50% 0;
    display: grid;
    place-items: center;
    background: var(--collab-pm);
    color: #fff;
    font: 700 12px/1 var(--font-body);
    box-shadow: 0 2px 6px rgb(0 0 0 / 0.18);
    transition: background var(--duration-base) var(--ease-out);
  }

  .pin.is-resolved .pin-marker {
    background: var(--status-success-fg);
    font-size: 0;
  }

  .pin.is-resolved .pin-marker::after {
    content: "\2713";
    font-size: 14px;
  }

  .pin-card {
    width: 236px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    box-shadow: 0 4px 16px rgb(24 24 27 / 0.12);
    display: grid;
    gap: 8px;
  }

  .pin-row {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr);
    gap: 8px;
    align-items: start;
  }

  .pin-row b {
    font: 600 12px/1.3 var(--font-body);
    color: var(--text-primary);
  }

  .pin-row p {
    margin: 1px 0 0;
    font: 400 12.5px/1.4 var(--font-body);
    color: var(--text-secondary);
  }

  .av {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font: 700 10px/1 var(--font-body);
    font-style: normal;
    color: #fff;
  }

  .av-pm {
    background: var(--collab-pm);
  }

  .av-vu {
    background: var(--cobalt-500);
  }

  .pin-reply {
    display: none;
    padding-top: 8px;
    border-top: 1px solid var(--border-subtle);
  }

  .pin.is-resolved .pin-reply {
    display: grid;
  }

  @media (prefers-reduced-motion: reduce) {
    .collab {
      display: none;
    }
  }

  .hero:not(.is-inspect) .ins-box,
  .hero:not(.is-inspect) .ins-gap,
  .hero:not(.is-inspect) .dt-hl,
  .hero:not(.is-inspect) .dt-tip {
    visibility: hidden;
  }

  .hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: radial-gradient(circle, var(--ink-500) 1.4px, transparent 1.75px);
    background-size: 16px 16px;
    background-position: 8px 8px;
    -webkit-mask-image: radial-gradient(circle 170px at var(--mx, -999px) var(--my, -999px), #000 0%, transparent 100%);
    mask-image: radial-gradient(circle 170px at var(--mx, -999px) var(--my, -999px), #000 0%, transparent 100%);
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .hero.is-spot::after {
      opacity: 0.85;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .hero::after {
      display: none;
    }
  }

  /* Selected work: one row per project. On hover both columns sit inside one card; a stretched link opens the case study */
  .proj-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-8);
  }

  .proj {
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-12);
    align-items: center;
    min-width: 0;
    padding: var(--proj-pad);
    margin-inline: calc(-1 * var(--proj-pad));
    border: 1px solid transparent;
    border-radius: var(--proj-radius);
    background: var(--surface-page);
    transition:
      border-color var(--duration-base) var(--ease-out),
      translate var(--duration-base) var(--ease-out);
  }

  /* Hover shadow is pre-painted on a pseudo layer and only fades in: no repaint per frame */
  .proj::after {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: -1;
    border-radius: inherit;
    box-shadow: var(--elevation-2);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  .proj-visual {
    min-width: 0;
  }

  .proj-media {
    position: relative;
    padding: var(--proj-media-pad-top) var(--proj-media-pad-x) 0;
    background: var(--tint);
    border: 1px solid var(--border-subtle);
    border-radius: var(--proj-media-radius);
    overflow: hidden;
  }

  .frame-label {
    position: absolute;
    top: 0;
    left: var(--proj-media-pad-x);
    font: var(--type-label);
    line-height: var(--proj-media-pad-top);
    color: var(--text-tertiary);
    opacity: 0;
    transform: translateY(var(--space-1));
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out);
  }

  .browser {
    border-radius: var(--browser-radius) var(--browser-radius) 0 0;
    overflow: hidden;
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    border-bottom: 0;
    box-shadow: var(--elevation-2);
    margin-bottom: var(--proj-frame-lift);
  }

  .browser-bar {
    height: var(--browser-bar-height);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-inline: var(--space-3);
    background: var(--ink-50);
    border-bottom: 1px solid var(--border-subtle);
  }

  .browser-bar i {
    width: var(--browser-dot);
    height: var(--browser-dot);
    border-radius: 50%;
    background: var(--ink-200);
  }

  .browser-view {
    position: relative;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--surface-sunken);
  }

  .browser-view .shot {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity var(--slide-fade) var(--ease-out);
  }

  .browser-view .shot.is-on {
    opacity: 1;
  }

  /* Theme wipe: the same screen re-rendered with another token set sweeps in from the left */
  .browser-view .shot.is-wipe-in {
    opacity: 1;
    z-index: 2;
    transition: none;
    clip-path: inset(0 100% 0 0);
  }

  .browser-view .shot.is-wipe-in.is-go {
    clip-path: inset(0 0 0 0);
    transition: clip-path var(--duration-wipe) var(--ease-in-out);
  }

  .browser-view .shot.is-wipe-out {
    opacity: 1;
    transition: none;
  }

  .wipe-track {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    transform: translateX(-100%);
  }

  .wipe-track.is-go {
    transform: translateX(0);
    transition: transform var(--duration-wipe) var(--ease-in-out);
  }

  .wipe-track::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 2px;
    background: var(--text-accent);
    box-shadow:
      0 0 0 1px rgb(255 255 255 / 0.5),
      0 0 var(--space-4) var(--wipe-glow);
  }

  .wipe-tag {
    position: absolute;
    top: var(--space-3);
    right: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-xs);
    background: var(--code-bg);
    color: var(--code-attr);
    font: var(--type-label);
    white-space: nowrap;
    box-shadow: var(--elevation-2);
  }

  .wipe-tag b {
    color: var(--code-string);
    font-weight: inherit;
  }

  .browser-view img.shot {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 0%;
    transition: opacity var(--slide-fade) var(--ease-out);
  }

  /* Slide indicators: the active one is a pill that fills while the slide plays */
  .dots {
    display: flex;
    justify-content: center;
    margin-top: var(--space-2);
  }

  .dot {
    position: relative;
    width: calc(var(--dot-size) + 2 * var(--dot-hit));
    height: calc(var(--dot-size) + 2 * var(--dot-hit) + var(--space-1));
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    transition: width var(--duration-base) var(--ease-out);
  }

  .dot::before,
  .dot::after {
    content: "";
    position: absolute;
    left: var(--dot-hit);
    right: var(--dot-hit);
    top: 50%;
    height: var(--dot-size);
    translate: 0 -50%;
    border-radius: var(--radius-full);
  }

  .dot::before {
    background: var(--dot-track);
    transition: background var(--duration-fast) var(--ease-out);
  }

  .dot:hover::before {
    background: var(--dot-track-hover);
  }

  .dot[aria-selected="true"] {
    width: calc(var(--dot-size-active) + 2 * var(--dot-hit));
  }

  .dot[aria-selected="true"]::before {
    background: var(--dot-track-active);
  }

  .dot[aria-selected="true"]::after {
    background: var(--text-accent);
    transform-origin: left;
  }

  .dots {
    position: relative;
    z-index: 2;
  }

  .media-open {
    position: absolute;
    inset: 0;
    z-index: 2;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
    border-radius: inherit;
  }

  .media-open:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: calc(-1 * var(--focus-ring-width));
  }

  .dot:focus-visible {
    outline: none;
  }

  .dot:focus-visible::before {
    box-shadow:
      0 0 0 var(--focus-ring-width) var(--surface-page),
      0 0 0 calc(2 * var(--focus-ring-width)) var(--focus-ring);
  }

  @media (prefers-reduced-motion: no-preference) {
    .is-auto .dot[aria-selected="true"]::after {
      animation: dot-fill 4s linear both;
    }

    .is-auto:not(.is-in-view) .dot::after,
    .is-auto:hover .dot::after,
    .lb-open .is-auto .dot::after {
      animation-play-state: paused;
    }
  }

  @keyframes dot-fill {
    from {
      transform: scaleX(0);
    }

    to {
      transform: scaleX(1);
    }
  }

  /* Lightbox: screens at full size, full-page captures scroll inside */
  .lb-open {
    overflow: hidden;
  }

  .lightbox {
    width: 100vw;
    height: 100dvh;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    overflow: hidden;
  }

  .lightbox::backdrop {
    background: var(--overlay-bg);
    backdrop-filter: blur(var(--overlay-blur));
    -webkit-backdrop-filter: blur(var(--overlay-blur));
  }

  .lightbox[open] {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
  }

  @media (prefers-reduced-motion: no-preference) {
    .lightbox[open] {
      animation: lb-in var(--duration-base) var(--ease-out);
    }

    .lightbox[open]::backdrop {
      animation: lb-fade var(--duration-base) var(--ease-out);
    }
  }

  @keyframes lb-in {
    from {
      opacity: 0;
      transform: scale(0.98);
    }
  }

  @keyframes lb-fade {
    from {
      opacity: 0;
    }
  }

  .lb-bar {
    background: var(--overlay-bar-bg);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4) var(--space-3) var(--space-6);
  }

  .lb-title {
    font: var(--type-label);
    color: var(--text-primary);
  }

  .lb-count {
    font: var(--type-label);
    color: var(--text-tertiary);
    margin-right: auto;
  }

  .lb-btn {
    display: inline-grid;
    place-items: center;
    width: var(--hit-target);
    height: var(--hit-target);
    border: 1px solid transparent;
    border-radius: var(--radius-full);
    background: var(--action-primary-bg);
    color: var(--action-primary-fg);
    font: 500 1.125rem/1 var(--font-body);
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out);
  }

  .lb-btn:hover {
    background: var(--action-primary-bg-hover);
  }

  .lb-btn:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: var(--focus-ring-width);
  }

  .lb-stage:focus {
    outline: none;
  }

  .lb-stage {
    position: relative;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0 calc(var(--hit-target) + var(--space-8)) var(--space-12);
  }

  .lb-stage img {
    display: block;
    width: 100%;
    max-width: var(--container);
    height: auto;
    margin-inline: auto;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-subtle);
    box-shadow: var(--elevation-2);
  }

  .lb-nav {
    position: fixed;
    top: 50%;
    translate: 0 -50%;
    z-index: 1;
  }

  .lb-prev {
    left: var(--space-4);
  }

  .lb-next {
    right: var(--space-4);
  }

  @media (max-width: 640px) {
    .lb-stage {
      padding: 0 var(--space-3) calc(var(--hit-target) + var(--space-12));
    }

    .lb-nav {
      top: auto;
      bottom: var(--space-6);
      translate: none;
    }

    .lb-prev {
      left: calc(50% - var(--hit-target) - var(--space-3));
    }

    .lb-next {
      right: calc(50% - var(--hit-target) - var(--space-3));
    }
  }

  /* Body */
  .proj-body {
    display: grid;
    gap: var(--space-6);
    align-content: center;
  }

  .proj-intro {
    display: grid;
    gap: var(--space-3);
    justify-items: start;
  }

  .proj-intro h3 {
    font: var(--type-heading-2);
    letter-spacing: var(--tracking-display);
    transition: color var(--duration-base) var(--ease-out);
  }

  .proj-intro h3 .cat {
    color: var(--text-tertiary);
    font-weight: 400;
  }

  /* Project title: the whole title underlines left to right on row hover */
  .proj-title {
    background: linear-gradient(currentColor, currentColor) 0 100% / 0 2px no-repeat;
    padding-bottom: 2px;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    transition: background-size var(--duration-slow) var(--ease-out);
  }

  .proj-intro h3 .cat {
    transition: color var(--duration-base) var(--ease-out);
  }

  @media (hover: hover) {
    .proj:hover .proj-title {
      background-size: 100% 2px;
    }

    .proj:hover .proj-intro h3 .cat {
      color: var(--text-secondary);
    }
  }

  .proj:has(.more:focus-visible) .proj-title {
    background-size: 100% 2px;
  }

  @media (prefers-reduced-motion: reduce) {
    .proj-title,
    .proj-intro h3 .cat {
      transition: none;
    }
  }


  .proj-intro p {
    color: var(--text-secondary);
    max-width: 48ch;
  }

  .proj-points {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-3);
  }

  .proj-points li {
    position: relative;
    padding-left: var(--space-6);
    color: var(--text-secondary);
    font: var(--type-caption);
  }

  .proj-points li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: var(--space-2);
    height: var(--space-2);
    border-radius: 2px;
    background: var(--action-accent-bg);
    opacity: 0.85;
  }

  .proj-points b {
    color: var(--text-primary);
    font-weight: 600;
  }

  .proj-body code {
    font: 500 0.88em/1 var(--font-mono);
    color: var(--text-primary);
    background: var(--surface-sunken);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    padding: 1px var(--space-1);
  }

  .proj-side {
    display: grid;
    gap: var(--space-4);
  }

  .proj-side .stats {
    border-top: 0;
    padding: 0;
  }

  .proj-side .stats div {
    justify-content: flex-start;
    gap: var(--space-4);
  }

  /* Tech stack chips: logo gray at rest, brand color while the row is hovered */
  .stack {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--tech-height);
    padding-inline: var(--space-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-full);
    font: var(--type-label);
    color: var(--text-secondary);
    background: var(--surface-page);
  }

  .chip svg {
    width: var(--tech-icon);
    height: var(--tech-icon);
    fill: var(--ink-500);
    transition: fill var(--duration-base) var(--ease-out);
  }

  .proj-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-6);
  }

  .proj-links .more {
    text-decoration: none;
  }

  .proj-links button.ext {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
  }

  .proj-links button.more {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--text-accent);
    cursor: pointer;
  }

  .proj-links .more .ico-go {
    transition: transform var(--duration-base) var(--ease-out);
  }

  .proj-links .more::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
  }

  .proj-links .more:focus-visible {
    outline: none;
  }

  .proj:has(.more:focus-visible) {
    border-color: var(--border-accent);
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: var(--focus-ring-width);
  }

  .proj-links .ext {
    position: relative;
    z-index: 2;
    color: var(--text-secondary);
    text-decoration: none;
    font-weight: 500;
  }

  .proj-links .ext:hover {
    color: var(--text-primary);
  }

  /* Row hover */
  @media (hover: hover) {
    .proj:hover {
      border-color: var(--border-accent);
      translate: 0 var(--proj-lift);
    }

    .proj:hover::after {
      opacity: 1;
    }

    .proj:hover .frame-label {
      opacity: 1;
      transform: none;
    }

    .proj:hover h3 {
      color: var(--text-accent);
    }


    .proj:hover .chip svg {
      fill: var(--brand);
    }
  }

  .proj:has(.more:focus-visible) .frame-label {
    opacity: 1;
    transform: none;
  }

  @media (prefers-reduced-motion: reduce) {
    .browser-view .shot,
    .proj,
    .proj-links .more .ico-go {
      transition: none;
    }
  }

  @media (max-width: 900px) {
    .proj {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-6);
      padding: var(--proj-pad-sm);
      margin-inline: calc(-1 * var(--proj-pad-sm));
    }
  }

  @media (max-width: 640px) {
    .proj-media {
      --proj-media-pad-x: var(--proj-media-pad-x-sm);
    }
  }

  .stats {
    display: grid;
    gap: 2px;
    padding: var(--space-2) var(--space-1) var(--space-1);
    border-top: 1px dashed var(--border-strong);
    margin: 0;
  }

  .stats div {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
  }

  .stats dt {
    color: var(--text-tertiary);
  }

  .stats dd {
    margin: 0;
    color: var(--text-primary);
    text-align: right;
  }

  /* Sections */
  section {
    scroll-margin-top: var(--section-offset);
  }

  .section {
    padding-block: var(--space-24);
  }

  .section-head {
    display: grid;
    gap: var(--space-3);
    margin-bottom: var(--space-12);
    max-width: var(--measure-head);
  }

  .section-head h2 {
    font: var(--type-heading-1);
    letter-spacing: var(--tracking-display);
  }

  .section-head p {
    color: var(--text-secondary);
    font: var(--type-body-lg);
    max-width: 60ch;
  }

  .more {
    font-weight: 600;
    color: var(--text-accent);
    display: inline-flex;
    gap: var(--space-2);
    align-items: center;
  }

  .more .ico-go {
    transition: transform var(--duration-base) var(--ease-out);
  }

  /* How I work: five steps, one row. Kept short so Selected work stays the highlight */
  .how {
    /* On the sunken band cobalt-500 falls just under 4.5:1 for small text, so step up one shade */
    --text-accent: var(--cobalt-600);
    background: var(--surface-sunken);
  }

  .steps {
    --col-w: calc((100% - 4 * var(--step-gap)) / 5);
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    column-gap: var(--step-gap);
  }

  .steps::before,
  .steps::after {
    content: "";
    position: absolute;
    left: calc(var(--step-dot) / 2);
    top: calc(var(--step-dot) / 2);
    transform-origin: left center;
  }

  .steps::before {
    right: calc(var(--col-w) - var(--step-dot) / 2);
    height: 1px;
    background: var(--border-strong);
  }

  /* Hover progress: from 01 to the hovered step */
  .steps::after {
    right: calc(var(--col-w) - var(--step-dot) / 2);
    height: 2px;
    margin-top: -0.5px;
    background: var(--text-accent);
    transform: scaleX(calc(var(--to, 0) / 4));
    transition: transform var(--duration-base) var(--ease-out);
  }

  .step {
    position: relative;
    display: grid;
    gap: var(--space-2);
    align-content: start;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  .step-dot {
    position: relative;
    width: var(--step-dot);
    height: var(--step-dot);
    margin-bottom: var(--space-3);
    display: grid;
    place-items: center;
    border-radius: var(--radius-full);
    background: var(--surface-page);
    border: 1px solid var(--border-strong);
    font: var(--type-label);
    color: var(--text-secondary);
    z-index: 1;
    transition:
      background var(--duration-base) var(--ease-out),
      border-color var(--duration-base) var(--ease-out),
      color var(--duration-base) var(--ease-out);
  }

  .step:last-child .step-dot {
    background: var(--action-accent-bg);
    border-color: transparent;
    color: var(--action-accent-fg);
  }

  .step-name {
    color: var(--text-accent);
  }

  .step h3 {
    transition: color var(--duration-base) var(--ease-out);
  }

  .steps.is-hovering .step.is-after {
    opacity: 0.7;
  }

  .steps.is-hovering .step.is-after .step-dot {
    background: var(--surface-page);
    border-color: var(--border-strong);
    color: var(--text-secondary);
  }

  .steps.is-hovering .step.is-done .step-dot {
    background: var(--action-accent-bg);
    border-color: transparent;
    color: var(--action-accent-fg);
  }

  .steps.is-hovering .step.is-current .step-dot {
    background: var(--surface-highlight);
    border-color: var(--border-accent);
    color: var(--text-accent);
  }

  .steps.is-hovering .step.is-current h3 {
    color: var(--text-accent);
  }

  /* Scroll-in: the line draws from 01 to the edge, steps appear as it reaches them */
  @media (prefers-reduced-motion: no-preference) {
    .steps.will-draw::before {
      transform: scaleX(0);
    }

    .steps.will-draw .step {
      opacity: 0;
      transform: translateY(var(--space-1));
    }

    .steps.is-drawn::before {
      transform: scaleX(1);
      transition: transform var(--step-draw) var(--ease-in-out);
    }

    .steps.is-drawn .step {
      opacity: 1;
      transform: none;
      transition:
        opacity var(--duration-slow) var(--ease-out),
        transform var(--duration-slow) var(--ease-out);
      transition-delay: calc(var(--i) * var(--step-draw) / 5);
    }
  }

  .step h3 {
    font: var(--type-heading-3);
    font-size: 1rem;
    letter-spacing: var(--tracking-display);
    text-wrap: pretty;
  }

  .step p {
    font: var(--type-caption);
    color: var(--text-secondary);
  }

  .step a {
    color: var(--text-accent);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    margin-right: var(--space-2);
  }

  .step-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-4);
  }

  .step a .ico {
    vertical-align: -0.125em;
  }

  .step a:hover {
    text-decoration: underline;
    text-underline-offset: var(--space-1);
  }

  /* About & Contact */
  .about-main {
    display: grid;
    grid-template-columns: var(--avatar-w) minmax(0, 1fr);
    gap: var(--space-12);
    align-items: start;
  }

  .avatar {
    margin: 0;
    display: grid;
    gap: var(--space-3);
  }

  .avatar-frame {
    aspect-ratio: 4 / 5;
    max-width: 100%;
    border-radius: var(--card-radius);
    overflow: hidden;
    border: 1px solid var(--card-border);
    box-shadow: var(--card-shadow);
    background: var(--surface-sunken);
  }

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

  .avatar figcaption {
    display: grid;
    gap: var(--space-1);
  }

  .avatar figcaption strong {
    font-weight: 600;
  }

  .place {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    color: var(--text-tertiary);
    font: var(--type-caption);
  }

  .flag {
    width: var(--flag-w);
    height: auto;
    aspect-ratio: 3 / 2;
    flex: none;
    border-radius: var(--flag-radius);
    overflow: hidden;
  }

  .flag rect {
    fill: var(--flag-red);
  }

  .flag path {
    fill: var(--flag-star);
  }

  .about-text {
    display: grid;
    gap: var(--space-6);
    font: var(--type-body-lg);
    color: var(--text-secondary);
    max-width: 60ch;
  }

  .about-text strong {
    color: var(--text-primary);
    font-weight: 600;
  }

  .hero-dot {
    width: var(--status-dot);
    height: var(--status-dot);
    border-radius: var(--radius-full);
    background: var(--status-online);
    box-shadow: 0 0 0 var(--status-ring) var(--status-online-ring);
    flex: none;
  }

  .facts {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: 0;
    margin: 0;
  }

  .section.contact {
    padding-top: 0;
  }

  .contact-card {
    border-radius: var(--radius-lg);
    background: var(--surface-inverse);
    color: var(--text-inverse);
    padding: var(--space-12);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-12);
    align-items: start;
  }

  .contact-intro {
    display: grid;
    gap: var(--space-6);
    align-content: start;
  }

  .contact-card h2 {
    font: var(--type-heading-1);
    letter-spacing: var(--tracking-display);
  }

  .contact-lead {
    max-width: 40ch;
    color: var(--ink-400);
    font: var(--type-body-lg);
  }

  .contact-meta {
    display: grid;
    gap: var(--space-3);
    padding: 0;
    margin: 0;
    list-style: none;
    color: var(--ink-400);
    font: var(--type-caption);
  }

  .contact-meta li {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }

  .contact-meta .hero-dot {
    margin-inline: calc((var(--flag-w) - var(--status-dot)) / 2);
  }

  .contact-actions {
    display: grid;
    gap: var(--space-6);
  }

  .email-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-3);
    align-items: stretch;
  }

  .email {
    font: 500 1rem/1.2 var(--font-mono);
    display: flex;
    align-items: center;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--inverse-fill);
    border: 1px solid var(--inverse-border);
    user-select: all;
    overflow-wrap: anywhere;
  }

  .email-row .btn {
    justify-content: center;
  }

  .email-row .copy-status {
    grid-column: 1 / -1;
  }

  .links {
    display: grid;
    padding: 0;
    margin: 0;
    list-style: none;
    border-top: 1px solid var(--inverse-divider);
  }

  .links a {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-block: var(--space-3);
    border-bottom: 1px solid var(--inverse-divider);
    text-decoration: none;
    font-weight: 500;
  }

  .links a .ico-go {
    color: var(--ink-400);
    transition:
      transform var(--duration-base) var(--ease-out),
      color var(--duration-base) var(--ease-out);
  }

  .links a:hover .ico-go {
    color: var(--text-accent-on-inverse);
  }


  /* Copy email: the label rolls up to "Copied!" and the check draws itself; no extra text below */
  .copy-btn {
    display: inline-grid;
    place-items: center;
    overflow: hidden;
  }

  .copy-face {
    grid-area: 1 / 1;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    transition:
      transform var(--duration-base) var(--ease-out),
      opacity var(--duration-base) var(--ease-out);
  }

  .copy-face.is-done {
    transform: translateY(100%);
    opacity: 0;
  }

  .copy-btn.is-copied .copy-face.is-idle {
    transform: translateY(-100%);
    opacity: 0;
  }

  .copy-btn.is-copied .copy-face.is-done {
    transform: none;
    opacity: 1;
  }

  .copy-check path {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
  }

  .copy-btn.is-copied .copy-check path {
    stroke-dashoffset: 0;
    transition: stroke-dashoffset var(--duration-slow) var(--ease-out) var(--duration-fast);
  }

  @media (prefers-reduced-motion: reduce) {
    .copy-face,
    .copy-btn.is-copied .copy-check path {
      transition: none;
    }
  }

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

  .copy-status {
    font: var(--type-label);
    color: var(--text-accent-on-inverse);
  }



  footer {
    color: var(--text-tertiary);
    font: var(--type-caption);
  }

  /* Footer reads left to right: brand, then each link group, sized to content */
  .footer-top {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: start;
    gap: var(--space-8) var(--space-24);
    padding-block: var(--space-8) var(--space-16);
    border-top: 1px solid var(--border-subtle);
  }

  .footer-brand {
    display: grid;
    gap: var(--space-2);
    align-content: start;
  }

  .footer-brand .brand {
    font-size: 1.125rem;
    justify-self: start;
  }

  /* Two link rows; the labels share one column so the rows line up */
  .footer-cols {
    display: grid;
    grid-template-columns: auto auto;
    gap: var(--space-3) var(--space-8);
  }

  .footer-col {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: baseline;
  }

  .footer-col h2 {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
  }

  .footer-col ul {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-6);
    padding: 0;
    margin: 0;
    list-style: none;
  }

  .footer-col a {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--duration-base) var(--ease-out);
  }

  .footer-col a:hover {
    color: var(--text-primary);
  }

  .footer-col a .ico-go {
    color: var(--text-tertiary);
  }

  .footer-bottom {
    padding-block: var(--space-6) var(--space-8);
    border-top: 1px solid var(--border-subtle);
  }

  /* Floating back-to-top: appears once the hero has scrolled away */
  .to-top {
    position: fixed;
    right: calc(var(--fab-offset) + env(safe-area-inset-right, 0px));
    bottom: calc(var(--fab-offset) + env(safe-area-inset-bottom, 0px));
    z-index: var(--z-overlay);
    display: grid;
    place-items: center;
    width: var(--fab-size);
    height: var(--fab-size);
    border-radius: var(--radius-full);
    border: 1px solid var(--action-secondary-border);
    background: var(--action-secondary-bg);
    color: var(--text-primary);
    box-shadow: var(--elevation-1);
    text-decoration: none;
    opacity: 0;
    visibility: hidden;
    transform: translateY(var(--space-2));
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out),
      visibility 0s linear var(--duration-base),
      border-color var(--duration-fast) var(--ease-out);
  }

  .to-top.is-on {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out),
      border-color var(--duration-fast) var(--ease-out);
  }

  .to-top:hover {
    border-color: var(--action-secondary-border-hover);
  }

  .to-top .ico {
    width: 1.125rem;
    height: 1.125rem;
  }

  .lb-open .to-top {
    display: none;
  }

  @media (prefers-reduced-motion: reduce) {
    .to-top,
    .to-top.is-on {
      transition: none;
    }
  }

  /* Icons */
  .ico {
    width: 1em;
    height: 1em;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .ico-brand {
    fill: currentColor;
    stroke: none;
  }

  .ico-go {
    width: 0.9em;
    height: 0.9em;
    transition: transform var(--duration-base) var(--ease-out);
  }

  /* Download icon: same size as the outbound arrow, nudges down instead */
  .ico-dl {
    width: 0.9em;
    height: 0.9em;
    transition: transform var(--duration-base) var(--ease-out);
  }

  a:hover .ico-dl,
  a:focus-visible .ico-dl {
    transform: translateY(var(--arrow-nudge));
  }

  .links a .ico-dl {
    color: var(--ink-400);
  }

  .links a:hover .ico-dl {
    color: var(--text-accent-on-inverse);
  }

  .footer-col a .ico-dl {
    color: var(--text-tertiary);
  }

  .lk-meta {
    font: var(--type-label);
    color: var(--ink-400);
  }

  /* Every outbound arrow nudges the same way on hover */
  a:hover .ico-go,
  a:focus-visible .ico-go {
    transform: translate(var(--arrow-nudge), calc(-1 * var(--arrow-nudge)));
  }

  @media (prefers-reduced-motion: reduce) {
    .ico-go,
    .ico-dl {
      transition: none;
    }
  }

  .btn .ico {
    width: 1.125rem;
    height: 1.125rem;
  }

  .lb-btn .ico {
    width: 1.25rem;
    height: 1.25rem;
  }

  .proj-links .ext {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
  }

  .proj-links .ext .ico-brand {
    width: 0.9rem;
    height: 0.9rem;
    margin-right: var(--space-1);
  }

  .email {
    gap: var(--space-3);
  }

  .email .ico {
    width: 1.125rem;
    height: 1.125rem;
    color: var(--ink-400);
  }

  .lk {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
  }

  .lk .ico {
    width: 1.125rem;
    height: 1.125rem;
    color: var(--ink-400);
  }

  /* Section eyebrow + About facts */
  .eyebrow {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-accent);
  }

  .eyebrow-inverse {
    color: var(--text-accent-on-inverse);
  }

  .chip {
    list-style: none;
  }

  .about-facts {
    display: grid;
    gap: var(--space-4);
  }

  .fact-row {
    display: grid;
    gap: var(--space-2);
  }

  .fact-label {
    color: var(--text-tertiary);
  }

  .about-facts .chip {
    padding-inline: var(--space-2) var(--space-3);
  }

  .stack-ico {
    width: var(--stack-icon);
    height: var(--stack-icon);
    flex: none;
    object-fit: contain;
  }

  .stack-ico.is-wide {
    width: var(--stack-icon-wide);
  }

  a.chip {
    height: auto;
    min-height: var(--tech-height);
    padding-block: var(--space-1);
    text-decoration: none;
    color: var(--text-secondary);
    transition:
      border-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out);
  }

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

  /* Same arrow as every other outbound link: stroked, never filled */
  .chip .ico-go {
    width: 0.9em;
    height: 0.9em;
    fill: none;
    stroke: currentColor;
    color: var(--text-tertiary);
  }

  a.chip:hover .ico-go {
    color: var(--text-primary);
  }

  .cert-badge {
    width: var(--cert-badge);
    height: var(--cert-badge);
    flex: none;
    margin-block: calc(-1 * var(--space-1));
  }

  /* Responsive: 1100 small laptop, 900 tablet, 640 phone */
  @media (max-width: 1100px) {
    .email-row {
      grid-template-columns: minmax(0, 1fr);
    }
  }

  @media (max-width: 900px) {
    .hero .wrap {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-8);
    }

    .steps {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-8);
      padding-left: calc(var(--step-dot) + var(--space-4));
    }

    .steps::before {
      left: calc(var(--step-dot) / 2);
      right: auto;
      top: var(--space-4);
      bottom: var(--space-4);
      width: 1px;
      height: auto;
      transform-origin: center top;
    }

    .steps::after {
      display: none;
    }

    .steps.will-draw::before {
      transform: scaleY(0);
    }

    .steps.is-drawn::before {
      transform: scaleY(1);
    }

    .step-dot {
      position: absolute;
      left: calc(-1 * (var(--step-dot) + var(--space-4)));
      top: calc(-1 * var(--space-2));
      margin: 0;
    }

    .contact-card {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-8);
      padding: var(--space-8);
    }
  }

  @media (max-width: 640px) {
    :root {
      --gutter: 16px;
      --card-padding: var(--space-6);
    }

    .nav a:not(.btn) {
      display: none;
    }

    .hero {
      padding-block: var(--space-8) var(--space-16);
    }

    .section {
      padding-block: var(--space-16);
    }

    .about-main {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-6);
    }

    .avatar {
      grid-template-columns: var(--avatar-w-sm) minmax(0, 1fr);
      align-items: end;
      gap: var(--space-4);
    }

    .contact-card {
      padding: var(--card-padding);
    }

    .email-row {
      grid-template-columns: minmax(0, 1fr);
    }

    .cert-chip {
      border-radius: var(--radius-sm);
    }

    .footer-top {
      flex-direction: column;
      gap: var(--space-8);
    }

    .footer-cols {
      gap: var(--space-4) var(--space-6);
    }

    .to-top {
      right: calc(var(--fab-offset-sm) + env(safe-area-inset-right, 0px));
      bottom: calc(var(--fab-offset-sm) + env(safe-area-inset-bottom, 0px));
    }
  }

/* ========== Writing: lists, index page and articles ========== */
  /* Text-first, reuses page tokens */
  :root {
    --note-date-w: 7.5rem;
    --note-row-pad: var(--space-6);
    --measure-prose: 68ch;
    --toc-w: 14rem;
  }

  .note-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--border-subtle);
  }

  .note-row {
    position: relative;
    display: grid;
    grid-template-columns: var(--note-date-w) minmax(0, 1fr) auto auto auto;
    align-items: baseline;
    gap: var(--space-6);
    padding-block: var(--note-row-pad);
  }


  /* Row hover: same move as the Selected work rows. The row lifts into a card;
     separators are inset pseudo-lines so they can hide under the card */
  .note-list {
    position: relative;
    border-top: 0;
  }

  .note-row {
    --row-pad: var(--proj-pad);
    isolation: isolate;
    padding-inline: var(--row-pad);
    margin-inline: calc(-1 * var(--row-pad));
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--surface-page);
    transition:
      border-color var(--duration-base) var(--ease-out),
      translate var(--duration-base) var(--ease-out);
  }

  /* Shadow pre-painted on a layer that only fades in */
  .note-row::after {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: -2;
    border-radius: inherit;
    box-shadow: var(--elevation-2);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out);
  }

  .note-row::before,
  .note-list::after {
    content: "";
    position: absolute;
    left: var(--row-pad, var(--proj-pad));
    right: var(--row-pad, var(--proj-pad));
    height: 1px;
    background: var(--border-subtle);
    transition: opacity var(--duration-fast) var(--ease-out);
    pointer-events: none;
  }

  .note-row::before {
    top: -1px;
  }

  .note-list::after {
    left: 0;
    right: 0;
    bottom: 0;
  }

  @media (hover: hover) {
    .note-row:hover {
      z-index: 1;
      border-color: var(--border-accent);
      translate: 0 var(--proj-lift);
    }

    .note-row:hover::after {
      opacity: 1;
    }

    .note-row:hover::before,
    .note-row:hover + .note-row::before,
    .note-list:has(.note-row:last-child:hover)::after {
      opacity: 0;
    }

    .note-row:hover .note-summary {
      color: var(--text-primary);
    }
  }


  /* Hover motion inside the card: title underline draws in, the meta steps aside and a "Read" pill slides in */
  .note-title a {
    background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
    transition: background-size var(--duration-slow) var(--ease-out);
  }

  .note-tag,
  .note-time,
  .note-row > .ico-go {
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out),
      color var(--duration-base) var(--ease-out);
  }

  .note-cta {
    position: absolute;
    right: var(--row-pad);
    top: calc(var(--note-row-pad) - var(--space-1));
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--tech-height);
    padding-inline: var(--space-3);
    border-radius: var(--radius-full);
    background: var(--action-accent-bg);
    color: var(--action-accent-fg);
    font: var(--type-label);
    letter-spacing: 0.02em;
    white-space: nowrap;
    opacity: 0;
    transform: translateX(var(--space-4));
    pointer-events: none;
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-slow) var(--ease-out);
  }

  .note-cta .ico {
    width: 0.875rem;
    height: 0.875rem;
  }

  @media (hover: hover) {
    .note-row:hover .note-title a {
      background-size: 100% 1px;
    }

    .note-row:hover .note-d-lg.note-tag,
    .note-row:hover .note-d-lg.note-time,
    .note-row:hover > .ico-go {
      opacity: 0;
      transform: translateX(calc(-1 * var(--space-4)));
    }

    .note-row:hover .note-cta {
      opacity: 1;
      transform: none;
      transition-delay: 60ms;
    }
  }

  @media (max-width: 640px) {
    .note-cta {
      display: none;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .note-title a,
    .note-cta,
    .note-tag,
    .note-time,
    .note-row > .ico-go {
      transition: none;
    }

    .note-cta {
      transform: none;
    }
  }


  .note-summary {
    transition: color var(--duration-base) var(--ease-out);
  }

  @media (max-width: 900px) {
    .note-row {
      --row-pad: var(--proj-pad-sm);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .note-row {
      transition: none;
    }
  }

  .note-date,
  .note-tag,
  .note-time {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
    white-space: nowrap;
  }

  .note-title {
    font: var(--type-heading-3);
    letter-spacing: var(--tracking-display);
    text-wrap: pretty;
    transition: color var(--duration-base) var(--ease-out);
  }

  .note-title a {
    color: inherit;
    text-decoration: none;
  }

  /* Stretched link: the whole row is the hit area */
  .note-title a::after {
    content: "";
    position: absolute;
    inset: 0;
  }

  .note-row .ico-go {
    color: var(--text-tertiary);
    align-self: center;
  }

  .note-summary {
    grid-column: 2 / -1;
    margin-top: calc(-1 * var(--space-4));
    color: var(--text-secondary);
    font: var(--type-caption);
    max-width: 64ch;
  }

  @media (hover: hover) {
    .note-row:hover .note-title {
      color: var(--text-accent);
    }

    .note-row:hover .ico-go {
      color: var(--text-accent);
    }
  }

  .note-row:has(a:focus-visible) {
    border-color: var(--border-accent);
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: var(--focus-ring-width);
  }

  .note-row a:focus-visible {
    outline: none;
  }

  .notes-more {
    margin-top: var(--space-8);
  }

  .notes-more a {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 600;
    color: var(--text-accent);
    text-decoration: none;
  }

  .notes-more a:hover {
    text-decoration: underline;
    text-underline-offset: var(--space-1);
  }

  /* Notes index page */
  .page-head {
    padding-block: var(--space-16) var(--space-8);
  }

  .page-head h1 {
    font: var(--type-heading-1);
    letter-spacing: var(--tracking-display);
  }

  .page-head p {
    margin-top: var(--space-3);
    color: var(--text-secondary);
    font: var(--type-body-lg);
    max-width: 60ch;
  }

  .note-filter {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-12);
  }

  .note-filter button {
    height: var(--tech-height);
    padding-inline: var(--space-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-full);
    background: var(--surface-page);
    color: var(--text-secondary);
    font: var(--type-label);
    cursor: pointer;
    transition:
      border-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out),
      background var(--duration-fast) var(--ease-out);
  }

  .note-filter button:hover {
    border-color: var(--action-secondary-border-hover);
    color: var(--text-primary);
  }

  .note-filter button[aria-pressed="true"] {
    background: var(--action-primary-bg);
    border-color: transparent;
    color: var(--action-primary-fg);
  }

  .note-year {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
    margin: var(--space-12) 0 var(--space-3);
  }

  .note-year:first-of-type {
    margin-top: 0;
  }

  .note-row[hidden] {
    display: none;
  }

  /* Article page */
  .article {
    padding-block: var(--space-12) var(--space-24);
  }

  .article-grid {
    display: grid;
    grid-template-columns: minmax(0, var(--measure-prose)) var(--toc-w);
    justify-content: space-between;
    gap: var(--space-16);
    align-items: start;
  }

  .back-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-secondary);
    text-decoration: none;
    font: var(--type-caption);
    font-weight: 500;
    margin-bottom: var(--space-8);
  }

  .back-link:hover {
    color: var(--text-primary);
  }

  .article-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
  }

  .article-meta .tag {
    color: var(--text-accent);
  }

  .article h1 {
    margin-top: var(--space-4);
    font: var(--type-heading-1);
    letter-spacing: var(--tracking-display);
  }

  .article-lead {
    margin-top: var(--space-6);
    font: var(--type-body-lg);
    font-size: 1.25rem;
    color: var(--text-secondary);
  }

  .prose {
    margin-top: var(--space-12);
    font: var(--type-body-lg);
    color: var(--text-secondary);
  }

  .prose > * + * {
    margin-top: var(--space-6);
  }

  .prose h2 {
    margin-top: var(--space-16);
    font: var(--type-heading-2);
    color: var(--text-primary);
    scroll-margin-top: var(--section-offset);
  }

  .prose strong {
    color: var(--text-primary);
    font-weight: 600;
  }

  .prose a {
    color: var(--text-accent);
    text-underline-offset: var(--space-1);
  }

  .prose ul {
    padding-left: var(--space-6);
  }

  .prose li + li {
    margin-top: var(--space-2);
  }

  .prose :not(pre) > code {
    font: 500 0.88em/1 var(--font-mono);
    color: var(--text-primary);
    background: var(--surface-sunken);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    padding: 1px var(--space-1);
    white-space: nowrap;
  }

  .prose pre {
    margin-inline: 0;
    padding: var(--space-6);
    border-radius: var(--radius-md);
    background: var(--code-bg);
    color: var(--ink-100);
    font: 400 0.875rem/1.7 var(--font-mono);
    overflow-x: auto;
  }

  .prose pre .k { color: var(--code-attr); }
  .prose pre .s { color: var(--code-string); }
  .prose pre .c { color: var(--ink-400); }

  .callout {
    padding: var(--space-6);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
    border: 1px solid var(--border-subtle);
    font: var(--type-body);
    color: var(--text-secondary);
  }

  .callout b {
    display: block;
    margin-bottom: var(--space-1);
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-primary);
  }

  .prose figure {
    margin-inline: 0;
  }

  .prose figure .browser {
    margin-bottom: 0;
    border-bottom: 1px solid var(--border-subtle);
    border-radius: var(--browser-radius);
  }

  .prose figcaption {
    margin-top: var(--space-3);
    font: var(--type-caption);
    color: var(--text-tertiary);
  }

  .toc {
    position: sticky;
    top: calc(var(--section-offset) + var(--space-8));
    display: grid;
    gap: var(--space-3);
    padding-top: var(--space-16);
  }

  .toc h2 {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
  }

  .toc ol {
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--space-4);
    display: grid;
    gap: var(--space-2);
    border-left: 1px solid var(--border-subtle);
  }

  .toc a {
    color: var(--text-secondary);
    text-decoration: none;
    font: var(--type-caption);
    transition: color var(--duration-fast) var(--ease-out);
  }

  .toc a:hover,
  .toc a[aria-current="true"] {
    color: var(--text-primary);
  }

  .toc a[aria-current="true"] {
    font-weight: 600;
  }

  .article-end {
    margin-top: var(--space-16);
    padding-top: var(--space-8);
    border-top: 1px solid var(--border-subtle);
    display: grid;
    gap: var(--space-8);
  }

  .pager {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
  }

  .pager a {
    display: grid;
    gap: var(--space-1);
    padding: var(--space-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    text-decoration: none;
    transition: border-color var(--duration-fast) var(--ease-out);
  }

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

  .pager .next {
    text-align: right;
  }

  .pager span {
    font: var(--type-label);
    letter-spacing: 0.02em;
    color: var(--text-tertiary);
  }

  .pager strong {
    font: var(--type-heading-3);
    font-size: 1rem;
    color: var(--text-primary);
  }

  .article-cta {
    color: var(--text-secondary);
  }

  .article-cta a {
    color: var(--text-accent);
    font-weight: 600;
    text-decoration: none;
  }

  .article-cta a:hover {
    text-decoration: underline;
    text-underline-offset: var(--space-1);
  }

  .page-head .preview-note,
  .preview-note {
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    background: var(--status-warning-bg);
    color: var(--status-warning-fg);
    font: var(--type-caption);
    margin-bottom: var(--space-8);
  }

  @media (max-width: 1100px) {
    .article-grid {
      grid-template-columns: minmax(0, var(--measure-prose));
    }

    .toc {
      display: none;
    }
  }

  @media (max-width: 640px) {
    .note-row {
      grid-template-columns: minmax(0, 1fr) auto;
      gap: var(--space-2) var(--space-4);
    }

    .note-title {
      grid-column: 1;
      grid-row: 1;
    }

    .note-row .ico-go {
      grid-column: 2;
      grid-row: 1;
    }

    .note-meta-sm {
      grid-column: 1 / -1;
      display: flex;
      gap: var(--space-3);
    }

    .note-summary {
      grid-column: 1 / -1;
      margin-top: 0;
    }

    .pager {
      grid-template-columns: minmax(0, 1fr);
    }
  }

  @media (min-width: 641px) {
    .note-meta-sm {
      display: contents;
    }
  }

/* ========== Writing: meta line on small screens ========== */
  .note-row .note-meta-sm { display: none; }
  @media (max-width: 640px) {
    .note-d-lg { display: none; }
    .note-row .note-meta-sm { display: flex; grid-column: 1 / -1; gap: var(--space-3); }
  }

/* ========== Writing: motion ========== */
  /* ===== Writing motion: each effect orients the reader; all off with reduced motion ===== */
  :root {
    --progress-h: 2px;
    --row-stagger: 70ms;
    --vt-duration: var(--duration-slow);
  }

  /* 1. Rows rise in on scroll (same move as the project rows; content stays visible at rest) */
  @media (prefers-reduced-motion: no-preference) {
    .js-wrise .note-row {
      transform: translateY(var(--proj-rise));
      transition: transform var(--duration-slower) var(--ease-out);
      transition-delay: calc(var(--i, 0) * var(--row-stagger));
    }

    .js-wrise .note-row.is-in {
      transform: none;
    }
  }

  /* 2. Cross-page title morph: list title becomes the article heading */
  @view-transition {
    navigation: auto;
  }

  .site-header {
    view-transition-name: site-header;
  }

  ::view-transition-group(*) {
    animation-duration: var(--vt-duration);
    animation-timing-function: var(--ease-out);
  }

  @media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
      animation: none !important;
    }
  }

  /* 3. Reading progress under the header */
  .read-progress {
    position: fixed;
    left: 0;
    right: 0;
    top: var(--header-height);
    height: var(--progress-h);
    z-index: var(--z-sticky);
    background: var(--text-accent);
    transform-origin: left center;
    transform: scaleX(var(--p, 0));
    pointer-events: none;
  }

  /* 4. TOC: a bar slides to the section being read */
  .toc-track {
    position: relative;
  }

  .toc-bar {
    position: absolute;
    left: -1px;
    top: 0;
    width: var(--progress-h);
    height: 0;
    border-radius: var(--radius-full);
    background: var(--text-accent);
    transform: translateY(var(--bar-y, 0));
    opacity: 0;
    transition:
      transform var(--duration-base) var(--ease-out),
      height var(--duration-base) var(--ease-out),
      opacity var(--duration-fast) var(--ease-out);
  }

  .toc-bar.is-on {
    opacity: 1;
  }

  @media (prefers-reduced-motion: reduce) {
    .toc-bar {
      transition: none;
    }
  }

  /* 6. Copy button on code blocks */
  .code-block {
    position: relative;
  }

  .code-copy {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: var(--tech-height);
    padding-inline: var(--space-2);
    border: 1px solid var(--inverse-border);
    border-radius: var(--radius-xs);
    background: var(--inverse-fill);
    color: var(--ink-400);
    font: var(--type-label);
    cursor: pointer;
    transition:
      color var(--duration-fast) var(--ease-out),
      border-color var(--duration-fast) var(--ease-out);
  }

  .code-copy:hover {
    color: var(--text-inverse);
    border-color: var(--ink-400);
  }

  .code-copy .ico {
    width: 0.875rem;
    height: 0.875rem;
  }

  .code-copy:focus-visible {
    outline: var(--focus-ring-width) solid var(--cobalt-400);
    outline-offset: var(--focus-ring-width);
  }

/* ========== Writing: one scroll box ========== */
/* All posts as full rows; about three and a half fit, the rest scroll inside with soft fades at the edges.
   The scrollbar is hidden so rows stay aligned with the rest of the page; wheel, touch and keyboard still scroll. */
:root {
  --note-scroll-max: 32rem; /* fallback; JS sets it to exactly five rows */
  --note-fade: var(--space-12);
}

.note-scroll {
  position: relative;
  max-height: var(--note-scroll-max);
  overflow-y: auto;
  transition: max-height var(--duration-slower) var(--ease-out);
  overscroll-behavior: contain;
  scrollbar-width: none;
  /* room for the hover lift and shadow inside the scroll box: rows reach --proj-pad past the content edge,
     so the sides need that plus the shadow's spread */
  --note-pad-top: var(--space-6);
  --note-pad-x: calc(var(--proj-pad) + var(--space-8));
  --note-pad-bottom: var(--space-12);
  padding: var(--note-pad-top) var(--note-pad-x) var(--note-pad-bottom);
  margin: calc(-1 * var(--note-pad-top)) calc(-1 * var(--note-pad-x)) calc(-1 * var(--note-pad-bottom));
  --fade-top: 0px;
  --fade-bottom: 0px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent 100%);
}

.note-scroll::-webkit-scrollbar {
  display: none;
}

.note-scroll.has-above {
  --fade-top: calc(var(--note-pad-top) + var(--note-fade));
}

.note-scroll.has-below {
  --fade-bottom: calc(var(--note-pad-bottom) + var(--note-fade));
}

/* A lighter shadow that fits inside the box's padding instead of being cut at its edges */
.note-scroll .note-row::after {
  box-shadow: var(--elevation-1);
}

.note-scroll:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: calc(-1 * var(--focus-ring-width));
  border-radius: var(--radius-md);
}

/* Opened: not a scroll container any more, so the wheel scrolls the page as usual */
.note-scroll.is-open {
  max-height: var(--note-scroll-full, 200rem);
  overflow-y: hidden;
  overflow-y: clip;
}

/* Text button: accent link style, no border */
.notes-toggle {
  /* sits above the scroll box's bottom padding, which overlaps it to give the hover shadow room */
  position: relative;
  z-index: 1;
  margin-top: var(--space-6);
}

.link-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--hit-target);
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-accent);
  font: var(--type-body);
  font-weight: 600;
  cursor: pointer;
}

.link-btn:hover span {
  text-decoration: underline;
  text-underline-offset: var(--space-1);
}

.link-btn .ico {
  transition: transform var(--duration-base) var(--ease-out);
}

.link-btn[aria-expanded="true"] .ico {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .note-scroll,
  .link-btn .ico {
    transition: none;
  }
}

/* ========== Writing: article figures (state sketches, small diagrams) ========== */
.state-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.state-grid li {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.state-grid svg {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
}

.state-grid span {
  font: var(--type-label);
  letter-spacing: 0.02em;
  color: var(--text-tertiary);
  text-align: center;
}

.state-homes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.state-homes li {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  font: var(--type-caption);
  color: var(--text-secondary);
}

.state-homes b {
  font: var(--type-label);
  letter-spacing: 0.02em;
  color: var(--text-accent);
}

.state-homes strong {
  color: var(--text-primary);
  font-weight: 600;
}

@media (max-width: 640px) {
  .state-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .state-homes {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Figure grids are not prose lists: no stacked list spacing */
.prose .state-grid li,
.prose .state-homes li {
  margin-top: 0;
}

/* A lone "Newer" link keeps its right-hand place */
.pager .next:only-child {
  grid-column: 2;
}

@media (max-width: 640px) {
  .pager .next:only-child {
    grid-column: 1;
  }
}

/* ========== Writing: tables and timeline figures inside articles ========== */
.prose .table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font: var(--type-caption);
}

.prose th,
.prose td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--border-subtle);
}

.prose th {
  font: var(--type-label);
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  background: var(--surface-sunken);
}

.prose tr:last-child td {
  border-bottom: 0;
}

.prose td:first-child {
  color: var(--text-primary);
  font-weight: 600;
  white-space: nowrap;
}

.prose figure > svg.diagram {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

/* ---------- Writing: subheadings, ordered lists, badge figure ---------- */
.prose h3 {
  margin-top: var(--space-12);
  font: var(--type-heading-3);
  color: var(--text-primary);
}

.prose h2 + h3 {
  margin-top: var(--space-6);
}

.prose ol {
  padding-left: var(--space-6);
}

.prose ol li::marker {
  color: var(--text-tertiary);
}

.prose .badge-figure {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.prose .badge-figure img {
  flex: none;
  width: var(--space-16);
  height: var(--space-16);
}

.prose .badge-figure figcaption {
  margin: 0;
  font: var(--type-caption);
  color: var(--text-secondary);
}

.prose .badge-figure strong {
  display: block;
}

.about-text a {
  color: var(--text-accent);
  text-underline-offset: var(--space-1);
}
