Style guide for adm.io.
The tokens, type and components behind adm.io — the portfolio site you're looking at. Everything is driven by a single set of CSS variables that swap between light and dark — toggle the theme (top right) to see this page respond live, while the colour table below always shows both values side by side.
Every token carries two values — one for dark mode, one for light. They're referenced as var(--hk-*) and swap automatically with the theme, so each row below shows both side by side.
Surfaces & lines
--hk-bg
Page background
--hk-cta
CTA / lifted surface
--hk-panel
Panel surface (chat, tooltips)
--hk-head
Header / input bars
--hk-bubble
Bubble / chip / tile surface
--hk-line
Hairlines & borders
Text
--hk-ink
Primary text & headings
--hk-body
Body copy
--hk-muted
Muted labels / meta
--hk-faint
Faint captions / coordinates
--hk-onimg
Text set over imagery
Accent & state
--hk-blue
Accent — electric blue
--hk-photo-tint
Photography duotone tint
--hk-error
Error / alert
Three families: Fraunces for editorial display, Hanken Grotesk for interface and body, IBM Plex Mono for eyebrows, numerals and coordinates. Samples render in the active theme — toggle (top right) to see them in the other.
The recurring building blocks — labels, buttons, dividers, bullets, cards and tags — all theme-aware, shown here in the active theme.
Ask about Adam
Grounded surface for bubbles, tooltips and chips.
Cinematic, architectural photography carries the mood. Every story image has a paired light and dark frame that crossfades when the theme switches; work covers and the fine-art grid are tinted to the active theme instead.
Dark
LightHero
Full-bleed image behind the headline — the first impression and the loudest mood-setter.
Dark
LightAbout
An editorial band paired with the about statement.
Dark
LightContact CTA
Dissolves into the “Let’s build” panel along its left edge.
Dark
LightHow I work
A quiet accent beside the four working principles.




Work covers
Square covers for the Selected Work carousel — one per live product.




Photography
Fine-art grid — desaturated with a theme tint, colourises on hover; sourced from buddsbeachhouse.com.
A single 1240px content column on a 12-ish step rhythm, reflowing at three Tailwind breakpoints. The schematics below show how the shell rearranges as the viewport grows.
Hamburger opens a full-screen menu. Hero text sits over a darkened image; grids drop to 1–2 columns.
Inline nav links appear; work and photography grids go to 3 across; the hero still stacks.
Full nav, a side-by-side hero, 4-column grids, and the assistant can expand full-screen.
“Ask about Adam” is a streaming, CV-grounded assistant. It lives in three escalating states and uses the accent blue to mark anything the visitor said.
- 01Pulse — A blue gradient launcher with a ping dot, bottom-right.
- 02Floating — A 380px popover anchored to the launcher.
- 03Expanded — Desktop only — a full-screen frosted takeover that keeps the page visible behind it. State is shareable via ?chat=open|expanded.
Visitor turns use a translucent accent-blue bubble — the one moment the accent fills a surface.
Assistant turns sit on the neutral bubble surface; answers stream token-by-token with a pulsing caret.
The assistant is deliberately narrow. Its strongest safeguard isn't a filter — it's scope: the model is only ever handed a public CV, has no tools, and can reach no data or secrets, so there is nothing sensitive for a jailbreak to surface.
- A static, public CV / profile string
- Public project names & what Adam does
- The current conversation (max 12 turns)
- The OpenAI key (server-only, never shipped)
- Databases, analytics, admin or visitor data
- The internet, files or any tool calls
- Other pages' data or environment variables
- Scope first — Even a successful jailbreak reaches only a public CV — there is nothing private to extract.
- Server-owned framing — The system prompt is built and prepended on the server; the client can only send user / assistant turns.
- Input sanitised — Roles are whitelisted and content is length- and turn-capped before it ever reaches the model.
- Grounded + steered — The prompt forbids inventing facts and steers off-topic or adversarial questions back to Adam's work.
Honest note: there is no dedicated jailbreak classifier or output filter — the design leans on minimal scope and server-controlled framing rather than trying to out-prompt every adversarial input.