@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('fonts/geist-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: 'Geist';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('fonts/geist-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;
}

/* one palette, white or black, resolved by color-scheme so it needs no script */
:root {
    color-scheme: light dark;
    --mono: 'Geist Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
    --sans: 'Geist', Arial, Helvetica, sans-serif;

    --bg: light-dark(#ffffff, #000000);
    --ink: light-dark(#0b0d10, #f6f8fa);
    --body: light-dark(#3a414c, #b9c0ca);
    --body-strong: light-dark(#262c35, #d6dbe2);
    --emphasis: light-dark(#14181e, #eef1f4);
    --subtle: light-dark(#4d5664, #a7afba);
    --muted: light-dark(#667080, #8b95a3);
    --listing-text: light-dark(#262c35, #d6dbe2);
    --faint: light-dark(#a9b2be, #47505b);
    --link: light-dark(#0b0d10, #f6f8fa);
    --link-quiet: light-dark(#262c35, #d6dbe2);
    --line: light-dark(#e7ecf2, #1c2127);
    --underline: light-dark(#bfe0ff, #2c5a82);
    --hover: light-dark(#0b0d10, #ffffff);
    --selection: light-dark(#d6ebff, #123a5c);

    /* the blue: very pale as a fill, deeper only where small text has to read */
    --ice: light-dark(#dcefff, #10283c);
    --ice-strong: light-dark(#bfe0ff, #1b4264);
    --accent: light-dark(#1a6cc9, #a9d8ff);
    --accent-2: light-dark(#7dbcf3, #cfe9ff);

    --surface-2: light-dark(#f2f8fe, #0c1116);
    --surface-border: light-dark(#dce7f2, #1f262e);
    --stroke: light-dark(#7c8896, #8e99a6);
    --stroke-faint: light-dark(#cdd8e3, #36404a);
    --track: light-dark(rgba(26,108,201,.08), rgba(169,216,255,.1));
    --backdrop: light-dark(rgba(245,249,253,.92), rgba(0,0,0,.92));
    --shadow: 0 18px 44px light-dark(rgba(30,70,120,.1), rgba(0,0,0,.4));
    --img-filter: none;
    --poster-glow: light-dark(rgba(125,188,243,.16), rgba(169,216,255,.1));
    --surface-grad: light-dark(linear-gradient(180deg, #ffffff, #f4f9fe), linear-gradient(180deg, #11161b, #080a0d));
    --arrow-rest: .8;
    --ease: cubic-bezier(.2, .7, .2, 1);

}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
    margin: 0;
    color: var(--body);
    background: var(--bg);
    font-family: var(--mono);
    font-size: 14px;
    font-weight: 400;
    line-height: 1.6;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--link); text-decoration: none; }
a:focus-visible, button:focus-visible, summary:focus-visible {
    outline: 1px solid var(--accent); outline-offset: 3px;
}
::selection { color: var(--ink); background: var(--selection); }

/* every link: a pale rule, with a darker line that wipes in from the left and out to the right */
.spread p a, .role a, .article-body a, .article-nav a, .work .entry-title, .link-mail span {
    background:
        linear-gradient(var(--accent), var(--accent)) 100% 100% / 0 1px no-repeat,
        linear-gradient(var(--ice-strong), var(--ice-strong)) 0 100% / 100% 1px no-repeat;
    transition: background-size 280ms var(--ease), color 180ms ease;
}

.skip-link {
    position: fixed; top: 8px; left: 8px; z-index: 100;
    padding: 7px 10px; color: var(--bg); background: var(--ink);
    transform: translateY(-160%);
}
.skip-link:focus { transform: translateY(0); }

.theme-toggle {
    position: fixed; top: 16px; right: 18px; z-index: 50;
    padding: 2px 4px; border: 0;
    color: var(--muted); background: var(--bg);
    font: inherit; font-size: 12px; cursor: pointer;
    transition: color 180ms ease;
}
.theme-toggle b { color: var(--ink); font-weight: 400; background: var(--ice); }

/* --- homepage: one spread, two columns, one character grid ---
   every width is in ch and the type scales with the viewport, so the page sets like a printed sheet */
.spread {
    --dashes: "+-------------------------------------------------------------------------------------------------------------------------------------";
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    min-height: 100vh; min-height: 100svh;
    padding: 34px clamp(24px, 3.4vw, 72px) 14px;
    /* fits both ways: never wider than the window, and rule to rule never taller than it.
       54.5 is the height of the content in em; 48px is the page's own top and bottom padding */
    font-size: clamp(10px, min(1.05vw, calc((100vh - 48px) / 54.5)), 24px);
    line-height: 1.58;
}
.col {
    position: relative; min-width: 0;
    display: flex; flex-direction: column;
    padding: 1.6lh 6ch 1.4lh 0;
}
.col-work { padding-right: 0; }
/* the rule is one line of real hyphens; a plus marks where each column starts */
.col::before, .col::after {
    content: var(--dashes);
    position: absolute; left: 0; right: 0;
    height: 1lh; overflow: hidden; white-space: nowrap;
    color: var(--stroke-faint); user-select: none;
}
.col::before { top: 0; }
.col::after { bottom: 0; }

.col-who { gap: 1.4lh; }
.col-work > * { max-width: 76ch; }
.who { display: flex; align-items: flex-end; gap: 2.5ch; }
.name {
    margin: 0; color: var(--ink);
    font-size: 4em; font-weight: 400; line-height: 1;
}
.role { margin: .5lh 0 0; color: var(--muted); }

/* a small square, head and shoulders: shows x 130-480, y 80-430 of the 640px photo */
.photo { position: relative; flex: none; width: 7.6em; aspect-ratio: 1; margin: 0; overflow: hidden; }
.photo img { position: absolute; top: -22.86%; left: -37.14%; display: block; width: 182.86%; max-width: none; height: auto; transition: transform 700ms var(--ease); }

.social-links { display: flex; flex-wrap: wrap; align-items: center; gap: .4lh .9em; }
.social-links a { display: flex; align-items: center; gap: .7ch; color: var(--muted); transition: opacity 240ms ease; }
.link-mark { flex: none; display: block; width: 1.15em; height: 1.15em; fill: var(--ink); transition: fill 180ms ease, transform 220ms var(--ease); }
.link-mail { margin-left: .9em; }

.section-label {
    margin: 0 0 1lh; color: var(--muted);
    font-size: 1em; font-weight: 400; line-height: inherit; text-transform: lowercase;
}
.section-label-next { margin-top: .9lh; margin-bottom: .75lh; }

.about { max-width: 66ch; }
.about p { margin: 0 0 1lh; color: var(--body); text-wrap: pretty; }
.about p:last-child { margin-bottom: 0; }
.about .lead { color: var(--emphasis); }
.about strong { color: var(--emphasis); font-weight: 500; }

.entry {
    display: flex; align-items: baseline; gap: 1ch;
    margin: 0 0 .25lh; color: var(--muted);
}
.entry-title { min-width: 0; color: var(--ink); }
.entry-title a { color: inherit; }
.entry-dots {
    flex: 1 1 2ch; min-width: 2ch; height: 1lh; overflow: hidden;
    user-select: none; white-space: nowrap;
    /* a half-accent, half-faint gradient clipped to the dots: sliding it runs the colour along the leader */
    background: linear-gradient(90deg, var(--accent) 50%, var(--faint) 50%) 100% 0 / 200% 100% no-repeat;
    -webkit-background-clip: text; background-clip: text; color: transparent;
    transition: background-position 420ms var(--ease);
}
.entry-dots::before { content: "................................................................................................"; }
.entry-end { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; transition: color 180ms ease; }
.entry-end.accepted { color: var(--accent); }

.paper { margin: 0 0 .6lh; transition: opacity 240ms ease; }
.paper .entry { position: relative; }
.paper .entry a::after { content: ""; position: absolute; inset: 0; }
.paper .entry { margin-bottom: .15lh; }
.entry-note { margin: 0; color: var(--muted); font-size: .94em; line-height: 1.5; text-wrap: pretty; }
.work { display: block; margin: 0 0 .85lh; color: inherit; transition: opacity 240ms ease; }
.work:last-child { margin-bottom: 0; }
.work .entry { margin-bottom: .45lh; }
.work .article-art { margin: 0; font-size: .99em; line-height: 1.2; }

/* --- article --- */
.reading-progress {
    position: fixed; top: 0; right: 0; left: 0; z-index: 40;
    height: 13px; overflow: hidden;
    color: var(--faint); background: var(--bg);
    font-size: 10px; line-height: 13px; white-space: nowrap;
    pointer-events: none; user-select: none;
}
.reading-progress span {
    position: absolute; inset: 0;
    color: var(--accent);
    clip-path: inset(0 calc(100% - var(--reading-progress, 0) * 100%) 0 0);
}
.article-nav {
    position: relative; z-index: 1;
    width: min(100%, 760px); margin: 0 auto; padding: 30px 38px 0;
    display: flex; justify-content: space-between; gap: 24px;
    color: var(--muted); font-size: 13px;
}
.article-nav-actions { display: flex; align-items: center; gap: 22px; }
.article-main { position: relative; z-index: 1; width: min(100%, 760px); margin: 0 auto; padding: 56px 38px 76px; }
.article-head { margin-bottom: 44px; }
.article-art {
    margin: 0 0 30px; min-height: calc(var(--rows, 9) * 1.3em);
    color: var(--stroke);
    transition: color 240ms ease;
    font: 400 min(13px, calc((100vw - 46px) / 43.2)) / 1.3 var(--mono);
    white-space: pre; overflow: hidden;
}
.article-art .hi { color: var(--accent-2); }
.article-art .dim { color: var(--faint); }
.article-art.playing .ink { color: var(--ink); }
.article-art.playing .hi { color: var(--accent); }
.article-title {
    max-width: 650px; margin: 0; color: var(--ink);
    font-size: clamp(24px, 3.2vw, 31px); font-weight: 500; letter-spacing: -.03em; line-height: 1.18;
}
.article-meta { margin-top: 14px; color: var(--muted); font-size: 12.5px; }
.article-head::after {
    content: "------------------------------------------------------------------------------------------------------------------------";
    display: block; margin-top: 20px; height: 1.4em; overflow: hidden;
    color: var(--faint); font-size: 13px; white-space: nowrap;
}
.article-body { color: var(--body); font-family: var(--sans); font-size: 17px; line-height: 1.68; letter-spacing: -.006em; }
/* the reading measure stays 620px and left-aligned; only .poster-figure breaks out,
   so its containing block is the full centred content box */
.article-body > p,
.article-body > h2,
.article-body > .math-display,
.article-body > figure:not(.poster-figure) { max-width: 620px; }
.article-body p { margin: 0 0 19px; }
.article-body .intro { color: var(--body-strong); }
.article-body h2 {
    margin: 49px 0 16px; color: var(--ink);
    font-family: var(--mono); font-size: 16px;
    font-weight: 500; letter-spacing: -.02em; line-height: 1.35;
}
.article-body h2::before { content: "## "; color: var(--accent-2); font-weight: 400; }
.article-body strong { color: var(--ink); font-weight: 500; }
.article-body code { font-family: var(--mono); }
.article-body code.terminal-command {
    display: inline-block; padding: 1px 6px 2px;
    background: var(--surface-2); color: var(--emphasis);
    font: 500 .8em/1.35 var(--mono);
    white-space: nowrap;
}
.article-body code.terminal-command::before { content: "$"; margin-right: .5em; color: var(--accent); }
.article-body pre.terminal-output {
    margin: 0; padding: 14px 16px; overflow-x: auto;
    background: var(--surface-2); color: var(--emphasis);
    font: 400 13.5px/1.6 var(--mono);
}
.article-body pre.terminal-output code { font: inherit; }
.article-body figure { margin: 34px 0 38px; }
.diagram {
    display: block; width: 100%; height: auto; color: var(--ink);
    font-family: var(--sans);
}
.diagram .muted { fill: var(--muted); }
.diagram .ink { fill: var(--ink); }
.diagram .node { fill: var(--bg); stroke: var(--stroke); stroke-width: 1.2; }
.diagram .accent-node { fill: var(--surface-2); stroke: var(--accent); stroke-width: 1.35; }
.diagram .line { fill: none; stroke: var(--subtle); stroke-width: 1.2; }
.diagram .accent-line { fill: none; stroke: var(--accent); stroke-width: 1.35; }
.diagram .faint-line { fill: none; stroke: var(--stroke-faint); stroke-width: 1.2; }
.diagram .dashed { stroke-dasharray: 4 5; }
.diagram .node, .diagram .accent-node, .diagram .line, .diagram .accent-line {
    transition: fill 220ms ease, stroke 220ms ease;
}
.diagram .node:hover, .diagram .accent-node:hover {
    fill: var(--ice); stroke: var(--accent);
}
.article-body figure:hover .diagram .line,
.article-body figure:hover .diagram .accent-line { stroke: var(--accent); }
.article-body .poster-figure::before {
    content: ""; position: absolute; inset: -6% -3% -10%; z-index: -1;
    background: radial-gradient(58% 58% at 50% 45%, var(--poster-glow), transparent 72%);
    pointer-events: none;
}
.poster-figure figcaption { text-align: center; }
.article-body figcaption { margin-top: 10px; color: var(--muted); font-size: 14px; line-height: 1.5; }
.article-body .poster-figure {
    position: relative; isolation: isolate;
    width: min(1060px, calc(100vw - 48px));
    margin: 60px 0 46px;
    margin-left: 50%;
    translate: -50% 0;
}
.poster-link {
    display: block; width: 100%; padding: 0; overflow: hidden;
    background: var(--surface-grad);
    border: 1px solid var(--surface-border); border-radius: 2px;
    box-shadow: var(--shadow);
    color: inherit; cursor: zoom-in;
    transition: border-color 220ms ease, box-shadow 220ms ease;
}
.poster-link:hover, .poster-link:focus-visible { border-color: var(--accent); }
.poster-link img {
    display: block; width: 100%; height: auto;
    filter: var(--img-filter);
}
.poster-dialog {
    width: min(94vw, 1500px); max-width: none; margin: auto; padding: 0;
    overflow: visible; color: var(--body); background: transparent; border: 0;
    cursor: zoom-out;
}
.poster-dialog::backdrop { background: var(--backdrop); backdrop-filter: blur(1px); }
.poster-dialog img {
    display: block; width: auto; max-width: 100%; max-height: 90vh;
    margin: 0 auto; border: 0; border-radius: 2px;
    cursor: default; filter: var(--img-filter);
}
.poster-close {
    position: absolute; top: -28px; right: 0; padding: 0; border: 0;
    color: var(--muted); background: transparent; font: inherit; font-size: 14px;
    cursor: pointer;
}
.poster-close:hover { color: var(--ink); }
.math-display {
    margin: 23px 0; overflow-x: auto; overflow-y: hidden;
    color: var(--ink); text-align: center;
}
.math-display .katex-display { margin: 0; }
.math-display.key-equation {
    margin: 31px 0; padding: 21px 0; border: 0;
    background:
        linear-gradient(90deg, var(--line), transparent) top left / 100% 1px no-repeat,
        linear-gradient(90deg, var(--line), transparent) bottom left / 100% 1px no-repeat;
}
.key-equation .katex { font-size: 1.08em; }
.katex { color: var(--ink); font-size: 1em; }

@media (max-width: 1040px) {
    .theme-toggle { position: absolute; }
    .article-nav { padding-top: 48px; }
}
/* hover states live here, so touch screens never get stuck in one */
@media (hover: hover) {
    .spread p a:is(:hover, :focus-visible), .role a:is(:hover, :focus-visible),
    .article-body a:is(:hover, :focus-visible), .article-nav a:is(:hover, :focus-visible) { color: var(--hover); }
    .spread p a:is(:hover, :focus-visible), .role a:is(:hover, :focus-visible),
    .article-body a:is(:hover, :focus-visible), .article-nav a:is(:hover, :focus-visible),
    .work:is(:hover, :focus-visible) .entry-title,
    .link-mail:is(:hover, :focus-visible) span {
        background-position: 0 100%, 0 100%;
        background-size: 100% 1px, 100% 1px;
    }

    /* a row: the dots fill towards the date, and the other rows step back */
    .work:is(:hover, :focus-visible) .entry-dots,
    .paper .entry:has(a:is(:hover, :focus-visible)) .entry-dots { background-position: 0 0; }
    .work:is(:hover, :focus-visible) .entry-end,
    .paper .entry:has(a:is(:hover, :focus-visible)) .entry-end:not(.accepted) { color: var(--ink); }
    .work:is(:hover, :focus-visible) .article-art { color: var(--body); }
    .col-work:has(.work:hover, .paper:hover) :is(.work, .paper):not(:hover) { opacity: .4; }

    .link-mail:is(:hover, :focus-visible) span { color: var(--ink); }
    .social-links a:is(:hover, :focus-visible) .link-mark { fill: var(--accent); transform: translateY(-1px); }
    .social-links:has(a:hover) a:not(:hover) { opacity: .4; }

    .photo:hover img { transform: scale(1.05); }
    .theme-toggle:hover { color: var(--ink); }
}

/* narrow: everything in reading order */
@media (max-width: 900px) {
    .spread { display: block; padding: 48px 24px 32px; font-size: 14px; }
    .col { padding: 1.6lh 0 1.2lh; }
    .col::after { display: none; }
    .col-work > * { max-width: none; }
    .who { gap: 2ch; }
    .name { font-size: 3.2em; }
    .photo { width: 6.4em; }
    .work .article-art { font-size: min(1em, calc((100vw - 48px) / 43.2)); }
    .entry { flex-wrap: wrap; }
    .entry-dots { display: none; }
    .entry-title { width: 100%; }
}
@media (max-width: 680px) {
    .article-nav { padding-right: 23px; padding-left: 23px; }
    .article-main { padding: 44px 23px 64px; }
    .article-head { margin-bottom: 36px; }
    .article-body h2 { margin-top: 41px; }
    .article-body figure { overflow-x: auto; }
    .diagram { min-width: 540px; }
    .article-body .poster-figure { width: 100%; margin-left: 0; translate: none; overflow: visible; }
    .math-display { text-align: left; }
    .entry-end { white-space: nowrap; }
}

@media (pointer: coarse) {
    .social-links { margin-left: -3px; }
    .social-links a { padding: 8px 3px; }
    .theme-toggle { padding: 6px 8px; top: 8px; right: 8px; }
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .spread p a, .role a, .work, .paper, .work .entry-title, .entry-dots, .entry-end, .article-art, .social-links a, .photo img,
    .link-mark, .link-mail span, .article-body a, .article-nav a, .poster-link,
    .diagram .node, .diagram .accent-node,
    .diagram .line, .diagram .accent-line { transition: none; }
}
