Design
How this notebook is drawn. 105 design tokens, one ink, one diagram language. Everything below is read from the code at build time, so it can't drift.
Paper & ink
Light theme is cream paper, dark theme is a blueprint. One ink for structure, one signal colour for what matters.
--bg#fafaf7 · #0b1424--surface#ffffff · #101c30--text#1c1c1e · #e6ebf3--muted#6b6b70 · #8d9bb1--border#e6e5df · #1f2e48--accent#1967d2 · #8ab4f8--story-1#1f4fbf · #8ab4f8--story-2#1f4fbf · #8ab4f8--story-3#1f4fbf · #8ab4f8--ink#1f4fbf · #8ab4f8--signal#c2410c · #ff9f5a--paper-linergba(31, 79, 191, 0.07) · rgba(138, 180, 248, 0.07)--watermark-inkrgba(31, 79, 191, 0.09) · rgba(138, 180, 248, 0.1)--panel-bg#14295c · #111c38--panel-text#f3f5fb · #eef2fb--panel-mutedrgba(243, 245, 251, 0.66) · rgba(238, 242, 251, 0.62)--panel-linergba(243, 245, 251, 0.08) · rgba(238, 242, 251, 0.06)--panel-edgergba(243, 245, 251, 0.22) · rgba(238, 242, 251, 0.18)--accent-softrgba(25, 103, 210, 0.08) · rgba(138, 180, 248, 0.12)--on-accent#ffffff · #0b1424--warn#9a6212 · #fbbf24--off#9a9aa0 · #5c636e--scrimrgba(0, 0, 0, 0.35)--overlayrgba(5, 6, 8, 0.94)--on-overlay#ffffff--on-overlay-mutedrgba(255, 255, 255, 0.15)--shadow0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.06) · 0 0 0 1px var(--border)--shadow-lg0 24px 80px rgba(0, 0, 0, 0.18) · 0 24px 80px rgba(0, 0, 0, 0.5)--term-bg#16181d · #08090b--term-text#d7dae0--term-accent#8ab4f8--term-muted#7d8590 · #6e7681--term-warn#fbbf24--term-linergba(255, 255, 255, 0.06)--term-chiprgba(255, 255, 255, 0.05)--term-chip-borderrgba(255, 255, 255, 0.1)--term-dot-close#ff5f57--term-dot-min#febc2e--term-dot-max#28c840
Type
Sans: for reading. Google Sans.
Mono: labels, data, code.
Handwriting: notes only
- Aa
--text-xs0.75rem - Aa
--text-sm0.875rem - Aa
--text-base1rem - Aa
--text-lg1.125rem - Aa
--text-xl1.25rem - Aa
--text-2xl1.5rem - Aa
--text-h3clamp(1.125rem, 1.4vw, 1.3rem) - Aa
--text-diagram13px - Aa
--text-diagram-sm10.5px - Aa
--text-diagram-note19px - Aa
--text-noteclamp(1.15rem, 1.5vw, 1.4rem) - Aa
--text-displayclamp(2.1rem, 4.6vw, 3.6rem) - Aa
--text-titleclamp(1.75rem, 3.2vw, 2.4rem) - Aa
--text-watermarkclamp(4rem, 14.5vw, 16rem) - Aa
--text-watermark-smclamp(4rem, 9vw, 7.5rem)
Diagram language
Every drawing is data in content/diagrams.js, drawn by lib/diagram.js. The same description makes the figure, the watermark behind a section and share images.
Space
--space-10.25rem--space-20.5rem--space-30.75rem--space-41rem--space-51.25rem--space-61.5rem--space-82rem--space-102.5rem--space-123rem--space-164rem--space-246rem
Radius
--radius-xs6px--radius-sm12px--radius20px--radius-lg28px--radius-pill999px
Motion
--easecubic-bezier(0.22, 1, 0.36, 1)--dur-fast0.15s--dur0.3s--dur-slow0.6s--dur-draw1.1s--stagger-draw35ms
Size
--max1040px--max-prose760px--guttervar(--space-4)--nav-h52px--size-control2.5rem--size-control-sm2.125rem--size-badge3.5rem--size-brand1.125rem--tabbar-h3.75rem--size-portraitclamp(13rem, 22vw, 20rem)--size-story-wclamp(9rem, 17vw, 14rem)--size-story-h8.5rem--size-story-h-sm5.5rem--size-story-band7.5rem--size-story-sideclamp(14rem, 24vw, 20rem)--size-portrait-sm10rem--size-paper32px--size-watermarkclamp(22rem, 46vw, 44rem)--size-marginclamp(11rem, 18vw, 15rem)
Layer
--z-backdrop-1--z-rail30--z-nav50--z-panel60--z-tabbar80--z-console95--z-palette100--z-toast150--z-egg200--z-lightbox300
Studies
Every UI experiment becomes a sketch: before, after, and what I learned. Captured with npm run sketch.
Decisions
One entry per design decision: what changed, why, and what I learned. Newest first.
Bigger visual changes also get a Sketch entry in the Lab with a before/after pair (npm run sketch).
2026-10-02 · Every experiment leaves a record
UI changes now come with a before/after Sketch, captured by one command (npm run sketch -- <slug> before|after)
and shown with a comparison slider. The first one is "One grid, one ink".
Learned: the habit only sticks if recording it is cheaper than skipping it.
2026-10-02 · Write the diagram, the site draws it
Diagrams can now be plain text (You (user) -> DNS : lookup) and the layout is automatic, so a new teardown can start
from a GitHub issue on my phone. The same text becomes the entry's figure and its share image.
Learned: automatic layout only has to be good at chains: most systems I care about are a request moving through hops.
2026-10-02 · Diagrams as code
Every drawing now starts as data in content/diagrams.js and is drawn by one engine (lib/diagram.js).
The same description renders the entry figure, the faint watermark behind a section and, later, share images.
Learned: a small visual language (box, store, cloud, user, one lit path, handwritten notes) is enough for most
systems, and consistency comes for free when nothing is drawn by hand.
2026-10-02 · Calm is fast
Scrolling the home page kept a phone's main thread 89% busy. Switching parts off one at a time found the cause: endless animations that kept running off screen (the infrastructure map) and a looping highlight on the drawings. Pausing the first off screen and removing the second brought it to 20%. Learned: measure before guessing. The frosted header I suspected first was not the problem.
2026-10-02 · One grid, one ink
The page had a grid on the paper and another grid inside every card, plus a blue-violet-teal gradient on drawings.
Now the paper is the only grid and drawings use a single ink colour, with --signal reserved for what matters.
Learned: texture works once. Repeated, it turns into noise.
2026-10-02 · A notebook, not a résumé
The site moves from a hiring page to a lab notebook: builds, teardowns and UI sketches, with a quiet colophon for who I am. The craft should show in the details rather than in a list of claims.
