KAPPA OS

Version 1.0 · 19 tokens

A portfolio site
disguised as a
miniature operating system.

Everything below is the working vocabulary of KAPPA OS — the colours, faces, radii and rules the desktop is actually built from. The components are the live imports, not pictures of them, and every value resolves from the same custom property the OS reads, so this page cannot quietly fall out of step with it.

The bar for the codebase is that it behaves like a real OS rather than a page that looks like one. Where a decision was between simpler to build and how the real thing behaves, the real thing won — and that is what most of these notes are recording.

01

Principles

Five rules. Each one is here because it was broken first, and the break shipped.

Monochrome, flat, engineered

Nothing OS-inspired. Colour lives only in tiny functional accents and never in the chrome — the moment a surface takes a hue it stops reading as a machine.

Tokens only

Reach for text-ink-soft or bg-[color:var(--card)], never a hex. A hex is a value that cannot follow the theme, and it will be found in dark mode by a visitor rather than by you.

Depth is tone, not borders

A card is one tone step deeper than the surface it sits on. Where a line is genuinely needed it is --line, a hairline, and it is the exception.

No shadows as decoration

The only elevation in the system is .floating on window chrome, and it deepens on focus. A shadow that isn't saying which surface is in front is noise.

Everything is drawn

No images for chrome, no icon fonts — SVG paths and CSS. Sounds are synthesised at runtime; there are no audio files anywhere in the project.

02

Colour

Two scales and a hairline carry the entire interface. The accent is the only hue, it is the visitor’s to choose, and it appears only where the interface is answering them.

Ink

Text and strokes

--ink

Body text, glyph strokes, anything meant to be read first.

--ink-soft

Secondary copy and metadata — present, not competing.

--ink-faint

Labels at rest, placeholder text, a disabled control.

Surface

Depth, in tone steps

--canvas

The page itself. Everything else is measured against it.

--card

A window body — one tone step deeper than the canvas.

--card-deep

A card inside a window, and the pressed state of a button.

--pill

Raised controls: the dock, buttons, sort bars.

--canvas-dot

The graph-paper dot in the default wallpaper.

The scale, nested

canvas

card

card-deep

pill

Structure

--line

The hairline, and the only border in the system. Reach for a tone step first.

Accent

Functional only

--accent

Whichever of the four the visitor picked. Focus rings, switches, selection.

--accent-red

The default.

--accent-green

--accent-blue

--accent-amber

Live — this sets the accent for the whole OS

Device

Outside the theme

--terminal-green

· fixed in both themes

Green-on-black widget text.

--vfd-amber

· fixed in both themes

A lit segment on the Tunes display and the boot screen. One token, so the two can't drift.

--vfd-amber-dim

· fixed in both themes

The same segment unlit — a VFD shows you the segments it isn't using.

--danger

· fixed in both themes

The close circle on hover, and every destructive action that borrowed it — Finder's delete, Settings' danger zone.

--ok

· fixed in both themes

The zoom square on hover, and the copy-not-move badge.

The chrome never takes an accent. A window title bar in the visitor’s blue is a themed application; the same bar in ink with a blue focus ring is a machine that answered them. The accent marks where the interface is responding — focus, a selection, a switch that is on — and nowhere else.

03

Typography

Four faces, each with one job. The body face is the monospace — this is a machine, and it reads like one.

Dot matrix

Doto · wordmark and clock only

KAPPA OS

09:41:07

Family

Doto

Two uses in the whole OS, and no third. It is the machine saying its own name — spend it anywhere else and it stops meaning that.

Label

Geist Mono · UI labels and metadata

Desktop · Projects · 14 items

Modified 12 Aug · 2.4 MB

Size

11px

Transform

uppercase

Tracking

0.14em

Uppercase at 11px sets too tight by default; the tracking is what makes it a label rather than a shout.

Display

Lustria · display copy

The single deliberate touch of warmth.

Family

Lustria

Stretch

95%

Tracking

-0.01em

A serif in an engineered system is a considered exception, and it is kept to display sizes — it never sets a paragraph of interface copy.

Body

Geist Mono · everything else

Body text is the mono face. It is doing the ordinary work: file names, notes, panel copy, this paragraph. Monospace for running text is usually a mistake, and it is the right one here — the whole conceit is that you are reading a machine.

Family

Geist Mono

Sizes

11 / 12 / 13px

Three sizes carry the interface. A fourth is nearly always a layout problem wearing a type solution.

04

Radius

Three radii and one drawn curve. A corner says what kind of object it is, so the set stays small enough to mean something.

Window

.floating

14px

Every floating surface: windows, panels, viewers, the shell.

Card

.card

4px

Content blocks inside a window. Small enough to read as a cut, not a lozenge.

Pill

.pill, .btn

9999px

Controls that are pressed: buttons, switches, the dock, dots.

App icon

SquircleIcon

squircle

A drawn path, not a radius. A rounded corner and this curve disagree by about a pixel at dock size, which was visible when half the icons used each.

05

Elevation

One shadow, three states. It exists to say which window you are talking to, and it is not used for anything else.

Focus states

.floating

Focused

The window you are in.

Resting

Open, not focused.

Receded

Unfocused and slightly see-through — which counts as translucency, so that setting turns it off.

Dark mode gets its own pair of shadows rather than the same ones at a higher opacity. A shadow is the absence of light, and on a near-black canvas there is very little to take away — the light-mode values simply disappear.

06

Motion

Quick and mechanical. No bounce, no spring, 60–240ms. If an animation draws attention to itself, it is wrong.

Every duration in the system

window-in

140ms · linear

A window opening: 6px of travel and a fade.

page-in

120ms · linear

A document arriving inside a window that is already open — half the travel, because it is the smaller event.

Button

120ms · linear

Background on hover, opacity on the solid variant.

Dock item

120ms · linear

The 3px lift under the cursor.

Switch

150ms · default

Track colour and knob travel together.

Elevation

240ms · ease

A window's shadow deepening as it takes focus. The slowest thing here, because it is the one nobody is waiting on.

Screensaver in

700ms · ease-out

The machine going quiet. The one deliberate exception — it is the only transition that isn't answering a gesture.

window-in, live

140ms linear

07

Components

These are the live imports from the OS, not reproductions. Three copies of the same markup is how the traffic lights drifted apart the first time.

Traffic lights

TrafficLights.tsx

Close is a circle, minimise a downward triangle, zoom a square. At rest the outlines sit in --ink-faint at 40%, so the cluster recedes into the titlebar; hover it and all three colour at once, because the hover group is the row rather than the mark. Unavailable lights render per inert: hidden, blank (the shape, uncoloured) or dim (own colour at 30%).

Window chrome

Window.tsx

Untitled

14px radius, no border, a hairline under the title bar, and the focused shadow. Every floating surface in the OS is this same frame.

Switch

SettingsPanel.tsx

The off track is ink at 18%, not a grey — it has to stay visible on both the card and the canvas, and a fixed grey can only manage one of them.

Buttons

Pill radius throughout. The solid variant fades on hover rather than shifting colour, because it is already ink and there is nowhere darker to go.

App icons

SquircleIcon.tsx

Solid ink, thin line glyphs, and the squircle path rather than a border radius. The corner reaches 34% along each edge, and anything sitting concentrically around an icon derives its own radius from that instead of guessing.

Cards and pills

Card

4px, no border

Pill

Raised control

Neither carries a line. The card is a tone step down, the pill a tone step up — that difference is the whole elevation model outside window chrome.

08

Stacking

One z-order, and a fixed set of bands above it. Every floating surface takes its z from nextZ() and calls it again on focus, so clicking anything brings it to the front.

Reserved bands

Every floating surface

100+

Windows, Finder, viewers, panels — all from nextZ(), all re-stamped on focus.

Context menus and their scrim

6000 / 6001

The dock

7000

Above menus, which is why a menu anchors to the top of the dock pill rather than to the pointer.

Drag ghosts

9000

An icon mid-drag has left the stack it came from.

Modal dialogs

9500

The blue screen, cover games

9990

Pretending to have stopped covers everything…

The screensaver

9995

…resting covers that…

The boot screen

10000

…and only starting up outranks resting.

Never invent a separate band. A viewer that gave itself its own range is what made the SNAP window unable to rise above a photo — both were “on top”, of different things.

09

Sound

Feedback, never decoration. Seven cues cover the whole OS, all synthesised at runtime — there are no audio files in the project.

The vocabulary

Click to play

A window opens.

Something is put down.

A drop resolved.

A drop was refused.

A switch changed.

A light touch — clearing a field, a minor control.

The machine is available: the end of boot, and waking.

Reuse this vocabulary rather than adding to it. Seven sounds a visitor can learn is a language; twelve they can’t is furniture noise. Volume and mute are governed globally from Settings, so these respect whatever the OS is set to.

10

Exceptions

Two surfaces are allowed their own idiom, and a third would be a decision to argue for rather than to assume.

Tunes

Skeuomorphic

88:8802:41

A late-80s deck rendered as a physical object rather than a document: brushed aluminium, an amber VFD, milled grooves, keys that travel a pixel under the finger. The unlit segments are drawn behind the lit ones — showing you the segments it isn’t using is most of what makes a VFD read as one.

kappash

Phosphor

kappash 1.0
> COLOR AMBER
>

A phosphor tube: green on black, scanlines, bloom, a block cursor sitting on the character it will overwrite. The visitor sets its finish from the shell itself, because how a device’s screen is set up answers to the person using it and not to the desktop theme.

Both keep their finish in both themes, because a real device doesn’t repaint itself when the desktop theme flips. Both stop at the content edge — the window around them is the ordinary OS chrome. Neither idiom leaks anywhere else.