@ima-jin/tokens 1.0.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.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @ima-jin/tokens
2
+
3
+ Design tokens for the Imajin platform in DTCG format, built with Style Dictionary v4.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @ima-jin/tokens
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Tailwind
14
+
15
+ ```js
16
+ // tailwind.config.js
17
+ const tokens = require('@ima-jin/tokens');
18
+ // Use tokens.colors, tokens.spacing, etc.
19
+ ```
20
+
21
+ ### CSS Variables
22
+
23
+ ```css
24
+ @import '@ima-jin/tokens/css';
25
+ ```
26
+
27
+ ## Part of Imajin
28
+
29
+ [Imajin](https://imajin.ai) — sovereign technology infrastructure. Open source.
package/build.mjs ADDED
@@ -0,0 +1,244 @@
1
+ import StyleDictionary from 'style-dictionary';
2
+ import { formats } from 'style-dictionary/enums';
3
+
4
+ const { cssVariables } = formats;
5
+
6
+ // Register a custom dimension transform that preserves original units (rem, em, px)
7
+ StyleDictionary.registerTransform({
8
+ name: 'dimension/preserve-unit',
9
+ type: 'value',
10
+ filter: (token) => token.$type === 'dimension',
11
+ transform: (token) => {
12
+ const val = token.$value ?? token.value;
13
+ // If already a string with a unit suffix, keep it as-is
14
+ if (typeof val === 'string' && /(px|rem|em|%|vh|vw|ch)$/.test(val)) {
15
+ return val;
16
+ }
17
+ // Otherwise fallback to px
18
+ return `${val}px`;
19
+ },
20
+ });
21
+
22
+ const sd = new StyleDictionary({
23
+ source: ['tokens.json'],
24
+ platforms: {
25
+ css: {
26
+ // Use web transforms but override dimension to preserve rem/em
27
+ transforms: [
28
+ 'attribute/cti',
29
+ 'name/kebab',
30
+ 'time/seconds',
31
+ 'dimension/preserve-unit',
32
+ 'color/css',
33
+ 'fontFamily/css',
34
+ ],
35
+ buildPath: 'dist/',
36
+ files: [{
37
+ destination: 'variables.css',
38
+ format: cssVariables,
39
+ options: {
40
+ outputReferences: true,
41
+ selector: ':root',
42
+ },
43
+ }],
44
+ },
45
+ tailwind: {
46
+ buildPath: 'dist/',
47
+ transforms: ['attribute/cti', 'name/kebab', 'color/css'],
48
+ files: [{
49
+ destination: 'tailwind.js',
50
+ format: 'tailwind',
51
+ }],
52
+ },
53
+ },
54
+ });
55
+
56
+ // Register a custom format for Tailwind theme extension
57
+ sd.registerFormat({
58
+ name: 'tailwind',
59
+ format: ({ dictionary }) => {
60
+ const tokens = dictionary.allTokens;
61
+
62
+ // Extract colors
63
+ const colors = {};
64
+ const sunset = {};
65
+ const surface = {};
66
+ const functional = {};
67
+ const interactive = {};
68
+
69
+ // Semantic tokens — role-based aliases (app code uses these, not raw)
70
+ const semSurface = {};
71
+ const semText = {};
72
+ const semCta = {};
73
+ const semBorder = {};
74
+ const semStatus = {};
75
+ let semAccent = null;
76
+ let semFocusRing = null;
77
+
78
+ // Extract spacing
79
+ const spacing = {};
80
+
81
+ // Extract border radius
82
+ const borderRadius = {};
83
+
84
+ // Extract shadows
85
+ const boxShadow = {};
86
+
87
+ // Extract font families
88
+ const fontFamily = {};
89
+
90
+ // Extract font weights
91
+ const fontWeight = {};
92
+
93
+ // Extract font sizes
94
+ const fontSize = {};
95
+
96
+ // Extract letter spacing
97
+ const letterSpacing = {};
98
+
99
+ for (const token of tokens) {
100
+ const path = token.path;
101
+ const value = token.$value ?? token.value;
102
+
103
+ // Colors
104
+ if (path[0] === 'color') {
105
+ if (path[1] === 'background') {
106
+ surface[path[2]] = value;
107
+ } else if (path[1] === 'sunset') {
108
+ sunset[path[2]] = value;
109
+ } else if (path[1] === 'functional') {
110
+ const key = path[2].replace('text-', '');
111
+ functional[key] = value;
112
+ } else if (path[1] === 'interactive') {
113
+ const key = path[2].replace('border-', '');
114
+ interactive[key] = value;
115
+ } else if (path[1] === 'gradient' && path[2] === 'sunset') {
116
+ colors['sunset-gradient'] = value;
117
+ }
118
+ }
119
+
120
+ // Semantic tokens — alias tier
121
+ if (path[0] === 'semantic') {
122
+ if (path[1] === 'surface') {
123
+ semSurface[path[2]] = value;
124
+ } else if (path[1] === 'text') {
125
+ semText[path[2]] = value;
126
+ } else if (path[1] === 'cta') {
127
+ semCta[path[2]] = value;
128
+ } else if (path[1] === 'border') {
129
+ semBorder[path[2]] = value;
130
+ } else if (path[1] === 'focus') {
131
+ if (path[2] === 'ring') semFocusRing = value;
132
+ } else if (path[1] === 'status') {
133
+ semStatus[path[2]] = value;
134
+ } else if (path[1] === 'accent' && path.length === 2) {
135
+ semAccent = value;
136
+ }
137
+ }
138
+
139
+ // Spacing
140
+ if (path[0] === 'space') {
141
+ spacing[path[1]] = value;
142
+ }
143
+
144
+ // Border radius
145
+ if (path[0] === 'radius') {
146
+ borderRadius[path[1]] = value;
147
+ }
148
+
149
+ // Shadows
150
+ if (path[0] === 'shadow') {
151
+ boxShadow[path[1]] = value;
152
+ }
153
+
154
+ // Font families
155
+ if (path[0] === 'font' && path[1] === 'family') {
156
+ fontFamily[path[2]] = value;
157
+ }
158
+
159
+ // Font weights
160
+ if (path[0] === 'font' && path[1] === 'weight') {
161
+ fontWeight[path[2]] = value;
162
+ }
163
+
164
+ // Font sizes
165
+ if (path[0] === 'font' && path[1] === 'size') {
166
+ fontSize[path[2]] = value;
167
+ }
168
+
169
+ // Letter spacing
170
+ if (path[0] === 'font' && path[1] === 'tracking') {
171
+ letterSpacing[path[2]] = value;
172
+ }
173
+ }
174
+
175
+ // Assemble the Tailwind theme extension
176
+ // Raw tokens stay available (imajin-*, surface-*, etc) for use INSIDE packages/ui only.
177
+ // Semantic tokens (accent, cta-*, surface-1/2/3, text-heading/body/quiet, border-*, focus-ring,
178
+ // status-*) are what app code and primitives should use.
179
+ const theme = {
180
+ colors: {
181
+ // --- Raw tokens (use only inside packages/ui primitives) ---
182
+ imajin: sunset,
183
+ surface,
184
+ ...functional,
185
+ interactive,
186
+ ...colors,
187
+ // --- Semantic tokens (use everywhere else) ---
188
+ ...(semAccent ? { accent: semAccent } : {}),
189
+ 'cta-primary': semCta.primary,
190
+ 'cta-secondary': semCta.secondary,
191
+ 'surface-1': semSurface['1'],
192
+ 'surface-2': semSurface['2'],
193
+ 'surface-3': semSurface['3'],
194
+ 'surface-input': semSurface.input,
195
+ 'text-heading': semText.heading,
196
+ 'text-body': semText.body,
197
+ 'text-quiet': semText.quiet,
198
+ 'text-on-accent': semText['on-accent'],
199
+ 'border-subtle': semBorder.subtle,
200
+ 'border-strong': semBorder.strong,
201
+ 'border-input-field': semBorder.input,
202
+ 'border-nav': semBorder.nav,
203
+ ...(semFocusRing ? { 'focus-ring': semFocusRing } : {}),
204
+ 'status-success': semStatus.success,
205
+ 'status-warning': semStatus.warning,
206
+ 'status-error': semStatus.error,
207
+ 'status-info': semStatus.info,
208
+ },
209
+ spacing,
210
+ borderRadius,
211
+ boxShadow,
212
+ fontFamily,
213
+ fontWeight,
214
+ fontSize,
215
+ letterSpacing,
216
+ };
217
+
218
+ // Serialize to JS — quote keys with special chars, keep clean identifiers unquoted
219
+ function serialize(value, indent = 2) {
220
+ const pad = ' '.repeat(indent);
221
+ if (Array.isArray(value)) {
222
+ const items = value.map((v) => serialize(v, indent + 2)).join(', ');
223
+ return `[${items}]`;
224
+ }
225
+ if (typeof value === 'object' && value !== null) {
226
+ const entries = Object.entries(value).map(([k, v]) => {
227
+ const key = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : `'${k}'`;
228
+ return `${pad}${key}: ${serialize(v, indent + 2)}`;
229
+ });
230
+ return `{\n${entries.join(',\n')}\n${' '.repeat(indent - 2)}}`;
231
+ }
232
+ if (typeof value === 'string') {
233
+ return `'${value.replace(/'/g, "\\'")}'`;
234
+ }
235
+ return String(value);
236
+ }
237
+
238
+ const jsString = serialize(theme, 2);
239
+ return `/** @type {import('tailwindcss').Config['theme']['extend']} */\nmodule.exports = ${jsString};\n`;
240
+ },
241
+ });
242
+
243
+ await sd.buildAllPlatforms();
244
+ console.log('✓ Built tokens to dist/');
@@ -0,0 +1,96 @@
1
+ /** @type {import('tailwindcss').Config['theme']['extend']} */
2
+ module.exports = {
3
+ colors: {
4
+ imajin: {
5
+ purple: '#8b5cf6',
6
+ blue: '#6366f1',
7
+ red: '#ef4444',
8
+ orange: '#f97316'
9
+ },
10
+ surface: {
11
+ base: '#0a0a0f',
12
+ surface: '#12121a',
13
+ elevated: '#1a1a26',
14
+ input: '#15151f'
15
+ },
16
+ primary: '#f0f0f5',
17
+ secondary: '#9393a8',
18
+ muted: '#5a5a72',
19
+ success: '#22c55e',
20
+ warning: '#eab308',
21
+ error: '#ef4444',
22
+ info: '#6366f1',
23
+ interactive: {
24
+ light: 'rgba(255, 255, 255, 0.1)',
25
+ 'light-hover': 'rgba(255, 255, 255, 0.2)',
26
+ input: 'rgba(255, 255, 255, 0.12)',
27
+ secondary: 'rgba(255, 255, 255, 0.15)',
28
+ nav: 'rgba(255, 255, 255, 0.08)',
29
+ 'scrollbar-thumb': 'rgba(139, 92, 246, 0.3)'
30
+ },
31
+ 'sunset-gradient': 'linear-gradient(135deg, #8b5cf6, #6366f1, #ef4444, #f97316)',
32
+ accent: '#f97316',
33
+ 'cta-primary': 'linear-gradient(135deg, #8b5cf6, #6366f1, #ef4444, #f97316)',
34
+ 'cta-secondary': '#1a1a26',
35
+ 'surface-1': '#0a0a0f',
36
+ 'surface-2': '#12121a',
37
+ 'surface-3': '#1a1a26',
38
+ 'surface-input': '#15151f',
39
+ 'text-heading': '#f0f0f5',
40
+ 'text-body': '#9393a8',
41
+ 'text-quiet': '#5a5a72',
42
+ 'text-on-accent': '#f0f0f5',
43
+ 'border-subtle': 'rgba(255, 255, 255, 0.1)',
44
+ 'border-strong': 'rgba(255, 255, 255, 0.2)',
45
+ 'border-input-field': 'rgba(255, 255, 255, 0.12)',
46
+ 'border-nav': 'rgba(255, 255, 255, 0.08)',
47
+ 'focus-ring': '#8b5cf6',
48
+ 'status-success': '#22c55e',
49
+ 'status-warning': '#eab308',
50
+ 'status-error': '#ef4444',
51
+ 'status-info': '#6366f1'
52
+ },
53
+ spacing: {
54
+ '1': '4px',
55
+ '2': '8px',
56
+ '3': '12px',
57
+ '4': '16px',
58
+ '6': '24px',
59
+ '8': '32px',
60
+ '12': '48px',
61
+ '16': '64px'
62
+ },
63
+ borderRadius: {
64
+ none: '0'
65
+ },
66
+ boxShadow: {
67
+ glow: '0 0 20px rgba(139, 92, 246, 0.15)'
68
+ },
69
+ fontFamily: {
70
+ mono: ['\'JetBrains Mono\'', 'ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace'],
71
+ sans: ['\'Inter\'', 'ui-sans-serif', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'sans-serif']
72
+ },
73
+ fontWeight: {
74
+ regular: 400,
75
+ medium: 500,
76
+ bold: 700
77
+ },
78
+ fontSize: {
79
+ label: '0.6875rem',
80
+ nav: '0.8125rem',
81
+ body: '0.875rem',
82
+ 'heading-sm': '1.5rem',
83
+ 'heading-md': '2rem',
84
+ 'heading-lg': '2.5rem',
85
+ 'hero-sm': '2.5rem',
86
+ 'hero-md': '3rem',
87
+ 'hero-lg': '4rem'
88
+ },
89
+ letterSpacing: {
90
+ tight: '-0.03em',
91
+ heading: '-0.02em',
92
+ normal: '0',
93
+ nav: '0.02em',
94
+ label: '0.05em'
95
+ }
96
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Do not edit directly, this file was auto-generated.
3
+ */
4
+
5
+ :root {
6
+ --color-background-base: #0a0a0f; /** Page background, app shell */
7
+ --color-background-surface: #12121a; /** Cards, panels, modals */
8
+ --color-background-elevated: #1a1a26; /** Hover states, raised elements */
9
+ --color-background-input: #15151f; /** Form fields, text inputs */
10
+ --color-sunset-purple: #8b5cf6; /** Gradient start — protocol, network, deep infrastructure */
11
+ --color-sunset-blue: #6366f1; /** Gradient mid-left — identity, trust, verification */
12
+ --color-sunset-red: #ef4444; /** Gradient mid-right — settlement, payments, action */
13
+ --color-sunset-orange: #f97316; /** Gradient end — community, presence, warmth */
14
+ --color-functional-text-primary: #f0f0f5; /** Primary text */
15
+ --color-functional-text-secondary: #9393a8; /** Secondary text, labels */
16
+ --color-functional-text-muted: #5a5a72; /** Placeholders, disabled */
17
+ --color-functional-success: #22c55e; /** Confirmations, positive states */
18
+ --color-functional-warning: #eab308; /** Warnings, caution */
19
+ --color-functional-error: #ef4444; /** Errors, destructive actions */
20
+ --color-functional-info: #6366f1; /** Informational */
21
+ --color-interactive-border-light: rgba(255, 255, 255, 0.1); /** Card borders */
22
+ --color-interactive-border-light-hover: rgba(255, 255, 255, 0.2); /** Card border hover */
23
+ --color-interactive-border-input: rgba(255, 255, 255, 0.12); /** Input borders */
24
+ --color-interactive-border-secondary: rgba(255, 255, 255, 0.15); /** Secondary button border */
25
+ --color-interactive-border-nav: rgba(255, 255, 255, 0.08); /** Navigation border */
26
+ --color-interactive-scrollbar-thumb: rgba(139, 92, 246, 0.3); /** Scrollbar thumb (purple) */
27
+ --color-gradient-sunset: linear-gradient(135deg, #8b5cf6, #6366f1, #ef4444, #f97316); /** The Imajin sunset gradient */
28
+ --space-1: 4px; /** Tight gaps (icon-to-text) */
29
+ --space-2: 8px; /** Inline spacing, small gaps */
30
+ --space-3: 12px; /** Input padding, list items */
31
+ --space-4: 16px; /** Card padding, section gaps */
32
+ --space-6: 24px; /** Between components */
33
+ --space-8: 32px; /** Section separators */
34
+ --space-12: 48px; /** Page sections */
35
+ --space-16: 64px; /** Hero spacing, major sections */
36
+ --radius-none: 0px; /** Everything */
37
+ --shadow-glow: 0 0 20px rgba(139, 92, 246, 0.15); /** Accent glow on focus/active (purple base) */
38
+ --font-family-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /** Headings, labels, navigation, data, code */
39
+ --font-family-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; /** Body text, long-form reading */
40
+ --font-weight-regular: 400; /** Body, data, code */
41
+ --font-weight-medium: 500; /** Labels, nav items */
42
+ --font-weight-bold: 700; /** Headings, hero/display */
43
+ --font-size-label: 0.6875rem; /** Labels (uppercase monospace) */
44
+ --font-size-nav: 0.8125rem; /** Nav items */
45
+ --font-size-body: 0.875rem; /** Body text */
46
+ --font-size-heading-sm: 1.5rem; /** Small headings */
47
+ --font-size-heading-md: 2rem; /** Medium headings */
48
+ --font-size-heading-lg: 2.5rem; /** Large headings */
49
+ --font-size-hero-sm: 2.5rem; /** Hero small */
50
+ --font-size-hero-md: 3rem; /** Hero medium */
51
+ --font-size-hero-lg: 4rem; /** Hero large */
52
+ --font-tracking-tight: -0.03em; /** Hero/display */
53
+ --font-tracking-heading: -0.02em; /** Headings */
54
+ --font-tracking-normal: 0px; /** Body, data, code */
55
+ --font-tracking-nav: 0.02em; /** Nav items */
56
+ --font-tracking-label: 0.05em; /** Labels (uppercase) */
57
+ --semantic-surface-1: var(--color-background-base); /** Page background, app shell */
58
+ --semantic-surface-2: var(--color-background-surface); /** Cards, panels, modals */
59
+ --semantic-surface-3: var(--color-background-elevated); /** Hover states, raised elements */
60
+ --semantic-surface-input: var(--color-background-input); /** Form fields */
61
+ --semantic-text-heading: var(--color-functional-text-primary); /** Headings, primary content */
62
+ --semantic-text-body: var(--color-functional-text-secondary); /** Body text, labels */
63
+ --semantic-text-quiet: var(--color-functional-text-muted); /** Placeholders, disabled, muted hints */
64
+ --semantic-text-on-accent: var(--color-functional-text-primary); /** Text on accent/CTA backgrounds */
65
+ --semantic-accent: var(--color-sunset-orange); /** The brand accent. Change this one token to rebrand. Currently warm/orange. */
66
+ --semantic-cta-primary: var(--color-gradient-sunset); /** Primary CTA — sunset gradient */
67
+ --semantic-cta-secondary: var(--color-background-elevated); /** Secondary CTA — quiet surface */
68
+ --semantic-border-subtle: var(--color-interactive-border-light); /** Card and panel borders */
69
+ --semantic-border-strong: var(--color-interactive-border-light-hover); /** Border on hover or emphasis */
70
+ --semantic-border-input: var(--color-interactive-border-input); /** Form field borders */
71
+ --semantic-border-nav: var(--color-interactive-border-nav); /** Navigation dividers */
72
+ --semantic-focus-ring: var(--color-sunset-purple); /** Focus ring color */
73
+ --semantic-focus-glow: var(--shadow-glow); /** Subtle purple glow on focus */
74
+ --semantic-status-success: var(--color-functional-success);
75
+ --semantic-status-warning: var(--color-functional-warning);
76
+ --semantic-status-error: var(--color-functional-error);
77
+ --semantic-status-info: var(--color-functional-info);
78
+ }
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@ima-jin/tokens",
3
+ "version": "1.0.0",
4
+ "description": "Imajin design tokens — DTCG format, built with Style Dictionary v4",
5
+ "main": "./dist/tailwind.js",
6
+ "exports": {
7
+ ".": "./dist/tailwind.js",
8
+ "./tailwind": "./dist/tailwind.js",
9
+ "./dist/tailwind.js": "./dist/tailwind.js",
10
+ "./css": "./dist/variables.css",
11
+ "./variables.css": "./dist/variables.css",
12
+ "./dist/variables.css": "./dist/variables.css"
13
+ },
14
+ "files": [
15
+ "dist/",
16
+ "tokens.json",
17
+ "build.mjs"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ }
22
+ }
package/tokens.json ADDED
@@ -0,0 +1,232 @@
1
+ {
2
+ "color": {
3
+ "$description": "Imajin color tokens — sunset on black",
4
+ "background": {
5
+ "base": {
6
+ "$value": "#0a0a0f",
7
+ "$type": "color",
8
+ "$description": "Page background, app shell"
9
+ },
10
+ "surface": {
11
+ "$value": "#12121a",
12
+ "$type": "color",
13
+ "$description": "Cards, panels, modals"
14
+ },
15
+ "elevated": {
16
+ "$value": "#1a1a26",
17
+ "$type": "color",
18
+ "$description": "Hover states, raised elements"
19
+ },
20
+ "input": {
21
+ "$value": "#15151f",
22
+ "$type": "color",
23
+ "$description": "Form fields, text inputs"
24
+ }
25
+ },
26
+ "sunset": {
27
+ "purple": {
28
+ "$value": "#8b5cf6",
29
+ "$type": "color",
30
+ "$description": "Gradient start — protocol, network, deep infrastructure"
31
+ },
32
+ "blue": {
33
+ "$value": "#6366f1",
34
+ "$type": "color",
35
+ "$description": "Gradient mid-left — identity, trust, verification"
36
+ },
37
+ "red": {
38
+ "$value": "#ef4444",
39
+ "$type": "color",
40
+ "$description": "Gradient mid-right — settlement, payments, action"
41
+ },
42
+ "orange": {
43
+ "$value": "#f97316",
44
+ "$type": "color",
45
+ "$description": "Gradient end — community, presence, warmth"
46
+ }
47
+ },
48
+ "functional": {
49
+ "text-primary": {
50
+ "$value": "#f0f0f5",
51
+ "$type": "color",
52
+ "$description": "Primary text"
53
+ },
54
+ "text-secondary": {
55
+ "$value": "#9393a8",
56
+ "$type": "color",
57
+ "$description": "Secondary text, labels"
58
+ },
59
+ "text-muted": {
60
+ "$value": "#5a5a72",
61
+ "$type": "color",
62
+ "$description": "Placeholders, disabled"
63
+ },
64
+ "success": {
65
+ "$value": "#22c55e",
66
+ "$type": "color",
67
+ "$description": "Confirmations, positive states"
68
+ },
69
+ "warning": {
70
+ "$value": "#eab308",
71
+ "$type": "color",
72
+ "$description": "Warnings, caution"
73
+ },
74
+ "error": {
75
+ "$value": "#ef4444",
76
+ "$type": "color",
77
+ "$description": "Errors, destructive actions"
78
+ },
79
+ "info": {
80
+ "$value": "#6366f1",
81
+ "$type": "color",
82
+ "$description": "Informational"
83
+ }
84
+ },
85
+ "interactive": {
86
+ "border-light": {
87
+ "$value": "rgba(255, 255, 255, 0.1)",
88
+ "$type": "color",
89
+ "$description": "Card borders"
90
+ },
91
+ "border-light-hover": {
92
+ "$value": "rgba(255, 255, 255, 0.2)",
93
+ "$type": "color",
94
+ "$description": "Card border hover"
95
+ },
96
+ "border-input": {
97
+ "$value": "rgba(255, 255, 255, 0.12)",
98
+ "$type": "color",
99
+ "$description": "Input borders"
100
+ },
101
+ "border-secondary": {
102
+ "$value": "rgba(255, 255, 255, 0.15)",
103
+ "$type": "color",
104
+ "$description": "Secondary button border"
105
+ },
106
+ "border-nav": {
107
+ "$value": "rgba(255, 255, 255, 0.08)",
108
+ "$type": "color",
109
+ "$description": "Navigation border"
110
+ },
111
+ "scrollbar-thumb": {
112
+ "$value": "rgba(139, 92, 246, 0.3)",
113
+ "$type": "color",
114
+ "$description": "Scrollbar thumb (purple)"
115
+ }
116
+ },
117
+ "gradient": {
118
+ "sunset": {
119
+ "$value": "linear-gradient(135deg, #8b5cf6, #6366f1, #ef4444, #f97316)",
120
+ "$type": "other",
121
+ "$description": "The Imajin sunset gradient"
122
+ }
123
+ }
124
+ },
125
+ "space": {
126
+ "$description": "4px base unit spacing system",
127
+ "1": { "$value": "4px", "$type": "dimension", "$description": "Tight gaps (icon-to-text)" },
128
+ "2": { "$value": "8px", "$type": "dimension", "$description": "Inline spacing, small gaps" },
129
+ "3": { "$value": "12px", "$type": "dimension", "$description": "Input padding, list items" },
130
+ "4": { "$value": "16px", "$type": "dimension", "$description": "Card padding, section gaps" },
131
+ "6": { "$value": "24px", "$type": "dimension", "$description": "Between components" },
132
+ "8": { "$value": "32px", "$type": "dimension", "$description": "Section separators" },
133
+ "12": { "$value": "48px", "$type": "dimension", "$description": "Page sections" },
134
+ "16": { "$value": "64px", "$type": "dimension", "$description": "Hero spacing, major sections" }
135
+ },
136
+ "radius": {
137
+ "$description": "Border radius — zero everywhere",
138
+ "none": { "$value": "0", "$type": "dimension", "$description": "Everything" }
139
+ },
140
+ "shadow": {
141
+ "$description": "Shadows — almost none",
142
+ "glow": {
143
+ "$value": "0 0 20px rgba(139, 92, 246, 0.15)",
144
+ "$type": "other",
145
+ "$description": "Accent glow on focus/active (purple base)"
146
+ }
147
+ },
148
+ "font": {
149
+ "$description": "Typography tokens",
150
+ "family": {
151
+ "mono": {
152
+ "$value": ["'JetBrains Mono'", "ui-monospace", "SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", "monospace"],
153
+ "$type": "fontFamily",
154
+ "$description": "Headings, labels, navigation, data, code"
155
+ },
156
+ "sans": {
157
+ "$value": ["'Inter'", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "sans-serif"],
158
+ "$type": "fontFamily",
159
+ "$description": "Body text, long-form reading"
160
+ }
161
+ },
162
+ "weight": {
163
+ "regular": { "$value": 400, "$type": "fontWeight", "$description": "Body, data, code" },
164
+ "medium": { "$value": 500, "$type": "fontWeight", "$description": "Labels, nav items" },
165
+ "bold": { "$value": 700, "$type": "fontWeight", "$description": "Headings, hero/display" }
166
+ },
167
+ "size": {
168
+ "label": { "$value": "0.6875rem", "$type": "dimension", "$description": "Labels (uppercase monospace)" },
169
+ "nav": { "$value": "0.8125rem", "$type": "dimension", "$description": "Nav items" },
170
+ "body": { "$value": "0.875rem", "$type": "dimension", "$description": "Body text" },
171
+ "heading-sm": { "$value": "1.5rem", "$type": "dimension", "$description": "Small headings" },
172
+ "heading-md": { "$value": "2rem", "$type": "dimension", "$description": "Medium headings" },
173
+ "heading-lg": { "$value": "2.5rem", "$type": "dimension", "$description": "Large headings" },
174
+ "hero-sm": { "$value": "2.5rem", "$type": "dimension", "$description": "Hero small" },
175
+ "hero-md": { "$value": "3rem", "$type": "dimension", "$description": "Hero medium" },
176
+ "hero-lg": { "$value": "4rem", "$type": "dimension", "$description": "Hero large" }
177
+ },
178
+ "tracking": {
179
+ "tight": { "$value": "-0.03em", "$type": "dimension", "$description": "Hero/display" },
180
+ "heading": { "$value": "-0.02em", "$type": "dimension", "$description": "Headings" },
181
+ "normal": { "$value": "0", "$type": "dimension", "$description": "Body, data, code" },
182
+ "nav": { "$value": "0.02em", "$type": "dimension", "$description": "Nav items" },
183
+ "label": { "$value": "0.05em", "$type": "dimension", "$description": "Labels (uppercase)" }
184
+ }
185
+ },
186
+ "semantic": {
187
+ "$description": "Semantic tokens — role-based aliases for raw colors. App code and UI primitives reference these, NOT the raw tokens. If you change the brand from orange to teal, you change semantic.accent here, not 200 components.",
188
+ "surface": {
189
+ "$description": "Layered backgrounds — 1 is page, 2 is cards/panels, 3 is hover/raised, input is form fields",
190
+ "1": { "$value": "{color.background.base}", "$type": "color", "$description": "Page background, app shell" },
191
+ "2": { "$value": "{color.background.surface}", "$type": "color", "$description": "Cards, panels, modals" },
192
+ "3": { "$value": "{color.background.elevated}", "$type": "color", "$description": "Hover states, raised elements" },
193
+ "input": { "$value": "{color.background.input}", "$type": "color", "$description": "Form fields" }
194
+ },
195
+ "text": {
196
+ "$description": "Text hierarchy — heading, body, quiet (descending prominence)",
197
+ "heading": { "$value": "{color.functional.text-primary}", "$type": "color", "$description": "Headings, primary content" },
198
+ "body": { "$value": "{color.functional.text-secondary}", "$type": "color", "$description": "Body text, labels" },
199
+ "quiet": { "$value": "{color.functional.text-muted}", "$type": "color", "$description": "Placeholders, disabled, muted hints" },
200
+ "on-accent": { "$value": "{color.functional.text-primary}", "$type": "color", "$description": "Text on accent/CTA backgrounds" }
201
+ },
202
+ "accent": {
203
+ "$description": "The brand accent. Change this one token to rebrand. Currently warm/orange.",
204
+ "$value": "{color.sunset.orange}",
205
+ "$type": "color"
206
+ },
207
+ "cta": {
208
+ "$description": "Call-to-action backgrounds — primary uses the brand gradient, secondary is a quiet button surface",
209
+ "primary": { "$value": "{color.gradient.sunset}", "$type": "other", "$description": "Primary CTA — sunset gradient" },
210
+ "secondary": { "$value": "{color.background.elevated}", "$type": "color", "$description": "Secondary CTA — quiet surface" }
211
+ },
212
+ "border": {
213
+ "$description": "Border tokens by purpose — subtle for cards, input for forms, focus for active state",
214
+ "subtle": { "$value": "{color.interactive.border-light}", "$type": "color", "$description": "Card and panel borders" },
215
+ "strong": { "$value": "{color.interactive.border-light-hover}", "$type": "color", "$description": "Border on hover or emphasis" },
216
+ "input": { "$value": "{color.interactive.border-input}", "$type": "color", "$description": "Form field borders" },
217
+ "nav": { "$value": "{color.interactive.border-nav}", "$type": "color", "$description": "Navigation dividers" }
218
+ },
219
+ "focus": {
220
+ "$description": "Focus ring — anchored on purple per DESIGN.md",
221
+ "ring": { "$value": "{color.sunset.purple}", "$type": "color", "$description": "Focus ring color" },
222
+ "glow": { "$value": "{shadow.glow}", "$type": "other", "$description": "Subtle purple glow on focus" }
223
+ },
224
+ "status": {
225
+ "$description": "Status colors — same values as functional but named by intent",
226
+ "success": { "$value": "{color.functional.success}", "$type": "color" },
227
+ "warning": { "$value": "{color.functional.warning}", "$type": "color" },
228
+ "error": { "$value": "{color.functional.error}", "$type": "color" },
229
+ "info": { "$value": "{color.functional.info}", "$type": "color" }
230
+ }
231
+ }
232
+ }