@spawn-llc/design-system 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ # Spawn Partners — Design System Reference
2
+
3
+ <!-- GENERATED from tokens/tokens.json by scripts/generate-tokens.mjs. Do not edit by hand. -->
4
+ > Generated from `tokens/tokens.json`. Do not edit by hand — run `npm run tokens:gen`.
5
+ > Editorial guidance (voice, clay discipline, do/don't, tier rules) lives in [SPEC.md](./SPEC.md).
6
+
7
+ Color ratio: 70% paper / 22% ink / ≤8% clay.
8
+
9
+ ## Color
10
+
11
+ | Token | Hex | Role |
12
+ |-------|-----|------|
13
+ | paper | `#FAF8F3` | app/page background |
14
+ | white | `#FFFFFF` | cards / surfaces |
15
+ | mist | `#F2F0E9` | subtle fills, track bg, flat chart fill |
16
+ | line | `#8C8678` | hairlines, borders, dividers — clears WCAG 3:1 on paper/white/mist |
17
+ | stone | `#B7B1A4` | muted bars, disabled |
18
+ | slate | `#6B655A` | secondary text, labels, axis ticks |
19
+ | ink | `#1A1916` | primary text, dark surfaces, default buttons |
20
+ | clay | `#C0492F` | THE accent — one element per view |
21
+ | ember | `#9C3A23` | clay hover / pressed |
22
+ | steel | `#2E3A46` | nav / chrome — internal tooling ONLY |
23
+ | steel-2 | `#3B4855` | active nav row |
24
+ | steel-border | `#7A8690` | steel chrome border — clears WCAG 3:1 on steel |
25
+ | nav-inactive | `#A6B0BB` | inactive nav labels |
26
+ | row-hover | `#FBFAF6` | table row hover |
27
+
28
+ ## Semantic roles
29
+
30
+ How brand colors map onto component/theme roles (shadcn / Tailwind names).
31
+
32
+ | Role | Brand token | Hex |
33
+ |------|-------------|-----|
34
+ | background | paper | `#FAF8F3` |
35
+ | foreground | ink | `#1A1916` |
36
+ | card | white | `#FFFFFF` |
37
+ | card-foreground | ink | `#1A1916` |
38
+ | popover | white | `#FFFFFF` |
39
+ | popover-foreground | ink | `#1A1916` |
40
+ | primary | ink | `#1A1916` |
41
+ | primary-foreground | paper | `#FAF8F3` |
42
+ | secondary | mist | `#F2F0E9` |
43
+ | secondary-foreground | ink | `#1A1916` |
44
+ | muted | mist | `#F2F0E9` |
45
+ | muted-foreground | slate | `#6B655A` |
46
+ | accent | mist | `#F2F0E9` |
47
+ | accent-foreground | ink | `#1A1916` |
48
+ | destructive | ember | `#9C3A23` |
49
+ | border | line | `#8C8678` |
50
+ | input | line | `#8C8678` |
51
+ | ring | ink | `#1A1916` |
52
+ | chart-1 | stone | `#B7B1A4` |
53
+ | chart-2 | steel | `#2E3A46` |
54
+ | chart-3 | slate | `#6B655A` |
55
+ | chart-4 | mist | `#F2F0E9` |
56
+ | chart-5 | clay | `#C0492F` |
57
+ | sidebar | steel | `#2E3A46` |
58
+ | sidebar-foreground | nav-inactive | `#A6B0BB` |
59
+ | sidebar-primary | clay | `#C0492F` |
60
+ | sidebar-primary-foreground | paper | `#FAF8F3` |
61
+ | sidebar-accent | steel-2 | `#3B4855` |
62
+ | sidebar-accent-foreground | white | `#FFFFFF` |
63
+ | sidebar-border | steel-border | `#7A8690` |
64
+ | sidebar-ring | clay | `#C0492F` |
65
+
66
+ ## Type
67
+
68
+ | Family | Stack | Use | Weights |
69
+ |--------|-------|-----|---------|
70
+ | serif | `'Newsreader Variable', Georgia, serif` | page titles, editorial, empty states | 300, 400, 500 |
71
+ | sans | `'Geist Variable', 'Geist', system-ui, Arial, sans-serif` | all UI / body / buttons / cells | 300, 400, 600 |
72
+ | mono | `'Geist Mono Variable', 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace` | labels, metadata, headers, figures-in-tables | 400, 500 |
73
+
74
+ Mono is set uppercase, 0.12em tracking, `tabular-nums`.
75
+
76
+ ## Type scale
77
+
78
+ | Role | Font | Size | Line height | Weight | Color |
79
+ |------|------|------|-------------|--------|-------|
80
+ | pageTitle | serif | 24px | 1.1 | 500 | — |
81
+ | figure | mono | 28px | 1 | 500 | — |
82
+ | section | sans | 14px | 1.3 | 600 | — |
83
+ | body | sans | 13px | 1.5 | 400 | — |
84
+ | secondary | sans | 12px | 1.4 | 400 | slate |
85
+ | label | mono | 10px | 1 | 500 | slate |
86
+ | axisTick | mono | 10px | 1 | 400 | slate |
87
+
88
+ ## Spacing
89
+
90
+ 8px base. Scale 4 · 8 · 16 · 24 · 32 · 48 · 64 · 96 (px), exposed as `--s-1`…`--s-8`.
91
+
92
+ ## Radius & shape
93
+
94
+ | Step | Value |
95
+ |------|-------|
96
+ | xs | 2px |
97
+ | sm | 3px |
98
+ | md | 4px |
99
+ | lg | 6px |
100
+ | xl | 8px |
101
+ | 2xl | 10px |
102
+ | 3xl | 12px |
103
+ | 4xl | 16px |
104
+
105
+ Base control radius 4px, max 16px. Separators: hairline 1px line. Shadows: none on anchored surfaces; small warm shadow on floating overlays (dropdowns, popovers, menus, sheets).
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # Spawn Partners — Design System
2
+
3
+ The single source of truth for the Spawn Partners brand. One spec for everything:
4
+ marketing & client-facing work and internal tooling & shippable products.
5
+
6
+ Editorial, founder-led, technical. Warm paper and ink with a single clay-red
7
+ accent used as a highlighter — never a theme color.
8
+
9
+ It ships as **`@spawn-llc/design-system`** — a React component library built on
10
+ [Base UI](https://base-ui.com) primitives (the full shadcn component set,
11
+ themed from the tokens below) plus the raw design tokens and brand assets.
12
+
13
+ ## What's in here
14
+
15
+ ```
16
+ SPEC.md ← the canonical spec. Read this first.
17
+ CLAUDE.md ← auto-loaded rules for Claude Code / Claude Design
18
+ src/
19
+ components/ui/ ← Base UI components, themed (button, card, table, …)
20
+ styles/theme.css ← shadcn/Tailwind-v4 theme derived from the tokens
21
+ index.ts ← public API (barrel export)
22
+ tokens/
23
+ tokens.css ← CSS custom properties — import, don't hardcode hex
24
+ tokens.json ← machine-readable tokens
25
+ assets/
26
+ logo/ ← Instance Mark + lockups (ink / paper / white)
27
+ avatars/ ← profile marks (clay / ink / paper)
28
+ banners/ ← social headers (LinkedIn, X, Slack)
29
+ examples/
30
+ finance-dashboard-overview.png ← internal-tooling reference
31
+ brand-system-reference.png ← full brand reference sheet
32
+ NOTES.md ← paste-ready copy for the Claude Design setup form
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ - **Color:** Paper `#FAF8F3` · Ink `#1A1916` · Clay `#C0492F` (the one accent).
38
+ Ratio ~70/22/≤8. Steel `#2E3A46` for tool chrome only.
39
+ - **Type:** Newsreader (titles) · Geist (UI/body) · Geist Mono
40
+ (labels/figures). Serif for what's said, sans for what's done, mono for what's
41
+ measured.
42
+ - **Shape:** 8px base, near-square corners (4px controls, 6px cards, ≤16px),
43
+ hairlines over boxes, no shadows.
44
+
45
+ The one rule that matters most: **clay marks exactly one element per view.**
46
+
47
+ See [`SPEC.md`](./SPEC.md) for the full system.
48
+
49
+ ## Use the component library
50
+
51
+ ```bash
52
+ npm install @spawn-llc/design-system
53
+ ```
54
+
55
+ Peer dependencies: `react` and `react-dom` (>=18.2).
56
+
57
+ **Fonts** — self-hosted, no external requests. Import once at your app entry:
58
+
59
+ ```ts
60
+ import "@spawn-llc/design-system/fonts"
61
+ ```
62
+
63
+ **Styling** — two paths:
64
+
65
+ 1. **Plain / no Tailwind** — import the prebuilt stylesheet, then use components:
66
+
67
+ ```ts
68
+ import "@spawn-llc/design-system/styles.css"
69
+ import { Button, Card } from "@spawn-llc/design-system"
70
+ ```
71
+
72
+ 2. **Tailwind v4 consumers** — import the brand theme into your CSS and add the
73
+ package to your sources so the component classes compile (with tree-shaking):
74
+
75
+ ```css
76
+ @import "tailwindcss";
77
+ @import "@spawn-llc/design-system/theme.css";
78
+ @source "../node_modules/@spawn-llc/design-system/dist";
79
+ ```
80
+
81
+ ```tsx
82
+ import { Button } from "@spawn-llc/design-system"
83
+
84
+ export function Example() {
85
+ return <Button>Get started</Button> // ink by default; clay reserved for one accent
86
+ }
87
+ ```
88
+
89
+ Raw tokens are also exported directly: `@spawn-llc/design-system/tokens.css`
90
+ and `@spawn-llc/design-system/tokens.json`.
91
+
92
+ ## Playground
93
+
94
+ A live, self-updating showcase of every component lives in [`playground/`](./playground).
95
+ It consumes the library from source, so adding a `playground/src/demos/<name>.demo.tsx`
96
+ file surfaces it automatically — a coverage test fails the build if any component
97
+ lacks a demo. It also includes a marketing-tier and an internal-tooling-tier view.
98
+
99
+ ```bash
100
+ npm run play # dev server with HMR
101
+ npm run play:build # static build (deployed to GitHub Pages on push to main)
102
+ ```
103
+
104
+ The playground is not part of the published package.
105
+
106
+ ## Build, test, verify
107
+
108
+ ```bash
109
+ npm run build # tsup (ESM + types) + Tailwind (dist/styles.css)
110
+ npm run typecheck # library types
111
+ npm run play:typecheck
112
+ npm test # Vitest: coverage gate, behavior, demo smoke tests
113
+ npm run test:e2e # Playwright: tier rendering + interaction
114
+ ```
115
+
116
+ ## License
117
+
118
+ MIT © Spawn Partners.
package/SPEC.md ADDED
@@ -0,0 +1,170 @@
1
+ # Spawn Partners — Design System
2
+
3
+ The single source of truth for the Spawn Partners brand. Applies to **everything**:
4
+ marketing & client-facing work (website, one-pagers, proposals, decks, reports,
5
+ email signatures) and internal tooling & shippable products (dashboards, apps,
6
+ admin). When in doubt, match the rendered references in `/examples`.
7
+
8
+ Editorial, founder-led, technical. Warm paper and ink with a single clay-red
9
+ accent used as a highlighter — never as a theme color.
10
+
11
+ ---
12
+
13
+ ## 1. Color
14
+
15
+ <!-- @tokens:auto:start spec-colors -->
16
+ | Token | Hex | Role |
17
+ |-------|-----|------|
18
+ | Paper | `#FAF8F3` | app/page background |
19
+ | White | `#FFFFFF` | cards / surfaces |
20
+ | Mist | `#F2F0E9` | subtle fills, track bg, flat chart fill |
21
+ | Line | `#8C8678` | hairlines, borders, dividers — clears WCAG 3:1 on paper/white/mist |
22
+ | Stone | `#B7B1A4` | muted bars, disabled |
23
+ | Slate | `#6B655A` | secondary text, labels, axis ticks |
24
+ | Ink | `#1A1916` | primary text, dark surfaces, default buttons |
25
+ | Clay | `#C0492F` | THE accent — one element per view |
26
+ | Ember | `#9C3A23` | clay hover / pressed |
27
+ | Steel | `#2E3A46` | nav / chrome — internal tooling ONLY |
28
+ | Steel-2 | `#3B4855` | active nav row |
29
+ <!-- @tokens:auto:end spec-colors -->
30
+
31
+ <!-- Color values above are generated from tokens/tokens.json — edit there, run `npm run tokens:gen`. -->
32
+
33
+
34
+ **Ratio:** ~70% paper · ~22% ink · ≤8% clay.
35
+
36
+ **Clay discipline (the most important rule):** clay marks exactly **ONE element
37
+ per view** — the live or critical figure (runway, overdue, shortfall), the
38
+ single current/critical bar in a chart, an active-link underline, the active nav
39
+ tick, or OVERDUE status. It is a highlighter, never a theme color. KPI numbers
40
+ and data values are **ink by default**, not clay.
41
+
42
+ No gradients, glows, or neon AI purple/blue. Ever.
43
+
44
+ **Contrast (enforced):** every text/surface pair must clear WCAG AA (4.5:1) and
45
+ every border/divider must clear 3:1 — this is why `Line` is `#8C8678` rather than
46
+ a fainter tint. The real pairings are listed in `test/contrast.manifest.ts` and
47
+ checked by `npm run test:contrast`, which runs on `git push` and in CI before
48
+ deploy/publish. After changing any token or component color, keep that gate
49
+ green.
50
+
51
+ ---
52
+
53
+ ## 2. Type
54
+
55
+ Three families, three jobs. **Serif for what's *said*, sans for what's *done*,
56
+ mono for what's *measured*.**
57
+
58
+ - **Newsreader** (serif, 300/400/500) — page titles, editorial headlines, empty
59
+ states. One serif headline per view. **Never body copy, never labels.**
60
+ - **Geist** (300/400/600) — all interface, body, buttons, table cells. The web
61
+ UI/body face. Falls back to system-ui → Arial.
62
+ - **Geist Mono** (400/500) — labels, metadata, table headers, axis ticks,
63
+ figures in tables. UPPERCASE, letter-spacing ~0.12–0.14em.
64
+ Always `font-variant-numeric: tabular-nums` on numerals. **Never paragraphs.**
65
+
66
+ Fonts are **self-hosted** (no external requests) via `@fontsource`. Apps using
67
+ this design system get them by importing `@spawn-llc/design-system/fonts`;
68
+ standalone usage installs `@fontsource-variable/geist`,
69
+ `@fontsource-variable/newsreader`, and `@fontsource-variable/geist-mono`.
70
+
71
+ ### Type scale (interface / dashboard density)
72
+ ```
73
+ Page title Newsreader 500 24px / 1.1 tracking -0.01em
74
+ KPI / card figure Geist Mono 500 28px / 1.0 tabular-nums
75
+ Section heading Geist 600 14px / 1.3
76
+ Body / table cell Geist 400 13px / 1.5
77
+ Secondary text Geist 400 12px / 1.4 #6B655A
78
+ Label (mono) Geist Mono 500 10px / 0.12em uppercase #6B655A
79
+ Axis tick Geist Mono 400 10px #6B655A
80
+ ```
81
+ In tools, body text never exceeds 14px. Marketing/editorial headlines scale up
82
+ freely in Newsreader, but the role rules never change.
83
+
84
+ ---
85
+
86
+ ## 3. Spacing & shape
87
+
88
+ - **8px base:** 4 · 8 · 16 · 24 · 32 · 48 · 64 · 96.
89
+ - Marketing section padding ≥ 76px. Tool card padding ~20px. Page padding 28–36px.
90
+ - **Near-square corners:** very light rounding — **4px** base on controls
91
+ (buttons, inputs), **6px** on cards/dialogs, up to **16px** on the largest
92
+ surfaces. Enough to take the hard edge off; never soft or pill-shaped.
93
+ - **Hairlines over boxes:** separate with 1px `Line #8C8678` rules, or a 1px
94
+ grid-gap on a `Line` background — not heavy borders or shadows.
95
+ - **No drop shadows on anchored surfaces** (cards, inputs, tabs). The one
96
+ exception: surfaces that float free of the layout — dropdowns, popovers,
97
+ selects, menus, tooltips, sheets — get a small warm-tinted shadow on top of
98
+ their 1px border so they read as lifted. **No card-on-card nesting.**
99
+ Left-aligned, asymmetric layouts.
100
+ - Cards: `background:#FFFFFF; border:1px solid #8C8678;`.
101
+ - Generous whitespace is the premium signal.
102
+
103
+ ---
104
+
105
+ ## 4. Components
106
+
107
+ - **Buttons** — default = ink (`bg #1A1916`, text `#FAF8F3`), optional clay arrow
108
+ glyph inside. Secondary = transparent + 1.5px ink border. Clay-filled button is
109
+ rare. **One primary action per screen.**
110
+ - **Links** — ink text with a 1.5px clay underline.
111
+ - **Sidebar / nav** (internal tooling) — Steel `#2E3A46`; active row `#3B4855`
112
+ with a 5px clay tick; inactive labels `#A6B0BB`.
113
+ - **Tables** — mono uppercase headers in Slate; cells in Geist; numerics
114
+ right-aligned in mono tabular-nums; row hover `#FBFAF6`; 1px `Line` dividers;
115
+ no zebra striping. Status like OVERDUE in clay with a leading `●`.
116
+ - **Charts** — bars in Stone / steel tint; only the single current/critical bar
117
+ in clay; flat Mist fills (never gradient ramps); 1.5px solid ink line strokes;
118
+ dashed `Line` target/baseline; mono 10px axis ticks; 9px square swatches.
119
+
120
+ ---
121
+
122
+ ## 5. Logo
123
+
124
+ Primary = the **Instance Mark** (stepped origin square → two outline squares,
125
+ outermost in clay) + the wordmark "Spawn" 600 (ink) / "Partners" 400 (slate),
126
+ set live in **Geist** — not baked into the SVG, so it stays crisp at any size and
127
+ tracks the theme. In React, use the `Logo` component (`variant` lockup/mark/
128
+ wordmark, `tone` default/on-ink). Min 20px digital / 8mm print. Clear space = the
129
+ height of the origin square. Static files in `/assets/logo`.
130
+
131
+ ---
132
+
133
+ ## 6. Voice
134
+
135
+ Founder-led, direct, technical, precise. Show real numbers and timelines.
136
+
137
+ **Banned words:** revolutionary, synergy, cutting-edge, leverage (v.),
138
+ supercharge, unlock, best-in-class, game-changing. **No emoji. No exclamation
139
+ marks.**
140
+
141
+ ---
142
+
143
+ ## 7. Tier rules — what to use where
144
+
145
+ **Marketing & client-facing** (website, one-pagers, proposals, decks, reports,
146
+ signatures) — paper / ink / clay only. Newsreader headlines, Geist body,
147
+ mono labels. Dark (ink) sections for covers and heroes; paper for content.
148
+ **No Steel.** The brand at full editorial volume.
149
+
150
+ **Internal tooling & shippable products** (dashboards, apps, admin) — same
151
+ palette and type, but **Steel `#2E3A46` is allowed for nav/chrome** to separate
152
+ "the tool" from "the brand." Data stays calm and neutral; clay marks only the
153
+ live or critical figure. Default button is ink. Newsreader reserved for page
154
+ titles and empty states; everything functional is Geist.
155
+
156
+ **All tiers** — default action button = ink; clay button is rare; text links =
157
+ ink with a clay underline; one primary action per screen.
158
+
159
+ ---
160
+
161
+ ## 8. Don't
162
+
163
+ - No gradients, glowing blobs, neon AI purple/blue.
164
+ - No pill tags or chip soup.
165
+ - No rounded corners > 16px, no pill shapes. No drop shadows on anchored
166
+ surfaces (a small lift on floating overlays is fine).
167
+ - No card-on-card nesting.
168
+ - No stock "team at laptops" photos or generic 3D renders.
169
+ - Don't let clay spread beyond one element per view.
170
+ - No emoji, no exclamation marks.
@@ -0,0 +1,105 @@
1
+ # Spawn Partners — Design System Reference
2
+
3
+ <!-- GENERATED from tokens/tokens.json by scripts/generate-tokens.mjs. Do not edit by hand. -->
4
+ > Generated from `tokens/tokens.json`. Do not edit by hand — run `npm run tokens:gen`.
5
+ > Editorial guidance (voice, clay discipline, do/don't, tier rules) lives in [SPEC.md](./SPEC.md).
6
+
7
+ Color ratio: 70% paper / 22% ink / ≤8% clay.
8
+
9
+ ## Color
10
+
11
+ | Token | Hex | Role |
12
+ |-------|-----|------|
13
+ | paper | `#FAF8F3` | app/page background |
14
+ | white | `#FFFFFF` | cards / surfaces |
15
+ | mist | `#F2F0E9` | subtle fills, track bg, flat chart fill |
16
+ | line | `#8C8678` | hairlines, borders, dividers — clears WCAG 3:1 on paper/white/mist |
17
+ | stone | `#B7B1A4` | muted bars, disabled |
18
+ | slate | `#6B655A` | secondary text, labels, axis ticks |
19
+ | ink | `#1A1916` | primary text, dark surfaces, default buttons |
20
+ | clay | `#C0492F` | THE accent — one element per view |
21
+ | ember | `#9C3A23` | clay hover / pressed |
22
+ | steel | `#2E3A46` | nav / chrome — internal tooling ONLY |
23
+ | steel-2 | `#3B4855` | active nav row |
24
+ | steel-border | `#7A8690` | steel chrome border — clears WCAG 3:1 on steel |
25
+ | nav-inactive | `#A6B0BB` | inactive nav labels |
26
+ | row-hover | `#FBFAF6` | table row hover |
27
+
28
+ ## Semantic roles
29
+
30
+ How brand colors map onto component/theme roles (shadcn / Tailwind names).
31
+
32
+ | Role | Brand token | Hex |
33
+ |------|-------------|-----|
34
+ | background | paper | `#FAF8F3` |
35
+ | foreground | ink | `#1A1916` |
36
+ | card | white | `#FFFFFF` |
37
+ | card-foreground | ink | `#1A1916` |
38
+ | popover | white | `#FFFFFF` |
39
+ | popover-foreground | ink | `#1A1916` |
40
+ | primary | ink | `#1A1916` |
41
+ | primary-foreground | paper | `#FAF8F3` |
42
+ | secondary | mist | `#F2F0E9` |
43
+ | secondary-foreground | ink | `#1A1916` |
44
+ | muted | mist | `#F2F0E9` |
45
+ | muted-foreground | slate | `#6B655A` |
46
+ | accent | mist | `#F2F0E9` |
47
+ | accent-foreground | ink | `#1A1916` |
48
+ | destructive | ember | `#9C3A23` |
49
+ | border | line | `#8C8678` |
50
+ | input | line | `#8C8678` |
51
+ | ring | ink | `#1A1916` |
52
+ | chart-1 | stone | `#B7B1A4` |
53
+ | chart-2 | steel | `#2E3A46` |
54
+ | chart-3 | slate | `#6B655A` |
55
+ | chart-4 | mist | `#F2F0E9` |
56
+ | chart-5 | clay | `#C0492F` |
57
+ | sidebar | steel | `#2E3A46` |
58
+ | sidebar-foreground | nav-inactive | `#A6B0BB` |
59
+ | sidebar-primary | clay | `#C0492F` |
60
+ | sidebar-primary-foreground | paper | `#FAF8F3` |
61
+ | sidebar-accent | steel-2 | `#3B4855` |
62
+ | sidebar-accent-foreground | white | `#FFFFFF` |
63
+ | sidebar-border | steel-border | `#7A8690` |
64
+ | sidebar-ring | clay | `#C0492F` |
65
+
66
+ ## Type
67
+
68
+ | Family | Stack | Use | Weights |
69
+ |--------|-------|-----|---------|
70
+ | serif | `'Newsreader Variable', Georgia, serif` | page titles, editorial, empty states | 300, 400, 500 |
71
+ | sans | `'Geist Variable', 'Geist', system-ui, Arial, sans-serif` | all UI / body / buttons / cells | 300, 400, 600 |
72
+ | mono | `'Geist Mono Variable', 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace` | labels, metadata, headers, figures-in-tables | 400, 500 |
73
+
74
+ Mono is set uppercase, 0.12em tracking, `tabular-nums`.
75
+
76
+ ## Type scale
77
+
78
+ | Role | Font | Size | Line height | Weight | Color |
79
+ |------|------|------|-------------|--------|-------|
80
+ | pageTitle | serif | 24px | 1.1 | 500 | — |
81
+ | figure | mono | 28px | 1 | 500 | — |
82
+ | section | sans | 14px | 1.3 | 600 | — |
83
+ | body | sans | 13px | 1.5 | 400 | — |
84
+ | secondary | sans | 12px | 1.4 | 400 | slate |
85
+ | label | mono | 10px | 1 | 500 | slate |
86
+ | axisTick | mono | 10px | 1 | 400 | slate |
87
+
88
+ ## Spacing
89
+
90
+ 8px base. Scale 4 · 8 · 16 · 24 · 32 · 48 · 64 · 96 (px), exposed as `--s-1`…`--s-8`.
91
+
92
+ ## Radius & shape
93
+
94
+ | Step | Value |
95
+ |------|-------|
96
+ | xs | 2px |
97
+ | sm | 3px |
98
+ | md | 4px |
99
+ | lg | 6px |
100
+ | xl | 8px |
101
+ | 2xl | 10px |
102
+ | 3xl | 12px |
103
+ | 4xl | 16px |
104
+
105
+ Base control radius 4px, max 16px. Separators: hairline 1px line. Shadows: none on anchored surfaces; small warm shadow on floating overlays (dropdowns, popovers, menus, sheets).
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/fonts.js ADDED
@@ -0,0 +1,3 @@
1
+ import '@fontsource-variable/geist';
2
+ import '@fontsource-variable/newsreader';
3
+ import '@fontsource-variable/geist-mono';