# 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 1. **Signal over noise.** About 70% of the screen is near-black void. Data glows; the background doesn't. 2. **Hard edges.** No rounded corners, soft shadows or gradients. Panels get one 45° clipped corner (top-right) and 1px hairline borders. 3. **Color is meaning, never decoration.** Yellow = act/focus. Cyan = info and live data. Red = danger. Green = OK. 4. **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-nums` for 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-rule` under headings (thick bar stepping down into a hairline), `.ng-edge` for a stepped band along a section's bottom (`.ng-edge--hot` makes it yellow), and `.ng-panel--notched` for 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 ``, 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 | `
Title…
` | 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 `` | 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, `linear` or `steps(4)`. No easing bounces. - Glitch (skew, RGB split, sliced, 360ms) on a state change, plus an ambient glitch: one random `.ng-glitch` element every ~10s. Put `.ng-glitch` on 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-void` and `--ng-panel`). - Never use color alone: every state also has a label or icon. - Real `