Principles
Six rules. When in doubt, these win.
Neon is a fill.
By Day it never carries text. By Dusk it may, because every fill passes 4.5:1 on Midnight.
Ink does the talking.
One text colour, one muted, one accent for links. That is all the coloured text there is.
Every edge is 3px.
Borders, rules, outlines and shapes. It keeps the neon from melting together, and it keeps working when colour drops out.
Shadows by day, glow by night.
Depth is the one token that changes shape between modes. Everything else only swaps colour.
Tilt one thing per view.
A sticker, a badge, a burst. Two tilted things and the page looks dropped.
One job per shape.
Two buttons, two toggles, a badge, an avatar, a tile and one unicorn. Shapes never swap jobs.
Colour
Seventeen tokens. Same names in both modes; the values swap.
Dusk Midnight #160B2B
Dusk Dusk #24123F
Dusk Starlight #F6EEFF
Dusk Moonlight #B9A6D6
Dusk Moonlight #B9A6D6
Dusk Flamingo #FF4FD8
Dusk Midnight #160B2B
Dusk Starlight #F6EEFF
Dusk Flamingo #FF4FD8
Dusk Sunset #FF9F45
Dusk Lemon #FFE600
Dusk Lime #39E61A
Dusk Lagoon #3DE8FF
Dusk Ultraviolet #9B5CFF
Dusk Void #0E061D
Dusk Lemon #FFE600
Due Friday reads at a glance.
Lime on paper is 1.6:1. By Dusk, neon text is allowed: every fill passes 4.5:1 on Midnight.
| Pair | Where | Day | Dusk |
|---|---|---|---|
| --text / --bg | Body | 20.0 AAA | 16.7 AAA |
| --text / --surface | Cards | 18.1 AAA | 15.1 AAA |
| --text-muted / --bg | Secondary text | 8.0 AAA | 8.5 AAA |
| --text-muted / --surface | Secondary on cards | 7.2 AAA | 7.7 AAA |
| --accent-text / --bg | Links | 6.6 AA | 6.6 AA |
| --on-fill / --fill-1 | Primary buttons, errors | 5.9 AA | 6.6 AA |
| --on-fill / --fill-2 | Badges, warnings | 8.5 AAA | 9.2 AAA |
| --on-fill / --fill-3 | Notices | 15.8 AAA | 14.8 AAA |
| --on-fill / --fill-4 | Success | 11.9 AAA | 11.2 AAA |
| --on-fill / --fill-5 | Selection | 11.3 AAA | 12.7 AAA |
| --on-fill-6 / --fill-6 | Violet (avoid text) | 5.4 AA | 4.8 AA |
| --code-text / --code-bg | Code | 15.8 AAA | 15.6 AAA |
| --ring / --bg | Focus (needs 3:1) | 5.4 pass | 16.7 pass |
--fill-6 by Day is the one exception: ink on violet is 3.7:1, so violet takes white text (--on-fill-6). Keep words off it.
Type
Three families, seven sizes. Display is always capitals.
Headings and short shouts. Capitals, tight leading, 24px and up.
Body and UI. Rounded terminals keep the loud parts friendly.
Labels, tokens, metadata and code. 12px capitals, +0.08em.
Space
Eight steps on a 4px base. Nothing in between.
Shape & depth
Round corners, hard edges. Depth is the only thing that changes with mode.
Shapes
Two kinds: decoration, and fat shapes that do a job.
Most text buttons. Min height 48. Dense UI and long labels use the plain pill.
Like, with its count inside. Min 64 wide.
Favorite. Min 56. The smallest safe area in the set.
Counters, NEW, stamps. Never clickable; it rides on something that is.
People. Min 48.
Category pickers and launchers.
The mascot, and the one hero button. The label sits on the belly. Once per product: "Surprise me", "Start", "Let's go".
Min 200 wide; smaller and the horn and legs blur into a blob. Never a small icon.
Components
Real controls. Hover, press, Tab through them, click the toggles.
States. Hover brightens the fill. Pressed drops --depth and shifts --press (3px). Focus draws a --ring that follows the outline. Disabled goes dashed and muted, with no depth.
Cloud pills are fixed sizes in v0.1. Long or translated labels use the plain pill until the cloud can stretch.
Lab report
Due Friday · 3 pagesStart one and it shows up here.
Prose
Plain HTML inside .lisa-prose. Links are --accent-text; code is a dark well.
Keep the loud stuff in its lane
Colour carries state, never meaning on its own. Read the principles before adding a seventh neon, and highlight one phrase per block at most.
- Spectrum slabs top and bottom only
- One neon fill per component
- One tilt per view
The rainbow is the border. Ink does the talking.
.button {
background: var(--fill-1);
color: var(--on-fill);
border: var(--rule) solid var(--border);
border-radius: var(--radius-pill);
box-shadow: var(--depth-sm);
}
Use it
Four files. Link the stylesheet and the fonts, add class="lisa", and opt components in.
| File | What it is |
|---|---|
| index.html | This page. Every token and component, live, in both modes. |
| README.md | The rules and why they exist. Read it before designing anything new. |
| lisa.css | Drop-in stylesheet: tokens for Day and Dusk, .lisa-* components, prose, print. Inert until an element opts in. |
| tokens.json | The same tokens in the Design Tokens Community Group format, for design tools. |
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bungee&family=Nunito:wght@400;700;900&family=Space+Mono:wght@400;700&display=swap"> <link rel="stylesheet" href="lisa.css"> <body class="lisa"> <!-- Day, or Dusk when the OS is dark --> <html data-theme="dusk"> <!-- force a mode: "day" or "dusk" --> <button class="lisa-btn lisa-btn--primary">Save</button> <div class="lisa-alert lisa-alert--notice" role="status">Saved.</div>
Mark & print
The wordmark, the icon, and what survives paper.
The unicorn icon holds at 64px and up. At 32px it turns into a blob, so the favicon uses the sparkle.
Always prints in Day. White ground; glows and the airbrush sky drop out. Fills stay under ink. The spectrum slab prints as a solid ink bar, and every shape keeps its 3px outline, so nothing depends on colour.