@actioneer/ads 0.5.8 → 0.6.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.
Files changed (40) hide show
  1. package/components/assistant-ui/composer-harness.js +12 -10
  2. package/components/avatar.d.ts +1 -0
  3. package/components/avatar.js +5 -4
  4. package/components/breadcrumbs.d.ts +3 -1
  5. package/components/breadcrumbs.js +62 -56
  6. package/components/button.js +11 -11
  7. package/components/card.js +19 -18
  8. package/components/chart.d.ts +6 -0
  9. package/components/chart.js +747 -657
  10. package/components/date-range-picker.d.ts +25 -0
  11. package/components/date-range-picker.js +187 -0
  12. package/components/drawer.d.ts +3 -1
  13. package/components/drawer.js +115 -95
  14. package/components/index.d.ts +1 -0
  15. package/components/index.js +499 -497
  16. package/components/modal.d.ts +5 -1
  17. package/components/modal.js +74 -61
  18. package/components/panel.js +31 -28
  19. package/components/pixel-icon.d.ts +4 -0
  20. package/components/pixel-icon.js +210 -163
  21. package/components/segmented.d.ts +1 -0
  22. package/components/segmented.js +31 -28
  23. package/components/select.d.ts +5 -0
  24. package/components/select.js +177 -132
  25. package/components/table.d.ts +7 -0
  26. package/components/table.js +183 -173
  27. package/components/tabs.js +1 -1
  28. package/components/tree.js +86 -58
  29. package/components/viz-charts.js +186 -183
  30. package/demo/components/add-to-artifact.js +131 -107
  31. package/demo/lib/artifact-library.js +37 -29
  32. package/demo/lib/artifact-pin-guard.js +12 -0
  33. package/fonts.css +2 -0
  34. package/lib/icons.d.ts +20 -0
  35. package/lib/icons.js +112 -107
  36. package/llms.txt +23 -3
  37. package/manifest.json +13774 -14
  38. package/package.json +4 -1
  39. package/styles.css +76 -60
  40. package/theme.css +70 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actioneer/ads",
3
- "version": "0.5.8",
3
+ "version": "0.6.0",
4
4
  "description": "Actioneer Design System 1.0 — React 19 + Tailwind v4 component library.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -36,6 +36,8 @@
36
36
  "dependencies": {
37
37
  "@assistant-ui/react": "^0.14.26",
38
38
  "@assistant-ui/react-markdown": "^0.14.5",
39
+ "@fontsource-variable/jetbrains-mono": "^5.3.0",
40
+ "@internationalized/date": "^3.12.3",
39
41
  "@paper-design/shaders": "^0.0.77",
40
42
  "@paper-design/shaders-react": "^0.0.77",
41
43
  "@phosphor-icons/react": "^2.1.10",
@@ -45,6 +47,7 @@
45
47
  "motion": "^12.42.2",
46
48
  "ogl": "^1.0.11",
47
49
  "radix-ui": "^1.6.2",
50
+ "react-aria-components": "^1.20.0",
48
51
  "recharts": "^2.15.4",
49
52
  "remark-gfm": "^4.0.1",
50
53
  "tailwind-merge": "^2.6.0",
package/styles.css CHANGED
@@ -5,6 +5,8 @@
5
5
  @import "tw-animate-css";
6
6
 
7
7
  /* ---- Aribau Grotesk ---- */
8
+ @import "@fontsource-variable/jetbrains-mono/wght.css";
9
+
8
10
  /* Aribau Grotesk — ADS UI typeface.
9
11
  TWO physical faces, both served compressed (woff2):
10
12
  • Regular → `font-normal` (weight 100–499)
@@ -37,7 +39,8 @@
37
39
  /*
38
40
  * ============================================================
39
41
  * ADS 1.0 — Design Tokens
40
- * Palette: Ink neutrals · Typeface: Aribau Grotesk
42
+ * Palette: Warm stone Studio neutrals + restrained green CTA
43
+ * Typeface: Aribau Grotesk
41
44
  * ============================================================
42
45
  */
43
46
  @theme {
@@ -48,11 +51,11 @@
48
51
  --font-sans: "Aribau Grotesk", ui-sans-serif, system-ui, -apple-system,
49
52
  "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
50
53
 
51
- /* Source code only (CodeBlock, inline Code). ADS ships no mono webfont —
52
- this resolves to the reader's platform mono, which is what a developer
53
- already reads code in. Never use it for UI copy or data. */
54
- --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
55
- "Liberation Mono", "Courier New", monospace;
54
+ /* Source code only (CodeBlock, inline Code). JetBrains Mono is bundled so
55
+ code renders consistently across platforms. Never use it for UI copy or
56
+ ordinary data. */
57
+ --font-mono: "JetBrains Mono Variable", ui-monospace, SFMono-Regular,
58
+ "SF Mono", Menlo, Consolas, "Liberation Mono", "Courier New", monospace;
56
59
 
57
60
  /* ---- Type scale ---- base = 15px (0.9375rem). Root stays 16px so the
58
61
  spacing grid is unaffected; only text sizes are anchored to 15px. */
@@ -76,27 +79,28 @@
76
79
  --text-2xl: 1.625rem; /* 26px — display */
77
80
  --text-2xl--line-height: 2rem;
78
81
 
79
- /* ---- Neutral ramp — a role-based neutral Gray 12-step light scale. Every
80
- channel is equal, so the product stays neutral with no Sand/Sage cast.
81
- The light surface steps retain subtle spacing; the solid/text end is
82
- perceptually widened so adjacent swatches and UI roles stay distinct.
82
+ /* ---- Warm ink ramp — a role-based 12-step light scale sampled from the
83
+ Actioneer product UI. A restrained red/yellow bias gives canvases and
84
+ fills an ivory/stone character instead of equal-channel grey. The light
85
+ surface steps retain subtle spacing; the solid/text end is perceptually
86
+ widened so adjacent swatches and UI roles stay distinct.
83
87
  Each step owns a role — 50/100 =
84
88
  backgrounds, 200/300/400 = interactive component fills, 500/600/700 =
85
89
  borders & separators, 800/850 = solid, 900/950 = accessible text. The
86
90
  `ink` name is retained as the stable ADS API. ---- */
87
- --color-ink-50: #fcfcfc; /* 1 · background */
88
- --color-ink-100: #f9f9f9; /* 2 · background */
89
- --color-ink-150: #f5f5f5; /* canvas */
90
- --color-ink-200: #f0f0f0; /* 3 · interactive */
91
- --color-ink-300: #e8e8e8; /* 4 · interactive */
92
- --color-ink-400: #e0e0e0; /* 5 · interactive */
93
- --color-ink-500: #d9d9d9; /* 6 · border */
94
- --color-ink-600: #cecece; /* 7 · border */
95
- --color-ink-700: #bbbbbb; /* 8 · border */
96
- --color-ink-800: #8d8d8d; /* 9 · solid */
97
- --color-ink-850: #737373; /* 10 · solid */
98
- --color-ink-900: #555555; /* 11 · accessible text */
99
- --color-ink-950: #202020; /* 12 · accessible text */
91
+ --color-ink-50: #fdfcf8; /* 1 · background */
92
+ --color-ink-100: #f9f8f3; /* 2 · background */
93
+ --color-ink-150: #f6f6f1; /* canvas */
94
+ --color-ink-200: #f0efeb; /* 3 · interactive */
95
+ --color-ink-300: #e8e7e2; /* 4 · interactive */
96
+ --color-ink-400: #deded9; /* 5 · interactive */
97
+ --color-ink-500: #d5d4cf; /* 6 · border */
98
+ --color-ink-600: #c9c8c2; /* 7 · border */
99
+ --color-ink-700: #b7b6b0; /* 8 · border */
100
+ --color-ink-800: #8d8c86; /* 9 · solid */
101
+ --color-ink-850: #70706a; /* 10 · solid */
102
+ --color-ink-900: #444440; /* 11 · accessible text */
103
+ --color-ink-950: #171714; /* 12 · accessible text */
100
104
 
101
105
  /* ---- Semantic accent ramps ---- */
102
106
  /* Success stays a semantic state color, never a product-primary hue. */
@@ -140,18 +144,18 @@
140
144
  /* Demo logo indigo — source for artifact canvas wash. */
141
145
  --color-brand-mark: #2e1065;
142
146
 
143
- /* ---- Radii ---- FOUR values, assigned by element scale and role.
144
- 2px = micro details; 4px = compact controls; 8px = standard controls
145
- and floating UI; 16px = cards and large surfaces. The repeated aliases
146
- keep the familiar Tailwind role names while capping surfaces at 16px. */
147
+ /* ---- Radii ---- FOUR restrained values, assigned by element scale.
148
+ 2px = micro details; 4px = compact controls; 6px = standard controls;
149
+ 8px = menus, cards, panels, and large surfaces. Repeated aliases keep the
150
+ familiar Tailwind role names while capping every surface at 8px. */
147
151
  --radius-xs: 0.125rem; /* 2px · micro details */
148
152
  --radius-sm: 0.25rem; /* 4px · compact controls */
149
- --radius-md: 0.5rem; /* 8px · standard controls */
153
+ --radius-md: 0.375rem; /* 6px · standard controls */
150
154
  --radius-lg: 0.5rem; /* 8px · menus and panels */
151
- --radius-xl: 1rem; /* 16px · cards and surfaces */
152
- --radius-2xl: 1rem; /* 16px · large surfaces */
153
- --radius-3xl: 1rem; /* 16px · capped compatibility alias */
154
- --radius-4xl: 1rem; /* 16px · capped compatibility alias */
155
+ --radius-xl: 0.5rem; /* 8px · cards and surfaces */
156
+ --radius-2xl: 0.5rem; /* 8px · large surfaces */
157
+ --radius-3xl: 0.5rem; /* 8px · capped compatibility alias */
158
+ --radius-4xl: 0.5rem; /* 8px · capped compatibility alias */
155
159
  /* Shape-only exception for avatars, icon buttons, progress tracks, chips,
156
160
  and badges. It is not part of the corner-radius scale. */
157
161
  --radius-full: 9999px;
@@ -161,19 +165,18 @@
161
165
  convention). */
162
166
  --radius-dot: 2px;
163
167
 
164
- /* ---- Elevation ---- ONE soft token (Claude-panel style).
165
- Delineate surfaces with fill color first; add this to gently lift them.
166
- The ambient drop sits close (y4, blur16) at low opacity and uses neutral
167
- ink — never a cool slate tint that would reintroduce a color cast. */
168
- --shadow-elevation: 0 0 0 1px rgb(32 32 32 / 0.03),
169
- 0 1px 2px 0 rgb(32 32 32 / 0.04),
170
- 0 4px 16px -6px rgb(32 32 32 / 0.06);
168
+ /* ---- Elevation ---- ONE restrained Studio token.
169
+ Delineate surfaces with fill color first; add this only to lift something
170
+ actionable. A close contact shadow anchors the surface while the large
171
+ negative spread keeps the ambient shadow soft, quiet, and borderless. */
172
+ --shadow-elevation: 0 1px 2px rgb(23 23 20 / 0.05),
173
+ 0 8px 20px -16px rgb(23 23 20 / 0.16);
171
174
 
172
175
  /* Pinned-table-column smudges — whisper-soft directional casts shown only
173
176
  while content is hidden behind a sticky column (Table is scroll-aware).
174
- Deep negative spread keeps the edge feathered; the tint is neutral ink. */
175
- --shadow-table-smudge-left: 8px 0 24px -14px rgb(32 32 32 / 0.05);
176
- --shadow-table-smudge-right: -8px 0 24px -14px rgb(32 32 32 / 0.05);
177
+ Deep negative spread keeps the edge feathered; the tint is warm ink. */
178
+ --shadow-table-smudge-left: 8px 0 24px -14px rgb(23 23 20 / 0.05);
179
+ --shadow-table-smudge-right: -8px 0 24px -14px rgb(23 23 20 / 0.05);
177
180
 
178
181
  /* ---- CTA inner glow ---- luminous inset highlight for primary buttons
179
182
  (adapted from the "AI button" Figma): a crisp top-edge catch plus a soft
@@ -187,7 +190,7 @@
187
190
  inset 0 8px 16px -8px rgb(255 255 255 / 0.45);
188
191
  /* Text fields — a whisper of inset depth so the writing surface reads
189
192
  recessed into the page (persists through hover/focus/invalid). */
190
- --inner-glow-field: inset 0 1px 2px 0 rgb(32 32 32 / 0.06);
193
+ --inner-glow-field: inset 0 1px 2px 0 rgb(23 23 20 / 0.06);
191
194
 
192
195
  /* ---- Layout ---- app-frame dimensions (Sidebar / Panel) */
193
196
  --sidebar-width: 15rem; /* 240px — primary nav rail */
@@ -267,6 +270,11 @@
267
270
  --color-card: var(--card);
268
271
  --color-card-foreground: var(--card-foreground);
269
272
 
273
+ /* Primary CTA role — restrained Studio green, used sparingly. */
274
+ --color-action-primary: var(--action-primary);
275
+ --color-action-primary-foreground: var(--action-primary-foreground);
276
+ --color-action-primary-hover: var(--action-primary-hover);
277
+
270
278
  /* Compatibility action role — neutral ink, never a colored primary hue. */
271
279
  --color-brand: var(--brand);
272
280
  --color-brand-foreground: var(--brand-foreground);
@@ -331,7 +339,7 @@
331
339
 
332
340
  /* ---- Theme (light only) ---- */
333
341
  :root {
334
- /* Every neutral semantic token below points INTO the ink primitive scale.
342
+ /* Every warm-neutral semantic token below points INTO the ink primitive scale.
335
343
  Only pure white (#ffffff) stays literal: it is a base surface, not a
336
344
  neutral scale step. */
337
345
  --background: var(--color-ink-100); /* step 2 · canvas */
@@ -339,12 +347,12 @@
339
347
 
340
348
  /* Text levels: primary ink-950, secondary ink-900, tertiary a tuned grey.
341
349
  All three clear AA (4.5:1) for body copy on every surface they land on.
342
- Tertiary is NOT an ink step: ink-800 (#8d8d8d) was AA-large only (2.7:1
343
- on muted) but is used at 13px in 200+ places, so it is pinned to the
350
+ Tertiary is NOT an ink step: ink-850 (#70706a) falls below AA on muted
351
+ but is used at 13px in 200+ places, so it is pinned to the
344
352
  lightest grey that still passes 4.5:1 on bg/card/surface/muted. */
345
- --text-primary: var(--color-ink-950); /* ~16:1 AAA */
346
- --text-secondary: var(--color-ink-900); /* ~7.1:1 AAA */
347
- --text-tertiary: #686868; /* ~4.55:1 AA (min surf) */
353
+ --text-primary: var(--color-ink-950); /* ~14.5:1 AAA (min surf) */
354
+ --text-secondary: var(--color-ink-900); /* ~7.9:1 AAA (min surf) */
355
+ --text-tertiary: #686863; /* ~4.52:1 AA (min surf) */
348
356
 
349
357
  --surface: var(--color-ink-200); /* step 3 · tinted canvas */
350
358
  --surface-foreground: var(--color-ink-950);
@@ -356,8 +364,15 @@
356
364
  --card: #ffffff; /* pure white base */
357
365
  --card-foreground: var(--color-ink-950);
358
366
 
367
+ /* Studio green is deliberately isolated to the primary CTA role (roughly
368
+ 5–10% of a screen). Selection controls keep using neutral `brand` below,
369
+ so tabs, switches, radios, and progress never inherit CTA color. */
370
+ --action-primary: #2f7d5a;
371
+ --action-primary-foreground: #ffffff;
372
+ --action-primary-hover: #256749;
373
+
359
374
  /* Neutral action role. The `brand` name remains as a compatibility API,
360
- but the product has no colored primary palette. */
375
+ and shared selection/control states intentionally remain achromatic. */
361
376
  --brand: var(--color-ink-950); /* darkest action ink */
362
377
  --brand-foreground: #ffffff;
363
378
  --brand-hover: var(--color-ink-900); /* lighter hover lift */
@@ -369,7 +384,7 @@
369
384
  --table-row-hover: color-mix(in srgb, var(--card) 40%, var(--muted));
370
385
  --table-row-selected: color-mix(in srgb, var(--card) 10%, var(--muted));
371
386
 
372
- /* Quiet component fill. Radix step 3 is the first interactive-background
387
+ /* Quiet component fill. Ink step 3 is the first interactive-background
373
388
  step, so this remains visible on both white cards and the step-2 canvas. */
374
389
  --fill: var(--color-ink-200); /* step 3 · default component fill */
375
390
  --fill-foreground: var(--color-ink-950);
@@ -377,12 +392,12 @@
377
392
  --accent: var(--color-ink-400); /* step 5 · active / selected wash */
378
393
  --accent-foreground: var(--color-ink-950);
379
394
 
380
- /* Borders use consecutive Radix steps 5–7. This avoids the old 3→5→7 jump:
381
- tertiary stays quiet but visible at 0.5px, secondary is the Radix subtle
395
+ /* Borders use consecutive ink steps 5–7. This avoids the old 3→5→7 jump:
396
+ tertiary stays quiet but visible at 0.5px, secondary is the subtle
382
397
  border step, and primary is the default interactive-control edge. */
383
- --border-primary: var(--color-ink-600); /* step 7 · #cecece · strongest */
384
- --border-secondary: var(--color-ink-500); /* step 6 · #d9d9d9 · default */
385
- --border-tertiary: var(--color-ink-400); /* step 5 · #e0e0e0 · faintest */
398
+ --border-primary: var(--color-ink-600); /* step 7 · #c9c8c2 · strongest */
399
+ --border-secondary: var(--color-ink-500); /* step 6 · #d5d4cf · default */
400
+ --border-tertiary: var(--color-ink-400); /* step 5 · #deded9 · faintest */
386
401
  /* Legacy aliases point into the scale so existing utilities keep resolving. */
387
402
  --border: var(--border-secondary); /* default hairline / separator */
388
403
  --border-strong: var(--border-primary); /* emphasized / hover / selected */
@@ -413,7 +428,7 @@
413
428
  --canvas-edge: var(--border-secondary);/* infinite-canvas edges / connectors */
414
429
  --texture-ink: var(--color-ink-950); /* brand-texture / pixel-blast marks */
415
430
  --table-shell: var(--color-ink-200); /* recessed table tray (lighter than muted) */
416
- --table-scroll-hint: rgb(32 32 32 / 0.04); /* right-edge "more columns" wash */
431
+ --table-scroll-hint: rgb(23 23 20 / 0.04); /* right-edge "more columns" wash */
417
432
  --surface-inverse: var(--color-ink-950); /* dark hero / inverse surface base */
418
433
  --surface-inverse-soft: var(--color-ink-900); /* dark hero gradient falloff */
419
434
  --artifact-canvas: color-mix(in srgb, var(--color-brand-mark) 7%, #ffffff);
@@ -698,13 +713,14 @@
698
713
  font-synthesis-weight: none;
699
714
  }
700
715
 
701
- /* One typeface only: neutralize the browser's default monospace on
702
- code/kbd/samp/pre so they render in Aribau Grotesk like everything else. */
716
+ /* Literal code uses the bundled mono face, including unclassed semantic
717
+ code elements. UI copy and data remain in Aribau Grotesk. */
703
718
  code,
704
719
  kbd,
705
720
  samp,
706
721
  pre {
707
- font-family: inherit;
722
+ font-family: var(--font-mono);
723
+ font-feature-settings: normal;
708
724
  }
709
725
 
710
726
  /* Consistent focus ring across the system */
package/theme.css CHANGED
@@ -8,7 +8,8 @@
8
8
  /*
9
9
  * ============================================================
10
10
  * ADS 1.0 — Design Tokens
11
- * Palette: Ink neutrals · Typeface: Aribau Grotesk
11
+ * Palette: Warm stone Studio neutrals + restrained green CTA
12
+ * Typeface: Aribau Grotesk
12
13
  * ============================================================
13
14
  */
14
15
  @theme {
@@ -19,11 +20,11 @@
19
20
  --font-sans: "Aribau Grotesk", ui-sans-serif, system-ui, -apple-system,
20
21
  "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
21
22
 
22
- /* Source code only (CodeBlock, inline Code). ADS ships no mono webfont —
23
- this resolves to the reader's platform mono, which is what a developer
24
- already reads code in. Never use it for UI copy or data. */
25
- --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
26
- "Liberation Mono", "Courier New", monospace;
23
+ /* Source code only (CodeBlock, inline Code). JetBrains Mono is bundled so
24
+ code renders consistently across platforms. Never use it for UI copy or
25
+ ordinary data. */
26
+ --font-mono: "JetBrains Mono Variable", ui-monospace, SFMono-Regular,
27
+ "SF Mono", Menlo, Consolas, "Liberation Mono", "Courier New", monospace;
27
28
 
28
29
  /* ---- Type scale ---- base = 15px (0.9375rem). Root stays 16px so the
29
30
  spacing grid is unaffected; only text sizes are anchored to 15px. */
@@ -47,27 +48,28 @@
47
48
  --text-2xl: 1.625rem; /* 26px — display */
48
49
  --text-2xl--line-height: 2rem;
49
50
 
50
- /* ---- Neutral ramp — a role-based neutral Gray 12-step light scale. Every
51
- channel is equal, so the product stays neutral with no Sand/Sage cast.
52
- The light surface steps retain subtle spacing; the solid/text end is
53
- perceptually widened so adjacent swatches and UI roles stay distinct.
51
+ /* ---- Warm ink ramp — a role-based 12-step light scale sampled from the
52
+ Actioneer product UI. A restrained red/yellow bias gives canvases and
53
+ fills an ivory/stone character instead of equal-channel grey. The light
54
+ surface steps retain subtle spacing; the solid/text end is perceptually
55
+ widened so adjacent swatches and UI roles stay distinct.
54
56
  Each step owns a role — 50/100 =
55
57
  backgrounds, 200/300/400 = interactive component fills, 500/600/700 =
56
58
  borders & separators, 800/850 = solid, 900/950 = accessible text. The
57
59
  `ink` name is retained as the stable ADS API. ---- */
58
- --color-ink-50: #fcfcfc; /* 1 · background */
59
- --color-ink-100: #f9f9f9; /* 2 · background */
60
- --color-ink-150: #f5f5f5; /* canvas */
61
- --color-ink-200: #f0f0f0; /* 3 · interactive */
62
- --color-ink-300: #e8e8e8; /* 4 · interactive */
63
- --color-ink-400: #e0e0e0; /* 5 · interactive */
64
- --color-ink-500: #d9d9d9; /* 6 · border */
65
- --color-ink-600: #cecece; /* 7 · border */
66
- --color-ink-700: #bbbbbb; /* 8 · border */
67
- --color-ink-800: #8d8d8d; /* 9 · solid */
68
- --color-ink-850: #737373; /* 10 · solid */
69
- --color-ink-900: #555555; /* 11 · accessible text */
70
- --color-ink-950: #202020; /* 12 · accessible text */
60
+ --color-ink-50: #fdfcf8; /* 1 · background */
61
+ --color-ink-100: #f9f8f3; /* 2 · background */
62
+ --color-ink-150: #f6f6f1; /* canvas */
63
+ --color-ink-200: #f0efeb; /* 3 · interactive */
64
+ --color-ink-300: #e8e7e2; /* 4 · interactive */
65
+ --color-ink-400: #deded9; /* 5 · interactive */
66
+ --color-ink-500: #d5d4cf; /* 6 · border */
67
+ --color-ink-600: #c9c8c2; /* 7 · border */
68
+ --color-ink-700: #b7b6b0; /* 8 · border */
69
+ --color-ink-800: #8d8c86; /* 9 · solid */
70
+ --color-ink-850: #70706a; /* 10 · solid */
71
+ --color-ink-900: #444440; /* 11 · accessible text */
72
+ --color-ink-950: #171714; /* 12 · accessible text */
71
73
 
72
74
  /* ---- Semantic accent ramps ---- */
73
75
  /* Success stays a semantic state color, never a product-primary hue. */
@@ -111,18 +113,18 @@
111
113
  /* Demo logo indigo — source for artifact canvas wash. */
112
114
  --color-brand-mark: #2e1065;
113
115
 
114
- /* ---- Radii ---- FOUR values, assigned by element scale and role.
115
- 2px = micro details; 4px = compact controls; 8px = standard controls
116
- and floating UI; 16px = cards and large surfaces. The repeated aliases
117
- keep the familiar Tailwind role names while capping surfaces at 16px. */
116
+ /* ---- Radii ---- FOUR restrained values, assigned by element scale.
117
+ 2px = micro details; 4px = compact controls; 6px = standard controls;
118
+ 8px = menus, cards, panels, and large surfaces. Repeated aliases keep the
119
+ familiar Tailwind role names while capping every surface at 8px. */
118
120
  --radius-xs: 0.125rem; /* 2px · micro details */
119
121
  --radius-sm: 0.25rem; /* 4px · compact controls */
120
- --radius-md: 0.5rem; /* 8px · standard controls */
122
+ --radius-md: 0.375rem; /* 6px · standard controls */
121
123
  --radius-lg: 0.5rem; /* 8px · menus and panels */
122
- --radius-xl: 1rem; /* 16px · cards and surfaces */
123
- --radius-2xl: 1rem; /* 16px · large surfaces */
124
- --radius-3xl: 1rem; /* 16px · capped compatibility alias */
125
- --radius-4xl: 1rem; /* 16px · capped compatibility alias */
124
+ --radius-xl: 0.5rem; /* 8px · cards and surfaces */
125
+ --radius-2xl: 0.5rem; /* 8px · large surfaces */
126
+ --radius-3xl: 0.5rem; /* 8px · capped compatibility alias */
127
+ --radius-4xl: 0.5rem; /* 8px · capped compatibility alias */
126
128
  /* Shape-only exception for avatars, icon buttons, progress tracks, chips,
127
129
  and badges. It is not part of the corner-radius scale. */
128
130
  --radius-full: 9999px;
@@ -132,19 +134,18 @@
132
134
  convention). */
133
135
  --radius-dot: 2px;
134
136
 
135
- /* ---- Elevation ---- ONE soft token (Claude-panel style).
136
- Delineate surfaces with fill color first; add this to gently lift them.
137
- The ambient drop sits close (y4, blur16) at low opacity and uses neutral
138
- ink — never a cool slate tint that would reintroduce a color cast. */
139
- --shadow-elevation: 0 0 0 1px rgb(32 32 32 / 0.03),
140
- 0 1px 2px 0 rgb(32 32 32 / 0.04),
141
- 0 4px 16px -6px rgb(32 32 32 / 0.06);
137
+ /* ---- Elevation ---- ONE restrained Studio token.
138
+ Delineate surfaces with fill color first; add this only to lift something
139
+ actionable. A close contact shadow anchors the surface while the large
140
+ negative spread keeps the ambient shadow soft, quiet, and borderless. */
141
+ --shadow-elevation: 0 1px 2px rgb(23 23 20 / 0.05),
142
+ 0 8px 20px -16px rgb(23 23 20 / 0.16);
142
143
 
143
144
  /* Pinned-table-column smudges — whisper-soft directional casts shown only
144
145
  while content is hidden behind a sticky column (Table is scroll-aware).
145
- Deep negative spread keeps the edge feathered; the tint is neutral ink. */
146
- --shadow-table-smudge-left: 8px 0 24px -14px rgb(32 32 32 / 0.05);
147
- --shadow-table-smudge-right: -8px 0 24px -14px rgb(32 32 32 / 0.05);
146
+ Deep negative spread keeps the edge feathered; the tint is warm ink. */
147
+ --shadow-table-smudge-left: 8px 0 24px -14px rgb(23 23 20 / 0.05);
148
+ --shadow-table-smudge-right: -8px 0 24px -14px rgb(23 23 20 / 0.05);
148
149
 
149
150
  /* ---- CTA inner glow ---- luminous inset highlight for primary buttons
150
151
  (adapted from the "AI button" Figma): a crisp top-edge catch plus a soft
@@ -158,7 +159,7 @@
158
159
  inset 0 8px 16px -8px rgb(255 255 255 / 0.45);
159
160
  /* Text fields — a whisper of inset depth so the writing surface reads
160
161
  recessed into the page (persists through hover/focus/invalid). */
161
- --inner-glow-field: inset 0 1px 2px 0 rgb(32 32 32 / 0.06);
162
+ --inner-glow-field: inset 0 1px 2px 0 rgb(23 23 20 / 0.06);
162
163
 
163
164
  /* ---- Layout ---- app-frame dimensions (Sidebar / Panel) */
164
165
  --sidebar-width: 15rem; /* 240px — primary nav rail */
@@ -238,6 +239,11 @@
238
239
  --color-card: var(--card);
239
240
  --color-card-foreground: var(--card-foreground);
240
241
 
242
+ /* Primary CTA role — restrained Studio green, used sparingly. */
243
+ --color-action-primary: var(--action-primary);
244
+ --color-action-primary-foreground: var(--action-primary-foreground);
245
+ --color-action-primary-hover: var(--action-primary-hover);
246
+
241
247
  /* Compatibility action role — neutral ink, never a colored primary hue. */
242
248
  --color-brand: var(--brand);
243
249
  --color-brand-foreground: var(--brand-foreground);
@@ -302,7 +308,7 @@
302
308
 
303
309
  /* ---- Theme (light only) ---- */
304
310
  :root {
305
- /* Every neutral semantic token below points INTO the ink primitive scale.
311
+ /* Every warm-neutral semantic token below points INTO the ink primitive scale.
306
312
  Only pure white (#ffffff) stays literal: it is a base surface, not a
307
313
  neutral scale step. */
308
314
  --background: var(--color-ink-100); /* step 2 · canvas */
@@ -310,12 +316,12 @@
310
316
 
311
317
  /* Text levels: primary ink-950, secondary ink-900, tertiary a tuned grey.
312
318
  All three clear AA (4.5:1) for body copy on every surface they land on.
313
- Tertiary is NOT an ink step: ink-800 (#8d8d8d) was AA-large only (2.7:1
314
- on muted) but is used at 13px in 200+ places, so it is pinned to the
319
+ Tertiary is NOT an ink step: ink-850 (#70706a) falls below AA on muted
320
+ but is used at 13px in 200+ places, so it is pinned to the
315
321
  lightest grey that still passes 4.5:1 on bg/card/surface/muted. */
316
- --text-primary: var(--color-ink-950); /* ~16:1 AAA */
317
- --text-secondary: var(--color-ink-900); /* ~7.1:1 AAA */
318
- --text-tertiary: #686868; /* ~4.55:1 AA (min surf) */
322
+ --text-primary: var(--color-ink-950); /* ~14.5:1 AAA (min surf) */
323
+ --text-secondary: var(--color-ink-900); /* ~7.9:1 AAA (min surf) */
324
+ --text-tertiary: #686863; /* ~4.52:1 AA (min surf) */
319
325
 
320
326
  --surface: var(--color-ink-200); /* step 3 · tinted canvas */
321
327
  --surface-foreground: var(--color-ink-950);
@@ -327,8 +333,15 @@
327
333
  --card: #ffffff; /* pure white base */
328
334
  --card-foreground: var(--color-ink-950);
329
335
 
336
+ /* Studio green is deliberately isolated to the primary CTA role (roughly
337
+ 5–10% of a screen). Selection controls keep using neutral `brand` below,
338
+ so tabs, switches, radios, and progress never inherit CTA color. */
339
+ --action-primary: #2f7d5a;
340
+ --action-primary-foreground: #ffffff;
341
+ --action-primary-hover: #256749;
342
+
330
343
  /* Neutral action role. The `brand` name remains as a compatibility API,
331
- but the product has no colored primary palette. */
344
+ and shared selection/control states intentionally remain achromatic. */
332
345
  --brand: var(--color-ink-950); /* darkest action ink */
333
346
  --brand-foreground: #ffffff;
334
347
  --brand-hover: var(--color-ink-900); /* lighter hover lift */
@@ -340,7 +353,7 @@
340
353
  --table-row-hover: color-mix(in srgb, var(--card) 40%, var(--muted));
341
354
  --table-row-selected: color-mix(in srgb, var(--card) 10%, var(--muted));
342
355
 
343
- /* Quiet component fill. Radix step 3 is the first interactive-background
356
+ /* Quiet component fill. Ink step 3 is the first interactive-background
344
357
  step, so this remains visible on both white cards and the step-2 canvas. */
345
358
  --fill: var(--color-ink-200); /* step 3 · default component fill */
346
359
  --fill-foreground: var(--color-ink-950);
@@ -348,12 +361,12 @@
348
361
  --accent: var(--color-ink-400); /* step 5 · active / selected wash */
349
362
  --accent-foreground: var(--color-ink-950);
350
363
 
351
- /* Borders use consecutive Radix steps 5–7. This avoids the old 3→5→7 jump:
352
- tertiary stays quiet but visible at 0.5px, secondary is the Radix subtle
364
+ /* Borders use consecutive ink steps 5–7. This avoids the old 3→5→7 jump:
365
+ tertiary stays quiet but visible at 0.5px, secondary is the subtle
353
366
  border step, and primary is the default interactive-control edge. */
354
- --border-primary: var(--color-ink-600); /* step 7 · #cecece · strongest */
355
- --border-secondary: var(--color-ink-500); /* step 6 · #d9d9d9 · default */
356
- --border-tertiary: var(--color-ink-400); /* step 5 · #e0e0e0 · faintest */
367
+ --border-primary: var(--color-ink-600); /* step 7 · #c9c8c2 · strongest */
368
+ --border-secondary: var(--color-ink-500); /* step 6 · #d5d4cf · default */
369
+ --border-tertiary: var(--color-ink-400); /* step 5 · #deded9 · faintest */
357
370
  /* Legacy aliases point into the scale so existing utilities keep resolving. */
358
371
  --border: var(--border-secondary); /* default hairline / separator */
359
372
  --border-strong: var(--border-primary); /* emphasized / hover / selected */
@@ -384,7 +397,7 @@
384
397
  --canvas-edge: var(--border-secondary);/* infinite-canvas edges / connectors */
385
398
  --texture-ink: var(--color-ink-950); /* brand-texture / pixel-blast marks */
386
399
  --table-shell: var(--color-ink-200); /* recessed table tray (lighter than muted) */
387
- --table-scroll-hint: rgb(32 32 32 / 0.04); /* right-edge "more columns" wash */
400
+ --table-scroll-hint: rgb(23 23 20 / 0.04); /* right-edge "more columns" wash */
388
401
  --surface-inverse: var(--color-ink-950); /* dark hero / inverse surface base */
389
402
  --surface-inverse-soft: var(--color-ink-900); /* dark hero gradient falloff */
390
403
  --artifact-canvas: color-mix(in srgb, var(--color-brand-mark) 7%, #ffffff);