Spec, stylesheet, glitch script, Claude Code skill and the design canvas source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.6 KiB
5.6 KiB
Night Grid style guide
Instructions for building UIs (dashboards, tools, pages) in the Night Grid style: a dark neon HUD look in the spirit of near-future noir games. Dark ground, neon signal, hard edges.
- Stylesheet:
night-grid.css(same folder). Use its classes and--ng-*variables; don't redefine them. - Script:
night-grid.js(same folder, optional,defer). Drives the random glitch; nothing else needs JS. - Visual reference: https://claude.ai/artifact/AT2mCxMkeLFzkife1rAuLk (private; the spec below is complete without it).
Principles
- Signal over noise. About 70% of the screen is near-black void. Data glows; the background doesn't.
- Hard edges. No rounded corners, soft shadows or gradients. Panels get one 45° clipped corner (top-right) and 1px hairline borders.
- Color is meaning, never decoration. Yellow = act/focus. Cyan = info and live data. Red = danger. Green = OK.
- Diegetic data. Labels read like machine output: uppercase mono, IDs, timestamps,
//separators (01 // NETWORK,ALERT // DISK FULL).
Colors
| Token | Hex | Use |
|---|---|---|
--ng-void |
#050508 |
Page background |
--ng-panel |
#0E1016 |
Cards, panels |
--ng-raise |
#1C2029 |
Meter tracks, gridlines, hover |
--ng-line |
#2A2F3A |
1px borders, dividers |
--ng-text |
#E6E8EC |
Primary text (never pure white) |
--ng-soft |
#C3C8D1 |
Secondary body text |
--ng-dim |
#8A93A3 |
Labels, axis text |
--ng-yellow |
#FCEE0A |
Primary action, focus, page title |
--ng-cyan |
#02D7F2 |
Info, links, live data, chart series 1 |
--ng-red |
#FF003C |
Danger fills/borders, thresholds |
--ng-red-txt |
#FF3B5C |
Danger text (better contrast than --ng-red) |
--ng-green |
#00FF9F |
Nominal/success, sparingly |
Screen budget, roughly: void 70%, panel 15%, yellow 8%, cyan 4%, red 3%.
Typography
- UI and display: Rajdhani 500/600/700. Headings and buttons uppercase; anything longer than one line in sentence case.
- Data and labels: JetBrains Mono 400/600,
font-variant-numeric: tabular-numsfor every metric. - Labels: mono 12–13px, uppercase,
letter-spacing: 0.15em,--ng-dim. - Scale (px): 13, 15, 18 (body), 24, 32, 48, 72, 120. Body text at least 16px.
- Fonts:
https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;600;700&family=JetBrains+Mono:wght@400;600&display=swap
Shape and line
- Clipped corner:
clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%). 16px for cards, 24px for big sections, 12px for buttons. One cut per shape. - Borders 1px
--ng-line. Live/active dividers can be cyan. - Selection or focus: yellow 2px corner brackets or a 2px yellow outline.
- Section headings can end in a broken yellow dash: a long line, then 8px, then 4px segments.
- Diagonal structure: edges step at 45°. Use
.ng-ruleunder headings (thick bar stepping down into a hairline),.ng-edgefor a stepped band along a section's bottom (.ng-edge--hotmakes it yellow), and.ng-panel--notchedfor a panel with several cuts. One or two of these per screen; they frame, they don't fill.
Components (classes in night-grid.css)
| Component | Class | Notes |
|---|---|---|
| Panel | .ng-panel |
Clipped card |
| Button | .ng-btn + --primary / --info / --danger |
Min height 48px. One --primary per view |
| Tag | .ng-tag + --priority / --live / --ok / --breach |
Status chips |
| Meter | .ng-meter with 10 <i>, lit ones get .on |
Add .ng-meter--danger past a threshold |
| Alert | .ng-alert |
Red border, 8% red fill. Say the thing, the number and the time |
| Input | .ng-input |
Yellow underline on focus, red when aria-invalid="true" |
| Label | .ng-label |
Mono machine label |
| Data | .ng-data |
Mono, tabular numbers |
| Glow | .ng-glow |
Only on the single most important value per screen |
| Fold panel | <details class="ng-fold"><summary>Title</summary>…</details> |
Yellow corner chip with »: points down when folded, up when open. Native, keyboard-accessible, no JS |
| Glitch | .ng-glitch |
Marks a heading or value as a glitch candidate; night-grid.js glitches one at random every 6–14s |
| Scanlines | .ng-scanlines on <body> |
Optional; disabled with reduced motion |
A stat tile is a .ng-panel holding a .ng-label, a big .ng-data value (about 40px, unit at 18px in --ng-dim), a .ng-meter, and a short status line.
Charts
- Series 1 cyan, series 2 yellow, threshold/alert red. At most three series.
- Gridlines
--ng-raise, axis labels mono 12px--ng-dim. No chart background. - Square bars with 2px gaps. Lines 2px, no smoothing.
Motion
- Fast and stepped: 120ms,
linearorsteps(4). No easing bounces. - Glitch (skew, RGB split, sliced, 360ms) on a state change, plus an ambient glitch: one random
.ng-glitchelement every ~10s. Put.ng-glitchon 3–6 headings or key values, never on body text or controls. - Numbers tick up when they change; panels wipe in left to right.
- Respect
prefers-reduced-motion: no animation, no scanlines.
Accessibility
- Text contrast at least 4.5:1 (all text tokens above pass on
--ng-voidand--ng-panel). - Never use color alone: every state also has a label or icon.
- Real
<button>,<a>,<label>elements; touch targets at least 44px.
Do / Don't
Do
- One yellow call to action per view.
- Separate groups with empty space before adding lines.
- Keep everything dark: this style has no light theme.
Don't
- Rounded corners, soft shadows, gradients, emoji.
- Yellow text on cyan or red.
- Glow everything.
- Use any game's logos, fonts or UI assets. Inspired by, never copied.