mirror of
https://github.com/hanzoai/design.git
synced 2026-10-30 14:58:37 +00:00
The two woff2 under assets/fonts were placed by hand and renamed on disk only — their internal `name` table still read the family Zen was derived from. The @font-face rule wins for matching, so a browser painted Zen and hid it; anything that reads a font's own name instead — a font picker, a PDF embed, a design tool opening the file — reported the wrong typeface on every Hanzo surface. The fix is to stop authoring them here. @hanzo/font is where Zen is authored, so gen-tokens.mjs now copies its two variable faces on every run and the copy cannot drift from its author. Declaring rather than @import-ing stays, for the reason tokens/fonts.css already gives. Also drops the stale family name from the prose that prescribes type: the integration doc, the two prompts an agent reads before it designs anything, and the two type cards' subtitles.
docs — how to use the system
The design system is one idea applied without exception: Hanzo is monochrome, true black, white type, and color is a signal — never a decoration. Everything else is machinery in service of that idea.
If you remember one thing: import one file, then reach for a token instead of a literal. Do that and your surface is already 90% on-brand.
@import "@hanzo/design/styles.css";
The map
| You want | Go to |
|---|---|
| To wire the tokens into an app | integrate.md |
| The raw values (color, type, space, radius, motion, z, elevation) | ../tokens/ |
| A component and how to use it | ../components/ + its *.prompt.md |
| To see a rule rendered | ../guidelines/ specimen cards |
| An AI to generate an on-brand screen | ../prompts/ |
| The words — voice, taglines | ../content/ |
| The mark, wordmark, logos | ../assets/ |
Why it is built this way
- One import. A single
styles.csspulls the whole token layer in a fixed order. There is no partial setup to get wrong. - Tokens, not literals. Every value is a CSS custom property whose name matches hanzo.ai's own variables. Code copies between the app and this system 1:1, because they speak the same names.
- Dark by construction. Surfaces mount dark. Light is a
.lightoverride for the few brand and docs pages that need it. - Opacity is the palette. One neutral ladder plus an opacity ladder is the entire non-semantic color system. Rank reads as opacity. This is why Hanzo looks like Hanzo and not like a theme.
- The parts are self-contained. Components carry their own inline styles, so one drops into Next, Vite, Tamagui, or nothing and renders identically.
The one rule that overrides the rest
When a decision is unclear, return to the atom. Monochrome, true black, white type. If the work reinforces it, keep the work. If it doesn't, change the work.