@haikit/client 0.8.0 → 0.9.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/README.md +50 -1
- package/package.json +1 -1
- package/src/app.d.ts +12 -2
- package/src/app.js +273 -33
- package/src/hai.css +496 -127
- package/src/icons.js +41 -0
- package/src/transcript.js +76 -14
package/src/hai.css
CHANGED
|
@@ -6,226 +6,595 @@
|
|
|
6
6
|
*
|
|
7
7
|
* It deliberately does not style the inside of your surfaces. Your components
|
|
8
8
|
* emit their own class names and your own stylesheet owns them — otherwise the
|
|
9
|
-
* framework starts dictating what your UI looks like.
|
|
9
|
+
* framework starts dictating what your UI looks like. They can use the tokens,
|
|
10
|
+
* though: --hai-hover and --hai-selected are there for rows and pickers.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
+
* Light and dark, following the system. Every colour is a custom property set
|
|
13
|
+
* here at zero specificity, so a plain `:root` rule in your own sheet wins.
|
|
14
|
+
* Give one value per scheme with light-dark(), behind a plain dark value for
|
|
15
|
+
* the browsers that fall back to dark below:
|
|
12
16
|
*
|
|
13
|
-
* :root { --hai-accent: #b07cff;
|
|
17
|
+
* :root { --hai-accent: #b07cff; }
|
|
18
|
+
* @supports (color: light-dark(#000, #fff)) {
|
|
19
|
+
* :root { --hai-accent: light-dark(#6d28d9, #b07cff); }
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* <html data-hai-theme="dark"> pins the page to one scheme, as does
|
|
23
|
+
* `mountChat({ theme: "dark" })`. The pin is on the root because the tokens
|
|
24
|
+
* are: a minifier that lowers light-dark() resolves them there.
|
|
14
25
|
*/
|
|
15
26
|
|
|
16
|
-
:root {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
--hai-
|
|
20
|
-
--hai-
|
|
21
|
-
--hai-
|
|
22
|
-
--hai-
|
|
23
|
-
--hai-
|
|
24
|
-
--hai-
|
|
25
|
-
--hai-
|
|
26
|
-
--hai-
|
|
27
|
-
--hai-
|
|
28
|
-
--hai-
|
|
29
|
-
--hai-
|
|
27
|
+
:where(:root) {
|
|
28
|
+
color-scheme: light dark;
|
|
29
|
+
|
|
30
|
+
--hai-bg: light-dark(#f6f7f9, #0c0f13);
|
|
31
|
+
--hai-panel: light-dark(#ffffff, #141920);
|
|
32
|
+
--hai-panel-2: light-dark(#f9fafb, #10141a);
|
|
33
|
+
--hai-line: light-dark(#e1e5ea, #252c35);
|
|
34
|
+
--hai-fg: light-dark(#161b22, #e3e8ee);
|
|
35
|
+
--hai-dim: light-dark(#5b6675, #8a95a3);
|
|
36
|
+
--hai-accent: light-dark(#2160e0, #7aa7ff);
|
|
37
|
+
--hai-on-accent: light-dark(#ffffff, #0b1220);
|
|
38
|
+
--hai-good: light-dark(#127a4c, #5ec597);
|
|
39
|
+
--hai-warn: light-dark(#9a5b00, #e7b65c);
|
|
40
|
+
--hai-bad: light-dark(#c23338, #f07b7b);
|
|
41
|
+
--hai-user-bg: light-dark(#e7eefb, #1e2835);
|
|
42
|
+
--hai-code-bg: light-dark(#f3f5f8, #0a0d11);
|
|
43
|
+
--hai-shadow: 0 1px 2px light-dark(rgb(15 23 42 / .06), rgb(0 0 0 / .35));
|
|
44
|
+
|
|
45
|
+
/* tints, derived — override the colour and these follow */
|
|
46
|
+
--hai-line-soft: color-mix(in srgb, var(--hai-line) 60%, transparent);
|
|
47
|
+
--hai-hover: color-mix(in srgb, var(--hai-fg) 6%, transparent);
|
|
48
|
+
--hai-selected: color-mix(in srgb, var(--hai-good) 15%, transparent);
|
|
49
|
+
--hai-accent-soft: color-mix(in srgb, var(--hai-accent) 14%, transparent);
|
|
50
|
+
--hai-good-soft: color-mix(in srgb, var(--hai-good) 13%, transparent);
|
|
51
|
+
--hai-warn-soft: color-mix(in srgb, var(--hai-warn) 12%, transparent);
|
|
52
|
+
--hai-bad-soft: color-mix(in srgb, var(--hai-bad) 12%, transparent);
|
|
53
|
+
|
|
54
|
+
--hai-radius: 12px;
|
|
55
|
+
--hai-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
|
|
56
|
+
--hai-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
57
|
+
--hai-column: 780px;
|
|
30
58
|
--hai-inspector-width: 400px;
|
|
31
59
|
}
|
|
32
60
|
|
|
61
|
+
:where(:root[data-hai-theme="light"]) { color-scheme: light; }
|
|
62
|
+
:where(:root[data-hai-theme="dark"]) { color-scheme: dark; }
|
|
63
|
+
|
|
64
|
+
/* A browser without light-dark() gets the dark scheme, not no colours at all. */
|
|
65
|
+
@supports not (color: light-dark(#000, #fff)) {
|
|
66
|
+
:where(:root) {
|
|
67
|
+
color-scheme: dark;
|
|
68
|
+
--hai-bg: #0c0f13;
|
|
69
|
+
--hai-panel: #141920;
|
|
70
|
+
--hai-panel-2: #10141a;
|
|
71
|
+
--hai-line: #252c35;
|
|
72
|
+
--hai-fg: #e3e8ee;
|
|
73
|
+
--hai-dim: #8a95a3;
|
|
74
|
+
--hai-accent: #7aa7ff;
|
|
75
|
+
--hai-on-accent: #0b1220;
|
|
76
|
+
--hai-good: #5ec597;
|
|
77
|
+
--hai-warn: #e7b65c;
|
|
78
|
+
--hai-bad: #f07b7b;
|
|
79
|
+
--hai-user-bg: #1e2835;
|
|
80
|
+
--hai-code-bg: #0a0d11;
|
|
81
|
+
--hai-shadow: 0 1px 2px rgb(0 0 0 / .35);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* the shell is the page */
|
|
86
|
+
:where(body:has(.hai-shell)) { margin: 0; }
|
|
87
|
+
|
|
33
88
|
/* ── shell ──────────────────────────────────────────────────────────── */
|
|
34
89
|
.hai-shell {
|
|
35
90
|
height: 100vh;
|
|
91
|
+
height: 100dvh;
|
|
36
92
|
display: flex;
|
|
37
93
|
flex-direction: column;
|
|
38
94
|
background: var(--hai-bg);
|
|
39
95
|
color: var(--hai-fg);
|
|
40
|
-
font: 14px/1.
|
|
96
|
+
font: 14px/1.5 var(--hai-sans);
|
|
97
|
+
-webkit-font-smoothing: antialiased;
|
|
41
98
|
}
|
|
99
|
+
|
|
100
|
+
.hai-icon { width: 16px; height: 16px; flex: none; }
|
|
101
|
+
|
|
42
102
|
.hai-top {
|
|
103
|
+
flex: none;
|
|
43
104
|
display: flex;
|
|
44
|
-
align-items:
|
|
105
|
+
align-items: center;
|
|
45
106
|
gap: 12px;
|
|
46
|
-
|
|
107
|
+
height: 52px;
|
|
108
|
+
padding: 0 10px 0 16px;
|
|
47
109
|
border-bottom: 1px solid var(--hai-line);
|
|
48
110
|
background: var(--hai-panel);
|
|
49
111
|
}
|
|
50
|
-
.hai-
|
|
51
|
-
.hai-
|
|
52
|
-
.hai-
|
|
112
|
+
.hai-brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
113
|
+
.hai-mark { width: 22px; height: 22px; color: var(--hai-accent); }
|
|
114
|
+
.hai-title { font-size: 15px; font-weight: 650; letter-spacing: -.01em; white-space: nowrap; }
|
|
115
|
+
.hai-subtitle {
|
|
116
|
+
color: var(--hai-dim);
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
padding-left: 10px;
|
|
119
|
+
border-left: 1px solid var(--hai-line);
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
text-overflow: ellipsis;
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
}
|
|
53
124
|
|
|
54
|
-
.hai-
|
|
55
|
-
.hai-
|
|
56
|
-
|
|
125
|
+
.hai-actions { margin-left: auto; display: flex; align-items: center; gap: 4px; flex: none; }
|
|
126
|
+
.hai-model {
|
|
127
|
+
display: inline-flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
gap: 6px;
|
|
130
|
+
margin-right: 6px;
|
|
131
|
+
padding: 3px 9px;
|
|
132
|
+
border: 1px solid var(--hai-line);
|
|
133
|
+
border-radius: 999px;
|
|
134
|
+
font: 11.5px var(--hai-mono);
|
|
135
|
+
color: var(--hai-dim);
|
|
136
|
+
}
|
|
137
|
+
.hai-model::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--hai-good); }
|
|
138
|
+
.hai-model[hidden] { display: none; }
|
|
139
|
+
|
|
140
|
+
.hai-btn {
|
|
141
|
+
display: inline-flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
gap: 7px;
|
|
144
|
+
height: 32px;
|
|
145
|
+
padding: 0 10px;
|
|
146
|
+
border: none;
|
|
147
|
+
border-radius: 8px;
|
|
148
|
+
background: none;
|
|
149
|
+
color: var(--hai-dim);
|
|
150
|
+
font: inherit;
|
|
151
|
+
font-size: 13px;
|
|
152
|
+
font-weight: 500;
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
}
|
|
155
|
+
.hai-btn:hover:not(:disabled) { background: var(--hai-hover); color: var(--hai-fg); }
|
|
156
|
+
.hai-btn:disabled { opacity: .4; cursor: default; }
|
|
157
|
+
.hai-btn[aria-expanded="true"] { color: var(--hai-fg); background: var(--hai-hover); }
|
|
158
|
+
.hai-ctx-count { font: 11.5px var(--hai-mono); color: var(--hai-dim); }
|
|
159
|
+
.hai-ctx-count:empty { display: none; }
|
|
57
160
|
|
|
58
|
-
.hai-
|
|
59
|
-
|
|
60
|
-
|
|
161
|
+
.hai-icon-btn {
|
|
162
|
+
display: grid;
|
|
163
|
+
place-items: center;
|
|
164
|
+
width: 30px;
|
|
165
|
+
height: 30px;
|
|
166
|
+
border: none;
|
|
167
|
+
border-radius: 8px;
|
|
168
|
+
background: none;
|
|
169
|
+
color: var(--hai-dim);
|
|
170
|
+
cursor: pointer;
|
|
171
|
+
}
|
|
172
|
+
.hai-icon-btn:hover { background: var(--hai-hover); color: var(--hai-fg); }
|
|
173
|
+
|
|
174
|
+
/* clips the drawer while it waits off the right edge */
|
|
175
|
+
.hai-main { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); min-height: 0; position: relative; overflow: hidden; }
|
|
176
|
+
|
|
177
|
+
/* the conversation is a centred column; the scrollbar stays at the edge */
|
|
178
|
+
.hai-chat {
|
|
179
|
+
--hai-gutter: max(16px, calc((100% - var(--hai-column)) / 2));
|
|
180
|
+
display: flex;
|
|
181
|
+
flex-direction: column;
|
|
182
|
+
min-width: 0;
|
|
183
|
+
min-height: 0;
|
|
184
|
+
transition: margin-right .25s cubic-bezier(.2, .8, .2, 1), opacity .25s;
|
|
185
|
+
}
|
|
186
|
+
/* behind the drawer on a narrow screen, out of reach until it closes */
|
|
187
|
+
.hai-chat[inert] { opacity: .4; }
|
|
188
|
+
/* on a wide screen the chat makes room for the open drawer */
|
|
189
|
+
@media (min-width: 900px) {
|
|
190
|
+
.hai-main.inspector-open > .hai-chat { margin-right: var(--hai-inspector-width); }
|
|
191
|
+
}
|
|
192
|
+
.hai-transcript {
|
|
193
|
+
flex: 1;
|
|
194
|
+
overflow-y: auto;
|
|
195
|
+
padding: 28px var(--hai-gutter) 8px;
|
|
196
|
+
scrollbar-width: thin;
|
|
197
|
+
scrollbar-color: var(--hai-line) transparent;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* ── empty state ────────────────────────────────────────────────────── */
|
|
201
|
+
.hai-empty { color: var(--hai-dim); }
|
|
202
|
+
.hai-empty p { margin: 0; max-width: 54ch; font-size: 15px; line-height: 1.6; }
|
|
203
|
+
.hai-empty-mark {
|
|
204
|
+
width: 28px;
|
|
205
|
+
height: 28px;
|
|
206
|
+
padding: 12px;
|
|
207
|
+
margin-bottom: 18px;
|
|
208
|
+
border-radius: 16px;
|
|
209
|
+
background: var(--hai-accent-soft);
|
|
210
|
+
color: var(--hai-accent);
|
|
211
|
+
}
|
|
212
|
+
/* alone, it greets; after what init showed, it stays out of the way */
|
|
213
|
+
.hai-empty:first-child {
|
|
214
|
+
display: flex;
|
|
215
|
+
flex-direction: column;
|
|
216
|
+
align-items: center;
|
|
217
|
+
text-align: center;
|
|
218
|
+
padding-top: clamp(24px, 14vh, 140px);
|
|
219
|
+
}
|
|
220
|
+
.hai-empty:not(:first-child) .hai-empty-mark { display: none; }
|
|
221
|
+
|
|
222
|
+
.hai-suggestions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
|
|
223
|
+
.hai-empty:first-child .hai-suggestions { justify-content: center; }
|
|
224
|
+
.hai-empty:not(:first-child) .hai-suggestions { margin-top: 12px; }
|
|
61
225
|
.hai-suggestion {
|
|
62
|
-
|
|
63
|
-
color: var(--hai-fg);
|
|
226
|
+
padding: 7px 14px;
|
|
64
227
|
border: 1px solid var(--hai-line);
|
|
65
228
|
border-radius: 999px;
|
|
66
|
-
|
|
67
|
-
|
|
229
|
+
background: var(--hai-panel);
|
|
230
|
+
color: var(--hai-fg);
|
|
68
231
|
font: inherit;
|
|
69
|
-
font-size:
|
|
232
|
+
font-size: 13.5px;
|
|
233
|
+
cursor: pointer;
|
|
234
|
+
transition: border-color .15s, background-color .15s;
|
|
70
235
|
}
|
|
71
|
-
.hai-suggestion:hover { border-color: var(--hai-accent); }
|
|
236
|
+
.hai-suggestion:hover { border-color: var(--hai-accent); background: var(--hai-accent-soft); }
|
|
72
237
|
|
|
73
238
|
/* ── transcript blocks ──────────────────────────────────────────────── */
|
|
74
|
-
.hai-block { margin: 0 0
|
|
239
|
+
.hai-block { margin: 0 0 18px; }
|
|
240
|
+
.hai-user .hai-body,
|
|
241
|
+
.hai-assistant .hai-body {
|
|
242
|
+
white-space: pre-wrap;
|
|
243
|
+
overflow-wrap: anywhere;
|
|
244
|
+
/* each paragraph takes its own direction: a reply can mix scripts */
|
|
245
|
+
unicode-bidi: plaintext;
|
|
246
|
+
font-size: 15px;
|
|
247
|
+
}
|
|
248
|
+
.hai-assistant { max-width: 72ch; line-height: 1.65; }
|
|
249
|
+
.hai-user { display: flex; justify-content: flex-end; }
|
|
75
250
|
.hai-user .hai-body {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
border-radius:
|
|
79
|
-
|
|
80
|
-
display: inline-block;
|
|
251
|
+
max-width: min(85%, 62ch);
|
|
252
|
+
padding: 9px 14px;
|
|
253
|
+
border-radius: 18px 18px 6px 18px;
|
|
254
|
+
background: var(--hai-user-bg);
|
|
81
255
|
}
|
|
82
|
-
|
|
83
|
-
|
|
256
|
+
|
|
257
|
+
/* an answer given in a surface — it went back to the model as the tool result */
|
|
258
|
+
.hai-interaction { display: flex; align-items: flex-start; gap: 10px; max-width: 72ch; font-size: 13.5px; color: var(--hai-dim); }
|
|
259
|
+
.hai-arrow {
|
|
260
|
+
flex: none;
|
|
261
|
+
display: grid;
|
|
262
|
+
place-items: center;
|
|
263
|
+
width: 22px;
|
|
264
|
+
height: 22px;
|
|
265
|
+
margin-top: -1px;
|
|
266
|
+
border-radius: 50%;
|
|
267
|
+
background: var(--hai-good-soft);
|
|
84
268
|
color: var(--hai-good);
|
|
85
|
-
|
|
269
|
+
}
|
|
270
|
+
.hai-arrow .hai-icon { width: 13px; height: 13px; }
|
|
271
|
+
|
|
272
|
+
.hai-error,
|
|
273
|
+
.hai-expired {
|
|
86
274
|
display: flex;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
padding
|
|
275
|
+
align-items: flex-start;
|
|
276
|
+
gap: 10px;
|
|
277
|
+
padding: 11px 14px;
|
|
278
|
+
border: 1px solid;
|
|
279
|
+
border-radius: var(--hai-radius);
|
|
90
280
|
}
|
|
91
|
-
.hai-error
|
|
281
|
+
.hai-error .hai-icon,
|
|
282
|
+
.hai-expired .hai-icon { margin-top: 2px; }
|
|
283
|
+
.hai-error {
|
|
284
|
+
border-color: color-mix(in srgb, var(--hai-bad) 35%, transparent);
|
|
285
|
+
background: var(--hai-bad-soft);
|
|
286
|
+
color: var(--hai-bad);
|
|
287
|
+
font: 12.5px/1.55 var(--hai-mono);
|
|
288
|
+
}
|
|
289
|
+
.hai-error .hai-body { overflow-wrap: anywhere; }
|
|
92
290
|
|
|
93
291
|
/* tool provenance row — chrome for the surface directly beneath it */
|
|
94
292
|
.hai-tool {
|
|
95
293
|
border: 1px solid var(--hai-line);
|
|
96
|
-
border-radius: var(--hai-radius)
|
|
97
|
-
background: var(--hai-panel);
|
|
98
|
-
|
|
99
|
-
margin-bottom: 0;
|
|
294
|
+
border-radius: var(--hai-radius);
|
|
295
|
+
background: var(--hai-panel-2);
|
|
296
|
+
overflow: hidden;
|
|
100
297
|
}
|
|
298
|
+
.hai-tool:has(+ .hai-surface) { margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
|
|
101
299
|
.hai-tool summary {
|
|
102
300
|
display: flex;
|
|
103
301
|
align-items: center;
|
|
104
|
-
gap:
|
|
302
|
+
gap: 9px;
|
|
303
|
+
min-height: 36px;
|
|
105
304
|
padding: 7px 12px;
|
|
305
|
+
box-sizing: border-box;
|
|
106
306
|
cursor: pointer;
|
|
107
|
-
font: 12px var(--hai-mono);
|
|
108
307
|
list-style: none;
|
|
308
|
+
font-size: 12.5px;
|
|
309
|
+
user-select: none;
|
|
109
310
|
}
|
|
110
311
|
.hai-tool summary::-webkit-details-marker { display: none; }
|
|
111
|
-
.hai-
|
|
112
|
-
.hai-
|
|
113
|
-
.hai-
|
|
114
|
-
.hai-
|
|
115
|
-
.hai-
|
|
312
|
+
.hai-tool summary:hover { background: var(--hai-hover); }
|
|
313
|
+
.hai-ticon { flex: none; display: grid; place-items: center; width: 16px; height: 16px; color: var(--hai-dim); }
|
|
314
|
+
.hai-ticon .hai-icon { width: 14px; height: 14px; }
|
|
315
|
+
.hai-tname { font: 500 12.5px var(--hai-mono); }
|
|
316
|
+
.hai-targs {
|
|
317
|
+
flex: 1;
|
|
318
|
+
min-width: 0;
|
|
319
|
+
overflow: hidden;
|
|
320
|
+
text-overflow: ellipsis;
|
|
321
|
+
white-space: nowrap;
|
|
322
|
+
font: 12px var(--hai-mono);
|
|
323
|
+
color: var(--hai-dim);
|
|
324
|
+
}
|
|
325
|
+
.hai-tstatus { color: var(--hai-dim); white-space: nowrap; font-variant-numeric: tabular-nums; }
|
|
326
|
+
.hai-chevron { width: 14px; height: 14px; color: var(--hai-dim); transition: transform .15s; }
|
|
327
|
+
.hai-tool[open] .hai-chevron { transform: rotate(90deg); }
|
|
328
|
+
|
|
329
|
+
.hai-status-ok .hai-ticon { color: var(--hai-good); }
|
|
116
330
|
.hai-status-running .hai-tstatus { color: var(--hai-accent); }
|
|
117
|
-
.hai-
|
|
118
|
-
.hai-
|
|
331
|
+
.hai-status-awaiting .hai-tstatus { color: var(--hai-warn); }
|
|
332
|
+
.hai-status-error .hai-ticon,
|
|
333
|
+
.hai-status-error .hai-tstatus { color: var(--hai-bad); }
|
|
334
|
+
/* the component is the question: the turn is parked on it */
|
|
335
|
+
.hai-tool.hai-status-awaiting { background: var(--hai-warn-soft); }
|
|
336
|
+
.hai-tool.hai-status-awaiting,
|
|
337
|
+
.hai-tool.hai-status-awaiting + .hai-surface { border-color: color-mix(in srgb, var(--hai-warn) 45%, var(--hai-line)); }
|
|
338
|
+
|
|
339
|
+
.hai-tool-detail { padding: 0 12px 12px; border-top: 1px solid var(--hai-line); }
|
|
340
|
+
.hai-label { margin: 10px 0 5px; font: 11px var(--hai-mono); color: var(--hai-dim); }
|
|
341
|
+
.hai-code,
|
|
119
342
|
.hai-digest {
|
|
120
343
|
margin: 0;
|
|
121
|
-
padding:
|
|
122
|
-
|
|
344
|
+
padding: 9px 11px;
|
|
345
|
+
max-height: 200px;
|
|
346
|
+
overflow: auto;
|
|
123
347
|
border: 1px solid var(--hai-line);
|
|
124
|
-
border-radius:
|
|
125
|
-
|
|
126
|
-
|
|
348
|
+
border-radius: 8px;
|
|
349
|
+
background: var(--hai-code-bg);
|
|
350
|
+
font: 12px/1.55 var(--hai-mono);
|
|
127
351
|
white-space: pre-wrap;
|
|
128
|
-
|
|
129
|
-
|
|
352
|
+
overflow-wrap: anywhere;
|
|
353
|
+
}
|
|
354
|
+
.hai-digest { color: var(--hai-good); }
|
|
355
|
+
|
|
356
|
+
.hai-spinner {
|
|
357
|
+
width: 12px;
|
|
358
|
+
height: 12px;
|
|
359
|
+
box-sizing: border-box;
|
|
360
|
+
border: 2px solid var(--hai-accent-soft);
|
|
361
|
+
border-top-color: var(--hai-accent);
|
|
362
|
+
border-radius: 50%;
|
|
363
|
+
animation: hai-spin .8s linear infinite;
|
|
364
|
+
}
|
|
365
|
+
.hai-pulse {
|
|
366
|
+
flex: none;
|
|
367
|
+
width: 8px;
|
|
368
|
+
height: 8px;
|
|
369
|
+
border-radius: 50%;
|
|
370
|
+
background: var(--hai-warn);
|
|
371
|
+
animation: hai-pulse 1.8s ease-out infinite;
|
|
130
372
|
}
|
|
131
373
|
|
|
132
374
|
/* surface container — your component mounts inside this */
|
|
133
375
|
.hai-surface {
|
|
134
|
-
|
|
135
|
-
border-top: none;
|
|
136
|
-
border-radius: 0 0 var(--hai-radius) var(--hai-radius);
|
|
137
|
-
background: var(--hai-panel-2);
|
|
138
|
-
margin-bottom: 14px;
|
|
376
|
+
margin-bottom: 18px;
|
|
139
377
|
overflow: hidden;
|
|
378
|
+
border: 1px solid var(--hai-line);
|
|
379
|
+
border-radius: var(--hai-radius);
|
|
380
|
+
background: var(--hai-panel);
|
|
381
|
+
box-shadow: var(--hai-shadow);
|
|
382
|
+
}
|
|
383
|
+
.hai-tool + .hai-surface { border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; }
|
|
384
|
+
.hai-skeleton { display: grid; gap: 9px; padding: 14px; }
|
|
385
|
+
.hai-skeleton-label { margin-bottom: 2px; font: 12px var(--hai-mono); color: var(--hai-dim); }
|
|
386
|
+
.hai-shimmer {
|
|
387
|
+
height: 10px;
|
|
388
|
+
border-radius: 5px;
|
|
389
|
+
background: linear-gradient(90deg, var(--hai-hover), var(--hai-line), var(--hai-hover)) 0 0 / 200% 100%;
|
|
390
|
+
animation: hai-shimmer 1.4s ease-in-out infinite;
|
|
391
|
+
}
|
|
392
|
+
.hai-shimmer:nth-child(3) { width: 82%; }
|
|
393
|
+
.hai-shimmer:nth-child(4) { width: 60%; }
|
|
394
|
+
.hai-surface-error {
|
|
395
|
+
margin-bottom: 18px;
|
|
396
|
+
padding: 11px 14px;
|
|
397
|
+
border: 1px solid color-mix(in srgb, var(--hai-bad) 35%, transparent);
|
|
398
|
+
border-radius: var(--hai-radius);
|
|
399
|
+
background: var(--hai-bad-soft);
|
|
400
|
+
color: var(--hai-bad);
|
|
401
|
+
font: 12.5px var(--hai-mono);
|
|
140
402
|
}
|
|
141
|
-
.hai-skeleton, .hai-surface-error { padding: 14px; font: 12px var(--hai-mono); color: var(--hai-dim); }
|
|
142
|
-
.hai-surface-error { color: var(--hai-bad); }
|
|
143
403
|
|
|
144
404
|
/* out of date — the runtime has made the surface inert; this only shows it */
|
|
145
405
|
.hai-surface[data-expired] { opacity: .45; filter: grayscale(.7); }
|
|
146
406
|
.hai-expired {
|
|
147
|
-
display: flex;
|
|
148
407
|
flex-wrap: wrap;
|
|
149
408
|
align-items: center;
|
|
150
|
-
gap: 10px
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
border-radius: var(--hai-radius);
|
|
409
|
+
gap: 10px 12px;
|
|
410
|
+
border-color: color-mix(in srgb, var(--hai-warn) 45%, transparent);
|
|
411
|
+
background: var(--hai-warn-soft);
|
|
154
412
|
color: var(--hai-warn);
|
|
155
413
|
}
|
|
414
|
+
.hai-expired .hai-icon { margin-top: 0; }
|
|
156
415
|
.hai-expired .hai-body { flex: 1 1 30ch; }
|
|
157
416
|
.hai-new {
|
|
158
|
-
|
|
159
|
-
color: var(--hai-bg);
|
|
417
|
+
padding: 7px 14px;
|
|
160
418
|
border: none;
|
|
161
419
|
border-radius: 8px;
|
|
162
|
-
|
|
420
|
+
background: var(--hai-warn);
|
|
421
|
+
color: var(--hai-on-accent);
|
|
163
422
|
font: inherit;
|
|
164
423
|
font-weight: 600;
|
|
165
424
|
cursor: pointer;
|
|
166
425
|
}
|
|
167
426
|
|
|
168
427
|
/* ── status + composer ──────────────────────────────────────────────── */
|
|
169
|
-
.hai-status {
|
|
428
|
+
.hai-status {
|
|
429
|
+
display: flex;
|
|
430
|
+
align-items: center;
|
|
431
|
+
gap: 8px;
|
|
432
|
+
min-height: 22px;
|
|
433
|
+
padding: 0 var(--hai-gutter) 6px;
|
|
434
|
+
font-size: 12.5px;
|
|
435
|
+
color: var(--hai-dim);
|
|
436
|
+
}
|
|
170
437
|
.hai-status[data-status="awaiting"] { color: var(--hai-warn); }
|
|
171
|
-
.hai-
|
|
438
|
+
.hai-dots { display: inline-flex; gap: 3px; }
|
|
439
|
+
.hai-dots i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: hai-blink 1.2s infinite both; }
|
|
440
|
+
.hai-dots i:nth-child(2) { animation-delay: .2s; }
|
|
441
|
+
.hai-dots i:nth-child(3) { animation-delay: .4s; }
|
|
442
|
+
|
|
443
|
+
.hai-composer { flex: none; padding: 0 var(--hai-gutter) 18px; }
|
|
444
|
+
.hai-composer-box {
|
|
445
|
+
display: flex;
|
|
446
|
+
align-items: flex-end;
|
|
447
|
+
gap: 8px;
|
|
448
|
+
padding: 7px 7px 7px 14px;
|
|
449
|
+
border: 1px solid var(--hai-line);
|
|
450
|
+
border-radius: 16px;
|
|
451
|
+
background: var(--hai-panel);
|
|
452
|
+
box-shadow: var(--hai-shadow);
|
|
453
|
+
transition: border-color .15s, box-shadow .15s;
|
|
454
|
+
}
|
|
455
|
+
.hai-composer-box:focus-within { border-color: var(--hai-accent); box-shadow: 0 0 0 3px var(--hai-accent-soft); }
|
|
172
456
|
.hai-input {
|
|
173
457
|
flex: 1;
|
|
458
|
+
box-sizing: border-box;
|
|
459
|
+
min-height: 34px;
|
|
460
|
+
max-height: 200px;
|
|
461
|
+
padding: 6px 0;
|
|
462
|
+
overflow-y: auto;
|
|
174
463
|
resize: none;
|
|
175
|
-
|
|
464
|
+
border: none;
|
|
465
|
+
outline: none;
|
|
466
|
+
background: transparent;
|
|
176
467
|
color: var(--hai-fg);
|
|
177
|
-
border: 1px solid var(--hai-line);
|
|
178
|
-
border-radius: 8px;
|
|
179
|
-
padding: 9px 12px;
|
|
180
468
|
font: inherit;
|
|
181
|
-
|
|
182
|
-
|
|
469
|
+
font-size: 15px;
|
|
470
|
+
line-height: 1.45;
|
|
183
471
|
}
|
|
184
|
-
.hai-input
|
|
185
|
-
.hai-input:disabled { opacity: .
|
|
472
|
+
.hai-input::placeholder { color: var(--hai-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
473
|
+
.hai-input:disabled { cursor: not-allowed; opacity: .6; }
|
|
186
474
|
.hai-send {
|
|
187
|
-
|
|
188
|
-
|
|
475
|
+
flex: none;
|
|
476
|
+
display: grid;
|
|
477
|
+
place-items: center;
|
|
478
|
+
width: 34px;
|
|
479
|
+
height: 34px;
|
|
189
480
|
border: none;
|
|
190
|
-
border-radius:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
font-weight: 600;
|
|
481
|
+
border-radius: 10px;
|
|
482
|
+
background: var(--hai-accent);
|
|
483
|
+
color: var(--hai-on-accent);
|
|
194
484
|
cursor: pointer;
|
|
485
|
+
transition: opacity .15s;
|
|
195
486
|
}
|
|
196
|
-
.hai-send
|
|
487
|
+
.hai-send .hai-icon { width: 18px; height: 18px; }
|
|
488
|
+
.hai-send:disabled { opacity: .35; cursor: default; }
|
|
197
489
|
|
|
198
|
-
/* ── context
|
|
490
|
+
/* ── model context debug drawer ─────────────────────────────────────── */
|
|
491
|
+
/* Closed, it waits off the right edge, out of the tab order and the
|
|
492
|
+
accessibility tree; open, it slides in, over the chat on a narrow screen. */
|
|
199
493
|
.hai-inspector {
|
|
200
|
-
|
|
201
|
-
|
|
494
|
+
position: absolute;
|
|
495
|
+
inset: 0 0 0 auto;
|
|
496
|
+
z-index: 10;
|
|
202
497
|
display: flex;
|
|
203
498
|
flex-direction: column;
|
|
499
|
+
width: min(100%, var(--hai-inspector-width));
|
|
204
500
|
min-height: 0;
|
|
501
|
+
border-left: 1px solid var(--hai-line);
|
|
502
|
+
background: var(--hai-panel-2);
|
|
503
|
+
box-shadow: -16px 0 32px -12px rgb(0 0 0 / .25);
|
|
504
|
+
transform: translateX(100%);
|
|
505
|
+
visibility: hidden;
|
|
506
|
+
transition: transform .25s cubic-bezier(.2, .8, .2, 1), visibility 0s .25s;
|
|
205
507
|
}
|
|
206
|
-
.hai-inspector-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
508
|
+
.hai-main.inspector-open > .hai-inspector {
|
|
509
|
+
transform: none;
|
|
510
|
+
visibility: visible;
|
|
511
|
+
transition: transform .25s cubic-bezier(.2, .8, .2, 1), visibility 0s;
|
|
512
|
+
}
|
|
513
|
+
.hai-inspector-head { display: flex; align-items: center; gap: 8px; padding: 10px 10px 10px 16px; border-bottom: 1px solid var(--hai-line); }
|
|
514
|
+
.hai-inspector-title { flex: 1; display: flex; flex-direction: column; font-size: 13px; font-weight: 600; }
|
|
515
|
+
.hai-inspector-title span { color: var(--hai-dim); font-size: 12px; font-weight: 400; }
|
|
516
|
+
.hai-inspector-body {
|
|
517
|
+
flex: 1;
|
|
518
|
+
overflow-y: auto;
|
|
519
|
+
padding: 0 16px 16px;
|
|
520
|
+
scrollbar-width: thin;
|
|
521
|
+
scrollbar-color: var(--hai-line) transparent;
|
|
522
|
+
}
|
|
523
|
+
.hai-inspector-empty { margin: 16px 0; color: var(--hai-dim); font-size: 13px; }
|
|
524
|
+
|
|
525
|
+
/* the numbers stay in view as the context scrolls under them */
|
|
526
|
+
.hai-ctx {
|
|
527
|
+
position: sticky;
|
|
528
|
+
top: 0;
|
|
529
|
+
z-index: 1;
|
|
530
|
+
padding: 14px 0 12px;
|
|
531
|
+
border-bottom: 1px solid var(--hai-line);
|
|
532
|
+
background: var(--hai-panel-2);
|
|
533
|
+
}
|
|
534
|
+
.hai-ctx-headline { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; font-size: 12.5px; color: var(--hai-dim); }
|
|
535
|
+
.hai-ctx-pct { font-size: 26px; font-weight: 650; letter-spacing: -.02em; color: var(--hai-good); font-variant-numeric: tabular-nums; }
|
|
536
|
+
.hai-meter { display: flex; height: 6px; margin-bottom: 10px; overflow: hidden; border-radius: 3px; background: var(--hai-good); }
|
|
537
|
+
.hai-meter-model { min-width: 2px; background: var(--hai-accent); }
|
|
538
|
+
.hai-ctx-stat { display: flex; justify-content: space-between; padding: 1px 0; font: 12px var(--hai-mono); }
|
|
539
|
+
.hai-ctx-label { display: inline-flex; align-items: center; gap: 7px; color: var(--hai-dim); }
|
|
540
|
+
.hai-ctx-tok { font-variant-numeric: tabular-nums; }
|
|
541
|
+
.hai-key { width: 8px; height: 8px; border-radius: 2px; }
|
|
542
|
+
.hai-key-model { background: var(--hai-accent); }
|
|
543
|
+
.hai-key-ui { background: var(--hai-good); }
|
|
544
|
+
|
|
545
|
+
.hai-msg { margin-top: 14px; padding-left: 11px; border-left: 2px solid var(--hai-line); }
|
|
546
|
+
.hai-role { margin-bottom: 4px; font: 600 10px var(--hai-mono); text-transform: uppercase; letter-spacing: .08em; color: var(--hai-dim); }
|
|
547
|
+
.hai-mbody { display: grid; gap: 6px; font: 12px/1.55 var(--hai-mono); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
548
|
+
.hai-tu,
|
|
549
|
+
.hai-tr { padding: 6px 8px; border-radius: 6px; }
|
|
550
|
+
.hai-tu { background: var(--hai-accent-soft); color: var(--hai-accent); }
|
|
551
|
+
.hai-tr { background: var(--hai-good-soft); color: var(--hai-good); }
|
|
552
|
+
.hai-kind { display: block; margin-bottom: 2px; font-size: 10.5px; opacity: .75; }
|
|
553
|
+
|
|
554
|
+
/* ── narrow screens ─────────────────────────────────────────────────── */
|
|
555
|
+
@media (max-width: 899.98px) {
|
|
556
|
+
.hai-subtitle { display: none; }
|
|
557
|
+
.hai-btn { padding: 0 8px; }
|
|
558
|
+
.hai-btn-label {
|
|
559
|
+
position: absolute;
|
|
560
|
+
width: 1px;
|
|
561
|
+
height: 1px;
|
|
562
|
+
overflow: hidden;
|
|
563
|
+
clip-path: inset(50%);
|
|
564
|
+
white-space: nowrap;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
@media (max-width: 599.98px) {
|
|
568
|
+
.hai-model { display: none; }
|
|
569
|
+
.hai-transcript { padding-top: 18px; }
|
|
570
|
+
.hai-composer { padding-bottom: 12px; }
|
|
219
571
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
.hai-
|
|
223
|
-
.hai-
|
|
224
|
-
.hai-
|
|
225
|
-
.hai-
|
|
226
|
-
.hai-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
572
|
+
|
|
573
|
+
/* ── focus, motion ──────────────────────────────────────────────────── */
|
|
574
|
+
.hai-btn:focus-visible,
|
|
575
|
+
.hai-icon-btn:focus-visible,
|
|
576
|
+
.hai-send:focus-visible,
|
|
577
|
+
.hai-suggestion:focus-visible,
|
|
578
|
+
.hai-new:focus-visible { outline: 2px solid var(--hai-accent); outline-offset: 2px; }
|
|
579
|
+
.hai-tool summary:focus-visible { outline: 2px solid var(--hai-accent); outline-offset: -2px; }
|
|
580
|
+
|
|
581
|
+
@keyframes hai-spin { to { transform: rotate(360deg); } }
|
|
582
|
+
@keyframes hai-pulse {
|
|
583
|
+
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--hai-warn) 55%, transparent); }
|
|
584
|
+
100% { box-shadow: 0 0 0 7px transparent; }
|
|
585
|
+
}
|
|
586
|
+
@keyframes hai-blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
|
|
587
|
+
@keyframes hai-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
|
|
588
|
+
|
|
589
|
+
@media (prefers-reduced-motion: reduce) {
|
|
590
|
+
.hai-spinner,
|
|
591
|
+
.hai-pulse,
|
|
592
|
+
.hai-dots i,
|
|
593
|
+
.hai-shimmer { animation: none; }
|
|
594
|
+
.hai-chevron,
|
|
595
|
+
.hai-suggestion,
|
|
596
|
+
.hai-composer-box,
|
|
597
|
+
.hai-chat,
|
|
598
|
+
.hai-inspector,
|
|
599
|
+
.hai-main.inspector-open > .hai-inspector { transition: none; }
|
|
231
600
|
}
|