/* ── Roboto Mono, self-hosted (variable: 300–500 roman, 300–400 italic) ──
   Subsets mirror what Google served: latin + latin-ext. Anything outside
   those ranges falls back to ui-monospace, exactly as it did before.      */
@font-face {
  font-family: "Roboto Mono";
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url("fonts/roboto-mono-roman-latin.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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Roboto Mono";
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url("fonts/roboto-mono-roman-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Roboto Mono";
  font-style: italic;
  font-weight: 300 400;
  font-display: swap;
  src: url("fonts/roboto-mono-italic-latin.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+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Roboto Mono";
  font-style: italic;
  font-weight: 300 400;
  font-display: swap;
  src: url("fonts/roboto-mono-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --mono: "Roboto Mono", ui-monospace, monospace;
  --accent-dark: #84cfa1;
  --accent-light: #a8451c;
  /* dark (default) */
  --bg: #0a0a0a;
  --bg2: #070707;          /* terminal inset */
  --tile: #111111;
  --ink: #e6e6e3;
  --soft: rgba(230,230,227,0.62);
  --faint: rgba(230,230,227,0.38);
  --ghost: rgba(230,230,227,0.16);
  --line: rgba(230,230,227,0.12);
  --accent: var(--accent-dark);
  --nav-bg: rgba(10,10,10,0.3);
  --hint-bg: rgba(10,10,10,0.72);
  --hover-line: rgba(230,230,227,0.4);
  --stripe: rgba(230,230,227,0.025);
  --term-bg: color-mix(in srgb, var(--bg2) 30%, transparent);
}
/* light — the cream-paper lineage (light-leak / preprint candidates) */
html[data-theme="light"] {
  --bg: #f3e9d4;
  --bg2: #ede2c9;
  --tile: #ede2c9;
  --ink: #1a1410;
  --soft: rgba(26,20,16,0.74);
  --faint: rgba(26,20,16,0.5);
  --ghost: rgba(26,20,16,0.16);
  --line: rgba(26,20,16,0.14);
  --accent: var(--accent-light);
  --nav-bg: rgba(243,233,212,0.3);
  --hint-bg: rgba(243,233,212,0.78);
  --hover-line: rgba(26,20,16,0.45);
  --stripe: rgba(26,20,16,0.03);
  --term-bg: rgba(26,20,16,0.055);   /* warm grey wash so the panel reads against the cream */
}
/* the soft light-leak horizon, carried over from the light candidates */
html[data-theme="light"] body { background: transparent; }
html[data-theme="light"] body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 48vh;
  z-index: -1; pointer-events: none;
  background: url("assets/lightleak-soft.webp") center 30% / cover no-repeat;
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.2) 56%, transparent 100%);
  mask-image: linear-gradient(180deg, rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.2) 56%, transparent 100%);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); }
html, body { transition: background .25s ease; }
body {
  font-family: var(--mono); color: var(--ink);
  font-size: 14px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh; display: flex; flex-direction: column;
}
main { flex: 1; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: var(--bg); }

/* ── blinking block cursor ─────────────────────────────────────────── */
.cursor {
  display: inline-block; width: 0.58em; height: 1.05em;
  background: var(--accent); vertical-align: text-bottom;
  margin-left: 2px;
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cursor { animation: none; } }

/* ── work-in-progress banner ───────────────────────────────────────── */
/* Sits above the sticky nav in normal flow, so it scrolls away and the nav
   then pins to the top on its own. Its height is deliberately not hardcoded
   anywhere — the landing page absorbs it via flex (see main.fill > #home),
   which holds however many lines the text wraps to. */
.banner {
  padding: 8px 40px; text-align: center;
  font-size: 11.5px; font-weight: 300; letter-spacing: 0.04em;
  color: var(--soft);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-bottom: 1px solid var(--line);
}

/* ── top bar ───────────────────────────────────────────────────────── */
nav {
  position: sticky; top: 0; z-index: 40;
  display: flex; justify-content: space-between; align-items: center;
  gap: 24px; padding: 0 40px; height: 52px;
  background: var(--nav-bg);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  border-bottom: 1px solid var(--line);
  font-size: 12px; letter-spacing: 0.02em;
}
nav .name { color: var(--ink); white-space: nowrap; transition: color .15s ease; }
nav .name:hover { color: var(--accent); }
nav .links { display: flex; gap: 26px; }
nav .links a { color: var(--soft); white-space: nowrap; transition: color .15s ease; }
nav .links a:hover { color: var(--accent); }
nav .links a.active { color: var(--accent); }
nav .theme {
  background: none; border: 1px solid var(--line); color: var(--soft);
  font: inherit; font-size: 11px; letter-spacing: 0.06em;
  padding: 3px 12px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
nav .theme:hover { color: var(--accent); border-color: var(--accent); }

/* ── landing (sparse — particle glyphs are the nav) ────────────────── */
#home {
  min-height: calc(100vh - 52px); position: relative;
  display: flex; flex-direction: column;
}
/* Inside a fill main the landing takes whatever height is left after the
   banner and nav, so it stays exactly one screen no matter how many lines
   the banner wraps to. The calc above is only the no-flex fallback. */
main.fill > #home { min-height: 0; }
.glyph-nav {
  flex: 1; display: flex; align-items: center; justify-content: center;
  gap: clamp(36px, 8vw, 120px); flex-wrap: wrap; padding: 60px 40px 120px;
}
.glyph { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.glyph canvas { display: block; width: 130px; height: 130px; }
.glyph .lbl {
  font-size: 12px; letter-spacing: 0.2em; color: var(--soft);
  transition: color .15s ease;
}
.glyph:hover .lbl { color: var(--accent); }
.corner {
  position: absolute; left: 40px; bottom: 36px; max-width: 46ch;
  font-size: 12.5px; line-height: 1.8; color: var(--faint); font-weight: 300;
}
.corner .who { color: var(--ink); font-weight: 400; transition: color .15s ease; }
.corner a:hover .who { color: var(--accent); }
.corner-r {
  position: absolute; right: 40px; bottom: 36px; text-align: right;
  font-size: 12px; color: var(--faint); font-weight: 300;
}

/* ── page content sits straight under the nav ─────────────────────── */
main > section { padding-top: 48px; }
/* the intro sits closer under the nav than a list or article does */
main > section.photos { padding-top: 28px; }
#home { padding-top: 0; }

/* ── writing / papers lists ────────────────────────────────────────── */
.list { border-top: 1px solid var(--line); margin: 0 40px; }
.list a {
  display: grid; grid-template-columns: 56px 1fr 220px; gap: 28px;
  align-items: baseline; padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
.list a .n { color: var(--faint); font-size: 12px; }
.list a .t { color: var(--ink); font-size: 16px; letter-spacing: -0.01em; transition: color .15s ease; }
.list a .dek { display: block; margin-top: 4px; color: var(--faint); font-size: 12.5px; font-weight: 300; line-height: 1.6; max-width: 60ch; }
.list a .meta { color: var(--faint); font-size: 11.5px; text-align: right; line-height: 1.8; font-weight: 300; }
.list a:hover .t { color: var(--accent); }
.tag { color: var(--soft); font-size: 11px; white-space: nowrap; }
.tag.draft { color: var(--accent); }

/* ── photos (infinite wrap-around grid) ───────────────────────────── */
.photos-pan {
  position: relative; height: calc(100vh - 100px); min-height: 480px;
  overflow: hidden; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none;
  outline: none;
}
.photos-intro {
  margin: 0 40px 26px; max-width: 68ch;
  font-size: 13px; font-weight: 300; line-height: 1.8; color: var(--soft);
}
.photos-intro p { margin: 0; text-wrap: pretty; }
.photos-intro .kit {
  margin-top: 10px; font-size: 11.5px; color: var(--faint); letter-spacing: 0.04em;
}

/* main is flex:1 inside a 100vh body, so when the grid's own height is shorter
   than the space main was given, the slack shows as dead space above the
   footer. `flex: 1 1 auto` lets the grid track that space in both directions:
   basis stays its declared height, grow soaks up any leftover, and shrink
   lets the intro above take its share rather than pushing the page into a
   scroll. min-height below is still the floor. */
main.fill { display: flex; flex-direction: column; }
main.fill > section { flex: 1 0 auto; display: flex; flex-direction: column; }
main.fill .photos-pan { flex: 1 1 auto; }
.photos-pan.dragging { cursor: grabbing; }
.photos-pan:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }
.pan-plane { position: absolute; inset: 0; will-change: transform; }
.pan-col { position: absolute; top: 0; will-change: transform; }
.pan-seq { display: flex; flex-direction: column; gap: var(--pan-gap, 26px); padding-bottom: var(--pan-gap, 26px); }
.pan-hint {
  position: absolute; right: 40px; bottom: 18px; z-index: 3;
  font-size: 11px; color: var(--faint); font-weight: 300; letter-spacing: 0.04em;
  pointer-events: none;
  background: var(--hint-bg); padding: 4px 10px;
}
.photo { cursor: zoom-in; }

/* ── lightbox ──────────────────────────────────────────────────────── */
.lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 4vmin;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  cursor: zoom-out;
  animation: lb-in .18s ease both;
}
/* .lightbox sets display:flex, which would otherwise beat the UA rule for the
   hidden attribute — so hiding has to be stated explicitly. */
.lightbox[hidden] { display: none; }
@keyframes lb-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .lightbox { animation: none; } }
.lightbox img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; display: block;
  border: 1px solid var(--line);
  cursor: default;
}
.lb-close {
  position: absolute; top: 20px; right: 24px;
  background: none; border: 1px solid var(--line); color: var(--soft);
  font: inherit; font-size: 11px; letter-spacing: 0.06em;
  padding: 3px 12px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.lb-close:hover { color: var(--accent); border-color: var(--accent); }
html.lb-locked, html.lb-locked body { overflow: hidden; }
.photo { display: block; }
.photo .ph {
  position: relative; overflow: hidden; background: var(--tile);
  border: 1px solid var(--line); aspect-ratio: 3 / 2;
  transition: border-color .2s ease;
}
.photo img { -webkit-user-drag: none; }
.photo .ph img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.001); transition: transform .45s cubic-bezier(.2,.6,.2,1);
}
.photo:hover .ph { border-color: var(--hover-line); }
.photo:hover .ph img { transform: scale(1.035); }
.photo .cap {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 10px 2px 0; font-size: 11.5px; color: var(--faint); font-weight: 300;
  transition: color .15s ease;
}
.photo:hover .cap { color: var(--soft); }
.photo .cap .m { white-space: nowrap; color: var(--faint); }
/* unscanned placeholder tiles */
.photo .ph.empty {
  display: flex; align-items: center; justify-content: center;
  background:
    repeating-linear-gradient(-45deg, var(--stripe) 0 1px, transparent 1px 9px),
    var(--tile);
}
.photo .ph.empty span { color: var(--faint); font-size: 11px; opacity: 0.85; padding: 0 18px; text-align: center; }

/* ── code (shell transcript) ───────────────────────────────────────── */
.term {
  margin: 0 40px; padding: 34px 36px 30px;
  background: var(--term-bg); border: 1px solid var(--line);
  font-size: 13px; line-height: 1.85; overflow-x: auto;
}
.term .row { white-space: pre-wrap; }
.term .ps { color: var(--accent); }
.term .cmd { color: var(--ink); }
.term .out { color: var(--soft); font-weight: 300; }
.term .dim { color: var(--faint); font-weight: 300; }
.term .gap { height: 1.2em; }
.term a.repo { color: var(--ink); border-bottom: 1px solid var(--ghost); transition: color .15s ease, border-color .15s ease; }
.term a.repo:hover { color: var(--accent); border-color: var(--accent); }

/* ── about ─────────────────────────────────────────────────────────── */
.about-wrap {
  display: grid; grid-template-columns: minmax(260px, 340px) 1fr;
  gap: 40px; padding: 0 40px; align-items: start;
}
.about-wrap .photo { cursor: default; }
.about-wrap .term { margin: 0; }
.about-wrap .photo .ph { aspect-ratio: 4 / 5; }

/* ── footer ────────────────────────────────────────────────────────── */
footer {
  margin-top: 96px; padding: 26px 40px 34px;
  border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: baseline; gap: 24px;
  font-size: 12px; color: var(--faint); font-weight: 300;
}
footer a { color: var(--soft); transition: color .15s ease; }
footer a:hover { color: var(--accent); }

@media (max-width: 900px) {
  nav { padding: 0 20px; }
  .banner { padding-left: 20px; padding-right: 20px; }
  .photos-intro { margin-left: 20px; margin-right: 20px; }
  footer { padding-left: 20px; padding-right: 20px; }
  .glyph-nav { gap: 28px; padding: 40px 20px; }
  .glyph canvas { width: 104px; height: 104px; }
  .corner, .corner-r { position: static; padding: 0 20px 24px; max-width: none; text-align: left; }
  .list { margin: 0 20px; }
  .list a { grid-template-columns: 40px 1fr; }
  .list a .meta { display: none; }
  .photos-pan { height: 64vh; min-height: 400px; }
  .pan-hint { right: 20px; }
  .term { margin: 0 20px; }
  .about-wrap { grid-template-columns: 1fr; padding: 0 20px; }
  .about-wrap .photo { max-width: 320px; }
}

/* ── reading pages (article + paper) ───────────────────────────────── */
.read { max-width: 1080px; margin: 0 auto; padding: 0 40px; }
.read .back { display: inline-block; font-size: 12px; color: var(--soft); transition: color .15s ease; }
.read .back:hover { color: var(--accent); }
.read-head { max-width: 680px; padding: 30px 0 0; }
.read-kicker { font-size: 11px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--accent); margin-bottom: 18px; }
.read-head h1 { margin: 0; font-weight: 500; font-size: 33px; line-height: 1.22; letter-spacing: -0.02em; color: var(--ink); text-wrap: pretty; }
.read-dek { margin: 14px 0 0; font-size: 15px; font-style: italic; font-weight: 300; color: var(--soft); line-height: 1.7; max-width: 54ch; }
.read-meta {
  margin-top: 22px; padding: 12px 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  font-size: 11.5px; color: var(--faint); font-weight: 300; letter-spacing: 0.04em;
}
.read-body { padding: 34px 0 8px; }
.end-mark { display: flex; align-items: center; gap: 12px; margin-top: 26px; font-size: 12px; color: var(--faint); font-weight: 300; max-width: 680px; }
.end-mark::before { content: ""; width: 9px; height: 9px; background: var(--accent); flex: none; }
.read-colophon {
  margin-top: 38px; padding-top: 16px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: baseline; gap: 24px;
  font-size: 11.5px; color: var(--faint); font-weight: 300; max-width: 680px;
}
.read-colophon a { color: var(--soft); transition: color .15s ease; }
.read-colophon a:hover { color: var(--accent); }

/* article: measure + margin-note rail */
.art-row { display: grid; grid-template-columns: minmax(0, 680px) 252px; gap: 56px; align-items: start; padding-bottom: 1.4em; }
.art-row > div > p { margin: 0; font-size: 15px; font-weight: 300; line-height: 1.95; color: var(--ink); text-wrap: pretty; }
.art-row sup { font-size: 10px; color: var(--accent); margin-left: 2px; }
.margin-note {
  border-left: 1px solid var(--line); padding-left: 16px; margin-top: 6px;
  font-size: 11.5px; line-height: 1.7; color: var(--faint); font-weight: 300;
}
.margin-note b { color: var(--accent); font-weight: 400; }
blockquote.pull {
  margin: 8px 0 0; padding-left: 22px; border-left: 2px solid var(--accent);
  font-size: 19px; line-height: 1.6; font-style: italic; font-weight: 300; color: var(--ink); text-wrap: pretty;
}
.sec-rule { display: flex; align-items: center; gap: 14px; max-width: 680px; margin: 4px 0 30px; color: var(--accent); font-size: 13px; }
.sec-rule::before, .sec-rule::after { content: ""; flex: 1; height: 1px; background: var(--line); }
figure.chart { margin: 8px 0 30px; max-width: 680px; }
figure.chart svg { display: block; width: 100%; }
figure.chart figcaption { margin-top: 10px; font-size: 11px; color: var(--faint); font-weight: 300; line-height: 1.6; }
figure.chart figcaption b { color: var(--accent); font-weight: 400; }

/* paper: centred preprint, terminal palette */
.paper-head { max-width: 680px; margin: 0 auto; text-align: center; padding: 30px 0 0; }
.paper-head .read-kicker { margin-bottom: 16px; }
.paper-head h1 { margin: 0; font-weight: 500; font-size: 29px; line-height: 1.28; letter-spacing: -0.015em; color: var(--ink); text-wrap: pretty; }
.paper-sub { margin: 12px auto 0; max-width: 46ch; font-size: 14px; font-style: italic; font-weight: 300; color: var(--soft); line-height: 1.7; }
.paper-auth { margin-top: 20px; font-size: 13.5px; color: var(--ink); }
.paper-auth sup { font-size: 9px; color: var(--accent); }
.paper-affil { margin-top: 6px; font-size: 11px; color: var(--faint); font-weight: 300; letter-spacing: 0.04em; }
.abstract {
  position: relative; max-width: 680px; margin: 34px auto 0; text-align: left;
  background: var(--bg2); border: 1px solid var(--line); padding: 22px 26px 18px;
}
.abstract .lab {
  position: absolute; top: -9px; left: 22px; background: var(--bg); padding: 0 8px;
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent);
}
.abstract p { margin: 0; font-size: 13px; font-weight: 300; line-height: 1.85; color: var(--ink); }
.abstract .kw { margin-top: 12px; font-size: 11.5px; color: var(--faint); font-weight: 300; }
.abstract .kw b { color: var(--soft); font-weight: 400; letter-spacing: 0.08em; }
.paper-body { max-width: 680px; margin: 0 auto; padding: 12px 0 8px; }
.paper-body h2 { margin: 32px 0 10px; font-size: 15.5px; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); }
.paper-body h2 .pn { color: var(--accent); margin-right: 10px; }
.paper-body p { margin: 0 0 1em; font-size: 14px; font-weight: 300; line-height: 1.9; color: var(--ink); text-wrap: pretty; }
.paper-body p i { font-style: italic; }
.defn {
  margin: 16px 0; padding: 14px 18px;
  border-left: 2px solid var(--accent); background: var(--bg2);
  font-size: 13px; font-weight: 300; line-height: 1.8; color: var(--ink);
}
.defn b { color: var(--accent); font-weight: 500; letter-spacing: 0.06em; }
.eq-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px; margin: 16px 0; }
.eq-row .tex { overflow-x: auto; }
.eq-row .num { font-size: 12px; color: var(--faint); }
.katex { font-size: 1.16em; }
.refs { margin-top: 34px; }
.refs .rh {
  font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink);
  padding-bottom: 8px; border-bottom: 1px solid var(--soft); margin-bottom: 12px;
}
.refs .r { display: grid; grid-template-columns: 34px 1fr; gap: 8px; margin-bottom: 8px; font-size: 12.5px; font-weight: 300; line-height: 1.7; color: var(--soft); }
.refs .r .k { font-size: 11.5px; color: var(--faint); }
.fn { margin-top: 18px; padding-top: 10px; border-top: 1px solid var(--line); font-size: 11px; color: var(--faint); font-weight: 300; line-height: 1.7; }
.fn sup { color: var(--accent); }

@media (max-width: 1000px) {
  .read { padding: 0 20px; }
  .art-row { grid-template-columns: 1fr; gap: 0; }
  .margin-note { margin: 14px 0 0; }
}

