@actioneer/ads 0.5.7 → 0.5.9

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 (147) 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 +133 -120
  5. package/components/ai-elements/chain-of-thought.d.ts +1 -1
  6. package/components/ai-elements/chain-of-thought.js +108 -108
  7. package/components/ai-elements/chart.js +16 -14
  8. package/components/ai-elements/inline-citation.js +41 -41
  9. package/components/ai-elements/message.js +4 -4
  10. package/components/ai-elements/queue.js +7 -7
  11. package/components/ai-elements/research-activity.js +114 -114
  12. package/components/ai-elements/shimmer.d.ts +2 -2
  13. package/components/ai-elements/speech-input.js +28 -28
  14. package/components/ai-elements/task-progress.js +26 -16
  15. package/components/ai-elements/task.js +17 -17
  16. package/components/ai-elements/tool.js +6 -6
  17. package/components/ai-elements/transcript.js +6 -5
  18. package/components/ai-elements/voice.js +1 -1
  19. package/components/alert.js +10 -10
  20. package/components/answer-sources.js +1 -1
  21. package/components/answer.js +115 -114
  22. package/components/assistant-ui/action-bar.js +94 -48
  23. package/components/assistant-ui/attachment.js +103 -75
  24. package/components/assistant-ui/badge.d.ts +1 -1
  25. package/components/assistant-ui/badge.js +17 -17
  26. package/components/assistant-ui/chain-of-thought.d.ts +1 -1
  27. package/components/assistant-ui/composer-add-context.js +9 -9
  28. package/components/assistant-ui/composer-deep-research.js +5 -5
  29. package/components/assistant-ui/composer-harness.js +11 -9
  30. package/components/assistant-ui/composer-trigger-popover.js +45 -34
  31. package/components/assistant-ui/composer.js +59 -59
  32. package/components/assistant-ui/error.js +14 -14
  33. package/components/assistant-ui/file.d.ts +1 -1
  34. package/components/assistant-ui/image.d.ts +1 -1
  35. package/components/assistant-ui/image.js +113 -103
  36. package/components/assistant-ui/markdown-text.js +18 -18
  37. package/components/assistant-ui/message.js +46 -45
  38. package/components/assistant-ui/quote.js +1 -1
  39. package/components/assistant-ui/reasoning.d.ts +1 -1
  40. package/components/assistant-ui/reasoning.js +66 -77
  41. package/components/assistant-ui/suggestions.js +4 -4
  42. package/components/assistant-ui/thread.js +22 -22
  43. package/components/assistant-ui/tool-fallback.js +60 -63
  44. package/components/assistant-ui/tool-group.d.ts +1 -1
  45. package/components/assistant-ui/tool-group.js +36 -42
  46. package/components/audio-waveform.js +25 -24
  47. package/components/autocomplete.d.ts +1 -0
  48. package/components/autocomplete.js +45 -43
  49. package/components/avatar.d.ts +1 -0
  50. package/components/avatar.js +27 -26
  51. package/components/badge.d.ts +1 -1
  52. package/components/breadcrumbs.d.ts +2 -0
  53. package/components/breadcrumbs.js +52 -50
  54. package/components/button.d.ts +2 -2
  55. package/components/button.js +22 -20
  56. package/components/card.js +8 -8
  57. package/components/carousel.js +105 -104
  58. package/components/chart.d.ts +6 -0
  59. package/components/chart.js +743 -672
  60. package/components/checkbox.js +74 -38
  61. package/components/chip.d.ts +1 -1
  62. package/components/code-block.js +3 -3
  63. package/components/collapsible.js +67 -23
  64. package/components/connector-card.js +6 -6
  65. package/components/drawer.d.ts +18 -11
  66. package/components/drawer.js +81 -78
  67. package/components/dropdown.d.ts +2 -0
  68. package/components/dropdown.js +88 -79
  69. package/components/empty-state.d.ts +1 -1
  70. package/components/empty-state.js +7 -7
  71. package/components/field.d.ts +4 -0
  72. package/components/field.js +45 -34
  73. package/components/file-dropzone.js +12 -12
  74. package/components/index.d.ts +3 -0
  75. package/components/index.js +584 -558
  76. package/components/input-field.js +51 -46
  77. package/components/input.js +20 -20
  78. package/components/link.js +9 -9
  79. package/components/modal.d.ts +5 -1
  80. package/components/modal.js +121 -76
  81. package/components/navbar.d.ts +1 -1
  82. package/components/navbar.js +1 -1
  83. package/components/number-field.js +38 -29
  84. package/components/page-header.js +12 -12
  85. package/components/pagination.js +19 -19
  86. package/components/panel.js +2 -2
  87. package/components/pixel-blast-svg.js +3 -3
  88. package/components/pixel-icon.d.ts +4 -0
  89. package/components/pixel-icon.js +210 -164
  90. package/components/popover.d.ts +1 -1
  91. package/components/popover.js +66 -64
  92. package/components/progress-circle.js +36 -32
  93. package/components/progress.js +28 -24
  94. package/components/radio.js +59 -49
  95. package/components/resizable-panel.js +1 -1
  96. package/components/reveal.d.ts +2 -2
  97. package/components/ripple.d.ts +3 -3
  98. package/components/scroll-area.js +17 -16
  99. package/components/segmented.d.ts +1 -0
  100. package/components/segmented.js +39 -36
  101. package/components/select.d.ts +7 -0
  102. package/components/select.js +186 -137
  103. package/components/setting-row.js +45 -42
  104. package/components/sidebar.js +131 -127
  105. package/components/skeleton.js +5 -5
  106. package/components/spinner.d.ts +13 -4
  107. package/components/spinner.js +42 -42
  108. package/components/stepper.js +21 -21
  109. package/components/switch.js +41 -39
  110. package/components/table.d.ts +16 -0
  111. package/components/table.js +393 -260
  112. package/components/tabs.js +149 -137
  113. package/components/toast.js +66 -66
  114. package/components/tooltip.js +2 -2
  115. package/components/tree.js +62 -51
  116. package/components/typography.d.ts +2 -1
  117. package/components/typography.js +33 -32
  118. package/components/ui/button.d.ts +2 -2
  119. package/components/ui/button.js +19 -19
  120. package/components/ui/collapsible.d.ts +1 -5
  121. package/components/ui/dialog.d.ts +3 -3
  122. package/components/ui/dialog.js +95 -58
  123. package/components/ui/tooltip.d.ts +2 -2
  124. package/components/ui/tooltip.js +67 -33
  125. package/components/viz-charts.js +95 -95
  126. package/demo/components/add-to-artifact.js +363 -0
  127. package/demo/lib/artifact-library.js +142 -0
  128. package/demo/lib/artifact-pin-guard.js +12 -0
  129. package/fonts/aribau-grotesk-medium.woff2 +0 -0
  130. package/fonts/aribau-grotesk-regular.woff2 +0 -0
  131. package/fonts.css +11 -11
  132. package/hooks/agents-ui/use-agent-audio-visualizer-aura.js +17 -16
  133. package/hooks/agents-ui/use-agent-audio-visualizer-wave.js +21 -20
  134. package/lib/icons.d.ts +24 -0
  135. package/lib/icons.js +114 -108
  136. package/lib/motion.d.ts +42 -39
  137. package/lib/motion.js +112 -52
  138. package/lib/spinner-mark.d.ts +9 -0
  139. package/lib/spinner-mark.js +98 -0
  140. package/llms.txt +53 -19
  141. package/manifest.json +258 -36
  142. package/package.json +1 -1
  143. package/styles.css +143 -124
  144. package/theme.css +90 -93
  145. package/components/ui/collapsible.js +0 -35
  146. package/fonts/aribau-grotesk-500.otf +0 -0
  147. package/fonts/aribau-grotesk-600.woff2 +0 -0
package/styles.css CHANGED
@@ -5,29 +5,35 @@
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
@@ -36,8 +42,9 @@
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,25 +76,27 @@
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 */
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 */
91
100
 
92
101
  /* ---- Semantic accent ramps ---- */
93
102
  /* Success stays a semantic state color, never a product-primary hue. */
@@ -128,15 +137,24 @@
128
137
  --color-amber-base: #f3a72e;
129
138
  --color-amber-deep: #b57414;
130
139
 
131
- /* ---- Radii ---- TWO values only: 2px and 4px. Compact roles resolve to
132
- 2px; every surface and formerly pill-shaped role resolves to 4px. */
133
- --radius-xs: 0.125rem; /* 2px */
134
- --radius-sm: 0.125rem; /* 2px */
135
- --radius-md: 0.25rem; /* 4px */
136
- --radius-lg: 0.25rem; /* 4px */
137
- --radius-xl: 0.25rem; /* 4px */
138
- --radius-2xl: 0.25rem; /* 4px */
139
- --radius-full: 0.25rem; /* 4px */
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. */
157
+ --radius-full: 9999px;
140
158
  /* Status/indicator dots are SQUARE with a hair of softening — echoing the
141
159
  growth-mark's square cells. Never render an indicator dot as a circle
142
160
  (`rounded-full`); radio controls are the one exception (control
@@ -145,20 +163,17 @@
145
163
 
146
164
  /* ---- Elevation ---- ONE soft token (Claude-panel style).
147
165
  Delineate surfaces with fill color first; add this to gently lift them.
148
- Tuned quieter (2026-07-30): the ambient drop sits closer (y8→y4,
149
- blur28→16) at lower opacity (9%→6%) with a faint COOL slate tint
150
- (rgb 15 23 42, not near-black) — a hard, offset-heavy black drop read
151
- "cheap" and floated small controls (switch thumb, tab pill). */
152
- --shadow-elevation: 0 0 0 1px rgb(15 23 42 / 0.03),
153
- 0 1px 2px 0 rgb(15 23 42 / 0.04),
154
- 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);
155
171
 
156
172
  /* Pinned-table-column smudges — whisper-soft directional casts shown only
157
173
  while content is hidden behind a sticky column (Table is scroll-aware).
158
- Deep negative spread keeps the edge feathered; same cool slate tint as
159
- the elevation token. */
160
- --shadow-table-smudge-left: 8px 0 24px -14px rgb(15 23 42 / 0.05);
161
- --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);
162
177
 
163
178
  /* ---- CTA inner glow ---- luminous inset highlight for primary buttons
164
179
  (adapted from the "AI button" Figma): a crisp top-edge catch plus a soft
@@ -172,36 +187,7 @@
172
187
  inset 0 8px 16px -8px rgb(255 255 255 / 0.45);
173
188
  /* Text fields — a whisper of inset depth so the writing surface reads
174
189
  recessed into the page (persists through hover/focus/invalid). */
175
- --inner-glow-field: inset 0 1px 2px 0 rgb(10 10 11 / 0.06);
176
-
177
- /* ---- Motion ---- strong custom curves; the built-in CSS easings are too
178
- weak. Declared here so the `ease-out` / `ease-in-out` utilities resolve
179
- to these system-wide. JS mirror: src/lib/motion.ts — keep in sync. */
180
- --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* entrances, exits, presses */
181
- --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* on-screen movement / morphs */
182
- --ease-expo-out: cubic-bezier(0.16, 1, 0.3, 1); /* side-panel and drawer slide */
183
- --ease-drawer: var(--ease-expo-out); /* backwards-compatible alias */
184
- --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* playful overshoot (rare) */
185
- --ease-disclosure: cubic-bezier(0.32, 0.72, 0, 1); /* height reveals — moves off the mark immediately, settles long */
186
-
187
- /* Durations — every animation/transition timing flows from these.
188
- UI animations stay under 300ms; exits run faster than enters. */
189
- --duration-fast: 0.15s; /* menu / popover / tooltip enter */
190
- --duration-normal: 0.2s; /* state transitions */
191
- --duration-disclosure: 0.28s; /* collapsible open — travels a real distance */
192
- --duration-spin: 0.8s; /* rotation loops (spinner) */
193
- --duration-pulse: 1.5s; /* breathing / shimmer loops */
194
- --duration-bloom: 0.9s; /* ambient reveals (chat texture bloom, curtain wipe) */
195
- --duration-brand-loader: 3.4s; /* BrandLoader flicker loop */
196
-
197
- /* Entrance-choreography beats — staggered delays for sequenced arrivals
198
- (e.g. chat welcome: mark → greeting → composer). */
199
- --stagger-1: 0.2s;
200
- --stagger-2: 0.3s;
201
- --stagger-3: 0.42s;
202
-
203
- /* Press feedback — every pressable element scales down on :active */
204
- --scale-press: 0.97;
190
+ --inner-glow-field: inset 0 1px 2px 0 rgb(32 32 32 / 0.06);
205
191
 
206
192
  /* ---- Layout ---- app-frame dimensions (Sidebar / Panel) */
207
193
  --sidebar-width: 15rem; /* 240px — primary nav rail */
@@ -292,13 +278,18 @@
292
278
  --color-fill-foreground: var(--fill-foreground);
293
279
  --color-table-shell: var(--table-shell);
294
280
 
281
+ --color-artifact-canvas: var(--artifact-canvas);
282
+
295
283
  --color-accent: var(--accent);
296
284
  --color-accent-foreground: var(--accent-foreground);
297
285
 
298
- --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);
299
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). */
300
291
  --color-warning: var(--color-warning-500);
301
- --color-warning-foreground: #ffffff;
292
+ --color-warning-foreground: var(--color-ink-950);
302
293
  --color-danger: var(--color-danger-600);
303
294
  --color-danger-foreground: #ffffff;
304
295
  --color-info: var(--color-info-600);
@@ -346,11 +337,14 @@
346
337
  --background: var(--color-ink-100); /* step 2 · canvas */
347
338
  --foreground: var(--color-ink-950); /* step 12 */
348
339
 
349
- /* Text levels: primary ink-950, secondary ink-900, tertiary ink-800.
350
- Primary + secondary clear AA for body copy; tertiary is AA-large only. */
351
- --text-primary: var(--color-ink-950); /* ~16:1 AAA */
352
- --text-secondary: var(--color-ink-900); /* ~5.3:1 AA */
353
- --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) */
354
348
 
355
349
  --surface: var(--color-ink-200); /* step 3 · tinted canvas */
356
350
  --surface-foreground: var(--color-ink-950);
@@ -375,17 +369,20 @@
375
369
  --table-row-hover: color-mix(in srgb, var(--card) 40%, var(--muted));
376
370
  --table-row-selected: color-mix(in srgb, var(--card) 10%, var(--muted));
377
371
 
378
- /* Quiet fill */
379
- --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 */
380
375
  --fill-foreground: var(--color-ink-950);
381
376
 
382
- --accent: var(--color-ink-200); /* step 3 */
377
+ --accent: var(--color-ink-400); /* step 5 · active / selected wash */
383
378
  --accent-foreground: var(--color-ink-950);
384
379
 
385
- /* Borders — a three-level scale, primary (strongest) → tertiary (faintest). */
386
- --border-primary: var(--color-ink-600); /* #cececd · strongest */
387
- --border-secondary: var(--color-ink-400); /* #e1e1e0 · default */
388
- --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 */
389
386
  /* Legacy aliases point into the scale so existing utilities keep resolving. */
390
387
  --border: var(--border-secondary); /* default hairline / separator */
391
388
  --border-strong: var(--border-primary); /* emphasized / hover / selected */
@@ -394,9 +391,8 @@
394
391
  /* Ripple — the appearance wash that radiates from a floating surface's
395
392
  origin corner as it opens (Dropdown/Popover/Select/Modal…). A soft ink
396
393
  tint that expands + fades once on mount; see the `.ads-ripple` layer and
397
- the `Ripple` component. Duration stays in the sub-300ms UI band. */
394
+ the `Ripple` component. */
398
395
  --ripple-tint: color-mix(in srgb, var(--brand) 20%, transparent);
399
- --ripple-duration: 300ms;
400
396
 
401
397
  /* Stroke width — ADS hairlines are 0.5px, not the Tailwind 1px default.
402
398
  The single-width border utilities are overridden to this token at the
@@ -410,16 +406,17 @@
410
406
  the ink scale. Components pass these into non-CSS renderers (Recharts,
411
407
  React Flow, the Paper/WebGL texture) so no component carries a raw ink-*
412
408
  value. Same DS pattern as the data-viz --color-chart-* palette. */
413
- --chart-axis: var(--color-ink-200); /* axis lines + de-emphasised marks */
414
- --chart-grid: var(--color-ink-50); /* gridlines */
415
- --chart-track: var(--color-ink-100); /* funnel / progress track */
416
- --chart-context: var(--color-ink-300); /* de-emphasised context series */
417
- --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 */
418
414
  --texture-ink: var(--color-ink-950); /* brand-texture / pixel-blast marks */
419
415
  --table-shell: var(--color-ink-200); /* recessed table tray (lighter than muted) */
420
- --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 */
421
417
  --surface-inverse: var(--color-ink-950); /* dark hero / inverse surface base */
422
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);
423
420
 
424
421
  /* shadcn-compat raw surfaces — so a downstream shadcn Sidebar / Popover
425
422
  (or an inline `var(--sidebar)` / `var(--popover)`) resolves to the ADS
@@ -473,7 +470,7 @@
473
470
  pointer-events: none;
474
471
  transform-origin: var(--ripple-origin, center);
475
472
  background: radial-gradient(125% 125% at var(--ripple-origin, center), var(--ripple-tint), transparent 62%);
476
- animation: ads-ripple-wave var(--ripple-duration, 300ms) var(--ease-out) forwards;
473
+ animation: ads-ripple-wave 300ms ease-out forwards;
477
474
  will-change: transform, opacity;
478
475
  }
479
476
  @media (prefers-reduced-motion: reduce) {
@@ -519,6 +516,16 @@
519
516
  box-shadow: var(--shadow-elevation);
520
517
  }
521
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
+
522
529
  .artifact-grid-stack > .grid-stack-placeholder > .placeholder-content {
523
530
  border: 1px dashed var(--color-border-strong);
524
531
  border-radius: var(--radius-sm);
@@ -540,7 +547,7 @@
540
547
  }
541
548
  }
542
549
  .ads-texture-reveal {
543
- animation: ads-texture-reveal var(--duration-bloom) var(--ease-out) both;
550
+ animation: ads-texture-reveal 900ms ease-out both;
544
551
  }
545
552
 
546
553
  /* Paper's WebGL shader owns the halftone animation. The canvas is bounded to
@@ -608,10 +615,10 @@
608
615
  mask-position: 0% 0%;
609
616
  -webkit-mask-position: 0% 0%;
610
617
  transition:
611
- mask-position 1s var(--ease-out),
612
- -webkit-mask-position 1s var(--ease-out),
613
- translate 1s var(--ease-out),
614
- 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;
615
622
  }
616
623
  .ads-texture-lifted {
617
624
  mask-position: 0% 100%;
@@ -620,7 +627,7 @@
620
627
  }
621
628
  @media (prefers-reduced-motion: reduce) {
622
629
  .ads-texture-lift {
623
- transition: opacity var(--duration-normal) var(--ease-out);
630
+ transition: opacity 200ms ease-out;
624
631
  }
625
632
  .ads-texture-lifted {
626
633
  mask-position: 0% 0%;
@@ -659,7 +666,7 @@
659
666
  }
660
667
  }
661
668
  .brand-loader-cell {
662
- animation: brand-flicker var(--duration-brand-loader) steps(1) infinite backwards;
669
+ animation: brand-flicker 3.4s steps(1) infinite backwards;
663
670
  }
664
671
  @media (prefers-reduced-motion: reduce) {
665
672
  .brand-loader-cell {
@@ -684,7 +691,10 @@
684
691
  color: var(--foreground);
685
692
  font-family: var(--font-sans);
686
693
  font-size: var(--text-base); /* 15px base */
687
- 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;
688
698
  font-synthesis-weight: none;
689
699
  }
690
700
 
@@ -769,7 +779,7 @@
769
779
  to { opacity: 1; }
770
780
  }
771
781
  .ads-reveal {
772
- 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;
773
783
  animation-delay: calc(var(--reveal-step, 70ms) * var(--reveal-order, 0));
774
784
  }
775
785
  .ads-reveal-ink { animation-name: ads-reveal-ink; }
@@ -814,9 +824,9 @@
814
824
  border-color: var(--glow-border-rest);
815
825
  box-shadow: var(--glow-inset);
816
826
  transition:
817
- color var(--duration-normal) var(--ease-out),
818
- border-color var(--duration-normal) var(--ease-out),
819
- 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;
820
830
  }
821
831
 
822
832
  /* Hover: the same solid brand-black stroke as focus — one consistent
@@ -892,7 +902,7 @@
892
902
  }
893
903
 
894
904
  .ads-row-flash > td {
895
- animation: ads-row-flash 1.6s var(--ease-out) forwards;
905
+ animation: ads-row-flash 1.6s ease-out forwards;
896
906
  }
897
907
 
898
908
  @media (prefers-reduced-motion: reduce) {
@@ -911,11 +921,9 @@
911
921
  it does not merge), so animating height alongside tw-animate-css's enter/exit
912
922
  silently drops the fade and leaves a bare height shutter — which reads as
913
923
  rigid no matter how it is timed. Radix publishes the measured height as
914
- --radix-collapsible-content-height; exits run faster than enters.
915
- Eased with --ease-disclosure. --ease-out front-loads ~60% of the travel into
916
- the first third (pop, then settle); --ease-in-out holds ~150ms before moving
917
- (lag, then rush). A height reveal needs to leave the mark immediately and
918
- 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. */
919
927
  @keyframes ads-collapsible-down {
920
928
  from {
921
929
  height: 0;
@@ -941,10 +949,10 @@
941
949
  }
942
950
  }
943
951
  .ads-collapsible[data-state="open"] {
944
- animation: ads-collapsible-down var(--duration-disclosure) var(--ease-disclosure);
952
+ animation: ads-collapsible-down 280ms ease-in-out;
945
953
  }
946
954
  .ads-collapsible[data-state="closed"] {
947
- animation: ads-collapsible-up var(--duration-normal) var(--ease-disclosure);
955
+ animation: ads-collapsible-up 200ms ease-in-out;
948
956
  }
949
957
  @media (prefers-reduced-motion: reduce) {
950
958
  .ads-collapsible[data-state="open"],
@@ -1006,5 +1014,16 @@
1006
1014
  border-left: 1px solid var(--border-strong);
1007
1015
  border-bottom-left-radius: var(--radius-lg);
1008
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;
1027
+ }
1009
1028
  /* Let the consumer's Tailwind discover the classes ADS components use. */
1010
1029
  @source "./**/*.{js,mjs}";