@tangle-network/agent-app 0.45.23 → 0.45.24

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 (58) hide show
  1. package/dist/{DesignCanvas-ZG7DJS7C.js → DesignCanvas-3RRPVPCP.js} +2 -2
  2. package/dist/{DesignCanvasEditor-SLFMHOII.js → DesignCanvasEditor-KAMMEX7E.js} +4 -4
  3. package/dist/{TimelineEditor-6PV42FLG.js → TimelineEditor-IIBVCAZV.js} +2 -2
  4. package/dist/VaultPane-MUWGYVJ7.js +7 -0
  5. package/dist/assistant/index.d.ts +11 -0
  6. package/dist/assistant/index.js +89 -56
  7. package/dist/assistant/index.js.map +1 -1
  8. package/dist/chat-react/index.js +4 -1
  9. package/dist/chat-react/index.js.map +1 -1
  10. package/dist/{chunk-MLACJ6DB.js → chunk-7O4FZAFP.js} +10 -10
  11. package/dist/chunk-7O4FZAFP.js.map +1 -0
  12. package/dist/{chunk-OASVAPRL.js → chunk-AWPK7ZDS.js} +3 -3
  13. package/dist/{chunk-YTMKRL3L.js → chunk-HZ4WCA37.js} +3 -2
  14. package/dist/chunk-HZ4WCA37.js.map +1 -0
  15. package/dist/{chunk-FVJP2RTC.js → chunk-JJJEO4ND.js} +91 -36
  16. package/dist/chunk-JJJEO4ND.js.map +1 -0
  17. package/dist/{chunk-7PFFFRVU.js → chunk-KOMP6NDW.js} +172 -43
  18. package/dist/chunk-KOMP6NDW.js.map +1 -0
  19. package/dist/{chunk-TZO3SOUL.js → chunk-LSQR6HM6.js} +49 -33
  20. package/dist/chunk-LSQR6HM6.js.map +1 -0
  21. package/dist/{chunk-3IHYJIDJ.js → chunk-NC2V63EL.js} +15 -15
  22. package/dist/chunk-NC2V63EL.js.map +1 -0
  23. package/dist/{chunk-73CQJOIU.js → chunk-OYGM5WLD.js} +5 -5
  24. package/dist/chunk-OYGM5WLD.js.map +1 -0
  25. package/dist/chunk-YIQHOAHN.js +340 -0
  26. package/dist/chunk-YIQHOAHN.js.map +1 -0
  27. package/dist/design-canvas-react/index.d.ts +2 -2
  28. package/dist/design-canvas-react/index.js +9 -9
  29. package/dist/design-canvas-react/index.js.map +1 -1
  30. package/dist/design-canvas-react/lazy.js +1 -1
  31. package/dist/sequences-react/index.js +2 -2
  32. package/dist/theme/index.d.ts +27 -1
  33. package/dist/theme/index.js +1 -1
  34. package/dist/theme/tailwind-preset.d.ts +25 -0
  35. package/dist/theme/tailwind-preset.js +55 -1
  36. package/dist/theme/tailwind-preset.js.map +1 -1
  37. package/dist/theme/tokens.css +298 -40
  38. package/dist/vault/index.js +1 -1
  39. package/dist/vault/lazy.js +1 -1
  40. package/dist/web-react/async/index.js +19 -307
  41. package/dist/web-react/async/index.js.map +1 -1
  42. package/dist/web-react/index.d.ts +73 -6
  43. package/dist/web-react/index.js +2 -2
  44. package/dist/work-product-react/index.js +1 -1
  45. package/package.json +1 -1
  46. package/dist/VaultPane-HFH734K6.js +0 -7
  47. package/dist/chunk-3IHYJIDJ.js.map +0 -1
  48. package/dist/chunk-73CQJOIU.js.map +0 -1
  49. package/dist/chunk-7PFFFRVU.js.map +0 -1
  50. package/dist/chunk-FVJP2RTC.js.map +0 -1
  51. package/dist/chunk-MLACJ6DB.js.map +0 -1
  52. package/dist/chunk-TZO3SOUL.js.map +0 -1
  53. package/dist/chunk-YTMKRL3L.js.map +0 -1
  54. /package/dist/{DesignCanvas-ZG7DJS7C.js.map → DesignCanvas-3RRPVPCP.js.map} +0 -0
  55. /package/dist/{DesignCanvasEditor-SLFMHOII.js.map → DesignCanvasEditor-KAMMEX7E.js.map} +0 -0
  56. /package/dist/{TimelineEditor-6PV42FLG.js.map → TimelineEditor-IIBVCAZV.js.map} +0 -0
  57. /package/dist/{VaultPane-HFH734K6.js.map → VaultPane-MUWGYVJ7.js.map} +0 -0
  58. /package/dist/{chunk-OASVAPRL.js.map → chunk-AWPK7ZDS.js.map} +0 -0
@@ -15,32 +15,85 @@
15
15
  *
16
16
  * The aliases reference the triples, so redefining only the triples in the dark
17
17
  * scope re-themes both vocabularies through the cascade.
18
+ *
19
+ * Neutrals are authored on ONE oklch ramp (`--neutral-*`, below) and the shadcn
20
+ * triples point at it. Structural reference: Cabinet (MIT) — see
21
+ * docs/design-tokens.md for the decisions and what we did differently.
18
22
  */
19
23
 
20
24
  :root {
25
+ /* ── The neutral ramp ────────────────────────────────────────────────────
26
+ ONE ladder, both themes: light reads it from the top down, dark from the
27
+ bottom up. Stop names ARE their oklch lightness (`--neutral-91` is
28
+ L 0.91), so the ladder rule is checkable rather than conventional:
29
+
30
+ L = 0.16 + 0.03n n = 0 … 28 (0.16 is the darkest surface,
31
+ 1.00 the terminal white)
32
+
33
+ Chroma is a CONSTANT 0.004 at hue 286 — one deliberate cool cast, not a
34
+ wandering one. The HSL these tokens replaced carried "S 5–7%" throughout
35
+ and that reads as consistent, but HSL saturation is not chroma: the same
36
+ nominal 5–7% produced 0.0014 chroma at L 0.976 and 0.0154 at L 0.478, so
37
+ the old ramp visibly GAINED blue as it darkened. Look at the `-hsl` mirrors
38
+ below to see the same fact from the other side — holding chroma constant
39
+ needs S 17.2% at L 0.97 and S 1.3% at L 0.49.
40
+
41
+ The terminal stop is chroma 0 because sRGB admits no chroma at L 1.
42
+
43
+ Each stop ships TWICE, and the pair is the whole compatibility story:
44
+ --neutral-NN the oklch value — the SOURCE, what new work reads
45
+ --neutral-NN-hsl the same colour as an "H S% L%" channel triple
46
+ A pinned consumer's `hsl(var(--border))` must keep resolving, and CSS
47
+ cannot convert oklch to a bare channel triple, so the triple is a mirror
48
+ rather than a derivation. tests/theme/tokens-contract.test.ts converts
49
+ every oklch stop to HSL and fails if its mirror has drifted, so the two
50
+ forms cannot disagree without a red test. */
51
+ --neutral-16: oklch(0.16 0.004 286);
52
+ --neutral-16-hsl: 240.1 6.8% 5.5%;
53
+ --neutral-19: oklch(0.19 0.004 286);
54
+ --neutral-19-hsl: 240 4.9% 8%;
55
+ --neutral-22: oklch(0.22 0.004 286);
56
+ --neutral-22-hsl: 239.9 3.8% 10.7%;
57
+ --neutral-25: oklch(0.25 0.004 286);
58
+ --neutral-25-hsl: 239.9 3.1% 13.5%;
59
+ --neutral-49: oklch(0.49 0.004 286);
60
+ --neutral-49-hsl: 239.7 1.3% 38.2%;
61
+ --neutral-70: oklch(0.7 0.004 286);
62
+ --neutral-70-hsl: 239.6 1.5% 62.5%;
63
+ --neutral-91: oklch(0.91 0.004 286);
64
+ --neutral-91-hsl: 239.6 5.2% 88.7%;
65
+ --neutral-94: oklch(0.94 0.004 286);
66
+ --neutral-94-hsl: 239.6 8% 92.6%;
67
+ --neutral-97: oklch(0.97 0.004 286);
68
+ --neutral-97-hsl: 239.6 17.2% 96.5%;
69
+ --neutral-100: oklch(1 0 0);
70
+ --neutral-100-hsl: 0 0% 100%;
71
+
21
72
  /* shadcn channel triples — "H S% L%", consumed as hsl(var(--name)).
22
- Values mirror @tangle-network/brand (Tangle Quiet) so agent-app surfaces
23
- match sandbox-ui in the same app. agent-app keeps its own light-default /
73
+ Neutrals point at a ramp stop; the brand hues (primary/destructive/status)
74
+ keep their measured HSL, because moving them would move agent-app off
75
+ @tangle-network/brand (Tangle Quiet) and off the status colours that were
76
+ tuned for AA as TEXT. agent-app keeps its own light-default /
24
77
  [data-theme="dark"] scope model (brand is dark-default), so /theme stays
25
78
  dependency-free — only the values are shared, not the cascade. */
26
- --background: 0 0% 100%;
27
- --foreground: 0 0% 5%;
28
- --card: 240 7% 97%;
29
- --card-foreground: 0 0% 5%;
30
- --popover: 0 0% 100%;
31
- --popover-foreground: 0 0% 5%;
79
+ --background: var(--neutral-100-hsl);
80
+ --foreground: var(--neutral-16-hsl);
81
+ --card: var(--neutral-97-hsl);
82
+ --card-foreground: var(--neutral-16-hsl);
83
+ --popover: var(--neutral-100-hsl);
84
+ --popover-foreground: var(--neutral-16-hsl);
32
85
  --primary: 245 62% 57%;
33
- --primary-foreground: 0 0% 100%;
34
- --secondary: 240 6% 93%;
35
- --secondary-foreground: 0 0% 10%;
36
- --muted: 240 6% 93%;
37
- --muted-foreground: 240 5% 38%;
38
- --accent: 240 6% 93%;
39
- --accent-foreground: 0 0% 10%;
86
+ --primary-foreground: var(--neutral-100-hsl);
87
+ --secondary: var(--neutral-94-hsl);
88
+ --secondary-foreground: var(--neutral-22-hsl);
89
+ --muted: var(--neutral-94-hsl);
90
+ --muted-foreground: var(--neutral-49-hsl);
91
+ --accent: var(--neutral-94-hsl);
92
+ --accent-foreground: var(--neutral-22-hsl);
40
93
  --destructive: 0 72% 41%;
41
- --destructive-foreground: 0 0% 100%;
42
- --border: 240 6% 89%;
43
- --input: 240 6% 89%;
94
+ --destructive-foreground: var(--neutral-100-hsl);
95
+ --border: var(--neutral-91-hsl);
96
+ --input: var(--neutral-91-hsl);
44
97
  --ring: 245 62% 57%;
45
98
  /* status colors — brand hues (teal/gold/red), but lightness kept dark enough
46
99
  to clear WCAG AA when used AS TEXT on tinted chips. Brand's own status
@@ -49,6 +102,17 @@
49
102
  --success-foreground: 0 0% 100%;
50
103
  --warning: 41 96% 38%;
51
104
  --warning-foreground: 38 92% 12%;
105
+ /* Warning as TEXT on a warning-TINTED surface (the approval card's
106
+ `bg-warning/[0.06]`), which is a different surface from the solid gold chip
107
+ `--warning-foreground` is paired with — and the reason that pairing cannot
108
+ serve both. Measured on the shipped approval card: no single lightness
109
+ clears AA in both themes, because the tint tracks the page. On the light
110
+ card rgb(251,248,240) the ramp needs L <= 30% (L 38% is 3.07:1); on the dark
111
+ card rgb(27,22,16) it needs L >= 34% (L 28% is 3.27:1). So this token
112
+ re-themes where `--warning` and `--warning-foreground` deliberately do not.
113
+ 28% / 56% are the values with margin either side of those knees: 5.17:1
114
+ light, 10.11:1 dark. */
115
+ --warning-strong: 41 96% 28%;
52
116
 
53
117
  /* canvas/sequences aliases — full colors, resolve to the triples above */
54
118
  --bg-input: hsl(var(--card));
@@ -73,42 +137,236 @@
73
137
  --accent-surface-soft: hsl(var(--accent));
74
138
  --accent-text: hsl(var(--accent-foreground));
75
139
  --status-error: hsl(var(--destructive));
76
- --radius-md: 0.5rem;
77
140
 
78
141
  /* canvas-only surfaces (not part of the shadcn vocabulary). Name matches the
79
- `--canvas-backdrop` the design-canvas Workspace references (with a #1a1a1a fallback). */
80
- --canvas-backdrop: hsl(240 7% 90%);
142
+ `--canvas-backdrop` the design-canvas Workspace references (with a #1a1a1a
143
+ fallback). One ramp stop below the sheet, so the page reads as lifted. */
144
+ --canvas-backdrop: hsl(var(--neutral-91-hsl));
145
+
146
+ /* Keyboard focus ring. Resolves through `--ring`, so the dark scope re-themes
147
+ it by the same cascade every other token here uses. */
148
+ --focus-ring-width: 2px;
149
+ --focus-ring-offset: 2px;
150
+ --focus-ring-color: hsl(var(--ring));
151
+
152
+ /* ── Radius ──────────────────────────────────────────────────────────────
153
+ One root, every step a multiplier of it, so a product re-proportions its
154
+ whole chrome by changing ONE number. `--radius-md` keeps its shipped
155
+ 0.5rem exactly (0.625 x 0.8), which is what pins the root at 0.625rem:
156
+ gtm-agent consumes `--radius-md` for its composer send button, and the
157
+ sandbox-ui MD3 components bridged above read it too.
158
+
159
+ The root is `--radius-base`, NOT `--radius`, and that is deliberate. Half
160
+ the fleet already owns `--radius` (tax-agent sets 0.5rem, legal-agent
161
+ 0.625rem) inside `@layer base`, while this file is linked UNLAYERED — an
162
+ unlayered declaration beats any layered one, so shipping `--radius` here
163
+ would silently seize a token products already drive their own scales from.
164
+ A product that wants its root to drive this ladder opts in with one line:
165
+ `--radius-base: var(--radius)`. */
166
+ --radius-base: 0.625rem;
167
+ --radius-sm: calc(var(--radius-base) * 0.6); /* 0.375rem — 6px */
168
+ --radius-md: calc(var(--radius-base) * 0.8); /* 0.5rem — 8px */
169
+ --radius-lg: var(--radius-base); /* 0.625rem — 10px */
170
+ --radius-xl: calc(var(--radius-base) * 1.4); /* 0.875rem — 14px */
171
+ --radius-2xl: calc(var(--radius-base) * 1.8); /* 1.125rem — 18px */
172
+ --radius-3xl: calc(var(--radius-base) * 2.2); /* 1.375rem — 22px */
173
+
174
+ /* ── Motion ──────────────────────────────────────────────────────────────
175
+ Four durations and three curves, paired into the three composites a
176
+ component actually reaches for. Before these, 64 transitions in this
177
+ package ran on Tailwind's implicit 150 ms / default curve with no named
178
+ intent — nothing was WRONG, but nothing was decidable either.
179
+
180
+ The durations are a x1.5-ish ladder rather than round numbers, because
181
+ what a user perceives is the ratio: 90 reads as instant, 150 as a
182
+ response, 240 as a movement you can follow, 360 as a surface travelling.
183
+
184
+ instant a control acknowledging a pointer (hover/active colour)
185
+ fast a state change on a control already on screen
186
+ base a surface arriving or leaving (popover, panel, disclosure)
187
+ slow a full-height surface travelling (drawer, sheet, sidebar)
188
+
189
+ `fast` is 150 ms on purpose: it is what those 64 transitions already run
190
+ at, so adopting the token is a rename, never a retune.
191
+
192
+ Curves: entrances decelerate hard and land softly; state changes
193
+ decelerate normally; exits ACCELERATE away, because a user who dismissed
194
+ something is done with it and should not wait for it to glide out. */
195
+ --duration-instant: 90ms;
196
+ --duration-fast: 150ms;
197
+ --duration-base: 240ms;
198
+ --duration-slow: 360ms;
199
+ --ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
200
+ --ease-entrance: cubic-bezier(0.22, 1, 0.36, 1);
201
+ --ease-exit: cubic-bezier(0.4, 0, 1, 1);
202
+ /* Drop-in duration+easing pairs: `transition: background-color var(--motion-control)`. */
203
+ --motion-control: var(--duration-fast) var(--ease-standard);
204
+ --motion-surface: var(--duration-base) var(--ease-entrance);
205
+ --motion-dismiss: var(--duration-instant) var(--ease-exit);
206
+
207
+ /* ── Border tiers ────────────────────────────────────────────────────────
208
+ Three strengths of the SAME border colour, because a divider inside a
209
+ panel and the edge of a card floated on the page are not the same line,
210
+ and shipping one strength for both is what makes a UI read boxy.
211
+
212
+ --border-soft dividers and de-emphasised edges — the tier the
213
+ `border-border` utility maps to, so all 151 of this
214
+ package's usages move together
215
+ --card-edge a container that must read as a container
216
+ hsl(--border) full strength: form-field edges (`--input`), and any
217
+ edge a component deliberately emphasises
218
+
219
+ LIGHT is 40% / 60%, chosen against OUR surfaces rather than copied. A 1px
220
+ hairline, contrast of the composited line against the surface it sits on,
221
+ rendered and read back by playground/scripts/token-render.mjs:
222
+
223
+ alpha on background on card on muted
224
+ 22% 1.060 1.044 1.026 the reference's soft value
225
+ 40% 1.108 1.072 1.036 quiet, still resolves
226
+ 60% 1.176 1.120 1.063 reads as a container
227
+ 100% 1.311 1.205 1.102 reads as a box
228
+
229
+ 40% is the quietest alpha at which a 1px line still resolves on `--card`,
230
+ which is where most of this package's dividers actually sit — at 22% it is
231
+ simply not there.
232
+ The card edge is 60% rather than the reference's 55% because ours has to
233
+ clear the soft tier by enough to read as a DIFFERENT decision (1.176 vs
234
+ 1.108), while our card already carries a fill step of its own (L 0.97 on a
235
+ 1.00 background) that the reference's card — the same colour as its
236
+ background — does not have.
237
+
238
+ DARK INVERTS: both tiers are FULL strength. Same measurement, our dark
239
+ ramp, and it forces the opposite answer. Dark `--border` (L 0.25) is
240
+ already at the edge of visible at 100% — 1.212 on background, 1.158 on
241
+ card, 1.085 on muted — and the same 40% takes those to 1.057 / 1.048 /
242
+ 1.023. That is not a quieter line, it is no line. A tier system that
243
+ erases the thing it is tiering is worse than no tiers, so dark collapses
244
+ the three to one. */
245
+ --border-soft: color-mix(in oklch, hsl(var(--border)) 40%, transparent);
246
+ --card-edge: color-mix(in oklch, hsl(var(--border)) 60%, transparent);
247
+ }
248
+
249
+ /**
250
+ * The keyboard-focus floor.
251
+ *
252
+ * Every interactive element is keyboard-visible by DEFAULT, so a component has
253
+ * to opt out on purpose rather than by omission. Before this rule an element
254
+ * that declared no focus style fell back to the browser's own ring — measured
255
+ * `rgb(16, 16, 16)` in BOTH themes, because nothing here sets `color-scheme`,
256
+ * which is 1.03:1 against the dark canvas backdrop `rgb(19, 19, 21)`. Visible in
257
+ * light, effectively absent in dark, on 30 of the 176 focusable elements the
258
+ * playground audit reaches.
259
+ *
260
+ * Specificity is deliberately left at one pseudo-class, and that is the whole
261
+ * contract:
262
+ *
263
+ * - It applies wherever nothing else declares a focus style — the gap above.
264
+ * - It LOSES to `.focus\:outline-none:focus` and `.focus-visible\:ring-*`
265
+ * (two compound selectors), so a component with a deliberate custom ring is
266
+ * untouched and no consumer gets a doubled ring from upgrading.
267
+ * - It TIES with a bare `.outline-none` utility, which means source order
268
+ * decides and the floor cannot be relied on to win. That is not a hole left
269
+ * open: a bare `outline-none` with no replacement is a defect this package
270
+ * fixes at the component and `tests/theme/focus-floor.test.ts` keeps fixed.
271
+ * CSS cannot distinguish a deliberate opt-out from a forgotten one, so the
272
+ * guard that can is a test, not a stronger selector.
273
+ *
274
+ * An outline, not a `ring-*` box-shadow, because an outline is not painted by
275
+ * the element's own background/shadow stack — it cannot be covered by a sibling
276
+ * and it needs no `ring-offset-color` matched to whatever surface it sits on.
277
+ */
278
+ :focus-visible {
279
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
280
+ outline-offset: var(--focus-ring-offset);
81
281
  }
82
282
 
83
283
  [data-theme='dark'],
84
284
  .dark {
85
- --background: 240 8% 5%;
86
- --foreground: 240 6% 93%;
87
- --card: 240 5% 8%;
88
- --card-foreground: 240 6% 93%;
89
- --popover: 240 4% 13%;
90
- --popover-foreground: 240 6% 93%;
285
+ /* The ramp is NOT redefined here — both themes read the same `--neutral-*`
286
+ ladder and only differ in which stop each role picks.
287
+ `--warning-foreground` (dark text on a solid gold chip) is theme-invariant
288
+ and is therefore absent, not omitted: the cascade already carries it. */
289
+ --background: var(--neutral-16-hsl);
290
+ --foreground: var(--neutral-94-hsl);
291
+ --card: var(--neutral-19-hsl);
292
+ --card-foreground: var(--neutral-94-hsl);
293
+ --popover: var(--neutral-25-hsl);
294
+ --popover-foreground: var(--neutral-94-hsl);
91
295
  /* 74% L (brand's #818CF8 intent) so primary clears AA as TEXT on a primary/10
92
- tint in dark; the solid primary button pairs it with a light foreground. */
296
+ tint in dark. That lightness is also why the foreground has to INVERT here:
297
+ the light theme's white-on-indigo is 6.01:1, but the same white on this
298
+ 74%-L lavender rgb(137,137,245) is 3.02:1 — measured failing on the
299
+ "Approve & run" button. A dark foreground on the same fill is 6.44:1, so
300
+ the solid button reads in both themes and the tint keeps its AA as text. */
93
301
  --primary: 239 84% 74%;
94
- --primary-foreground: 0 0% 100%;
95
- --secondary: 240 5% 11%;
96
- --secondary-foreground: 240 6% 93%;
97
- --muted: 240 5% 11%;
98
- --muted-foreground: 240 4% 62%;
99
- --accent: 240 5% 11%;
100
- --accent-foreground: 240 6% 93%;
302
+ --primary-foreground: var(--neutral-16-hsl);
303
+ --secondary: var(--neutral-22-hsl);
304
+ --secondary-foreground: var(--neutral-94-hsl);
305
+ --muted: var(--neutral-22-hsl);
306
+ --muted-foreground: var(--neutral-70-hsl);
307
+ --accent: var(--neutral-22-hsl);
308
+ --accent-foreground: var(--neutral-94-hsl);
101
309
  --destructive: 348 90% 68%;
102
- --destructive-foreground: 0 0% 12%;
103
- --border: 240 3% 13%;
104
- --input: 240 5% 11%;
310
+ --destructive-foreground: var(--neutral-25-hsl);
311
+ /* @see the :root declaration this is the tier that re-themes. */
312
+ --warning-strong: 40 94% 56%;
313
+ --border: var(--neutral-25-hsl);
314
+ --input: var(--neutral-22-hsl);
105
315
  --ring: 239 84% 74%;
106
316
  --success: 160 70% 52%;
107
317
  --success-foreground: 160 84% 10%;
108
318
  --warning: 40 94% 56%;
109
- --warning-foreground: 38 92% 12%;
110
319
 
111
- --canvas-backdrop: hsl(240 8% 5%);
320
+ --canvas-backdrop: hsl(var(--neutral-16-hsl));
321
+
322
+ /* The tier inversion. Full strength for BOTH tiers — see the measurement in
323
+ the :root block: a softened dark hairline is not quieter, it is absent. */
324
+ --border-soft: hsl(var(--border));
325
+ --card-edge: hsl(var(--border));
326
+ }
327
+
328
+ /**
329
+ * Reduced motion, at the token layer and at the floor.
330
+ *
331
+ * Two rules, because they cover two different populations. Collapsing the
332
+ * duration TOKENS is what makes motion built on this system honour the
333
+ * preference for free — a component that wrote `var(--motion-surface)` needs no
334
+ * media query of its own, and gets no chance to forget one. The universal rule
335
+ * under it is the floor for everything that predates the tokens: 64 transitions
336
+ * in this package run on Tailwind's implicit duration, and a consumer's own
337
+ * components run on theirs. Neither reads a token, so neither would be reached.
338
+ *
339
+ * 1ms rather than 0: a zero-duration transition fires no `transitionend`, and
340
+ * any component that awaits one to unmount or advance a state machine hangs
341
+ * forever. 1ms is imperceptible AND still fires.
342
+ *
343
+ * The floor uses `!important` where the `:focus-visible` floor deliberately did
344
+ * not, and the asymmetry is the point. Focus styling is a design decision a
345
+ * component is entitled to make differently. Reduced motion is not a design
346
+ * decision — it is an explicit request from the person using the product, and a
347
+ * component overriding it is a defect, not a preference. Motion that genuinely
348
+ * carries meaning (a determinate progress indicator, a live-status pulse) opts
349
+ * out by declaring `data-motion="essential"`; the exclusion covers that element
350
+ * and its subtree, and `:where()` keeps the selector at zero specificity so a
351
+ * consumer's own `!important` can still win.
352
+ */
353
+ @media (prefers-reduced-motion: reduce) {
354
+ :root {
355
+ --duration-instant: 1ms;
356
+ --duration-fast: 1ms;
357
+ --duration-base: 1ms;
358
+ --duration-slow: 1ms;
359
+ }
360
+
361
+ *:where(:not([data-motion='essential'], [data-motion='essential'] *)) {
362
+ animation-duration: 1ms !important;
363
+ animation-iteration-count: 1 !important;
364
+ transition-duration: 1ms !important;
365
+ }
366
+
367
+ html {
368
+ scroll-behavior: auto !important;
369
+ }
112
370
  }
113
371
 
114
372
  .agent-app-edit-selection::selection {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ConfirmDialog,
3
3
  VaultPane
4
- } from "../chunk-FVJP2RTC.js";
4
+ } from "../chunk-JJJEO4ND.js";
5
5
  export {
6
6
  ConfirmDialog,
7
7
  VaultPane
@@ -1,7 +1,7 @@
1
1
  // src/vault/lazy.tsx
2
2
  import { lazy } from "react";
3
3
  var VaultPaneLazy = lazy(
4
- () => import("../VaultPane-HFH734K6.js").then((m) => ({ default: m.VaultPane }))
4
+ () => import("../VaultPane-MUWGYVJ7.js").then((m) => ({ default: m.VaultPane }))
5
5
  );
6
6
  export {
7
7
  VaultPaneLazy