tokens: re-emit @hanzo/tokens as styles/variables.css, drop the bespoke palette

variables.css was a hand-authored palette that had drifted from the system — a
purple accent, a Zen type stack, blue/amber status hues, its own surface blacks.
It is now @hanzo/tokens' generated bundle, re-emitted by scripts/gen-variables.mjs,
so the Go dashboards that vendor this sheet (ci/cd/git) share the one monochrome
palette. A short compatibility block aliases the legacy names those consumers
still reference (--hanzo-accent -> the ink, --error/--success -> the state hues,
--border-hairline -> --border, ...) onto the generated tokens, so nothing that
links this sheet stops resolving. Edit @hanzo/tokens src/theme.ts and run `pnpm gen`.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-01 12:19:28 -07:00
co-authored by Hanzo Dev
parent a94d5d54ec
commit 04c919c4d9
4 changed files with 300 additions and 214 deletions
+8
View File
@@ -24,6 +24,14 @@ brand.docsDomain; // 'docs.hanzo.ai'
The Hanzo palette is **pure monochrome** (black + white, Vercel/Linear style) — The Hanzo palette is **pure monochrome** (black + white, Vercel/Linear style) —
no color accent. `brand.json` is canonical: names, domains, socials, theme. no color accent. `brand.json` is canonical: names, domains, socials, theme.
**CSS variables come from [`@hanzo/tokens`](https://git.hanzo.ai/hanzoai/ui).**
`styles/variables.css` is NOT hand-authored — it is that package's generated
bundle, re-emitted by `scripts/gen-variables.mjs` (plus a thin compatibility block
for legacy names the Go dashboards still reference). To change a value, edit
`@hanzo/tokens` `src/theme.ts`, run `pnpm --filter @hanzo/tokens gen-css`, then
`pnpm gen` here. Go surfaces (`ci`/`cd`/`git` dashboards) vendor this sheet, so
the whole estate shares one palette.
## Social-card toolkit ## Social-card toolkit
One layout engine, **any brand**. Zero-dependency SVG — no browser/canvas. Same One layout engine, **any brand**. Zero-dependency SVG — no browser/canvas. Same
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hanzo/brand", "name": "@hanzo/brand",
"version": "1.4.8", "version": "1.4.9",
"packageManager": "[email protected]", "packageManager": "[email protected]",
"description": "Official brand assets and design system for Hanzo AI", "description": "Official brand assets and design system for Hanzo AI",
"main": "dist/index.js", "main": "dist/index.js",
@@ -82,7 +82,8 @@
"brand.json" "brand.json"
], ],
"scripts": { "scripts": {
"build": "tsup src/index.ts src/loader.ts src/hero.ts src/cli.ts src/brand-id.ts src/registry.ts src/marks.ts --format cjs,esm --dts --clean", "gen": "node scripts/gen-variables.mjs",
"build": "pnpm gen && tsup src/index.ts src/loader.ts src/hero.ts src/cli.ts src/brand-id.ts src/registry.ts src/marks.ts --format cjs,esm --dts --clean",
"dev": "tsup src/index.ts src/loader.ts src/hero.ts src/cli.ts src/brand-id.ts src/registry.ts src/marks.ts --format cjs,esm --dts --watch", "dev": "tsup src/index.ts src/loader.ts src/hero.ts src/cli.ts src/brand-id.ts src/registry.ts src/marks.ts --format cjs,esm --dts --watch",
"lint": "eslint src", "lint": "eslint src",
"type-check": "tsc --noEmit", "type-check": "tsc --noEmit",
+70
View File
@@ -0,0 +1,70 @@
// gen-variables.mjs — styles/variables.css is @hanzo/tokens, re-emitted.
//
// @hanzo/brand does not author its own palette any more. The values come from
// @hanzo/tokens (src/theme.ts), the one place the estate's colours, radii, type
// and spacing live, and this script republishes that generated bundle as a plain
// custom-property sheet the Go surfaces link or embed (ci/cd/git dashboards). One
// edit in @hanzo/tokens propagates to React (the TS), to @hanzo/design (its CSS),
// and here — nothing retyped, nothing to drift.
//
// A short compatibility block follows the bundle: the legacy @hanzo/brand names a
// few consumers still reference, each aliased onto a generated token so it keeps
// resolving while the value converges on the system. New code uses the token
// names from the bundle; the aliases are a bridge, not a second palette.
import { readFileSync, writeFileSync, existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { createRequire } from 'node:module'
import { dirname, join } from 'node:path'
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
const require = createRequire(import.meta.url)
function resolveBundle() {
const candidates = []
try { candidates.push(require.resolve('@hanzo/tokens/css')) } catch {}
candidates.push(join(root, '..', 'ui', 'pkgs', 'tokens', 'dist', 'tokens.css'))
for (const c of candidates) if (c && existsSync(c)) return c
throw new Error('gen-variables: @hanzo/tokens/css (dist/tokens.css) not found — build @hanzo/tokens first')
}
const src = resolveBundle()
const bundle = readFileSync(src, 'utf8')
// The bundle's own header names its generator; drop it, this file has its own.
.replace(/^\/\*[\s\S]*?\*\/\s*/, '')
.trim()
const header = `/**
* @hanzo/brand — CSS custom properties.
*
* AUTO-GENERATED by scripts/gen-variables.mjs from @hanzo/tokens — DO NOT EDIT.
* Edit the token in @hanzo/tokens src/theme.ts and re-run \`pnpm gen\` here (which
* regenerates from the freshly built @hanzo/tokens bundle).
*
* Hanzo is monochrome — one hue through an opacity ladder, dark by default.
* Usage: @import '@hanzo/brand/styles/variables.css';
* or: <link rel="stylesheet" href="https://unpkg.com/@hanzo/brand/styles/variables.css">
*/`
const compat = `
/* ——— compatibility aliases ———
Legacy @hanzo/brand names, each aliased onto a generated token so existing
consumers keep resolving while the value converges on the one system. Prefer
the token names above in new code. */
:root{
--border-hairline:var(--border);
--border-hairline-strong:var(--border-strong);
--radius-card:var(--radius);
--error:var(--state-error);
--success:var(--state-success);
--warning:#f59e0b; /* build-status amber, sibling of --chrome-dot-yellow */
--warning-light:#fcd34d;
--text-muted:var(--text-tertiary);
/* The one accent is the ink itself — monochrome, no purple. */
--hanzo-accent:var(--foreground);
--hanzo-accent-muted:var(--muted-foreground);
--hanzo-accent-soft:var(--white-10);
}
`
writeFileSync(join(root, 'styles', 'variables.css'), `${header}\n\n${bundle}\n${compat}`)
console.log(`gen-variables: wrote styles/variables.css from ${src}`)
+219 -212
View File
@@ -1,235 +1,242 @@
/** /**
* @hanzo/brand CSS Variables * @hanzo/brand — CSS custom properties.
* *
* Hanzo is monochrome — the brand is ink, paper, and a neutral grayscale. * AUTO-GENERATED by scripts/gen-variables.mjs from @hanzo/tokens — DO NOT EDIT.
* There is no brand hue; the brand color is the ink (dark) / paper (light). * Edit the token in @hanzo/tokens src/theme.ts and re-run `pnpm gen` here (which
* regenerates from the freshly built @hanzo/tokens bundle).
* *
* Usage: * Hanzo is monochrome — one hue through an opacity ladder, dark by default.
* @import '@hanzo/brand/styles/variables.css'; * Usage: @import '@hanzo/brand/styles/variables.css';
* or link: <link rel="stylesheet" href="https://unpkg.com/@hanzo/brand/styles/variables.css"> * or: <link rel="stylesheet" href="https://unpkg.com/@hanzo/brand/styles/variables.css">
*/ */
:root { /* Hanzo design tokens — colour + radius + type + spacing. The full bundle. */
/* ===== Hanzo Brand (Monochrome: Hanzo Black ↔ Hanzo White) ===== */
--hanzo-black: #0a0a0b;
--hanzo-black-rgb: 10, 10, 11;
--hanzo-white: #ffffff;
--hanzo-white-rgb: 255, 255, 255;
--hanzo-mono-50: #fafafa;
--hanzo-mono-100: #f5f5f5;
--hanzo-mono-200: #e5e5e5;
--hanzo-mono-300: #d4d4d4;
--hanzo-mono-400: #a3a3a3;
--hanzo-mono-500: #737373;
--hanzo-mono-600: #525252;
--hanzo-mono-700: #404040;
--hanzo-mono-800: #262626;
--hanzo-mono-900: #171717;
--hanzo-mono-950: #0a0a0a;
/* ===== Accent — the ONE Hanzo accent: PURPLE (palette = White · Gray · Purple). :root{
The monochrome base stays (primary action = white, neutrals = gray); purple is color-scheme:dark;
the single interactive/brand accent — links, active, focus, selection. NO blue,
green, or orange. White-label tenants override --hanzo-accent per host so
lux/zoo/pars never inherit Hanzo purple. ===== */
--hanzo-accent: #8b5cf6; /* violet-500 */
--hanzo-accent-hover: #7c3aed; /* violet-600 */
--hanzo-accent-muted: #a78bfa; /* violet-400 — accent text on dark */
--hanzo-accent-soft: rgba(139, 92, 246, 0.12); /* subtle fill / selected row */
--hanzo-accent-rgb: 139, 92, 246;
/* ===== Layered surface blacks (Builder v2 — no gray panels; each subtly different) ===== */ /* ——— base neutral ladder ——— */
--surface-0: #080808; /* app background */ --neutral-50:#FAFAFA;
--surface-1: #0d0d0d; /* panels */ --neutral-100:#F5F5F5;
--surface-2: #111111; /* raised */ --neutral-200:#E5E5E5;
--surface-3: #171717; /* controls / hover */ --neutral-300:#D4D4D4;
--neutral-400:#A3A3A3;
--neutral-500:#737373;
--neutral-600:#525252;
--neutral-700:#404040;
--neutral-800:#262626;
--neutral-900:#171717;
--neutral-950:#0A0A0A;
--pure-black:#000000;
--pure-white:#FFFFFF;
--hanzo-black:#0A0A0B;
--hanzo-white:#FFFFFF;
/* ===== Hairline border — 1px, almost invisible (no thick outlines) ===== */ /* ——— the opacity ladder: the real palette ——— */
--border-hairline: rgba(255, 255, 255, 0.06); --white-03:rgb(255 255 255 / .03); /* the raised fill */
--border-hairline-strong: rgba(255, 255, 255, 0.1); --white-05:rgb(255 255 255 / .05);
--white-06:rgb(255 255 255 / .06);
--white-08:rgb(255 255 255 / .08);
--white-10:rgb(255 255 255 / .10);
--white-14:rgb(255 255 255 / .14); /* selection wash */
--white-15:rgb(255 255 255 / .15);
--white-16:rgb(255 255 255 / .16);
--white-18:rgb(255 255 255 / .18); /* selection tint */
--white-20:rgb(255 255 255 / .20);
--white-22:rgb(255 255 255 / .22);
--white-30:rgb(255 255 255 / .30);
--white-40:rgb(255 255 255 / .40);
--white-45:rgb(255 255 255 / .45); /* the dimmest ink */
--white-55:rgb(255 255 255 / .55);
--white-60:rgb(255 255 255 / .60);
--white-78:rgb(255 255 255 / .78);
--white-80:rgb(255 255 255 / .80);
--white-92:rgb(255 255 255 / .92); /* body ink */
/* ===== Semantic radius (Builder v2): cards 8 · controls/toolbar 10 · preview/panels 12 ===== */ /* ——— semantic aliases (dark, the default) ——— */
--radius-card: 0.5rem; /* 8px */ --background:#0a0a0a;
--radius-control: 0.625rem; /* 10px — buttons, toolbar, inputs */ --foreground:#fafafa;
--radius-panel: 0.75rem; /* 12px — preview, large panels */ --card:#0f0f0f;
--card-foreground:#fafafa;
--popover:#0f0f0f;
--popover-foreground:#fafafa;
--primary:#fafafa;
--primary-hover:#e5e5e5;
--primary-foreground:#0a0a0a;
--secondary:#262626;
--secondary-hover:#333333;
--secondary-foreground:#fafafa;
--muted:#171717;
--muted-foreground:#a3a3a3;
--accent:#262626;
--accent-foreground:#fafafa;
--destructive:var(--state-error);
--destructive-hover:#dc2626; /* red-600 — deepens under the cursor */
--destructive-foreground:#fafafa;
/* ===== Semantic type roles (Builder v2): heading 20 · body 14 · secondary 12 ===== */ /* ——— boundaries — ONE ladder, cut from alpha, graded by duty ——— */
--text-heading: 1.25rem; /* 20px @ 600 */ --border:var(--white-10); /* the hairline */
--text-body: 0.875rem; /* 14px @ 400 */ --border-strong:var(--white-16); /* hover, emphasis */
--text-secondary: 0.75rem; /* 12px @ 400/500 */ --border-control:var(--white-15); /* a control's resting edge */
--border-focus:var(--white-22); /* that control, focused */
--border-selected:var(--white-30); /* the thing currently CHOSEN */
--input:var(--border-control); /* shadcn `border-input` — a control */
--ring:var(--white-40); /* the focus indicator — 3:1 non-text contrast */
--ring-halo:var(--white-10); /* the soft halo outside the ring */
--brand:#e4e4e7;
--brand-foreground:#09090b;
--brand-muted:#a3a3a3;
--black:#000000;
--white:#fafafa;
--selection:var(--white-20);
/* ===== Semantic Aliases (monochrome; flips with scheme) ===== */ /* ——— glass: the lift ——— */
--brand: var(--hanzo-black); --glass:var(--white-05);
--brand-light: var(--hanzo-mono-800); --glass-strong:var(--white-08);
--brand-dark: #000000;
--brand-hover: var(--hanzo-mono-900);
--brand-secondary: var(--hanzo-mono-600);
/* ===== Dark Theme Backgrounds ===== */ /* ——— surface recipes ——— */
--bg-primary: #0a0a0a; --surface-page:var(--background);
--bg-secondary: #141414; --surface-card:rgb(38 38 38 / .5); /* -> #181818 on the page */
--bg-tertiary: #1a1a1a; --surface-card-emphasis:rgb(38 38 38 / .75); /* -> #1f1f1f — featured */
--bg-card: rgba(23, 23, 23, 0.5); --surface-card-quiet:rgb(38 38 38 / .35); /* -> #141414 — story cards */
--surface-overlay:rgb(23 23 23 / .92); /* dropdown / popover panels */
--surface-header:rgb(0 0 0 / .7); /* fixed nav, with backdrop blur */
--surface-scrim:rgb(0 0 0 / .8); /* the dialog / sheet backdrop */
/* ===== Light Theme Backgrounds ===== */ /* ——— the numeric surface ladder ——— */
--bg-light: #ffffff; --surface-0:var(--background);
--bg-light-secondary: #fafafa; --surface-1:var(--card);
--bg-light-tertiary: #f5f5f5; --surface-2:var(--muted);
--surface-3:var(--secondary);
/* ===== Borders ===== */ /* ——— text ranks — a graded ramp, not one flat white ——— */
--border: #262626; --text-primary:#fafafa;
--border-light: #e5e5e5; --text-secondary:var(--white-78);
--border-focus: var(--hanzo-black); --text-tertiary:var(--white-55);
--text-helper:var(--muted-foreground);
--text-disabled:var(--white-30);
/* ===== Text Colors (Dark Theme) ===== */ /* ——— the ONLY permitted hues (DESIGN.md §2.4) ——— */
--text-primary: #fafafa; --state-error:#ef4444; /* red-500 — destructive / blocking error */
--text-secondary: #a3a3a3; --state-error-text:#fca5a5; /* red-300 */
--text-muted: #737373; --state-error-bg:rgb(239 68 68 / .1);
--text-disabled: #525252; --state-online:#4ade80; /* green-400 — live status dot */
--state-success:#22c55e; /* green-500 — "Free" / "Save N%" callouts */
--chrome-dot-red:rgb(239 68 68 / .6);
--chrome-dot-yellow:rgb(234 179 8 / .6);
--chrome-dot-green:rgb(34 197 94 / .6);
/* ===== Text Colors (Light Theme) ===== */ /* ——— radius ——— */
--text-light-primary: #0a0a0b; --radius:0.5rem;
--text-light-secondary: #525252; --radius-sm:0.375rem; /* rounded-md — buttons, inputs */
--text-light-muted: #737373; --radius-md:0.5rem;
--radius-lg:0.75rem; /* rounded-xl — cards */
--radius-xl:1rem; /* rounded-2xl — dropdown panels */
--radius-2xl:1.5rem; /* rounded-3xl — story / hero cards */
--radius-composer:28px; /* the chat composer, exactly 28px */
--radius-full:9999px; /* pills, CTAs, avatars, badges */
/* ===== Neutral Scale ===== */ /* ——— type — Geist + Geist Mono, self-hosted ——— */
--neutral-0: #ffffff; --font-sans:'Geist', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--neutral-50: #fafafa; --font-mono:'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
--neutral-100: #f5f5f5; --font-size-xs:0.6875rem; /* 11px — eyebrows / section labels */
--neutral-200: #e5e5e5; --font-size-sm:0.8125rem; /* 13px — nav labels, dense body */
--neutral-300: #d4d4d4; --font-size-base:0.875rem; /* 14px — base app text */
--neutral-400: #a3a3a3; --font-size-lg:0.9375rem; /* 15px */
--neutral-500: #737373; --font-size-xl:1.0625rem; /* 17px */
--neutral-600: #525252; --font-size-2xl:1.3125rem; /* 21px */
--neutral-700: #404040; --font-size-3xl:1.625rem; /* 26px */
--neutral-800: #262626; --font-size-4xl:2rem; /* 32px */
--neutral-900: #171717; --font-size-5xl:2.5rem; /* 40px */
--neutral-950: #0a0a0a; --font-size-6xl:3.25rem; /* 52px */
--neutral-1000: #000000; --font-size-7xl:4rem; /* 64px */
--font-size-8xl:5.25rem; /* 84px */
--font-size-9xl:7rem; /* 112px */
/* ===== Semantic Colors ===== */ /* ——— spacing — the 4px ramp ——— */
--success: #10b981; --space-1:0.25rem;
--success-light: #34d399; --space-2:0.5rem;
--success-dark: #059669; --space-3:0.75rem;
--space-4:1rem;
--warning: #f59e0b; --space-5:1.25rem;
--warning-light: #fcd34d; --space-6:1.5rem;
--warning-dark: #d97706; --space-8:2rem;
--space-10:2.5rem;
--error: #ef4444; --space-12:3rem;
--error-light: #f87171; --space-16:4rem;
--error-dark: #dc2626; --space-20:5rem;
--space-24:6rem;
--info: #3b82f6;
--info-light: #60a5fa;
--info-dark: #2563eb;
/* ===== Gradients ===== */
--gradient-brand: linear-gradient(135deg, var(--hanzo-mono-800) 0%, var(--hanzo-black) 100%);
--gradient-accent: linear-gradient(135deg, var(--hanzo-black) 0%, #000000 100%);
--gradient-dark: linear-gradient(135deg, #0a0a0b 0%, #262626 100%);
/* ===== Spacing ===== */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-5: 1.25rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-10: 2.5rem;
--space-12: 3rem;
--space-16: 4rem;
--space-20: 5rem;
--space-24: 6rem;
/* ===== Border Radius ===== */
--radius-sm: 0.125rem;
--radius: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-2xl: 1rem;
--radius-full: 9999px;
/* ===== Shadows ===== */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
/* ===== Transitions ===== */
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition: 200ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
/* ===== Typography ===== */
--font-sans: 'Zen', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'Zen Mono', ui-monospace, Monaco, monospace;
/* ===== Font Size scale (mirrors typography.ts `fontSize`) =====
TIGHT app-first default — the compact developer-app register (linear.app /
vercel.com), NOT a roomy marketing scale. Base is 14px, nav 13px, labels 11px.
Every surface that imports @hanzo/brand inherits this; a brand/tenant can
override any --font-size-* on :root to retune density on demand. */
--font-size-xs: 0.6875rem; /* 11px — eyebrows / section labels */
--font-size-sm: 0.8125rem; /* 13px — nav labels, dense body */
--font-size-base: 0.875rem; /* 14px — base app text (was 16px) */
--font-size-lg: 0.9375rem; /* 15px */
--font-size-xl: 1.0625rem; /* 17px */
--font-size-2xl: 1.3125rem; /* 21px */
--font-size-3xl: 1.625rem; /* 26px */
--font-size-4xl: 2rem; /* 32px */
--font-size-5xl: 2.5rem; /* 40px */
--font-size-6xl: 3.25rem; /* 52px */
--font-size-7xl: 4rem; /* 64px */
--font-size-8xl: 5.25rem; /* 84px */
--font-size-9xl: 7rem; /* 112px */
/* ===== Z-index ladder (mirrors tokens.ts `zIndex`) ===== */
--z-0: 0;
--z-10: 10;
--z-20: 20;
--z-30: 30;
--z-40: 40;
--z-50: 50;
--z-dropdown: 100;
--z-sticky: 200;
--z-overlay: 300;
--z-modal: 400;
--z-popover: 500;
--z-tooltip: 600;
--z-notification: 700;
} }
/* Dark theme (default for Hanzo) */ .light{
[data-theme="dark"], color-scheme:light;
.dark {
color-scheme: dark; /* ——— semantic aliases (light) ——— */
--background:#f7f7f7;
--foreground:#0a0a0a;
--card:#f2f2f2;
--card-foreground:#0a0a0a;
--popover:#fbfbfb;
--popover-foreground:#0a0a0a;
--primary:#0a0a0a;
--primary-hover:#262626;
--primary-foreground:#fafafa;
--secondary:#e4e4e4;
--secondary-hover:#e0e0e0;
--secondary-foreground:#0a0a0a;
--muted:#ededed;
--muted-foreground:#525252;
--accent:#e4e4e4;
--accent-foreground:#0a0a0a;
--destructive:var(--state-error);
--destructive-hover:#dc2626;
--destructive-foreground:#ffffff;
/* ——— boundaries — restated as black-alpha ——— */
--border:rgb(0 0 0 / .10);
--border-strong:rgb(0 0 0 / .16);
--border-control:rgb(0 0 0 / .15);
--border-focus:rgb(0 0 0 / .32); /* pushed past .22: black-on-white reads fainter */
--border-selected:rgb(0 0 0 / .42);
--input:var(--border-control);
--ring:rgb(0 0 0 / .5); /* 3.98:1 on #ffffff, 3.67:1 on #f5f5f5 */
--ring-halo:rgb(0 0 0 / .07);
--black:#0a0a0a;
--white:#ffffff;
--selection:rgb(0 0 0 / .16);
/* ——— glass + surfaces (light) ——— */
--glass:rgb(0 0 0 / .04);
--glass-strong:rgb(0 0 0 / .07);
--surface-card:#f2f2f2;
--surface-card-emphasis:#fdfdfd;
--surface-card-quiet:#f5f5f5;
--surface-overlay:rgb(255 255 255 / .95);
--surface-header:rgb(255 255 255 / .8);
--surface-scrim:rgb(0 0 0 / .5);
/* ——— text ranks (light) ——— */
--text-primary:var(--neutral-950);
--text-secondary:rgb(10 10 10 / .78);
--text-tertiary:rgb(10 10 10 / .55);
--text-disabled:rgb(10 10 10 / .3);
} }
/* Light theme */ /* ——— compatibility aliases ———
[data-theme="light"], Legacy @hanzo/brand names, each aliased onto a generated token so existing
.light { consumers keep resolving while the value converges on the one system. Prefer
--bg-primary: var(--bg-light); the token names above in new code. */
--bg-secondary: var(--bg-light-secondary); :root{
--bg-tertiary: var(--bg-light-tertiary); --border-hairline:var(--border);
--bg-card: rgba(255, 255, 255, 0.8); --border-hairline-strong:var(--border-strong);
--border: var(--border-light); --radius-card:var(--radius);
--text-primary: var(--text-light-primary); --error:var(--state-error);
--text-secondary: var(--text-light-secondary); --success:var(--state-success);
--text-muted: var(--text-light-muted); --warning:#f59e0b; /* build-status amber, sibling of --chrome-dot-yellow */
/* purple accent flips a shade deeper for contrast on paper */ --warning-light:#fcd34d;
--hanzo-accent: #7c3aed; --text-muted:var(--text-tertiary);
--hanzo-accent-hover: #6d28d9; /* The one accent is the ink itself — monochrome, no purple. */
--hanzo-accent-muted: #7c3aed; --hanzo-accent:var(--foreground);
/* layered "blacks" become layered near-whites in light */ --hanzo-accent-muted:var(--muted-foreground);
--surface-0: #ffffff; --hanzo-accent-soft:var(--white-10);
--surface-1: #fafafa;
--surface-2: #f5f5f5;
--surface-3: #ededed;
--border-hairline: rgba(0, 0, 0, 0.08);
--border-hairline-strong: rgba(0, 0, 0, 0.12);
color-scheme: light;
} }