@visuno/angular 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +56 -2
  3. package/account-table/account-table.component.d.ts +72 -0
  4. package/action-log/action-log.component.d.ts +41 -0
  5. package/activity-heatmap/activity-heatmap.component.d.ts +67 -0
  6. package/agent-inbox/agent-inbox.component.d.ts +75 -0
  7. package/agent-lanes/agent-lanes.component.d.ts +152 -0
  8. package/agent-phases/agent-phases.component.d.ts +62 -0
  9. package/agent-run-timeline/agent-run-timeline.component.d.ts +113 -0
  10. package/agent-tree/agent-tree.component.d.ts +80 -0
  11. package/answer-action-bar/answer-action-bar.component.d.ts +110 -0
  12. package/artifact-card/artifact-card.component.d.ts +145 -0
  13. package/attachment-tray/attachment-tray.component.d.ts +84 -0
  14. package/badge/badge.component.d.ts +25 -0
  15. package/bar-chart/bar-chart.component.d.ts +87 -0
  16. package/browser-session/browser-session.component.d.ts +70 -0
  17. package/buttons/buttons.component.d.ts +63 -0
  18. package/card/card.component.d.ts +21 -0
  19. package/change-review/change-review.component.d.ts +97 -0
  20. package/citation-hover-card/citation-hover-card.component.d.ts +95 -0
  21. package/code-viewer/code-viewer.component.d.ts +86 -0
  22. package/composer/composer.component.d.ts +114 -0
  23. package/context-meter/context-meter.component.d.ts +60 -0
  24. package/core/icon.component.d.ts +10 -0
  25. package/core/reduced-motion.service.d.ts +15 -0
  26. package/decision-prompt/decision-prompt.component.d.ts +56 -0
  27. package/design-review/design-review.component.d.ts +108 -0
  28. package/design-tuner/design-tuner.component.d.ts +75 -0
  29. package/details-panel/details-panel.component.d.ts +150 -0
  30. package/donut-chart/donut-chart.component.d.ts +63 -0
  31. package/draft-review/draft-review.component.d.ts +128 -0
  32. package/error-recovery/error-recovery.component.d.ts +59 -0
  33. package/esm2022/account-table/account-table.component.mjs +399 -0
  34. package/esm2022/action-log/action-log.component.mjs +177 -0
  35. package/esm2022/activity-heatmap/activity-heatmap.component.mjs +285 -0
  36. package/esm2022/agent-inbox/agent-inbox.component.mjs +284 -0
  37. package/esm2022/agent-lanes/agent-lanes.component.mjs +600 -0
  38. package/esm2022/agent-phases/agent-phases.component.mjs +300 -0
  39. package/esm2022/agent-run-timeline/agent-run-timeline.component.mjs +412 -0
  40. package/esm2022/agent-tree/agent-tree.component.mjs +393 -0
  41. package/esm2022/answer-action-bar/answer-action-bar.component.mjs +636 -0
  42. package/esm2022/artifact-card/artifact-card.component.mjs +916 -0
  43. package/esm2022/attachment-tray/attachment-tray.component.mjs +402 -0
  44. package/esm2022/badge/badge.component.mjs +97 -0
  45. package/esm2022/bar-chart/bar-chart.component.mjs +300 -0
  46. package/esm2022/browser-session/browser-session.component.mjs +352 -0
  47. package/esm2022/buttons/buttons.component.mjs +215 -0
  48. package/esm2022/card/card.component.mjs +107 -0
  49. package/esm2022/change-review/change-review.component.mjs +398 -0
  50. package/esm2022/citation-hover-card/citation-hover-card.component.mjs +360 -0
  51. package/esm2022/code-viewer/code-viewer.component.mjs +291 -0
  52. package/esm2022/composer/composer.component.mjs +743 -0
  53. package/esm2022/context-meter/context-meter.component.mjs +275 -0
  54. package/esm2022/core/icon.component.mjs +111 -0
  55. package/esm2022/core/reduced-motion.service.mjs +34 -0
  56. package/esm2022/decision-prompt/decision-prompt.component.mjs +259 -0
  57. package/esm2022/design-review/design-review.component.mjs +428 -0
  58. package/esm2022/design-tuner/design-tuner.component.mjs +341 -0
  59. package/esm2022/details-panel/details-panel.component.mjs +537 -0
  60. package/esm2022/donut-chart/donut-chart.component.mjs +240 -0
  61. package/esm2022/draft-review/draft-review.component.mjs +549 -0
  62. package/esm2022/error-recovery/error-recovery.component.mjs +231 -0
  63. package/esm2022/eval-results/eval-results.component.mjs +368 -0
  64. package/esm2022/feedback-sheet/feedback-sheet.component.mjs +411 -0
  65. package/esm2022/field-extraction/field-extraction.component.mjs +368 -0
  66. package/esm2022/funnel-chart/funnel-chart.component.mjs +258 -0
  67. package/esm2022/grid/grid.component.mjs +66 -0
  68. package/esm2022/health-score/health-score.component.mjs +420 -0
  69. package/esm2022/human-handoff/human-handoff.component.mjs +676 -0
  70. package/esm2022/image-generation/image-generation.component.mjs +1028 -0
  71. package/esm2022/inline-text-diff/inline-text-diff.component.mjs +390 -0
  72. package/esm2022/launch-checklist/launch-checklist.component.mjs +229 -0
  73. package/esm2022/line-chart/line-chart.component.mjs +417 -0
  74. package/esm2022/live-answer/live-answer.component.mjs +411 -0
  75. package/esm2022/metric-insight/metric-insight.component.mjs +511 -0
  76. package/esm2022/modal/modal.component.mjs +202 -0
  77. package/esm2022/model-picker/model-picker.component.mjs +491 -0
  78. package/esm2022/permission-gate/permission-gate.component.mjs +498 -0
  79. package/esm2022/plan-review/plan-review.component.mjs +432 -0
  80. package/esm2022/progress/progress.component.mjs +503 -0
  81. package/esm2022/prompt-library/prompt-library.component.mjs +453 -0
  82. package/esm2022/prompt-starters/prompt-starters.component.mjs +272 -0
  83. package/esm2022/proposal-card/proposal-card.component.mjs +402 -0
  84. package/esm2022/public-api.mjs +88 -0
  85. package/esm2022/radar-chart/radar-chart.component.mjs +500 -0
  86. package/esm2022/radial-goals/radial-goals.component.mjs +418 -0
  87. package/esm2022/reasoning-trail/reasoning-trail.component.mjs +284 -0
  88. package/esm2022/response-versions/response-versions.component.mjs +288 -0
  89. package/esm2022/rewrite-toolbar/rewrite-toolbar.component.mjs +397 -0
  90. package/esm2022/rich-text-editor/rich-text-editor.component.mjs +1755 -0
  91. package/esm2022/run-cost/run-cost.component.mjs +215 -0
  92. package/esm2022/run-queue/run-queue.component.mjs +481 -0
  93. package/esm2022/run-summary/run-summary.component.mjs +331 -0
  94. package/esm2022/scatter-chart/scatter-chart.component.mjs +705 -0
  95. package/esm2022/score-breakdown/score-breakdown.component.mjs +460 -0
  96. package/esm2022/segmented-control/segmented-control.component.mjs +180 -0
  97. package/esm2022/source-stack/source-stack.component.mjs +245 -0
  98. package/esm2022/stat-cards/stat-cards.component.mjs +258 -0
  99. package/esm2022/status-pill/status-pill.component.mjs +305 -0
  100. package/esm2022/steering/steering.component.mjs +343 -0
  101. package/esm2022/step-loader/step-loader.component.mjs +209 -0
  102. package/esm2022/task-table/task-table.component.mjs +534 -0
  103. package/esm2022/terminal-stream/terminal-stream.component.mjs +583 -0
  104. package/esm2022/thinking/thinking.component.mjs +276 -0
  105. package/esm2022/thinking-states/thinking-states.component.mjs +333 -0
  106. package/esm2022/thread-panel/thread-panel.component.mjs +271 -0
  107. package/esm2022/toast/toast.component.mjs +195 -0
  108. package/esm2022/toast-stack/toast-stack.component.mjs +301 -0
  109. package/esm2022/tool-call/tool-call.component.mjs +273 -0
  110. package/esm2022/tooltip/tooltip.component.mjs +417 -0
  111. package/esm2022/top-pages/top-pages.component.mjs +240 -0
  112. package/esm2022/trace-view/trace-view.component.mjs +440 -0
  113. package/esm2022/visuno-angular.mjs +5 -0
  114. package/esm2022/voice-capture/voice-capture.component.mjs +650 -0
  115. package/esm2022/voice-orb/voice-orb.component.mjs +538 -0
  116. package/esm2022/web-search/web-search.component.mjs +374 -0
  117. package/eval-results/eval-results.component.d.ts +67 -0
  118. package/feedback-sheet/feedback-sheet.component.d.ts +74 -0
  119. package/fesm2022/visuno-angular.mjs +31992 -0
  120. package/fesm2022/visuno-angular.mjs.map +1 -0
  121. package/field-extraction/field-extraction.component.d.ts +82 -0
  122. package/funnel-chart/funnel-chart.component.d.ts +70 -0
  123. package/grid/grid.component.d.ts +22 -0
  124. package/health-score/health-score.component.d.ts +87 -0
  125. package/human-handoff/human-handoff.component.d.ts +125 -0
  126. package/image-generation/image-generation.component.d.ts +253 -0
  127. package/index.d.ts +5 -0
  128. package/inline-text-diff/inline-text-diff.component.d.ts +76 -0
  129. package/launch-checklist/launch-checklist.component.d.ts +46 -0
  130. package/line-chart/line-chart.component.d.ts +89 -0
  131. package/live-answer/live-answer.component.d.ts +110 -0
  132. package/metric-insight/metric-insight.component.d.ts +110 -0
  133. package/modal/modal.component.d.ts +37 -0
  134. package/model-picker/model-picker.component.d.ts +97 -0
  135. package/package.json +51 -4
  136. package/permission-gate/permission-gate.component.d.ts +100 -0
  137. package/plan-review/plan-review.component.d.ts +86 -0
  138. package/progress/progress.component.d.ts +91 -0
  139. package/prompt-library/prompt-library.component.d.ts +121 -0
  140. package/prompt-starters/prompt-starters.component.d.ts +65 -0
  141. package/proposal-card/proposal-card.component.d.ts +101 -0
  142. package/public-api.d.ts +82 -0
  143. package/radar-chart/radar-chart.component.d.ts +110 -0
  144. package/radial-goals/radial-goals.component.d.ts +90 -0
  145. package/reasoning-trail/reasoning-trail.component.d.ts +73 -0
  146. package/response-versions/response-versions.component.d.ts +54 -0
  147. package/rewrite-toolbar/rewrite-toolbar.component.d.ts +92 -0
  148. package/rich-text-editor/rich-text-editor.component.d.ts +180 -0
  149. package/run-cost/run-cost.component.d.ts +43 -0
  150. package/run-queue/run-queue.component.d.ts +93 -0
  151. package/run-summary/run-summary.component.d.ts +81 -0
  152. package/scatter-chart/scatter-chart.component.d.ts +139 -0
  153. package/score-breakdown/score-breakdown.component.d.ts +107 -0
  154. package/segmented-control/segmented-control.component.d.ts +44 -0
  155. package/source-stack/source-stack.component.d.ts +60 -0
  156. package/stat-cards/stat-cards.component.d.ts +86 -0
  157. package/status-pill/status-pill.component.d.ts +64 -0
  158. package/steering/steering.component.d.ts +75 -0
  159. package/step-loader/step-loader.component.d.ts +40 -0
  160. package/styles.css +424 -0
  161. package/task-table/task-table.component.d.ts +114 -0
  162. package/terminal-stream/terminal-stream.component.d.ts +110 -0
  163. package/thinking/thinking.component.d.ts +63 -0
  164. package/thinking-states/thinking-states.component.d.ts +51 -0
  165. package/thread-panel/thread-panel.component.d.ts +75 -0
  166. package/toast/toast.component.d.ts +56 -0
  167. package/toast-stack/toast-stack.component.d.ts +72 -0
  168. package/tokens.css +424 -0
  169. package/tool-call/tool-call.component.d.ts +61 -0
  170. package/tooltip/tooltip.component.d.ts +89 -0
  171. package/top-pages/top-pages.component.d.ts +75 -0
  172. package/trace-view/trace-view.component.d.ts +95 -0
  173. package/voice-capture/voice-capture.component.d.ts +103 -0
  174. package/voice-orb/voice-orb.component.d.ts +78 -0
  175. package/web-search/web-search.component.d.ts +77 -0
package/tokens.css ADDED
@@ -0,0 +1,424 @@
1
+ /* @visuno/angular design tokens — self-contained.
2
+ * Dark mode: <html data-theme="dark"> Soft style: <html data-style="soft">
3
+ * Import once globally: @import '@visuno/angular/styles.css';
4
+ */
5
+ /* Visuno shared core: tokens for Blueprint (default) and Soft (data-style="soft" on <html> or on any element around the components), light and dark (<html data-theme="dark">) */
6
+ :where([data-c]) [hidden]{display:none!important}
7
+ /* hold(): an end state centred in the height its component had */
8
+ .held{display:flex;flex-direction:column;justify-content:center}
9
+ /* the glide starts fast in both styles, so the field is on its way up before an opening list reaches the stage's edge */
10
+ .glide{transform:translateY(var(--vo-gy,0px));transition:transform var(--vo-t) cubic-bezier(.22,1,.36,1)}
11
+ /* and a list that opens under a gliding field fades in a beat after it starts to move */
12
+ .glide>.csx-pop.open{transition-delay:.08s}
13
+ .glide>.msc-pop.open{transition-delay:.08s,.08s,.08s,0s}
14
+ /* Soft 2: one quiet surface per object, grey type for finished work, motion only on what is happening now */
15
+ :root,[data-style="soft"]{
16
+ --vo-motion:soft;
17
+ --vo-page:#f7f7f7; --vo-stage:#fafafa; --vo-surface:#ffffff; --vo-raised:#ffffff;
18
+ --vo-fg:#171717; --vo-fg2:#525252; --vo-muted:#6a6a6a; --vo-faint:#c4c4c4; --vo-rail:#d4d4d4; --vo-line:#e8e8e8; --vo-field-line:#d4d4d4; --vo-line-strong:#858585; --vo-field-line-strong:#b3b3b3;
19
+ --vo-chip:#f3f3f3; --vo-hover:#ebebeb; --vo-press:#e3e3e3; --vo-wash:#f9f9f9; --vo-row:#fafafa;
20
+ --vo-soft:#ececec; --vo-soft-h:#e3e3e3; --vo-soft-ring:inset 0 0 0 1px rgba(0,0,0,.03),inset 0 1px 0 rgba(255,255,255,.7); --vo-dis:#a6a6a6;
21
+ /* disabled: text and icons take --vo-dis; a control with a fill swaps it for --vo-dis-fill (Blueprint hatches it) */
22
+ --vo-dis-fill:var(--vo-soft); --vo-dis-hatch:none;
23
+ --vo-shadow-lift:0 0 0 1px rgba(0,0,0,.05),0 2px 4px rgba(0,0,0,.04),0 16px 32px -10px rgba(0,0,0,.16);
24
+ /* the accent has three roles: --vo-accent fills (with --vo-on-accent on top, 4.5:1), --vo-accent-fg is text and icons in the accent
25
+ (4.5:1 on the surface, and on the chips and tints it sits on) and --vo-accent-mark is lines, rings and chart marks (3:1). A
26
+ light accent like lime keeps its fills and gets a darker mark and ink-coloured text on a light page */
27
+ --vo-accent:#116ff8; --vo-on-accent:#ffffff; --vo-accent-fg:#0f5fd5; --vo-accent-mark:#116ff8; --vo-sel:color-mix(in srgb,var(--vo-accent) 6%,transparent);
28
+ /* fields (text fields, textareas, search fields, dropdown triggers) have a dimmed grey edge, --vo-field-line, that steps up
29
+ a little, to --vo-field-line-strong, while they have the focus. The keyboard's focus ring on every other control is 2px of
30
+ a stronger grey (--vo-line-strong, as --vo-focus), as an outline offset 2px, or as a 2px box-shadow ring where an outline would be clipped. Never
31
+ the accent and never black, and only from the keyboard (:focus-visible), so a click or a tap never shows one */
32
+ --vo-focus:var(--vo-line-strong);
33
+ --vo-ink:#1b1b1b; --vo-on-ink:#ffffff;
34
+ --vo-ok:#0a7034; --vo-ok-bg:#cff5db; --vo-ok-mark:#4cbb17; --vo-warn:#9a4704; --vo-warn-bg:#ffe5b8; --vo-warn-mark:#f76700; --vo-bad:#b81d23; --vo-bad-bg:#ffe8e8;
35
+ --vo-merge:#7c4cd4; --vo-merge-bg:#f2ecfd; --vo-add:#187633; --vo-del:#c7212c;
36
+ --vo-pb:#1460d0; --vo-pb-bg:#eaf2ff; --vo-pl:#6b47d6; --vo-pl-bg:#f2edff; --vo-pm:#10754a; --vo-pm-bg:#e7f8f0; --vo-pp:#994c0b; --vo-pp-bg:#fff2e6;
37
+ --vo-pr:#bf314d; --vo-pr-bg:#ffeef1; --vo-py:#856404; --vo-py-bg:#fffae3; --vo-pk:#b92e75; --vo-pk-bg:#fff0f7; --vo-pt:#0e747d; --vo-pt-bg:#e6f9fa;
38
+ /* avatars have colours of their own, the same in every style and theme: a bright fill and the initials' ink on it (4.5:1,
39
+ APCA Lc 60). Blue, violet, red and pink are deep enough for white; green, teal, yellow and orange are too light for white
40
+ and take a dark ink of their own hue. An avatar given one of these, var(--vo-av-l), takes its ink, var(--vo-av-l-ink), on its own */
41
+ --vo-av-b:#126fe6; --vo-av-b-ink:#ffffff; --vo-av-l:#834ff5; --vo-av-l-ink:#ffffff; --vo-av-r:#d73341; --vo-av-r-ink:#ffffff; --vo-av-k:#cf3288; --vo-av-k-ink:#ffffff;
42
+ --vo-av-m:#27cf86; --vo-av-m-ink:#052616; --vo-av-t:#28c9d8; --vo-av-t-ink:#042428; --vo-av-y:#e9ac1a; --vo-av-y-ink:#2a1d03; --vo-av-p:#fda154; --vo-av-p-ink:#301804;
43
+ --vo-ts:#2c6cb2; --vo-react:#0a738b;
44
+ /* every raised surface carries its own hairline edge, so nothing needs a separate ring */
45
+ /* soft, layered shadows: a hairline, a contact shadow and two wide, faint ones, with a faint highlight on the top edge */
46
+ --vo-shadow:0 0 0 1px rgba(0,0,0,.03),0 1px 1px rgba(0,0,0,.025),0 2px 4px -1px rgba(0,0,0,.03),0 8px 16px -6px rgba(0,0,0,.05),0 20px 36px -14px rgba(0,0,0,.08),inset 0 1px 0 rgba(255,255,255,.75);
47
+ --vo-shadow-pop:0 0 0 1px rgba(0,0,0,.035),0 1px 2px rgba(0,0,0,.03),0 4px 10px -4px rgba(0,0,0,.05),0 14px 28px -10px rgba(0,0,0,.08),0 32px 56px -24px rgba(0,0,0,.12),inset 0 1px 0 rgba(255,255,255,.75);
48
+ --vo-shadow-toast:0 0 0 1px rgba(0,0,0,.03),0 4px 12px rgba(0,0,0,.08);
49
+ --vo-hl:#fdeb9a; --vo-hl-ok:#d3f1df;
50
+ /* Soft is plush: every corner is scaled by --vo-rk, and larger still where the browser draws true squircles (below) */
51
+ --vo-rk:1.25;
52
+ --vo-r-card:calc(16px * var(--vo-rk));
53
+ /* spacing runs on a 4px scale, and corners on a small set of radii; values off the scale are still written out */
54
+ --vo-s-1:4px; --vo-s-2:8px; --vo-s-3:12px; --vo-s-4:16px; --vo-s-5:20px; --vo-s-6:24px; --vo-s-8:32px; --vo-r-xs:calc(4px * var(--vo-rk)); --vo-r-lg:calc(20px * var(--vo-rk)); --vo-r-in:calc(12px * var(--vo-rk)); --vo-r-sm:calc(8px * var(--vo-rk)); --vo-r-pill:999px;
55
+ /* fields and tags have slightly rounded corners, never pills: --vo-r-field for one-line fields and dropdown triggers, --vo-r-box
56
+ for boxes you write several lines in, --vo-r-tag for tags. Where the browser smooths corners (corner-shape: squircle) a
57
+ corner looks smaller, so each takes the larger -sq radius there to look the same size. Fields share one height and,
58
+ where a component is a single field, one width */
59
+ --vo-r-field:10px; --vo-r-field-sq:16px; --vo-r-box:14px; --vo-r-box-sq:22px; --vo-r-tag:7px; --vo-r-tag-sq:12px;
60
+ --vo-field-h:40px; --vo-field-w:320px;
61
+ --vo-sans:"Inter",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
62
+ --vo-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
63
+ --vo-ease:cubic-bezier(.22,1,.36,1); --vo-ease-io:cubic-bezier(.65,0,.35,1);
64
+ --vo-t-fast:.22s; --vo-t:.45s; --vo-t-slow:.7s;
65
+ }
66
+ @media (prefers-color-scheme:dark){:root:not([data-theme="light"]),:root:not([data-theme="light"]) [data-style="soft"]{
67
+ --vo-page:#111111; --vo-stage:#1c1c1c; --vo-surface:#262626; --vo-raised:#2c2c2c;
68
+ --vo-fg:#f2f2f2; --vo-fg2:#c9c9c9; --vo-muted:#c0c0c0; --vo-faint:#555555; --vo-rail:#414141; --vo-line:#333333; --vo-field-line:#424242; --vo-line-strong:#808080; --vo-field-line-strong:#808080;
69
+ --vo-chip:#303030; --vo-hover:#373737; --vo-press:#3f3f3f; --vo-wash:#2c2c2c; --vo-row:color-mix(in srgb,var(--vo-fg) 5.5%,transparent);
70
+ --vo-soft:#323232; --vo-soft-h:#3a3a3a; --vo-soft-ring:inset 0 0 0 1px rgba(255,255,255,.035),inset 0 1px 0 rgba(255,255,255,.05); --vo-dis:#737373;
71
+ --vo-shadow-lift:0 0 0 1px rgba(255,255,255,.08),0 2px 4px rgba(0,0,0,.3),0 16px 32px -10px rgba(0,0,0,.6);
72
+ --vo-accent:#116ff8; --vo-on-accent:#ffffff; --vo-accent-fg:#9dc4ff; --vo-accent-mark:#3d8bff; --vo-sel:color-mix(in srgb,var(--vo-accent) 9%,transparent);
73
+ --vo-ink:#f2f2f2; --vo-on-ink:#161616;
74
+ --vo-ok:#4ee28a; --vo-ok-bg:rgba(34,214,110,.2); --vo-ok-mark:#4cbb17; --vo-warn:#ffc247; --vo-warn-bg:rgba(255,184,40,.2); --vo-warn-mark:#ffa940; --vo-bad:#ff8a8a; --vo-bad-bg:rgba(255,90,90,.14);
75
+ --vo-merge:#cbb8ff; --vo-merge-bg:rgba(169,139,255,.15); --vo-add:#63d998; --vo-del:#ffa9ae;
76
+ --vo-pb:#a0c5ff; --vo-pb-bg:rgba(90,150,255,.18); --vo-pl:#cbb9ff; --vo-pl-bg:rgba(155,125,255,.18); --vo-pm:#6ad9a7; --vo-pm-bg:rgba(70,205,150,.16); --vo-pp:#ffb57a; --vo-pp-bg:rgba(255,155,80,.17);
77
+ --vo-pr:#ffadbb; --vo-pr-bg:rgba(255,105,130,.17); --vo-py:#f0cd5a; --vo-py-bg:rgba(240,200,60,.15); --vo-pk:#ffa8d4; --vo-pk-bg:rgba(255,100,175,.16); --vo-pt:#5fd8df; --vo-pt-bg:rgba(60,200,210,.16);
78
+ --vo-ts:#8fbcff; --vo-react:#3dd0ee;
79
+ --vo-shadow:0 0 0 1px rgba(255,255,255,.045),0 1px 2px rgba(0,0,0,.28),0 6px 14px -6px rgba(0,0,0,.36),0 20px 36px -14px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.06); --vo-shadow-pop:0 0 0 1px rgba(255,255,255,.055),0 2px 4px rgba(0,0,0,.3),0 12px 24px -8px rgba(0,0,0,.45),0 32px 56px -20px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.07); --vo-shadow-toast:0 0 0 1px rgba(255,255,255,.05),0 4px 12px rgba(0,0,0,.4); --vo-hl:rgba(240,200,60,.3); --vo-hl-ok:rgba(60,207,126,.24); color-scheme:dark}}
80
+ :root[data-theme="dark"],:root[data-theme="dark"] [data-style="soft"]{
81
+ --vo-page:#111111; --vo-stage:#1c1c1c; --vo-surface:#262626; --vo-raised:#2c2c2c;
82
+ --vo-fg:#f2f2f2; --vo-fg2:#c9c9c9; --vo-muted:#c0c0c0; --vo-faint:#555555; --vo-rail:#414141; --vo-line:#333333; --vo-field-line:#424242; --vo-line-strong:#808080; --vo-field-line-strong:#808080;
83
+ --vo-chip:#303030; --vo-hover:#373737; --vo-press:#3f3f3f; --vo-wash:#2c2c2c; --vo-row:color-mix(in srgb,var(--vo-fg) 5.5%,transparent);
84
+ --vo-soft:#323232; --vo-soft-h:#3a3a3a; --vo-soft-ring:inset 0 0 0 1px rgba(255,255,255,.035),inset 0 1px 0 rgba(255,255,255,.05); --vo-dis:#737373;
85
+ --vo-shadow-lift:0 0 0 1px rgba(255,255,255,.08),0 2px 4px rgba(0,0,0,.3),0 16px 32px -10px rgba(0,0,0,.6);
86
+ --vo-accent:#116ff8; --vo-on-accent:#ffffff; --vo-accent-fg:#9dc4ff; --vo-accent-mark:#3d8bff; --vo-sel:color-mix(in srgb,var(--vo-accent) 9%,transparent);
87
+ --vo-ink:#f2f2f2; --vo-on-ink:#161616;
88
+ --vo-ok:#4ee28a; --vo-ok-bg:rgba(34,214,110,.2); --vo-ok-mark:#4cbb17; --vo-warn:#ffc247; --vo-warn-bg:rgba(255,184,40,.2); --vo-warn-mark:#ffa940; --vo-bad:#ff8a8a; --vo-bad-bg:rgba(255,90,90,.14);
89
+ --vo-merge:#cbb8ff; --vo-merge-bg:rgba(169,139,255,.15); --vo-add:#63d998; --vo-del:#ffa9ae;
90
+ --vo-pb:#a0c5ff; --vo-pb-bg:rgba(90,150,255,.18); --vo-pl:#cbb9ff; --vo-pl-bg:rgba(155,125,255,.18); --vo-pm:#6ad9a7; --vo-pm-bg:rgba(70,205,150,.16); --vo-pp:#ffb57a; --vo-pp-bg:rgba(255,155,80,.17);
91
+ --vo-pr:#ffadbb; --vo-pr-bg:rgba(255,105,130,.17); --vo-py:#f0cd5a; --vo-py-bg:rgba(240,200,60,.15); --vo-pk:#ffa8d4; --vo-pk-bg:rgba(255,100,175,.16); --vo-pt:#5fd8df; --vo-pt-bg:rgba(60,200,210,.16);
92
+ --vo-ts:#8fbcff; --vo-react:#3dd0ee;
93
+ --vo-shadow:0 0 0 1px rgba(255,255,255,.045),0 1px 2px rgba(0,0,0,.28),0 6px 14px -6px rgba(0,0,0,.36),0 20px 36px -14px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.06); --vo-shadow-pop:0 0 0 1px rgba(255,255,255,.055),0 2px 4px rgba(0,0,0,.3),0 12px 24px -8px rgba(0,0,0,.45),0 32px 56px -20px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.07); --vo-shadow-toast:0 0 0 1px rgba(255,255,255,.05),0 4px 12px rgba(0,0,0,.4); --vo-hl:rgba(240,200,60,.3); --vo-hl-ok:rgba(60,207,126,.24); color-scheme:dark}
94
+
95
+ /* the accent's hover fill (--vo-accent-2) and tint (--vo-accent-bg) are worked out from the accent, in every style and theme, so a
96
+ picked accent brings its own. Hovering a filled button moves its fill away from its text colour: darker under white text,
97
+ lighter under dark text, so the label keeps its contrast in every style, theme and accent */
98
+ :root,[data-style="soft"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 86%,#000);--vo-accent-bg:color-mix(in srgb,var(--vo-accent) 9%,transparent)}
99
+ @media (prefers-color-scheme:dark){:root:not([data-theme="light"]),:root:not([data-theme="light"]) [data-style="soft"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 84%,#fff);--vo-accent-bg:color-mix(in srgb,var(--vo-accent) 13%,transparent)}}
100
+ :root[data-theme="dark"],:root[data-theme="dark"] [data-style="soft"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 84%,#fff);--vo-accent-bg:color-mix(in srgb,var(--vo-accent) 13%,transparent)}
101
+ @supports (color:rgb(from red r g b)){:root,[data-style="soft"],:root:not([data-theme="light"]),:root:not([data-theme="light"]) [data-style="soft"],:root[data-theme="dark"],:root[data-theme="dark"] [data-style="soft"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 86%,rgb(from var(--vo-on-accent) calc(255 - r) calc(255 - g) calc(255 - b)))}}
102
+ @supports not (color:rgb(from red r g b)){:root,[data-style="soft"],:root:not([data-theme="light"]),:root:not([data-theme="light"]) [data-style="soft"],:root[data-theme="dark"],:root[data-theme="dark"] [data-style="soft"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 86%,#000)}:root:not([data-style="soft"]),:root:not([data-style="soft"]):not([data-theme="light"]),:root:not([data-style="soft"])[data-theme="dark"]{--vo-accent-2:color-mix(in srgb,var(--vo-accent) 86%,#fff)}}
103
+ /* picked things (chips, options, cards in a picker) are white tiles with a dimmed grey edge, and the picked one's edge
104
+ is a light step stronger, never a dark or black outline */
105
+ :root,[data-style="soft"]{--vo-pick-line:var(--vo-rail);--vo-pick-on:var(--vo-faint)}
106
+
107
+ /* Soft is plush: corners are drawn as squircles where the browser can (corner-shape), and since a squircle's corner
108
+ reads smaller than a round one of the same radius, the radii grow with it. Circles (spinners, loader rings, avatars,
109
+ dots) stay round; pills, chips, buttons and switchers are squircles too. Blueprint stays square (its corners are 0) */
110
+ @supports (corner-shape:squircle){
111
+ :root,[data-style="soft"]{--vo-rk:1.7}
112
+ :root:not([data-style="soft"]){--vo-rk:1}
113
+ :where([data-c]) *,:where([data-c]) *::before,:where([data-c]) *::after{corner-shape:squircle}
114
+ .acx-n .s,.afx-pen,.afx-r b,.agx-now i,.alg-ph-pg,.alg-sc-knob,.alg-sc-ld,.alg-sc-n,.aln-cw-tr b,.aln-pk,.asx-lp-stop,.asx-lp-th,.asx-lp-th i,.asx-tb-dot,.atx-cmp-ok,.atx-cmp-send,.atx-cmp-x,.av,.bdg-dot,.bdg-x,.bdg-x:focus-visible,.btx-live,.bws-dots i,.ccx-fl .flag,.ccx-sw,.cmx-go,.cmx-pin,.cpx-att .fchip .rt,.cpx-att .fchip .x,.cpx-dot,.cpx-send,.ctb-n .s,.dot,.drv-ag,.drv-ring,.dtx-sl .k,.ecx-days b,.ecx-dh.t b,.erx-o i,.evr-dot,.evr-jg-arc .tr,.evr-jg-arc i,.fxp-n .ag,.hox-av,.ib,.lcx-ring,.lnx-k i,.lnx-pt,.mix-dot,.msc-c button,.ntx-n .u,.obx .obx-rw .obx-rk,.obx-ck,.obx-rk,.plx-s .n,.psx-go,.pulse,.rq-wk-c .rq-ic,.rq-wk-ring .h i,.rq-wk-ring .tr,.rq-wk-stack i,.rsu-g,.rsu-rc-nd,.rsu-rc-ok,.rsu-rc-ok i,.rsu-rp-ok,.rxx-add,.sgc-wr .e i,.spin,.ssx-ics span,.ste-go,.stx-conf i.d,.stx-st .n,.tcx[data-d="inline"] .tcb-wire i,.think i,.thp-send,.thp[data-d] .tpx-dots i,.thp[data-d] .tpx-send,.thp[data-d] .tpx-st,.tk-st .mk,.tsk-c .g,.tst-t .g,.ttp-av,.vcx-dot,.vor .vor-orb i,.vor-dot,.vor-gl,.vor-orb i,.cxm-av,.crs-dots button,.rdx-lg i,.scx-lg i.c,.cvq-lg i.c,.rgx-r i,.cpk-k,.wsx-marks span,.igx-steps i,.ths-dg i,.ths-mtx i{corner-shape:round}
115
+ .aln-det div::before{corner-shape:round}
116
+ .asx-lp-rg::-moz-range-thumb{corner-shape:round}
117
+ .asx-lp-rg::-webkit-slider-thumb{corner-shape:round}
118
+ .btx-live::after{corner-shape:round}
119
+ .dpk-d.t::after{corner-shape:round}
120
+ .ecx-now::before{corner-shape:round}
121
+ .fxp-tree::-webkit-scrollbar-thumb{corner-shape:round}
122
+ .hand::before{corner-shape:round}
123
+ .hnx-t .ic::after{corner-shape:round}
124
+ .ksx-s .ic::after{corner-shape:round}
125
+ .pulse::after{corner-shape:round}
126
+ .radar::after{corner-shape:round}
127
+ .radar::before{corner-shape:round}
128
+ .sgc-mo .d.e::after{corner-shape:round}
129
+ .shx-r .ic::after{corner-shape:round}
130
+ .stx-ok::after{corner-shape:round}
131
+ .tmx-body::-webkit-scrollbar-thumb{corner-shape:round}
132
+ .toggle::after{corner-shape:round}
133
+ .afx-desk::before{corner-shape:round}
134
+ }
135
+ /* ---------- page shell ---------- */
136
+ :where([data-c]) *{box-sizing:border-box}
137
+ :where([data-c]) button,:where([data-c]) input,:where([data-c]) textarea,:where([data-c]) select{font:inherit;color:inherit}
138
+ :where([data-c]) button{background:none;border:0;padding:0;cursor:pointer}
139
+ /* one weight for emphasis: medium, never bold */
140
+ :where([data-c]) b,:where([data-c]) strong{font-weight:500}
141
+ :where([data-c]) :focus-visible{outline:2px solid var(--vo-focus);outline-offset:2px;border-radius:calc(6px * var(--vo-rk))}
142
+ /* a field shows the focus with its own edge, which steps up to --vo-field-line-strong, so it never takes the ring as well */
143
+ :where([data-c]) :focus-visible:is(input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"],[type="button"],[type="submit"],[type="reset"]),textarea,select,[contenteditable]:not([contenteditable="false"])){outline:0}
144
+ .stage-in{width:100%;max-width:440px;min-width:0;position:relative;container-type:inline-size}
145
+ .card.wide .stage-in{max-width:720px}
146
+
147
+ /* ---------- icons ---------- */
148
+ .i{width:16px;height:16px;flex:none;display:inline-block;vertical-align:-3px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
149
+ .i.s{width:14px;height:14px}.i.xs{width:12px;height:12px}.i.l{width:18px;height:18px}
150
+ .brand{width:16px;height:16px;display:block;flex:none}
151
+ .flag{width:20px;height:15px;border-radius:3px;object-fit:cover;display:block;flex:none;box-shadow:0 0 0 1px rgba(0,0,0,.08)}
152
+
153
+ /* ---------- primitives ---------- */
154
+ .mono{font-family:var(--vo-mono)}
155
+ .sp{flex:1}
156
+ .num{font-variant-numeric:tabular-nums}
157
+ .muted{color:var(--vo-muted)}.fg2{color:var(--vo-fg2)}
158
+ .panel{background:var(--vo-surface);border-radius:var(--vo-r-card);box-shadow:var(--vo-shadow);position:relative}
159
+ .ib{width:30px;height:30px;border-radius:50%;display:inline-grid;place-items:center;color:var(--vo-fg2);transition:background var(--vo-t-fast),color var(--vo-t-fast),transform .15s}
160
+ @media (hover:hover) and (pointer:fine){.ib:hover{background:var(--vo-row);color:var(--vo-fg)}}
161
+ .ib:active{transform:scale(.94)}
162
+ .ib.fill{background:var(--vo-soft);box-shadow:var(--vo-soft-ring)}
163
+ @media (hover:hover) and (pointer:fine){.ib.fill:hover{background:var(--vo-soft-h)}}
164
+ .ib.on{background:var(--vo-accent-bg);color:var(--vo-accent-fg,var(--vo-accent))}
165
+ .chip{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 var(--vo-s-3);border-radius:var(--vo-r-pill);font-size:13px;color:var(--vo-fg2);background:var(--vo-chip);white-space:nowrap;transition:background var(--vo-t-fast),color var(--vo-t-fast),box-shadow var(--vo-t-fast)}
166
+ @media (hover:hover) and (pointer:fine){.chip:hover{background:var(--vo-hover);color:var(--vo-fg)}}
167
+ .chip.on{background:var(--vo-surface);color:var(--vo-fg);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-pick-on) 50%,transparent)}
168
+ .chip.sm{height:24px;padding:0 9px;font-size:12px}
169
+ .pill{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:32px;padding:0 14px;border-radius:var(--vo-r-pill);font-size:13px;font-weight:500;white-space:nowrap;transition:background var(--vo-t-fast),color var(--vo-t-fast),opacity var(--vo-t-fast),transform .15s}
170
+ .pill:active{transform:scale(.97)}
171
+ /* the primary action is the accent, with --vo-on-accent on it, so it follows the accent and stays readable in any colour */
172
+ .pill.primary{background:var(--vo-accent);color:var(--vo-on-accent)}
173
+ @media (hover:hover) and (pointer:fine){.pill.primary:hover{background:var(--vo-accent-2)}}
174
+ .pill.accent{background:var(--vo-accent);color:var(--vo-on-accent)}
175
+ .pill.accent.hl{background:var(--vo-accent-2)}
176
+ @media (hover:hover) and (pointer:fine){.pill.accent:hover{background:var(--vo-accent-2)}}
177
+ .pill.soft{background:var(--vo-soft);color:var(--vo-fg);box-shadow:var(--vo-soft-ring)}
178
+ @media (hover:hover) and (pointer:fine){.pill.soft:hover{background:var(--vo-soft-h)}}
179
+ .pill.line{background:var(--vo-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent);color:var(--vo-fg)}
180
+ .pill.ghost{color:var(--vo-fg2)}@media (hover:hover) and (pointer:fine){.pill.ghost:hover{background:var(--vo-row);color:var(--vo-fg)}}
181
+ /* one disabled look for every control: nothing fades; its text and icons take --vo-dis, a control with a fill swaps the fill
182
+ for --vo-dis-fill with its quiet edge (hatched in Blueprint), one without keeps no fill, and the pointer says not-allowed */
183
+ .pill[disabled]{opacity:1;color:var(--vo-dis);background:none;cursor:not-allowed;transform:none}
184
+ @media (hover:hover) and (pointer:fine){.pill[disabled]:hover{opacity:1;color:var(--vo-dis);background:none;cursor:not-allowed;transform:none}}
185
+ :where([data-c]) button:disabled{cursor:not-allowed}
186
+ .pill:is(.accent,.primary,.soft,.line)[disabled]{background:var(--vo-dis-hatch),var(--vo-dis-fill);color:var(--vo-dis);box-shadow:var(--vo-soft-ring)}
187
+ @media (hover:hover) and (pointer:fine){.pill:is(.accent,.primary,.soft,.line)[disabled]:hover{background:var(--vo-dis-hatch),var(--vo-dis-fill);color:var(--vo-dis);box-shadow:var(--vo-soft-ring)}}
188
+ .pill[disabled] .kbd{background:var(--vo-chip);color:inherit}
189
+ .pill.sm{height:28px;padding:0 11px;font-size:12.5px}
190
+ .tag{display:inline-flex;align-items:center;gap:5px;height:20px;padding:0 7px;border-radius:var(--vo-r-tag);font-size:11.5px;font-weight:500;white-space:nowrap;background:var(--vo-chip);color:var(--vo-fg2)}
191
+ .tag.b{background:var(--vo-pb-bg);color:var(--vo-pb)}.tag.l{background:var(--vo-pl-bg);color:var(--vo-pl)}.tag.m{background:var(--vo-pm-bg);color:var(--vo-pm)}.tag.p{background:var(--vo-pp-bg);color:var(--vo-pp)}
192
+ .tag.r{background:var(--vo-pr-bg);color:var(--vo-pr)}.tag.y{background:var(--vo-py-bg);color:var(--vo-py)}.tag.k{background:var(--vo-pk-bg);color:var(--vo-pk)}.tag.t{background:var(--vo-pt-bg);color:var(--vo-pt)}
193
+ .tag.ok{background:var(--vo-ok-bg);color:var(--vo-ok)}.tag.warn{background:var(--vo-warn-bg);color:var(--vo-warn)}.tag.bad{background:var(--vo-bad-bg);color:var(--vo-bad)}
194
+ @supports (corner-shape:squircle){.tag{corner-shape:squircle;border-radius:var(--vo-r-tag-sq)}}
195
+ .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none;display:inline-block}
196
+ .fchip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 10px 0 var(--vo-s-2);border-radius:var(--vo-r-pill);background:var(--vo-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent);font-size:12.5px;color:var(--vo-fg);white-space:nowrap}
197
+ .fchip.lnk{cursor:pointer;transition:background var(--vo-t-fast),box-shadow var(--vo-t-fast)}
198
+ @media (hover:hover) and (pointer:fine){.fchip.lnk:hover{background:var(--vo-row);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent)}}
199
+ .ft{font-family:var(--vo-sans);font-size:9.5px;font-weight:500;color:var(--vo-ts);letter-spacing:.02em}
200
+ .ft.re{color:var(--vo-react)}.ft.fg{color:var(--vo-pl)}.ft.pdf{color:var(--vo-pr)}.ft.csv{color:var(--vo-pm)}
201
+ .kbd{font-family:inherit;font-size:11px;padding:1px 5px;border-radius:5px;background:var(--vo-chip);color:var(--vo-fg2)}
202
+ /* on a row that is hovered, highlighted or picked, the row turns grey, so its shortcut chips turn white to stay visible */
203
+ @media (hover:hover) and (pointer:fine){:is(.mi,.cpl-i,[role="option"],[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"]):is(:hover,.hl,.on,[aria-selected="true"]) .kbd{background:var(--vo-surface)}}
204
+ @media (hover:hover) and (pointer:fine){.pill.ghost:hover .kbd{background:var(--vo-surface)}}
205
+ .pill .kbd{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 var(--vo-s-1);margin-right:-6px}
206
+ /* a key hint on a filled button sits on a slightly darker well of the fill, so white text keeps its contrast */
207
+ .pill.primary .kbd,.pill.accent .kbd{background:color-mix(in srgb,var(--vo-accent) 80%,#000);color:inherit}
208
+ code.c{font-family:var(--vo-mono);font-size:12.5px;background:var(--vo-chip);padding:1px 5px;border-radius:5px}
209
+ .av{width:22px;height:22px;border-radius:50%;display:inline-grid;place-items:center;font-size:10px;font-weight:500;color:#fff;flex:none}
210
+ .hr{height:1px;background:var(--vo-line);border:0;margin:0}
211
+ /* an off switch and an empty box are drawn in a grey that holds 3:1 against the surface; an accent fill keeps a hairline of the
212
+ accent's mark, so a light accent like lime still has an edge */
213
+ .toggle{width:30px;height:18px;border-radius:calc(9px * var(--vo-rk));background:color-mix(in srgb,var(--vo-muted) 80%,var(--vo-surface));position:relative;flex:none;transition:background var(--vo-t-fast)}
214
+ .toggle::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2);transition:transform var(--vo-t) var(--vo-ease)}
215
+ .toggle[aria-checked="true"]{background:var(--vo-accent);box-shadow:inset 0 0 0 1px var(--vo-accent-mark,var(--vo-accent))}
216
+ .toggle[aria-checked="true"]::after{transform:translateX(12px);background:var(--vo-on-accent)}
217
+ /* on a touch screen every control gets a tap area of at least 40px square, centred on it, without changing how it looks or
218
+ where anything sits: a clear ::before (or ::after, where a component draws with its ::before) over and around it. Where
219
+ two controls sit closer than that, the core script (fitHits) shrinks both areas evenly, so each tap still lands on the
220
+ control nearest to it. Everything here weighs nothing (:where), so a component's own position or pseudo-element wins.
221
+ The build checks that every selector drawing with a ::before or ::after is in the lists below */
222
+ @media (pointer:coarse){
223
+ :where([data-c]) :where(button,a[href],summary,[role="button"],[role="switch"],[role="checkbox"],[role="radio"],[role="tab"],[role="option"],[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"],[role="slider"],label:has(input[type="checkbox"],input[type="radio"])){position:relative;--vo-hit-w:40px;--vo-hit-h:40px}
224
+ :where([data-c]) :where(button,a[href],summary,[role="button"],[role="switch"],[role="checkbox"],[role="radio"],[role="tab"],[role="option"],[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"],[role="slider"],label:has(input[type="checkbox"],input[type="radio"])):not(:where(.radar,.hand,.rtr-li:not(:last-child),.atr-kids,.bws-nav b,.rc-cap,.erx-row:not(:last-child),.rte-body.empty,.rte-hint,.afx-desk,.dtx-sl,.crx-l.add .c,.crx-l.del .c,.crx-l.ctx .c,.crx-hk.kept .crx-l.add .c,.crx-hk.undone .crx-l.del .c,.ahx-bot,.ecx-now,.ssi-or,.cmx-th>.cmx-c:first-child:has(+ .cmx-rp),.cmx-rp,.aln-ct,.aln-rows>*,.aln-av,.aln-det div,.aln-pk,.trv-r[data-k="agent"] .trv-b i,.tk-st:not(:last-child),.tmx-blk,.atx-ic))::before,:where([data-c]) :where(button,a[href],summary,[role="button"],[role="switch"],[role="checkbox"],[role="radio"],[role="tab"],[role="option"],[role="menuitem"],[role="menuitemradio"],[role="menuitemcheckbox"],[role="slider"],label:has(input[type="checkbox"],input[type="radio"])):where(.radar,.hand,.rtr-li:not(:last-child),.atr-kids,.bws-nav b,.rc-cap,.erx-row:not(:last-child),.rte-body.empty,.rte-hint,.afx-desk,.dtx-sl,.crx-l.add .c,.crx-l.del .c,.crx-l.ctx .c,.crx-hk.kept .crx-l.add .c,.crx-hk.undone .crx-l.del .c,.ahx-bot,.ecx-now,.ssi-or,.cmx-th>.cmx-c:first-child:has(+ .cmx-rp),.cmx-rp):not(:where(.aln-lane,.trv-g i.el,.trv-r.run:not([data-k="agent"]) .trv-b i,.trv-r[data-k="agent"] .trv-b i,.trv-b,.trv-sc,.tk-st.done:not(:last-child),.tmx-h,.tmx.live .tmx-body,.atx-ic,.toggle,.radar,.pulse,.stl-track i,.stx-ok,.aln-tr i,.afx-card .afx-open,.plx-s.edited .t,.vor-mute,.mix-mk,.hnx-t .ic,.ksx-s .ic,.shx-r .ic,.dpk-d.t,.sgc-mo .d.e,.agx-now,.btx-ask,.btx-live,.ssi-or,.rxx-r,.bdg.live .bdg-dot,.thp[data-d="deck"] .tpb-card,.crs-pv,.crs-pic,.hmx-sc))::after{content:"";position:absolute;inset:min(0px,(100% - var(--vo-hit-h)) / 2) min(0px,(100% - var(--vo-hit-w)) / 2);--vo-hit:1}
225
+ }
226
+ .seg2{display:inline-flex;padding:2px;background:var(--vo-chip);border-radius:var(--vo-r-pill);position:relative}
227
+ .seg2 button{position:relative;z-index:1;height:26px;padding:0 11px;border-radius:var(--vo-r-pill);font-size:12.5px;color:var(--vo-fg2);transition:color var(--vo-t-fast)}
228
+ .seg2 button[aria-pressed="true"]{color:var(--vo-fg)}
229
+ .seg2 .knob{position:absolute;top:2px;bottom:2px;border-radius:var(--vo-r-pill);background:var(--vo-surface);box-shadow:0 1px 2px rgba(0,0,0,.08);transition:left var(--vo-t) var(--vo-ease),width var(--vo-t) var(--vo-ease)}
230
+ .seg2 button:focus-visible{outline-offset:-2px;border-radius:var(--vo-r-pill)}
231
+ /* demo stages: the component sits centred, the variant switcher sits at the foot of the stage under it */
232
+ .stage-in:has(>.dm){align-self:stretch;display:flex}
233
+ .dm{width:100%;min-height:328px;display:flex;flex-direction:column;align-items:center;gap:var(--vo-s-8)}
234
+ .dm>.vo-main{margin-block:auto;width:100%;display:flex;flex-direction:column;align-items:center}
235
+ .dm>.demo{flex:none;display:flex;justify-content:center}
236
+
237
+ .bub{align-self:flex-end;max-width:85%;background:var(--vo-hover);border-radius:var(--vo-r-card);padding:9px 13px;font-size:14px;line-height:1.45}
238
+ .msg{margin:0;font-size:14px;line-height:1.65}
239
+
240
+ /* ---------- status glyphs ---------- */
241
+ .spin{width:12px;height:12px;border-radius:50%;border:1.5px solid currentColor;border-right-color:transparent;animation:rot .8s linear infinite;flex:none;display:inline-block}
242
+ @keyframes rot{to{transform:rotate(360deg)}}
243
+ .radar{position:relative;width:13px;height:13px;flex:none;display:inline-block}
244
+ .radar::before{content:"";position:absolute;inset:3.5px;border-radius:50%;background:currentColor}
245
+ .radar::after{content:"";position:absolute;inset:0;border-radius:50%;border:1.3px solid currentColor;border-right-color:transparent;animation:rot .9s linear infinite}
246
+ /* the rotating thinking mark from Soft 1, four dots turning */
247
+ .think{width:14px;height:14px;position:relative;flex:none;display:inline-block}
248
+ .think i{position:absolute;width:3.4px;height:3.4px;border-radius:50%;background:currentColor;left:50%;top:50%;margin:-1.7px}
249
+ .think i:nth-child(1){transform:translate(-3.6px,-3.6px)}.think i:nth-child(2){transform:translate(3.6px,-3.6px)}.think i:nth-child(3){transform:translate(3.6px,3.6px)}.think i:nth-child(4){transform:translate(-3.6px,3.6px)}
250
+ .think.on{animation:thinkrot 1.6s var(--vo-ease-io) infinite}
251
+ .think.on i{animation:thinkpulse 1.6s var(--vo-ease-io) infinite}
252
+ .think.on i:nth-child(2){animation-delay:.2s}.think.on i:nth-child(3){animation-delay:.4s}.think.on i:nth-child(4){animation-delay:.6s}
253
+ @keyframes thinkrot{0%{transform:rotate(0)}50%{transform:rotate(90deg)}100%{transform:rotate(180deg)}}
254
+ @keyframes thinkpulse{0%,100%{opacity:1}50%{opacity:.35}}
255
+ /* the step that is happening now in a trace: a quiet grey dot with a soft ping */
256
+ .pulse{position:relative;width:6px;height:6px;border-radius:50%;background:var(--vo-muted);flex:none;display:inline-block}
257
+ .pulse::after{content:"";position:absolute;inset:0;border-radius:50%;background:inherit;animation:ping 1.8s var(--vo-ease) infinite}
258
+ @keyframes ping{0%{transform:scale(1);opacity:.45}80%,100%{transform:scale(2.8);opacity:0}}
259
+
260
+ /* ---------- motion ---------- */
261
+ .shim{background:linear-gradient(90deg,var(--vo-fg) 0%,var(--vo-fg) 38%,var(--vo-faint) 50%,var(--vo-fg) 62%,var(--vo-fg) 100%);background-size:260% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:shim 2.2s linear infinite}
262
+ @keyframes shim{from{background-position:100% 0}to{background-position:-160% 0}}
263
+ .enter{animation:enter var(--vo-t-slow) var(--vo-ease) backwards}
264
+ @keyframes enter{from{opacity:0;transform:translateY(6px);filter:blur(4px)}to{opacity:1;transform:none;filter:blur(0)}}
265
+ /* the person in a preview's story: a pointer that glides to what it uses and presses it */
266
+ .hand{position:absolute;left:0;top:0;width:18px;height:18px;z-index:30;pointer-events:none;opacity:0;color:var(--vo-fg);transition:transform .42s var(--vo-ease),opacity .16s;filter:drop-shadow(0 1px 1.5px rgba(0,0,0,.22))}
267
+ .hand.on{opacity:1}
268
+ .hand svg{display:block;width:18px;height:18px;transform-origin:3px 2px;transition:transform .16s var(--vo-ease)}
269
+ .hand svg path{fill:currentColor;stroke:var(--vo-surface);stroke-width:1.4;stroke-linejoin:round}
270
+ .hand.down svg{transform:scale(.82)}
271
+ .hand::before{content:"";position:absolute;left:-8px;top:-9px;width:22px;height:22px;border-radius:50%;background:var(--vo-accent);opacity:0;pointer-events:none}
272
+ .hand.down::before{animation:handtap .5s var(--vo-ease)}
273
+ @keyframes handtap{from{opacity:.3;transform:scale(.3)}to{opacity:0;transform:scale(1.3)}}
274
+ .pop-in{animation:popin .5s var(--vo-ease) backwards}
275
+ @keyframes popin{from{opacity:0;transform:scale(.96);filter:blur(3px)}to{opacity:1;transform:none;filter:blur(0)}}
276
+ .leave{animation:leave .35s var(--vo-ease) both}
277
+ @keyframes leave{to{opacity:0;transform:translateY(-6px);filter:blur(4px)}}
278
+ .sw{display:inline-block;transition:opacity .2s var(--vo-ease),filter .2s var(--vo-ease),transform .25s var(--vo-ease)}
279
+ .sw.out{opacity:0;filter:blur(3px);transform:translateY(3px)}
280
+ .fold{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--vo-t) var(--vo-ease),opacity var(--vo-t) var(--vo-ease)}
281
+ .fold>*{overflow:hidden;min-height:0}
282
+ /* shadows inside an open fold aren't cut off: the clip leaves room round its edge (a shut fold is invisible anyway) */
283
+ .fold{grid-template-columns:minmax(0,1fr)}
284
+ .fold>*{overflow:clip;overflow-clip-margin:12px;min-width:0}
285
+ /* a shut fold is hidden as well as clear once it has folded, so Tab passes over what is inside it */
286
+ .fold.shut{grid-template-rows:0fr;opacity:0;visibility:hidden;transition:grid-template-rows var(--vo-t) var(--vo-ease),opacity var(--vo-t) var(--vo-ease),visibility 0s var(--vo-t)}
287
+
288
+ /* ---------- tooltip and popover ---------- */
289
+ .tip{position:fixed;z-index:1000;pointer-events:none;background:var(--vo-ink);color:var(--vo-on-ink);font-size:12px;line-height:1.35;padding:6px 9px;border-radius:var(--vo-r-sm);max-width:240px;opacity:0;transform:translateY(4px);filter:blur(2px);transition:opacity .18s var(--vo-ease),transform .25s var(--vo-ease),filter .18s}
290
+ .tip.show{opacity:1;transform:none;filter:none}
291
+ .copied{color:var(--vo-ok)!important}
292
+ @media (hover:hover) and (pointer:fine){.copied:hover{color:var(--vo-ok)!important}}
293
+ .tip .kbd{background:rgba(255,255,255,.14);color:inherit;margin-left:6px}
294
+ :root[data-theme="dark"] .tip .kbd{background:rgba(0,0,0,.1)}
295
+ :root[data-theme="dark"] .ssx-ics span{color:#0d0d0d!important}
296
+ @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .ssx-ics span{color:#0d0d0d!important}}
297
+ /* a closed popover is hidden as well as clear, so Tab and screen readers pass over it: it shows at once as it opens, so the
298
+ focus can go into it, and hides once it has faded out */
299
+ .pop{position:absolute;z-index:50;min-width:200px;background:var(--vo-raised);border-radius:calc(14px * var(--vo-rk));box-shadow:var(--vo-shadow-pop);padding:6px;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(6px) scale(.98);transform-origin:var(--vo-origin,top left);filter:blur(3px);transition:opacity .2s var(--vo-ease),transform .35s var(--vo-ease),filter .2s var(--vo-ease),visibility 0s .2s}
300
+ .pop.open{opacity:1;visibility:visible;pointer-events:auto;transform:none;filter:none;transition-property:opacity,transform,filter}
301
+ .pop .ph{padding:6px var(--vo-s-2) var(--vo-s-1);font-size:11.5px;color:var(--vo-muted)}
302
+ .mi{display:flex;align-items:center;gap:10px;width:100%;padding:7px var(--vo-s-2);border-radius:calc(9px * var(--vo-rk));font-size:13px;text-align:left;color:var(--vo-fg);transition:background var(--vo-t-fast)}
303
+ .mi.hl{background:var(--vo-row)}
304
+ @media (hover:hover) and (pointer:fine){.mi:hover{background:var(--vo-row)}}
305
+ /* the rows of a menu or list stand 2px apart, so two highlighted rows never touch */
306
+ .mi+.mi,.cpl-i+.cpl-i,.six-it+.six-it{margin-top:2px}
307
+ .mi .i{color:var(--vo-fg2)}
308
+ .mi .d{display:block;font-size:12px;color:var(--vo-muted)}
309
+ /* on a hovered or picked row's tint the line under an item steps up, so it keeps 4.5:1 in dark mode */
310
+ @media (hover:hover) and (pointer:fine){.mi:is(:hover,.hl,[aria-checked="true"]) .d{color:var(--vo-fg2)}}
311
+ .mi .r{margin-left:auto;color:var(--vo-muted);font-size:12px}
312
+ .mi .ck{margin-left:auto;color:var(--vo-accent-fg,var(--vo-accent));opacity:0;transition:opacity var(--vo-t-fast)}
313
+ .mi[aria-checked="true"] .ck{opacity:1}
314
+ .mi[aria-checked="true"]{background:var(--vo-row);font-weight:500}
315
+ .pop .sep{height:1px;background:var(--vo-line);margin:var(--vo-s-1) 2px}
316
+ /* every list row hovers with --vo-row; an icon chip or track inside a hovered row lifts above it (white in light mode, one step lighter in dark) */
317
+ @media (hover:hover) and (pointer:fine){:root[data-theme="dark"] :is(.alg-it:hover .alg-ic,.plx-s:hover .n,.tpx-r:hover .tr){background:var(--vo-hover)}}
318
+ @media (prefers-color-scheme:dark){@media (hover:hover) and (pointer:fine){:root:not([data-theme="light"]) :is(.alg-it:hover .alg-ic,.plx-s:hover .n,.tpx-r:hover .tr){background:var(--vo-hover)}}}
319
+
320
+ @media (prefers-reduced-motion:reduce){:where([data-c]) *,:where([data-c]) *::before,:where([data-c]) *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}.shim{color:var(--vo-fg);background:none}}
321
+
322
+ /* bare: components that live in the chat stream sit on the chat surface, no card */
323
+ .card.bare .stage-in .panel:not(.keep){background:none;box-shadow:none;padding-left:0;padding-right:0;border-radius:0}
324
+ /* chart palette, saturated */
325
+ :root,[data-style="soft"]{--vo-c1:var(--vo-accent-mark,var(--vo-accent));--vo-c2:#7c4dff;--vo-c3:#4cbb17;--vo-c4:#f76700;--vo-c5:#ff4d6d;--vo-c6:#00a2bf}
326
+ /* the accent as a ramp, for charts whose parts are shares of one thing: full strength, then lighter steps toward the surface */
327
+ :root,[data-style="soft"]{--vo-a1:var(--vo-c1);--vo-a2:color-mix(in oklab,var(--vo-c1) 72%,var(--vo-surface));--vo-a3:color-mix(in oklab,var(--vo-c1) 50%,var(--vo-surface));--vo-a4:color-mix(in oklab,var(--vo-c1) 32%,var(--vo-surface))}
328
+ :root[data-theme="dark"],:root[data-theme="dark"] [data-style="soft"]{--vo-c1:var(--vo-accent-mark,var(--vo-accent));--vo-c2:#9b7bff;--vo-c3:#5fcb2a;--vo-c4:#ffa033;--vo-c5:#ff6b85;--vo-c6:#22cce8}
329
+ @media (prefers-color-scheme: dark){:root:not([data-theme="light"]),:root:not([data-theme="light"]) [data-style="soft"]{--vo-c1:var(--vo-accent-mark,var(--vo-accent));--vo-c2:#9b7bff;--vo-c3:#5fcb2a;--vo-c4:#ffa033;--vo-c5:#ff6b85;--vo-c6:#22cce8}}
330
+
331
+ /* ---------- Blueprint 2 ---------- */
332
+ /* Blueprint 2: the same components drawn as a technical sheet. Square corners, hairline edges instead of shadows,
333
+ a lime accent, and motion that wipes and ticks into place in short, hard beats instead of blurring in */
334
+ :root:not([data-style="soft"]){
335
+ --vo-motion:bp;
336
+ --vo-page:#f3f3f0; --vo-stage:#fafaf8; --vo-surface:#ffffff; --vo-raised:#ffffff;
337
+ --vo-fg:#121212; --vo-fg2:#4a4a46; --vo-muted:#666660; --vo-faint:#bdbdb6; --vo-rail:#d2d2cb; --vo-line:#e3e3dd; --vo-field-line:#d2d2cb; --vo-line-strong:#858580; --vo-field-line-strong:#b0b0a9;
338
+ --vo-chip:#f1f1ed; --vo-hover:#e8e8e3; --vo-press:#dededa; --vo-wash:#f6f6f3; --vo-row:#fafaf8;
339
+ --vo-soft:#ebebe6; --vo-soft-h:#e1e1db; --vo-soft-ring:inset 0 0 0 1px rgba(20,20,12,.045); --vo-dis:#a3a39c;
340
+ --vo-accent:#d4f84a; --vo-on-accent:#121212; --vo-accent-fg:var(--vo-fg); --vo-accent-mark:#4cbb17; --vo-sel:color-mix(in srgb,var(--vo-accent) 7%,transparent);
341
+ --vo-ink:#121212; --vo-on-ink:#ffffff;
342
+ --vo-shadow:0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent);
343
+ --vo-shadow-pop:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 12px 28px -14px rgba(20,20,12,.22);
344
+ --vo-shadow-toast:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 10px 24px -14px rgba(20,20,12,.24);
345
+ --vo-shadow-lift:0 0 0 1px color-mix(in srgb,var(--vo-fg) 50%,transparent);
346
+ --vo-grid:rgba(20,20,12,.09); --vo-tick:#b5b5ad;
347
+ --vo-dis-hatch:repeating-linear-gradient(135deg,transparent 0 4px,var(--vo-grid) 4px 5px);
348
+ --vo-ease:cubic-bezier(.65,0,.25,1); --vo-ease-io:cubic-bezier(.65,0,.25,1);
349
+ --vo-t-fast:.14s; --vo-t:.3s; --vo-t-slow:.44s;
350
+ }
351
+ @media (prefers-color-scheme:dark){:root:not([data-style="soft"]):not([data-theme="light"]){
352
+ --vo-page:#111111; --vo-stage:#1c1c1c; --vo-surface:#262626; --vo-raised:#2c2c2c;
353
+ --vo-fg:#f2f2f2; --vo-fg2:#c9c9c9; --vo-muted:#c0c0c0; --vo-faint:#555555; --vo-rail:#414141; --vo-line:#333333; --vo-field-line:#424242; --vo-line-strong:#80807a; --vo-field-line-strong:#808080;
354
+ --vo-chip:#303030; --vo-hover:#373737; --vo-press:#3f3f3f; --vo-wash:#2c2c2c; --vo-row:color-mix(in srgb,var(--vo-fg) 5.5%,transparent);
355
+ --vo-soft:#323232; --vo-soft-h:#3a3a3a; --vo-soft-ring:inset 0 0 0 1px rgba(255,255,255,.04); --vo-dis:#737373;
356
+ --vo-accent:#d4f84a; --vo-on-accent:#121212; --vo-accent-fg:#d4f84a; --vo-accent-mark:#d4f84a; --vo-sel:color-mix(in srgb,var(--vo-accent) 10%,transparent);
357
+ --vo-ink:#f2f2f2; --vo-on-ink:#161616;
358
+ --vo-shadow:0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent);
359
+ --vo-shadow-pop:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 16px 32px -14px rgba(0,0,0,.7);
360
+ --vo-shadow-toast:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 12px 28px -14px rgba(0,0,0,.7);
361
+ --vo-shadow-lift:0 0 0 1px color-mix(in srgb,var(--vo-fg2) 50%,transparent);
362
+ --vo-grid:rgba(255,255,255,.07); --vo-tick:#55554f;
363
+ --vo-dis-hatch:repeating-linear-gradient(135deg,transparent 0 4px,var(--vo-grid) 4px 5px);
364
+ --vo-ease:cubic-bezier(.65,0,.25,1); --vo-ease-io:cubic-bezier(.65,0,.25,1);
365
+ --vo-t-fast:.14s; --vo-t:.3s; --vo-t-slow:.44s}}
366
+ :root:not([data-style="soft"])[data-theme="dark"]{
367
+ --vo-page:#111111; --vo-stage:#1c1c1c; --vo-surface:#262626; --vo-raised:#2c2c2c;
368
+ --vo-fg:#f2f2f2; --vo-fg2:#c9c9c9; --vo-muted:#c0c0c0; --vo-faint:#555555; --vo-rail:#414141; --vo-line:#333333; --vo-field-line:#424242; --vo-line-strong:#80807a; --vo-field-line-strong:#808080;
369
+ --vo-chip:#303030; --vo-hover:#373737; --vo-press:#3f3f3f; --vo-wash:#2c2c2c; --vo-row:color-mix(in srgb,var(--vo-fg) 5.5%,transparent);
370
+ --vo-soft:#323232; --vo-soft-h:#3a3a3a; --vo-soft-ring:inset 0 0 0 1px rgba(255,255,255,.04); --vo-dis:#737373;
371
+ --vo-accent:#d4f84a; --vo-on-accent:#121212; --vo-accent-fg:#d4f84a; --vo-accent-mark:#d4f84a; --vo-sel:color-mix(in srgb,var(--vo-accent) 10%,transparent);
372
+ --vo-ink:#f2f2f2; --vo-on-ink:#161616;
373
+ --vo-shadow:0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent);
374
+ --vo-shadow-pop:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 16px 32px -14px rgba(0,0,0,.7);
375
+ --vo-shadow-toast:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent),0 12px 28px -14px rgba(0,0,0,.7);
376
+ --vo-shadow-lift:0 0 0 1px color-mix(in srgb,var(--vo-fg2) 50%,transparent);
377
+ --vo-grid:rgba(255,255,255,.07); --vo-tick:#55554f;
378
+ --vo-dis-hatch:repeating-linear-gradient(135deg,transparent 0 4px,var(--vo-grid) 4px 5px);
379
+ --vo-ease:cubic-bezier(.65,0,.25,1); --vo-ease-io:cubic-bezier(.65,0,.25,1);
380
+ --vo-t-fast:.14s; --vo-t:.3s; --vo-t-slow:.44s}
381
+
382
+ /* every corner is square, only the turning loaders stay round */
383
+ :root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *)),:root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *))::before,:root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *))::after{border-radius:0!important}
384
+ :root:not([data-style="soft"]) .spin:not(:where([data-style="soft"],[data-style="soft"] *)),:root:not([data-style="soft"]) .radar:not(:where([data-style="soft"],[data-style="soft"] *))::before,:root:not([data-style="soft"]) .radar:not(:where([data-style="soft"],[data-style="soft"] *))::after{border-radius:50%!important}
385
+ :root:not([data-style="soft"]) :where([data-c],.tip,.kbx-k.ghost) svg:not(.i):not(.brand) rect:not(:where([data-style="soft"],[data-style="soft"] *)){rx:0;ry:0}
386
+ :root:not([data-style="soft"]) :where([data-c],.tip,.kbx-k.ghost) svg:not(.i):not(.brand) :is(path,line,polyline,circle):not(:where([data-style="soft"],[data-style="soft"] *)){stroke-linecap:butt}
387
+ /* no blur anywhere: things wipe in or cut, they never soften */
388
+ :root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *)),:root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *))::before,:root:not([data-style="soft"]) :where([data-c],[data-c] *,.tip,.tip *,.kbx-k.ghost,.kbx-k.ghost *):not(:where([data-style="soft"],[data-style="soft"] *))::after{filter:none!important}
389
+
390
+ /* the sheet: cards share their hairlines, every stage is drafting paper with crop marks in the corners */
391
+ :root:not([data-style="soft"]) .seg2 .knob:not(:where([data-style="soft"],[data-style="soft"] *)){box-shadow:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent)}
392
+
393
+ /* parts: mono labels, hairline controls, hatched when disabled */
394
+ :root:not([data-style="soft"]) .tag:not(:where([data-style="soft"],[data-style="soft"] *)){font-size:10.5px;font-weight:500;letter-spacing:.03em;text-transform:uppercase;height:19px;padding:0 6px}
395
+ :root:not([data-style="soft"]) .kbd:not(:where([data-style="soft"],[data-style="soft"] *)){box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent)}
396
+ :root:not([data-style="soft"]) .pill.line:not(:where([data-style="soft"],[data-style="soft"] *)){box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent)}
397
+ @media (hover:hover) and (pointer:fine){:root:not([data-style="soft"]) .pill.line:hover:not(:where([data-style="soft"],[data-style="soft"] *)){background:var(--vo-wash);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-faint) 50%,transparent)}}
398
+ :root:not([data-style="soft"]) .pill:active:not(:where([data-style="soft"],[data-style="soft"] *)),:root:not([data-style="soft"]) .ib:active:not(:where([data-style="soft"],[data-style="soft"] *)){transform:translateY(1px)}
399
+ :root:not([data-style="soft"]) .chip.on:not(:where([data-style="soft"],[data-style="soft"] *)){box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-pick-on) 50%,transparent)}
400
+ :root:not([data-style="soft"]) .bub:not(:where([data-style="soft"],[data-style="soft"] *)){background:var(--vo-chip);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--vo-line) 50%,transparent)}
401
+ :root:not([data-style="soft"]) .tip:not(:where([data-style="soft"],[data-style="soft"] *)){box-shadow:none}
402
+
403
+ /* motion: a top-down wipe that settles on a hard ease, stepped loaders, a blinking cursor instead of a soft ping */
404
+ @keyframes bpin{0%{opacity:0;clip-path:inset(0 0 100% 0);transform:translateY(4px)}30%{opacity:1}100%{opacity:1;clip-path:inset(0 0 0 0);transform:none}}
405
+ @keyframes bpout{to{opacity:0;clip-path:inset(0 0 100% 0)}}
406
+ @keyframes bpblink{0%,55%{opacity:1}56%,100%{opacity:.2}}
407
+ :root:not([data-style="soft"]) .enter:not(:where([data-style="soft"],[data-style="soft"] *)),:root:not([data-style="soft"]) .pop-in:not(:where([data-style="soft"],[data-style="soft"] *)){animation-name:bpin;animation-duration:var(--vo-t-slow);animation-timing-function:var(--vo-ease);animation-fill-mode:backwards}
408
+ :root:not([data-style="soft"]) .leave:not(:where([data-style="soft"],[data-style="soft"] *)){animation:bpout .26s var(--vo-ease) both}
409
+ :root:not([data-style="soft"]) .chx-card.show:not(:where([data-style="soft"],[data-style="soft"] *)){animation:bpin .34s var(--vo-ease) backwards}
410
+ :root:not([data-style="soft"]) .sw.out:not(:where([data-style="soft"],[data-style="soft"] *)){transform:translateY(-3px)}
411
+ :root:not([data-style="soft"]) .pop:not(:where([data-style="soft"],[data-style="soft"] *)){transform:translateY(4px);transition-duration:.16s}
412
+ :root:not([data-style="soft"]) .pop.open:not(:where([data-style="soft"],[data-style="soft"] *)){transform:none}
413
+ :root:not([data-style="soft"]) .spin:not(:where([data-style="soft"],[data-style="soft"] *)){animation:rot .9s steps(8) infinite}
414
+ :root:not([data-style="soft"]) .radar:not(:where([data-style="soft"],[data-style="soft"] *))::after{animation:rot 1s steps(8) infinite}
415
+ :root:not([data-style="soft"]) .pulse:not(:where([data-style="soft"],[data-style="soft"] *)){animation:bpblink 1.1s steps(1,end) infinite}
416
+ :root:not([data-style="soft"]) .pulse:not(:where([data-style="soft"],[data-style="soft"] *))::after{display:none}
417
+ :root:not([data-style="soft"]) .btx-ask:not(:where([data-style="soft"],[data-style="soft"] *))::after{background:linear-gradient(90deg,transparent 0 40%,rgba(255,255,255,.38) 40% 46%,transparent 46%)}
418
+ @media (hover:hover) and (pointer:fine){:root:not([data-style="soft"]) .btx-ask:hover:not(:where([data-style="soft"],[data-style="soft"] *))::after{transition:transform .5s steps(10)}}
419
+ :root:not([data-style="soft"]) .btx-live:not(:where([data-style="soft"],[data-style="soft"] *))::after{display:none}
420
+ :root:not([data-style="soft"]) .btx-live:not(:where([data-style="soft"],[data-style="soft"] *)){animation:bpblink 1.1s steps(1,end) infinite}
421
+
422
+ /* a component card: the template renders into .stage-in */
423
+ [data-c]{width:440px;max-width:100%;font-family:var(--vo-sans);font-size:14px;line-height:1.5;color:var(--vo-fg);-webkit-font-smoothing:antialiased}
424
+ [data-c].wide{width:720px}
@@ -0,0 +1,61 @@
1
+ import { EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
+ import { type VoIconName } from '../core/icon.component';
3
+ import { ReducedMotionService } from '../core/reduced-motion.service';
4
+ import * as i0 from "@angular/core";
5
+ /** Any value a tool takes or returns. */
6
+ export type Json = string | number | boolean | null | Json[] | {
7
+ [key: string]: Json;
8
+ };
9
+ /** The lifecycle of one call: queued waits, running spins, done shows its result. */
10
+ export type ToolCallState = 'queued' | 'running' | 'done';
11
+ /** One tool the agent called. */
12
+ export interface ToolCallItem {
13
+ key: string;
14
+ /** The tool's server or namespace, like "billing". */
15
+ server?: string;
16
+ /** The tool's name, like "list_plan_changes". */
17
+ name: string;
18
+ /** The icon in front of the call. */
19
+ icon?: VoIconName;
20
+ /** queued waits, running spins, done shows the time it took and the output. */
21
+ state: ToolCallState;
22
+ /** How long it took, like "412 ms". Shown once it is done. */
23
+ duration?: string;
24
+ /** What the agent sent, shown as highlighted JSON. */
25
+ input?: Json;
26
+ /** What came back, shown once it is done. */
27
+ output?: Json;
28
+ }
29
+ export declare class ToolCallComponent implements OnChanges, OnDestroy {
30
+ /** The agent's message before the calls. */
31
+ message?: string | null;
32
+ /** The tools the agent called. */
33
+ calls: ToolCallItem[];
34
+ /** The agent's answer after the calls. It fades in once every call is done. */
35
+ reply?: string | null;
36
+ /** Keys of the calls that are open. Leave it out to let each call toggle itself. */
37
+ open?: string[];
38
+ /** The calls open at first when `open` is not controlled. */
39
+ defaultOpen: string[];
40
+ /** Emitted with the new set of open keys whenever a call is toggled. */
41
+ openChange: EventEmitter<string[]>;
42
+ readonly motion: ReducedMotionService;
43
+ /** The reply is laid out from the start and fades in a frame after the last call finishes. */
44
+ shown: boolean;
45
+ private openKeys;
46
+ private raf?;
47
+ ngOnChanges(changes: SimpleChanges): void;
48
+ private get done();
49
+ private updateShown;
50
+ isOpen(key: string): boolean;
51
+ toggle(key: string): void;
52
+ /** The status text swapped in the row: the duration once done, else the state. */
53
+ label(call: ToolCallItem): string;
54
+ /** Renders a JSON value as the same coloured HTML the Vanilla/React port shows. */
55
+ jsonHtml(value: Json): string;
56
+ private parts;
57
+ private esc;
58
+ ngOnDestroy(): void;
59
+ static ɵfac: i0.ɵɵFactoryDeclaration<ToolCallComponent, never>;
60
+ static ɵcmp: i0.ɵɵComponentDeclaration<ToolCallComponent, "vo-tool-call", never, { "message": { "alias": "message"; "required": false; }; "calls": { "alias": "calls"; "required": false; }; "reply": { "alias": "reply"; "required": false; }; "open": { "alias": "open"; "required": false; }; "defaultOpen": { "alias": "defaultOpen"; "required": false; }; }, { "openChange": "openChange"; }, never, never, true, never>;
61
+ }
@@ -0,0 +1,89 @@
1
+ import { AfterViewInit, ElementRef, OnDestroy } from '@angular/core';
2
+ import { type VoIconName } from '../core/icon.component';
3
+ import * as i0 from "@angular/core";
4
+ export interface TooltipTool {
5
+ key: string;
6
+ icon: VoIconName;
7
+ /** The button's name, read out by screen readers. */
8
+ label: string;
9
+ /** The tooltip, when it should say more than the name. Defaults to the label. */
10
+ tip?: string;
11
+ /** A shortcut shown after the tip, like "⌘Z". */
12
+ kbd?: string;
13
+ onClick?: () => void;
14
+ }
15
+ export interface TooltipPerson {
16
+ key: string;
17
+ initials: string;
18
+ /** The avatar's colour, like 'var(--vo-av-l)'. */
19
+ color: string;
20
+ name: string;
21
+ /** The quiet line under the name, like "Design lead". */
22
+ role: string;
23
+ /** What they are doing now, like "Editing Pricing, frame 2". */
24
+ status: string;
25
+ /** Shows the agent's thinking dots instead of the green dot. */
26
+ working?: boolean;
27
+ }
28
+ interface TipAt {
29
+ x: number;
30
+ y: number;
31
+ label: string;
32
+ kbd?: string;
33
+ }
34
+ interface CardAt {
35
+ person: TooltipPerson;
36
+ left: number;
37
+ top: number;
38
+ }
39
+ /** A toolbar whose labels follow the pointer between buttons, with a richer card for people. */
40
+ export declare class TooltipComponent implements AfterViewInit, OnDestroy {
41
+ /** The toolbar's buttons, in groups with a line between them. */
42
+ groups: TooltipTool[][];
43
+ /** Avatars at the end of the toolbar; hovering one shows a card. */
44
+ people: TooltipPerson[];
45
+ /** A quiet line under the toolbar. */
46
+ note?: string;
47
+ /** How long the person card waits before it shows. */
48
+ cardDelay: number;
49
+ private _openTip;
50
+ private _openCard;
51
+ /** Shows this tool's tip, by key, as if it were hovered. */
52
+ set openTip(key: string | null | undefined);
53
+ get openTip(): string | null | undefined;
54
+ /** Shows this person's card, by key, as if they were hovered. */
55
+ set openCard(key: string | null | undefined);
56
+ get openCard(): string | null | undefined;
57
+ root: ElementRef<HTMLDivElement>;
58
+ tipEl: ElementRef<HTMLDivElement>;
59
+ tipAt: TipAt | null;
60
+ tipShow: boolean;
61
+ card: CardAt | null;
62
+ cardShow: boolean;
63
+ private tipTimer?;
64
+ private cardTimer?;
65
+ private tipOverKey;
66
+ private cardOverKey;
67
+ private ready;
68
+ ink(color: string): string | undefined;
69
+ ngAfterViewInit(): void;
70
+ openTipFor(t: TooltipTool, e: Event): void;
71
+ focusTip(t: TooltipTool, e: FocusEvent): void;
72
+ leaveTip(): void;
73
+ private showTip;
74
+ private placeTip;
75
+ private hideTip;
76
+ private applyOpenTip;
77
+ private buttonFor;
78
+ openCardFor(person: TooltipPerson, e: Event): void;
79
+ focusCard(person: TooltipPerson, e: FocusEvent): void;
80
+ leaveCard(): void;
81
+ private openCardAt;
82
+ closeCard(): void;
83
+ private applyOpenCard;
84
+ private avatarFor;
85
+ ngOnDestroy(): void;
86
+ static ɵfac: i0.ɵɵFactoryDeclaration<TooltipComponent, never>;
87
+ static ɵcmp: i0.ɵɵComponentDeclaration<TooltipComponent, "vo-tooltip", never, { "groups": { "alias": "groups"; "required": false; }; "people": { "alias": "people"; "required": false; }; "note": { "alias": "note"; "required": false; }; "cardDelay": { "alias": "cardDelay"; "required": false; }; "openTip": { "alias": "openTip"; "required": false; }; "openCard": { "alias": "openCard"; "required": false; }; }, {}, never, never, true, never>;
88
+ }
89
+ export {};