@campfire-interactive/design-tokens 0.1.1 → 0.2.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,89 @@
1
+ # @campfire-interactive/design-tokens
2
+
3
+ The source of truth for every shared value in the Campfire Suite — colors, type,
4
+ spacing, radii, shadows, motion, z-index, chart series and chrome dimensions —
5
+ as CSS custom properties under a `--cfi-` prefix.
6
+
7
+ `tokens.css` is the source; `tokens.json` is generated from it by
8
+ `scripts/generate.mjs` and resolves the `var(--cfi-app-*, fallback)` chains to
9
+ literals for non-CSS consumers.
10
+
11
+ ## ⚠ 0.2.x is a rewrite, and adoption is not open yet
12
+
13
+ 0.1.1 had 42 tokens. 0.2.0 has 148, in three layers, with an opt-in dark theme.
14
+ The semantic naming is **not settled** until more than one app has migrated onto
15
+ it, so treat these names as movable.
16
+
17
+ One name already moved: the orange ramp is `--cfi-color-orange-*`, renamed from
18
+ `--cfi-color-primary-*`. Raw scales in this file are named by hue, so a role word
19
+ in a palette slot read as "the primary color" — which is how buttons ended up
20
+ wired to it. It is master-data's and pim's app-identity color. The color of
21
+ anything you press is `--cfi-action`.
22
+
23
+ Three published packages still reference the old name with literal fallbacks
24
+ (`shell-header`, `side-nav`, `volume-intelligence-ui`), and that is deliberate:
25
+ with the token gone they keep rendering their own literals, which is exactly
26
+ what they render today. No alias is provided, because an alias would resolve
27
+ `volume-intelligence-ui`'s blue buttons to orange the moment an app imports
28
+ this file.
29
+
30
+ `^0.1.1` does not resolve to 0.2.0 — a caret below 1.0 never crosses a minor —
31
+ so nothing picks this up by accident. Bumping to `^0.2.0` is a deliberate act,
32
+ and the gate for it is in the repo's `CLAUDE.md`.
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ npm i @campfire-interactive/design-tokens
38
+ ```
39
+
40
+ ```ts
41
+ // once, at the app entry point, BEFORE the app's own stylesheets
42
+ import '@campfire-interactive/design-tokens/tokens.css';
43
+ ```
44
+
45
+ Declaring the dependency does nothing on its own. It was a dependency of eleven
46
+ frontends and imported by none of them; the `--cfi-*` variables reached those
47
+ pages only because `shell-header` and `side-nav` bundle their own use of them.
48
+ Import the stylesheet, or the tokens are not there.
49
+
50
+ ## The three layers, and which one to reference
51
+
52
+ 1. **Raw scales** — `--cfi-color-gray-500`, `--cfi-font-size-sm`. Palette values.
53
+ Reference these only when defining a semantic token.
54
+ 2. **Semantic roles** — `--cfi-surface`, `--cfi-content-muted`, `--cfi-border`,
55
+ `--cfi-action`, the focus ring, the overlay. **This is what component CSS
56
+ should use.** A component that reaches past these into a raw gray cannot be
57
+ re-themed and breaks in dark mode.
58
+ 3. **App overrides** — `--cfi-app-primary` and friends. The app's own identity
59
+ color, for the shell badge. Set these in the consuming app.
60
+
61
+ ### Two colors, two jobs
62
+
63
+ `--cfi-action` is the suite-wide color for anything you press — buttons, links,
64
+ focus rings, selected rows. Its value is omsf's `#030213`, because omsf is the
65
+ reference for main styles. It is identical in every app; that is the point of it.
66
+
67
+ `--cfi-app-primary` is the app's identity color, and its only job is the app
68
+ badge in the shell header plus its tile in the app switcher. The canonical value
69
+ per app is the `color` field in `shell-header`'s `appCatalog`.
70
+
71
+ **Do not point one at the other.** Wiring buttons to the app color makes the
72
+ same primary button violet in one app, sky blue in another and indigo in a
73
+ third — the opposite of a design system.
74
+
75
+ ## Dark mode is opt-in
76
+
77
+ ```html
78
+ <html data-theme="dark"> <!-- explicit -->
79
+ <html class="cfi-theme-auto"> <!-- follow the OS -->
80
+ ```
81
+
82
+ Neither happens by accident, so adding this file to an app that has never
83
+ considered dark mode cannot change how it looks today.
84
+
85
+ ## Status colors
86
+
87
+ Each semantic hue carries a `-soft` background and a `-text` foreground that
88
+ meets 4.5:1 against it. Use the pair. `bg-[#10B981]/10 text-[#10B981]` — the
89
+ shape several apps had — lands near 2:1.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@campfire-interactive/design-tokens",
3
- "version": "0.1.1",
4
- "description": "Shared design tokens for Campfire Suite",
3
+ "version": "0.2.0",
4
+ "description": "Shared design tokens for Campfire Suite — raw scales, semantic roles, per-app accent hooks, and an opt-in dark theme",
5
5
  "main": "src/tokens.css",
6
6
  "exports": {
7
7
  ".": "./src/tokens.css",
@@ -11,8 +11,13 @@
11
11
  "files": [
12
12
  "src"
13
13
  ],
14
+ "scripts": {
15
+ "build": "node scripts/generate.mjs",
16
+ "prepublishOnly": "node scripts/guard-publish.mjs && node scripts/generate.mjs"
17
+ },
14
18
  "publishConfig": {
15
19
  "registry": "https://registry.npmjs.org",
16
20
  "access": "public"
17
- }
21
+ },
22
+ "_notReady": "0.2.x is UNVETTED — no app has migrated onto the semantic-role layer yet. scripts/guard-publish.mjs blocks npm publish; see docs/plans/2026-09-09-ui-package-and-showcase.md."
18
23
  }
package/src/tokens.css CHANGED
@@ -1,13 +1,65 @@
1
+ /* =============================================================================
2
+ * Campfire Suite design tokens
3
+ * =============================================================================
4
+ *
5
+ * The source of truth for every shared value in the suite. `tokens.json` and
6
+ * the Tailwind preset are GENERATED from this file — run `npm run build` in
7
+ * this package after editing (scripts/generate.mjs), never hand-edit those.
8
+ *
9
+ * Three layers, and the layer you reference matters:
10
+ *
11
+ * 1. RAW SCALES --cfi-color-gray-500, --cfi-font-size-sm, …
12
+ * Palette values. Reference these only when defining a
13
+ * semantic token below.
14
+ * 2. SEMANTIC ROLES --cfi-surface, --cfi-content-muted, --cfi-border, …
15
+ * What components should use. A component that reaches
16
+ * past these into a raw gray cannot be re-themed and
17
+ * breaks in dark mode.
18
+ * 3. APP OVERRIDES --cfi-app-primary, --cfi-app-surface, …
19
+ * The app's own identity color, for the shell badge.
20
+ * Set these in the consuming app; every shared component
21
+ * reads them with a fallback chain, so an app that sets
22
+ * nothing still renders correctly. Controls do NOT read
23
+ * them — buttons and links come from `--cfi-action`.
24
+ *
25
+ * NO DARK THEME. There was one — two blocks of 59 tokens, an explicit
26
+ * `data-theme="dark"` and a follow-the-OS copy — and no app ever stamped
27
+ * either, so it never rendered once. It was not free: every token change cost
28
+ * three edits instead of one, it needed a build-time check to stop the two
29
+ * copies drifting, and it drifted anyway (the OS copy was missing the action
30
+ * and chart tokens, so that path painted a near-black button on a near-black
31
+ * ground). A half-maintained dark theme is worse than none, because it looks
32
+ * supported until someone turns it on.
33
+ *
34
+ * Rebuild it when a real app wants it, against that app's screens.
35
+ *
36
+ * Usage:
37
+ * import '@campfire-interactive/design-tokens/tokens.css';
38
+ * at the app's entry point, BEFORE the app's own stylesheets.
39
+ * ============================================================================= */
40
+
1
41
  :root {
2
- /* ── Primary (Orange) ──────────────────────────────────────────── */
3
- --cfi-color-primary-50: #fff7ed;
4
- --cfi-color-primary-100: #ffedd5;
5
- --cfi-color-primary-200: #fed7aa;
6
- --cfi-color-primary-500: #f97316;
7
- --cfi-color-primary-600: #ea580c;
8
- --cfi-color-primary-700: #c2410c;
9
-
10
- /* ── Gray Scale ────────────────────────────────────────────────── */
42
+ /* ═══ RAW SCALES ═══════════════════════════════════════════════════════════
43
+ * Palette only. Prefer a semantic role below in component CSS. */
44
+
45
+ /* ── Orange ────────────────────────────────────────────────
46
+ * Campfire orange. It is master-data's and pim's app-identity color, which
47
+ * is the only job it has. It was called `--cfi-color-primary-*`, and that
48
+ * name is why buttons ended up wired to it: raw scales in this file are
49
+ * named by HUE (see gray, below), so a role word in a palette slot reads as
50
+ * "the primary color". The color of anything you press is `--cfi-action`. */
51
+ --cfi-color-orange-50: #fff7ed;
52
+ --cfi-color-orange-100: #ffedd5;
53
+ --cfi-color-orange-200: #fed7aa;
54
+ --cfi-color-orange-300: #fdba74;
55
+ --cfi-color-orange-400: #fb923c;
56
+ --cfi-color-orange-500: #f97316;
57
+ --cfi-color-orange-600: #ea580c;
58
+ --cfi-color-orange-700: #c2410c;
59
+ --cfi-color-orange-800: #9a3412;
60
+ --cfi-color-orange-900: #7c2d12;
61
+
62
+ /* ── Gray scale ──────────────────────────────────────────────────── */
11
63
  --cfi-color-gray-50: #f9fafb;
12
64
  --cfi-color-gray-100: #f3f4f6;
13
65
  --cfi-color-gray-200: #e5e7eb;
@@ -18,37 +70,278 @@
18
70
  --cfi-color-gray-700: #374151;
19
71
  --cfi-color-gray-800: #1f2937;
20
72
  --cfi-color-gray-900: #111827;
73
+ --cfi-color-gray-950: #030712;
74
+
75
+ --cfi-color-white: #ffffff;
76
+ --cfi-color-black: #000000;
21
77
 
22
- /* ── Semantic ──────────────────────────────────────────────────── */
78
+ /* ── Semantic hues ───────────────────────────────────────────────────
79
+ * Each carries a `-soft` background and a `-text` foreground that meets
80
+ * 4.5:1 against that background. Apps were hard-coding `/10` alpha of the
81
+ * base color and putting the base color on top of it, which does not. */
23
82
  --cfi-color-success: #10b981;
83
+ --cfi-color-success-soft: #ecfdf5;
84
+ --cfi-color-success-text: #047857;
85
+ --cfi-color-success-border: #a7f3d0;
86
+
24
87
  --cfi-color-warning: #f59e0b;
88
+ --cfi-color-warning-soft: #fffbeb;
89
+ --cfi-color-warning-text: #b45309;
90
+ --cfi-color-warning-border: #fde68a;
91
+
25
92
  --cfi-color-error: #ef4444;
93
+ /* A SOLID FILL that carries white text needs a darker red than an indicator
94
+ dot does. White on #ef4444 is 3.76:1 and fails AA; on #dc2626 it is 4.83:1.
95
+ The base stays red-500 because that is the right weight for a dot, a bar or
96
+ a border — this is the value for a destructive button. The other hues gain
97
+ a `-strong` the day one of them is used as a solid fill under white text. */
98
+ --cfi-color-error-strong: #dc2626;
99
+ --cfi-color-error-soft: #fef2f2;
100
+ --cfi-color-error-text: #b91c1c;
101
+ --cfi-color-error-border: #fecaca;
102
+
26
103
  --cfi-color-info: #3b82f6;
104
+ --cfi-color-info-soft: #eff6ff;
105
+ --cfi-color-info-text: #1d4ed8;
106
+ --cfi-color-info-border: #bfdbfe;
107
+
108
+ /* A base neutral for "no verdict / not assessed", which the other hues
109
+ have and this one lacked. pm needs it for an unassessed RAG category:
110
+ grey, and deliberately not green, because "not assessed" and "assessed
111
+ as fine" are different answers. */
112
+ --cfi-color-neutral: #9ca3af;
113
+ --cfi-color-neutral-soft: #f3f4f6;
114
+ --cfi-color-neutral-text: #374151;
115
+ --cfi-color-neutral-border: #e5e7eb;
116
+
117
+ /* ── Categorical chart series ────────────────────────────────────────
118
+ * Ordered so the first four stay separable for the most common color
119
+ * deficiencies — the pairs that collide (orange/green, blue/violet) are kept
120
+ * apart in the sequence rather than adjacent. Series color is never the
121
+ * only encoding: charts label their series directly or carry a legend.
122
+ * Nine apps use recharts today and every one picked its own colors. */
123
+ --cfi-chart-1: #ea580c;
124
+ --cfi-chart-2: #0e7490;
125
+ --cfi-chart-3: #7c3aed;
126
+ --cfi-chart-4: #059669;
127
+ --cfi-chart-5: #b45309;
128
+ --cfi-chart-6: #be185d;
129
+ --cfi-chart-7: #1d4ed8;
130
+ --cfi-chart-8: #4d7c0f;
131
+
132
+ /* Chart chrome — grid, axis and tick colors follow the theme. */
133
+ --cfi-chart-grid: var(--cfi-color-gray-200);
134
+ --cfi-chart-axis: var(--cfi-color-gray-300);
135
+ --cfi-chart-label: var(--cfi-color-gray-500);
136
+
137
+ /* ═══ SEMANTIC ROLES ══════════════════════════════════════════════════════
138
+ * What component CSS should reference. These are what dark mode redefines. */
139
+
140
+ /* ── Surfaces ────────────────────────────────────────────────────── */
141
+ --cfi-surface: var(--cfi-color-white);
142
+ --cfi-surface-raised: var(--cfi-color-white);
143
+ --cfi-surface-sunken: var(--cfi-color-gray-50);
144
+ --cfi-surface-hover: var(--cfi-color-gray-50);
145
+ --cfi-surface-active: var(--cfi-color-gray-100);
146
+ --cfi-surface-selected: var(--cfi-color-gray-100);
147
+ --cfi-surface-disabled: var(--cfi-color-gray-100);
148
+ /* A muted FILL, distinct from the page ground. omsf: --muted: #ececf0.
149
+ Mapping this to surface-sunken made every muted tray (tab strips,
150
+ segmented controls) read a shade too light against the page. */
151
+ --cfi-surface-muted: #ececf0;
152
+ /* Form-control fills, from omsf: --input-background and --switch-background.
153
+ The preset was mapping these to the plain surface and to gray-300, which
154
+ made checkboxes white instead of tinted and switch tracks a shade off. */
155
+ --cfi-input-bg: #f3f3f5;
156
+ --cfi-switch-bg: #cbced4;
157
+
158
+ /* ── Content (text and icons) ────────────────────────────────────── */
159
+ /* omsf --foreground. A NEUTRAL dark, not Tailwind gray-900 (#111827), which
160
+ carries a blue tint. The two gray families split the fleet along the same
161
+ 7/5 line as the styling stacks: the shadcn apps use neutral oklch grays,
162
+ the plain-CSS apps use the blue-tinted --color-gray-* scale. omsf is the
163
+ reference, so neutral wins and the plain-CSS apps shift very slightly when
164
+ they migrate. */
165
+ --cfi-content: oklch(0.145 0 0);
166
+ /* Darkened from omsf's --muted-foreground #717182, which is 4.79:1 on white
167
+ but only 4.06:1 on --cfi-surface-muted — and muted text ON the muted tray
168
+ is a pairing the suite uses constantly (67 instances on one pm screen).
169
+ #666676 is 4.78:1 there and 5.63:1 on white, so both pass, and the shift
170
+ from omsf's value is small enough not to read as a different gray.
171
+ Dark mode needs no change: #a9b4c1 on #262d37 is already 7.42:1. */
172
+ --cfi-content-muted: #666676;
173
+ --cfi-content-subtle: var(--cfi-color-gray-400);
174
+ --cfi-content-inverse: var(--cfi-color-white);
175
+ --cfi-content-disabled: var(--cfi-color-gray-400);
176
+ --cfi-content-link: var(--cfi-color-info-text);
27
177
 
28
- /* ── Typography ────────────────────────────────────────────────── */
178
+ /* ── Borders ─────────────────────────────────────────────────────── */
179
+ --cfi-border: var(--cfi-color-gray-200);
180
+ --cfi-border-subtle: var(--cfi-color-gray-100);
181
+ --cfi-border-strong: var(--cfi-color-gray-300);
182
+ --cfi-border-focus: var(--cfi-action);
183
+
184
+ /* ── Interaction ─────────────────────────────────────────────────── */
185
+ --cfi-focus-ring-color: var(--cfi-action);
186
+ --cfi-focus-ring-width: 2px;
187
+ --cfi-focus-ring-offset: 2px;
188
+ --cfi-overlay: rgb(17 24 39 / 0.45);
189
+
190
+ /* ── Action color — buttons, links, focus, selected states ──────────
191
+ * The suite-wide color for "this is the thing to press".
192
+ *
193
+ * Blue, not the near-black `#030213` this used to be. That value came from
194
+ * omsf, but omsf inherited it from Figma Make and never changed it — and the
195
+ * same is true of cpq, analytics and forecast, so "four apps agree" was one
196
+ * generator default four times rather than a decision. Every place in the
197
+ * fleet where somebody actually CHOSE a colour to press chose a blue: omsf's
198
+ * own nav active pill and bom's `--primary` are both #2563eb, and
199
+ * volume-intelligence-ui falls back to it.
200
+ *
201
+ * #2563eb is Tailwind blue-600. White text on it is 5.17:1, clear of AA at
202
+ * every size a button uses; it holds 2.83:1 against the dark nav so a control
203
+ * near the rail stays separate; and using the value omsf already paints its
204
+ * selected state with means buttons and selection are ONE colour instead of
205
+ * two different blues.
206
+ *
207
+ * This is DELIBERATELY NOT the per-app color below. Pointing buttons at
208
+ * `--cfi-app-primary` gives every primary button the app's identity color —
209
+ * the same button violet in analytics, sky blue in omsf, indigo in cpq.
210
+ * Actions look the same everywhere; only the app badge differs. */
211
+ --cfi-action: #2563eb;
212
+ --cfi-action-hover: #1d4ed8;
213
+ --cfi-action-fg: var(--cfi-color-white);
214
+ --cfi-action-soft: #eff6ff;
215
+
216
+ /* ── App identity color ─────────────────────────────────────────────
217
+ * ONE job: the app badge in the shell header — the 28px square with the
218
+ * app's initial, and the matching tile in the app switcher. It exists so a
219
+ * user can tell at a glance which app they are in.
220
+ *
221
+ * The canonical value per app is the `color` field in shell-header's
222
+ * `appCatalog` (omsf #0ea5e9, cpq #4f46e5, analytics #7c3aed, forecast
223
+ * #10b981, pm #e11d48, …). An app sets this to its own catalog color.
224
+ *
225
+ * Do NOT wire buttons, links or focus rings to it — use `--cfi-action`.
226
+ * Defaults to the action color so an app that sets nothing gets a neutral
227
+ * badge rather than a surprise. */
228
+ --cfi-app-primary: var(--cfi-action);
229
+ --cfi-app-primary-hover: var(--cfi-action-hover);
230
+ --cfi-app-primary-soft: var(--cfi-action-soft);
231
+ --cfi-app-primary-fg: var(--cfi-color-white);
232
+ --cfi-app-surface: var(--cfi-surface);
233
+
234
+ /* ═══ TYPOGRAPHY ══════════════════════════════════════════════════════════ */
29
235
  --cfi-font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
236
+ --cfi-font-family-mono: ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Menlo, Consolas, monospace;
237
+
30
238
  --cfi-font-size-xs: 0.75rem;
31
239
  --cfi-font-size-sm: 0.875rem;
32
240
  --cfi-font-size-base: 1rem;
33
241
  --cfi-font-size-lg: 1.125rem;
34
242
  --cfi-font-size-xl: 1.25rem;
35
243
  --cfi-font-size-2xl: 1.5rem;
244
+ --cfi-font-size-3xl: 1.875rem;
245
+
246
+ --cfi-font-weight-normal: 400;
247
+ --cfi-font-weight-medium: 500;
248
+ --cfi-font-weight-semibold: 600;
249
+ --cfi-font-weight-bold: 700;
36
250
 
37
- /* ── Spacing ───────────────────────────────────────────────────── */
251
+ --cfi-line-height-tight: 1.2;
252
+ --cfi-line-height-snug: 1.35;
253
+ --cfi-line-height-normal: 1.5;
254
+ --cfi-line-height-relaxed: 1.65;
255
+
256
+ --cfi-letter-spacing-tight: -0.015em;
257
+ --cfi-letter-spacing-normal: 0;
258
+ --cfi-letter-spacing-wide: 0.04em;
259
+ --cfi-letter-spacing-caps: 0.08em;
260
+
261
+ /* ═══ SPACING ═════════════════════════════════════════════════════════════ */
262
+ --cfi-spacing-3xs: 0.125rem;
263
+ --cfi-spacing-2xs: 0.1875rem;
38
264
  --cfi-spacing-xs: 0.25rem;
39
265
  --cfi-spacing-sm: 0.5rem;
40
266
  --cfi-spacing-md: 1rem;
41
267
  --cfi-spacing-lg: 1.5rem;
42
268
  --cfi-spacing-xl: 2rem;
269
+ --cfi-spacing-2xl: 3rem;
270
+ --cfi-spacing-3xl: 4rem;
271
+
272
+ /* ═══ BORDERS, RADII, SHADOWS ═════════════════════════════════════════════ */
273
+ /* Derived from omsf's `--radius: 0.625rem` the way shadcn derives its scale
274
+ (sm = base-4, md = base-2, lg = base, xl = base+4). The scale here was a
275
+ step tighter at every stop, so every button and card in a migrated app
276
+ came out slightly squarer than it renders today. */
277
+ --cfi-radius-none: 0;
278
+ --cfi-radius-base: 0.625rem; /* 10px — omsf --radius */
279
+ --cfi-radius-sm: 0.375rem; /* 6px */
280
+ --cfi-radius-md: 0.5rem; /* 8px */
281
+ --cfi-radius-lg: 0.625rem; /* 10px */
282
+ --cfi-radius-xl: 0.875rem; /* 14px */
283
+ --cfi-radius-full: 9999px;
43
284
 
44
- /* ── Borders & Shadows ─────────────────────────────────────────── */
45
- --cfi-radius-sm: 0.25rem;
46
- --cfi-radius-md: 0.375rem;
47
- --cfi-radius-lg: 0.5rem;
48
- --cfi-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
49
- --cfi-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
50
- --cfi-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
285
+ --cfi-shadow-xs: 0 1px 1px rgb(17 24 39 / 0.04);
286
+ --cfi-shadow-sm: 0 1px 2px rgb(17 24 39 / 0.05);
287
+ --cfi-shadow-md: 0 4px 6px rgb(17 24 39 / 0.07);
288
+ --cfi-shadow-lg: 0 10px 15px rgb(17 24 39 / 0.1);
289
+ --cfi-shadow-xl: 0 20px 40px -12px rgb(17 24 39 / 0.22);
51
290
 
52
- /* ── Shell Layout ──────────────────────────────────────────────── */
291
+ /* ═══ MOTION ══════════════════════════════════════════════════════════════ */
292
+ --cfi-easing: cubic-bezier(0.4, 0, 0.2, 1);
293
+ --cfi-duration-fast: 120ms;
294
+ --cfi-duration-base: 200ms;
295
+ --cfi-duration-slow: 320ms;
296
+ --cfi-transition-fast: var(--cfi-duration-fast) var(--cfi-easing);
297
+ --cfi-transition-base: var(--cfi-duration-base) var(--cfi-easing);
298
+
299
+ /* ═══ LAYERING ════════════════════════════════════════════════════════════
300
+ * One scale for the whole suite. Overlays that pick their own numbers end up
301
+ * behind the shell header or on top of a modal they were opened from. */
302
+ --cfi-z-base: 0;
303
+ --cfi-z-raised: 10;
304
+ --cfi-z-sticky: 100;
305
+ --cfi-z-shell-header: 200;
306
+ --cfi-z-dropdown: 1000;
307
+ --cfi-z-overlay: 1100;
308
+ --cfi-z-modal: 1200;
309
+ --cfi-z-popover: 1300;
310
+ --cfi-z-toast: 1400;
311
+ --cfi-z-tooltip: 1500;
312
+
313
+ /* ═══ SHELL LAYOUT ════════════════════════════════════════════════════════
314
+ * The canonical chrome dimensions. An app that picks its own header height
315
+ * knocks the side nav out of alignment with the shell — one app is on 57px
316
+ * against the shell's 48px today. */
53
317
  --cfi-shell-header-height: 48px;
318
+ --cfi-sidenav-width: 256px;
319
+ --cfi-sidenav-width-collapsed: 64px;
320
+ --cfi-content-max-width: 1440px;
321
+
322
+ /* ── Side nav palette ────────────────────────────────────────────────
323
+ * The nav is DARK, and it is its own palette rather than the page's.
324
+ *
325
+ * Read off omsf, which is the reference: `aside.w-64 bg-[#1e293b]
326
+ * border-r-[#334155]`, items `text-[#cbd5e1]`, the active item a solid
327
+ * `#2563eb` pill with white text at 8px radius. `help-panel` independently
328
+ * hardcodes the same `#1e293b` as "the colour OMSF paints its sidebar", so
329
+ * two places already agree on it.
330
+ *
331
+ * These are NOT `--cfi-surface` / `--cfi-content`. A dark rail beside a light
332
+ * page is a deliberate two-ground layout — the nav is chrome, not a surface —
333
+ * and resolving it through the page's tokens turns it white, which is the
334
+ * mistake this block exists to prevent. The active item is likewise NOT
335
+ * `--cfi-action`: omsf's is blue, and the near-black action colour would be
336
+ * invisible on this ground.
337
+ *
338
+ * Note these do not flip in the dark theme. The nav is already dark. */
339
+ --cfi-sidenav-bg: #1e293b;
340
+ --cfi-sidenav-border: #334155;
341
+ --cfi-sidenav-fg: #cbd5e1;
342
+ --cfi-sidenav-fg-muted: #94a3b8;
343
+ --cfi-sidenav-item-hover-bg: #334155;
344
+ --cfi-sidenav-item-hover-fg: #ffffff;
345
+ --cfi-sidenav-item-active-bg: #2563eb;
346
+ --cfi-sidenav-item-active-fg: #ffffff;
54
347
  }
@@ -0,0 +1,843 @@
1
+ {
2
+ "$schema": "https://design-tokens.github.io/community-group/format/",
3
+ "$comment": "GENERATED from tokens.css by scripts/generate.mjs — do not edit by hand.",
4
+ "version": "0.2.0",
5
+ "tokens": {
6
+ "color": {
7
+ "orange-50": {
8
+ "value": "#fff7ed",
9
+ "css": "var(--cfi-color-orange-50)",
10
+ "raw": "#fff7ed"
11
+ },
12
+ "orange-100": {
13
+ "value": "#ffedd5",
14
+ "css": "var(--cfi-color-orange-100)",
15
+ "raw": "#ffedd5"
16
+ },
17
+ "orange-200": {
18
+ "value": "#fed7aa",
19
+ "css": "var(--cfi-color-orange-200)",
20
+ "raw": "#fed7aa"
21
+ },
22
+ "orange-300": {
23
+ "value": "#fdba74",
24
+ "css": "var(--cfi-color-orange-300)",
25
+ "raw": "#fdba74"
26
+ },
27
+ "orange-400": {
28
+ "value": "#fb923c",
29
+ "css": "var(--cfi-color-orange-400)",
30
+ "raw": "#fb923c"
31
+ },
32
+ "orange-500": {
33
+ "value": "#f97316",
34
+ "css": "var(--cfi-color-orange-500)",
35
+ "raw": "#f97316"
36
+ },
37
+ "orange-600": {
38
+ "value": "#ea580c",
39
+ "css": "var(--cfi-color-orange-600)",
40
+ "raw": "#ea580c"
41
+ },
42
+ "orange-700": {
43
+ "value": "#c2410c",
44
+ "css": "var(--cfi-color-orange-700)",
45
+ "raw": "#c2410c"
46
+ },
47
+ "orange-800": {
48
+ "value": "#9a3412",
49
+ "css": "var(--cfi-color-orange-800)",
50
+ "raw": "#9a3412"
51
+ },
52
+ "orange-900": {
53
+ "value": "#7c2d12",
54
+ "css": "var(--cfi-color-orange-900)",
55
+ "raw": "#7c2d12"
56
+ },
57
+ "gray-50": {
58
+ "value": "#f9fafb",
59
+ "css": "var(--cfi-color-gray-50)",
60
+ "raw": "#f9fafb"
61
+ },
62
+ "gray-100": {
63
+ "value": "#f3f4f6",
64
+ "css": "var(--cfi-color-gray-100)",
65
+ "raw": "#f3f4f6"
66
+ },
67
+ "gray-200": {
68
+ "value": "#e5e7eb",
69
+ "css": "var(--cfi-color-gray-200)",
70
+ "raw": "#e5e7eb"
71
+ },
72
+ "gray-300": {
73
+ "value": "#d1d5db",
74
+ "css": "var(--cfi-color-gray-300)",
75
+ "raw": "#d1d5db"
76
+ },
77
+ "gray-400": {
78
+ "value": "#9ca3af",
79
+ "css": "var(--cfi-color-gray-400)",
80
+ "raw": "#9ca3af"
81
+ },
82
+ "gray-500": {
83
+ "value": "#6b7280",
84
+ "css": "var(--cfi-color-gray-500)",
85
+ "raw": "#6b7280"
86
+ },
87
+ "gray-600": {
88
+ "value": "#4b5563",
89
+ "css": "var(--cfi-color-gray-600)",
90
+ "raw": "#4b5563"
91
+ },
92
+ "gray-700": {
93
+ "value": "#374151",
94
+ "css": "var(--cfi-color-gray-700)",
95
+ "raw": "#374151"
96
+ },
97
+ "gray-800": {
98
+ "value": "#1f2937",
99
+ "css": "var(--cfi-color-gray-800)",
100
+ "raw": "#1f2937"
101
+ },
102
+ "gray-900": {
103
+ "value": "#111827",
104
+ "css": "var(--cfi-color-gray-900)",
105
+ "raw": "#111827"
106
+ },
107
+ "gray-950": {
108
+ "value": "#030712",
109
+ "css": "var(--cfi-color-gray-950)",
110
+ "raw": "#030712"
111
+ },
112
+ "white": {
113
+ "value": "#ffffff",
114
+ "css": "var(--cfi-color-white)",
115
+ "raw": "#ffffff"
116
+ },
117
+ "black": {
118
+ "value": "#000000",
119
+ "css": "var(--cfi-color-black)",
120
+ "raw": "#000000"
121
+ },
122
+ "success": {
123
+ "value": "#10b981",
124
+ "css": "var(--cfi-color-success)",
125
+ "raw": "#10b981"
126
+ },
127
+ "success-soft": {
128
+ "value": "#ecfdf5",
129
+ "css": "var(--cfi-color-success-soft)",
130
+ "raw": "#ecfdf5"
131
+ },
132
+ "success-text": {
133
+ "value": "#047857",
134
+ "css": "var(--cfi-color-success-text)",
135
+ "raw": "#047857"
136
+ },
137
+ "success-border": {
138
+ "value": "#a7f3d0",
139
+ "css": "var(--cfi-color-success-border)",
140
+ "raw": "#a7f3d0"
141
+ },
142
+ "warning": {
143
+ "value": "#f59e0b",
144
+ "css": "var(--cfi-color-warning)",
145
+ "raw": "#f59e0b"
146
+ },
147
+ "warning-soft": {
148
+ "value": "#fffbeb",
149
+ "css": "var(--cfi-color-warning-soft)",
150
+ "raw": "#fffbeb"
151
+ },
152
+ "warning-text": {
153
+ "value": "#b45309",
154
+ "css": "var(--cfi-color-warning-text)",
155
+ "raw": "#b45309"
156
+ },
157
+ "warning-border": {
158
+ "value": "#fde68a",
159
+ "css": "var(--cfi-color-warning-border)",
160
+ "raw": "#fde68a"
161
+ },
162
+ "error": {
163
+ "value": "#ef4444",
164
+ "css": "var(--cfi-color-error)",
165
+ "raw": "#ef4444"
166
+ },
167
+ "error-strong": {
168
+ "value": "#dc2626",
169
+ "css": "var(--cfi-color-error-strong)",
170
+ "raw": "#dc2626"
171
+ },
172
+ "error-soft": {
173
+ "value": "#fef2f2",
174
+ "css": "var(--cfi-color-error-soft)",
175
+ "raw": "#fef2f2"
176
+ },
177
+ "error-text": {
178
+ "value": "#b91c1c",
179
+ "css": "var(--cfi-color-error-text)",
180
+ "raw": "#b91c1c"
181
+ },
182
+ "error-border": {
183
+ "value": "#fecaca",
184
+ "css": "var(--cfi-color-error-border)",
185
+ "raw": "#fecaca"
186
+ },
187
+ "info": {
188
+ "value": "#3b82f6",
189
+ "css": "var(--cfi-color-info)",
190
+ "raw": "#3b82f6"
191
+ },
192
+ "info-soft": {
193
+ "value": "#eff6ff",
194
+ "css": "var(--cfi-color-info-soft)",
195
+ "raw": "#eff6ff"
196
+ },
197
+ "info-text": {
198
+ "value": "#1d4ed8",
199
+ "css": "var(--cfi-color-info-text)",
200
+ "raw": "#1d4ed8"
201
+ },
202
+ "info-border": {
203
+ "value": "#bfdbfe",
204
+ "css": "var(--cfi-color-info-border)",
205
+ "raw": "#bfdbfe"
206
+ },
207
+ "neutral": {
208
+ "value": "#9ca3af",
209
+ "css": "var(--cfi-color-neutral)",
210
+ "raw": "#9ca3af"
211
+ },
212
+ "neutral-soft": {
213
+ "value": "#f3f4f6",
214
+ "css": "var(--cfi-color-neutral-soft)",
215
+ "raw": "#f3f4f6"
216
+ },
217
+ "neutral-text": {
218
+ "value": "#374151",
219
+ "css": "var(--cfi-color-neutral-text)",
220
+ "raw": "#374151"
221
+ },
222
+ "neutral-border": {
223
+ "value": "#e5e7eb",
224
+ "css": "var(--cfi-color-neutral-border)",
225
+ "raw": "#e5e7eb"
226
+ }
227
+ },
228
+ "chart": {
229
+ "1": {
230
+ "value": "#ea580c",
231
+ "css": "var(--cfi-chart-1)",
232
+ "raw": "#ea580c"
233
+ },
234
+ "2": {
235
+ "value": "#0e7490",
236
+ "css": "var(--cfi-chart-2)",
237
+ "raw": "#0e7490"
238
+ },
239
+ "3": {
240
+ "value": "#7c3aed",
241
+ "css": "var(--cfi-chart-3)",
242
+ "raw": "#7c3aed"
243
+ },
244
+ "4": {
245
+ "value": "#059669",
246
+ "css": "var(--cfi-chart-4)",
247
+ "raw": "#059669"
248
+ },
249
+ "5": {
250
+ "value": "#b45309",
251
+ "css": "var(--cfi-chart-5)",
252
+ "raw": "#b45309"
253
+ },
254
+ "6": {
255
+ "value": "#be185d",
256
+ "css": "var(--cfi-chart-6)",
257
+ "raw": "#be185d"
258
+ },
259
+ "7": {
260
+ "value": "#1d4ed8",
261
+ "css": "var(--cfi-chart-7)",
262
+ "raw": "#1d4ed8"
263
+ },
264
+ "8": {
265
+ "value": "#4d7c0f",
266
+ "css": "var(--cfi-chart-8)",
267
+ "raw": "#4d7c0f"
268
+ },
269
+ "grid": {
270
+ "value": "#e5e7eb",
271
+ "css": "var(--cfi-chart-grid)",
272
+ "raw": "var(--cfi-color-gray-200)"
273
+ },
274
+ "axis": {
275
+ "value": "#d1d5db",
276
+ "css": "var(--cfi-chart-axis)",
277
+ "raw": "var(--cfi-color-gray-300)"
278
+ },
279
+ "label": {
280
+ "value": "#6b7280",
281
+ "css": "var(--cfi-chart-label)",
282
+ "raw": "var(--cfi-color-gray-500)"
283
+ }
284
+ },
285
+ "surface": {
286
+ "surface": {
287
+ "value": "#ffffff",
288
+ "css": "var(--cfi-surface)",
289
+ "raw": "var(--cfi-color-white)"
290
+ },
291
+ "raised": {
292
+ "value": "#ffffff",
293
+ "css": "var(--cfi-surface-raised)",
294
+ "raw": "var(--cfi-color-white)"
295
+ },
296
+ "sunken": {
297
+ "value": "#f9fafb",
298
+ "css": "var(--cfi-surface-sunken)",
299
+ "raw": "var(--cfi-color-gray-50)"
300
+ },
301
+ "hover": {
302
+ "value": "#f9fafb",
303
+ "css": "var(--cfi-surface-hover)",
304
+ "raw": "var(--cfi-color-gray-50)"
305
+ },
306
+ "active": {
307
+ "value": "#f3f4f6",
308
+ "css": "var(--cfi-surface-active)",
309
+ "raw": "var(--cfi-color-gray-100)"
310
+ },
311
+ "selected": {
312
+ "value": "#f3f4f6",
313
+ "css": "var(--cfi-surface-selected)",
314
+ "raw": "var(--cfi-color-gray-100)"
315
+ },
316
+ "disabled": {
317
+ "value": "#f3f4f6",
318
+ "css": "var(--cfi-surface-disabled)",
319
+ "raw": "var(--cfi-color-gray-100)"
320
+ },
321
+ "muted": {
322
+ "value": "#ececf0",
323
+ "css": "var(--cfi-surface-muted)",
324
+ "raw": "#ececf0"
325
+ }
326
+ },
327
+ "input": {
328
+ "bg": {
329
+ "value": "#f3f3f5",
330
+ "css": "var(--cfi-input-bg)",
331
+ "raw": "#f3f3f5"
332
+ }
333
+ },
334
+ "switch": {
335
+ "bg": {
336
+ "value": "#cbced4",
337
+ "css": "var(--cfi-switch-bg)",
338
+ "raw": "#cbced4"
339
+ }
340
+ },
341
+ "content": {
342
+ "content": {
343
+ "value": "oklch(0.145 0 0)",
344
+ "css": "var(--cfi-content)",
345
+ "raw": "oklch(0.145 0 0)"
346
+ },
347
+ "muted": {
348
+ "value": "#666676",
349
+ "css": "var(--cfi-content-muted)",
350
+ "raw": "#666676"
351
+ },
352
+ "subtle": {
353
+ "value": "#9ca3af",
354
+ "css": "var(--cfi-content-subtle)",
355
+ "raw": "var(--cfi-color-gray-400)"
356
+ },
357
+ "inverse": {
358
+ "value": "#ffffff",
359
+ "css": "var(--cfi-content-inverse)",
360
+ "raw": "var(--cfi-color-white)"
361
+ },
362
+ "disabled": {
363
+ "value": "#9ca3af",
364
+ "css": "var(--cfi-content-disabled)",
365
+ "raw": "var(--cfi-color-gray-400)"
366
+ },
367
+ "link": {
368
+ "value": "#1d4ed8",
369
+ "css": "var(--cfi-content-link)",
370
+ "raw": "var(--cfi-color-info-text)"
371
+ },
372
+ "max-width": {
373
+ "value": "1440px",
374
+ "css": "var(--cfi-content-max-width)",
375
+ "raw": "1440px"
376
+ }
377
+ },
378
+ "border": {
379
+ "border": {
380
+ "value": "#e5e7eb",
381
+ "css": "var(--cfi-border)",
382
+ "raw": "var(--cfi-color-gray-200)"
383
+ },
384
+ "subtle": {
385
+ "value": "#f3f4f6",
386
+ "css": "var(--cfi-border-subtle)",
387
+ "raw": "var(--cfi-color-gray-100)"
388
+ },
389
+ "strong": {
390
+ "value": "#d1d5db",
391
+ "css": "var(--cfi-border-strong)",
392
+ "raw": "var(--cfi-color-gray-300)"
393
+ },
394
+ "focus": {
395
+ "value": "#2563eb",
396
+ "css": "var(--cfi-border-focus)",
397
+ "raw": "var(--cfi-action)"
398
+ }
399
+ },
400
+ "focus": {
401
+ "ring-color": {
402
+ "value": "#2563eb",
403
+ "css": "var(--cfi-focus-ring-color)",
404
+ "raw": "var(--cfi-action)"
405
+ },
406
+ "ring-width": {
407
+ "value": "2px",
408
+ "css": "var(--cfi-focus-ring-width)",
409
+ "raw": "2px"
410
+ },
411
+ "ring-offset": {
412
+ "value": "2px",
413
+ "css": "var(--cfi-focus-ring-offset)",
414
+ "raw": "2px"
415
+ }
416
+ },
417
+ "overlay": {
418
+ "overlay": {
419
+ "value": "rgb(17 24 39 / 0.45)",
420
+ "css": "var(--cfi-overlay)",
421
+ "raw": "rgb(17 24 39 / 0.45)"
422
+ }
423
+ },
424
+ "action": {
425
+ "action": {
426
+ "value": "#2563eb",
427
+ "css": "var(--cfi-action)",
428
+ "raw": "#2563eb"
429
+ },
430
+ "hover": {
431
+ "value": "#1d4ed8",
432
+ "css": "var(--cfi-action-hover)",
433
+ "raw": "#1d4ed8"
434
+ },
435
+ "fg": {
436
+ "value": "#ffffff",
437
+ "css": "var(--cfi-action-fg)",
438
+ "raw": "var(--cfi-color-white)"
439
+ },
440
+ "soft": {
441
+ "value": "#eff6ff",
442
+ "css": "var(--cfi-action-soft)",
443
+ "raw": "#eff6ff"
444
+ }
445
+ },
446
+ "app": {
447
+ "primary": {
448
+ "value": "#2563eb",
449
+ "css": "var(--cfi-app-primary)",
450
+ "raw": "var(--cfi-action)"
451
+ },
452
+ "primary-hover": {
453
+ "value": "#1d4ed8",
454
+ "css": "var(--cfi-app-primary-hover)",
455
+ "raw": "var(--cfi-action-hover)"
456
+ },
457
+ "primary-soft": {
458
+ "value": "#eff6ff",
459
+ "css": "var(--cfi-app-primary-soft)",
460
+ "raw": "var(--cfi-action-soft)"
461
+ },
462
+ "primary-fg": {
463
+ "value": "#ffffff",
464
+ "css": "var(--cfi-app-primary-fg)",
465
+ "raw": "var(--cfi-color-white)"
466
+ },
467
+ "surface": {
468
+ "value": "#ffffff",
469
+ "css": "var(--cfi-app-surface)",
470
+ "raw": "var(--cfi-surface)"
471
+ }
472
+ },
473
+ "font": {
474
+ "family": {
475
+ "value": "system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
476
+ "css": "var(--cfi-font-family)",
477
+ "raw": "system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif"
478
+ },
479
+ "family-mono": {
480
+ "value": "ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Menlo, Consolas, monospace",
481
+ "css": "var(--cfi-font-family-mono)",
482
+ "raw": "ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Menlo, Consolas, monospace"
483
+ },
484
+ "size-xs": {
485
+ "value": "0.75rem",
486
+ "css": "var(--cfi-font-size-xs)",
487
+ "raw": "0.75rem"
488
+ },
489
+ "size-sm": {
490
+ "value": "0.875rem",
491
+ "css": "var(--cfi-font-size-sm)",
492
+ "raw": "0.875rem"
493
+ },
494
+ "size-base": {
495
+ "value": "1rem",
496
+ "css": "var(--cfi-font-size-base)",
497
+ "raw": "1rem"
498
+ },
499
+ "size-lg": {
500
+ "value": "1.125rem",
501
+ "css": "var(--cfi-font-size-lg)",
502
+ "raw": "1.125rem"
503
+ },
504
+ "size-xl": {
505
+ "value": "1.25rem",
506
+ "css": "var(--cfi-font-size-xl)",
507
+ "raw": "1.25rem"
508
+ },
509
+ "size-2xl": {
510
+ "value": "1.5rem",
511
+ "css": "var(--cfi-font-size-2xl)",
512
+ "raw": "1.5rem"
513
+ },
514
+ "size-3xl": {
515
+ "value": "1.875rem",
516
+ "css": "var(--cfi-font-size-3xl)",
517
+ "raw": "1.875rem"
518
+ },
519
+ "weight-normal": {
520
+ "value": "400",
521
+ "css": "var(--cfi-font-weight-normal)",
522
+ "raw": "400"
523
+ },
524
+ "weight-medium": {
525
+ "value": "500",
526
+ "css": "var(--cfi-font-weight-medium)",
527
+ "raw": "500"
528
+ },
529
+ "weight-semibold": {
530
+ "value": "600",
531
+ "css": "var(--cfi-font-weight-semibold)",
532
+ "raw": "600"
533
+ },
534
+ "weight-bold": {
535
+ "value": "700",
536
+ "css": "var(--cfi-font-weight-bold)",
537
+ "raw": "700"
538
+ }
539
+ },
540
+ "line": {
541
+ "height-tight": {
542
+ "value": "1.2",
543
+ "css": "var(--cfi-line-height-tight)",
544
+ "raw": "1.2"
545
+ },
546
+ "height-snug": {
547
+ "value": "1.35",
548
+ "css": "var(--cfi-line-height-snug)",
549
+ "raw": "1.35"
550
+ },
551
+ "height-normal": {
552
+ "value": "1.5",
553
+ "css": "var(--cfi-line-height-normal)",
554
+ "raw": "1.5"
555
+ },
556
+ "height-relaxed": {
557
+ "value": "1.65",
558
+ "css": "var(--cfi-line-height-relaxed)",
559
+ "raw": "1.65"
560
+ }
561
+ },
562
+ "letter": {
563
+ "spacing-tight": {
564
+ "value": "-0.015em",
565
+ "css": "var(--cfi-letter-spacing-tight)",
566
+ "raw": "-0.015em"
567
+ },
568
+ "spacing-normal": {
569
+ "value": "0",
570
+ "css": "var(--cfi-letter-spacing-normal)",
571
+ "raw": "0"
572
+ },
573
+ "spacing-wide": {
574
+ "value": "0.04em",
575
+ "css": "var(--cfi-letter-spacing-wide)",
576
+ "raw": "0.04em"
577
+ },
578
+ "spacing-caps": {
579
+ "value": "0.08em",
580
+ "css": "var(--cfi-letter-spacing-caps)",
581
+ "raw": "0.08em"
582
+ }
583
+ },
584
+ "spacing": {
585
+ "3xs": {
586
+ "value": "0.125rem",
587
+ "css": "var(--cfi-spacing-3xs)",
588
+ "raw": "0.125rem"
589
+ },
590
+ "2xs": {
591
+ "value": "0.1875rem",
592
+ "css": "var(--cfi-spacing-2xs)",
593
+ "raw": "0.1875rem"
594
+ },
595
+ "xs": {
596
+ "value": "0.25rem",
597
+ "css": "var(--cfi-spacing-xs)",
598
+ "raw": "0.25rem"
599
+ },
600
+ "sm": {
601
+ "value": "0.5rem",
602
+ "css": "var(--cfi-spacing-sm)",
603
+ "raw": "0.5rem"
604
+ },
605
+ "md": {
606
+ "value": "1rem",
607
+ "css": "var(--cfi-spacing-md)",
608
+ "raw": "1rem"
609
+ },
610
+ "lg": {
611
+ "value": "1.5rem",
612
+ "css": "var(--cfi-spacing-lg)",
613
+ "raw": "1.5rem"
614
+ },
615
+ "xl": {
616
+ "value": "2rem",
617
+ "css": "var(--cfi-spacing-xl)",
618
+ "raw": "2rem"
619
+ },
620
+ "2xl": {
621
+ "value": "3rem",
622
+ "css": "var(--cfi-spacing-2xl)",
623
+ "raw": "3rem"
624
+ },
625
+ "3xl": {
626
+ "value": "4rem",
627
+ "css": "var(--cfi-spacing-3xl)",
628
+ "raw": "4rem"
629
+ }
630
+ },
631
+ "radius": {
632
+ "none": {
633
+ "value": "0",
634
+ "css": "var(--cfi-radius-none)",
635
+ "raw": "0"
636
+ },
637
+ "base": {
638
+ "value": "0.625rem",
639
+ "css": "var(--cfi-radius-base)",
640
+ "raw": "0.625rem"
641
+ },
642
+ "sm": {
643
+ "value": "0.375rem",
644
+ "css": "var(--cfi-radius-sm)",
645
+ "raw": "0.375rem"
646
+ },
647
+ "md": {
648
+ "value": "0.5rem",
649
+ "css": "var(--cfi-radius-md)",
650
+ "raw": "0.5rem"
651
+ },
652
+ "lg": {
653
+ "value": "0.625rem",
654
+ "css": "var(--cfi-radius-lg)",
655
+ "raw": "0.625rem"
656
+ },
657
+ "xl": {
658
+ "value": "0.875rem",
659
+ "css": "var(--cfi-radius-xl)",
660
+ "raw": "0.875rem"
661
+ },
662
+ "full": {
663
+ "value": "9999px",
664
+ "css": "var(--cfi-radius-full)",
665
+ "raw": "9999px"
666
+ }
667
+ },
668
+ "shadow": {
669
+ "xs": {
670
+ "value": "0 1px 1px rgb(17 24 39 / 0.04)",
671
+ "css": "var(--cfi-shadow-xs)",
672
+ "raw": "0 1px 1px rgb(17 24 39 / 0.04)"
673
+ },
674
+ "sm": {
675
+ "value": "0 1px 2px rgb(17 24 39 / 0.05)",
676
+ "css": "var(--cfi-shadow-sm)",
677
+ "raw": "0 1px 2px rgb(17 24 39 / 0.05)"
678
+ },
679
+ "md": {
680
+ "value": "0 4px 6px rgb(17 24 39 / 0.07)",
681
+ "css": "var(--cfi-shadow-md)",
682
+ "raw": "0 4px 6px rgb(17 24 39 / 0.07)"
683
+ },
684
+ "lg": {
685
+ "value": "0 10px 15px rgb(17 24 39 / 0.1)",
686
+ "css": "var(--cfi-shadow-lg)",
687
+ "raw": "0 10px 15px rgb(17 24 39 / 0.1)"
688
+ },
689
+ "xl": {
690
+ "value": "0 20px 40px -12px rgb(17 24 39 / 0.22)",
691
+ "css": "var(--cfi-shadow-xl)",
692
+ "raw": "0 20px 40px -12px rgb(17 24 39 / 0.22)"
693
+ }
694
+ },
695
+ "easing": {
696
+ "easing": {
697
+ "value": "cubic-bezier(0.4, 0, 0.2, 1)",
698
+ "css": "var(--cfi-easing)",
699
+ "raw": "cubic-bezier(0.4, 0, 0.2, 1)"
700
+ }
701
+ },
702
+ "duration": {
703
+ "fast": {
704
+ "value": "120ms",
705
+ "css": "var(--cfi-duration-fast)",
706
+ "raw": "120ms"
707
+ },
708
+ "base": {
709
+ "value": "200ms",
710
+ "css": "var(--cfi-duration-base)",
711
+ "raw": "200ms"
712
+ },
713
+ "slow": {
714
+ "value": "320ms",
715
+ "css": "var(--cfi-duration-slow)",
716
+ "raw": "320ms"
717
+ }
718
+ },
719
+ "transition": {
720
+ "fast": {
721
+ "value": "var(--cfi-duration-fast) var(--cfi-easing)",
722
+ "css": "var(--cfi-transition-fast)",
723
+ "raw": "var(--cfi-duration-fast) var(--cfi-easing)"
724
+ },
725
+ "base": {
726
+ "value": "var(--cfi-duration-base) var(--cfi-easing)",
727
+ "css": "var(--cfi-transition-base)",
728
+ "raw": "var(--cfi-duration-base) var(--cfi-easing)"
729
+ }
730
+ },
731
+ "z": {
732
+ "base": {
733
+ "value": "0",
734
+ "css": "var(--cfi-z-base)",
735
+ "raw": "0"
736
+ },
737
+ "raised": {
738
+ "value": "10",
739
+ "css": "var(--cfi-z-raised)",
740
+ "raw": "10"
741
+ },
742
+ "sticky": {
743
+ "value": "100",
744
+ "css": "var(--cfi-z-sticky)",
745
+ "raw": "100"
746
+ },
747
+ "shell-header": {
748
+ "value": "200",
749
+ "css": "var(--cfi-z-shell-header)",
750
+ "raw": "200"
751
+ },
752
+ "dropdown": {
753
+ "value": "1000",
754
+ "css": "var(--cfi-z-dropdown)",
755
+ "raw": "1000"
756
+ },
757
+ "overlay": {
758
+ "value": "1100",
759
+ "css": "var(--cfi-z-overlay)",
760
+ "raw": "1100"
761
+ },
762
+ "modal": {
763
+ "value": "1200",
764
+ "css": "var(--cfi-z-modal)",
765
+ "raw": "1200"
766
+ },
767
+ "popover": {
768
+ "value": "1300",
769
+ "css": "var(--cfi-z-popover)",
770
+ "raw": "1300"
771
+ },
772
+ "toast": {
773
+ "value": "1400",
774
+ "css": "var(--cfi-z-toast)",
775
+ "raw": "1400"
776
+ },
777
+ "tooltip": {
778
+ "value": "1500",
779
+ "css": "var(--cfi-z-tooltip)",
780
+ "raw": "1500"
781
+ }
782
+ },
783
+ "shell": {
784
+ "header-height": {
785
+ "value": "48px",
786
+ "css": "var(--cfi-shell-header-height)",
787
+ "raw": "48px"
788
+ }
789
+ },
790
+ "sidenav": {
791
+ "width": {
792
+ "value": "256px",
793
+ "css": "var(--cfi-sidenav-width)",
794
+ "raw": "256px"
795
+ },
796
+ "width-collapsed": {
797
+ "value": "64px",
798
+ "css": "var(--cfi-sidenav-width-collapsed)",
799
+ "raw": "64px"
800
+ },
801
+ "bg": {
802
+ "value": "#1e293b",
803
+ "css": "var(--cfi-sidenav-bg)",
804
+ "raw": "#1e293b"
805
+ },
806
+ "border": {
807
+ "value": "#334155",
808
+ "css": "var(--cfi-sidenav-border)",
809
+ "raw": "#334155"
810
+ },
811
+ "fg": {
812
+ "value": "#cbd5e1",
813
+ "css": "var(--cfi-sidenav-fg)",
814
+ "raw": "#cbd5e1"
815
+ },
816
+ "fg-muted": {
817
+ "value": "#94a3b8",
818
+ "css": "var(--cfi-sidenav-fg-muted)",
819
+ "raw": "#94a3b8"
820
+ },
821
+ "item-hover-bg": {
822
+ "value": "#334155",
823
+ "css": "var(--cfi-sidenav-item-hover-bg)",
824
+ "raw": "#334155"
825
+ },
826
+ "item-hover-fg": {
827
+ "value": "#ffffff",
828
+ "css": "var(--cfi-sidenav-item-hover-fg)",
829
+ "raw": "#ffffff"
830
+ },
831
+ "item-active-bg": {
832
+ "value": "#2563eb",
833
+ "css": "var(--cfi-sidenav-item-active-bg)",
834
+ "raw": "#2563eb"
835
+ },
836
+ "item-active-fg": {
837
+ "value": "#ffffff",
838
+ "css": "var(--cfi-sidenav-item-active-fg)",
839
+ "raw": "#ffffff"
840
+ }
841
+ }
842
+ }
843
+ }