mirror of
https://github.com/luxfi/design.git
synced 2026-10-30 16:58:57 +00:00
The CTO reversed the accent: "no gold in lux, only monochrome white and black, more severe and minimal than hanzo.ai". 0.1.0's archaeology was real but historical — every live Lux surface had already flattened that slot to white, and lux.network's repo carries an e2e asserting the page paints zero pixels in hue band 20-60. 0.1.0 climbed that fence. --lux-gold is deleted rather than parked. An unused brand-colour token is exactly what gets re-wired by accident. The light-theme bronze (#7E5A16) dissolves with it: monochrome has no hue to darken. Severity is not an adjective here, it is four measured values, each from @luxfi/[email protected] or from a headless render of the live surfaces: ground #000000 (Hanzo #0a0a0a) brand surface1, both product configs accent #ffffff (Hanzo #e4e4e7) brand accent1 — above the ink, not below lift one (Hanzo two) 73 cards measured at #0a0a0a hairline .08 (Hanzo .10) 286 of 331 painted edges Nothing is invented; every value is a rung of the inherited ladder. Only the decorative boundary was quieted — control, focus, selected and ring are untouched, because they tell a keyboard user where they are. Lux also withdraws the fourth permitted hue. --chrome-dot-yellow is hue 45.6, inside the fenced band, so a Lux window mock would have failed lux.network's e2e having never gone near the gold. Four things the gate could not see before, each found by adding the check: --lux-black was #0A0A0B — Hanzo's press-kit black wearing a Lux name after the hanzo- -> lux- rename, and not even grey. It paints the mark. assets/brand/hero-visualization.png was a full-spectrum rainbow, 39% saturated, in a card captioned "no warm gradients, no illustration style". The specimen cards captioned --border as #1f1f1f and --ring as #333 beside chips correctly painting the current tokens — fossils of the fork. And prompts/system.md still quoted the Hanzo brand hex. Gate: 26 checks. New — every token resolves achromatic in both themes except three named signals, each proven outside band 20-60; unreadable colour syntax fails rather than passes; specimen captions match the sheet; brand imagery is achromatic (PNG decoded in ~40 lines on node:zlib, no dependency). The .light rule is now value-shaped — exempt only if the value is a bare var() onto something that inverts — replacing a name-shaped --lux-* exemption that existed for a token now deleted. Verified: build green; the packed tarball rendered headless in both themes paints 0 saturated pixels of 8,780,800; eight mutations each fail the build and restore byte-identically. Co-authored-by: Hanzo Dev <[email protected]>
2.6 KiB
2.6 KiB
Rules — do / don't
The checklist. Grep it before you ship a Lux surface. Every "don't" maps to a token or pattern that makes the "do" trivial.
Color
| Do | Don't |
|---|---|
Use --background, --foreground, --surface-card, the --white-* ladder. |
Write a raw hex, rgb(), or hsl() in a component. |
Rank by opacity (--white-80 > --white-40). |
Invent an off-ladder step (12%, 37%). |
Add a hue only for --state-error, --state-online, --state-success, or a third-party logo. |
Color a button, gradient, or hero for decoration. |
| Leave the window-chrome dots monochrome. | Restore the yellow one — hue 45.6° is inside the band lux.network's e2e fences. |
Keep the accent white (--brand). |
Add gold. 0.1.0 did; 0.1.1 reversed it by CTO decision. |
| Design the dark surface first. | Treat light as primary. |
Type
| Do | Don't |
|---|---|
Use --font-sans / --font-mono and the --type-* roles. |
Add a third typeface or a raw font-size in px. |
| Sentence case for headings and buttons. | ALL CAPS bodies or Title Case Buttons (eyebrows excepted). |
Layout & spacing
| Do | Don't |
|---|---|
Constrain to --container-max / --container-prose; pad with --gutter*. |
Let content run full-bleed edge to edge. |
Space on the --space-* ramp. |
Hardcode padding: 13px. |
| Remove an element when it feels crowded. | Shrink the spacing to cram more in. |
Components
| Do | Don't |
|---|---|
| One primary (white) action per view; everything else outline or ghost. | Two competing primary buttons. |
Plain <a> / <Link> with className, or the shipped <Button>. |
<Button asChild> — it breaks the build under React 18 strict children. |
Elevation as a hairline border + --shadow-floating only when floating. |
Drop shadows on flat, in-flow cards. |
Motion
| Do | Don't |
|---|---|
Fade + --entry-rise, lux-fade-up, CSS-only hovers. |
Springs, bounce, parallax, autoplay carousels. |
Honor prefers-reduced-motion. |
Animate a transform on hover. |
Accessibility (non-negotiable)
| Do | Don't |
|---|---|
| Keep every body/background pair at WCAG AA, 16px. | Ship --white-30 text as body copy. |
Keep focus visible via --ring. |
outline: none without a replacement ring. |
| Make dialogs/menus Tab-reachable and Escape-closable. | Trap keyboard users. |
Give every <img> alt text; mark decorative SVG aria-hidden. |
Leave images unlabeled. |
The one test
Monochrome, true black, white type, color only as state. If the screenshot would look at home on lux.network, it passes. If it looks like a generic SaaS template, it fails.