@actioneer/ads 0.5.6 → 0.5.8

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 (149) hide show
  1. package/bin/ads-init.mjs +6 -0
  2. package/components/accordion.js +50 -48
  3. package/components/agent-icon.d.ts +12 -0
  4. package/components/agent-icon.js +135 -121
  5. package/components/ai-elements/chain-of-thought-icon.d.ts +10 -12
  6. package/components/ai-elements/chain-of-thought-icon.js +341 -201
  7. package/components/ai-elements/chain-of-thought.d.ts +2 -2
  8. package/components/ai-elements/chain-of-thought.js +108 -108
  9. package/components/ai-elements/chart.js +16 -14
  10. package/components/ai-elements/inline-citation.js +41 -41
  11. package/components/ai-elements/message.js +4 -4
  12. package/components/ai-elements/queue.js +7 -7
  13. package/components/ai-elements/research-activity.js +114 -114
  14. package/components/ai-elements/shimmer.d.ts +2 -2
  15. package/components/ai-elements/speech-input.js +28 -28
  16. package/components/ai-elements/task-progress.js +26 -16
  17. package/components/ai-elements/task.js +17 -17
  18. package/components/ai-elements/tool.js +6 -6
  19. package/components/ai-elements/transcript.js +6 -5
  20. package/components/ai-elements/voice.js +1 -1
  21. package/components/alert.js +10 -10
  22. package/components/answer-sources.d.ts +42 -0
  23. package/components/answer-sources.js +111 -0
  24. package/components/answer.js +115 -114
  25. package/components/assistant-ui/action-bar.js +94 -48
  26. package/components/assistant-ui/attachment.js +131 -103
  27. package/components/assistant-ui/badge.d.ts +1 -1
  28. package/components/assistant-ui/badge.js +17 -17
  29. package/components/assistant-ui/chain-of-thought.d.ts +1 -1
  30. package/components/assistant-ui/composer-add-context.js +9 -9
  31. package/components/assistant-ui/composer-deep-research.js +5 -5
  32. package/components/assistant-ui/composer-harness.js +12 -9
  33. package/components/assistant-ui/composer-trigger-popover.js +45 -34
  34. package/components/assistant-ui/composer.js +59 -59
  35. package/components/assistant-ui/error.js +14 -14
  36. package/components/assistant-ui/file.d.ts +1 -1
  37. package/components/assistant-ui/image.d.ts +1 -1
  38. package/components/assistant-ui/image.js +113 -103
  39. package/components/assistant-ui/markdown-text.js +18 -18
  40. package/components/assistant-ui/message.js +46 -45
  41. package/components/assistant-ui/quote.js +1 -1
  42. package/components/assistant-ui/reasoning.d.ts +1 -1
  43. package/components/assistant-ui/reasoning.js +66 -77
  44. package/components/assistant-ui/suggestions.js +4 -4
  45. package/components/assistant-ui/thread-context.d.ts +2 -0
  46. package/components/assistant-ui/thread.js +41 -40
  47. package/components/assistant-ui/tool-fallback.js +60 -63
  48. package/components/assistant-ui/tool-group.d.ts +1 -1
  49. package/components/assistant-ui/tool-group.js +36 -42
  50. package/components/audio-waveform.js +25 -24
  51. package/components/autocomplete.d.ts +1 -0
  52. package/components/autocomplete.js +45 -43
  53. package/components/avatar.js +30 -30
  54. package/components/badge.d.ts +1 -1
  55. package/components/breadcrumbs.js +2 -2
  56. package/components/button.d.ts +2 -2
  57. package/components/button.js +22 -20
  58. package/components/card.js +8 -8
  59. package/components/carousel.js +105 -104
  60. package/components/chart.js +9 -7
  61. package/components/checkbox.js +74 -38
  62. package/components/chip.d.ts +1 -1
  63. package/components/code-block.js +3 -3
  64. package/components/collapsible.js +67 -23
  65. package/components/connector-card.js +6 -6
  66. package/components/drawer.d.ts +15 -10
  67. package/components/drawer.js +78 -77
  68. package/components/dropdown.d.ts +3 -1
  69. package/components/dropdown.js +88 -79
  70. package/components/empty-state.d.ts +4 -4
  71. package/components/empty-state.js +7 -7
  72. package/components/field.d.ts +4 -0
  73. package/components/field.js +45 -34
  74. package/components/file-dropzone.js +12 -12
  75. package/components/index.d.ts +4 -0
  76. package/components/index.js +584 -553
  77. package/components/infinite-canvas.js +1 -1
  78. package/components/input-field.js +51 -46
  79. package/components/input.js +20 -20
  80. package/components/link.js +9 -9
  81. package/components/modal.js +105 -73
  82. package/components/navbar.d.ts +1 -1
  83. package/components/navbar.js +1 -1
  84. package/components/number-field.js +38 -29
  85. package/components/page-header.js +12 -12
  86. package/components/pagination.js +19 -19
  87. package/components/panel.js +2 -2
  88. package/components/pixel-blast-svg.js +3 -3
  89. package/components/pixel-icon.d.ts +3 -1
  90. package/components/pixel-icon.js +294 -215
  91. package/components/popover.d.ts +1 -1
  92. package/components/popover.js +66 -64
  93. package/components/progress-circle.js +36 -32
  94. package/components/progress.js +28 -24
  95. package/components/radio.js +59 -49
  96. package/components/resizable-panel.js +1 -1
  97. package/components/reveal.d.ts +2 -2
  98. package/components/ripple.d.ts +3 -3
  99. package/components/scroll-area.js +17 -16
  100. package/components/segmented.d.ts +4 -1
  101. package/components/segmented.js +26 -25
  102. package/components/select.d.ts +2 -0
  103. package/components/select.js +61 -57
  104. package/components/setting-row.js +45 -42
  105. package/components/sidebar.d.ts +2 -2
  106. package/components/sidebar.js +131 -127
  107. package/components/skeleton.js +5 -5
  108. package/components/spinner.d.ts +13 -4
  109. package/components/spinner.js +42 -42
  110. package/components/stepper.js +21 -21
  111. package/components/switch.js +52 -32
  112. package/components/table.d.ts +24 -7
  113. package/components/table.js +457 -220
  114. package/components/tabs.js +149 -137
  115. package/components/textarea.js +1 -2
  116. package/components/toast.js +66 -66
  117. package/components/tooltip.js +2 -2
  118. package/components/tree.js +62 -51
  119. package/components/typography.d.ts +2 -1
  120. package/components/typography.js +33 -32
  121. package/components/ui/button.d.ts +2 -2
  122. package/components/ui/button.js +19 -19
  123. package/components/ui/collapsible.d.ts +1 -5
  124. package/components/ui/dialog.d.ts +3 -3
  125. package/components/ui/dialog.js +95 -58
  126. package/components/ui/tooltip.d.ts +2 -2
  127. package/components/ui/tooltip.js +67 -33
  128. package/components/viz-charts.js +95 -95
  129. package/demo/components/add-to-artifact.js +341 -0
  130. package/demo/lib/artifact-library.js +134 -0
  131. package/fonts/aribau-grotesk-medium.woff2 +0 -0
  132. package/fonts/aribau-grotesk-regular.woff2 +0 -0
  133. package/fonts.css +11 -11
  134. package/hooks/agents-ui/use-agent-audio-visualizer-aura.js +17 -16
  135. package/hooks/agents-ui/use-agent-audio-visualizer-wave.js +21 -20
  136. package/lib/icons.d.ts +12 -0
  137. package/lib/icons.js +107 -104
  138. package/lib/motion.d.ts +42 -39
  139. package/lib/motion.js +112 -52
  140. package/lib/spinner-mark.d.ts +9 -0
  141. package/lib/spinner-mark.js +98 -0
  142. package/llms.txt +69 -26
  143. package/manifest.json +344 -42
  144. package/package.json +1 -1
  145. package/styles.css +175 -161
  146. package/theme.css +104 -128
  147. package/components/ui/collapsible.js +0 -35
  148. package/fonts/aribau-grotesk-500.otf +0 -0
  149. package/fonts/aribau-grotesk-600.woff2 +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actioneer/ads",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "Actioneer Design System 1.0 — React 19 + Tailwind v4 component library.",
5
5
  "type": "module",
6
6
  "sideEffects": [
package/styles.css CHANGED
@@ -5,39 +5,46 @@
5
5
  @import "tw-animate-css";
6
6
 
7
7
  /* ---- Aribau Grotesk ---- */
8
- /* Aribau Grotesk — ADS 1.0 brand typeface.
9
- TWO weights only: Regular (400) and Semibold (600). Use `font-normal` and
10
- `font-semibold` — there is NO dedicated bold face, so never reach for
11
- `font-bold` (it would just fold onto the 600 file). The weight RANGES map
12
- Tailwind's utilities onto the two physical files:
13
- `font-normal` → Regular (100–500), `font-semibold` → Semibold (600–900).
14
- `font-synthesis-weight: none` (set in index.css) prevents faux weights. */
8
+ /* Aribau Grotesk — ADS UI typeface.
9
+ TWO physical faces, both served compressed (woff2):
10
+ • Regular → `font-normal` (weight 100–499)
11
+ • Medium → `font-medium` (weight 500)
12
+ There is NO semibold or bold face. The broad face range keeps legacy
13
+ consumers on the real Medium file, while ADS source uses only 400 and 500.
14
+ `font-synthesis-weight: none` (index.css) blocks faux bolding. */
15
15
  @font-face {
16
16
  font-family: "Aribau Grotesk";
17
- src: url("./fonts/aribau-grotesk-400.otf") format("opentype");
18
- font-weight: 100 500;
17
+ src: url("./fonts/aribau-grotesk-regular.woff2") format("woff2");
18
+ font-weight: 100 499;
19
19
  font-style: normal;
20
20
  font-display: swap;
21
21
  }
22
22
  @font-face {
23
23
  font-family: "Aribau Grotesk";
24
- src: url("./fonts/aribau-grotesk-600.woff2") format("woff2");
25
- font-weight: 600 900;
24
+ src: url("./fonts/aribau-grotesk-medium.woff2") format("woff2");
25
+ font-weight: 500 900;
26
26
  font-style: normal;
27
27
  font-display: swap;
28
28
  }
29
29
 
30
30
  /* ---- Design tokens ---- */
31
+ /* ADS is light-only. Redefine the `dark` variant to be class-gated instead of
32
+ Tailwind's default `@media (prefers-color-scheme: dark)`, so a stray `dark:`
33
+ utility can never activate off the OS setting while there is no dark token
34
+ set. Nothing in ADS adds `.dark`, so `dark:` styles stay dormant. */
35
+ @custom-variant dark (&:where(.dark, .dark *));
36
+
31
37
  /*
32
38
  * ============================================================
33
39
  * ADS 1.0 — Design Tokens
34
- * Brand: Sage (green) · Neutrals: brand-palette grey · Typeface: Aribau Grotesk
40
+ * Palette: Ink neutrals · Typeface: Aribau Grotesk
35
41
  * ============================================================
36
42
  */
37
43
  @theme {
38
44
  /* ---- Typography ----
39
- One brand typeface. Figures inside prose stay in Aribau Grotesk with
40
- `tabular-nums`; only literal source code steps to the mono stack. */
45
+ One brand typeface (Regular + Medium). Figures stay in Aribau Grotesk with
46
+ `tabular-nums` (enabled globally in index.css); only literal source code
47
+ steps to the mono stack. */
41
48
  --font-sans: "Aribau Grotesk", ui-sans-serif, system-ui, -apple-system,
42
49
  "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
43
50
 
@@ -69,49 +76,30 @@
69
76
  --text-2xl: 1.625rem; /* 26px — display */
70
77
  --text-2xl--line-height: 2rem;
71
78
 
72
- /* ---- Neutral ramp — the full 12-step brand palette grey (light section,
73
- solid row). A Radix-style scale: each step owns a role — 50/100 =
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.
83
+ Each step owns a role — 50/100 =
74
84
  backgrounds, 200/300/400 = interactive component fills, 500/600/700 =
75
- borders & separators, 800/850 = solid, 900/950 = accessible text. All 12
76
- values are present (the earlier 11-step cut is restored: #82827f is
77
- ink-850). The `ink` name is retained so every existing reference resolves;
78
- the semantic tokens below are re-derived from these roles. ---- */
79
- --color-ink-50: #fdfdfc; /* 1 · background */
80
- --color-ink-100: #f9f9f8; /* 2 · background */
81
- --color-ink-200: #f0f0ef; /* 3 · interactive */
82
- --color-ink-300: #e8e8e7; /* 4 · interactive */
83
- --color-ink-400: #e1e1e0; /* 5 · interactive */
84
- --color-ink-500: #d9d9d8; /* 6 · border */
85
- --color-ink-600: #cececd; /* 7 · border */
86
- --color-ink-700: #bbbbb9; /* 8 · border */
87
- --color-ink-800: #8c8c89; /* 9 · solid */
88
- --color-ink-850: #82827f; /* 10 · solid */
89
- --color-ink-900: #636461; /* 11 · accessible text */
90
- --color-ink-950: #1f1f1c; /* 12 · accessible text */
91
-
92
- /* ---- Brand ramp — the full 12-step Sage green (light section, solid row),
93
- same Radix roles as the neutral ramp. All 12 present: sage-850 (#417c36,
94
- step 11 = the accessible green text tone) and sage-950 (#273d23, step 12)
95
- are restored. The interactive brand (--brand #3f7a34) is step 9 (solid);
96
- its hover is step 10 (#316c26). NOTE: steps 9–12 are not a pure lightness
97
- ramp (Radix convention) — the Tailwind name order differs from role
98
- order, so read the role comment, not the number. ---- */
99
- --color-sage-50: #fbfefb; /* 1 · background */
100
- --color-sage-100: #f6fbf5; /* 2 · background */
101
- --color-sage-200: #e9f7e6; /* 3 · interactive */
102
- --color-sage-300: #dbf1d6; /* 4 · interactive */
103
- --color-sage-400: #cae8c5; /* 5 · interactive */
104
- --color-sage-500: #b6dcaf; /* 6 · border */
105
- --color-sage-600: #9ccc93; /* 7 · border */
106
- --color-sage-700: #77b76b; /* 8 · border */
107
- --color-sage-800: #3f7a34; /* 9 · solid (brand) */
108
- --color-sage-900: #316c26; /* 10 · solid (hover) */
109
- --color-sage-850: #417c36; /* 11 · accessible text */
110
- --color-sage-950: #273d23; /* 12 · accessible text */
85
+ borders & separators, 800/850 = solid, 900/950 = accessible text. The
86
+ `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 */
111
100
 
112
101
  /* ---- Semantic accent ramps ---- */
113
- /* Success — shifted cooler (emerald/teal) so positive states stay clearly
114
- distinct from the warm Sage brand green. */
102
+ /* Success stays a semantic state color, never a product-primary hue. */
115
103
  --color-success-50: #ecfdf5;
116
104
  --color-success-100: #d1fae5;
117
105
  --color-success-500: #10b981;
@@ -138,7 +126,7 @@
138
126
 
139
127
  /* ---- Data-viz accents ---- three small ramps for charts & illustration.
140
128
  deep = text/lines · base = fills · soft = backgrounds. Separate from the
141
- semantic status ramps above; these are the "focal data" companions to Sage. */
129
+ semantic status ramps above; these carry data, not product identity. */
142
130
  --color-cyan-soft: #c7efe9; /* Cyan — vivid cool contrast; 2nd series, links */
143
131
  --color-cyan-base: #12b5a5;
144
132
  --color-cyan-deep: #0a7e82;
@@ -149,14 +137,23 @@
149
137
  --color-amber-base: #f3a72e;
150
138
  --color-amber-deep: #b57414;
151
139
 
152
- /* ---- Radii ---- FIVE steps only: 2 · 4 · 8 · 16 · 24 (px), plus `full`
153
- for pills/circles. xs aliases sm (4px); 2xl aliases xl (24px). */
154
- --radius-xs: 0.25rem; /* 4px */
155
- --radius-sm: 0.25rem; /* 4px */
156
- --radius-md: 0.5rem; /* 8px */
157
- --radius-lg: 1rem; /* 16px */
158
- --radius-xl: 1.5rem; /* 24px */
159
- --radius-2xl: 1.5rem; /* 24px (alias xl) */
140
+ /* Demo logo indigo — source for artifact canvas wash. */
141
+ --color-brand-mark: #2e1065;
142
+
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
+ --radius-xs: 0.125rem; /* 2px · micro details */
148
+ --radius-sm: 0.25rem; /* 4px · compact controls */
149
+ --radius-md: 0.5rem; /* 8px · standard controls */
150
+ --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
+ /* Shape-only exception for avatars, icon buttons, progress tracks, chips,
156
+ and badges. It is not part of the corner-radius scale. */
160
157
  --radius-full: 9999px;
161
158
  /* Status/indicator dots are SQUARE with a hair of softening — echoing the
162
159
  growth-mark's square cells. Never render an indicator dot as a circle
@@ -166,20 +163,17 @@
166
163
 
167
164
  /* ---- Elevation ---- ONE soft token (Claude-panel style).
168
165
  Delineate surfaces with fill color first; add this to gently lift them.
169
- Tuned quieter (2026-07-30): the ambient drop sits closer (y8→y4,
170
- blur28→16) at lower opacity (9%→6%) with a faint COOL slate tint
171
- (rgb 15 23 42, not near-black) — a hard, offset-heavy black drop read
172
- "cheap" and floated small controls (switch thumb, tab pill). */
173
- --shadow-elevation: 0 0 0 1px rgb(15 23 42 / 0.03),
174
- 0 1px 2px 0 rgb(15 23 42 / 0.04),
175
- 0 4px 16px -6px rgb(15 23 42 / 0.06);
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);
176
171
 
177
172
  /* Pinned-table-column smudges — whisper-soft directional casts shown only
178
173
  while content is hidden behind a sticky column (Table is scroll-aware).
179
- Deep negative spread keeps the edge feathered; same cool slate tint as
180
- the elevation token. */
181
- --shadow-table-smudge-left: 8px 0 24px -14px rgb(15 23 42 / 0.05);
182
- --shadow-table-smudge-right: -8px 0 24px -14px rgb(15 23 42 / 0.05);
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);
183
177
 
184
178
  /* ---- CTA inner glow ---- luminous inset highlight for primary buttons
185
179
  (adapted from the "AI button" Figma): a crisp top-edge catch plus a soft
@@ -193,36 +187,7 @@
193
187
  inset 0 8px 16px -8px rgb(255 255 255 / 0.45);
194
188
  /* Text fields — a whisper of inset depth so the writing surface reads
195
189
  recessed into the page (persists through hover/focus/invalid). */
196
- --inner-glow-field: inset 0 1px 2px 0 rgb(10 10 11 / 0.06);
197
-
198
- /* ---- Motion ---- strong custom curves; the built-in CSS easings are too
199
- weak. Declared here so the `ease-out` / `ease-in-out` utilities resolve
200
- to these system-wide. JS mirror: src/lib/motion.ts — keep in sync. */
201
- --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* entrances, exits, presses */
202
- --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* on-screen movement / morphs */
203
- --ease-expo-out: cubic-bezier(0.16, 1, 0.3, 1); /* side-panel and drawer slide */
204
- --ease-drawer: var(--ease-expo-out); /* backwards-compatible alias */
205
- --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* playful overshoot (rare) */
206
- --ease-disclosure: cubic-bezier(0.32, 0.72, 0, 1); /* height reveals — moves off the mark immediately, settles long */
207
-
208
- /* Durations — every animation/transition timing flows from these.
209
- UI animations stay under 300ms; exits run faster than enters. */
210
- --duration-fast: 0.15s; /* menu / popover / tooltip enter */
211
- --duration-normal: 0.2s; /* state transitions */
212
- --duration-disclosure: 0.28s; /* collapsible open — travels a real distance */
213
- --duration-spin: 0.8s; /* rotation loops (spinner) */
214
- --duration-pulse: 1.5s; /* breathing / shimmer loops */
215
- --duration-bloom: 0.9s; /* ambient reveals (chat texture bloom, curtain wipe) */
216
- --duration-brand-loader: 3.4s; /* BrandLoader flicker loop */
217
-
218
- /* Entrance-choreography beats — staggered delays for sequenced arrivals
219
- (e.g. chat welcome: mark → greeting → composer). */
220
- --stagger-1: 0.2s;
221
- --stagger-2: 0.3s;
222
- --stagger-3: 0.42s;
223
-
224
- /* Press feedback — every pressable element scales down on :active */
225
- --scale-press: 0.97;
190
+ --inner-glow-field: inset 0 1px 2px 0 rgb(32 32 32 / 0.06);
226
191
 
227
192
  /* ---- Layout ---- app-frame dimensions (Sidebar / Panel) */
228
193
  --sidebar-width: 15rem; /* 240px — primary nav rail */
@@ -302,7 +267,7 @@
302
267
  --color-card: var(--card);
303
268
  --color-card-foreground: var(--card-foreground);
304
269
 
305
- /* Brand (Sage green) — used for solid fills / primary actions, not body text */
270
+ /* Compatibility action role — neutral ink, never a colored primary hue. */
306
271
  --color-brand: var(--brand);
307
272
  --color-brand-foreground: var(--brand-foreground);
308
273
  --color-brand-hover: var(--brand-hover);
@@ -313,13 +278,18 @@
313
278
  --color-fill-foreground: var(--fill-foreground);
314
279
  --color-table-shell: var(--table-shell);
315
280
 
281
+ --color-artifact-canvas: var(--artifact-canvas);
282
+
316
283
  --color-accent: var(--accent);
317
284
  --color-accent-foreground: var(--accent-foreground);
318
285
 
319
- --color-success: var(--color-success-600);
286
+ /* success-700 on white = 5.48:1 (600 was 3.77:1, failed AA). */
287
+ --color-success: var(--color-success-700);
320
288
  --color-success-foreground: #ffffff;
289
+ /* Amber-500 fill kept (it IS the caution signal); dark ink foreground
290
+ instead of white = 6.94:1 (white on amber was 2.35:1, failed even 3:1). */
321
291
  --color-warning: var(--color-warning-500);
322
- --color-warning-foreground: #ffffff;
292
+ --color-warning-foreground: var(--color-ink-950);
323
293
  --color-danger: var(--color-danger-600);
324
294
  --color-danger-foreground: #ffffff;
325
295
  --color-info: var(--color-info-600);
@@ -361,18 +331,20 @@
361
331
 
362
332
  /* ---- Theme (light only) ---- */
363
333
  :root {
364
- /* Every semantic token below points INTO a primitive scale step
365
- (var(--color-ink-*) / var(--color-sage-*)) — the 12-step scales are the
366
- single source of truth. Only pure white (#ffffff) stays literal: it is a
367
- base surface, not a neutral scale step. */
334
+ /* Every neutral semantic token below points INTO the ink primitive scale.
335
+ Only pure white (#ffffff) stays literal: it is a base surface, not a
336
+ neutral scale step. */
368
337
  --background: var(--color-ink-100); /* step 2 · canvas */
369
338
  --foreground: var(--color-ink-950); /* step 12 */
370
339
 
371
- /* Text levels: primary ink-950, secondary ink-900, tertiary ink-800.
372
- Primary + secondary clear AA for body copy; tertiary is AA-large only. */
373
- --text-primary: var(--color-ink-950); /* ~16:1 AAA */
374
- --text-secondary: var(--color-ink-900); /* ~5.3:1 AA */
375
- --text-tertiary: var(--color-ink-800); /* ~3:1 AA-large */
340
+ /* Text levels: primary ink-950, secondary ink-900, tertiary a tuned grey.
341
+ 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
344
+ 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) */
376
348
 
377
349
  --surface: var(--color-ink-200); /* step 3 · tinted canvas */
378
350
  --surface-foreground: var(--color-ink-950);
@@ -384,11 +356,12 @@
384
356
  --card: #ffffff; /* pure white base */
385
357
  --card-foreground: var(--color-ink-950);
386
358
 
387
- /* Sage brand (green) — solid role. brand = sage step 9, hover = step 10. */
388
- --brand: var(--color-sage-800); /* step 9 · solid */
359
+ /* Neutral action role. The `brand` name remains as a compatibility API,
360
+ but the product has no colored primary palette. */
361
+ --brand: var(--color-ink-950); /* darkest action ink */
389
362
  --brand-foreground: #ffffff;
390
- --brand-hover: var(--color-sage-900); /* step 10 · hover */
391
- --brand-text: var(--color-sage-850); /* step 11 · accessible green text/links */
363
+ --brand-hover: var(--color-ink-900); /* lighter hover lift */
364
+ --brand-text: var(--color-ink-950); /* action text / links */
392
365
 
393
366
  /* Table interaction fills are pre-composited and opaque. Sticky edge cells
394
367
  therefore cover horizontally scrolled content while preserving the
@@ -396,56 +369,59 @@
396
369
  --table-row-hover: color-mix(in srgb, var(--card) 40%, var(--muted));
397
370
  --table-row-selected: color-mix(in srgb, var(--card) 10%, var(--muted));
398
371
 
399
- /* Quiet fill */
400
- --fill: var(--color-ink-50); /* step 1 · lightest recessed fill */
372
+ /* Quiet component fill. Radix step 3 is the first interactive-background
373
+ step, so this remains visible on both white cards and the step-2 canvas. */
374
+ --fill: var(--color-ink-200); /* step 3 · default component fill */
401
375
  --fill-foreground: var(--color-ink-950);
402
376
 
403
- --accent: var(--color-ink-200); /* step 3 */
377
+ --accent: var(--color-ink-400); /* step 5 · active / selected wash */
404
378
  --accent-foreground: var(--color-ink-950);
405
379
 
406
- /* Borders — a three-level scale, primary (strongest) → tertiary (faintest). */
407
- --border-primary: var(--color-ink-600); /* #cececd · strongest */
408
- --border-secondary: var(--color-ink-400); /* #e1e1e0 · default */
409
- --border-tertiary: var(--color-ink-200); /* #f0f0ef · faintest */
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
382
+ 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 */
410
386
  /* Legacy aliases point into the scale so existing utilities keep resolving. */
411
387
  --border: var(--border-secondary); /* default hairline / separator */
412
388
  --border-strong: var(--border-primary); /* emphasized / hover / selected */
413
389
  --input: var(--border-primary); /* form-control edge */
414
390
 
415
391
  /* Ripple — the appearance wash that radiates from a floating surface's
416
- origin corner as it opens (Dropdown/Popover/Select/Modal…). A soft brand
392
+ origin corner as it opens (Dropdown/Popover/Select/Modal…). A soft ink
417
393
  tint that expands + fades once on mount; see the `.ads-ripple` layer and
418
- the `Ripple` component. Duration stays in the sub-300ms UI band. */
394
+ the `Ripple` component. */
419
395
  --ripple-tint: color-mix(in srgb, var(--brand) 20%, transparent);
420
- --ripple-duration: 300ms;
421
396
 
422
397
  /* Stroke width — ADS hairlines are 0.5px, not the Tailwind 1px default.
423
398
  The single-width border utilities are overridden to this token at the
424
399
  bottom of this file, so every `border`/`border-t|r|b|l|x|y` reads as a
425
400
  true hairline. Explicit `border-2`+ widths are unaffected. */
426
401
  --stroke-width: 0.5px;
427
- --ring: color-mix(in srgb, var(--color-sage-800) 50%, transparent); /* brand @ 50% */
402
+ --ring: color-mix(in srgb, var(--color-ink-950) 50%, transparent); /* ink @ 50% */
428
403
  --overlay: color-mix(in srgb, var(--color-ink-950) 50%, transparent); /* ink-950 @ 50% */
429
404
 
430
405
  /* Functional / domain tokens — named for their RENDER role, pointing into
431
406
  the ink scale. Components pass these into non-CSS renderers (Recharts,
432
407
  React Flow, the Paper/WebGL texture) so no component carries a raw ink-*
433
408
  value. Same DS pattern as the data-viz --color-chart-* palette. */
434
- --chart-axis: var(--color-ink-200); /* axis lines + de-emphasised marks */
435
- --chart-grid: var(--color-ink-50); /* gridlines */
436
- --chart-track: var(--color-ink-100); /* funnel / progress track */
437
- --chart-context: var(--color-ink-300); /* de-emphasised context series */
438
- --canvas-edge: var(--color-ink-300); /* infinite-canvas edges / connectors */
409
+ --chart-axis: var(--border-tertiary); /* axis lines + de-emphasised marks */
410
+ --chart-grid: var(--color-ink-200); /* quieter than axes, visible on white */
411
+ --chart-track: var(--color-ink-200); /* funnel / progress track */
412
+ --chart-context: var(--color-ink-500); /* de-emphasised context series */
413
+ --canvas-edge: var(--border-secondary);/* infinite-canvas edges / connectors */
439
414
  --texture-ink: var(--color-ink-950); /* brand-texture / pixel-blast marks */
440
415
  --table-shell: var(--color-ink-200); /* recessed table tray (lighter than muted) */
441
- --table-scroll-hint: rgb(15 23 42 / 0.04); /* right-edge "more columns" wash */
416
+ --table-scroll-hint: rgb(32 32 32 / 0.04); /* right-edge "more columns" wash */
442
417
  --surface-inverse: var(--color-ink-950); /* dark hero / inverse surface base */
443
418
  --surface-inverse-soft: var(--color-ink-900); /* dark hero gradient falloff */
419
+ --artifact-canvas: color-mix(in srgb, var(--color-brand-mark) 7%, #ffffff);
444
420
 
445
421
  /* shadcn-compat raw surfaces — so a downstream shadcn Sidebar / Popover
446
422
  (or an inline `var(--sidebar)` / `var(--popover)`) resolves to the ADS
447
423
  palette instead of shadcn's grey/black defaults. The sidebar reads as the
448
- neutral canvas; its active item takes Sage. A consumer that had
424
+ neutral canvas; its active item takes action ink. A consumer that had
449
425
  hard-coded these can now delete its overrides and inherit from here. */
450
426
  --sidebar: var(--surface);
451
427
  --sidebar-foreground: var(--foreground);
@@ -494,7 +470,7 @@
494
470
  pointer-events: none;
495
471
  transform-origin: var(--ripple-origin, center);
496
472
  background: radial-gradient(125% 125% at var(--ripple-origin, center), var(--ripple-tint), transparent 62%);
497
- animation: ads-ripple-wave var(--ripple-duration, 300ms) var(--ease-out) forwards;
473
+ animation: ads-ripple-wave 300ms ease-out forwards;
498
474
  will-change: transform, opacity;
499
475
  }
500
476
  @media (prefers-reduced-motion: reduce) {
@@ -530,6 +506,32 @@
530
506
  display: none;
531
507
  }
532
508
 
509
+ /* Artifact widgets are positioned by GridStack; ADS cards own the visible
510
+ surface while the library content wrapper only clips during interaction.
511
+ The subtle elevation lives on the wrapper (not the inner card) because the
512
+ wrapper's own `overflow: hidden` would clip a shadow drawn on its child. */
513
+ .artifact-grid-stack > .grid-stack-item > .grid-stack-item-content {
514
+ overflow: hidden;
515
+ border-radius: var(--radius-lg);
516
+ box-shadow: var(--shadow-elevation);
517
+ }
518
+
519
+ /* Edit affordances live on a parent flag — never toggle GridStack's own
520
+ className, or React will wipe library-managed classes (grid-stack, gs-N). */
521
+ [data-artifact-edit-mode] .artifact-grid-stack > .grid-stack-item > .grid-stack-item-content {
522
+ cursor: grab;
523
+ }
524
+
525
+ [data-artifact-edit-mode] .artifact-grid-stack > .grid-stack-item > .grid-stack-item-content:active {
526
+ cursor: grabbing;
527
+ }
528
+
529
+ .artifact-grid-stack > .grid-stack-placeholder > .placeholder-content {
530
+ border: 1px dashed var(--color-border-strong);
531
+ border-radius: var(--radius-sm);
532
+ background: var(--color-muted);
533
+ }
534
+
533
535
  /* BrandTexture entrance (src/components/brand-texture.tsx): a radial bloom —
534
536
  the halftone reveals from the centre out to the corners (clip-path circle)
535
537
  while gently scaling up to rest. `from{}`-only keyframe, so it settles into
@@ -545,7 +547,7 @@
545
547
  }
546
548
  }
547
549
  .ads-texture-reveal {
548
- animation: ads-texture-reveal var(--duration-bloom) var(--ease-out) both;
550
+ animation: ads-texture-reveal 900ms ease-out both;
549
551
  }
550
552
 
551
553
  /* Paper's WebGL shader owns the halftone animation. The canvas is bounded to
@@ -613,10 +615,10 @@
613
615
  mask-position: 0% 0%;
614
616
  -webkit-mask-position: 0% 0%;
615
617
  transition:
616
- mask-position 1s var(--ease-out),
617
- -webkit-mask-position 1s var(--ease-out),
618
- translate 1s var(--ease-out),
619
- opacity 1s var(--ease-out);
618
+ mask-position 1s ease-out,
619
+ -webkit-mask-position 1s ease-out,
620
+ translate 1s ease-out,
621
+ opacity 1s ease-out;
620
622
  }
621
623
  .ads-texture-lifted {
622
624
  mask-position: 0% 100%;
@@ -625,7 +627,7 @@
625
627
  }
626
628
  @media (prefers-reduced-motion: reduce) {
627
629
  .ads-texture-lift {
628
- transition: opacity var(--duration-normal) var(--ease-out);
630
+ transition: opacity 200ms ease-out;
629
631
  }
630
632
  .ads-texture-lifted {
631
633
  mask-position: 0% 0%;
@@ -664,7 +666,7 @@
664
666
  }
665
667
  }
666
668
  .brand-loader-cell {
667
- animation: brand-flicker var(--duration-brand-loader) steps(1) infinite backwards;
669
+ animation: brand-flicker 3.4s steps(1) infinite backwards;
668
670
  }
669
671
  @media (prefers-reduced-motion: reduce) {
670
672
  .brand-loader-cell {
@@ -689,7 +691,10 @@
689
691
  color: var(--foreground);
690
692
  font-family: var(--font-sans);
691
693
  font-size: var(--text-base); /* 15px base */
692
- font-feature-settings: "cv01", "ss01";
694
+ /* Stylistic sets ss01, ss02, ss03. Figures are tabular everywhere
695
+ (data-dense UI) via the real property, not a "tnum" feature tag. */
696
+ font-feature-settings: "ss01", "ss02", "ss03";
697
+ font-variant-numeric: tabular-nums;
693
698
  font-synthesis-weight: none;
694
699
  }
695
700
 
@@ -718,7 +723,7 @@
718
723
  }
719
724
  ::-webkit-scrollbar-thumb {
720
725
  background: var(--border-strong);
721
- border-radius: 9999px;
726
+ border-radius: var(--radius-lg);
722
727
  border: 2px solid var(--background);
723
728
  }
724
729
  ::-webkit-scrollbar-thumb:hover {
@@ -774,7 +779,7 @@
774
779
  to { opacity: 1; }
775
780
  }
776
781
  .ads-reveal {
777
- animation: ads-reveal-rise var(--reveal-duration, 0.45s) var(--ease-out) both;
782
+ animation: ads-reveal-rise var(--reveal-duration, 0.45s) ease-out both;
778
783
  animation-delay: calc(var(--reveal-step, 70ms) * var(--reveal-order, 0));
779
784
  }
780
785
  .ads-reveal-ink { animation-name: ads-reveal-ink; }
@@ -819,9 +824,9 @@
819
824
  border-color: var(--glow-border-rest);
820
825
  box-shadow: var(--glow-inset);
821
826
  transition:
822
- color var(--duration-normal) var(--ease-out),
823
- border-color var(--duration-normal) var(--ease-out),
824
- box-shadow var(--duration-normal) var(--ease-out);
827
+ color 200ms ease-out,
828
+ border-color 200ms ease-out,
829
+ box-shadow 200ms ease-out;
825
830
  }
826
831
 
827
832
  /* Hover: the same solid brand-black stroke as focus — one consistent
@@ -897,7 +902,7 @@
897
902
  }
898
903
 
899
904
  .ads-row-flash > td {
900
- animation: ads-row-flash 1.6s var(--ease-out) forwards;
905
+ animation: ads-row-flash 1.6s ease-out forwards;
901
906
  }
902
907
 
903
908
  @media (prefers-reduced-motion: reduce) {
@@ -916,11 +921,9 @@
916
921
  it does not merge), so animating height alongside tw-animate-css's enter/exit
917
922
  silently drops the fade and leaves a bare height shutter — which reads as
918
923
  rigid no matter how it is timed. Radix publishes the measured height as
919
- --radix-collapsible-content-height; exits run faster than enters.
920
- Eased with --ease-disclosure. --ease-out front-loads ~60% of the travel into
921
- the first third (pop, then settle); --ease-in-out holds ~150ms before moving
922
- (lag, then rush). A height reveal needs to leave the mark immediately and
923
- settle long, which is what this curve does. */
924
+ --radix-collapsible-content-height. This CSS-only primitive keeps its short
925
+ timing local; Motion-based disclosures use springDisclosure from
926
+ src/lib/motion.ts. */
924
927
  @keyframes ads-collapsible-down {
925
928
  from {
926
929
  height: 0;
@@ -946,10 +949,10 @@
946
949
  }
947
950
  }
948
951
  .ads-collapsible[data-state="open"] {
949
- animation: ads-collapsible-down var(--duration-disclosure) var(--ease-disclosure);
952
+ animation: ads-collapsible-down 280ms ease-in-out;
950
953
  }
951
954
  .ads-collapsible[data-state="closed"] {
952
- animation: ads-collapsible-up var(--duration-normal) var(--ease-disclosure);
955
+ animation: ads-collapsible-up 200ms ease-in-out;
953
956
  }
954
957
  @media (prefers-reduced-motion: reduce) {
955
958
  .ads-collapsible[data-state="open"],
@@ -1009,7 +1012,18 @@
1009
1012
  width: 1rem;
1010
1013
  border-bottom: 1px solid var(--border-strong);
1011
1014
  border-left: 1px solid var(--border-strong);
1012
- border-bottom-left-radius: 9px;
1015
+ border-bottom-left-radius: var(--radius-lg);
1016
+ }
1017
+
1018
+ /* Comments become a placement mode while the comments panel is open. Keep
1019
+ the native cursor readable while giving it the same compact ADS chat mark
1020
+ used by the rest of the Artifact UI. */
1021
+ .artifact-comment-cursor,
1022
+ .artifact-comment-cursor * {
1023
+ cursor:
1024
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'%3E%3Ccircle cx='14' cy='14' r='12' fill='white' stroke='%23242424' stroke-width='1.5'/%3E%3Cpath d='M8.5 9.5h11v7h-5.5l-3.5 3v-3h-2z' fill='%23242424'/%3E%3C/svg%3E")
1025
+ 5 5,
1026
+ crosshair !important;
1013
1027
  }
1014
1028
  /* Let the consumer's Tailwind discover the classes ADS components use. */
1015
1029
  @source "./**/*.{js,mjs}";