/*
  Charcoal & Spark — near-white paper, rose cameo, soft graph craft
  Default palette 5; Frame A structure without teal-clone scaffolding
*/

/* Self-hosted latin WOFF2 — web.dev: WOFF2-only, swap/optional, subset */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/bricolage-grotesque-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/bricolage-grotesque-latin-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/bricolage-grotesque-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: optional;
  src: url("/fonts/jetbrains-mono-latin-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2190-2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light;
  /* Default: Palette 5 — charcoal mono + spark */
  --bg: #ffffff;
  --fg: #111111;
  --muted: #666666;
  /* ≥4.5:1 on white — kept darker than the #767 AA floor for headroom */
  --muted-soft: #6b6b6b;
  --accent: #111111;
  --accent-soft: #111111;
  --cameo: #e11d48;
  --ruling: rgba(17, 17, 17, 0.12);
  --hairline: rgba(17, 17, 17, 0.12);
  --graph-dot: radial-gradient(
    circle at center,
    var(--ruling) 0.85px,
    transparent 1.05px
  );
  /* Slightly off-square — notebook ruling isn’t laser-perfect */
  --graph-size: 16px 17px;
  --font: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --page: 38rem;
  /* Motion — Emil: color hover = ease + short; press/enter = strong ease-out */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease: ease; /* color / opacity hover — not expo */
  --duration-press: 100ms; /* button :active */
  --duration-hover: 100ms; /* link/button color (high-freq) */
  --duration-theme: 250ms; /* legacy soft wash (fallback / reduced surfaces) */
  --duration-theme-icon: 420ms; /* sun/moon rise·set — occasional, allowed to breathe */
  --duration-theme-wipe: 400ms; /* light ↔ dark page wipe L→R */
  --press-btn: scale(0.97);
  --link-underline-thickness: 1.5px;
  --link-underline-offset: 0.2em;

  /*
    Type scale — major-third (~1.25) from body 1rem.
    Fixed: label/meta 12 → sm 14 → ui/body 16 → title 20
    Fluid clamps land on the same ramp (20/24/32/48).
  */
  --text-label: 0.75rem; /* 12 — mono uppercase system labels */
  --text-meta: 0.75rem; /* 12 — dates, indexes, colophon (same step as label) */
  --text-sm: 0.875rem; /* 14 — errors, code */
  --text-ui: 1rem; /* 16 — nav, TY, back, status */
  --text-body: 1rem; /* 16 — lede, fields, send, secondary prose */
  --text-title: 1.25rem; /* 20 — section / work / note titles */
  --text-headline: clamp(1.25rem, 2vw, 1.5rem); /* 20 → 24 — name */
  --text-page-title: clamp(1.5rem, 3.5vw, 2rem); /* 24 → 32 — Notes h1 */
  --text-display: clamp(2rem, 5.5vw, 3rem); /* 32 → 48 — thesis */
  --text-display-sm: clamp(1.5rem, 6.5vw, 2.25rem); /* 24 → 36 — thesis ≤720px */

  --leading-display: 1.1;
  --leading-headline: 1.25;
  --leading-title: 1.3;
  --leading-body: 1.65;
  --leading-ui: 1.5;
  --leading-label: 1.4;

  --tracking-display: -0.03em; /* floor ≥ -0.04em */
  --tracking-headline: -0.02em;
  --tracking-title: -0.015em;
  --tracking-label: 0.12em;
  --tracking-meta: 0.04em;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 700; /* no 600 file — map to bold */
  --weight-bold: 700;

  /* Spacing — 4px base, ~1.5× growth. No half-steps (6/20/40). */
  --space-2xs: 0.25rem; /* 4 */
  --space-xs: 0.5rem; /* 8 */
  --space-sm: 0.75rem; /* 12 */
  --space-md: 1rem; /* 16 */
  --space-lg: 1.5rem; /* 24 */
  --space-xl: 2rem; /* 32 */
  --space-2xl: 3rem; /* 48 */
  --space-3xl: 4rem; /* 64 */

  /*
    One content column — chrome + page share this measure so left edges lock.
    --gutter flips at the mobile breakpoint (see below).
  */
  --gutter: var(--space-lg); /* 24 */
  --column: min(var(--page), calc(100% - (2 * var(--gutter))));

  /* Fluid section rhythm — clamps land on ramp endpoints only */
  --space-section: clamp(var(--space-xl), 6vw, var(--space-2xl)); /* 32 → 48 */
  --space-section-lg: clamp(var(--space-2xl), 8vw, var(--space-3xl)); /* 48 → 64 */
  --space-page-y: clamp(var(--space-xl), 6vw, var(--space-3xl)); /* 32 → 64 */
  --space-page-y-end: clamp(var(--space-2xl), 7vw, var(--space-3xl)); /* 48 → 64 */

  --touch: 2.75rem; /* 44px a11y target */
  --touch-compact: 2.25rem; /* short landscape */
  --measure: 52ch;
  --measure-narrow: 40ch;

  /* Header chrome height offsets (not spacing rhythm — measured stack) */
  --chrome-offset: 7.25rem; /* measured fixed chrome stack (~116px) */
  --chrome-offset-scroll: 7.25rem; /* keep in sync with --chrome-offset — one scroll inset */
  --chrome-offset-mobile: 7.25rem; /* same measured stack on narrow; was overshooting by 8px */
  --chrome-offset-landscape: 5.5rem;
}

/* Palette 1 — Frame A teal */
:root[data-palette="1"] {
  --bg: #f8f8f8;
  --fg: #1a1a1a;
  --muted: #555555;
  --muted-soft: #6b6b6b;
  --accent: #45a28e;
  --cameo: #c9892a;
  --ruling: rgba(26, 26, 26, 0.09);
  --hairline: rgba(26, 26, 26, 0.12);
}

/* Palette 2 — Blueprint ink */
:root[data-palette="2"] {
  --bg: #fafafa;
  --fg: #141820;
  --muted: #5c6570;
  --muted-soft: #5c6570;
  --accent: #2f6fed;
  --cameo: #c45c26;
  --ruling: rgba(20, 24, 32, 0.09);
  --hairline: rgba(20, 24, 32, 0.12);
}

/* Palette 3 — Lamp brass (accent only) */
:root[data-palette="3"] {
  --bg: #f7f7f5;
  --fg: #1c1917;
  --muted: #57534e;
  --muted-soft: #57534e;
  --accent: #a16207;
  --cameo: #0f766e;
  --ruling: rgba(28, 25, 23, 0.09);
  --hairline: rgba(28, 25, 23, 0.12);
}

/* Palette 4 — Forest signal */
:root[data-palette="4"] {
  --bg: #f8f8f8;
  --fg: #1a1a1a;
  --muted: #4b5563;
  --muted-soft: #4b5563;
  --accent: #3f6f5a;
  --cameo: #b45309;
  --ruling: rgba(26, 26, 26, 0.09);
  --hairline: rgba(26, 26, 26, 0.12);
}

/* Palette 5 — Charcoal mono + spark (default) */
:root[data-palette="5"] {
  --bg: #ffffff;
  --fg: #111111;
  --muted: #666666;
  --muted-soft: #6b6b6b;
  --accent: #111111;
  --cameo: #e11d48;
  --ruling: rgba(17, 17, 17, 0.12);
  --hairline: rgba(17, 17, 17, 0.12);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0c0c0c;
  --fg: #f2f2f2;
  --muted: #a0a0a0;
  --muted-soft: #8a8a8a;
  --accent: #5ebfaa;
  --accent-soft: #5ebfaa;
  --cameo: #e0a84a;
  --ruling: rgba(242, 242, 242, 0.1);
  --hairline: rgba(242, 242, 242, 0.14);
}

:root[data-theme="dark"][data-palette="2"] {
  --accent: #6b9cff;
  --cameo: #e07a45;
}

:root[data-theme="dark"][data-palette="3"] {
  --accent: #e0a84a;
  --cameo: #2dd4bf;
}

:root[data-theme="dark"][data-palette="4"] {
  --accent: #6f9f86;
  --cameo: #f59e0b;
}

:root[data-theme="dark"][data-palette="5"] {
  --bg: #0c0c0c;
  --fg: #f2f2f2;
  --muted: #a0a0a0;
  --muted-soft: #8a8a8a;
  --accent: #f2f2f2;
  --accent-soft: #f2f2f2;
  --cameo: #fb7185;
  --ruling: rgba(242, 242, 242, 0.1);
  --hairline: rgba(242, 242, 242, 0.14);
}

:root[data-palette="5"] .submit:hover:not(:disabled) {
  color: #fff;
  background: var(--cameo);
}

:root[data-palette="5"] .site-initials:focus-visible,
:root[data-palette="5"] .theme-icon:focus-visible {
  color: var(--cameo);
}

@media (hover: hover) and (pointer: fine) {
  :root[data-palette="5"] .header-nav a:hover {
    color: var(--cameo);
    text-decoration-color: var(--cameo);
  }

  :root[data-palette="5"] .site-initials:hover,
  :root[data-palette="5"] .theme-icon:hover {
    color: var(--cameo);
  }

  :root[data-palette="5"] .work-list a:hover .work-title,
  :root[data-palette="5"] .post-card a:hover .post-card-title,
  :root[data-palette="5"] .back-link:hover,
  :root[data-palette="5"] .empty-state a:hover {
    color: var(--cameo);
    text-decoration-color: var(--cameo);
  }
}

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

/* Firefox — same thin tokens on every scroll container */
* {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--fg) 28%, transparent) transparent;
}

html {
  scroll-behavior: smooth;
  /* Single scroll inset for hash targets / skip-link — matches fixed chrome */
  scroll-padding-top: calc(var(--chrome-offset) + env(safe-area-inset-top, 0px));
  /* Keep layout width stable when one route needs a scrollbar and another doesn’t */
  scrollbar-gutter: stable;
}

/*
  Cross-page hash landings (Notes → /#contact) must jump, not ease.
  Smooth scroll from y=0 makes the fixed chrome feel like it’s transitioning.
*/
html[data-scroll="instant"] {
  scroll-behavior: auto;
}

/*
  Theme toggle — L→R page wipe via View Transitions (CSS owns the motion).
  JS only calls document.startViewTransition(() => flip theme).
*/
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: none;
    z-index: 1;
  }

  ::view-transition-new(root) {
    animation: theme-page-wipe var(--duration-theme-wipe) var(--ease-out) both;
    z-index: 2;
  }
}

@keyframes theme-page-wipe {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

/* WebKit / Chromium / Safari — replace platform-native chrome */
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

*::-webkit-scrollbar-track {
  background: transparent;
}

*::-webkit-scrollbar-thumb {
  background-color: color-mix(in srgb, var(--fg) 28%, transparent);
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 0;
}

*::-webkit-scrollbar-thumb:hover {
  background-color: color-mix(in srgb, var(--fg) 45%, transparent);
}

*::-webkit-scrollbar-thumb:active {
  background-color: var(--cameo);
}

*::-webkit-scrollbar-corner {
  background: transparent;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  /* No soft bg wash — theme wipe owns the mode change; avoids stagger vs browser chrome */
}

/* Theme wash — ink/muted surfaces follow the mode change */
.name,
.thesis,
.lede,
.section-title,
.label,
.field-label,
.section-note,
.colophon,
.work-index,
.work-desc,
.contact-lede,
.form-status,
.field-error,
.post-card-desc,
.post-meta,
.empty-state,
.markdown-body p,
.markdown-body li,
.markdown-body h2,
.markdown-body h3,
.post-body p,
.post-body li,
.post-body h2,
.post-body h3 {
  transition: color var(--duration-theme) var(--ease-out);
}

::selection {
  background: color-mix(in srgb, var(--cameo) 32%, transparent);
  color: var(--fg);
}

/* Thin C — Making Software: soft graph dots, not warm wash */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 1;
  background-image: var(--graph-dot);
  background-size: var(--graph-size);
  background-position: 0 0;
}

/* Visually hidden until keyboard focus — never leave a peeking black sliver */
.skip-link {
  position: fixed;
  top: max(var(--space-sm), env(safe-area-inset-top, 0px));
  left: max(var(--space-sm), env(safe-area-inset-left, 0px));
  z-index: 50;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  background: var(--fg);
  color: var(--bg);
  font-weight: var(--weight-bold);
  text-decoration: none;
}

.skip-link:focus,
.skip-link:focus-visible {
  width: auto;
  height: auto;
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
  outline: none;
  box-shadow:
    0 0 0 2px var(--bg),
    0 0 0 4px var(--cameo);
}

.desk {
  position: relative;
  z-index: 1;
  padding-top: calc(var(--chrome-offset) + env(safe-area-inset-top, 0px));
  padding-right: env(safe-area-inset-right, 0px);
  padding-left: env(safe-area-inset-left, 0px);
}

.top-util {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  /* Block + shared --column — same centering math as .page (not padded flex) */
  display: block;
  width: 100%;
  margin: 0;
  padding-top: max(var(--space-sm), env(safe-area-inset-top, 0px));
  padding-right: env(safe-area-inset-right, 0px);
  padding-bottom: var(--space-sm);
  padding-left: env(safe-area-inset-left, 0px);
  box-sizing: border-box;
  /* Paper + same graph as body so chrome doesn’t break the craft tell */
  background-color: var(--bg);
  background-image: var(--graph-dot);
  background-size: var(--graph-size);
  background-position: 0 0;
  border-bottom: 1px solid var(--hairline);
  transition: border-color var(--duration-theme) var(--ease-out);
  /* Instant with theme tokens — wipe handles the visible transition */
}

.brand-block {
  display: grid;
  gap: var(--space-2xs);
  min-width: 0;
  width: var(--column);
  margin-inline: auto;
}

.brand-row {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2xs);
  min-width: 0;
  width: fit-content;
}

.site-initials {
  margin: 0;
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  width: fit-content;
  font-family: var(--font-mono);
  font-size: var(--text-ui);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg);
  text-decoration: none;
  /* High-freq chrome: color only — matches header nav */
  transition: color var(--duration-hover) var(--ease);
}

.site-initials:active {
  color: var(--cameo);
}

.site-initials:focus-visible {
  outline: none;
  color: var(--cameo);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.22em;
}

.header-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-md);
  min-width: 0;
}

.header-nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  padding-inline: 0;
  font-size: var(--text-ui);
  font-weight: var(--weight-medium);
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--link-underline-thickness);
  text-underline-offset: var(--link-underline-offset);
  transition:
    color var(--duration-hover) var(--ease),
    text-decoration-color var(--duration-hover) var(--ease);
}

/* Grow tap target without shifting the glyph off the column edge */
.header-nav a::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: calc(var(--space-2xs) * -1);
}

.header-nav a.is-strong,
.header-nav a[aria-current="page"] {
  color: var(--fg);
  font-weight: var(--weight-bold);
  text-decoration-color: transparent;
}

.header-nav a:active {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.header-nav a:focus-visible {
  outline: none;
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

/* Reserved for future logo — hidden until a real mark ships */
.logo-slot {
  display: none;
  flex-shrink: 0;
  width: var(--space-xl);
  height: var(--space-xl);
}

.theme-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--touch);
  height: var(--touch);
  margin: 0 0 0 calc(var(--space-xs) * -1);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  flex-shrink: 0;
  /* Clips icons at the button edge = horizon line for rise / set */
  overflow: hidden;
  transform: scale(1);
  transition:
    color var(--duration-hover) var(--ease),
    transform var(--duration-press) var(--ease-out);
}

/* Hover = color only; motion reserved for theme rise/set + press */
.theme-icon:active {
  color: var(--cameo);
  transform: var(--press-btn);
}

/* Cameo icon + short underline — color alone isn’t enough for focus */
.theme-icon:focus-visible {
  outline: none;
  color: var(--cameo);
}

.theme-icon:focus-visible::after {
  content: "";
  position: absolute;
  bottom: var(--space-xs);
  left: 50%;
  width: var(--space-md);
  height: 2px;
  transform: translateX(-50%);
  background: currentColor;
  pointer-events: none;
}

.theme-icon svg {
  position: absolute;
  width: 1.375rem;
  height: 1.375rem;
  display: block;
  transform-origin: 50% 50%;
  transition:
    opacity var(--duration-theme-icon) var(--ease-out),
    transform var(--duration-theme-icon) var(--ease-out),
    color var(--duration-hover) var(--ease);
}

/*
  Sun / moon as rise & set (read this once):

  Light mode  → moon is up (click invites night)
  Dark mode   → sun is up  (click invites day)

  On toggle, the visible icon SETS (drops past the horizon + tips + fades).
  The other RISES from below (tips upright + fades in). Bold travel so
  the metaphor is obvious — not a tiny nudge.
*/
.theme-icon .icon-moon {
  opacity: 1;
  transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
  color: inherit;
}

.theme-icon .icon-sun {
  opacity: 0;
  transform: translate3d(0, 120%, 0) rotate(-28deg) scale(0.7);
  pointer-events: none;
  color: inherit;
}

:root[data-theme="dark"] .theme-icon .icon-moon {
  opacity: 0;
  transform: translate3d(0, 120%, 0) rotate(28deg) scale(0.7);
  pointer-events: none;
}

:root[data-theme="dark"] .theme-icon .icon-sun {
  opacity: 1;
  transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
  pointer-events: auto;
}

/* Cameo only while swapping — JS toggles .is-swapping briefly */
.theme-icon.is-swapping {
  color: var(--cameo);
}

@media (prefers-reduced-motion: reduce) {
  .theme-icon svg {
    transition: opacity var(--duration-hover) var(--ease);
  }

  .theme-icon .icon-moon,
  .theme-icon .icon-sun,
  :root[data-theme="dark"] .theme-icon .icon-moon,
  :root[data-theme="dark"] .theme-icon .icon-sun {
    transform: none;
  }
}

@media (hover: hover) and (pointer: fine) {
  .site-initials:hover {
    color: var(--accent);
  }

  .theme-icon:hover {
    color: var(--accent);
  }

  .header-nav a:hover {
    color: var(--accent);
    text-decoration-color: var(--accent);
  }

  .work-list a:hover .work-title,
  .post-card a:hover .post-card-title,
  .back-link:hover,
  .empty-state a:hover {
    color: var(--accent);
    text-decoration-color: var(--accent);
  }
}

.page,
.page-shell {
  position: relative;
  z-index: 1;
  width: var(--column);
  margin: 0 auto;
  padding: var(--space-page-y) 0 var(--space-page-y-end);
}

@media (prefers-reduced-motion: no-preference) {
  /*
    Home hero entrance only — never the fixed chrome (TY / theme).
    Skipped for deep links (html[data-enter="0"], e.g. /#contact from Notes).
  */
  html:not([data-enter="0"]) body.home .name,
  html:not([data-enter="0"]) body.home .thesis,
  html:not([data-enter="0"]) body.home .lede {
    animation: hero-in 620ms var(--ease-out) both;
  }

  html:not([data-enter="0"]) body.home .name {
    animation-delay: 80ms;
  }

  html:not([data-enter="0"]) body.home .thesis {
    animation-delay: 120ms;
  }

  html:not([data-enter="0"]) body.home .lede {
    animation-delay: 160ms;
  }

  html:not([data-enter="0"]) .page-heading {
    animation: hero-in 580ms var(--ease-out) both;
    animation-delay: 40ms;
  }
}

@keyframes hero-in {
  from {
    opacity: 0.55;
    filter: blur(4px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

.name {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-headline);
  font-weight: var(--weight-bold);
  line-height: var(--leading-headline);
  letter-spacing: var(--tracking-headline);
  color: var(--fg);
  overflow-wrap: break-word;
  text-wrap: balance;
}

.thesis {
  margin: 0 0 var(--space-md);
  max-width: min(11.5em, 100%);
  font-size: var(--text-display);
  font-weight: var(--weight-bold);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  color: var(--fg);
  text-wrap: balance;
  overflow-wrap: break-word;
  hyphens: manual;
}

.lede {
  margin: 0 0 var(--space-section);
  max-width: var(--measure);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--muted);
  text-wrap: pretty;
}

.label {
  margin: 0 0 var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-soft);
}

h2.label {
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
}

/* Section heads — ink + title size (not mono field labels) */
.section-title {
  margin: 0 0 var(--space-xs);
  font-family: var(--font);
  font-size: var(--text-title);
  font-weight: var(--weight-bold);
  line-height: var(--leading-title);
  letter-spacing: var(--tracking-title);
  color: var(--fg);
  text-wrap: balance;
}

.section-note {
  margin: 0 0 var(--space-lg);
  max-width: var(--measure-narrow);
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
  letter-spacing: var(--tracking-meta);
  color: var(--muted-soft);
  text-wrap: pretty;
}

.work {
  margin-bottom: 0;
  content-visibility: auto;
  contain-intrinsic-size: auto 12rem;
}

.work-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.work-list li {
  border-top: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
}

.work-list li:last-child {
  border-bottom: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
}

.work-list a {
  display: grid;
  gap: var(--space-xs);
  padding-block: var(--space-md);
  text-decoration: none;
  color: inherit;
  border-radius: 0;
}

/* Index above title — every text line shares the column left edge */
.work-head {
  display: grid;
  gap: var(--space-2xs);
  min-width: 0;
}

.work-index {
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
  letter-spacing: var(--tracking-meta);
  color: var(--muted-soft);
  width: fit-content;
  /* Hand-log feel: slight optical drift per entry */
  transform: rotate(-1.5deg);
  transform-origin: left center;
}

.work-list li:nth-child(2) .work-index {
  transform: rotate(1deg);
}

.work-list li:nth-child(3) .work-index {
  transform: rotate(-0.75deg);
}

.work-title {
  font-size: var(--text-title);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-title);
  color: var(--fg);
  overflow-wrap: anywhere;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--link-underline-thickness);
  text-underline-offset: var(--link-underline-offset);
  transition:
    color var(--duration-hover) var(--ease),
    text-decoration-color var(--duration-hover) var(--ease);
}

.work-desc {
  font-size: var(--text-body);
  line-height: var(--leading-ui);
  color: var(--muted);
  overflow-wrap: break-word;
  text-wrap: pretty;
}

.work-list a:active .work-title {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.work-list a:focus-visible {
  outline: none;
}

.work-list a:focus-visible .work-title {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.work-list a:focus-visible .work-index {
  color: var(--cameo);
}

.colophon {
  margin: var(--space-section-lg) 0 0;
  padding-top: var(--space-md);
  border-top: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-meta);
  color: var(--muted-soft);
}

.contact {
  margin-top: var(--space-section);
  padding-top: var(--space-xl);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  /*
    Tall enough that hash/nav can park this section under the fixed chrome
    without running out of scroll room (colophon alone is too short).
  */
  min-height: calc(
    100svh - var(--chrome-offset) - env(safe-area-inset-top, 0px) +
      var(--space-page-y-end)
  );
  box-sizing: border-box;
}

.contact-lede {
  margin: 0 0 var(--space-xl);
  max-width: var(--measure);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--muted);
  text-wrap: pretty;
}

.contact-form {
  display: grid;
  gap: var(--space-lg);
  max-width: min(32rem, 100%);
}

.contact-form label {
  display: grid;
  gap: var(--space-xs);
}

.field-label {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--muted-soft);
  line-height: var(--leading-label);
}

.req {
  color: var(--cameo);
  letter-spacing: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.contact-form input,
.contact-form textarea {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  border-radius: 0;
  background: transparent;
  color: var(--fg);
  caret-color: var(--fg);
  font-family: var(--font);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  letter-spacing: normal;
  text-transform: none;
  padding: var(--space-xs) 0 var(--space-sm);
  transition:
    color var(--duration-theme) var(--ease-out),
    border-color var(--duration-hover) var(--ease);
}

/* Multiline needs a defined field — single-line stays underline-only */
.contact-form textarea {
  border: 1px solid var(--hairline);
  padding: var(--space-sm);
  min-height: 8.5rem;
  resize: none;
  line-height: var(--leading-ui);
  vertical-align: top;
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--muted-soft);
  opacity: 1;
}

.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
}

.contact-form input:focus-visible {
  border-bottom-color: var(--cameo);
}

.contact-form textarea:focus-visible {
  border-color: var(--cameo);
}

.contact-form input[aria-invalid="true"] {
  border-bottom-color: var(--cameo);
}

.contact-form textarea[aria-invalid="true"] {
  border-color: var(--cameo);
}

.field-error {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--cameo);
}

.form-status {
  margin: 0;
  font-size: var(--text-ui);
  font-weight: var(--weight-medium);
  color: var(--muted);
  transition: color var(--duration-hover) var(--ease);
}

.form-status:empty {
  display: none;
}

.form-status[data-state="success"] {
  color: var(--fg);
}

.form-status[data-state="error"] {
  color: var(--cameo);
}

@media (prefers-reduced-motion: no-preference) {
  .form-status:not(:empty) {
    animation: status-in var(--duration-hover) var(--ease-out) both;
  }
}

@keyframes status-in {
  from {
    opacity: 0.65;
  }
  to {
    opacity: 1;
  }
}

/* One solid stamp on an otherwise line-led page — intentional primary action */
.submit {
  width: fit-content;
  margin-top: var(--space-xs);
  min-height: var(--touch);
  padding: var(--space-sm) var(--space-md);
  border: 0;
  border-radius: 0;
  background: var(--fg);
  color: var(--bg);
  font: inherit;
  font-size: var(--text-body);
  font-weight: var(--weight-bold);
  text-decoration: none;
  cursor: pointer;
  transform: scale(1);
  transition:
    background-color var(--duration-hover) var(--ease),
    color var(--duration-hover) var(--ease),
    opacity var(--duration-hover) var(--ease),
    box-shadow var(--duration-hover) var(--ease),
    transform var(--duration-press) var(--ease-out);
}

.submit:hover:not(:disabled) {
  background: var(--accent);
  color: var(--bg);
}

.submit:active:not(:disabled) {
  transform: var(--press-btn);
}

.submit:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--cameo);
}

.submit:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* —— Blog / Notes —— */

.topbar {
  display: grid;
  gap: var(--space-xs);
  margin-bottom: var(--space-section);
  padding-bottom: var(--space-md);
  border-bottom: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
  transition: border-color var(--duration-theme) var(--ease-out);
}

/* Notes index — intro sits above the log; list owns the rules */
.topbar--index {
  margin-bottom: var(--space-md);
  padding-bottom: 0;
  border-bottom: none;
}

.page-heading {
  margin: 0;
  font-size: var(--text-page-title);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-display);
  color: var(--fg);
  overflow-wrap: break-word;
  text-wrap: balance;
}

.topbar .section-note {
  margin-bottom: 0;
}

.topbar .back-link {
  width: fit-content;
  margin-bottom: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  letter-spacing: var(--tracking-meta);
}

.topbar .page-heading {
  margin-bottom: 0;
}

.topbar .post-meta {
  margin: var(--space-2xs) 0 0;
}

.back-link {
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--link-underline-thickness);
  text-underline-offset: var(--link-underline-offset);
  font-size: var(--text-ui);
  font-weight: var(--weight-medium);
  transition:
    color var(--duration-hover) var(--ease),
    text-decoration-color var(--duration-hover) var(--ease);
}

.back-link:active {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.back-link:focus-visible {
  outline: none;
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.blog-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.blog-list .post-card {
  border-top: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
}

.blog-list .post-card:last-child {
  border-bottom: 1px dashed color-mix(in srgb, var(--fg) 14%, transparent);
}

.post-card a {
  display: grid;
  gap: var(--space-xs);
  padding-block: var(--space-md);
  text-decoration: none;
  color: inherit;
  border-radius: 0;
}

.post-card .post-meta {
  margin: 0;
}

.post-card-body {
  display: grid;
  gap: var(--space-xs);
  min-width: 0;
}

.post-card-title {
  font-size: var(--text-title);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-title);
  color: var(--fg);
  overflow-wrap: break-word;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--link-underline-thickness);
  text-underline-offset: var(--link-underline-offset);
  transition:
    color var(--duration-hover) var(--ease),
    text-decoration-color var(--duration-hover) var(--ease);
}

.post-card-desc {
  margin: 0;
  font-size: var(--text-body);
  line-height: var(--leading-ui);
  color: var(--muted);
  text-wrap: pretty;
}

.post-card a:focus-visible {
  outline: none;
}

.post-card a:focus-visible .post-card-title {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.post-card a:active .post-card-title {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.empty-state {
  margin: 0;
  max-width: var(--measure-narrow);
  color: var(--muted);
}

.empty-state a {
  color: var(--fg);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--link-underline-thickness);
  text-underline-offset: var(--link-underline-offset);
  transition:
    color var(--duration-hover) var(--ease),
    text-decoration-color var(--duration-hover) var(--ease);
}

.empty-state a:active {
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.empty-state a:focus-visible {
  outline: none;
  color: var(--cameo);
  text-decoration-color: var(--cameo);
}

.post-meta {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  letter-spacing: var(--tracking-meta);
  color: var(--muted-soft);
}

.blog-post {
  display: grid;
  gap: var(--space-md);
  max-width: 40rem;
}

.post-body,
.markdown-body {
  display: grid;
  gap: var(--space-md);
}

.post-body p,
.post-body li,
.markdown-body p,
.markdown-body li {
  color: var(--muted);
  max-width: var(--measure);
  overflow-wrap: break-word;
}

.post-body h2,
.post-body h3,
.markdown-body h2,
.markdown-body h3 {
  margin: var(--space-sm) 0 0;
  color: var(--fg);
}

/* Notebook lists — en-dash markers, not browser discs / 40px indent */
.post-body ul,
.markdown-body ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-xs);
  max-width: var(--measure);
  color: var(--muted);
}

.post-body ul li,
.markdown-body ul li {
  position: relative;
  padding-left: var(--space-md);
}

.post-body ul li::before,
.markdown-body ul li::before {
  content: "–";
  position: absolute;
  left: 0;
  color: var(--muted-soft);
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  line-height: var(--leading-ui);
}

.post-body ol,
.markdown-body ol {
  margin: 0;
  padding-left: var(--space-md);
  display: grid;
  gap: var(--space-xs);
  max-width: var(--measure);
  color: var(--muted);
}

.post-body ol li::marker,
.markdown-body ol li::marker {
  font-family: var(--font-mono);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  color: var(--muted-soft);
}

.post-body code,
.markdown-body code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  padding: 0 var(--space-2xs);
  border-bottom: 1px solid var(--hairline);
}

.post-body pre,
.markdown-body pre {
  overflow-x: auto;
  padding: var(--space-md) 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

.post-body pre code,
.markdown-body pre code {
  padding: 0;
  border: 0;
}

@media (max-width: 720px) {
  :root {
    --gutter: var(--space-md); /* 16 — narrow screens */
  }

  .page,
  .page-shell {
    width: var(--column);
    margin-left: auto;
    margin-right: auto;
    padding-top: var(--space-lg);
  }

  html {
    scroll-padding-top: calc(
      var(--chrome-offset-mobile) + env(safe-area-inset-top, 0px)
    );
  }

  .header-nav {
    gap: 0 var(--space-sm);
  }

  .header-nav a {
    font-size: var(--text-ui);
  }

  .desk {
    padding-top: calc(var(--chrome-offset-mobile) + env(safe-area-inset-top, 0px));
  }

  .thesis {
    max-width: 100%;
    font-size: var(--text-display-sm);
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-display);
  }

  .contact {
    min-height: calc(
      100svh - var(--chrome-offset-mobile) - env(safe-area-inset-top, 0px) +
        var(--space-page-y-end)
    );
  }

  .contact-lede {
    margin-bottom: var(--space-lg);
  }

  .contact-form {
    max-width: none;
    gap: var(--space-md);
  }

  .lede {
    max-width: none;
  }
}

/* Short landscape phones — keep chrome compact */
@media (max-height: 480px) and (orientation: landscape) {
  html {
    scroll-padding-top: calc(
      var(--chrome-offset-landscape) + env(safe-area-inset-top, 0px)
    );
  }

  .desk {
    padding-top: calc(var(--chrome-offset-landscape) + env(safe-area-inset-top, 0px));
  }

  .contact {
    min-height: calc(
      100svh - var(--chrome-offset-landscape) - env(safe-area-inset-top, 0px) +
        var(--space-page-y-end)
    );
  }

  .brand-row,
  .header-nav a,
  .site-initials,
  .theme-icon {
    min-height: var(--touch-compact);
  }

  .theme-icon {
    width: var(--touch-compact);
    height: var(--touch-compact);
  }

  .page,
  .page-shell {
    padding-top: var(--space-lg);
    padding-bottom: var(--space-xl);
  }
}

/* Touch: don’t rely on hover alone */
@media (hover: none) {
  .header-nav a:active,
  .site-initials:active,
  .work-list a:active .work-title,
  .back-link:active,
  .post-card a:active .post-card-title {
    color: var(--accent);
  }

  :root[data-palette="5"] .header-nav a:active,
  :root[data-palette="5"] .site-initials:active,
  :root[data-palette="5"] .theme-icon:active,
  :root[data-palette="5"] .work-list a:active .work-title,
  :root[data-palette="5"] .post-card a:active .post-card-title {
    color: var(--cameo);
  }
}

@media (pointer: coarse) {
  .contact-form input,
  .contact-form textarea {
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
    font-size: var(--text-body); /* avoid iOS zoom on focus */
  }

  .submit {
    min-height: var(--touch);
    padding-inline: var(--space-md);
  }

  .work-list a,
  .post-card a {
    padding-block: var(--space-md);
  }
}
