@mosetta/editor 0.0.0-stage → 0.0.28

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 (115) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/LICENSE +21 -0
  3. package/README.md +10 -2
  4. package/mosetta.json +6 -0
  5. package/package.json +35 -3
  6. package/prefabs/workbench/prefab.json +11 -0
  7. package/prefabs/workbench/versions/1.json +120 -0
  8. package/prefabs/workbench/versions/2.json +13 -0
  9. package/prefabs/workbench/versions/3.json +19 -0
  10. package/prefabs/workbench/versions/4.json +29 -0
  11. package/prefabs/workbench/versions/5.json +29 -0
  12. package/tiles/canvas/canvas.component.tsx +2038 -0
  13. package/tiles/canvas/canvas.css +973 -0
  14. package/tiles/canvas/canvasTools.ts +66 -0
  15. package/tiles/canvas/chromeNodes.ts +35 -0
  16. package/tiles/canvas/ghosts.ts +33 -0
  17. package/tiles/canvas/insertPopover.tsx +56 -0
  18. package/tiles/canvas/popoverPlacement.ts +104 -0
  19. package/tiles/canvas/popoverSize.ts +87 -0
  20. package/tiles/canvas/providerChrome.tsx +191 -0
  21. package/tiles/canvas/scrollWatch.ts +43 -0
  22. package/tiles/canvas/settingsPopover.tsx +257 -0
  23. package/tiles/canvas/settingsTabs.ts +78 -0
  24. package/tiles/canvas/toolPanel.tsx +86 -0
  25. package/tiles/content/autoBind.ts +61 -0
  26. package/tiles/content/blockPage.css +390 -0
  27. package/tiles/content/blockPage.tsx +379 -0
  28. package/tiles/content/blockPicker.css +215 -0
  29. package/tiles/content/blockPicker.tsx +501 -0
  30. package/tiles/content/blockUpgrades.ts +145 -0
  31. package/tiles/content/blockVariants.ts +185 -0
  32. package/tiles/content/blockVocabulary.ts +77 -0
  33. package/tiles/content/catalogVersions.ts +106 -0
  34. package/tiles/content/componentPreview.css +82 -0
  35. package/tiles/content/componentPreview.tsx +249 -0
  36. package/tiles/content/content.server.ts +593 -0
  37. package/tiles/content/contentCommon.ts +133 -0
  38. package/tiles/content/disconnected.ts +56 -0
  39. package/tiles/content/distributions.css +256 -0
  40. package/tiles/content/distributions.tsx +271 -0
  41. package/tiles/content/editingAutosave.ts +125 -0
  42. package/tiles/content/editingClipboard.ts +185 -0
  43. package/tiles/content/editingConflicts.ts +223 -0
  44. package/tiles/content/editingHotkeys.ts +59 -0
  45. package/tiles/content/editingNotices.ts +105 -0
  46. package/tiles/content/formRoot.ts +18 -0
  47. package/tiles/content/fuzzySearch.ts +121 -0
  48. package/tiles/content/mediaUpload.ts +55 -0
  49. package/tiles/content/moduleSiblings.ts +9 -0
  50. package/tiles/content/mountedTree.ts +136 -0
  51. package/tiles/content/nodeSettings.css +483 -0
  52. package/tiles/content/nodeSettings.tsx +963 -0
  53. package/tiles/content/pasteText.ts +131 -0
  54. package/tiles/content/prefabFields.tsx +158 -0
  55. package/tiles/content/prefabParts.ts +105 -0
  56. package/tiles/content/previewEnvironment.ts +46 -0
  57. package/tiles/content/projectConfig.ts +46 -0
  58. package/tiles/content/projectPrefabs.ts +57 -0
  59. package/tiles/content/publishModal.css +109 -0
  60. package/tiles/content/publishModal.tsx +92 -0
  61. package/tiles/content/refsEditing.ts +412 -0
  62. package/tiles/content/scaledStage.ts +63 -0
  63. package/tiles/content/searchField.css +32 -0
  64. package/tiles/content/searchField.tsx +32 -0
  65. package/tiles/content/settingsDraft.ts +178 -0
  66. package/tiles/content/settingsIssues.tsx +124 -0
  67. package/tiles/content/themeScope.ts +72 -0
  68. package/tiles/content/themeVariables.ts +47 -0
  69. package/tiles/content/tooltipPlacement.ts +17 -0
  70. package/tiles/content/tooltips.tsx +131 -0
  71. package/tiles/content/treeMounter.ts +33 -0
  72. package/tiles/content/updatesModal.css +124 -0
  73. package/tiles/content/updatesModal.tsx +110 -0
  74. package/tiles/content/useCtrlHeld.ts +24 -0
  75. package/tiles/content/useEditingSession.ts +115 -0
  76. package/tiles/content/useMountedTree.ts +47 -0
  77. package/tiles/content/workbenchScale.css +27 -0
  78. package/tiles/hostFallback/hostFallback.component.tsx +32 -0
  79. package/tiles/hostFallback/hostFallback.css +12 -0
  80. package/tiles/hostFallback/hostFallback.editor.tsx +10 -0
  81. package/tiles/page/page.component.tsx +7 -0
  82. package/tiles/page/page.script.tsx +5 -0
  83. package/tiles/pageModules/pageModules.component.tsx +740 -0
  84. package/tiles/pageModules/pageModules.css +383 -0
  85. package/tiles/pageModules/pageModules.icon.svg +1 -0
  86. package/tiles/pageModules/servedPage.ts +465 -0
  87. package/tiles/pagesPanel/pagesPanel.component.tsx +1645 -0
  88. package/tiles/pagesPanel/pagesPanel.css +713 -0
  89. package/tiles/pagesPanel/pagesPanel.editor.tsx +23 -0
  90. package/tiles/pagesPanel/pagesSearch.ts +194 -0
  91. package/tiles/pagesPanel/routeTree.ts +98 -0
  92. package/tiles/previewBridge/landing.ts +66 -0
  93. package/tiles/previewBridge/previewAgent.ts +457 -0
  94. package/tiles/previewBridge/previewBridge.component.tsx +137 -0
  95. package/tiles/previewBridge/previewBridge.editor.tsx +10 -0
  96. package/tiles/previewBridge/previewBridgeCommon.ts +172 -0
  97. package/tiles/previewBridge/standIn.ts +22 -0
  98. package/tiles/treeView/treeView.component.tsx +514 -0
  99. package/tiles/treeView/treeView.css +303 -0
  100. package/tiles/treeView/treeView.editor.tsx +12 -0
  101. package/tiles/workbench/assistant.css +401 -0
  102. package/tiles/workbench/assistant.tsx +516 -0
  103. package/tiles/workbench/assistantChat.ts +165 -0
  104. package/tiles/workbench/dictation.ts +354 -0
  105. package/tiles/workbench/projectInfo.ts +72 -0
  106. package/tiles/workbench/recent.ts +67 -0
  107. package/tiles/workbench/workbench.component.tsx +476 -0
  108. package/tiles/workbench/workbench.css +376 -0
  109. package/tiles/workbench/workbenchAddress.ts +202 -0
  110. package/tiles/workbench/workspace.ts +775 -0
  111. package/tiles/workbenchEditor/workbenchEditor.component.tsx +461 -0
  112. package/tiles/workbenchEditor/workbenchEditor.css +370 -0
  113. package/tiles/workbenchHome/workbenchHome.component.tsx +196 -0
  114. package/tiles/workbenchHome/workbenchHome.css +271 -0
  115. package/tsconfig.json +3 -0
@@ -0,0 +1,303 @@
1
+ /* A FLEX column on purpose: flex items never collapse margins. The move zones are zero-net
2
+ (22px padding against -22px margins), but wherever two zones end up adjacent — a nested
3
+ section's end meeting the parent's next gap — collapsed block margins gave -11 instead of
4
+ -22, and the tree grew 11px per boundary the moment the mode rendered them. */
5
+ .tree-view {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: stretch;
9
+ font: var(--mosetta-wb-font)/1.5 ui-sans-serif, system-ui, sans-serif;
10
+ }
11
+
12
+ .tree-view__empty {
13
+ color: #71717a;
14
+ padding: 12px;
15
+ }
16
+
17
+ .tree-view__header {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: 8px;
21
+ padding: 6px 8px;
22
+ border-bottom: 1px solid #e4e4e7;
23
+ font-weight: 600;
24
+ }
25
+
26
+ .tree-view__dirty {
27
+ color: #dc2626;
28
+ }
29
+
30
+ .tree-view__save {
31
+ margin-left: auto;
32
+ cursor: pointer;
33
+ }
34
+
35
+ .tree-view__node {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 6px;
39
+ padding: 3px 8px;
40
+ cursor: pointer;
41
+ border-radius: 4px;
42
+ }
43
+
44
+ /* hover on every row — a shade lighter than the selection, so pointing never reads as picking.
45
+ Guarded on the stateful rows: :hover outweighs a single state class by specificity, and a
46
+ selected/picked row must not flicker lighter under the pointer */
47
+ .tree-view__node:hover {
48
+ background: #f4f4f5;
49
+ }
50
+
51
+ /* the inspector's hover, echoed: pointing at a block in ANY canvas washes its row a pale blue —
52
+ quieter than the selection, gone the moment the pointer moves on */
53
+ .tree-view__node--hovered {
54
+ background: #eff6ff;
55
+ }
56
+
57
+ .tree-view__node--selected,
58
+ .tree-view__node--selected:hover {
59
+ background: #e4e4e7;
60
+ }
61
+
62
+ /* The Ctrl (multi) mode wears YELLOW, here as in the canvas — the whole picked branch lights up.
63
+ No radius: adjacent picked rows must read as ONE band, not an accordion of pills */
64
+ .tree-view__node--multi,
65
+ .tree-view__node--multi:hover {
66
+ background: #fef08a;
67
+ border-radius: 0;
68
+ }
69
+
70
+ /* Ctrl held: pointing at a row promises the yellow pick, the way ctrl-hover does in the canvas */
71
+ .tree-view--ctrl .tree-view__node:hover {
72
+ background: #fef9c3;
73
+ }
74
+
75
+ .tree-view--ctrl .tree-view__node--multi:hover {
76
+ background: #fde047;
77
+ }
78
+
79
+ .tree-view--ctrl .tree-view__slot:hover {
80
+ background: #fef9c3;
81
+ }
82
+
83
+ .tree-view--ctrl .tree-view__slot--multi:hover {
84
+ background: #fde047;
85
+ }
86
+
87
+ /* a block of a DISCONNECTED distribution: still in the page, left out by the site — its name
88
+ struck through, a small amber "off" beside it (disconnected.ts) */
89
+ .tree-view__node--off .tree-view__label {
90
+ color: #a1a1aa;
91
+ text-decoration: line-through;
92
+ }
93
+
94
+ .tree-view__off {
95
+ flex: none;
96
+ padding: 0 5px;
97
+ border-radius: 3px;
98
+ background: #fef3c7;
99
+ color: #92400e;
100
+ font-size: var(--mosetta-wb-font-xs);
101
+ line-height: 16px;
102
+ }
103
+
104
+ /* a block with a newer version (ADR-0061): its row names it, quietly blue */
105
+ .tree-view__up {
106
+ flex: none;
107
+ padding: 0 5px;
108
+ border-radius: 3px;
109
+ background: #dbeafe;
110
+ color: #1d4ed8;
111
+ font-size: var(--mosetta-wb-font-xs);
112
+ line-height: 16px;
113
+ }
114
+
115
+ /* a slot's section title (the default one included) — the children under it live in that slot.
116
+ Not a node, but a DOOR and a selectable one: plain click selects it, Ctrl passes to children */
117
+ .tree-view__slot {
118
+ color: #a1a1aa;
119
+ font-size: var(--mosetta-wb-font-xs);
120
+ padding: 2px 8px;
121
+ letter-spacing: 0.02em;
122
+ border-radius: 4px;
123
+ cursor: pointer;
124
+ }
125
+
126
+ .tree-view__slot:hover {
127
+ background: #f4f4f5;
128
+ }
129
+
130
+ .tree-view__slot--multi,
131
+ .tree-view__slot--multi:hover {
132
+ background: #fef08a;
133
+ border-radius: 0;
134
+ }
135
+
136
+ /* the slot IS the selection — same gray the selected node row wears */
137
+ .tree-view__slot--selected,
138
+ .tree-view__slot--selected:hover {
139
+ background: #e4e4e7;
140
+ color: #3f3f46;
141
+ }
142
+
143
+
144
+ /* the fold chevron before a row with something inside; a leaf keeps its room so labels line up */
145
+ .tree-view__fold {
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ flex: none;
150
+ width: var(--mosetta-wb-icon-sm);
151
+ height: var(--mosetta-wb-icon-sm);
152
+ margin-left: -2px;
153
+ padding: 0;
154
+ border: 0;
155
+ border-radius: 3px;
156
+ background: none;
157
+ color: #a1a1aa;
158
+ cursor: pointer;
159
+ }
160
+
161
+ .tree-view__fold svg {
162
+ width: var(--mosetta-wb-icon-sm);
163
+ height: var(--mosetta-wb-icon-sm);
164
+ transform: rotate(90deg);
165
+ transition: transform 120ms ease;
166
+ }
167
+
168
+ .tree-view__fold[data-folded] svg {
169
+ transform: none;
170
+ }
171
+
172
+ .tree-view__fold:hover {
173
+ color: #27272a;
174
+ background: #e4e4e7;
175
+ }
176
+
177
+ .tree-view__fold--none {
178
+ pointer-events: none;
179
+ }
180
+
181
+ /* row actions (move + remove) stay out of sight until the row is under the pointer (or a button
182
+ is keyboard-focused — hover must not be the only way to reach them) */
183
+ .tree-view__row-actions {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 2px;
187
+ margin-left: auto;
188
+ opacity: 0;
189
+ pointer-events: none;
190
+ }
191
+
192
+ .tree-view__node:hover .tree-view__row-actions,
193
+ .tree-view__row-actions:focus-within {
194
+ opacity: 1;
195
+ pointer-events: auto;
196
+ }
197
+
198
+ .tree-view__move,
199
+ .tree-view__remove {
200
+ display: flex;
201
+ align-items: center;
202
+ border: 0;
203
+ background: none;
204
+ cursor: pointer;
205
+ color: #a1a1aa;
206
+ padding: 1px;
207
+ }
208
+
209
+ .tree-view__move svg {
210
+ width: var(--mosetta-wb-icon-sm);
211
+ height: var(--mosetta-wb-icon-sm);
212
+ }
213
+
214
+ /* purple is the MOVE colour, everywhere the mode shows */
215
+ .tree-view__move:hover {
216
+ color: #8b5cf6;
217
+ }
218
+
219
+ .tree-view__remove:hover {
220
+ color: #dc2626;
221
+ }
222
+
223
+ /* The MOVE mode: rows stop being targets — the GAPS between them take over. A zone is flat in
224
+ the flow but its hit area reaches halfway into both neighbouring rows (padding + negative
225
+ margins), so "hovering between the centres of two rows" is literal. */
226
+ .tree-view--move .tree-view__node,
227
+ .tree-view--move .tree-view__slot {
228
+ cursor: default;
229
+ }
230
+
231
+ .tree-view--move .tree-view__node:hover,
232
+ .tree-view--move .tree-view__slot:hover {
233
+ background: none;
234
+ }
235
+
236
+ /* the travelling branch wears the mode's colour */
237
+ .tree-view__node--moving,
238
+ .tree-view--move .tree-view__node--moving:hover {
239
+ background: #ede9fe;
240
+ }
241
+
242
+ .tree-view__move-zone {
243
+ position: relative;
244
+ z-index: 1;
245
+ display: flex;
246
+ align-items: center;
247
+ height: 0;
248
+ padding: 11px 0;
249
+ margin: -11px 0;
250
+ }
251
+
252
+ /* the SKEWER: a hairline runs the whole gap — exactly between the two rows — and the tip sits
253
+ ON it (the line is behind, the tip's own background keeps its letters clean) */
254
+ .tree-view__move-zone:hover::before {
255
+ content: '';
256
+ position: absolute;
257
+ top: 50%;
258
+ right: 4px;
259
+ left: var(--skewer-left, 8px);
260
+ height: 2px;
261
+ margin-top: -1px;
262
+ border-radius: 1px;
263
+ background: #8b5cf6;
264
+ }
265
+
266
+ .tree-view__move-tip {
267
+ position: relative;
268
+ display: none;
269
+ margin-left: auto;
270
+ margin-right: 12px;
271
+ padding: 1px 6px;
272
+ border-radius: 3px;
273
+ background: #8b5cf6;
274
+ color: #ffffff;
275
+ font-size: calc(var(--mosetta-wb-font-2xs) - 1px);
276
+ line-height: 12px;
277
+ cursor: pointer;
278
+ }
279
+
280
+ .tree-view__move-zone:hover .tree-view__move-tip {
281
+ display: inline-block;
282
+ }
283
+
284
+ /* …and the tip itself answers the pointer: a shade deeper right before the click */
285
+ .tree-view__move-tip:hover {
286
+ background: #7c3aed;
287
+ }
288
+
289
+ .tree-view__error {
290
+ color: #dc2626;
291
+ padding: 4px 8px;
292
+ }
293
+
294
+ /* a PREFAB's own blocks under its node: seen, not changed — quieter than the page's; a click on
295
+ one selects it to be seen, read-only (prefabParts.ts) */
296
+ .tree-view__node--prefab {
297
+ color: #a1a1aa;
298
+ font-style: italic;
299
+ }
300
+
301
+ .tree-view__node--prefab.tree-view__node--selected {
302
+ color: #52525b;
303
+ }
@@ -0,0 +1,12 @@
1
+ import { defineEditorSide } from '@mosetta/react';
2
+ import { PreviewEditingSession } from '../content/previewEnvironment';
3
+
4
+ export default defineEditorSide({
5
+ // the REAL panel is the preview: its environment is arranged — a session seeded with a small
6
+ // page to outline — and the component itself never knows it is being looked at
7
+ preview: 'self',
8
+ previewServices: [PreviewEditingSession],
9
+ Component() {
10
+ return <div data-no-settings>This panel has no settings.</div>;
11
+ },
12
+ });
@@ -0,0 +1,401 @@
1
+ /* The assistant: a column on the right of the workbench, the full height of it. */
2
+ /* The assistant: an island over the workbench, never a column taking its room. */
3
+ .assistant {
4
+ position: absolute;
5
+ z-index: 60;
6
+ display: flex;
7
+ flex-direction: column;
8
+ box-sizing: border-box;
9
+ min-height: 0;
10
+ border: 1px solid var(--wb-border, #e4e4e7);
11
+ border-radius: 14px;
12
+ background: #fafafa;
13
+ box-shadow: 0 12px 36px rgb(24 24 27 / 16%), 0 2px 6px rgb(24 24 27 / 8%);
14
+ }
15
+
16
+ /* over Home and the lists: at the bottom, in the middle — the page stays in sight above it */
17
+ .assistant--bottom {
18
+ left: 50%;
19
+ bottom: 16px;
20
+ width: min(760px, calc(100% - 32px));
21
+ max-height: min(62%, 600px);
22
+ transform: translateX(-50%);
23
+ }
24
+
25
+ /* in the editor: over the tree — the tree's column takes the island's width while it is open (the
26
+ tree hidden under it), so the canvas beside it stays whole */
27
+ .workbench {
28
+ --assistant-tree: 360px;
29
+ }
30
+
31
+ .assistant--tree {
32
+ top: 46px;
33
+ bottom: 10px;
34
+ left: 8px;
35
+ width: calc(var(--assistant-tree) - 16px);
36
+ }
37
+
38
+ .workbench[data-assistant="tree"] .workbench__tree {
39
+ display: block !important;
40
+ width: var(--assistant-tree) !important;
41
+ }
42
+
43
+ .workbench[data-assistant="tree"] .workbench__splitter {
44
+ display: none;
45
+ }
46
+
47
+ .assistant--folded .assistant__head {
48
+ border-bottom: 0;
49
+ }
50
+
51
+ .assistant__head {
52
+ display: flex;
53
+ flex: none;
54
+ align-items: center;
55
+ gap: 6px;
56
+ padding: 8px 10px 8px 14px;
57
+ border-bottom: 1px solid var(--wb-border, #e4e4e7);
58
+ }
59
+
60
+ .assistant__title {
61
+ flex: 1;
62
+ font-weight: 600;
63
+ }
64
+
65
+ .assistant__cost {
66
+ color: var(--wb-muted, #71717a);
67
+ font-size: 0.85em;
68
+ font-variant-numeric: tabular-nums;
69
+ }
70
+
71
+ .assistant__head-button {
72
+ padding: 3px 8px;
73
+ border: 1px solid transparent;
74
+ border-radius: 6px;
75
+ background: none;
76
+ color: var(--wb-muted, #71717a);
77
+ font: inherit;
78
+ cursor: pointer;
79
+ }
80
+
81
+ .assistant__head-button:hover:not(:disabled) {
82
+ border-color: var(--wb-border, #e4e4e7);
83
+ background: #ffffff;
84
+ color: var(--wb-ink, #18181b);
85
+ }
86
+
87
+ .assistant__head-button:disabled {
88
+ opacity: 0.4;
89
+ cursor: default;
90
+ }
91
+
92
+ /* ---- the conversation ------------------------------------------------------------------------ */
93
+
94
+ .assistant__list {
95
+ display: flex;
96
+ flex: 1;
97
+ flex-direction: column;
98
+ gap: 8px;
99
+ min-height: 0;
100
+ padding: 12px;
101
+ overflow-y: auto;
102
+ }
103
+
104
+ .assistant__user {
105
+ align-self: flex-end;
106
+ max-width: 85%;
107
+ padding: 7px 10px;
108
+ border-radius: 10px 10px 2px;
109
+ background: var(--wb-blue, #2563eb);
110
+ color: #ffffff;
111
+ white-space: pre-wrap;
112
+ overflow-wrap: anywhere;
113
+ }
114
+
115
+ .assistant__reply {
116
+ white-space: pre-wrap;
117
+ overflow-wrap: anywhere;
118
+ }
119
+
120
+ .assistant__reply a {
121
+ color: var(--wb-blue, #2563eb);
122
+ }
123
+
124
+ .assistant__reply code {
125
+ padding: 1px 4px;
126
+ border-radius: 4px;
127
+ background: #ececef;
128
+ font: 0.92em ui-monospace, SFMono-Regular, Menlo, monospace;
129
+ }
130
+
131
+ .assistant__tool {
132
+ border: 1px solid var(--wb-border, #e4e4e7);
133
+ border-radius: 7px;
134
+ background: #ffffff;
135
+ font-size: 0.92em;
136
+ }
137
+
138
+ .assistant__tool summary {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 7px;
142
+ padding: 5px 8px;
143
+ color: var(--wb-muted, #71717a);
144
+ cursor: pointer;
145
+ list-style: none;
146
+ }
147
+
148
+ .assistant__tool summary::-webkit-details-marker {
149
+ display: none;
150
+ }
151
+
152
+ .assistant__tool-mark {
153
+ display: inline-flex;
154
+ justify-content: center;
155
+ width: 14px;
156
+ color: #16a34a;
157
+ }
158
+
159
+ .assistant__tool--failed .assistant__tool-mark {
160
+ color: #dc2626;
161
+ }
162
+
163
+ .assistant__tool-summary {
164
+ overflow: hidden;
165
+ text-overflow: ellipsis;
166
+ white-space: nowrap;
167
+ }
168
+
169
+ .assistant__tool-result {
170
+ max-height: 220px;
171
+ margin: 0;
172
+ padding: 6px 8px;
173
+ border-top: 1px solid var(--wb-border, #e4e4e7);
174
+ overflow: auto;
175
+ font: 11px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
176
+ white-space: pre-wrap;
177
+ overflow-wrap: anywhere;
178
+ }
179
+
180
+ /* the screenshots a tool took: small, side by side, each opening whole */
181
+ .assistant__pictures {
182
+ display: flex;
183
+ gap: 6px;
184
+ margin-top: -2px;
185
+ }
186
+
187
+ .assistant__pictures a {
188
+ display: block;
189
+ flex: 0 1 auto;
190
+ max-width: 50%;
191
+ border: 1px solid var(--wb-border, #e4e4e7);
192
+ border-radius: 6px;
193
+ overflow: hidden;
194
+ background: #ffffff;
195
+ }
196
+
197
+ .assistant__pictures img {
198
+ display: block;
199
+ max-width: 100%;
200
+ max-height: 120px;
201
+ object-fit: cover;
202
+ object-position: top;
203
+ }
204
+
205
+ .assistant__spinner {
206
+ width: 10px;
207
+ height: 10px;
208
+ border: 2px solid #d4d4d8;
209
+ border-top-color: var(--wb-blue, #2563eb);
210
+ border-radius: 50%;
211
+ animation: assistant-spin 0.8s linear infinite;
212
+ }
213
+
214
+ @keyframes assistant-spin {
215
+ to {
216
+ transform: rotate(360deg);
217
+ }
218
+ }
219
+
220
+ .assistant__error {
221
+ padding: 7px 10px;
222
+ border-radius: 7px;
223
+ background: #fef2f2;
224
+ color: #b91c1c;
225
+ }
226
+
227
+ .assistant__thinking {
228
+ color: var(--wb-muted, #71717a);
229
+ }
230
+
231
+ .assistant__empty {
232
+ display: flex;
233
+ flex-direction: column;
234
+ gap: 8px;
235
+ color: var(--wb-muted, #71717a);
236
+ }
237
+
238
+ .assistant__empty p {
239
+ margin: 0 0 4px;
240
+ }
241
+
242
+ .assistant__suggestion {
243
+ padding: 7px 10px;
244
+ border: 1px solid var(--wb-border, #e4e4e7);
245
+ border-radius: 7px;
246
+ background: #ffffff;
247
+ color: var(--wb-ink, #18181b);
248
+ font: inherit;
249
+ text-align: left;
250
+ cursor: pointer;
251
+ }
252
+
253
+ .assistant__suggestion:hover {
254
+ border-color: var(--wb-blue, #2563eb);
255
+ }
256
+
257
+ /* ---- the composer ---------------------------------------------------------------------------- */
258
+
259
+ .assistant__composer {
260
+ padding: 8px 10px 10px;
261
+ }
262
+
263
+ .assistant__field {
264
+ display: flex;
265
+ align-items: flex-end;
266
+ gap: 6px;
267
+ padding: 6px 6px 6px 10px;
268
+ border: 1px solid var(--wb-border, #e4e4e7);
269
+ border-radius: 12px;
270
+ background: #ffffff;
271
+ }
272
+
273
+ .assistant__field:focus-within {
274
+ border-color: var(--wb-blue, #2563eb);
275
+ box-shadow: 0 0 0 3px rgb(37 99 235 / 12%);
276
+ }
277
+
278
+ .assistant__field--listening {
279
+ border-color: #dc2626;
280
+ box-shadow: 0 0 0 3px rgb(220 38 38 / 12%);
281
+ }
282
+
283
+ /* grows with what is written (set from the panel), never dragged by a corner */
284
+ .assistant__input {
285
+ flex: 1;
286
+ box-sizing: border-box;
287
+ min-height: 30px;
288
+ max-height: 168px;
289
+ padding: 5px 0;
290
+ border: 0;
291
+ outline: none;
292
+ background: transparent;
293
+ font: inherit;
294
+ line-height: 1.45;
295
+ resize: none;
296
+ }
297
+
298
+ .assistant__actions {
299
+ display: flex;
300
+ flex: none;
301
+ align-items: center;
302
+ gap: 4px;
303
+ }
304
+
305
+ .assistant__icon {
306
+ display: inline-flex;
307
+ align-items: center;
308
+ justify-content: center;
309
+ width: 30px;
310
+ height: 30px;
311
+ padding: 0;
312
+ border: 0;
313
+ border-radius: 9px;
314
+ background: none;
315
+ color: var(--wb-muted, #71717a);
316
+ cursor: pointer;
317
+ }
318
+
319
+ .assistant__icon svg {
320
+ width: 16px;
321
+ height: 16px;
322
+ }
323
+
324
+ .assistant__icon:hover:not(:disabled) {
325
+ background: #f1f1f3;
326
+ color: var(--wb-ink, #18181b);
327
+ }
328
+
329
+ .assistant__icon--on,
330
+ .assistant__icon--on:hover:not(:disabled) {
331
+ background: #fef2f2;
332
+ color: #dc2626;
333
+ }
334
+
335
+ .assistant__icon--send,
336
+ .assistant__icon--send:hover:not(:disabled) {
337
+ background: var(--wb-blue, #2563eb);
338
+ color: #ffffff;
339
+ }
340
+
341
+ .assistant__icon:disabled {
342
+ opacity: 0.35;
343
+ cursor: default;
344
+ }
345
+
346
+ /* how long the recording runs — in place of the language switch, which the platform needs not */
347
+ .assistant__clock {
348
+ padding: 2px 4px;
349
+ color: #dc2626;
350
+ font: 600 10px/1.4 ui-sans-serif, system-ui, sans-serif;
351
+ font-variant-numeric: tabular-nums;
352
+ }
353
+
354
+ .assistant__lang {
355
+ padding: 2px 5px;
356
+ border: 0;
357
+ border-radius: 6px;
358
+ background: none;
359
+ color: var(--wb-muted, #71717a);
360
+ font: 600 10px/1.4 ui-sans-serif, system-ui, sans-serif;
361
+ letter-spacing: 0.04em;
362
+ cursor: pointer;
363
+ }
364
+
365
+ .assistant__lang:hover {
366
+ background: #f1f1f3;
367
+ color: var(--wb-ink, #18181b);
368
+ }
369
+
370
+ .assistant__hint {
371
+ margin: 6px 4px 0;
372
+ color: var(--wb-muted, #71717a);
373
+ font-size: 0.86em;
374
+ }
375
+
376
+ /* ---- the workbench while the assistant works: frozen, its work showing through ---------------- */
377
+
378
+ .workbench__main {
379
+ position: relative;
380
+ }
381
+
382
+ .workbench__frozen {
383
+ position: absolute;
384
+ inset: 0;
385
+ z-index: 50;
386
+ display: flex;
387
+ align-items: flex-start;
388
+ justify-content: center;
389
+ padding-top: 14px;
390
+ background: rgb(255 255 255 / 18%);
391
+ cursor: progress;
392
+ }
393
+
394
+ .workbench__frozen-note {
395
+ padding: 5px 12px;
396
+ border-radius: 999px;
397
+ background: var(--wb-ink, #18181b);
398
+ color: #ffffff;
399
+ font-size: 0.92em;
400
+ box-shadow: 0 4px 14px rgb(0 0 0 / 18%);
401
+ }