@artooi/ag-ui-web-component 0.20.1 → 0.22.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.
- package/CHANGELOG.md +192 -1
- package/README.md +404 -28
- package/dist/ag-ui-web-component.bundle.js +781 -451
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +29 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +93 -1
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/create_http_agent.d.ts +9 -0
- package/dist/core/create_http_agent.d.ts.map +1 -1
- package/dist/core/remote_conversation_store.d.ts +8 -1
- package/dist/core/remote_conversation_store.d.ts.map +1 -1
- package/dist/core/run_index.d.ts +8 -1
- package/dist/core/run_index.d.ts.map +1 -1
- package/dist/core/transcribe_audio.d.ts +7 -0
- package/dist/core/transcribe_audio.d.ts.map +1 -1
- package/dist/core/upload_attachment.d.ts +9 -0
- package/dist/core/upload_attachment.d.ts.map +1 -1
- package/dist/core/utils.d.ts +12 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/dom/animations.d.ts +51 -11
- package/dist/dom/animations.d.ts.map +1 -1
- package/dist/dom/dom_driver.d.ts +12 -7
- package/dist/dom/dom_driver.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1275 -520
- package/dist/index.js.map +3 -3
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +8 -1
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/dist/ui/voice_input.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +35 -0
- package/src/core/ag_ui_chat.ts +452 -55
- package/src/core/create_http_agent.ts +14 -3
- package/src/core/remote_conversation_store.ts +25 -6
- package/src/core/run_index.ts +27 -5
- package/src/core/transcribe_audio.ts +20 -5
- package/src/core/upload_attachment.ts +13 -0
- package/src/core/utils.ts +18 -0
- package/src/dom/animations.ts +175 -31
- package/src/dom/dom_driver.ts +18 -12
- package/src/index.ts +4 -0
- package/src/ui/styles.ts +751 -421
- package/src/ui/ui_strings.ts +9 -1
- package/src/ui/voice_input.ts +7 -1
- package/src/version.ts +1 -1
package/src/ui/styles.ts
CHANGED
|
@@ -3,151 +3,216 @@
|
|
|
3
3
|
// CSS pipeline. Scoped by the shadow boundary, so class names stay terse.
|
|
4
4
|
|
|
5
5
|
export const STYLES = `
|
|
6
|
+
/* ── Token defaults ─────────────────────────────────────────────────────────
|
|
7
|
+
Every public --ag-ui-* token is read here into a private --_* alias, and
|
|
8
|
+
only the alias is used by the rules below.
|
|
9
|
+
|
|
10
|
+
The indirection is what makes ancestor theming work. Declaring the public
|
|
11
|
+
name on :host would set it *on the host element*, and a value on an element
|
|
12
|
+
always beats one inherited from an ancestor — so a page that put the tokens
|
|
13
|
+
on a wrapper would see no effect at all, which is the one thing the API is
|
|
14
|
+
documented to support. Reading the public name with the default as a var()
|
|
15
|
+
fallback leaves it undeclared on the element, so an ancestor's value is
|
|
16
|
+
inherited normally while a value aimed at the element still wins over it.
|
|
17
|
+
|
|
18
|
+
Two invariants hold this together:
|
|
19
|
+
1. No rule outside this file's :host blocks may reference a public name
|
|
20
|
+
directly. A public name read outside these blocks resolves to nothing and
|
|
21
|
+
silently drops its declaration rather than erroring, so the miss shows up
|
|
22
|
+
as a missing colour, not a failure.
|
|
23
|
+
2. Every --_* alias in use is declared here. Aliases inherit like any custom
|
|
24
|
+
property, so an undeclared one would pick up a same-named property from
|
|
25
|
+
the host page; declaring it on :host shields the shadow tree from that. */
|
|
6
26
|
:host {
|
|
7
27
|
/* Colors */
|
|
8
|
-
--ag-ui-bg
|
|
9
|
-
--ag-ui-fg
|
|
10
|
-
--ag-ui-accent
|
|
11
|
-
--ag-ui-user-bg
|
|
12
|
-
--ag-ui-user-fg
|
|
13
|
-
--ag-ui-assistant-bg
|
|
14
|
-
--ag-ui-hover
|
|
15
|
-
--
|
|
16
|
-
--
|
|
17
|
-
--ag-ui-tool-fg
|
|
18
|
-
--ag-ui-header-bg
|
|
19
|
-
--ag-ui-header-fg
|
|
20
|
-
--ag-ui-border
|
|
21
|
-
--ag-ui-radius
|
|
28
|
+
--_bg: var(--ag-ui-bg, #ffffff);
|
|
29
|
+
--_fg: var(--ag-ui-fg, #1a1a2e);
|
|
30
|
+
--_accent: var(--ag-ui-accent, #4f46e5);
|
|
31
|
+
--_user-bg: var(--ag-ui-user-bg, #4f46e5);
|
|
32
|
+
--_user-fg: var(--ag-ui-user-fg, #ffffff);
|
|
33
|
+
--_assistant-bg: var(--ag-ui-assistant-bg, #f1f1f6);
|
|
34
|
+
--_hover: var(--ag-ui-hover, #e7e7ee);
|
|
35
|
+
--_input-bg: var(--ag-ui-input-bg, var(--_bg));
|
|
36
|
+
--_tool-bg: var(--ag-ui-tool-bg, var(--_assistant-bg));
|
|
37
|
+
--_tool-fg: var(--ag-ui-tool-fg, var(--_accent));
|
|
38
|
+
--_header-bg: var(--ag-ui-header-bg, var(--_accent));
|
|
39
|
+
--_header-fg: var(--ag-ui-header-fg, #ffffff);
|
|
40
|
+
--_border: var(--ag-ui-border, #e2e2ec);
|
|
41
|
+
--_radius: var(--ag-ui-radius, 12px);
|
|
42
|
+
|
|
43
|
+
/* Body text and raised chrome. Both are referenced by the code-block copy
|
|
44
|
+
button; neither had a default before, so the declarations reading them
|
|
45
|
+
were dropped and the button fell back to the inherited colour over a
|
|
46
|
+
transparent box. The defaults below restate exactly that, so this is a
|
|
47
|
+
rename with no repaint — see the note on .code-copy. */
|
|
48
|
+
--_text: var(--ag-ui-text, var(--_fg));
|
|
49
|
+
--_surface: var(--ag-ui-surface, transparent);
|
|
22
50
|
|
|
23
51
|
/* Status accents for tool-call cards. */
|
|
24
|
-
--ag-ui-success
|
|
25
|
-
--ag-ui-danger
|
|
26
|
-
--ag-ui-muted
|
|
52
|
+
--_success: var(--ag-ui-success, #15803d);
|
|
53
|
+
--_danger: var(--ag-ui-danger, #b91c1c);
|
|
54
|
+
--_muted: var(--ag-ui-muted, #6b7280);
|
|
27
55
|
|
|
28
56
|
/* Tool-call status icon glyphs (override to re-theme) + spinner speed.
|
|
29
57
|
The pending state is the animated ring; the settled states use these. */
|
|
30
|
-
--ag-ui-tool-icon-done
|
|
31
|
-
--ag-ui-tool-icon-error
|
|
32
|
-
--ag-ui-tool-icon-declined
|
|
33
|
-
--ag-ui-tool-spin-duration
|
|
58
|
+
--_tool-icon-done: var(--ag-ui-tool-icon-done, "✓");
|
|
59
|
+
--_tool-icon-error: var(--ag-ui-tool-icon-error, "✕");
|
|
60
|
+
--_tool-icon-declined: var(--ag-ui-tool-icon-declined, "⊘");
|
|
61
|
+
--_tool-spin-duration: var(--ag-ui-tool-spin-duration, 0.7s);
|
|
34
62
|
|
|
35
63
|
/* Answer well (opt-in via data-answer-well) — boxes a whole assistant turn. */
|
|
36
|
-
--ag-ui-well-bg
|
|
37
|
-
--
|
|
64
|
+
--_well-bg: var(--ag-ui-well-bg, transparent);
|
|
65
|
+
--_well-border: var(--ag-ui-well-border, var(--_border));
|
|
38
66
|
|
|
39
67
|
/* Surface — set --ag-ui-shadow: none for a flush, embedded panel. */
|
|
40
|
-
--ag-ui-shadow
|
|
41
|
-
--ag-ui-font
|
|
42
|
-
--ag-ui-font-size
|
|
43
|
-
--ag-ui-code-font
|
|
68
|
+
--_shadow: var(--ag-ui-shadow, 0 12px 32px rgba(20, 20, 50, 0.18));
|
|
69
|
+
--_font: var(--ag-ui-font, inherit);
|
|
70
|
+
--_font-size: var(--ag-ui-font-size, 14px);
|
|
71
|
+
--_code-font: var(--ag-ui-code-font, ui-monospace, "SF Mono", Menlo, monospace);
|
|
72
|
+
|
|
73
|
+
/* Header / launcher icon box. */
|
|
74
|
+
--_icon-size: var(--ag-ui-icon-size, 22px);
|
|
75
|
+
--_icon-radius: var(--ag-ui-icon-radius, 4px);
|
|
76
|
+
|
|
77
|
+
/* Composer — one bordered surface holding the field and its tool row. */
|
|
78
|
+
--_composer-radius: var(--ag-ui-composer-radius, 14px);
|
|
79
|
+
--_composer-max-height: var(--ag-ui-composer-max-height, 40vh);
|
|
80
|
+
--_tool-btn-size: var(--ag-ui-tool-btn-size, 30px);
|
|
81
|
+
--_send-size: var(--ag-ui-send-size, 30px);
|
|
82
|
+
--_glyph-size: var(--ag-ui-glyph-size, 18px);
|
|
83
|
+
--_glyph-stroke: var(--ag-ui-glyph-stroke, 1.75);
|
|
84
|
+
|
|
85
|
+
/* Unread badge on the launcher. */
|
|
86
|
+
--_badge-bg: var(--ag-ui-badge-bg, var(--_danger));
|
|
87
|
+
--_badge-fg: var(--ag-ui-badge-fg, #ffffff);
|
|
88
|
+
--_badge-size: var(--ag-ui-badge-size, 18px);
|
|
89
|
+
--_badge-font-size: var(--ag-ui-badge-font-size, 11px);
|
|
90
|
+
|
|
91
|
+
/* The floating launcher a collapsed widget shrinks to. */
|
|
92
|
+
--_launcher-size: var(--ag-ui-launcher-size, 56px);
|
|
93
|
+
--_launcher-bg: var(--ag-ui-launcher-bg, var(--_header-bg));
|
|
94
|
+
--_launcher-fg: var(--ag-ui-launcher-fg, var(--_header-fg));
|
|
95
|
+
--_launcher-radius: var(--ag-ui-launcher-radius, 50%);
|
|
96
|
+
--_launcher-icon-size: var(--ag-ui-launcher-icon-size, 26px);
|
|
97
|
+
--_launcher-inset: var(--ag-ui-launcher-inset, auto 0 0 auto);
|
|
98
|
+
|
|
99
|
+
/* Motion. One duration and two curves drive every collapse, expand and
|
|
100
|
+
slide-over, so the whole widget accelerates and settles as one thing.
|
|
101
|
+
The default curve is a long-tailed ease-out (a fast start that decelerates
|
|
102
|
+
into place); the pop curve overshoots slightly, for something arriving. */
|
|
103
|
+
--_motion: var(--ag-ui-motion, 0.28s);
|
|
104
|
+
--_ease: var(--ag-ui-ease, cubic-bezier(0.32, 0.72, 0, 1));
|
|
105
|
+
--_ease-pop: var(--ag-ui-ease-pop, cubic-bezier(0.34, 1.36, 0.64, 1));
|
|
44
106
|
|
|
45
107
|
/* Spacing — the density preset overrides these. */
|
|
46
|
-
--ag-ui-space
|
|
47
|
-
--ag-ui-pad
|
|
48
|
-
--ag-ui-msg-pad
|
|
49
|
-
--ag-ui-msg-radius
|
|
108
|
+
--_space: var(--ag-ui-space, 10px);
|
|
109
|
+
--_pad: var(--ag-ui-pad, 16px);
|
|
110
|
+
--_msg-pad: var(--ag-ui-msg-pad, 8px 12px);
|
|
111
|
+
--_msg-radius: var(--ag-ui-msg-radius, 14px);
|
|
50
112
|
|
|
51
113
|
/* Layout — override from outside to dock the widget anywhere.
|
|
52
114
|
Set --ag-ui-position: static (and place this element in your own
|
|
53
115
|
grid/flex layout) to embed it in the page flow instead of floating. */
|
|
54
|
-
--ag-ui-position
|
|
55
|
-
--ag-ui-z-index
|
|
56
|
-
--ag-ui-width
|
|
57
|
-
--ag-ui-height
|
|
58
|
-
--ag-ui-inset
|
|
59
|
-
--ag-ui-max-width
|
|
60
|
-
--ag-ui-max-height
|
|
116
|
+
--_position: var(--ag-ui-position, fixed);
|
|
117
|
+
--_z-index: var(--ag-ui-z-index, 2147483000);
|
|
118
|
+
--_width: var(--ag-ui-width, 380px);
|
|
119
|
+
--_height: var(--ag-ui-height, 560px);
|
|
120
|
+
--_inset: var(--ag-ui-inset, auto 24px 24px auto);
|
|
121
|
+
--_max-width: var(--ag-ui-max-width, calc(100vw - 48px));
|
|
122
|
+
--_max-height: var(--ag-ui-max-height, calc(100vh - 48px));
|
|
61
123
|
/* Reading-column width for placement="page" (full-bleed, centred content). */
|
|
62
|
-
--ag-ui-content-max-width
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
124
|
+
--_content-max-width: var(--ag-ui-content-max-width, 820px);
|
|
125
|
+
/* Slim rail the sidebar placement collapses to. Only that placement reads
|
|
126
|
+
it, but it is declared here so invariant 2 holds for every alias. */
|
|
127
|
+
--_rail-width: var(--ag-ui-rail-width, 52px);
|
|
128
|
+
|
|
129
|
+
position: var(--_position);
|
|
130
|
+
inset: var(--_inset);
|
|
131
|
+
z-index: var(--_z-index);
|
|
132
|
+
width: var(--_width);
|
|
133
|
+
max-width: var(--_max-width);
|
|
134
|
+
height: var(--_height);
|
|
135
|
+
max-height: var(--_max-height);
|
|
71
136
|
display: flex;
|
|
72
|
-
font-family: var(--
|
|
73
|
-
font-size: var(--
|
|
74
|
-
color: var(--
|
|
137
|
+
font-family: var(--_font);
|
|
138
|
+
font-size: var(--_font-size);
|
|
139
|
+
color: var(--_fg);
|
|
75
140
|
}
|
|
76
141
|
|
|
77
142
|
/* ── Themes ─────────────────────────────────────────────────────────────
|
|
78
143
|
Themes only re-set the colour variables; layout/spacing are unaffected.
|
|
79
144
|
theme="auto" follows the OS via prefers-color-scheme. */
|
|
80
145
|
:host([theme="dark"]) {
|
|
81
|
-
--ag-ui-bg
|
|
82
|
-
--ag-ui-fg
|
|
83
|
-
--ag-ui-assistant-bg
|
|
84
|
-
--ag-ui-hover
|
|
85
|
-
--ag-ui-header-bg
|
|
86
|
-
--ag-ui-header-fg
|
|
87
|
-
--ag-ui-border
|
|
88
|
-
--ag-ui-muted
|
|
89
|
-
--ag-ui-shadow
|
|
146
|
+
--_bg: var(--ag-ui-bg, #15151f);
|
|
147
|
+
--_fg: var(--ag-ui-fg, #e8e8f2);
|
|
148
|
+
--_assistant-bg: var(--ag-ui-assistant-bg, #25253a);
|
|
149
|
+
--_hover: var(--ag-ui-hover, #303049);
|
|
150
|
+
--_header-bg: var(--ag-ui-header-bg, #1f1f30);
|
|
151
|
+
--_header-fg: var(--ag-ui-header-fg, #e8e8f2);
|
|
152
|
+
--_border: var(--ag-ui-border, #33334a);
|
|
153
|
+
--_muted: var(--ag-ui-muted, #9aa0b4);
|
|
154
|
+
--_shadow: var(--ag-ui-shadow, 0 12px 32px rgba(0, 0, 0, 0.5));
|
|
90
155
|
}
|
|
91
156
|
|
|
92
157
|
@media (prefers-color-scheme: dark) {
|
|
93
158
|
:host([theme="auto"]) {
|
|
94
|
-
--ag-ui-bg
|
|
95
|
-
--ag-ui-fg
|
|
96
|
-
--ag-ui-assistant-bg
|
|
97
|
-
--ag-ui-hover
|
|
98
|
-
--ag-ui-header-bg
|
|
99
|
-
--ag-ui-header-fg
|
|
100
|
-
--ag-ui-border
|
|
101
|
-
--ag-ui-muted
|
|
102
|
-
--ag-ui-shadow
|
|
159
|
+
--_bg: var(--ag-ui-bg, #15151f);
|
|
160
|
+
--_fg: var(--ag-ui-fg, #e8e8f2);
|
|
161
|
+
--_assistant-bg: var(--ag-ui-assistant-bg, #25253a);
|
|
162
|
+
--_hover: var(--ag-ui-hover, #303049);
|
|
163
|
+
--_header-bg: var(--ag-ui-header-bg, #1f1f30);
|
|
164
|
+
--_header-fg: var(--ag-ui-header-fg, #e8e8f2);
|
|
165
|
+
--_border: var(--ag-ui-border, #33334a);
|
|
166
|
+
--_muted: var(--ag-ui-muted, #9aa0b4);
|
|
167
|
+
--_shadow: var(--ag-ui-shadow, 0 12px 32px rgba(0, 0, 0, 0.5));
|
|
103
168
|
}
|
|
104
169
|
}
|
|
105
170
|
|
|
106
171
|
/* A terminal-flavoured "code" theme: dark, monospace, green accent. */
|
|
107
172
|
:host([theme="code"]) {
|
|
108
|
-
--ag-ui-bg
|
|
109
|
-
--ag-ui-fg
|
|
110
|
-
--ag-ui-accent
|
|
111
|
-
--ag-ui-user-bg
|
|
112
|
-
--ag-ui-assistant-bg
|
|
113
|
-
--ag-ui-hover
|
|
114
|
-
--ag-ui-header-bg
|
|
115
|
-
--ag-ui-header-fg
|
|
116
|
-
--ag-ui-border
|
|
117
|
-
--ag-ui-muted
|
|
118
|
-
--ag-ui-font
|
|
119
|
-
--ag-ui-shadow
|
|
173
|
+
--_bg: var(--ag-ui-bg, #0d1117);
|
|
174
|
+
--_fg: var(--ag-ui-fg, #c9d1d9);
|
|
175
|
+
--_accent: var(--ag-ui-accent, #3fb950);
|
|
176
|
+
--_user-bg: var(--ag-ui-user-bg, #238636);
|
|
177
|
+
--_assistant-bg: var(--ag-ui-assistant-bg, #161b22);
|
|
178
|
+
--_hover: var(--ag-ui-hover, #21262d);
|
|
179
|
+
--_header-bg: var(--ag-ui-header-bg, #010409);
|
|
180
|
+
--_header-fg: var(--ag-ui-header-fg, #c9d1d9);
|
|
181
|
+
--_border: var(--ag-ui-border, #30363d);
|
|
182
|
+
--_muted: var(--ag-ui-muted, #8b949e);
|
|
183
|
+
--_font: var(--ag-ui-font, var(--_code-font));
|
|
184
|
+
--_shadow: var(--ag-ui-shadow, 0 12px 32px rgba(0, 0, 0, 0.6));
|
|
120
185
|
}
|
|
121
186
|
|
|
122
187
|
/* ── Density ────────────────────────────────────────────────────────────── */
|
|
123
188
|
:host([density="compact"]) {
|
|
124
|
-
--ag-ui-font-size
|
|
125
|
-
--ag-ui-space
|
|
126
|
-
--ag-ui-pad
|
|
127
|
-
--ag-ui-msg-pad
|
|
128
|
-
--ag-ui-msg-radius
|
|
189
|
+
--_font-size: var(--ag-ui-font-size, 13px);
|
|
190
|
+
--_space: var(--ag-ui-space, 6px);
|
|
191
|
+
--_pad: var(--ag-ui-pad, 10px);
|
|
192
|
+
--_msg-pad: var(--ag-ui-msg-pad, 5px 9px);
|
|
193
|
+
--_msg-radius: var(--ag-ui-msg-radius, 10px);
|
|
129
194
|
}
|
|
130
195
|
|
|
131
196
|
/* ── Placement presets ──────────────────────────────────────────────────── */
|
|
132
197
|
:host([placement="bottom-left"]) {
|
|
133
|
-
--ag-ui-inset
|
|
198
|
+
--_inset: var(--ag-ui-inset, auto auto 24px 24px);
|
|
134
199
|
}
|
|
135
200
|
|
|
136
201
|
:host([placement="side"]) {
|
|
137
|
-
--ag-ui-inset
|
|
138
|
-
--ag-ui-width
|
|
139
|
-
--ag-ui-height
|
|
140
|
-
--ag-ui-max-height
|
|
141
|
-
--ag-ui-radius
|
|
202
|
+
--_inset: var(--ag-ui-inset, 0 0 0 auto);
|
|
203
|
+
--_width: var(--ag-ui-width, 420px);
|
|
204
|
+
--_height: var(--ag-ui-height, 100vh);
|
|
205
|
+
--_max-height: var(--ag-ui-max-height, 100vh);
|
|
206
|
+
--_radius: var(--ag-ui-radius, 0);
|
|
142
207
|
}
|
|
143
208
|
|
|
144
209
|
:host([placement="full"]) {
|
|
145
|
-
--ag-ui-inset
|
|
146
|
-
--ag-ui-width
|
|
147
|
-
--ag-ui-height
|
|
148
|
-
--ag-ui-max-width
|
|
149
|
-
--ag-ui-max-height
|
|
150
|
-
--ag-ui-radius
|
|
210
|
+
--_inset: var(--ag-ui-inset, 0);
|
|
211
|
+
--_width: var(--ag-ui-width, 100vw);
|
|
212
|
+
--_height: var(--ag-ui-height, 100vh);
|
|
213
|
+
--_max-width: var(--ag-ui-max-width, 100vw);
|
|
214
|
+
--_max-height: var(--ag-ui-max-height, 100vh);
|
|
215
|
+
--_radius: var(--ag-ui-radius, 0);
|
|
151
216
|
}
|
|
152
217
|
|
|
153
218
|
/* Page: full-bleed background with a centred reading column. Unlike
|
|
@@ -156,85 +221,20 @@ export const STYLES = `
|
|
|
156
221
|
padding on the scroll area + composer (no per-row wrapper), so user pills
|
|
157
222
|
still right-align and the assistant well spans the column. */
|
|
158
223
|
:host([placement="page"]) {
|
|
159
|
-
--ag-ui-inset
|
|
160
|
-
--ag-ui-width
|
|
161
|
-
--ag-ui-height
|
|
162
|
-
--ag-ui-max-width
|
|
163
|
-
--ag-ui-max-height
|
|
164
|
-
--ag-ui-radius
|
|
224
|
+
--_inset: var(--ag-ui-inset, 0);
|
|
225
|
+
--_width: var(--ag-ui-width, 100vw);
|
|
226
|
+
--_height: var(--ag-ui-height, 100vh);
|
|
227
|
+
--_max-width: var(--ag-ui-max-width, 100vw);
|
|
228
|
+
--_max-height: var(--ag-ui-max-height, 100vh);
|
|
229
|
+
--_radius: var(--ag-ui-radius, 0);
|
|
165
230
|
}
|
|
166
231
|
|
|
167
232
|
:host([placement="page"]) .messages {
|
|
168
|
-
padding-inline: max(var(--
|
|
233
|
+
padding-inline: max(var(--_pad), calc((100% - var(--_content-max-width)) / 2));
|
|
169
234
|
}
|
|
170
235
|
|
|
171
|
-
:host([placement="page"])
|
|
172
|
-
|
|
173
|
-
nothing to drag. */
|
|
174
|
-
.resize-handle {
|
|
175
|
-
position: absolute;
|
|
176
|
-
z-index: 2;
|
|
177
|
-
background: transparent;
|
|
178
|
-
touch-action: none;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.resize-handle:focus-visible {
|
|
182
|
-
outline: 2px solid var(--ag-ui-accent);
|
|
183
|
-
outline-offset: -2px;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/* The grip sits at the corner the panel grows toward. Which corner that is
|
|
187
|
-
depends on the host's layout, not on placement, so the element measures it
|
|
188
|
-
and stamps data-resize-anchor with the edges that stay put.
|
|
189
|
-
|
|
190
|
-
Default (bottom-right pinned, the floating case) puts the grip top-left. */
|
|
191
|
-
.resize-handle {
|
|
192
|
-
top: 0;
|
|
193
|
-
left: 0;
|
|
194
|
-
width: 14px;
|
|
195
|
-
height: 14px;
|
|
196
|
-
cursor: nwse-resize;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
:host([data-resize-anchor~="left"]) .resize-handle {
|
|
200
|
-
left: auto;
|
|
201
|
-
right: 0;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
:host([data-resize-anchor~="top"]) .resize-handle {
|
|
205
|
-
top: auto;
|
|
206
|
-
bottom: 0;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/* One axis flipped means the drag runs along the other diagonal. */
|
|
210
|
-
:host([data-resize-anchor="top-right"]) .resize-handle,
|
|
211
|
-
:host([data-resize-anchor="bottom-left"]) .resize-handle {
|
|
212
|
-
cursor: nesw-resize;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* Docked: the placement owns the height, so only the inner edge is the user's. */
|
|
216
|
-
:host([placement="sidebar"]) .resize-handle,
|
|
217
|
-
:host([placement="side"]) .resize-handle {
|
|
218
|
-
top: 0;
|
|
219
|
-
bottom: auto;
|
|
220
|
-
width: 8px;
|
|
221
|
-
height: 100%;
|
|
222
|
-
cursor: ew-resize;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/* Full-bleed: nothing to drag. */
|
|
226
|
-
:host([placement="full"]) .resize-handle,
|
|
227
|
-
:host([placement="page"]) .resize-handle {
|
|
228
|
-
display: none;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.resize-handle[data-dragging] {
|
|
232
|
-
background: var(--ag-ui-accent);
|
|
233
|
-
opacity: 0.35;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.input-row {
|
|
237
|
-
padding-inline: max(12px, calc((100% - var(--ag-ui-content-max-width)) / 2));
|
|
236
|
+
:host([placement="page"]) .input-row {
|
|
237
|
+
padding-inline: max(12px, calc((100% - var(--_content-max-width)) / 2));
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
/* The rows between the message list and the composer (skill chips, the
|
|
@@ -243,12 +243,12 @@ export const STYLES = `
|
|
|
243
243
|
margin-based, so each gets its own inline axis nudged by the same gutter. */
|
|
244
244
|
:host([placement="page"]) .skill-chips,
|
|
245
245
|
:host([placement="page"]) .attachment-tray {
|
|
246
|
-
padding-inline: max(12px, calc((100% - var(--
|
|
246
|
+
padding-inline: max(12px, calc((100% - var(--_content-max-width)) / 2));
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
:host([placement="page"]) .skill-palette,
|
|
250
250
|
:host([placement="page"]) .skill-hint {
|
|
251
|
-
margin-inline: max(12px, calc((100% - var(--
|
|
251
|
+
margin-inline: max(12px, calc((100% - var(--_content-max-width)) / 2));
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
/* In the reading column the assistant well uses the full width; the user
|
|
@@ -263,75 +263,179 @@ export const STYLES = `
|
|
|
263
263
|
--ag-ui-position: static (and place this element in your own layout) for a
|
|
264
264
|
host-managed push instead. */
|
|
265
265
|
:host([placement="sidebar"]) {
|
|
266
|
-
--ag-ui-inset
|
|
267
|
-
--ag-ui-width
|
|
268
|
-
--ag-ui-height
|
|
269
|
-
--ag-ui-max-height
|
|
270
|
-
--ag-ui-radius
|
|
271
|
-
|
|
272
|
-
transition: width 0.28s ease;
|
|
266
|
+
--_inset: var(--ag-ui-inset, 0 0 0 auto);
|
|
267
|
+
--_width: var(--ag-ui-width, 420px);
|
|
268
|
+
--_height: var(--ag-ui-height, 100vh);
|
|
269
|
+
--_max-height: var(--ag-ui-max-height, 100vh);
|
|
270
|
+
--_radius: var(--ag-ui-radius, 0);
|
|
271
|
+
transition: width var(--_motion) var(--_ease);
|
|
273
272
|
}
|
|
274
273
|
|
|
275
274
|
:host([placement="sidebar"][data-side="left"]) {
|
|
276
|
-
--ag-ui-inset
|
|
275
|
+
--_inset: var(--ag-ui-inset, 0 auto 0 0);
|
|
277
276
|
}
|
|
278
277
|
|
|
278
|
+
/* The docked panel is pinned to the edge it docks against rather than filling
|
|
279
|
+
the host as a flex child. Collapsing shrinks the host to the rail width, and
|
|
280
|
+
a flex child would be squashed to 52px on the way out instead of sliding out
|
|
281
|
+
at full width. */
|
|
279
282
|
:host([placement="sidebar"]) .chat {
|
|
280
|
-
|
|
283
|
+
position: absolute;
|
|
284
|
+
inset: 0 0 0 auto;
|
|
285
|
+
width: var(--_width);
|
|
286
|
+
transform-origin: right center;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
:host([placement="sidebar"][data-side="left"]) .chat {
|
|
290
|
+
inset: 0 auto 0 0;
|
|
291
|
+
transform-origin: left center;
|
|
281
292
|
}
|
|
282
293
|
|
|
283
|
-
/* Collapsed sidebar: shrink the host to the rail width
|
|
284
|
-
|
|
285
|
-
wins regardless of source order. */
|
|
294
|
+
/* Collapsed sidebar: shrink the host to the rail width and slide the panel out
|
|
295
|
+
through the edge it docks against. Higher specificity than the generic
|
|
296
|
+
collapse rules, so it wins regardless of source order. */
|
|
286
297
|
:host([placement="sidebar"][collapsed]) {
|
|
287
|
-
width: var(--
|
|
298
|
+
width: var(--_rail-width);
|
|
288
299
|
height: 100vh;
|
|
289
300
|
max-height: 100vh;
|
|
290
301
|
bottom: 0;
|
|
302
|
+
pointer-events: auto;
|
|
291
303
|
}
|
|
292
304
|
|
|
293
305
|
:host([placement="sidebar"][collapsed]) .chat {
|
|
294
|
-
|
|
306
|
+
transform: translateX(100%);
|
|
295
307
|
}
|
|
296
308
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
309
|
+
:host([placement="sidebar"][data-side="left"][collapsed]) .chat {
|
|
310
|
+
transform: translateX(-100%);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@media (prefers-reduced-motion: reduce) {
|
|
314
|
+
:host([placement="sidebar"]),
|
|
315
|
+
:host([placement="sidebar"]) .chat {
|
|
316
|
+
transition: none;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* ── Launcher ───────────────────────────────────────────────────────────────
|
|
321
|
+
What a collapsed widget shrinks to: a round floating button by default, the
|
|
322
|
+
sidebar's slim edge rail under that placement. A sibling of the panel, so it
|
|
323
|
+
survives the panel being hidden, and the only part of a collapsed widget
|
|
324
|
+
that takes pointer events. */
|
|
325
|
+
.launcher {
|
|
326
|
+
display: flex;
|
|
327
|
+
position: absolute;
|
|
328
|
+
inset: var(--_launcher-inset);
|
|
329
|
+
align-items: center;
|
|
330
|
+
justify-content: center;
|
|
331
|
+
width: var(--_launcher-size);
|
|
332
|
+
height: var(--_launcher-size);
|
|
333
|
+
padding: 0;
|
|
301
334
|
border: none;
|
|
335
|
+
border-radius: var(--_launcher-radius);
|
|
336
|
+
background: var(--_launcher-bg);
|
|
337
|
+
color: var(--_launcher-fg);
|
|
338
|
+
box-shadow: var(--_shadow);
|
|
302
339
|
font: inherit;
|
|
340
|
+
cursor: pointer;
|
|
341
|
+
pointer-events: auto;
|
|
342
|
+
opacity: 0;
|
|
343
|
+
transform: scale(0.4);
|
|
344
|
+
visibility: hidden;
|
|
345
|
+
transition:
|
|
346
|
+
opacity var(--_motion) var(--_ease),
|
|
347
|
+
transform var(--_motion) var(--_ease-pop),
|
|
348
|
+
visibility var(--_motion) var(--_ease);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* The launcher grows out of the corner the panel shrank into.
|
|
352
|
+
It is laid out at rest rather than display:none, which is what lets it
|
|
353
|
+
animate in *and* out: an element that was not rendered has no before-change
|
|
354
|
+
style to transition from, and one whose display flips to none cannot
|
|
355
|
+
transition at all. visibility keeps it unpaintable, untabbable and
|
|
356
|
+
unclickable in between -- the expanded panel's own controls sit under it and
|
|
357
|
+
must stay reachable. */
|
|
358
|
+
:host([collapsed]) .launcher {
|
|
359
|
+
opacity: 1;
|
|
360
|
+
transform: none;
|
|
361
|
+
visibility: visible;
|
|
303
362
|
}
|
|
304
363
|
|
|
305
|
-
:host([
|
|
306
|
-
|
|
364
|
+
:host([collapsed]) .launcher:hover {
|
|
365
|
+
transform: scale(1.06);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
:host([collapsed]) .launcher:active {
|
|
369
|
+
transform: scale(0.94);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.launcher .icon-holder {
|
|
373
|
+
width: var(--_launcher-icon-size);
|
|
374
|
+
height: var(--_launcher-icon-size);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/* The unread badge rides the launcher's top-right corner. The ring in the
|
|
378
|
+
widget's own background is what separates it from the launcher underneath,
|
|
379
|
+
whatever colour the host themes either one. */
|
|
380
|
+
.launcher-badge {
|
|
307
381
|
position: absolute;
|
|
382
|
+
top: -2px;
|
|
383
|
+
right: -2px;
|
|
384
|
+
display: inline-flex;
|
|
385
|
+
align-items: center;
|
|
386
|
+
justify-content: center;
|
|
387
|
+
box-sizing: border-box;
|
|
388
|
+
min-width: var(--_badge-size);
|
|
389
|
+
height: var(--_badge-size);
|
|
390
|
+
padding: 0 5px;
|
|
391
|
+
border-radius: 999px;
|
|
392
|
+
background: var(--_badge-bg);
|
|
393
|
+
color: var(--_badge-fg);
|
|
394
|
+
font-size: var(--_badge-font-size);
|
|
395
|
+
font-weight: 600;
|
|
396
|
+
line-height: 1;
|
|
397
|
+
box-shadow: 0 0 0 2px var(--_bg);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.launcher-badge[hidden] {
|
|
401
|
+
display: none;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* The sidebar collapses to an edge rail instead: full height, square, flush
|
|
405
|
+
against the dock. It slides in with the panel rather than popping. */
|
|
406
|
+
:host([placement="sidebar"][collapsed]) .launcher {
|
|
308
407
|
inset: 0;
|
|
408
|
+
width: auto;
|
|
409
|
+
height: auto;
|
|
309
410
|
align-items: flex-start;
|
|
310
|
-
justify-content: center;
|
|
311
411
|
padding-top: 16px;
|
|
312
|
-
border: 1px solid var(--
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
412
|
+
border: 1px solid var(--_border);
|
|
413
|
+
border-radius: 0;
|
|
414
|
+
background: var(--_header-bg);
|
|
415
|
+
color: var(--_header-fg);
|
|
416
|
+
box-shadow: none;
|
|
417
|
+
transform: none;
|
|
316
418
|
}
|
|
317
419
|
|
|
420
|
+
/* Every transition in this file is timed by --_motion, so collapsing it to a
|
|
421
|
+
frame is the whole reduced-motion story: states still change (and display
|
|
422
|
+
still flips at the end of its discrete transition), nothing travels. */
|
|
318
423
|
@media (prefers-reduced-motion: reduce) {
|
|
319
|
-
:host
|
|
320
|
-
|
|
321
|
-
transition: none;
|
|
424
|
+
:host {
|
|
425
|
+
--_motion: var(--ag-ui-motion, 0.001s);
|
|
322
426
|
}
|
|
323
427
|
}
|
|
324
428
|
|
|
325
429
|
/* Embedded: drop the floating chrome and the high z-index stacking context so
|
|
326
430
|
the widget lives in the host's own layout (fixes overlay/z-index clashes). */
|
|
327
431
|
:host([placement="embedded"]) {
|
|
328
|
-
--ag-ui-position
|
|
329
|
-
--ag-ui-width
|
|
330
|
-
--ag-ui-height
|
|
331
|
-
--ag-ui-max-width
|
|
332
|
-
--ag-ui-max-height
|
|
333
|
-
--ag-ui-shadow
|
|
334
|
-
--ag-ui-z-index
|
|
432
|
+
--_position: var(--ag-ui-position, static);
|
|
433
|
+
--_width: var(--ag-ui-width, 100%);
|
|
434
|
+
--_height: var(--ag-ui-height, 100%);
|
|
435
|
+
--_max-width: var(--ag-ui-max-width, 100%);
|
|
436
|
+
--_max-height: var(--ag-ui-max-height, 100%);
|
|
437
|
+
--_shadow: var(--ag-ui-shadow, none);
|
|
438
|
+
--_z-index: var(--ag-ui-z-index, auto);
|
|
335
439
|
}
|
|
336
440
|
|
|
337
441
|
.chat {
|
|
@@ -340,10 +444,10 @@ export const STYLES = `
|
|
|
340
444
|
flex-direction: column;
|
|
341
445
|
flex: 1;
|
|
342
446
|
min-height: 0;
|
|
343
|
-
background: var(--
|
|
344
|
-
border: 1px solid var(--
|
|
345
|
-
border-radius: var(--
|
|
346
|
-
box-shadow: var(--
|
|
447
|
+
background: var(--_bg);
|
|
448
|
+
border: 1px solid var(--_border);
|
|
449
|
+
border-radius: var(--_radius);
|
|
450
|
+
box-shadow: var(--_shadow);
|
|
347
451
|
overflow: hidden;
|
|
348
452
|
}
|
|
349
453
|
|
|
@@ -353,9 +457,9 @@ export const STYLES = `
|
|
|
353
457
|
justify-content: space-between;
|
|
354
458
|
gap: 8px;
|
|
355
459
|
padding: 10px 14px;
|
|
356
|
-
border-bottom: 1px solid var(--
|
|
357
|
-
background: var(--
|
|
358
|
-
color: var(--
|
|
460
|
+
border-bottom: 1px solid var(--_border);
|
|
461
|
+
background: var(--_header-bg);
|
|
462
|
+
color: var(--_header-fg);
|
|
359
463
|
}
|
|
360
464
|
|
|
361
465
|
.header-title {
|
|
@@ -374,8 +478,8 @@ export const STYLES = `
|
|
|
374
478
|
align-items: center;
|
|
375
479
|
justify-content: center;
|
|
376
480
|
flex: none;
|
|
377
|
-
width: var(--
|
|
378
|
-
height: var(--
|
|
481
|
+
width: var(--_icon-size);
|
|
482
|
+
height: var(--_icon-size);
|
|
379
483
|
line-height: 1;
|
|
380
484
|
}
|
|
381
485
|
|
|
@@ -383,7 +487,7 @@ export const STYLES = `
|
|
|
383
487
|
width: 100%;
|
|
384
488
|
height: 100%;
|
|
385
489
|
object-fit: contain;
|
|
386
|
-
border-radius: var(--
|
|
490
|
+
border-radius: var(--_icon-radius);
|
|
387
491
|
}
|
|
388
492
|
|
|
389
493
|
.header-controls {
|
|
@@ -409,36 +513,87 @@ export const STYLES = `
|
|
|
409
513
|
background: rgba(255, 255, 255, 0.18);
|
|
410
514
|
}
|
|
411
515
|
|
|
412
|
-
/*
|
|
413
|
-
|
|
516
|
+
/* ── Collapse ───────────────────────────────────────────────────────────────
|
|
517
|
+
Collapsing shrinks the widget to the round floating launcher: the panel
|
|
518
|
+
scales down toward the launcher's corner and fades out, the launcher pops in
|
|
519
|
+
from that same point. Both halves are transform and opacity only, so the
|
|
520
|
+
morph runs on the compositor and never reflows the host page.
|
|
521
|
+
|
|
522
|
+
The host box keeps its expanded size. Animating it would animate layout, and
|
|
523
|
+
a dragged --ag-ui-width would then fight the launcher's own size. Nothing
|
|
524
|
+
paints there once the panel is gone, so the box only has to stop swallowing
|
|
525
|
+
clicks: pointer events go to none, and the launcher takes them back.
|
|
526
|
+
|
|
527
|
+
Two placements collapse to something else and restore what they need:
|
|
528
|
+
"sidebar" slides to its rail (below), while "embedded" and "page" keep the
|
|
529
|
+
original header bar — embedded is laid out by the host page, where a
|
|
530
|
+
floating circle would escape the layout, and page is a full-screen route
|
|
531
|
+
with no corner to float in. */
|
|
414
532
|
:host([collapsed]) {
|
|
533
|
+
pointer-events: none;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
:host([collapsed]) .chat {
|
|
537
|
+
opacity: 0;
|
|
538
|
+
transform: scale(0.94);
|
|
539
|
+
visibility: hidden;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/* visibility is what keeps the panel out of the tab order and the a11y tree at
|
|
543
|
+
rest without display:none killing the transition. It interpolates so that any
|
|
544
|
+
progress below 1 still counts as visible: the panel stays on screen for the
|
|
545
|
+
whole collapse and flips hidden exactly at the end, and on expand it is
|
|
546
|
+
visible from the first frame. */
|
|
547
|
+
.chat {
|
|
548
|
+
transform-origin: bottom right;
|
|
549
|
+
transition:
|
|
550
|
+
opacity var(--_motion) var(--_ease),
|
|
551
|
+
transform var(--_motion) var(--_ease),
|
|
552
|
+
visibility var(--_motion) var(--_ease);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
:host([placement="bottom-left"]) .chat {
|
|
556
|
+
transform-origin: bottom left;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/* The two in-flow placements keep the original collapse: hide the body, let
|
|
560
|
+
the host shrink to the header bar. */
|
|
561
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) {
|
|
415
562
|
height: auto;
|
|
416
563
|
max-height: none;
|
|
564
|
+
pointer-events: auto;
|
|
417
565
|
}
|
|
418
566
|
|
|
419
|
-
:host([collapsed]) .
|
|
420
|
-
:
|
|
421
|
-
:
|
|
422
|
-
:
|
|
423
|
-
:host([collapsed]) .skill-hint {
|
|
424
|
-
display: none;
|
|
567
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .chat {
|
|
568
|
+
opacity: 1;
|
|
569
|
+
transform: none;
|
|
570
|
+
visibility: visible;
|
|
425
571
|
}
|
|
426
572
|
|
|
427
|
-
/*
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
:host([collapsed][placement="
|
|
432
|
-
|
|
573
|
+
/* These two keep the header bar, so the launcher must stay out of the way —
|
|
574
|
+
an embedded host is position: static, which would otherwise leave an
|
|
575
|
+
absolutely-positioned circle to escape the layout entirely and land against
|
|
576
|
+
whatever the page happens to position. */
|
|
577
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .launcher {
|
|
578
|
+
visibility: hidden;
|
|
579
|
+
opacity: 0;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .messages,
|
|
583
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .input-row,
|
|
584
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .skill-chips,
|
|
585
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .skill-palette,
|
|
586
|
+
:host([collapsed]:is([placement="embedded"], [placement="page"])) .skill-hint {
|
|
587
|
+
display: none;
|
|
433
588
|
}
|
|
434
589
|
|
|
435
590
|
.messages {
|
|
436
591
|
flex: 1;
|
|
437
592
|
overflow-y: auto;
|
|
438
|
-
padding: var(--
|
|
593
|
+
padding: var(--_pad);
|
|
439
594
|
display: flex;
|
|
440
595
|
flex-direction: column;
|
|
441
|
-
gap: var(--
|
|
596
|
+
gap: var(--_space);
|
|
442
597
|
}
|
|
443
598
|
|
|
444
599
|
/* Empty-state region (slot): centred while it's the only thing in the
|
|
@@ -446,7 +601,7 @@ export const STYLES = `
|
|
|
446
601
|
.empty {
|
|
447
602
|
margin: auto;
|
|
448
603
|
text-align: center;
|
|
449
|
-
color: var(--
|
|
604
|
+
color: var(--_muted);
|
|
450
605
|
}
|
|
451
606
|
|
|
452
607
|
.empty[hidden] {
|
|
@@ -462,22 +617,22 @@ export const STYLES = `
|
|
|
462
617
|
.answer {
|
|
463
618
|
display: flex;
|
|
464
619
|
flex-direction: column;
|
|
465
|
-
gap: var(--
|
|
620
|
+
gap: var(--_space);
|
|
466
621
|
align-self: stretch;
|
|
467
622
|
min-width: 0;
|
|
468
623
|
}
|
|
469
624
|
|
|
470
625
|
:host([data-answer-well]) .answer {
|
|
471
|
-
padding: var(--
|
|
472
|
-
background: var(--
|
|
473
|
-
border: 1px solid var(--
|
|
474
|
-
border-radius: var(--
|
|
626
|
+
padding: var(--_pad);
|
|
627
|
+
background: var(--_well-bg);
|
|
628
|
+
border: 1px solid var(--_well-border);
|
|
629
|
+
border-radius: var(--_radius);
|
|
475
630
|
}
|
|
476
631
|
|
|
477
632
|
.message {
|
|
478
633
|
max-width: 80%;
|
|
479
|
-
padding: var(--
|
|
480
|
-
border-radius: var(--
|
|
634
|
+
padding: var(--_msg-pad);
|
|
635
|
+
border-radius: var(--_msg-radius);
|
|
481
636
|
line-height: 1.4;
|
|
482
637
|
white-space: pre-wrap;
|
|
483
638
|
word-break: break-word;
|
|
@@ -515,14 +670,14 @@ export const STYLES = `
|
|
|
515
670
|
|
|
516
671
|
.message--user {
|
|
517
672
|
align-self: flex-end;
|
|
518
|
-
background: var(--
|
|
519
|
-
color: var(--
|
|
673
|
+
background: var(--_user-bg);
|
|
674
|
+
color: var(--_user-fg);
|
|
520
675
|
border-bottom-right-radius: 4px;
|
|
521
676
|
}
|
|
522
677
|
|
|
523
678
|
.message--assistant {
|
|
524
679
|
align-self: flex-start;
|
|
525
|
-
background: var(--
|
|
680
|
+
background: var(--_assistant-bg);
|
|
526
681
|
border-bottom-left-radius: 4px;
|
|
527
682
|
/* Assistant bubbles hold rendered markdown/HTML, so collapse the source
|
|
528
683
|
whitespace the renderer leaves between block tags. */
|
|
@@ -552,7 +707,7 @@ export const STYLES = `
|
|
|
552
707
|
}
|
|
553
708
|
|
|
554
709
|
.message--assistant a {
|
|
555
|
-
color: var(--
|
|
710
|
+
color: var(--_accent);
|
|
556
711
|
text-decoration: underline;
|
|
557
712
|
}
|
|
558
713
|
|
|
@@ -567,8 +722,8 @@ export const STYLES = `
|
|
|
567
722
|
.message--assistant pre {
|
|
568
723
|
padding: 8px 10px;
|
|
569
724
|
overflow: auto;
|
|
570
|
-
background: var(--
|
|
571
|
-
border: 1px solid var(--
|
|
725
|
+
background: var(--_bg);
|
|
726
|
+
border: 1px solid var(--_border);
|
|
572
727
|
border-radius: 6px;
|
|
573
728
|
}
|
|
574
729
|
|
|
@@ -584,6 +739,13 @@ export const STYLES = `
|
|
|
584
739
|
position: relative;
|
|
585
740
|
}
|
|
586
741
|
|
|
742
|
+
/* This button is the only reader of --ag-ui-surface and --ag-ui-text, and
|
|
743
|
+
neither had a default until the alias layer gave them one. Both references
|
|
744
|
+
used to resolve to nothing, dropping the declaration: the background fell
|
|
745
|
+
back to the initial transparent, and the hover/copied colour to the
|
|
746
|
+
inherited body colour. The defaults chosen upstream (transparent, and the
|
|
747
|
+
body foreground) reproduce that, so the rename repaints nothing. A raised
|
|
748
|
+
surface behind the button is a separate design question. */
|
|
587
749
|
.code-copy {
|
|
588
750
|
position: absolute;
|
|
589
751
|
top: 4px;
|
|
@@ -592,9 +754,9 @@ export const STYLES = `
|
|
|
592
754
|
font: inherit;
|
|
593
755
|
font-size: 0.75em;
|
|
594
756
|
line-height: 1.6;
|
|
595
|
-
color: var(--
|
|
596
|
-
background: var(--
|
|
597
|
-
border: 1px solid var(--
|
|
757
|
+
color: var(--_muted);
|
|
758
|
+
background: var(--_surface);
|
|
759
|
+
border: 1px solid var(--_border);
|
|
598
760
|
border-radius: 4px;
|
|
599
761
|
cursor: pointer;
|
|
600
762
|
opacity: 0;
|
|
@@ -609,24 +771,24 @@ export const STYLES = `
|
|
|
609
771
|
}
|
|
610
772
|
|
|
611
773
|
.code-copy:hover {
|
|
612
|
-
color: var(--
|
|
613
|
-
background: var(--
|
|
774
|
+
color: var(--_text);
|
|
775
|
+
background: var(--_hover);
|
|
614
776
|
}
|
|
615
777
|
|
|
616
778
|
.code-copy[data-state="copied"] {
|
|
617
779
|
opacity: 1;
|
|
618
|
-
color: var(--
|
|
780
|
+
color: var(--_text);
|
|
619
781
|
}
|
|
620
782
|
|
|
621
783
|
.code-copy[data-state="failed"] {
|
|
622
784
|
opacity: 1;
|
|
623
|
-
color: var(--
|
|
785
|
+
color: var(--_danger, var(--_text));
|
|
624
786
|
}
|
|
625
787
|
|
|
626
788
|
.message--assistant blockquote {
|
|
627
789
|
padding-left: 10px;
|
|
628
|
-
border-left: 3px solid var(--
|
|
629
|
-
color: var(--
|
|
790
|
+
border-left: 3px solid var(--_border);
|
|
791
|
+
color: var(--_muted);
|
|
630
792
|
}
|
|
631
793
|
|
|
632
794
|
/* Markdown tables. table/thead/tbody/tr/th/td are all in
|
|
@@ -647,13 +809,13 @@ export const STYLES = `
|
|
|
647
809
|
.message--assistant th,
|
|
648
810
|
.message--assistant td {
|
|
649
811
|
padding: 6px 10px;
|
|
650
|
-
border: 1px solid var(--
|
|
812
|
+
border: 1px solid var(--_border);
|
|
651
813
|
text-align: left;
|
|
652
814
|
vertical-align: top;
|
|
653
815
|
}
|
|
654
816
|
|
|
655
817
|
.message--assistant th {
|
|
656
|
-
background: var(--
|
|
818
|
+
background: var(--_hover);
|
|
657
819
|
font-weight: 600;
|
|
658
820
|
}
|
|
659
821
|
|
|
@@ -663,7 +825,7 @@ export const STYLES = `
|
|
|
663
825
|
gap: 4px;
|
|
664
826
|
align-items: center;
|
|
665
827
|
padding: 12px 14px;
|
|
666
|
-
background: var(--
|
|
828
|
+
background: var(--_assistant-bg);
|
|
667
829
|
border-radius: 14px;
|
|
668
830
|
border-bottom-left-radius: 4px;
|
|
669
831
|
}
|
|
@@ -672,7 +834,7 @@ export const STYLES = `
|
|
|
672
834
|
width: 6px;
|
|
673
835
|
height: 6px;
|
|
674
836
|
border-radius: 50%;
|
|
675
|
-
background: var(--
|
|
837
|
+
background: var(--_muted);
|
|
676
838
|
animation: ag-ui-pending 1.2s infinite ease-in-out both;
|
|
677
839
|
}
|
|
678
840
|
|
|
@@ -705,7 +867,7 @@ export const STYLES = `
|
|
|
705
867
|
flex-direction: column;
|
|
706
868
|
gap: 4px;
|
|
707
869
|
font-size: 12px;
|
|
708
|
-
color: var(--
|
|
870
|
+
color: var(--_muted);
|
|
709
871
|
}
|
|
710
872
|
|
|
711
873
|
.thoughts-toggle {
|
|
@@ -716,7 +878,7 @@ export const STYLES = `
|
|
|
716
878
|
font: inherit;
|
|
717
879
|
font-size: 12px;
|
|
718
880
|
font-weight: 600;
|
|
719
|
-
color: var(--
|
|
881
|
+
color: var(--_muted);
|
|
720
882
|
cursor: pointer;
|
|
721
883
|
}
|
|
722
884
|
|
|
@@ -741,7 +903,7 @@ export const STYLES = `
|
|
|
741
903
|
.thoughts-body {
|
|
742
904
|
margin: 0;
|
|
743
905
|
padding: 4px 0 4px 10px;
|
|
744
|
-
border-left: 2px solid var(--
|
|
906
|
+
border-left: 2px solid var(--_border);
|
|
745
907
|
max-height: 220px;
|
|
746
908
|
overflow: auto;
|
|
747
909
|
white-space: pre-wrap;
|
|
@@ -770,9 +932,9 @@ export const STYLES = `
|
|
|
770
932
|
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
771
933
|
padding: 8px 10px;
|
|
772
934
|
border-radius: 8px;
|
|
773
|
-
background: var(--
|
|
774
|
-
border: 1px solid var(--
|
|
775
|
-
color: var(--
|
|
935
|
+
background: var(--_tool-bg);
|
|
936
|
+
border: 1px solid var(--_border);
|
|
937
|
+
color: var(--_tool-fg);
|
|
776
938
|
}
|
|
777
939
|
|
|
778
940
|
.tool-call-head {
|
|
@@ -805,10 +967,10 @@ export const STYLES = `
|
|
|
805
967
|
|
|
806
968
|
/* Pending: a real spinning ring. Speed is tunable; reduced motion stops it. */
|
|
807
969
|
.tool-call[data-status="pending"] .tool-call-icon {
|
|
808
|
-
border: 2px solid var(--
|
|
970
|
+
border: 2px solid var(--_muted);
|
|
809
971
|
border-top-color: transparent;
|
|
810
972
|
border-radius: 50%;
|
|
811
|
-
animation: ag-ui-tool-spin var(--
|
|
973
|
+
animation: ag-ui-tool-spin var(--_tool-spin-duration) linear infinite;
|
|
812
974
|
}
|
|
813
975
|
|
|
814
976
|
@keyframes ag-ui-tool-spin {
|
|
@@ -817,18 +979,18 @@ export const STYLES = `
|
|
|
817
979
|
|
|
818
980
|
/* Settled: a themeable glyph coloured by outcome. */
|
|
819
981
|
.tool-call[data-status="done"] .tool-call-icon::before {
|
|
820
|
-
content: var(--
|
|
821
|
-
color: var(--
|
|
982
|
+
content: var(--_tool-icon-done);
|
|
983
|
+
color: var(--_success);
|
|
822
984
|
}
|
|
823
985
|
|
|
824
986
|
.tool-call[data-status="error"] .tool-call-icon::before {
|
|
825
|
-
content: var(--
|
|
826
|
-
color: var(--
|
|
987
|
+
content: var(--_tool-icon-error);
|
|
988
|
+
color: var(--_danger);
|
|
827
989
|
}
|
|
828
990
|
|
|
829
991
|
.tool-call[data-status="declined"] .tool-call-icon::before {
|
|
830
|
-
content: var(--
|
|
831
|
-
color: var(--
|
|
992
|
+
content: var(--_tool-icon-declined);
|
|
993
|
+
color: var(--_muted);
|
|
832
994
|
}
|
|
833
995
|
|
|
834
996
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -854,19 +1016,19 @@ export const STYLES = `
|
|
|
854
1016
|
font-size: 11px;
|
|
855
1017
|
font-weight: 600;
|
|
856
1018
|
background: rgba(127, 127, 127, 0.16);
|
|
857
|
-
color: var(--
|
|
1019
|
+
color: var(--_muted);
|
|
858
1020
|
}
|
|
859
1021
|
|
|
860
1022
|
.tool-call[data-status="done"] .tool-call-status {
|
|
861
|
-
color: var(--
|
|
1023
|
+
color: var(--_success);
|
|
862
1024
|
}
|
|
863
1025
|
|
|
864
1026
|
.tool-call[data-status="error"] .tool-call-status {
|
|
865
|
-
color: var(--
|
|
1027
|
+
color: var(--_danger);
|
|
866
1028
|
}
|
|
867
1029
|
|
|
868
1030
|
.tool-call[data-status="declined"] .tool-call-status {
|
|
869
|
-
color: var(--
|
|
1031
|
+
color: var(--_muted);
|
|
870
1032
|
}
|
|
871
1033
|
|
|
872
1034
|
.tool-call-body {
|
|
@@ -888,7 +1050,7 @@ export const STYLES = `
|
|
|
888
1050
|
font-weight: 700;
|
|
889
1051
|
letter-spacing: 0.06em;
|
|
890
1052
|
text-transform: uppercase;
|
|
891
|
-
color: var(--
|
|
1053
|
+
color: var(--_muted);
|
|
892
1054
|
}
|
|
893
1055
|
|
|
894
1056
|
/* The record of a human decision on a gated call. An approved call used to
|
|
@@ -896,7 +1058,7 @@ export const STYLES = `
|
|
|
896
1058
|
.skill-item-token {
|
|
897
1059
|
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
898
1060
|
font-size: 0.92em;
|
|
899
|
-
color: var(--
|
|
1061
|
+
color: var(--_accent);
|
|
900
1062
|
margin-right: 6px;
|
|
901
1063
|
}
|
|
902
1064
|
|
|
@@ -904,7 +1066,7 @@ export const STYLES = `
|
|
|
904
1066
|
flex: none;
|
|
905
1067
|
font-size: 11px;
|
|
906
1068
|
font-style: italic;
|
|
907
|
-
color: var(--
|
|
1069
|
+
color: var(--_muted);
|
|
908
1070
|
}
|
|
909
1071
|
|
|
910
1072
|
.tool-call-args,
|
|
@@ -913,12 +1075,12 @@ export const STYLES = `
|
|
|
913
1075
|
padding: 6px 8px;
|
|
914
1076
|
max-height: 160px;
|
|
915
1077
|
overflow: auto;
|
|
916
|
-
background: var(--
|
|
917
|
-
border: 1px solid var(--
|
|
1078
|
+
background: var(--_bg);
|
|
1079
|
+
border: 1px solid var(--_border);
|
|
918
1080
|
border-radius: 6px;
|
|
919
1081
|
white-space: pre-wrap;
|
|
920
1082
|
word-break: break-word;
|
|
921
|
-
color: var(--
|
|
1083
|
+
color: var(--_fg);
|
|
922
1084
|
}
|
|
923
1085
|
|
|
924
1086
|
/* Display modes are pure visibility over one DOM shape, selected from the host
|
|
@@ -965,7 +1127,7 @@ export const STYLES = `
|
|
|
965
1127
|
background: none;
|
|
966
1128
|
font: inherit;
|
|
967
1129
|
font-weight: 600;
|
|
968
|
-
color: var(--
|
|
1130
|
+
color: var(--_accent);
|
|
969
1131
|
cursor: pointer;
|
|
970
1132
|
}
|
|
971
1133
|
|
|
@@ -988,13 +1150,12 @@ export const STYLES = `
|
|
|
988
1150
|
}
|
|
989
1151
|
|
|
990
1152
|
.resize-handle:focus-visible {
|
|
991
|
-
outline: 2px solid var(--
|
|
1153
|
+
outline: 2px solid var(--_accent);
|
|
992
1154
|
outline-offset: -2px;
|
|
993
1155
|
}
|
|
994
1156
|
|
|
995
1157
|
/* The grip sits on the corner opposite the panel's anchor, because a resize
|
|
996
|
-
measures from whichever edge is not moving.
|
|
997
|
-
so switching placement moves the grip immediately.
|
|
1158
|
+
measures from whichever edge is not moving.
|
|
998
1159
|
|
|
999
1160
|
Default is floating: pinned bottom-right, so the grip is top-left. */
|
|
1000
1161
|
.resize-handle {
|
|
@@ -1005,7 +1166,9 @@ export const STYLES = `
|
|
|
1005
1166
|
cursor: nwse-resize;
|
|
1006
1167
|
}
|
|
1007
1168
|
|
|
1008
|
-
/*
|
|
1169
|
+
/* Placement is only the opening guess, and these two rules are all it is good
|
|
1170
|
+
for. Embedded sits in normal flow, pinned top-left, so it grows bottom-right;
|
|
1171
|
+
bottom-left is pinned there, so its free corner is top-right. */
|
|
1009
1172
|
:host([placement="embedded"]) .resize-handle {
|
|
1010
1173
|
top: auto;
|
|
1011
1174
|
left: auto;
|
|
@@ -1014,16 +1177,64 @@ export const STYLES = `
|
|
|
1014
1177
|
cursor: nwse-resize;
|
|
1015
1178
|
}
|
|
1016
1179
|
|
|
1017
|
-
/* Pinned bottom-left, so the free corner is top-right. */
|
|
1018
1180
|
:host([placement="bottom-left"]) .resize-handle {
|
|
1019
1181
|
left: auto;
|
|
1020
1182
|
right: 0;
|
|
1021
1183
|
cursor: nesw-resize;
|
|
1022
1184
|
}
|
|
1023
1185
|
|
|
1024
|
-
/*
|
|
1186
|
+
/* Then the measurement corrects it. Which edges are held still belongs to the
|
|
1187
|
+
host's layout rather than to placement -- a floating panel a host right-aligns
|
|
1188
|
+
is anchored bottom-left, not bottom-right -- so the element measures the edges
|
|
1189
|
+
that stay put and stamps them here as "<y>-<x>". Equal specificity to the
|
|
1190
|
+
rules above, so source order is what lets the measured value win.
|
|
1191
|
+
|
|
1192
|
+
These must not be written as [data-resize-anchor~="left"]: the stamped value
|
|
1193
|
+
is one hyphenated token, and ~= matches whitespace-separated words, so such a
|
|
1194
|
+
selector cannot ever match. It did not, which left the grip drawn at the
|
|
1195
|
+
corner that moves while the cursor pointed along the right diagonal.
|
|
1196
|
+
|
|
1197
|
+
Each rule also sets both sides of its axis rather than only the side it
|
|
1198
|
+
moves. One that flipped a single way could not undo a placement guess that
|
|
1199
|
+
had flipped the other, which put the grip on the anchored corner for an
|
|
1200
|
+
embedded panel its host right-aligns. */
|
|
1201
|
+
:host([data-resize-anchor$="-left"]) .resize-handle {
|
|
1202
|
+
left: auto;
|
|
1203
|
+
right: 0;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
:host([data-resize-anchor$="-right"]) .resize-handle {
|
|
1207
|
+
left: 0;
|
|
1208
|
+
right: auto;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
:host([data-resize-anchor^="top-"]) .resize-handle {
|
|
1212
|
+
top: auto;
|
|
1213
|
+
bottom: 0;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
:host([data-resize-anchor^="bottom-"]) .resize-handle {
|
|
1217
|
+
top: 0;
|
|
1218
|
+
bottom: auto;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/* One axis flipped means the drag runs along the other diagonal. */
|
|
1222
|
+
:host([data-resize-anchor="top-left"]) .resize-handle,
|
|
1223
|
+
:host([data-resize-anchor="bottom-right"]) .resize-handle {
|
|
1224
|
+
cursor: nwse-resize;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
:host([data-resize-anchor="top-right"]) .resize-handle,
|
|
1228
|
+
:host([data-resize-anchor="bottom-left"]) .resize-handle {
|
|
1229
|
+
cursor: nesw-resize;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/* Docked: the placement owns the height, so only the inner edge is the user's --
|
|
1233
|
+
an edge, not a corner, so this outranks the measured anchor by coming after. */
|
|
1025
1234
|
:host([placement="sidebar"]) .resize-handle,
|
|
1026
1235
|
:host([placement="side"]) .resize-handle {
|
|
1236
|
+
top: 0;
|
|
1237
|
+
bottom: auto;
|
|
1027
1238
|
width: 8px;
|
|
1028
1239
|
height: 100%;
|
|
1029
1240
|
cursor: ew-resize;
|
|
@@ -1042,106 +1253,191 @@ export const STYLES = `
|
|
|
1042
1253
|
}
|
|
1043
1254
|
|
|
1044
1255
|
.resize-handle[data-dragging] {
|
|
1045
|
-
background: var(--
|
|
1256
|
+
background: var(--_accent);
|
|
1046
1257
|
opacity: 0.35;
|
|
1047
1258
|
}
|
|
1048
1259
|
|
|
1260
|
+
/* ── Composer ───────────────────────────────────────────────────────────────
|
|
1261
|
+
One surface owns the border, the background and the focus ring; the field and
|
|
1262
|
+
its tool row sit inside it. The row used to be four siblings stretched to the
|
|
1263
|
+
textarea's height, which gave a paperclip the same visual weight as the field
|
|
1264
|
+
and turned Send into a full-height slab. */
|
|
1049
1265
|
.input-row {
|
|
1050
1266
|
display: flex;
|
|
1051
|
-
gap: 8px;
|
|
1052
1267
|
padding: 12px;
|
|
1053
|
-
border-top: 1px solid var(--
|
|
1268
|
+
border-top: 1px solid var(--_border);
|
|
1054
1269
|
}
|
|
1055
1270
|
|
|
1056
|
-
.
|
|
1271
|
+
.composer {
|
|
1057
1272
|
flex: 1;
|
|
1273
|
+
min-width: 0;
|
|
1274
|
+
display: flex;
|
|
1275
|
+
flex-direction: column;
|
|
1276
|
+
gap: 4px;
|
|
1277
|
+
padding: 6px 6px 6px 10px;
|
|
1278
|
+
background: var(--_input-bg);
|
|
1279
|
+
border: 1px solid var(--_border);
|
|
1280
|
+
border-radius: var(--_composer-radius);
|
|
1281
|
+
transition: border-color var(--_motion) var(--_ease);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
.composer:focus-within {
|
|
1285
|
+
border-color: var(--_accent);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/* The field grows with its content (sized by #autoGrow) up to the ceiling,
|
|
1289
|
+
then scrolls. border-box keeps that measurement stable: with content-box the
|
|
1290
|
+
padding would be added to every scrollHeight read and the field would creep
|
|
1291
|
+
taller on each keystroke. */
|
|
1292
|
+
.input {
|
|
1293
|
+
box-sizing: border-box;
|
|
1058
1294
|
resize: none;
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1295
|
+
max-height: var(--_composer-max-height);
|
|
1296
|
+
overflow-y: auto;
|
|
1297
|
+
padding: 6px 4px 2px;
|
|
1298
|
+
background: transparent;
|
|
1299
|
+
border: none;
|
|
1063
1300
|
font: inherit;
|
|
1064
1301
|
color: inherit;
|
|
1065
1302
|
outline: none;
|
|
1066
1303
|
}
|
|
1067
1304
|
|
|
1068
|
-
.
|
|
1069
|
-
|
|
1305
|
+
.composer-tools {
|
|
1306
|
+
display: flex;
|
|
1307
|
+
align-items: center;
|
|
1308
|
+
gap: 2px;
|
|
1070
1309
|
}
|
|
1071
1310
|
|
|
1072
|
-
.
|
|
1311
|
+
/* Icon buttons: quiet at rest, so the field is what the eye lands on. */
|
|
1312
|
+
.attach-btn,
|
|
1313
|
+
.voice-btn {
|
|
1314
|
+
display: inline-flex;
|
|
1315
|
+
align-items: center;
|
|
1316
|
+
justify-content: center;
|
|
1317
|
+
width: var(--_tool-btn-size);
|
|
1318
|
+
height: var(--_tool-btn-size);
|
|
1319
|
+
padding: 0;
|
|
1073
1320
|
border: none;
|
|
1074
1321
|
border-radius: 8px;
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
color: #ffffff;
|
|
1322
|
+
background: transparent;
|
|
1323
|
+
color: var(--_muted);
|
|
1078
1324
|
font: inherit;
|
|
1079
|
-
|
|
1325
|
+
line-height: 1;
|
|
1080
1326
|
cursor: pointer;
|
|
1327
|
+
transition:
|
|
1328
|
+
background-color var(--_motion) var(--_ease),
|
|
1329
|
+
color var(--_motion) var(--_ease);
|
|
1081
1330
|
}
|
|
1082
1331
|
|
|
1083
|
-
.
|
|
1084
|
-
|
|
1085
|
-
|
|
1332
|
+
.attach-btn:hover,
|
|
1333
|
+
.voice-btn:hover {
|
|
1334
|
+
background: var(--_hover);
|
|
1335
|
+
color: var(--_fg);
|
|
1086
1336
|
}
|
|
1087
1337
|
|
|
1088
|
-
|
|
1089
|
-
.
|
|
1090
|
-
|
|
1338
|
+
.attach-btn:disabled,
|
|
1339
|
+
.voice-btn:disabled {
|
|
1340
|
+
cursor: default;
|
|
1341
|
+
opacity: 0.6;
|
|
1091
1342
|
}
|
|
1092
1343
|
|
|
1093
|
-
/*
|
|
1094
|
-
|
|
1095
|
-
.
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1344
|
+
/* Send closes the row on the right: a circle, the only filled control in the
|
|
1345
|
+
composer, so "the thing that acts" reads at a glance. */
|
|
1346
|
+
.send {
|
|
1347
|
+
margin-left: auto;
|
|
1348
|
+
display: inline-flex;
|
|
1349
|
+
align-items: center;
|
|
1350
|
+
justify-content: center;
|
|
1351
|
+
flex: none;
|
|
1352
|
+
width: var(--_send-size);
|
|
1353
|
+
height: var(--_send-size);
|
|
1354
|
+
padding: 0;
|
|
1355
|
+
border: none;
|
|
1356
|
+
border-radius: 50%;
|
|
1357
|
+
background: var(--_accent);
|
|
1358
|
+
color: #ffffff;
|
|
1101
1359
|
font: inherit;
|
|
1360
|
+
line-height: 1;
|
|
1102
1361
|
cursor: pointer;
|
|
1362
|
+
transition:
|
|
1363
|
+
background-color var(--_motion) var(--_ease),
|
|
1364
|
+
transform var(--_motion) var(--_ease-pop);
|
|
1103
1365
|
}
|
|
1104
1366
|
|
|
1105
|
-
.
|
|
1106
|
-
|
|
1367
|
+
.send:hover {
|
|
1368
|
+
transform: scale(1.08);
|
|
1107
1369
|
}
|
|
1108
1370
|
|
|
1109
|
-
.
|
|
1371
|
+
.send:active {
|
|
1372
|
+
transform: scale(0.92);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
.send:disabled {
|
|
1376
|
+
opacity: 0.5;
|
|
1377
|
+
cursor: default;
|
|
1378
|
+
transform: none;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/* The composer button doubles as the Stop control while a run is in flight —
|
|
1382
|
+
same circle, different glyph, so nothing moves when a run starts. */
|
|
1383
|
+
.send[data-state="running"] {
|
|
1384
|
+
background: var(--_muted);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
.send[data-state="idle"] .send-stop,
|
|
1388
|
+
.send[data-state="running"] .send-send {
|
|
1110
1389
|
display: none;
|
|
1111
1390
|
}
|
|
1112
1391
|
|
|
1113
|
-
/*
|
|
1114
|
-
.
|
|
1115
|
-
|
|
1392
|
+
/* Glyphs — one class, painted from the button's own colour so every state
|
|
1393
|
+
(hover, recording, running) carries the icon with it. */
|
|
1394
|
+
.glyph {
|
|
1395
|
+
width: var(--_glyph-size);
|
|
1396
|
+
height: var(--_glyph-size);
|
|
1397
|
+
fill: none;
|
|
1398
|
+
stroke: currentColor;
|
|
1399
|
+
stroke-width: var(--_glyph-stroke);
|
|
1400
|
+
stroke-linecap: round;
|
|
1401
|
+
stroke-linejoin: round;
|
|
1116
1402
|
}
|
|
1117
1403
|
|
|
1118
|
-
.
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
padding: 0 10px;
|
|
1122
|
-
background: var(--ag-ui-input-bg);
|
|
1123
|
-
color: inherit;
|
|
1124
|
-
font: inherit;
|
|
1125
|
-
cursor: pointer;
|
|
1404
|
+
.glyph--solid {
|
|
1405
|
+
fill: currentColor;
|
|
1406
|
+
stroke: none;
|
|
1126
1407
|
}
|
|
1127
1408
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1409
|
+
/* In an icon holder (header brand, launcher) the glyph takes the holder's size
|
|
1410
|
+
rather than the composer's. */
|
|
1411
|
+
.icon-holder .glyph {
|
|
1412
|
+
width: 100%;
|
|
1413
|
+
height: 100%;
|
|
1130
1414
|
}
|
|
1131
1415
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1416
|
+
/* ── File attachments ───────────────────────────────────────────────────── */
|
|
1417
|
+
/* The picker button sits in the composer's tool row; hidden until
|
|
1418
|
+
data-attachments-url. */
|
|
1419
|
+
.attach-input {
|
|
1420
|
+
display: none;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/* The mic button's mount point; filled only once #wireVoice mounts the
|
|
1424
|
+
control. */
|
|
1425
|
+
.voice-slot {
|
|
1426
|
+
display: contents;
|
|
1135
1427
|
}
|
|
1136
1428
|
|
|
1137
1429
|
/* Recording: a red tint + a gentle pulse so it's clearly "live". */
|
|
1138
1430
|
.voice-btn[data-state="recording"] {
|
|
1139
|
-
|
|
1140
|
-
background: var(--ag-ui-danger);
|
|
1431
|
+
background: var(--_danger);
|
|
1141
1432
|
color: #ffffff;
|
|
1142
1433
|
animation: ag-ui-voice-pulse 1.2s ease-in-out infinite;
|
|
1143
1434
|
}
|
|
1144
1435
|
|
|
1436
|
+
.voice-btn[data-state="recording"]:hover {
|
|
1437
|
+
background: var(--_danger);
|
|
1438
|
+
color: #ffffff;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1145
1441
|
@keyframes ag-ui-voice-pulse {
|
|
1146
1442
|
0%, 100% { opacity: 1; }
|
|
1147
1443
|
50% { opacity: 0.6; }
|
|
@@ -1180,10 +1476,10 @@ export const STYLES = `
|
|
|
1180
1476
|
max-width: 100%;
|
|
1181
1477
|
margin: 2px 0;
|
|
1182
1478
|
padding: 3px 10px;
|
|
1183
|
-
border: 1px dashed var(--
|
|
1479
|
+
border: 1px dashed var(--_border);
|
|
1184
1480
|
border-radius: 999px;
|
|
1185
1481
|
background: transparent;
|
|
1186
|
-
color: var(--
|
|
1482
|
+
color: var(--_muted);
|
|
1187
1483
|
font-size: 0.8em;
|
|
1188
1484
|
line-height: 1.4;
|
|
1189
1485
|
}
|
|
@@ -1204,16 +1500,16 @@ export const STYLES = `
|
|
|
1204
1500
|
gap: 6px;
|
|
1205
1501
|
max-width: 100%;
|
|
1206
1502
|
padding: 4px 8px;
|
|
1207
|
-
border: 1px solid var(--
|
|
1503
|
+
border: 1px solid var(--_border);
|
|
1208
1504
|
border-radius: 999px;
|
|
1209
|
-
background: var(--
|
|
1505
|
+
background: var(--_assistant-bg);
|
|
1210
1506
|
font-size: 0.85em;
|
|
1211
1507
|
position: relative;
|
|
1212
1508
|
}
|
|
1213
1509
|
|
|
1214
1510
|
.attachment-chip--error {
|
|
1215
|
-
border-color: var(--
|
|
1216
|
-
color: var(--
|
|
1511
|
+
border-color: var(--_danger);
|
|
1512
|
+
color: var(--_danger);
|
|
1217
1513
|
}
|
|
1218
1514
|
|
|
1219
1515
|
.attachment-chip-name {
|
|
@@ -1224,12 +1520,12 @@ export const STYLES = `
|
|
|
1224
1520
|
}
|
|
1225
1521
|
|
|
1226
1522
|
.attachment-chip-size {
|
|
1227
|
-
color: var(--
|
|
1523
|
+
color: var(--_muted);
|
|
1228
1524
|
white-space: nowrap;
|
|
1229
1525
|
}
|
|
1230
1526
|
|
|
1231
1527
|
.attachment-chip--error .attachment-chip-size {
|
|
1232
|
-
color: var(--
|
|
1528
|
+
color: var(--_danger);
|
|
1233
1529
|
}
|
|
1234
1530
|
|
|
1235
1531
|
/* The progress bar fills as the file uploads. */
|
|
@@ -1237,13 +1533,13 @@ export const STYLES = `
|
|
|
1237
1533
|
flex-basis: 100%;
|
|
1238
1534
|
height: 3px;
|
|
1239
1535
|
border-radius: 2px;
|
|
1240
|
-
background: var(--
|
|
1536
|
+
background: var(--_border);
|
|
1241
1537
|
overflow: hidden;
|
|
1242
1538
|
}
|
|
1243
1539
|
|
|
1244
1540
|
.attachment-chip-bar-fill {
|
|
1245
1541
|
height: 100%;
|
|
1246
|
-
background: var(--
|
|
1542
|
+
background: var(--_accent);
|
|
1247
1543
|
transition: width 0.15s ease;
|
|
1248
1544
|
}
|
|
1249
1545
|
|
|
@@ -1265,14 +1561,14 @@ export const STYLES = `
|
|
|
1265
1561
|
|
|
1266
1562
|
/* A subtle outline while a file is dragged over the shell. */
|
|
1267
1563
|
.chat--dragover {
|
|
1268
|
-
outline: 2px dashed var(--
|
|
1564
|
+
outline: 2px dashed var(--_accent);
|
|
1269
1565
|
outline-offset: -4px;
|
|
1270
1566
|
}
|
|
1271
1567
|
|
|
1272
1568
|
/* Muted "⏹ Stopped" line after a cancelled run — a note, not an error bubble. */
|
|
1273
1569
|
.stopped-note {
|
|
1274
1570
|
align-self: flex-start;
|
|
1275
|
-
color: var(--
|
|
1571
|
+
color: var(--_muted);
|
|
1276
1572
|
font-size: 12px;
|
|
1277
1573
|
padding: 2px 4px;
|
|
1278
1574
|
}
|
|
@@ -1285,14 +1581,14 @@ export const STYLES = `
|
|
|
1285
1581
|
flex-direction: column;
|
|
1286
1582
|
gap: 8px;
|
|
1287
1583
|
padding: 12px;
|
|
1288
|
-
background: var(--
|
|
1289
|
-
border: 1px solid var(--
|
|
1584
|
+
background: var(--_bg);
|
|
1585
|
+
border: 1px solid var(--_accent);
|
|
1290
1586
|
border-radius: 10px;
|
|
1291
1587
|
}
|
|
1292
1588
|
|
|
1293
1589
|
.confirm[data-resolved] {
|
|
1294
1590
|
opacity: 0.7;
|
|
1295
|
-
border-color: var(--
|
|
1591
|
+
border-color: var(--_border);
|
|
1296
1592
|
}
|
|
1297
1593
|
|
|
1298
1594
|
.confirm-body {
|
|
@@ -1306,7 +1602,7 @@ export const STYLES = `
|
|
|
1306
1602
|
overflow: auto;
|
|
1307
1603
|
font-size: 12px;
|
|
1308
1604
|
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
1309
|
-
background: var(--
|
|
1605
|
+
background: var(--_assistant-bg);
|
|
1310
1606
|
border-radius: 8px;
|
|
1311
1607
|
white-space: pre-wrap;
|
|
1312
1608
|
word-break: break-word;
|
|
@@ -1319,14 +1615,14 @@ export const STYLES = `
|
|
|
1319
1615
|
}
|
|
1320
1616
|
|
|
1321
1617
|
.confirm-btn {
|
|
1322
|
-
border: 1px solid var(--
|
|
1618
|
+
border: 1px solid var(--_border);
|
|
1323
1619
|
border-radius: 8px;
|
|
1324
1620
|
padding: 8px 14px;
|
|
1325
1621
|
font: inherit;
|
|
1326
1622
|
font-weight: 600;
|
|
1327
1623
|
cursor: pointer;
|
|
1328
|
-
background: var(--
|
|
1329
|
-
color: var(--
|
|
1624
|
+
background: var(--_bg);
|
|
1625
|
+
color: var(--_fg);
|
|
1330
1626
|
}
|
|
1331
1627
|
|
|
1332
1628
|
.confirm-btn:disabled {
|
|
@@ -1335,8 +1631,8 @@ export const STYLES = `
|
|
|
1335
1631
|
}
|
|
1336
1632
|
|
|
1337
1633
|
.confirm-btn--confirm {
|
|
1338
|
-
border-color: var(--
|
|
1339
|
-
background: var(--
|
|
1634
|
+
border-color: var(--_accent);
|
|
1635
|
+
background: var(--_accent);
|
|
1340
1636
|
color: #ffffff;
|
|
1341
1637
|
}
|
|
1342
1638
|
|
|
@@ -1348,14 +1644,14 @@ export const STYLES = `
|
|
|
1348
1644
|
flex-direction: column;
|
|
1349
1645
|
gap: 8px;
|
|
1350
1646
|
padding: 12px;
|
|
1351
|
-
background: var(--
|
|
1352
|
-
border: 1px solid var(--
|
|
1647
|
+
background: var(--_bg);
|
|
1648
|
+
border: 1px solid var(--_accent);
|
|
1353
1649
|
border-radius: 10px;
|
|
1354
1650
|
}
|
|
1355
1651
|
|
|
1356
1652
|
.approval[data-resolved] {
|
|
1357
1653
|
opacity: 0.7;
|
|
1358
|
-
border-color: var(--
|
|
1654
|
+
border-color: var(--_border);
|
|
1359
1655
|
}
|
|
1360
1656
|
|
|
1361
1657
|
.approval-body {
|
|
@@ -1369,14 +1665,14 @@ export const STYLES = `
|
|
|
1369
1665
|
}
|
|
1370
1666
|
|
|
1371
1667
|
.approval-btn {
|
|
1372
|
-
border: 1px solid var(--
|
|
1668
|
+
border: 1px solid var(--_border);
|
|
1373
1669
|
border-radius: 8px;
|
|
1374
1670
|
padding: 8px 14px;
|
|
1375
1671
|
font: inherit;
|
|
1376
1672
|
font-weight: 600;
|
|
1377
1673
|
cursor: pointer;
|
|
1378
|
-
background: var(--
|
|
1379
|
-
color: var(--
|
|
1674
|
+
background: var(--_bg);
|
|
1675
|
+
color: var(--_fg);
|
|
1380
1676
|
}
|
|
1381
1677
|
|
|
1382
1678
|
.approval-btn:disabled {
|
|
@@ -1385,8 +1681,8 @@ export const STYLES = `
|
|
|
1385
1681
|
}
|
|
1386
1682
|
|
|
1387
1683
|
.approval-btn--approve {
|
|
1388
|
-
border-color: var(--
|
|
1389
|
-
background: var(--
|
|
1684
|
+
border-color: var(--_accent);
|
|
1685
|
+
background: var(--_accent);
|
|
1390
1686
|
color: #ffffff;
|
|
1391
1687
|
}
|
|
1392
1688
|
|
|
@@ -1398,14 +1694,14 @@ export const STYLES = `
|
|
|
1398
1694
|
flex-direction: column;
|
|
1399
1695
|
gap: 8px;
|
|
1400
1696
|
padding: 12px;
|
|
1401
|
-
background: var(--
|
|
1402
|
-
border: 1px solid var(--
|
|
1697
|
+
background: var(--_bg);
|
|
1698
|
+
border: 1px solid var(--_accent);
|
|
1403
1699
|
border-radius: 10px;
|
|
1404
1700
|
}
|
|
1405
1701
|
|
|
1406
1702
|
.question[data-resolved] {
|
|
1407
1703
|
opacity: 0.7;
|
|
1408
|
-
border-color: var(--
|
|
1704
|
+
border-color: var(--_border);
|
|
1409
1705
|
}
|
|
1410
1706
|
|
|
1411
1707
|
.question-body {
|
|
@@ -1430,9 +1726,9 @@ export const STYLES = `
|
|
|
1430
1726
|
width: 100%;
|
|
1431
1727
|
padding: 8px 10px;
|
|
1432
1728
|
font: inherit;
|
|
1433
|
-
color: var(--
|
|
1434
|
-
background: var(--
|
|
1435
|
-
border: 1px solid var(--
|
|
1729
|
+
color: var(--_fg);
|
|
1730
|
+
background: var(--_bg);
|
|
1731
|
+
border: 1px solid var(--_border);
|
|
1436
1732
|
border-radius: 8px;
|
|
1437
1733
|
}
|
|
1438
1734
|
|
|
@@ -1446,13 +1742,13 @@ export const STYLES = `
|
|
|
1446
1742
|
}
|
|
1447
1743
|
|
|
1448
1744
|
.question-btn {
|
|
1449
|
-
border: 1px solid var(--
|
|
1745
|
+
border: 1px solid var(--_accent);
|
|
1450
1746
|
border-radius: 8px;
|
|
1451
1747
|
padding: 8px 14px;
|
|
1452
1748
|
font: inherit;
|
|
1453
1749
|
font-weight: 600;
|
|
1454
1750
|
cursor: pointer;
|
|
1455
|
-
background: var(--
|
|
1751
|
+
background: var(--_accent);
|
|
1456
1752
|
color: #ffffff;
|
|
1457
1753
|
}
|
|
1458
1754
|
|
|
@@ -1470,18 +1766,18 @@ export const STYLES = `
|
|
|
1470
1766
|
}
|
|
1471
1767
|
|
|
1472
1768
|
.skill-chip {
|
|
1473
|
-
border: 1px solid var(--
|
|
1769
|
+
border: 1px solid var(--_border);
|
|
1474
1770
|
border-radius: 999px;
|
|
1475
1771
|
padding: 4px 12px;
|
|
1476
1772
|
font: inherit;
|
|
1477
1773
|
font-size: 0.9em;
|
|
1478
1774
|
cursor: pointer;
|
|
1479
|
-
background: var(--
|
|
1480
|
-
color: var(--
|
|
1775
|
+
background: var(--_assistant-bg);
|
|
1776
|
+
color: var(--_fg);
|
|
1481
1777
|
}
|
|
1482
1778
|
|
|
1483
1779
|
.skill-chip:hover {
|
|
1484
|
-
border-color: var(--
|
|
1780
|
+
border-color: var(--_accent);
|
|
1485
1781
|
}
|
|
1486
1782
|
|
|
1487
1783
|
.skill-palette {
|
|
@@ -1490,8 +1786,8 @@ export const STYLES = `
|
|
|
1490
1786
|
flex-direction: column;
|
|
1491
1787
|
max-height: 220px;
|
|
1492
1788
|
overflow: auto;
|
|
1493
|
-
background: var(--
|
|
1494
|
-
border: 1px solid var(--
|
|
1789
|
+
background: var(--_bg);
|
|
1790
|
+
border: 1px solid var(--_border);
|
|
1495
1791
|
border-radius: 8px;
|
|
1496
1792
|
box-shadow: 0 8px 24px rgba(20, 20, 50, 0.16);
|
|
1497
1793
|
}
|
|
@@ -1507,11 +1803,11 @@ export const STYLES = `
|
|
|
1507
1803
|
font: inherit;
|
|
1508
1804
|
text-align: left;
|
|
1509
1805
|
cursor: pointer;
|
|
1510
|
-
color: var(--
|
|
1806
|
+
color: var(--_fg);
|
|
1511
1807
|
}
|
|
1512
1808
|
|
|
1513
1809
|
.skill-item[aria-selected="true"] {
|
|
1514
|
-
background: var(--
|
|
1810
|
+
background: var(--_assistant-bg);
|
|
1515
1811
|
}
|
|
1516
1812
|
|
|
1517
1813
|
.skill-item-title {
|
|
@@ -1520,7 +1816,7 @@ export const STYLES = `
|
|
|
1520
1816
|
|
|
1521
1817
|
.skill-item-desc {
|
|
1522
1818
|
font-size: 0.85em;
|
|
1523
|
-
color: var(--
|
|
1819
|
+
color: var(--_muted);
|
|
1524
1820
|
}
|
|
1525
1821
|
|
|
1526
1822
|
/* The hint sits directly above the composer's top border, so a zero bottom
|
|
@@ -1529,19 +1825,38 @@ export const STYLES = `
|
|
|
1529
1825
|
margin: 8px 12px;
|
|
1530
1826
|
font-size: 0.85em;
|
|
1531
1827
|
line-height: 1.4;
|
|
1532
|
-
color: var(--
|
|
1828
|
+
color: var(--_danger);
|
|
1533
1829
|
}
|
|
1534
1830
|
|
|
1535
|
-
/* Chat-history drawer — a slide-over within the chat panel.
|
|
1831
|
+
/* Chat-history drawer — a slide-over within the chat panel.
|
|
1832
|
+
The hidden attribute stays the single source of truth for open/closed (no
|
|
1833
|
+
JS-driven animation state): display is transitioned discretely, so on close
|
|
1834
|
+
the drawer stays displayed for the whole exit and is removed only at the end,
|
|
1835
|
+
which is what lets the backdrop fade and the panel slide out. */
|
|
1536
1836
|
.drawer {
|
|
1537
1837
|
position: absolute;
|
|
1538
1838
|
inset: 0;
|
|
1539
1839
|
z-index: 5;
|
|
1540
1840
|
display: flex;
|
|
1841
|
+
transition: visibility var(--_motion) var(--_ease);
|
|
1541
1842
|
}
|
|
1542
1843
|
|
|
1844
|
+
/* Closed. The overlay keeps its box (display, not none) so the backdrop and
|
|
1845
|
+
panel inside it stay rendered and can transition both ways; visibility is
|
|
1846
|
+
what takes the whole subtree out of the tab order, the a11y tree and hit
|
|
1847
|
+
testing at rest, and it holds off until the slide has finished. */
|
|
1543
1848
|
.drawer[hidden] {
|
|
1544
|
-
display:
|
|
1849
|
+
display: flex;
|
|
1850
|
+
visibility: hidden;
|
|
1851
|
+
pointer-events: none;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
.drawer[hidden] .drawer-backdrop {
|
|
1855
|
+
opacity: 0;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
.drawer[hidden] .drawer-panel {
|
|
1859
|
+
transform: translateX(-100%);
|
|
1545
1860
|
}
|
|
1546
1861
|
|
|
1547
1862
|
.checkpoints {
|
|
@@ -1553,16 +1868,27 @@ export const STYLES = `
|
|
|
1553
1868
|
flex-direction: column;
|
|
1554
1869
|
gap: 0.25rem;
|
|
1555
1870
|
padding: 0.5rem;
|
|
1556
|
-
border: 1px solid var(--
|
|
1871
|
+
border: 1px solid var(--_border);
|
|
1557
1872
|
border-radius: 0.5rem;
|
|
1558
|
-
background: var(--
|
|
1873
|
+
background: var(--_assistant-bg);
|
|
1559
1874
|
box-shadow: 0 6px 24px rgb(0 0 0 / 12%);
|
|
1560
1875
|
max-height: 60%;
|
|
1561
1876
|
overflow-y: auto;
|
|
1877
|
+
transform-origin: top center;
|
|
1878
|
+
transition:
|
|
1879
|
+
opacity var(--_motion) var(--_ease),
|
|
1880
|
+
transform var(--_motion) var(--_ease),
|
|
1881
|
+
visibility var(--_motion) var(--_ease);
|
|
1562
1882
|
}
|
|
1563
1883
|
|
|
1884
|
+
/* Same idiom as the drawer: laid out at rest, hidden by visibility, so the
|
|
1885
|
+
popover can animate open and closed. */
|
|
1564
1886
|
.checkpoints[hidden] {
|
|
1565
|
-
display:
|
|
1887
|
+
display: flex;
|
|
1888
|
+
visibility: hidden;
|
|
1889
|
+
pointer-events: none;
|
|
1890
|
+
opacity: 0;
|
|
1891
|
+
transform: scale(0.96) translateY(-6px);
|
|
1566
1892
|
}
|
|
1567
1893
|
|
|
1568
1894
|
.checkpoints-title {
|
|
@@ -1586,7 +1912,7 @@ export const STYLES = `
|
|
|
1586
1912
|
}
|
|
1587
1913
|
|
|
1588
1914
|
.checkpoint-row:hover {
|
|
1589
|
-
background: var(--
|
|
1915
|
+
background: var(--_hover);
|
|
1590
1916
|
}
|
|
1591
1917
|
|
|
1592
1918
|
.checkpoint-label {
|
|
@@ -1601,7 +1927,7 @@ export const STYLES = `
|
|
|
1601
1927
|
font-size: 0.6875rem;
|
|
1602
1928
|
padding: 0 0.375rem;
|
|
1603
1929
|
border-radius: 999px;
|
|
1604
|
-
background: var(--
|
|
1930
|
+
background: var(--_hover);
|
|
1605
1931
|
opacity: 0.8;
|
|
1606
1932
|
}
|
|
1607
1933
|
|
|
@@ -1610,20 +1936,22 @@ export const STYLES = `
|
|
|
1610
1936
|
font-size: 0.75rem;
|
|
1611
1937
|
cursor: pointer;
|
|
1612
1938
|
padding: 0.125rem 0.5rem;
|
|
1613
|
-
border: 1px solid var(--
|
|
1939
|
+
border: 1px solid var(--_border);
|
|
1614
1940
|
border-radius: 0.375rem;
|
|
1615
1941
|
background: transparent;
|
|
1616
1942
|
color: inherit;
|
|
1617
1943
|
}
|
|
1618
1944
|
|
|
1619
1945
|
.checkpoint-action:hover {
|
|
1620
|
-
background: var(--
|
|
1946
|
+
background: var(--_hover);
|
|
1621
1947
|
}
|
|
1622
1948
|
|
|
1623
1949
|
.drawer-backdrop {
|
|
1624
1950
|
position: absolute;
|
|
1625
1951
|
inset: 0;
|
|
1626
1952
|
background: rgba(20, 20, 50, 0.32);
|
|
1953
|
+
opacity: 1;
|
|
1954
|
+
transition: opacity var(--_motion) var(--_ease);
|
|
1627
1955
|
}
|
|
1628
1956
|
|
|
1629
1957
|
.drawer-panel {
|
|
@@ -1632,19 +1960,21 @@ export const STYLES = `
|
|
|
1632
1960
|
flex-direction: column;
|
|
1633
1961
|
width: min(300px, 85%);
|
|
1634
1962
|
height: 100%;
|
|
1635
|
-
background: var(--
|
|
1636
|
-
border-right: 1px solid var(--
|
|
1637
|
-
box-shadow: var(--
|
|
1963
|
+
background: var(--_bg);
|
|
1964
|
+
border-right: 1px solid var(--_border);
|
|
1965
|
+
box-shadow: var(--_shadow);
|
|
1638
1966
|
overflow: hidden;
|
|
1967
|
+
transform: none;
|
|
1968
|
+
transition: transform var(--_motion) var(--_ease);
|
|
1639
1969
|
}
|
|
1640
1970
|
|
|
1641
1971
|
.drawer-header {
|
|
1642
1972
|
display: flex;
|
|
1643
1973
|
align-items: center;
|
|
1644
1974
|
justify-content: space-between;
|
|
1645
|
-
gap: var(--
|
|
1646
|
-
padding: var(--
|
|
1647
|
-
border-bottom: 1px solid var(--
|
|
1975
|
+
gap: var(--_space);
|
|
1976
|
+
padding: var(--_pad);
|
|
1977
|
+
border-bottom: 1px solid var(--_border);
|
|
1648
1978
|
}
|
|
1649
1979
|
|
|
1650
1980
|
.drawer-title {
|
|
@@ -1652,10 +1982,10 @@ export const STYLES = `
|
|
|
1652
1982
|
}
|
|
1653
1983
|
|
|
1654
1984
|
.drawer-new {
|
|
1655
|
-
border: 1px solid var(--
|
|
1656
|
-
border-radius: var(--
|
|
1657
|
-
background: var(--
|
|
1658
|
-
color: var(--
|
|
1985
|
+
border: 1px solid var(--_border);
|
|
1986
|
+
border-radius: var(--_radius);
|
|
1987
|
+
background: var(--_bg);
|
|
1988
|
+
color: var(--_accent);
|
|
1659
1989
|
padding: 4px 10px;
|
|
1660
1990
|
font: inherit;
|
|
1661
1991
|
font-size: 0.85em;
|
|
@@ -1669,19 +1999,19 @@ export const STYLES = `
|
|
|
1669
1999
|
}
|
|
1670
2000
|
|
|
1671
2001
|
.drawer-empty {
|
|
1672
|
-
padding: var(--
|
|
2002
|
+
padding: var(--_pad);
|
|
1673
2003
|
font-size: 0.9em;
|
|
1674
|
-
color: var(--
|
|
2004
|
+
color: var(--_muted);
|
|
1675
2005
|
}
|
|
1676
2006
|
|
|
1677
2007
|
.drawer-row {
|
|
1678
2008
|
display: flex;
|
|
1679
2009
|
align-items: stretch;
|
|
1680
|
-
border-bottom: 1px solid var(--
|
|
2010
|
+
border-bottom: 1px solid var(--_border);
|
|
1681
2011
|
}
|
|
1682
2012
|
|
|
1683
2013
|
.drawer-row--active {
|
|
1684
|
-
background: var(--
|
|
2014
|
+
background: var(--_assistant-bg);
|
|
1685
2015
|
}
|
|
1686
2016
|
|
|
1687
2017
|
.drawer-row-select {
|
|
@@ -1708,12 +2038,12 @@ export const STYLES = `
|
|
|
1708
2038
|
|
|
1709
2039
|
.drawer-row-time {
|
|
1710
2040
|
font-size: 0.72em;
|
|
1711
|
-
color: var(--
|
|
2041
|
+
color: var(--_muted);
|
|
1712
2042
|
}
|
|
1713
2043
|
|
|
1714
2044
|
.drawer-row-preview {
|
|
1715
2045
|
font-size: 0.8em;
|
|
1716
|
-
color: var(--
|
|
2046
|
+
color: var(--_muted);
|
|
1717
2047
|
overflow: hidden;
|
|
1718
2048
|
white-space: nowrap;
|
|
1719
2049
|
text-overflow: ellipsis;
|
|
@@ -1730,7 +2060,7 @@ export const STYLES = `
|
|
|
1730
2060
|
.drawer-row-delete {
|
|
1731
2061
|
border: none;
|
|
1732
2062
|
background: none;
|
|
1733
|
-
color: var(--
|
|
2063
|
+
color: var(--_muted);
|
|
1734
2064
|
font-size: 0.9em;
|
|
1735
2065
|
padding: 4px;
|
|
1736
2066
|
cursor: pointer;
|
|
@@ -1741,10 +2071,10 @@ export const STYLES = `
|
|
|
1741
2071
|
min-width: 0;
|
|
1742
2072
|
margin: 6px 10px;
|
|
1743
2073
|
padding: 4px 8px;
|
|
1744
|
-
border: 1px solid var(--
|
|
2074
|
+
border: 1px solid var(--_accent);
|
|
1745
2075
|
border-radius: 6px;
|
|
1746
|
-
background: var(--
|
|
1747
|
-
color: var(--
|
|
2076
|
+
background: var(--_input-bg);
|
|
2077
|
+
color: var(--_fg);
|
|
1748
2078
|
font: inherit;
|
|
1749
2079
|
}
|
|
1750
2080
|
|
|
@@ -1757,13 +2087,13 @@ export const STYLES = `
|
|
|
1757
2087
|
}
|
|
1758
2088
|
|
|
1759
2089
|
.drawer-confirm-label {
|
|
1760
|
-
color: var(--
|
|
2090
|
+
color: var(--_danger);
|
|
1761
2091
|
}
|
|
1762
2092
|
|
|
1763
2093
|
.drawer-confirm-yes {
|
|
1764
2094
|
border: none;
|
|
1765
2095
|
border-radius: 6px;
|
|
1766
|
-
background: var(--
|
|
2096
|
+
background: var(--_danger);
|
|
1767
2097
|
color: #ffffff;
|
|
1768
2098
|
padding: 3px 10px;
|
|
1769
2099
|
font: inherit;
|
|
@@ -1771,7 +2101,7 @@ export const STYLES = `
|
|
|
1771
2101
|
}
|
|
1772
2102
|
|
|
1773
2103
|
.drawer-confirm-no {
|
|
1774
|
-
border: 1px solid var(--
|
|
2104
|
+
border: 1px solid var(--_border);
|
|
1775
2105
|
border-radius: 6px;
|
|
1776
2106
|
background: none;
|
|
1777
2107
|
color: inherit;
|