@singlebase/elements 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/{authui-display-BCZBP7HR.js → authui-display-CKfGK5va.js} +519 -503
  2. package/dist/authui-display-CKfGK5va.js.map +1 -0
  3. package/dist/{authui-display-CLGFSqRi.cjs → authui-display-aWNht0cW.cjs} +38 -58
  4. package/dist/authui-display-aWNht0cW.cjs.map +1 -0
  5. package/dist/authui.cjs +1 -1
  6. package/dist/authui.js +2 -2
  7. package/dist/chat-C-gsskho.cjs +3258 -0
  8. package/dist/chat-C-gsskho.cjs.map +1 -0
  9. package/dist/{chat-bXaRWel7.js → chat-CEh6RygY.js} +1957 -1137
  10. package/dist/chat-CEh6RygY.js.map +1 -0
  11. package/dist/chat-messages.d.ts +11 -5
  12. package/dist/chat.cjs +1 -1
  13. package/dist/chat.d.ts +4 -3
  14. package/dist/chat.js +8 -6
  15. package/dist/elements/authui-base.d.ts +2 -0
  16. package/dist/elements/authui-buttons.d.ts +1 -1
  17. package/dist/elements/authui-display.d.ts +1 -1
  18. package/dist/elements/authui.d.ts +5 -1
  19. package/dist/elements/chat.d.ts +153 -10
  20. package/dist/elements/uploader.d.ts +14 -0
  21. package/dist/{files-BOwtpYyQ.js → files-DDJWPzZW.js} +82 -35
  22. package/dist/files-DDJWPzZW.js.map +1 -0
  23. package/dist/files-DyxcjZsx.cjs +75 -0
  24. package/dist/files-DyxcjZsx.cjs.map +1 -0
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.js +24 -22
  27. package/dist/singlebase-elements.min.js +3799 -2892
  28. package/dist/singlebase-elements.min.js.map +1 -1
  29. package/dist/styles/branding.d.ts +5 -0
  30. package/dist/styles/tokens.d.ts +2 -0
  31. package/dist/{uploader-DGV2y9uT.cjs → uploader-660JIgIN.cjs} +53 -76
  32. package/dist/uploader-660JIgIN.cjs.map +1 -0
  33. package/dist/{uploader-abQoem5q.js → uploader-vfczkX51.js} +294 -271
  34. package/dist/uploader-vfczkX51.js.map +1 -0
  35. package/dist/uploader.cjs +1 -1
  36. package/dist/uploader.js +2 -2
  37. package/dist/utils/branding.d.ts +8 -0
  38. package/dist/utils/markdown.d.ts +69 -12
  39. package/dist/utils/svg.d.ts +10 -0
  40. package/package.json +3 -3
  41. package/dist/authui-display-BCZBP7HR.js.map +0 -1
  42. package/dist/authui-display-CLGFSqRi.cjs.map +0 -1
  43. package/dist/chat-DRenTJlI.cjs +0 -3001
  44. package/dist/chat-DRenTJlI.cjs.map +0 -1
  45. package/dist/chat-bXaRWel7.js.map +0 -1
  46. package/dist/files-BOwtpYyQ.js.map +0 -1
  47. package/dist/files-DW8A4Jl-.cjs +0 -38
  48. package/dist/files-DW8A4Jl-.cjs.map +0 -1
  49. package/dist/uploader-DGV2y9uT.cjs.map +0 -1
  50. package/dist/uploader-abQoem5q.js.map +0 -1
@@ -0,0 +1,3258 @@
1
+ "use strict";var Kt=Object.defineProperty;var bt=l=>{throw TypeError(l)};var Wt=(l,o,e)=>o in l?Kt(l,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[o]=e;var O=(l,o,e)=>Wt(l,typeof o!="symbol"?o+"":o,e),ft=(l,o,e)=>o.has(l)||bt("Cannot "+e);var h=(l,o,e)=>(ft(l,o,"read from private field"),e?e.call(l):o.get(l)),p=(l,o,e)=>o.has(l)?bt("Cannot add the same private member more than once"):o instanceof WeakSet?o.add(l):o.set(l,e),u=(l,o,e,t)=>(ft(l,o,"write to private field"),t?t.call(l,e):o.set(l,e),e);const s=require("lit"),g=require("lit/decorators.js"),Jt=require("lit/directives/repeat.js"),Ht=require("@singlebase/core"),T=require("./files-DyxcjZsx.cjs");if(typeof CSS<"u"&&"registerProperty"in CSS)try{CSS.registerProperty({name:"--sb-ai-angle",syntax:"<angle>",inherits:!1,initialValue:"0deg"})}catch{}const qt=s.css`
2
+ :host {
3
+ --c-ink: var(--sb-ink, #16181a);
4
+ --c-ink2: var(--sb-ink-2, #41464b);
5
+ --c-muted: var(--sb-muted-ink, #61666c);
6
+ --c-faint: #8a8f95;
7
+ --c-bg: var(--sb-surface, #ffffff);
8
+ --c-bg2: var(--sb-surface-alt, #fafafa);
9
+ --c-hover: var(--sb-hover, #f2f3f4);
10
+ --c-line: var(--sb-border, #e4e6e9);
11
+ --c-line2: var(--sb-divider, #ecedee);
12
+ --c-strong: var(--sb-border-strong, #cdd1d6);
13
+ --c-brand: var(--sb-accent, #16181a);
14
+ --c-on-brand: var(--sb-on-accent, #ffffff);
15
+ --c-danger: var(--sb-danger, #b4231a);
16
+ --c-ok: var(--sb-ok, #0f6b4a);
17
+ --c-mono: var(--sb-mono, "Geist Mono", ui-monospace, monospace);
18
+ --c-r: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));
19
+ --c-r2: calc(var(--c-r) * 1.5);
20
+ --c-r3: calc(var(--c-r) * 2);
21
+ --c-r4: calc(var(--c-r) * 3);
22
+ --c-glow: 0.6;
23
+ --c-conic: conic-gradient(
24
+ from var(--sb-ai-angle, 0deg),
25
+ oklch(0.72 0.15 295),
26
+ oklch(0.74 0.13 245),
27
+ oklch(0.8 0.11 190),
28
+ oklch(0.84 0.12 85),
29
+ oklch(0.78 0.12 350),
30
+ oklch(0.72 0.15 295)
31
+ );
32
+ --c-z: var(--sb-chat-z, 1000);
33
+ display: block;
34
+ height: 100%;
35
+ min-height: 0;
36
+ color-scheme: light;
37
+ }
38
+
39
+ :host([theme="dark"]) {
40
+ --sb-hover: #24272b;
41
+ --sb-ink-2: #c9ccd0;
42
+ --sb-divider: #26292d;
43
+ --c-faint: #7c8187;
44
+ color-scheme: dark;
45
+ }
46
+
47
+ :host([glow="vivid"]) {
48
+ --c-glow: 1;
49
+ }
50
+
51
+ :host([embed="inline"]) {
52
+ height: auto;
53
+ }
54
+
55
+ :host([embed="launcher"]) {
56
+ height: 0;
57
+ }
58
+
59
+ * {
60
+ box-sizing: border-box;
61
+ }
62
+
63
+ button {
64
+ font: inherit;
65
+ color: inherit;
66
+ }
67
+
68
+ button:focus-visible,
69
+ input:focus-visible,
70
+ textarea:focus-visible,
71
+ [role="button"]:focus-visible {
72
+ outline: 2px solid var(--c-ink);
73
+ outline-offset: 1px;
74
+ }
75
+
76
+ .mono {
77
+ font-family: var(--c-mono);
78
+ }
79
+
80
+ .label {
81
+ font-family: var(--c-mono);
82
+ font-size: 11px;
83
+ letter-spacing: 0.07em;
84
+ text-transform: uppercase;
85
+ color: var(--c-muted);
86
+ }
87
+
88
+ /* ── frames ───────────────────────────────────────────── */
89
+
90
+ .frame {
91
+ position: relative;
92
+ display: flex;
93
+ height: 100%;
94
+ min-height: 0;
95
+ background: var(--c-bg);
96
+ color: var(--c-ink);
97
+ overflow: hidden;
98
+ }
99
+
100
+ .frame.boxed {
101
+ border: 1px solid var(--c-line);
102
+ border-radius: var(--c-r4);
103
+ }
104
+
105
+ .frame.inline {
106
+ width: 440px;
107
+ height: 660px;
108
+ min-width: 340px;
109
+ min-height: 480px;
110
+ max-width: 100%;
111
+ resize: both;
112
+ box-shadow: 0 1px 2px rgba(22, 24, 26, 0.06);
113
+ }
114
+
115
+ @media (max-width: 559px) {
116
+ .frame.inline {
117
+ width: 100%;
118
+ min-width: 0;
119
+ resize: none;
120
+ }
121
+ }
122
+
123
+ .frame.launcher {
124
+ position: fixed;
125
+ bottom: 96px;
126
+ right: 24px;
127
+ z-index: var(--c-z);
128
+ width: 420px;
129
+ height: min(680px, calc(100vh - 120px));
130
+ max-width: calc(100vw - 48px);
131
+ box-shadow: 0 24px 60px -24px rgba(22, 24, 26, 0.35);
132
+ transform-origin: bottom right;
133
+ animation: scaleIn 0.2s ease-out;
134
+ }
135
+
136
+ :host([position="left"]) .frame.launcher {
137
+ right: auto;
138
+ left: 24px;
139
+ transform-origin: bottom left;
140
+ }
141
+
142
+ .frame.expanded {
143
+ position: fixed;
144
+ inset: 24px;
145
+ width: auto;
146
+ height: auto;
147
+ max-width: none;
148
+ z-index: var(--c-z);
149
+ resize: none;
150
+ box-shadow: 0 24px 60px -24px rgba(22, 24, 26, 0.35);
151
+ animation: scaleIn 0.2s ease-out;
152
+ }
153
+
154
+ .frame.full {
155
+ position: fixed;
156
+ inset: 0;
157
+ width: auto;
158
+ height: auto;
159
+ max-width: none;
160
+ border-radius: 0;
161
+ border: none;
162
+ z-index: var(--c-z);
163
+ resize: none;
164
+ }
165
+
166
+ .root {
167
+ position: relative;
168
+ display: flex;
169
+ flex: 1;
170
+ min-width: 0;
171
+ min-height: 0;
172
+ font-family: var(--sb-font, "Geist", -apple-system, "Segoe UI", Helvetica, sans-serif);
173
+ background: var(--c-bg);
174
+ color: var(--c-ink);
175
+ }
176
+
177
+ /* ── launcher ─────────────────────────────────────────── */
178
+
179
+ .launcher-btn {
180
+ position: fixed;
181
+ bottom: 24px;
182
+ right: 24px;
183
+ z-index: calc(var(--c-z) + 1);
184
+ width: 56px;
185
+ height: 56px;
186
+ border-radius: 999px;
187
+ display: inline-flex;
188
+ align-items: center;
189
+ justify-content: center;
190
+ border: none;
191
+ cursor: pointer;
192
+ background: var(--c-brand);
193
+ color: var(--c-on-brand);
194
+ box-shadow: 0 12px 28px -10px rgba(22, 24, 26, 0.45);
195
+ }
196
+
197
+ :host([position="left"]) .launcher-btn,
198
+ :host([position="left"]) .bubble {
199
+ right: auto;
200
+ left: 24px;
201
+ }
202
+
203
+ .badge {
204
+ position: absolute;
205
+ top: 2px;
206
+ right: 2px;
207
+ width: 12px;
208
+ height: 12px;
209
+ border-radius: 999px;
210
+ background: var(--c-danger);
211
+ border: 2px solid var(--c-bg);
212
+ }
213
+
214
+ .bubble {
215
+ position: fixed;
216
+ bottom: 96px;
217
+ right: 24px;
218
+ z-index: var(--c-z);
219
+ width: 260px;
220
+ display: flex;
221
+ align-items: flex-start;
222
+ gap: 8px;
223
+ padding: 12px 10px 12px 14px;
224
+ background: var(--c-bg);
225
+ color: var(--c-ink);
226
+ border: 1px solid var(--c-line);
227
+ border-radius: calc(var(--c-r) * 2.5);
228
+ box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.25);
229
+ font-family: var(--sb-font, "Geist", -apple-system, "Segoe UI", Helvetica, sans-serif);
230
+ animation: aiIn 0.25s ease-out;
231
+ }
232
+
233
+ .bubble-text {
234
+ flex: 1;
235
+ min-width: 0;
236
+ text-align: left;
237
+ font-size: 13.5px;
238
+ line-height: 1.45;
239
+ background: none;
240
+ border: none;
241
+ padding: 0;
242
+ cursor: pointer;
243
+ }
244
+
245
+ /* ── icon buttons ─────────────────────────────────────── */
246
+
247
+ .icon {
248
+ display: inline-flex;
249
+ align-items: center;
250
+ justify-content: center;
251
+ flex: 0 0 auto;
252
+ width: 28px;
253
+ height: 28px;
254
+ padding: 0;
255
+ border: none;
256
+ border-radius: var(--c-r);
257
+ background: transparent;
258
+ color: var(--c-muted);
259
+ cursor: pointer;
260
+ }
261
+
262
+ .icon:hover:not(:disabled),
263
+ .icon.on {
264
+ color: var(--c-ink);
265
+ }
266
+
267
+ .icon:hover:not(:disabled) {
268
+ background: var(--c-hover);
269
+ }
270
+
271
+ .icon.danger:hover:not(:disabled) {
272
+ color: var(--c-danger);
273
+ }
274
+
275
+ .icon:disabled {
276
+ opacity: 0.4;
277
+ cursor: default;
278
+ }
279
+
280
+ .icon.sm {
281
+ width: 24px;
282
+ height: 24px;
283
+ }
284
+
285
+ svg.i {
286
+ width: 16px;
287
+ height: 16px;
288
+ fill: none;
289
+ stroke: currentColor;
290
+ stroke-width: 1.5;
291
+ stroke-linecap: round;
292
+ stroke-linejoin: round;
293
+ }
294
+
295
+ svg.i.filled path {
296
+ fill: currentColor;
297
+ }
298
+
299
+ @media (pointer: coarse) {
300
+ .icon {
301
+ width: 44px;
302
+ height: 44px;
303
+ }
304
+ }
305
+
306
+ /* ── sidebar ──────────────────────────────────────────── */
307
+
308
+ .scrim {
309
+ position: absolute;
310
+ inset: 0;
311
+ z-index: 29;
312
+ background: rgba(22, 24, 26, 0.18);
313
+ }
314
+
315
+ .sidebar {
316
+ display: flex;
317
+ flex-direction: column;
318
+ min-height: 0;
319
+ min-width: 0;
320
+ background: var(--c-bg2);
321
+ border-right: 1px solid var(--c-line);
322
+ }
323
+
324
+ .sidebar.docked {
325
+ position: relative;
326
+ flex: 0 0 272px;
327
+ width: 272px;
328
+ }
329
+
330
+ .sidebar.overlay {
331
+ position: absolute;
332
+ left: 0;
333
+ top: 0;
334
+ bottom: 0;
335
+ z-index: 30;
336
+ width: min(280px, 86%);
337
+ box-shadow: 12px 0 32px -16px rgba(22, 24, 26, 0.25);
338
+ animation: slideIn 0.15s ease-out;
339
+ }
340
+
341
+ .side-head {
342
+ display: flex;
343
+ align-items: center;
344
+ justify-content: space-between;
345
+ gap: 8px;
346
+ padding: 14px 12px 10px 16px;
347
+ }
348
+
349
+ .side-tools {
350
+ display: flex;
351
+ flex-direction: column;
352
+ gap: 8px;
353
+ padding: 0 12px 8px;
354
+ }
355
+
356
+ .new-chat {
357
+ display: flex;
358
+ align-items: center;
359
+ gap: 8px;
360
+ width: 100%;
361
+ min-height: 34px;
362
+ font-size: 13px;
363
+ font-weight: 500;
364
+ color: var(--c-on-brand);
365
+ background: var(--c-brand);
366
+ border: 1px solid var(--c-brand);
367
+ border-radius: var(--c-r2);
368
+ padding: 8px 12px;
369
+ cursor: pointer;
370
+ }
371
+
372
+ .new-chat:hover {
373
+ filter: brightness(1.2);
374
+ }
375
+
376
+ .search {
377
+ width: 100%;
378
+ font: inherit;
379
+ font-size: 13px;
380
+ color: var(--c-ink);
381
+ background: var(--c-bg);
382
+ border: 1px solid var(--c-line);
383
+ border-radius: var(--c-r2);
384
+ padding: 8px 10px;
385
+ outline: none;
386
+ }
387
+
388
+ .search:focus {
389
+ border-color: var(--c-ink);
390
+ }
391
+
392
+ .threads {
393
+ flex: 1;
394
+ min-height: 0;
395
+ overflow-y: auto;
396
+ display: flex;
397
+ flex-direction: column;
398
+ gap: 1px;
399
+ padding: 4px 12px 12px;
400
+ }
401
+
402
+ .group {
403
+ font-family: var(--c-mono);
404
+ font-size: 11px;
405
+ letter-spacing: 0.07em;
406
+ text-transform: uppercase;
407
+ color: var(--c-muted);
408
+ padding: 10px 8px 6px;
409
+ }
410
+
411
+ .thread {
412
+ display: flex;
413
+ align-items: center;
414
+ gap: 4px;
415
+ min-height: 34px;
416
+ width: 100%;
417
+ font-size: 13px;
418
+ color: var(--c-ink);
419
+ border-radius: var(--c-r2);
420
+ padding: 3px 4px 3px 10px;
421
+ cursor: pointer;
422
+ }
423
+
424
+ .thread:hover {
425
+ background: var(--c-hover);
426
+ }
427
+
428
+ .thread.active {
429
+ background: var(--c-line2);
430
+ font-weight: 500;
431
+ }
432
+
433
+ .thread-title {
434
+ flex: 1;
435
+ min-width: 0;
436
+ overflow: hidden;
437
+ text-overflow: ellipsis;
438
+ white-space: nowrap;
439
+ }
440
+
441
+ .thread-actions {
442
+ display: none;
443
+ gap: 0;
444
+ }
445
+
446
+ .thread:hover .thread-actions,
447
+ .thread:focus-within .thread-actions {
448
+ display: flex;
449
+ }
450
+
451
+ .thread-rename {
452
+ flex: 1;
453
+ min-width: 0;
454
+ font: inherit;
455
+ color: var(--c-ink);
456
+ background: var(--c-bg);
457
+ border: 1px solid var(--c-ink);
458
+ border-radius: var(--c-r);
459
+ padding: 3px 6px;
460
+ outline: none;
461
+ }
462
+
463
+ .side-extra {
464
+ display: none;
465
+ }
466
+
467
+ .side-extra.filled {
468
+ display: block;
469
+ padding: 12px 16px;
470
+ border-top: 1px solid var(--c-line);
471
+ font-size: 12.5px;
472
+ }
473
+
474
+ .side-note {
475
+ font-size: 12.5px;
476
+ color: var(--c-muted);
477
+ padding: 6px 10px;
478
+ }
479
+
480
+ .skeleton {
481
+ height: 28px;
482
+ margin: 3px 0;
483
+ border-radius: var(--c-r2);
484
+ background: linear-gradient(90deg, var(--c-hover) 0%, var(--c-line2) 50%, var(--c-hover) 100%);
485
+ background-size: 200% 100%;
486
+ animation: aiShimmer 1.6s linear infinite;
487
+ }
488
+
489
+ /* ── main column ──────────────────────────────────────── */
490
+
491
+ .main {
492
+ container: chat / inline-size;
493
+ position: relative;
494
+ flex: 1;
495
+ min-width: 0;
496
+ min-height: 0;
497
+ display: flex;
498
+ flex-direction: column;
499
+ }
500
+
501
+ .header {
502
+ display: flex;
503
+ align-items: center;
504
+ justify-content: space-between;
505
+ gap: 12px;
506
+ min-height: 52px;
507
+ padding: 10px 8px 10px 12px;
508
+ border-bottom: 1px solid var(--c-line);
509
+ }
510
+
511
+ .header-left {
512
+ display: flex;
513
+ align-items: center;
514
+ gap: 10px;
515
+ min-width: 0;
516
+ }
517
+
518
+ .header-right {
519
+ flex: 0 0 auto;
520
+ display: flex;
521
+ align-items: center;
522
+ gap: 2px;
523
+ }
524
+
525
+ .title {
526
+ min-width: 0;
527
+ font-size: 14px;
528
+ font-weight: 600;
529
+ letter-spacing: -0.01em;
530
+ overflow: hidden;
531
+ text-overflow: ellipsis;
532
+ white-space: nowrap;
533
+ background: none;
534
+ border: none;
535
+ padding: 2px 4px;
536
+ border-radius: var(--c-r);
537
+ cursor: text;
538
+ animation: aiIn 0.25s ease-out;
539
+ }
540
+
541
+ .title:hover:not(:disabled) {
542
+ background: var(--c-hover);
543
+ }
544
+
545
+ .title:disabled {
546
+ cursor: default;
547
+ }
548
+
549
+ .title-input {
550
+ min-width: 0;
551
+ width: 320px;
552
+ max-width: 100%;
553
+ font: inherit;
554
+ font-size: 14px;
555
+ font-weight: 600;
556
+ color: var(--c-ink);
557
+ background: var(--c-bg);
558
+ border: 1px solid var(--c-ink);
559
+ border-radius: var(--c-r);
560
+ padding: 2px 6px;
561
+ outline: none;
562
+ }
563
+
564
+ .divider {
565
+ width: 1px;
566
+ height: 18px;
567
+ background: var(--c-line);
568
+ margin: 0 4px;
569
+ }
570
+
571
+ .menu-wrap {
572
+ position: relative;
573
+ }
574
+
575
+ .menu-scrim {
576
+ position: fixed;
577
+ inset: 0;
578
+ z-index: 40;
579
+ }
580
+
581
+ .menu {
582
+ position: absolute;
583
+ right: 0;
584
+ top: 34px;
585
+ z-index: 41;
586
+ width: 220px;
587
+ display: flex;
588
+ flex-direction: column;
589
+ padding: 4px;
590
+ background: var(--c-bg);
591
+ border: 1px solid var(--c-line);
592
+ border-radius: var(--c-r2);
593
+ box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.22);
594
+ animation: aiIn 0.15s ease-out;
595
+ }
596
+
597
+ .menu .label {
598
+ font-size: 10.5px;
599
+ padding: 8px 10px 6px;
600
+ }
601
+
602
+ .menu-item {
603
+ display: flex;
604
+ align-items: baseline;
605
+ justify-content: space-between;
606
+ gap: 10px;
607
+ width: 100%;
608
+ text-align: left;
609
+ font-size: 13px;
610
+ background: none;
611
+ border: none;
612
+ border-radius: var(--c-r);
613
+ padding: 8px 10px;
614
+ cursor: pointer;
615
+ }
616
+
617
+ .menu-item:hover {
618
+ background: var(--c-hover);
619
+ }
620
+
621
+ .menu-item .ext {
622
+ font-family: var(--c-mono);
623
+ font-size: 11px;
624
+ color: var(--c-muted);
625
+ }
626
+
627
+ .scroller {
628
+ position: relative;
629
+ flex: 1;
630
+ min-height: 0;
631
+ overflow-y: auto;
632
+ }
633
+
634
+ .banner {
635
+ margin: 10px 16px 0;
636
+ padding: 8px 12px;
637
+ font-size: 12.5px;
638
+ color: var(--c-ink2);
639
+ background: var(--c-bg2);
640
+ border: 1px solid var(--c-line);
641
+ border-radius: var(--c-r2);
642
+ }
643
+
644
+ /* ── welcome ──────────────────────────────────────────── */
645
+
646
+ .welcome-slot {
647
+ min-height: 100%;
648
+ display: flex;
649
+ flex-direction: column;
650
+ justify-content: center;
651
+ }
652
+
653
+ ::slotted([slot="welcome"]) {
654
+ box-sizing: border-box;
655
+ width: 100%;
656
+ max-width: 640px;
657
+ margin: 0 auto;
658
+ padding: 28px 18px;
659
+ }
660
+
661
+ .welcome {
662
+ max-width: 640px;
663
+ min-height: 100%;
664
+ margin: 0 auto;
665
+ display: flex;
666
+ flex-direction: column;
667
+ justify-content: center;
668
+ gap: 20px;
669
+ padding: 28px 18px;
670
+ }
671
+
672
+ .welcome-head {
673
+ display: flex;
674
+ flex-direction: column;
675
+ gap: 8px;
676
+ }
677
+
678
+ .welcome-logo {
679
+ width: 32px;
680
+ height: 32px;
681
+ object-fit: contain;
682
+ border-radius: var(--c-r2);
683
+ }
684
+
685
+ .welcome h2 {
686
+ margin: 0;
687
+ font-size: 24px;
688
+ font-weight: 600;
689
+ letter-spacing: -0.01em;
690
+ }
691
+
692
+ .welcome p {
693
+ margin: 0;
694
+ font-size: 14px;
695
+ line-height: 1.55;
696
+ color: var(--c-muted);
697
+ text-wrap: pretty;
698
+ }
699
+
700
+ .prompts {
701
+ display: grid;
702
+ grid-template-columns: repeat(2, minmax(0, 1fr));
703
+ gap: 8px;
704
+ }
705
+
706
+ .prompt {
707
+ display: flex;
708
+ flex-direction: column;
709
+ gap: 4px;
710
+ text-align: left;
711
+ background: var(--c-bg);
712
+ border: 1px solid var(--c-line);
713
+ border-radius: var(--c-r2);
714
+ padding: 12px 14px;
715
+ cursor: pointer;
716
+ transition:
717
+ border-color 0.15s,
718
+ box-shadow 0.15s;
719
+ }
720
+
721
+ .prompt:hover {
722
+ border-color: var(--c-ink);
723
+ box-shadow: 0 6px 18px -10px rgba(22, 24, 26, 0.25);
724
+ }
725
+
726
+ .prompt .label {
727
+ font-size: 10.5px;
728
+ letter-spacing: 0.06em;
729
+ }
730
+
731
+ .prompt-text {
732
+ font-size: 13.5px;
733
+ font-weight: 500;
734
+ line-height: 1.4;
735
+ }
736
+
737
+ @container chat (max-width: 480px) {
738
+ .prompts {
739
+ grid-template-columns: minmax(0, 1fr);
740
+ }
741
+ }
742
+
743
+ /* ── messages ─────────────────────────────────────────── */
744
+
745
+ .thread-view {
746
+ max-width: 760px;
747
+ margin: 0 auto;
748
+ display: flex;
749
+ flex-direction: column;
750
+ gap: 30px;
751
+ padding: 20px 16px 28px;
752
+ }
753
+
754
+ .msg {
755
+ position: relative;
756
+ display: flex;
757
+ flex-direction: column;
758
+ border-radius: var(--c-r3);
759
+ }
760
+
761
+ .msg.user {
762
+ align-self: flex-end;
763
+ max-width: 80%;
764
+ align-items: flex-end;
765
+ gap: 6px;
766
+ margin-bottom: -22px;
767
+ animation: aiIn 0.25s ease-out;
768
+ }
769
+
770
+ .bubble-user {
771
+ padding: 10px 14px;
772
+ font-size: 14.5px;
773
+ line-height: 1.6;
774
+ white-space: pre-wrap;
775
+ overflow-wrap: anywhere;
776
+ background: var(--c-hover);
777
+ border-radius: calc(var(--c-r) * 2.5) calc(var(--c-r) * 2.5) 2px calc(var(--c-r) * 2.5);
778
+ }
779
+
780
+ .attachments {
781
+ display: flex;
782
+ flex-wrap: wrap;
783
+ justify-content: flex-end;
784
+ gap: 6px;
785
+ }
786
+
787
+ .doc-chip {
788
+ display: inline-flex;
789
+ align-items: center;
790
+ gap: 8px;
791
+ padding: 6px 10px;
792
+ font-size: 12.5px;
793
+ border-radius: var(--c-r2);
794
+ border: 1px solid var(--c-line);
795
+ background: var(--c-bg);
796
+ }
797
+
798
+ .doc-chip .ext {
799
+ font-family: var(--c-mono);
800
+ font-size: 10px;
801
+ letter-spacing: 0.04em;
802
+ color: var(--c-muted);
803
+ }
804
+
805
+ .doc-chip .name {
806
+ max-width: 180px;
807
+ overflow: hidden;
808
+ text-overflow: ellipsis;
809
+ white-space: nowrap;
810
+ }
811
+
812
+ .toolbar {
813
+ display: flex;
814
+ align-items: center;
815
+ gap: 2px;
816
+ opacity: 0;
817
+ transition: opacity 0.15s;
818
+ }
819
+
820
+ .msg:hover .toolbar,
821
+ .msg:focus-within .toolbar,
822
+ .toolbar.pinned {
823
+ opacity: 1;
824
+ }
825
+
826
+ @media (hover: none) {
827
+ .toolbar {
828
+ opacity: 1;
829
+ }
830
+ }
831
+
832
+ .msg.bot .toolbar {
833
+ margin-left: -6px;
834
+ }
835
+
836
+ .time {
837
+ font-family: var(--c-mono);
838
+ font-size: 11px;
839
+ color: var(--c-faint);
840
+ padding: 0 6px;
841
+ font-variant-numeric: tabular-nums;
842
+ }
843
+
844
+ .note {
845
+ font-size: 12px;
846
+ color: var(--c-muted);
847
+ }
848
+
849
+ .spacer {
850
+ flex: 1;
851
+ }
852
+
853
+ .saved {
854
+ display: inline-flex;
855
+ align-items: center;
856
+ gap: 4px;
857
+ font-family: var(--c-mono);
858
+ font-size: 10.5px;
859
+ letter-spacing: 0.05em;
860
+ text-transform: uppercase;
861
+ color: var(--c-ink);
862
+ }
863
+
864
+ .saved svg {
865
+ width: 12px;
866
+ height: 12px;
867
+ fill: currentColor;
868
+ stroke: currentColor;
869
+ stroke-width: 1.5;
870
+ }
871
+
872
+ .bot-body {
873
+ position: relative;
874
+ z-index: 1;
875
+ display: flex;
876
+ flex-direction: column;
877
+ gap: 12px;
878
+ }
879
+
880
+ .edit-box {
881
+ width: 440px;
882
+ max-width: 100%;
883
+ display: flex;
884
+ flex-direction: column;
885
+ gap: 8px;
886
+ padding: 8px;
887
+ border: 1px solid var(--c-ink);
888
+ border-radius: var(--c-r3);
889
+ background: var(--c-bg);
890
+ }
891
+
892
+ .edit-box textarea {
893
+ width: 100%;
894
+ resize: vertical;
895
+ font: inherit;
896
+ font-size: 14px;
897
+ line-height: 1.5;
898
+ color: var(--c-ink);
899
+ background: transparent;
900
+ border: none;
901
+ outline: none;
902
+ padding: 4px;
903
+ }
904
+
905
+ .row-end {
906
+ display: flex;
907
+ justify-content: flex-end;
908
+ gap: 8px;
909
+ }
910
+
911
+ .btn {
912
+ font-size: 12.5px;
913
+ font-weight: 500;
914
+ border-radius: var(--c-r);
915
+ padding: 6px 12px;
916
+ cursor: pointer;
917
+ background: transparent;
918
+ color: var(--c-muted);
919
+ border: 1px solid var(--c-line);
920
+ }
921
+
922
+ .btn:hover {
923
+ color: var(--c-ink);
924
+ background: var(--c-bg2);
925
+ }
926
+
927
+ .btn.primary {
928
+ background: var(--c-brand);
929
+ color: var(--c-on-brand);
930
+ border-color: var(--c-brand);
931
+ }
932
+
933
+ .btn.primary:hover {
934
+ filter: brightness(1.2);
935
+ }
936
+
937
+ .error-card {
938
+ display: flex;
939
+ align-items: center;
940
+ justify-content: space-between;
941
+ gap: 12px;
942
+ padding: 10px 12px;
943
+ font-size: 13px;
944
+ color: var(--c-danger);
945
+ border: 1px solid var(--sb-danger-border, #f3d6d3);
946
+ background: var(--sb-danger-bg, #fdf1f0);
947
+ border-radius: var(--c-r2);
948
+ }
949
+
950
+ .followups {
951
+ display: flex;
952
+ flex-direction: column;
953
+ align-items: flex-start;
954
+ gap: 6px;
955
+ }
956
+
957
+ .followup {
958
+ display: inline-flex;
959
+ align-items: baseline;
960
+ gap: 8px;
961
+ text-align: left;
962
+ font-size: 13px;
963
+ background: var(--c-bg);
964
+ border: 1px solid var(--c-line);
965
+ border-radius: var(--c-r2);
966
+ padding: 6px 12px;
967
+ cursor: pointer;
968
+ animation: aiIn 0.25s ease-out;
969
+ }
970
+
971
+ .followup:hover {
972
+ background: var(--c-hover);
973
+ }
974
+
975
+ .followup .arrow {
976
+ font-family: var(--c-mono);
977
+ color: var(--c-muted);
978
+ }
979
+
980
+ .jump {
981
+ position: absolute;
982
+ left: 50%;
983
+ bottom: 8px;
984
+ transform: translateX(-50%);
985
+ z-index: 5;
986
+ font-size: 12.5px;
987
+ font-weight: 500;
988
+ color: var(--c-on-brand);
989
+ background: var(--c-brand);
990
+ border: none;
991
+ border-radius: 999px;
992
+ padding: 6px 14px;
993
+ cursor: pointer;
994
+ box-shadow: 0 8px 20px -10px rgba(22, 24, 26, 0.4);
995
+ animation: aiIn 0.2s ease-out;
996
+ }
997
+
998
+ /* ── rendered answer ──────────────────────────────────── */
999
+
1000
+ .answer {
1001
+ display: flex;
1002
+ flex-direction: column;
1003
+ gap: 14px;
1004
+ font-size: 14.5px;
1005
+ line-height: 1.7;
1006
+ }
1007
+
1008
+ .answer p {
1009
+ margin: 0;
1010
+ text-wrap: pretty;
1011
+ overflow-wrap: anywhere;
1012
+ }
1013
+
1014
+ .answer .raw {
1015
+ white-space: pre-wrap;
1016
+ }
1017
+
1018
+ .answer h3 {
1019
+ margin: 6px 0 0;
1020
+ font-size: 15.5px;
1021
+ font-weight: 600;
1022
+ letter-spacing: -0.01em;
1023
+ line-height: 1.4;
1024
+ }
1025
+
1026
+ .answer ul,
1027
+ .answer ol {
1028
+ margin: 0;
1029
+ padding-left: 20px;
1030
+ display: flex;
1031
+ flex-direction: column;
1032
+ gap: 6px;
1033
+ }
1034
+
1035
+ .answer li {
1036
+ line-height: 1.65;
1037
+ padding-left: 2px;
1038
+ }
1039
+
1040
+ .answer strong {
1041
+ font-weight: 600;
1042
+ }
1043
+
1044
+ .answer a {
1045
+ color: var(--c-ink);
1046
+ text-underline-offset: 3px;
1047
+ }
1048
+
1049
+ .answer code.inline {
1050
+ font-family: var(--c-mono);
1051
+ font-size: 12.5px;
1052
+ background: var(--c-hover);
1053
+ border-radius: calc(var(--c-r) * 0.75);
1054
+ padding: 1px 5px;
1055
+ }
1056
+
1057
+ .answer h3.h1 {
1058
+ font-size: 18px;
1059
+ }
1060
+
1061
+ .answer h3.h2 {
1062
+ font-size: 16.5px;
1063
+ }
1064
+
1065
+ .answer h3.h4 {
1066
+ font-size: 14.5px;
1067
+ }
1068
+
1069
+ .answer hr {
1070
+ width: 100%;
1071
+ border: none;
1072
+ border-top: 1px solid var(--c-line);
1073
+ margin: 4px 0;
1074
+ }
1075
+
1076
+ .answer li.task {
1077
+ list-style: none;
1078
+ margin-left: -18px;
1079
+ }
1080
+
1081
+ .answer li.task input {
1082
+ margin: 0 6px 0 0;
1083
+ vertical-align: -1px;
1084
+ accent-color: var(--c-brand);
1085
+ }
1086
+
1087
+ .callout {
1088
+ display: flex;
1089
+ flex-direction: column;
1090
+ gap: 4px;
1091
+ font-size: 13.5px;
1092
+ line-height: 1.6;
1093
+ padding: 10px 14px;
1094
+ border: 1px solid var(--c-line);
1095
+ border-left: 3px solid var(--callout, var(--c-ink));
1096
+ border-radius: var(--c-r2);
1097
+ background: color-mix(in srgb, var(--callout, var(--c-ink)) 7%, var(--c-bg));
1098
+ }
1099
+
1100
+ .callout-title {
1101
+ font-weight: 600;
1102
+ color: var(--callout, var(--c-ink));
1103
+ }
1104
+
1105
+ .callout.note {
1106
+ --callout: oklch(0.55 0.15 255);
1107
+ }
1108
+
1109
+ .callout.tip {
1110
+ --callout: oklch(0.55 0.12 160);
1111
+ }
1112
+
1113
+ .callout.important {
1114
+ --callout: oklch(0.52 0.17 300);
1115
+ }
1116
+
1117
+ .callout.warning {
1118
+ --callout: oklch(0.6 0.14 70);
1119
+ }
1120
+
1121
+ .callout.caution {
1122
+ --callout: var(--c-danger);
1123
+ }
1124
+
1125
+ .jtree {
1126
+ padding: 10px 14px;
1127
+ overflow-x: auto;
1128
+ font-family: var(--c-mono);
1129
+ font-size: 12.5px;
1130
+ line-height: 1.7;
1131
+ }
1132
+
1133
+ .jtree summary {
1134
+ cursor: pointer;
1135
+ list-style-position: outside;
1136
+ }
1137
+
1138
+ .jkids {
1139
+ padding-left: 16px;
1140
+ border-left: 1px solid var(--c-line);
1141
+ margin-left: 4px;
1142
+ }
1143
+
1144
+ .jkey {
1145
+ color: var(--c-ink2);
1146
+ }
1147
+
1148
+ .jmeta {
1149
+ color: var(--c-muted);
1150
+ }
1151
+
1152
+ .jv.string {
1153
+ color: oklch(0.52 0.12 160);
1154
+ }
1155
+
1156
+ .jv.number {
1157
+ color: oklch(0.55 0.15 255);
1158
+ }
1159
+
1160
+ .jv.boolean,
1161
+ .jv.null {
1162
+ color: oklch(0.52 0.17 300);
1163
+ }
1164
+
1165
+ .table th button.sort {
1166
+ display: inline-flex;
1167
+ align-items: center;
1168
+ gap: 4px;
1169
+ font: inherit;
1170
+ color: inherit;
1171
+ background: none;
1172
+ border: none;
1173
+ padding: 0;
1174
+ cursor: pointer;
1175
+ }
1176
+
1177
+ .table th .arrow {
1178
+ font-size: 10px;
1179
+ opacity: 0.5;
1180
+ }
1181
+
1182
+ .table th[aria-sort="ascending"] .arrow,
1183
+ .table th[aria-sort="descending"] .arrow {
1184
+ opacity: 1;
1185
+ }
1186
+
1187
+ .table-note {
1188
+ padding: 7px 12px;
1189
+ font-size: 12px;
1190
+ color: var(--c-muted);
1191
+ border-top: 1px solid var(--c-line2);
1192
+ background: var(--c-bg2);
1193
+ }
1194
+
1195
+ figure.svg {
1196
+ margin: 0;
1197
+ display: flex;
1198
+ flex-direction: column;
1199
+ gap: 6px;
1200
+ align-items: flex-start;
1201
+ }
1202
+
1203
+ figure.svg img {
1204
+ display: block;
1205
+ width: min(100%, 480px);
1206
+ height: auto;
1207
+ max-height: 420px;
1208
+ object-fit: contain;
1209
+ padding: 12px;
1210
+ border: 1px solid var(--c-line);
1211
+ border-radius: var(--c-r2);
1212
+ background: #ffffff;
1213
+ }
1214
+
1215
+ .custom-block {
1216
+ min-width: 0;
1217
+ }
1218
+
1219
+ .quote {
1220
+ font-size: 13.5px;
1221
+ line-height: 1.6;
1222
+ color: var(--c-ink2);
1223
+ background: var(--c-bg2);
1224
+ border: 1px solid var(--c-line);
1225
+ border-radius: var(--c-r2);
1226
+ padding: 10px 14px;
1227
+ }
1228
+
1229
+ .code {
1230
+ border: 1px solid var(--c-line);
1231
+ border-radius: var(--c-r2);
1232
+ overflow: hidden;
1233
+ background: var(--c-bg2);
1234
+ }
1235
+
1236
+ .code-head {
1237
+ display: flex;
1238
+ align-items: center;
1239
+ justify-content: space-between;
1240
+ padding: 7px 12px;
1241
+ border-bottom: 1px solid var(--c-line);
1242
+ }
1243
+
1244
+ .code-head .label {
1245
+ font-size: 11px;
1246
+ }
1247
+
1248
+ .text-btn {
1249
+ font-size: 12px;
1250
+ color: var(--c-muted);
1251
+ background: none;
1252
+ border: none;
1253
+ padding: 0;
1254
+ cursor: pointer;
1255
+ }
1256
+
1257
+ .text-btn:hover {
1258
+ color: var(--c-ink);
1259
+ }
1260
+
1261
+ .text-btn.underline {
1262
+ text-decoration: underline;
1263
+ text-underline-offset: 3px;
1264
+ }
1265
+
1266
+ .code pre {
1267
+ margin: 0;
1268
+ padding: 12px 14px;
1269
+ overflow-x: auto;
1270
+ font-family: var(--c-mono);
1271
+ font-size: 13px;
1272
+ line-height: 1.6;
1273
+ }
1274
+
1275
+ .table {
1276
+ border: 1px solid var(--c-line);
1277
+ border-radius: var(--c-r2);
1278
+ overflow-x: auto;
1279
+ }
1280
+
1281
+ .table table {
1282
+ width: 100%;
1283
+ border-collapse: collapse;
1284
+ font-size: 13px;
1285
+ font-variant-numeric: tabular-nums;
1286
+ }
1287
+
1288
+ .table th {
1289
+ text-align: left;
1290
+ font-size: 12px;
1291
+ font-weight: 500;
1292
+ color: var(--c-muted);
1293
+ background: var(--c-bg2);
1294
+ border-bottom: 1px solid var(--c-line);
1295
+ padding: 9px 12px;
1296
+ white-space: nowrap;
1297
+ }
1298
+
1299
+ .table td {
1300
+ padding: 9px 12px;
1301
+ border-top: 1px solid var(--c-line2);
1302
+ white-space: nowrap;
1303
+ }
1304
+
1305
+ .table th:first-child,
1306
+ .table td:first-child {
1307
+ min-width: 120px;
1308
+ }
1309
+
1310
+ .cite {
1311
+ display: inline-flex;
1312
+ align-items: center;
1313
+ justify-content: center;
1314
+ min-width: 17px;
1315
+ height: 17px;
1316
+ padding: 0 4px;
1317
+ margin: 0 1px 0 3px;
1318
+ vertical-align: 2px;
1319
+ font: 500 10px var(--c-mono);
1320
+ border-radius: calc(var(--c-r) * 0.75);
1321
+ cursor: pointer;
1322
+ border: 1px solid var(--c-strong);
1323
+ background: var(--c-hover);
1324
+ color: var(--c-ink);
1325
+ }
1326
+
1327
+ .cite:hover,
1328
+ .cite.active {
1329
+ background: var(--c-ink);
1330
+ color: var(--c-bg);
1331
+ border-color: var(--c-ink);
1332
+ }
1333
+
1334
+ .chart {
1335
+ margin: 0;
1336
+ display: flex;
1337
+ flex-direction: column;
1338
+ gap: 14px;
1339
+ border: 1px solid var(--c-line);
1340
+ border-radius: var(--c-r2);
1341
+ padding: 14px 16px 12px;
1342
+ background: var(--c-bg);
1343
+ }
1344
+
1345
+ .chart-head {
1346
+ display: flex;
1347
+ flex-wrap: wrap;
1348
+ align-items: baseline;
1349
+ justify-content: space-between;
1350
+ gap: 8px 16px;
1351
+ }
1352
+
1353
+ .chart-title {
1354
+ font-size: 13px;
1355
+ font-weight: 600;
1356
+ }
1357
+
1358
+ .legend {
1359
+ display: flex;
1360
+ flex-wrap: wrap;
1361
+ gap: 4px 12px;
1362
+ }
1363
+
1364
+ .legend span {
1365
+ display: inline-flex;
1366
+ align-items: center;
1367
+ gap: 6px;
1368
+ font-size: 12px;
1369
+ color: var(--c-ink2);
1370
+ }
1371
+
1372
+ .swatch {
1373
+ width: 8px;
1374
+ height: 8px;
1375
+ border-radius: 2px;
1376
+ }
1377
+
1378
+ .bars {
1379
+ display: flex;
1380
+ flex-direction: column;
1381
+ gap: 10px;
1382
+ }
1383
+
1384
+ .bar-row {
1385
+ display: grid;
1386
+ grid-template-columns: 92px minmax(0, 1fr) 64px;
1387
+ align-items: center;
1388
+ gap: 12px;
1389
+ }
1390
+
1391
+ .bar-label {
1392
+ font-size: 12.5px;
1393
+ color: var(--c-ink2);
1394
+ overflow: hidden;
1395
+ text-overflow: ellipsis;
1396
+ white-space: nowrap;
1397
+ }
1398
+
1399
+ .bar-track {
1400
+ display: flex;
1401
+ height: 12px;
1402
+ background: var(--c-hover);
1403
+ border-radius: 2px;
1404
+ overflow: hidden;
1405
+ }
1406
+
1407
+ .bar-fill {
1408
+ display: flex;
1409
+ height: 100%;
1410
+ transform-origin: left;
1411
+ animation: aiGrow 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
1412
+ }
1413
+
1414
+ .bar-value {
1415
+ font-family: var(--c-mono);
1416
+ font-size: 11.5px;
1417
+ text-align: right;
1418
+ font-variant-numeric: tabular-nums;
1419
+ }
1420
+
1421
+ .line-chart {
1422
+ display: flex;
1423
+ flex-direction: column;
1424
+ gap: 6px;
1425
+ padding-left: 48px;
1426
+ }
1427
+
1428
+ .plot {
1429
+ position: relative;
1430
+ height: 170px;
1431
+ }
1432
+
1433
+ .tick {
1434
+ position: absolute;
1435
+ left: 0;
1436
+ right: 0;
1437
+ border-top: 1px dashed var(--c-line2);
1438
+ }
1439
+
1440
+ .tick.base {
1441
+ border-top: 1px solid var(--c-strong);
1442
+ }
1443
+
1444
+ .tick span,
1445
+ .x-labels span {
1446
+ font-family: var(--c-mono);
1447
+ font-size: 10.5px;
1448
+ color: var(--c-faint);
1449
+ white-space: nowrap;
1450
+ font-variant-numeric: tabular-nums;
1451
+ }
1452
+
1453
+ .tick span {
1454
+ position: absolute;
1455
+ right: calc(100% + 8px);
1456
+ top: -7px;
1457
+ }
1458
+
1459
+ .plot svg {
1460
+ position: absolute;
1461
+ inset: 0;
1462
+ width: 100%;
1463
+ height: 100%;
1464
+ overflow: visible;
1465
+ }
1466
+
1467
+ .plot polyline {
1468
+ fill: none;
1469
+ stroke-width: 2;
1470
+ vector-effect: non-scaling-stroke;
1471
+ stroke-linejoin: round;
1472
+ stroke-linecap: round;
1473
+ stroke-dasharray: 1;
1474
+ animation: aiDraw 1s ease-out;
1475
+ }
1476
+
1477
+ .x-labels {
1478
+ display: flex;
1479
+ justify-content: space-between;
1480
+ gap: 4px;
1481
+ }
1482
+
1483
+ .chart-pending {
1484
+ display: flex;
1485
+ align-items: center;
1486
+ justify-content: center;
1487
+ height: 190px;
1488
+ border: 1px solid var(--c-line);
1489
+ border-radius: var(--c-r2);
1490
+ background: linear-gradient(90deg, var(--c-bg2) 0%, var(--c-hover) 50%, var(--c-bg2) 100%);
1491
+ background-size: 200% 100%;
1492
+ animation: aiShimmer 1.6s linear infinite;
1493
+ }
1494
+
1495
+ .gallery {
1496
+ display: grid;
1497
+ grid-template-columns: minmax(0, 1fr);
1498
+ gap: 10px;
1499
+ max-width: 520px;
1500
+ }
1501
+
1502
+ .gallery.many {
1503
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1504
+ max-width: 100%;
1505
+ }
1506
+
1507
+ .gallery figure {
1508
+ margin: 0;
1509
+ display: flex;
1510
+ flex-direction: column;
1511
+ gap: 6px;
1512
+ min-width: 0;
1513
+ }
1514
+
1515
+ .gallery img {
1516
+ width: 100%;
1517
+ aspect-ratio: 16 / 10;
1518
+ max-height: 320px;
1519
+ object-fit: contain;
1520
+ border-radius: var(--c-r2);
1521
+ border: 1px solid var(--c-line);
1522
+ background: var(--c-bg2);
1523
+ }
1524
+
1525
+ .img-missing {
1526
+ aspect-ratio: 16 / 9;
1527
+ display: flex;
1528
+ align-items: center;
1529
+ justify-content: center;
1530
+ border-radius: var(--c-r2);
1531
+ border: 1px dashed var(--c-strong);
1532
+ background: repeating-linear-gradient(135deg, var(--c-bg2) 0 10px, var(--c-hover) 10px 20px);
1533
+ }
1534
+
1535
+ figcaption {
1536
+ font-family: var(--c-mono);
1537
+ font-size: 11px;
1538
+ color: var(--c-muted);
1539
+ overflow: hidden;
1540
+ text-overflow: ellipsis;
1541
+ white-space: nowrap;
1542
+ }
1543
+
1544
+ .caret {
1545
+ display: inline-block;
1546
+ width: 7px;
1547
+ height: 15px;
1548
+ margin-top: -6px;
1549
+ background: var(--c-brand);
1550
+ animation: rgcaret 1s steps(1) infinite;
1551
+ }
1552
+
1553
+ /* ── sources ──────────────────────────────────────────── */
1554
+
1555
+ .retrieval {
1556
+ display: flex;
1557
+ flex-direction: column;
1558
+ border: 1px solid var(--c-line);
1559
+ border-radius: var(--c-r2);
1560
+ background: var(--c-bg2);
1561
+ }
1562
+
1563
+ .retrieval-toggle {
1564
+ display: flex;
1565
+ align-items: center;
1566
+ gap: 10px;
1567
+ width: 100%;
1568
+ text-align: left;
1569
+ font-size: 12.5px;
1570
+ color: var(--c-ink2);
1571
+ background: none;
1572
+ border: none;
1573
+ padding: 9px 12px;
1574
+ cursor: pointer;
1575
+ }
1576
+
1577
+ .retrieval-toggle .chev,
1578
+ .retrieval-toggle .ms {
1579
+ font-family: var(--c-mono);
1580
+ font-size: 11px;
1581
+ color: var(--c-muted);
1582
+ }
1583
+
1584
+ .retrieval-list {
1585
+ display: flex;
1586
+ flex-direction: column;
1587
+ border-top: 1px solid var(--c-line);
1588
+ padding: 4px 12px;
1589
+ }
1590
+
1591
+ .passage {
1592
+ display: grid;
1593
+ grid-template-columns: 22px minmax(0, 1fr) 64px;
1594
+ align-items: center;
1595
+ gap: 10px;
1596
+ width: 100%;
1597
+ text-align: left;
1598
+ background: none;
1599
+ border: none;
1600
+ border-bottom: 1px solid var(--c-line2);
1601
+ padding: 8px 0;
1602
+ cursor: pointer;
1603
+ }
1604
+
1605
+ .passage:last-child {
1606
+ border-bottom: none;
1607
+ }
1608
+
1609
+ .passage .n,
1610
+ .passage .score {
1611
+ font-family: var(--c-mono);
1612
+ font-size: 11px;
1613
+ color: var(--c-muted);
1614
+ font-variant-numeric: tabular-nums;
1615
+ }
1616
+
1617
+ .passage .what {
1618
+ display: flex;
1619
+ flex-direction: column;
1620
+ gap: 1px;
1621
+ min-width: 0;
1622
+ }
1623
+
1624
+ .passage .what span:first-child {
1625
+ font-size: 12.5px;
1626
+ overflow: hidden;
1627
+ text-overflow: ellipsis;
1628
+ white-space: nowrap;
1629
+ }
1630
+
1631
+ .passage .what span:last-child {
1632
+ font-size: 11.5px;
1633
+ color: var(--c-muted);
1634
+ }
1635
+
1636
+ .relevance {
1637
+ display: flex;
1638
+ flex-direction: column;
1639
+ gap: 3px;
1640
+ align-items: flex-end;
1641
+ }
1642
+
1643
+ .relevance-track {
1644
+ width: 64px;
1645
+ height: 3px;
1646
+ background: var(--c-line);
1647
+ border-radius: 99px;
1648
+ overflow: hidden;
1649
+ }
1650
+
1651
+ .relevance-fill {
1652
+ display: block;
1653
+ height: 100%;
1654
+ background: var(--c-brand);
1655
+ }
1656
+
1657
+ .cards {
1658
+ display: flex;
1659
+ flex-direction: column;
1660
+ gap: 8px;
1661
+ }
1662
+
1663
+ .card-grid {
1664
+ display: grid;
1665
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1666
+ gap: 8px;
1667
+ }
1668
+
1669
+ .source-card {
1670
+ display: flex;
1671
+ flex-direction: column;
1672
+ gap: 6px;
1673
+ min-width: 0;
1674
+ text-align: left;
1675
+ padding: 10px 12px;
1676
+ border-radius: var(--c-r2);
1677
+ cursor: pointer;
1678
+ background: var(--c-bg);
1679
+ border: 1px solid var(--c-line);
1680
+ }
1681
+
1682
+ .source-card:hover,
1683
+ .source-card.active {
1684
+ border-color: var(--c-ink);
1685
+ }
1686
+
1687
+ .source-card .top {
1688
+ display: flex;
1689
+ align-items: center;
1690
+ gap: 8px;
1691
+ min-width: 0;
1692
+ }
1693
+
1694
+ .num {
1695
+ min-width: 16px;
1696
+ height: 16px;
1697
+ padding: 0 4px;
1698
+ border-radius: calc(var(--c-r) * 0.75);
1699
+ border: 1px solid var(--c-strong);
1700
+ display: inline-flex;
1701
+ align-items: center;
1702
+ justify-content: center;
1703
+ font-family: var(--c-mono);
1704
+ font-size: 10px;
1705
+ background: var(--c-bg);
1706
+ }
1707
+
1708
+ .source-card .t {
1709
+ font-size: 13px;
1710
+ font-weight: 500;
1711
+ overflow: hidden;
1712
+ text-overflow: ellipsis;
1713
+ white-space: nowrap;
1714
+ }
1715
+
1716
+ .source-card .s {
1717
+ font-size: 12px;
1718
+ line-height: 1.45;
1719
+ color: var(--c-muted);
1720
+ display: -webkit-box;
1721
+ -webkit-line-clamp: 2;
1722
+ -webkit-box-orient: vertical;
1723
+ overflow: hidden;
1724
+ }
1725
+
1726
+ .panel {
1727
+ display: flex;
1728
+ flex-direction: column;
1729
+ min-height: 0;
1730
+ min-width: 0;
1731
+ background: var(--c-bg);
1732
+ border-left: 1px solid var(--c-line);
1733
+ animation: aiIn 0.15s ease-out;
1734
+ }
1735
+
1736
+ .panel.docked {
1737
+ position: relative;
1738
+ flex: 0 0 400px;
1739
+ width: 400px;
1740
+ }
1741
+
1742
+ .panel.overlay {
1743
+ position: absolute;
1744
+ right: 0;
1745
+ top: 0;
1746
+ bottom: 0;
1747
+ z-index: 30;
1748
+ width: min(420px, 100%);
1749
+ box-shadow: -12px 0 32px -16px rgba(22, 24, 26, 0.25);
1750
+ }
1751
+
1752
+ .panel-head {
1753
+ display: flex;
1754
+ align-items: center;
1755
+ justify-content: space-between;
1756
+ gap: 8px;
1757
+ padding: 14px 18px;
1758
+ border-bottom: 1px solid var(--c-line);
1759
+ }
1760
+
1761
+ .panel-body {
1762
+ flex: 1;
1763
+ min-height: 0;
1764
+ overflow-y: auto;
1765
+ display: flex;
1766
+ flex-direction: column;
1767
+ gap: 16px;
1768
+ padding: 18px;
1769
+ }
1770
+
1771
+ .panel-body h3 {
1772
+ margin: 0;
1773
+ font-size: 16px;
1774
+ font-weight: 600;
1775
+ letter-spacing: -0.01em;
1776
+ }
1777
+
1778
+ .panel-meta {
1779
+ display: flex;
1780
+ flex-direction: column;
1781
+ gap: 4px;
1782
+ }
1783
+
1784
+ .panel-meta .path {
1785
+ font-family: var(--c-mono);
1786
+ font-size: 11px;
1787
+ color: var(--c-muted);
1788
+ overflow-wrap: anywhere;
1789
+ }
1790
+
1791
+ .panel-meta .meta {
1792
+ font-size: 12px;
1793
+ color: var(--c-muted);
1794
+ }
1795
+
1796
+ .passage-box {
1797
+ display: flex;
1798
+ flex-direction: column;
1799
+ gap: 8px;
1800
+ padding: 12px 14px;
1801
+ border-radius: var(--c-r2);
1802
+ background: var(--c-hover);
1803
+ border: 1px solid var(--c-strong);
1804
+ }
1805
+
1806
+ .passage-box .text {
1807
+ font-size: 13px;
1808
+ line-height: 1.6;
1809
+ color: var(--c-ink2);
1810
+ white-space: pre-wrap;
1811
+ overflow-wrap: anywhere;
1812
+ }
1813
+
1814
+ .passage-foot {
1815
+ display: flex;
1816
+ align-items: center;
1817
+ justify-content: space-between;
1818
+ gap: 8px;
1819
+ padding-top: 8px;
1820
+ border-top: 1px solid var(--c-line);
1821
+ }
1822
+
1823
+ .copy-ref {
1824
+ display: inline-flex;
1825
+ align-items: center;
1826
+ gap: 6px;
1827
+ font-size: 12px;
1828
+ background: var(--c-bg);
1829
+ border: 1px solid var(--c-line);
1830
+ border-radius: var(--c-r);
1831
+ padding: 4px 8px;
1832
+ cursor: pointer;
1833
+ }
1834
+
1835
+ .copy-ref:hover {
1836
+ border-color: var(--c-strong);
1837
+ }
1838
+
1839
+ .panel-foot {
1840
+ display: flex;
1841
+ flex-direction: column;
1842
+ gap: 6px;
1843
+ padding: 12px 18px 16px;
1844
+ border-top: 1px solid var(--c-line);
1845
+ }
1846
+
1847
+ .chips {
1848
+ display: flex;
1849
+ flex-wrap: wrap;
1850
+ gap: 6px;
1851
+ }
1852
+
1853
+ .chip {
1854
+ font-size: 12px;
1855
+ background: var(--c-bg);
1856
+ border: 1px solid var(--c-line);
1857
+ border-radius: var(--c-r);
1858
+ padding: 4px 8px;
1859
+ cursor: pointer;
1860
+ max-width: 100%;
1861
+ overflow: hidden;
1862
+ text-overflow: ellipsis;
1863
+ white-space: nowrap;
1864
+ }
1865
+
1866
+ .chip:hover {
1867
+ border-color: var(--c-ink);
1868
+ }
1869
+
1870
+ /* ── composer ─────────────────────────────────────────── */
1871
+
1872
+ .composer-wrap {
1873
+ padding: 0 12px 12px;
1874
+ }
1875
+
1876
+ .composer-wrap.reader {
1877
+ padding-top: 10px;
1878
+ }
1879
+
1880
+ .composer-col {
1881
+ max-width: 760px;
1882
+ margin: 0 auto;
1883
+ display: flex;
1884
+ flex-direction: column;
1885
+ gap: 8px;
1886
+ }
1887
+
1888
+ .composer-box {
1889
+ position: relative;
1890
+ }
1891
+
1892
+ .composer {
1893
+ position: relative;
1894
+ z-index: 1;
1895
+ display: flex;
1896
+ flex-direction: column;
1897
+ gap: 4px;
1898
+ padding: 8px;
1899
+ border-radius: calc(var(--c-r) * 2.25);
1900
+ background: var(--c-bg);
1901
+ border: 1px solid var(--c-strong);
1902
+ box-shadow:
1903
+ 0 1px 2px rgba(22, 24, 26, 0.04),
1904
+ 0 12px 32px -18px rgba(22, 24, 26, 0.22);
1905
+ transition: border-color 0.15s;
1906
+ }
1907
+
1908
+ .composer:focus-within {
1909
+ border-color: var(--c-ink);
1910
+ }
1911
+
1912
+ .composer.busy {
1913
+ border-color: transparent;
1914
+ }
1915
+
1916
+ :host([glow="off"]) .composer.busy {
1917
+ border-color: var(--c-strong);
1918
+ }
1919
+
1920
+ .composer textarea {
1921
+ width: 100%;
1922
+ resize: none;
1923
+ font: inherit;
1924
+ font-size: 14.5px;
1925
+ line-height: 1.5;
1926
+ color: var(--c-ink);
1927
+ background: transparent;
1928
+ border: none;
1929
+ outline: none;
1930
+ padding: 6px 6px 2px;
1931
+ max-height: 176px;
1932
+ }
1933
+
1934
+ .composer textarea::placeholder {
1935
+ color: var(--c-faint);
1936
+ }
1937
+
1938
+ .composer-row {
1939
+ display: flex;
1940
+ align-items: center;
1941
+ justify-content: space-between;
1942
+ gap: 8px;
1943
+ }
1944
+
1945
+ .attach {
1946
+ display: inline-flex;
1947
+ align-items: center;
1948
+ gap: 6px;
1949
+ font-size: 12.5px;
1950
+ color: var(--c-muted);
1951
+ background: none;
1952
+ border: none;
1953
+ border-radius: var(--c-r);
1954
+ padding: 6px 8px;
1955
+ cursor: pointer;
1956
+ }
1957
+
1958
+ .attach:hover {
1959
+ background: var(--c-hover);
1960
+ color: var(--c-ink);
1961
+ }
1962
+
1963
+ .send {
1964
+ display: inline-flex;
1965
+ align-items: center;
1966
+ justify-content: center;
1967
+ width: 32px;
1968
+ height: 32px;
1969
+ padding: 0;
1970
+ border-radius: var(--c-r2);
1971
+ border: 1px solid var(--c-brand);
1972
+ cursor: pointer;
1973
+ background: var(--c-brand);
1974
+ color: var(--c-on-brand);
1975
+ transition: background 0.15s;
1976
+ }
1977
+
1978
+ .send:disabled {
1979
+ cursor: default;
1980
+ background: var(--c-line);
1981
+ border-color: var(--c-line);
1982
+ color: var(--c-faint);
1983
+ }
1984
+
1985
+ .send.stop {
1986
+ background: var(--c-bg);
1987
+ color: var(--c-ink);
1988
+ border-color: var(--c-ink);
1989
+ }
1990
+
1991
+ .send.stop svg {
1992
+ fill: currentColor;
1993
+ stroke: none;
1994
+ }
1995
+
1996
+ .pending-files {
1997
+ display: flex;
1998
+ flex-wrap: wrap;
1999
+ gap: 6px;
2000
+ padding: 2px 2px 4px;
2001
+ }
2002
+
2003
+ .pending-file {
2004
+ display: inline-flex;
2005
+ align-items: center;
2006
+ gap: 8px;
2007
+ padding: 4px 8px 4px 4px;
2008
+ font-size: 12.5px;
2009
+ border-radius: var(--c-r2);
2010
+ border: 1px solid var(--c-line);
2011
+ background: var(--c-bg2);
2012
+ animation: aiIn 0.2s ease-out;
2013
+ }
2014
+
2015
+ .pending-file .ext {
2016
+ width: 28px;
2017
+ height: 28px;
2018
+ display: inline-flex;
2019
+ align-items: center;
2020
+ justify-content: center;
2021
+ border-radius: var(--c-r);
2022
+ background: var(--c-bg);
2023
+ border: 1px solid var(--c-line);
2024
+ font-family: var(--c-mono);
2025
+ font-size: 9px;
2026
+ letter-spacing: 0.03em;
2027
+ color: var(--c-muted);
2028
+ }
2029
+
2030
+ .pending-file .meta {
2031
+ display: flex;
2032
+ flex-direction: column;
2033
+ gap: 1px;
2034
+ min-width: 0;
2035
+ }
2036
+
2037
+ .pending-file .name {
2038
+ max-width: 160px;
2039
+ overflow: hidden;
2040
+ text-overflow: ellipsis;
2041
+ white-space: nowrap;
2042
+ }
2043
+
2044
+ .pending-file .size {
2045
+ font-family: var(--c-mono);
2046
+ font-size: 10.5px;
2047
+ color: var(--c-muted);
2048
+ }
2049
+
2050
+ .pending-file button {
2051
+ font-size: 15px;
2052
+ line-height: 1;
2053
+ color: var(--c-muted);
2054
+ background: none;
2055
+ border: none;
2056
+ padding: 0 0 0 2px;
2057
+ cursor: pointer;
2058
+ }
2059
+
2060
+ .pending-file button:hover {
2061
+ color: var(--c-danger);
2062
+ }
2063
+
2064
+ .footnote {
2065
+ text-align: center;
2066
+ font-size: 11.5px;
2067
+ color: var(--c-muted);
2068
+ }
2069
+
2070
+ .branding {
2071
+ padding: 0 12px 10px;
2072
+ margin-top: -4px;
2073
+ }
2074
+
2075
+ .toast {
2076
+ position: absolute;
2077
+ left: 50%;
2078
+ bottom: 124px;
2079
+ transform: translateX(-50%);
2080
+ z-index: 35;
2081
+ display: flex;
2082
+ align-items: center;
2083
+ gap: 14px;
2084
+ padding: 9px 14px;
2085
+ background: var(--c-ink);
2086
+ color: var(--c-bg);
2087
+ font-size: 13px;
2088
+ border-radius: var(--c-r2);
2089
+ box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.25);
2090
+ white-space: nowrap;
2091
+ animation: aiIn 0.2s ease-out;
2092
+ }
2093
+
2094
+ .toast button {
2095
+ font-size: 13px;
2096
+ font-weight: 500;
2097
+ color: var(--c-bg);
2098
+ background: none;
2099
+ border: none;
2100
+ padding: 0;
2101
+ cursor: pointer;
2102
+ text-decoration: underline;
2103
+ text-underline-offset: 3px;
2104
+ }
2105
+
2106
+ .drop {
2107
+ position: absolute;
2108
+ inset: 10px;
2109
+ z-index: 36;
2110
+ display: flex;
2111
+ flex-direction: column;
2112
+ align-items: center;
2113
+ justify-content: center;
2114
+ gap: 6px;
2115
+ text-align: center;
2116
+ padding: 16px;
2117
+ border: 1.5px dashed var(--c-ink);
2118
+ border-radius: var(--c-r3);
2119
+ background: color-mix(in srgb, var(--c-bg) 92%, transparent);
2120
+ }
2121
+
2122
+ .drop strong {
2123
+ font-size: 15px;
2124
+ font-weight: 600;
2125
+ }
2126
+
2127
+ .drop span {
2128
+ font-size: 12.5px;
2129
+ color: var(--c-muted);
2130
+ }
2131
+
2132
+ /* ── AI glow ──────────────────────────────────────────── */
2133
+
2134
+ .halo {
2135
+ position: absolute;
2136
+ inset: -18px -24px;
2137
+ z-index: 0;
2138
+ pointer-events: none;
2139
+ opacity: var(--c-glow);
2140
+ }
2141
+
2142
+ .halo::before {
2143
+ content: "";
2144
+ position: absolute;
2145
+ inset: 0;
2146
+ border-radius: 20px;
2147
+ background: var(--c-conic);
2148
+ filter: blur(32px);
2149
+ opacity: 0.45;
2150
+ animation:
2151
+ aiSpin 5s linear infinite,
2152
+ aiBreathe 2.6s ease-in-out infinite;
2153
+ }
2154
+
2155
+ .arrived {
2156
+ position: absolute;
2157
+ inset: -12px -16px;
2158
+ z-index: 0;
2159
+ pointer-events: none;
2160
+ border-radius: var(--c-r4);
2161
+ animation: aiDone 2.6s ease-out forwards;
2162
+ }
2163
+
2164
+ .arrived .wash {
2165
+ position: absolute;
2166
+ inset: 0;
2167
+ border-radius: inherit;
2168
+ background: var(--c-conic);
2169
+ filter: blur(26px);
2170
+ opacity: calc(0.22 * var(--c-glow) + 0.06);
2171
+ animation: aiSpin 2.6s linear infinite;
2172
+ }
2173
+
2174
+ .ring {
2175
+ position: absolute;
2176
+ inset: 0;
2177
+ border-radius: inherit;
2178
+ padding: 1px;
2179
+ background: var(--c-conic);
2180
+ -webkit-mask:
2181
+ linear-gradient(#000 0 0) content-box,
2182
+ linear-gradient(#000 0 0);
2183
+ -webkit-mask-composite: xor;
2184
+ mask-composite: exclude;
2185
+ animation: aiSpin 2.6s linear infinite;
2186
+ pointer-events: none;
2187
+ }
2188
+
2189
+ .arrived .sweep {
2190
+ position: absolute;
2191
+ inset: 0;
2192
+ border-radius: inherit;
2193
+ overflow: hidden;
2194
+ }
2195
+
2196
+ .arrived .sweep::before {
2197
+ content: "";
2198
+ position: absolute;
2199
+ inset: 0;
2200
+ background: linear-gradient(
2201
+ 100deg,
2202
+ transparent 25%,
2203
+ oklch(0.88 0.07 260 / 0.5) 50%,
2204
+ transparent 75%
2205
+ );
2206
+ animation: aiSweep 1.6s cubic-bezier(0.3, 0.6, 0.3, 1) forwards;
2207
+ }
2208
+
2209
+ .pill {
2210
+ position: relative;
2211
+ display: inline-flex;
2212
+ align-self: flex-start;
2213
+ align-items: center;
2214
+ gap: 9px;
2215
+ padding: 6px 14px 6px 10px;
2216
+ border-radius: 999px;
2217
+ background: var(--c-bg);
2218
+ box-shadow: 0 0 24px -6px oklch(0.7 0.15 280 / 0.5);
2219
+ animation: aiIn 0.25s ease-out;
2220
+ }
2221
+
2222
+ .pill .ring {
2223
+ border-radius: 999px;
2224
+ animation-duration: 2.4s;
2225
+ }
2226
+
2227
+ .pill .dot {
2228
+ width: 9px;
2229
+ height: 9px;
2230
+ border-radius: 50%;
2231
+ background: var(--c-conic);
2232
+ animation:
2233
+ aiSpin 1.6s linear infinite,
2234
+ aiPulse 1.6s ease-in-out infinite;
2235
+ }
2236
+
2237
+ .pill .shimmer {
2238
+ font-size: 12.5px;
2239
+ font-weight: 500;
2240
+ background: linear-gradient(90deg, var(--c-faint) 0%, var(--c-ink) 45%, var(--c-faint) 90%);
2241
+ background-size: 200% 100%;
2242
+ -webkit-background-clip: text;
2243
+ background-clip: text;
2244
+ color: transparent;
2245
+ animation: aiShimmer 1.8s linear infinite;
2246
+ }
2247
+
2248
+ .composer-glow {
2249
+ position: absolute;
2250
+ inset: -4px;
2251
+ z-index: 0;
2252
+ border-radius: var(--c-r4);
2253
+ background: var(--c-conic);
2254
+ filter: blur(14px);
2255
+ opacity: calc(0.32 + 0.23 * (var(--c-glow) - 0.6) / 0.4);
2256
+ animation: aiSpin 4s linear infinite;
2257
+ pointer-events: none;
2258
+ }
2259
+
2260
+ .composer-ring {
2261
+ position: absolute;
2262
+ inset: 0;
2263
+ z-index: 2;
2264
+ border-radius: calc(var(--c-r) * 2.25);
2265
+ pointer-events: none;
2266
+ }
2267
+
2268
+ .composer-ring .ring {
2269
+ animation-duration: 3s;
2270
+ }
2271
+
2272
+ :host([glow="off"]) .halo,
2273
+ :host([glow="off"]) .arrived,
2274
+ :host([glow="off"]) .composer-glow,
2275
+ :host([glow="off"]) .composer-ring,
2276
+ :host([glow="off"]) .pill .ring {
2277
+ display: none;
2278
+ }
2279
+
2280
+ :host([glow="off"]) .pill {
2281
+ box-shadow: inset 0 0 0 1px var(--c-line);
2282
+ }
2283
+
2284
+ :host([glow="off"]) .pill .dot {
2285
+ background: var(--c-ink);
2286
+ }
2287
+
2288
+ @keyframes aiSpin {
2289
+ to {
2290
+ --sb-ai-angle: 360deg;
2291
+ }
2292
+ }
2293
+
2294
+ @keyframes aiShimmer {
2295
+ from {
2296
+ background-position: 200% 0;
2297
+ }
2298
+ to {
2299
+ background-position: -200% 0;
2300
+ }
2301
+ }
2302
+
2303
+ @keyframes aiBreathe {
2304
+ 0%,
2305
+ 100% {
2306
+ transform: scale(0.97);
2307
+ }
2308
+ 50% {
2309
+ transform: scale(1.03);
2310
+ }
2311
+ }
2312
+
2313
+ @keyframes aiPulse {
2314
+ 0%,
2315
+ 100% {
2316
+ transform: scale(0.8);
2317
+ }
2318
+ 50% {
2319
+ transform: scale(1.15);
2320
+ }
2321
+ }
2322
+
2323
+ @keyframes aiDone {
2324
+ 0% {
2325
+ opacity: 0;
2326
+ }
2327
+ 12% {
2328
+ opacity: 1;
2329
+ }
2330
+ 100% {
2331
+ opacity: 0;
2332
+ }
2333
+ }
2334
+
2335
+ @keyframes aiSweep {
2336
+ from {
2337
+ transform: translateX(-100%);
2338
+ }
2339
+ to {
2340
+ transform: translateX(100%);
2341
+ }
2342
+ }
2343
+
2344
+ @keyframes aiIn {
2345
+ from {
2346
+ opacity: 0;
2347
+ transform: translateY(4px);
2348
+ }
2349
+ to {
2350
+ opacity: 1;
2351
+ transform: none;
2352
+ }
2353
+ }
2354
+
2355
+ @keyframes scaleIn {
2356
+ from {
2357
+ opacity: 0;
2358
+ transform: translateY(12px) scale(0.98);
2359
+ }
2360
+ to {
2361
+ opacity: 1;
2362
+ transform: none;
2363
+ }
2364
+ }
2365
+
2366
+ @keyframes slideIn {
2367
+ from {
2368
+ opacity: 0;
2369
+ transform: translateX(-8px);
2370
+ }
2371
+ to {
2372
+ opacity: 1;
2373
+ transform: none;
2374
+ }
2375
+ }
2376
+
2377
+ @keyframes aiGrow {
2378
+ from {
2379
+ transform: scaleX(0);
2380
+ }
2381
+ }
2382
+
2383
+ @keyframes aiDraw {
2384
+ from {
2385
+ stroke-dashoffset: 1;
2386
+ }
2387
+ to {
2388
+ stroke-dashoffset: 0;
2389
+ }
2390
+ }
2391
+
2392
+ @keyframes rgcaret {
2393
+ 0%,
2394
+ 100% {
2395
+ opacity: 1;
2396
+ }
2397
+ 50% {
2398
+ opacity: 0;
2399
+ }
2400
+ }
2401
+
2402
+ @media (prefers-reduced-motion: reduce) {
2403
+ *,
2404
+ *::before,
2405
+ *::after {
2406
+ animation-duration: 0.01ms !important;
2407
+ animation-iteration-count: 1 !important;
2408
+ }
2409
+ .caret {
2410
+ display: none;
2411
+ }
2412
+ }
2413
+
2414
+ @media print {
2415
+ .sidebar,
2416
+ .scrim,
2417
+ .header-right,
2418
+ .composer-wrap,
2419
+ .branding,
2420
+ .toolbar,
2421
+ .followups,
2422
+ .panel,
2423
+ .toast {
2424
+ display: none !important;
2425
+ }
2426
+ .frame,
2427
+ .scroller {
2428
+ overflow: visible;
2429
+ height: auto;
2430
+ }
2431
+ }
2432
+ `,Nt={eyebrowChat:"Chat",eyebrowRag:"Grounded answers",headingChat:"What can I help with?",headingRag:"Ask your knowledge base",descriptionChat:"Ask anything. Attach text files to give it more context.",descriptionRag:"Answers are grounded in your sources, with a citation for every claim. Attach text files to search them too.",placeholderChat:"Message {name}…",placeholderRag:"Ask about your sources…",footnote:"{name} can make mistakes. Check important details.",attach:"Attach files",send:"Send message",stop:"Stop generating",removeFile:"Remove file",dropTitle:"Drop files to attach",dropSub:"Text, Markdown, CSV and JSON files are added as context.",thinking:"Thinking",searching:"Searching sources",chats:"Chats",newChat:"New chat",searchChats:"Search chats",groupBookmarked:"Bookmarked",groupToday:"Today",groupYesterday:"Yesterday",groupWeek:"Previous 7 days",groupOlder:"Older",noChats:"No chats yet.",noMatch:"No chats match “{query}”.",loadingChats:"Loading chats",showChats:"Show chats",hideSidebar:"Hide sidebar",untitled:"New chat",renameChat:"Rename chat",bookmarkChat:"Bookmark chat",unbookmarkChat:"Remove chat bookmark",exportChat:"Export chat",deleteChat:"Delete chat",expand:"Expand",restore:"Restore size",minimize:"Minimize chat",exportHeading:"Export this chat",exportMarkdown:"Markdown",exportJson:"JSON",exportText:"Plain text",exportCopy:"Copy as Markdown",copy:"Copy",copied:"Copied",edit:"Edit and resend",saveResend:"Save & resend",cancel:"Cancel",regenerate:"Regenerate",helpful:"Helpful",notHelpful:"Not helpful",markedHelpful:"Marked helpful",thanksFeedback:"Thanks for the feedback",bookmarkMessage:"Bookmark message",unbookmarkMessage:"Remove bookmark",deleteMessage:"Delete message",saved:"Saved",stopped:"Stopped",emptyReply:"(empty response)",newReply:"New reply",you:"You",sourcesCited:"Cited sources",sourcesRetrieved:"Sources",searchedSources:"Searched {n} sources",sourceLabel:"Source {n}",openSource:"Open source {n}",citedPassage:"Cited passage",copyReference:"Copy passage with reference",alsoCited:"Also cited",close:"Close",renderingChart:"Rendering chart",renderingSvg:"Rendering drawing",copySvg:"Copy SVG",showRaw:"View raw",showFormatted:"View formatted",showingRows:"Showing {n} of {total} rows",calloutNote:"Note",calloutTip:"Tip",calloutImportant:"Important",calloutWarning:"Warning",calloutCaution:"Caution",undo:"Undo",chatDeleted:"Chat deleted",messageDeleted:"Message deleted",messageBookmarked:"Message bookmarked",bookmarkRemoved:"Bookmark removed",chatBookmarked:"Chat bookmarked",chatUnbookmarked:"Chat removed from bookmarks",exported:"Exported {name}",copiedMarkdown:"Copied as Markdown",fileTooLarge:"{name} is larger than {size}.",fileType:"{name} isn't a text file.",tooManyFiles:"Attach up to {n} files at a time.",errGeneric:"Something went wrong.",errNotFound:"This chat no longer exists. Retry to start a new one.",errNoClient:"Chat isn't connected. Create a SinglebaseClient() on this page.",errLoad:"Couldn't load this chat.",retry:"Retry",offline:"You're offline. Messages will send when you reconnect.",bubbleText:"Hi! Questions? Ask me here.",openChat:"Open chat",closeChat:"Close chat",dismiss:"Dismiss",brandingLabel:"Chat by Singlebase"};function At(l){return{...Nt,...l??{}}}const Gt=/^\|.*\|$/,xt=/^\|[\s:|-]+\|$/,vt=/^!\[([^\]]*)\]\(([^)]*)\)$/,yt=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,wt=/^\[( |x|X)\]\s+/,Vt=/^(-{3,}|\*{3,}|_{3,})$/,Xt=/^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*(.*)$/i,Yt=["note","tip","important","warning","caution"];function Rt(l){const o=[],e=(l??"").replace(/\r/g,"").split("```");return e.forEach((t,i)=>{if(i%2===1){const a=t.indexOf(`
2433
+ `),r=(a>-1?t.slice(0,a):t).trim(),n=(a>-1?t.slice(a+1):"").replace(/\n$/,"");o.push(Qt(r,n,i===e.length-1));return}for(const a of t.split(/\n{2,}/))a.trim()&&o.push(...Et(a))}),o}function Qt(l,o,e){const[t="",...i]=l.split(/\s+/),a=t.toLowerCase();if(a==="chart"){const r=e?null:ei(o);return r?{type:"chart",spec:r}:{type:"pending",kind:"chart"}}if(a==="svg")return e||!/<svg[\s>]/i.test(o)?{type:"pending",kind:"svg"}:{type:"svg",source:o.trim()};if(!e&&(a==="csv"||a==="tsv")){const r=Zt(o,a==="tsv"?" ":",");if(r.length>1)return{type:"table",head:r[0],rows:r.slice(1),align:r[0].map(()=>null)}}if(!e&&a==="json")try{return{type:"json",value:JSON.parse(o),source:o}}catch{}if(a==="callout"){const r=(i[0]??"").toLowerCase(),n=Yt.includes(r);return{type:"callout",kind:n?r:"note",title:(n?i.slice(1):i).join(" "),text:o.trim()}}return{type:"code",lang:a||"code",text:o}}function Et(l){const o=l.split(`
2434
+ `).filter(i=>i.trim()),e=o.map(i=>i.trim());if(e.length>1&&e.every(i=>Gt.test(i))){const i=c=>c.replace(/^\||\|$/g,"").split("|").map(b=>b.trim()),a=e.findIndex(c=>xt.test(c)),r=a>-1?i(e[a]).map(c=>/^:-+:$/.test(c)?"center":/^-+:$/.test(c)?"right":/^:-+$/.test(c)?"left":null):[],n=e.filter(c=>!xt.test(c)).map(i),d=n[0]??[];return[{type:"table",head:d,rows:n.slice(1),align:d.map((c,b)=>r[b]??null)}]}if(e.length===1&&Vt.test(e[0]))return[{type:"hr"}];if(e.every(i=>vt.test(i)))return[{type:"img",images:e.map(i=>{const a=i.match(vt);return{alt:a[1],src:a[2]}})}];if(e.every(i=>i.startsWith(">"))){const i=e.map(r=>r.replace(/^>\s?/,"")),a=i[0].match(Xt);return a?[{type:"callout",kind:a[1].toLowerCase(),title:a[2].trim(),text:i.slice(1).join(`
2435
+ `).trim()}]:[{type:"quote",text:i.join(" ")}]}if(yt.test(o[0])){const i=[];for(const a of o){const r=a.match(yt);if(r){const n=r[3].match(wt);i.push({text:n?r[3].replace(wt,""):r[3],depth:Math.min(3,Math.floor(r[1].replace(/\t/g," ").length/2)),checked:n?n[1]!==" ":null})}else i[i.length-1].text+=` ${a.trim()}`}return[{type:"list",ordered:/^\s*\d/.test(o[0]),items:i}]}const t=e[0].match(/^(#{1,4})\s+(.*)$/);if(t){const i=o.slice(1).join(`
2436
+ `);return[{type:"h",level:t[1].length,text:t[2]},...i?Et(i):[]]}return[{type:"p",text:e.join(" ")}]}function Zt(l,o=","){var d;const e=[];let t=[],i="",a=!1;const r=l.replace(/\r/g,"");for(let c=0;c<r.length;c++){const b=r[c];a?b==='"'&&r[c+1]==='"'?(i+='"',c++):b==='"'?a=!1:i+=b:b==='"'&&i===""?a=!0:b===o?(t.push(i.trim()),i=""):b===`
2437
+ `?(t.push(i.trim()),t.some(Boolean)&&e.push(t),t=[],i=""):i+=b}t.push(i.trim()),t.some(Boolean)&&e.push(t);const n=((d=e[0])==null?void 0:d.length)??0;return e.map(c=>c.length<n?[...c,...Array(n-c.length).fill("")]:c)}function ei(l){let o;try{o=JSON.parse(l)}catch{return null}if(!o||typeof o!="object")return null;const e=(Array.isArray(o.series)?o.series:[]).filter(i=>i&&Array.isArray(i.values)).map((i,a)=>({name:String(i.name??`Series ${a+1}`),values:i.values.map(r=>Number(r)||0)}));if(!e.length)return null;const t=Array.isArray(o.labels)?o.labels.map(String):e[0].values.map((i,a)=>String(a+1));return{type:o.type==="line"?"line":"bar",title:String(o.title??""),unit:String(o.unit??""),labels:t,series:e}}const kt=new RegExp([/\*\*([^*]+)\*\*/.source,/~~([^~]+)~~/.source,/`([^`]+)`/.source,/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/.source,/(https?:\/\/[^\s<>()]*[^\s<>().,;:!?'"\]])/.source,new RegExp("(?<![\\w*])\\*(?![\\s*])([^*\\n]+?)\\*(?![\\w*])").source,new RegExp("(?<![\\w_])_(?![\\s_])([^_\\n]+?)_(?![\\w_])").source,/\s?\[(\d+(?:\s*,\s*\d+)*)\]/.source].join("|"),"g");function Bt(l,o=0){const e=[];let t=0,i;kt.lastIndex=0;const a=r=>{if(!r)return;const n=e[e.length-1];(n==null?void 0:n.type)==="text"?n.text+=r:e.push({type:"text",text:r})};for(;i=kt.exec(l);){if(a(l.slice(t,i.index)),i[1]!==void 0)e.push({type:"bold",text:i[1]});else if(i[2]!==void 0)e.push({type:"strike",text:i[2]});else if(i[3]!==void 0)e.push({type:"code",text:i[3]});else if(i[4]!==void 0)e.push({type:"link",text:i[4],href:i[5]});else if(i[6]!==void 0)e.push({type:"link",text:i[6],href:i[6]});else if(i[7]!==void 0)e.push({type:"italic",text:i[7]});else if(i[8]!==void 0)e.push({type:"italic",text:i[8]});else{const n=i[9].split(",").map(d=>Number(d.trim())).filter(d=>d>=1&&d<=o);o?n.forEach(d=>e.push({type:"cite",n:d})):a(i[0])}t=i.index+i[0].length}return a(l.slice(t)),e}function Dt(l){if(((l??"").match(/```/g)??[]).length%2===1)return l;const o=l.lastIndexOf(`
2438
+
2439
+ `),e=o>-1?l.slice(0,o+2):"";let t=o>-1?l.slice(o+2):l;const i=t.split(`
2440
+ `),a=i[i.length-1];a.trimStart().startsWith("|")&&!a.trimEnd().endsWith("|")&&i.pop(),t=i.join(`
2441
+ `),t=t.replace(/!?\[[^\]\n]*(\]\([^)\n]*)?$/,"");for(const r of["**","~~","`"])if((t.split(r).length-1)%2===1){const d=t.lastIndexOf(r);t=t.slice(0,d)+t.slice(d+r.length)}return e+t}function ut(l){const o=new Set;for(const e of(l??"").match(/\[(\d+(?:\s*,\s*\d+)*)\]/g)??[])e.replace(/[[\]]/g,"").split(",").forEach(t=>o.add(Number(t.trim())));return o}function ti(l){return[["",...l.series.map(o=>o.name)],...l.labels.map((o,e)=>[o,...l.series.map(t=>t.values[e]===void 0?"":`${t.values[e]}${l.unit}`)])]}const $t=l=>l.map(o=>o.join(" · ")).join(`
2442
+ `),ii={note:"Note",tip:"Tip",important:"Important",warning:"Warning",caution:"Caution"};function Ft(l,o){if(o==="rich")return l;const e=o==="plain";return l.map(t=>{switch(t.type){case"chart":{const[i,...a]=ti(t.spec);return e?{type:"raw",text:[t.spec.title,$t([i,...a])].filter(Boolean).join(`
2443
+ `)}:{type:"table",head:t.spec.title?[t.spec.title,...i.slice(1)]:i,rows:a,align:i.map(()=>null)}}case"pending":return t.kind==="svg"&&!e?t:{type:"raw",text:""};case"callout":return{type:"quote",text:`**${t.title||ii[t.kind]}** ${t.text}`.trim()};case"img":return{type:"p",text:t.images.map(i=>`Image: ${i.alt||"untitled"}`).join(" · ")};case"table":return e?{type:"raw",text:$t([t.head,...t.rows])}:t;case"json":return e?{type:"code",lang:"json",text:t.source}:t;case"svg":return e?{type:"code",lang:"svg",text:t.source}:t;default:return t}})}function gt(l){const o=l??"",e=o.search(/FOLLOWUPS:/i);if(e<0)return{text:o.trim(),followups:[]};const i=o.slice(e).replace(/^FOLLOWUPS:/i,"").split(/\||\n/).map(a=>a.replace(/^\s*(?:[-*↳→]|\d+[.)])\s*/,"").trim()).filter(Boolean).slice(0,3);return{text:o.slice(0,e).trim(),followups:i}}function si(l){return(l??"").replace(/```(\w*)[\s\S]*?(```|$)/g,(o,e)=>e==="chart"?"[Chart] ":e==="svg"?"[Drawing] ":"[Code] ").replace(/!\[([^\]]*)\]\([^)]*\)/g,"[Image: $1]").replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,"$1").replace(/\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]/gi,"").replace(/[*#>`~]/g,"").replace(/\|/g," ").replace(/\s?\[\d+(?:\s*,\s*\d+)*\]/g,"").replace(/\s+/g," ").trim()}function ai(l,o=48){const e=si(l);if(e.length<=o)return e;const t=e.slice(0,o),i=t.lastIndexOf(" ");return(i>o/2?t.slice(0,i):t).trim()}function ri(l){return String(l??"").split(`
2444
+ `)[0].trim().replace(/^["'“”‘’]+|["'“”‘’]+$/g,"").replace(/^title:\s*/i,"").replace(/[.!?:;,]+$/,"").trim().slice(0,80)}function Ct(l,o=!1){return/^https?:\/\//i.test(l)?!0:o&&/^(blob:|data:image\/)/i.test(l)}const ni=2e5,oi=new Set(["script","foreignobject","iframe","object","embed","image","audio","video","animate","set","animatemotion","animatetransform","handler","listener"]);function Ut(l){if(!l||l.length>ni||typeof DOMParser>"u")return null;const o=new DOMParser().parseFromString(l,"image/svg+xml"),e=o.documentElement;if(!e||e.nodeName.toLowerCase()!=="svg"||o.querySelector("parsererror"))return null;const t=a=>{for(const r of Array.from(a.children)){const n=r.nodeName.toLowerCase();if(oi.has(n))r.remove();else if(n==="a"){const d=Array.from(r.childNodes);r.replaceWith(...d),d.forEach(c=>c instanceof Element&&t(c))}else t(r)}for(const r of Array.from(a.attributes)){const n=r.name.toLowerCase(),d=r.value.trim().toLowerCase(),c=(n==="href"||n.endsWith(":href"))&&!d.startsWith("#"),b=d.includes("javascript:")||/url\(\s*['"]?(?!#)/.test(d);(n.startsWith("on")||c||b)&&a.removeAttribute(r.name)}};t(e);for(const a of Array.from(e.querySelectorAll("style")))a.textContent=(a.textContent??"").replace(/@import[^;]*;?/gi,"").replace(/url\(\s*['"]?(?!#)[^)]*\)/gi,"none");e.setAttribute("xmlns","http://www.w3.org/2000/svg");const i=new XMLSerializer().serializeToString(e);return`data:image/svg+xml;charset=utf-8,${encodeURIComponent(i)}`}var Pt=Object.defineProperty,li=Object.getOwnPropertyDescriptor,ci=(l,o,e)=>o in l?Pt(l,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[o]=e,m=(l,o,e,t)=>{for(var i=t>1?void 0:t?li(o,e):o,a=l.length-1,r;a>=0;a--)(r=l[a])&&(i=(t?r(o,e,i):r(i))||i);return t&&i&&Pt(o,e,i),i},di=(l,o,e)=>ci(l,o+"",e);const St=["embed","mode","format","renderers","beforeSend","afterParse","glow","position","sidebar","showTitle","assistantName","logoUrl","heading","description","eyebrow","prompts","bubbleText","greetingBubble","unreadBadge","allowUpload","allowExport","allowRaw","allowCopy","allowRegenerate","allowBookmark","allowDelete","allowRename","allowFeedback","showTime","showComposer","footnote","brandingText","brandingUrl","branding","followups","showFollowups","showSources","showNewChat","showBookmarked","allowSearch","autoTitle","model","params","systemMessage","retrieval","metadata","messages","theme","radius"],mt={fromAttribute:l=>{if(l)try{return JSON.parse(l)}catch{console.warn("[singlebase-chat] an attribute holds invalid JSON; ignoring it");return}},toAttribute:l=>JSON.stringify(l??null)},S={fromAttribute:l=>l===null?!0:l!=="false",toAttribute:l=>l?null:"false"},hi={fromAttribute:l=>l===null?"auto":l===""||l==="true"?"open":l==="false"?"closed":["auto","open","closed","none"].includes(l)?l:"auto",toAttribute:l=>l==="auto"?null:l},pi=272,ui=820,gi=940,Tt=5,Ot=512*1024,mi=/\.(md|markdown|txt|csv|tsv|json|html?|ya?ml|xml|log)$/i,bi=5e3,fi=200,It=2e3,xi={note:"calloutNote",tip:"calloutTip",important:"calloutImportant",warning:"calloutWarning",caution:"calloutCaution"},vi=2600,_=["var(--c-ink)","oklch(0.58 0.13 255)","oklch(0.63 0.1 175)","oklch(0.74 0.12 70)"],Mt={chat:"Be helpful and concise. Use Markdown when it helps: headings, lists, **bold**, code blocks and tables.",rag:"Answer ONLY from the sources provided with each message, numbered in the order given. Put a citation like [1] right after each claim it supports. If the sources don't cover the question, say so plainly."},yi={raw:"Reply in plain text. Don't use Markdown or any other markup.",plain:"Format with light Markdown only: short paragraphs, lists, **bold**, *italics*, `inline code`, code blocks and links. Don't use tables, charts, callouts, images or other special blocks.",advanced:`You can use Markdown: headings, lists, task lists, **bold**, *italics*, links, code blocks and pipe tables. For data, use a fenced "csv" block or a fenced "json" block. For a diagram or illustration, write a self-contained fenced "svg" block with a viewBox, and no scripts, links or external images. Don't use charts, callouts or images.`,rich:'When the answer is about data, lead with one sentence stating the key finding, with key numbers in **bold**, then show the data visually. You can use Markdown: headings, lists, task lists, **bold**, *italics*, links, code blocks and pipe tables. For data, use a fenced "csv" block or a fenced "json" block. For a diagram or illustration, write a self-contained fenced "svg" block with a viewBox, and no scripts, links or external images. For trends and comparisons, use a fenced "chart" block containing only JSON: {"type":"bar"|"line","title":string,"unit":string,"labels":[string],"series":[{"name":string,"values":[number]}]}. For notes and warnings, use callouts: a quote starting with [!NOTE], [!TIP], [!IMPORTANT], [!WARNING] or [!CAUTION]. Images use ![alt](https://…).'},wi="After the answer, on a final line write FOLLOWUPS: followed by three short follow-up questions the user might ask next, separated by |.",zt={chat:[["Write","Draft a short welcome email for new users"],["Explain","Explain how refresh tokens work, simply"],["Code","Write a JavaScript debounce function"],["Plan","Outline a one-week plan to learn TypeScript"]],rag:[["Overview","What topics do these sources cover?"],["Summarize","Summarize the most important points"],["Find","Where is the refund policy described?"],["Explain","Explain the setup steps in plain language"]]},I=(l,o="")=>s.html`<svg class="i ${o}" viewBox="0 0 16 16" aria-hidden="true">${l}</svg>`,y={sidebar:()=>I(s.svg`<rect x="2" y="2.5" width="12" height="11" rx="1.5"></rect><path d="M6 2.5v11"></path>`),plus:()=>I(s.svg`<path d="M8 3v10M3 8h10"></path>`),bookmark:(l=!1)=>I(s.svg`<path d="M4.5 2.5h7v11L8 11l-3.5 2.5z"></path>`,l?"filled":""),download:()=>I(s.svg`<path d="M8 2.5v8M4.5 7.5L8 11l3.5-3.5M2.5 13.5h11"></path>`),trash:()=>I(s.svg`<path d="M2.5 4.5h11M6.5 4.5v-2h3v2M4 4.5l.7 9h6.6l.7-9"></path>`),pencil:()=>I(s.svg`<path d="M10.5 2.5l3 3L6 13H3v-3z"></path>`),copy:()=>I(s.svg`<rect x="5.5" y="5.5" width="8" height="8" rx="1.5"></rect><path d="M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2"></path>`),raw:()=>I(s.svg`<path d="M5.5 4.5L2 8l3.5 3.5M10.5 4.5L14 8l-3.5 3.5"></path>`),refresh:()=>I(s.svg`<path d="M13.5 8A5.5 5.5 0 1 1 11.9 4.1M13.5 2v3.5H10"></path>`),thumb:(l=!1)=>s.html`<svg
2445
+ class="i"
2446
+ viewBox="0 0 16 16"
2447
+ aria-hidden="true"
2448
+ style=${l?"transform:rotate(180deg)":""}
2449
+ >
2450
+ <path
2451
+ d="M5 7v6.5H2.5V7zM5 7l2.5-4.5a1.3 1.3 0 0 1 1.9 1.4L9 6.5h3.6a1 1 0 0 1 1 1.2l-1 4.8a1 1 0 0 1-1 .8H5"
2452
+ ></path>
2453
+ </svg>`,expand:()=>I(s.svg`<path d="M9.5 2.5h4v4M13.5 2.5L9 7M6.5 13.5h-4v-4M2.5 13.5L7 9"></path>`),restore:()=>I(s.svg`<path d="M13.5 6.5h-4v-4M9.5 6.5l4-4M2.5 9.5h4v4M6.5 9.5l-4 4"></path>`),minimize:()=>I(s.svg`<path d="M4 8h8"></path>`),close:()=>I(s.svg`<path d="M4 4l8 8M12 4l-8 8"></path>`),clip:()=>I(s.svg`<path d="M13 7.5l-5.3 5.3a3 3 0 0 1-4.3-4.3L9 2.9a2 2 0 0 1 2.9 2.9L6.4 11.3a1 1 0 0 1-1.4-1.4L10 5"></path>`),up:()=>I(s.svg`<path d="M8 13V3M3.5 7.5L8 3l4.5 4.5"></path>`),stop:()=>I(s.svg`<rect x="4.5" y="4.5" width="7" height="7" rx="1"></rect>`),chat:()=>s.html`<svg
2454
+ width="22"
2455
+ height="22"
2456
+ viewBox="0 0 22 22"
2457
+ aria-hidden="true"
2458
+ style="fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round"
2459
+ >
2460
+ <path
2461
+ d="M4 5.5A2.5 2.5 0 0 1 6.5 3h9A2.5 2.5 0 0 1 18 5.5v7a2.5 2.5 0 0 1-2.5 2.5H9l-4 3.5V15H6.5"
2462
+ ></path>
2463
+ </svg>`,chevronDown:()=>s.html`<svg
2464
+ width="20"
2465
+ height="20"
2466
+ viewBox="0 0 20 20"
2467
+ aria-hidden="true"
2468
+ style="fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round"
2469
+ >
2470
+ <path d="M5 8l5 5 5-5"></path>
2471
+ </svg>`};let ki=0;const pt=()=>`m${Date.now().toString(36)}${(ki++).toString(36)}`;function _t(l){var e;const o=l;return(o==null?void 0:o.message)==="NOT_FOUND"||(o==null?void 0:o.code)==="NOT_FOUND"||((e=o==null?void 0:o.details)==null?void 0:e.status)===404}function $i(l){const o=l;return(o==null?void 0:o.code)||(o==null?void 0:o.message)||"UNKNOWN"}const Ci=()=>typeof matchMedia<"u"&&matchMedia("(prefers-reduced-motion: reduce)").matches,ht=(l,o)=>(Number.isInteger(l)?l.toLocaleString("en-US"):l.toFixed(1))+o,Lt=l=>{const o=l.lastIndexOf(".");return o>0?l.slice(o+1,o+5).toUpperCase():"FILE"};function L(l,o){const e=l??{},t=e.metadata&&typeof e.metadata=="object"?e.metadata:{},i=(...n)=>n.find(d=>typeof d=="string"&&d.trim()),a=i(e.content,e.text,e.page_content,e.body,e.snippet,e.chunk,t.content)??JSON.stringify(e,null,2),r=[e.score,e.relevance,e._score,t.score].find(n=>typeof n=="number");return{n:o,title:i(e.title,e.name,e.filename,t.title,t.name)??`Source ${o}`,path:i(e.path,e.url,e.key,e.source,t.path,t.url)??"",collection:i(e.collection,e.namespace,e.dbname,t.collection)??"",updated:i(e.updated,e._modified_at,t.updated)??"",text:a,score:r===void 0?null:Math.max(0,Math.min(1,r))}}function Si(l){const o=[],e=[];for(const t of l)if(/\.csv$/i.test(t.name))o.push({type:"csv",data:t.content});else if(/\.json$/i.test(t.name))try{o.push({type:"json",data:JSON.parse(t.content)})}catch{e.push({title:t.name,content:t.content})}else e.push({title:t.name,content:t.content});return e.length&&o.push({type:"docs",payload:{documents:e}}),o}function Ti(l){const o=l?Date.parse(l):NaN;if(Number.isNaN(o))return"older";const e=new Date;e.setHours(0,0,0,0);const t=864e5;return o>=e.getTime()?"today":o>=e.getTime()-t?"yesterday":o>=e.getTime()-7*t?"week":"older"}var j,N,A,R,E,B,D,F,U,P,K,W,J,H,q,G,V,X,Y,Q,Z,ee,te,ie,se,ae,re,ne,oe,le,ce,de,he,pe,ue,ge,me,be,fe,xe,ve,ye,we,ke,$e,Ce,Se,Te,Oe,Ie,Me,ze,_e,Le,je,Ne,Ae,Re,Ee,Be,De,Fe,Ue,Pe,Ke,We,Je,He,qe,Ge,Ve,Xe,Ye,Qe,Ze,et,tt,it,st,at,rt,nt,ot,lt,ct,dt,jt;exports.SinglebaseChat=(jt=class extends s.LitElement{constructor(){super(...arguments);p(this,j,null);p(this,N,{});p(this,A);p(this,R);p(this,E,"chat");p(this,B,"advanced");p(this,D,{});p(this,F,null);p(this,U,null);p(this,P,"subtle");p(this,K,!0);p(this,W,!0);p(this,J,!0);p(this,H,!0);p(this,q,!0);p(this,G,!0);p(this,V,!0);p(this,X,"");p(this,Y,{});p(this,Q,"");p(this,Z,[]);p(this,ee,{});p(this,te,"page");p(this,ie,"right");p(this,se,"auto");p(this,ae,!0);p(this,re,"");p(this,ne,"Assistant");p(this,oe,"");p(this,le,"");p(this,ce,"");p(this,de);p(this,he,"");p(this,pe,"");p(this,ue,!1);p(this,ge,!1);p(this,me,!0);p(this,be,!0);p(this,fe,!0);p(this,xe,!0);p(this,ve,!0);p(this,ye,!0);p(this,we,!0);p(this,ke,!0);p(this,$e,!0);p(this,Ce,!0);p(this,Se);p(this,Te,!1);p(this,Oe,!0);p(this,Ie,"");p(this,Me,"");p(this,ze,[]);p(this,_e,"idle");p(this,Le,null);p(this,je,"");p(this,Ne,!1);p(this,Ae,[]);p(this,Re,!1);p(this,Ee,"");p(this,Be,!1);p(this,De,"");p(this,Fe,[]);p(this,Ue,"");p(this,Pe,null);p(this,Ke,0);p(this,We,null);p(this,Je,!1);p(this,He,"");p(this,qe,"");p(this,Ge,!1);p(this,Ve,"");p(this,Xe,null);p(this,Ye,"");p(this,Qe,new Set);p(this,Ze,new Set);p(this,et,!1);p(this,tt,new Map);p(this,it,"");p(this,st,!1);p(this,at,!1);p(this,rt,!1);p(this,nt,!1);p(this,ot,!1);p(this,lt,!1);p(this,ct,!1);p(this,dt,!1);O(this,"run",0);O(this,"abort",null);O(this,"revealTimer");O(this,"timers",new Set);O(this,"toastTimer");O(this,"stick",!0);O(this,"renamed",new Set);O(this,"observer",null);O(this,"observed",null);O(this,"media",null);O(this,"focusNext","");O(this,"bubbleScheduled",!1);O(this,"pendingChatId","");O(this,"onNetwork",()=>{this.offline=navigator.onLine===!1});O(this,"onMedia",()=>{var e;this.mobile=!!((e=this.media)!=null&&e.matches)})}get client(){return h(this,j)}set client(e){u(this,j,e)}get messages(){return h(this,N)}set messages(e){u(this,N,e)}get theme(){return h(this,A)}set theme(e){u(this,A,e)}get radius(){return h(this,R)}set radius(e){u(this,R,e)}get mode(){return h(this,E)}set mode(e){u(this,E,e)}get format(){return h(this,B)}set format(e){u(this,B,e)}get renderers(){return h(this,D)}set renderers(e){u(this,D,e)}get beforeSend(){return h(this,F)}set beforeSend(e){u(this,F,e)}get afterParse(){return h(this,U)}set afterParse(e){u(this,U,e)}get glow(){return h(this,P)}set glow(e){u(this,P,e)}get followups(){return h(this,K)}set followups(e){u(this,K,e)}get showSources(){return h(this,W)}set showSources(e){u(this,W,e)}get showNewChat(){return h(this,J)}set showNewChat(e){u(this,J,e)}get showBookmarked(){return h(this,H)}set showBookmarked(e){u(this,H,e)}get showFollowups(){return h(this,q)}set showFollowups(e){u(this,q,e)}get allowSearch(){return h(this,G)}set allowSearch(e){u(this,G,e)}get autoTitle(){return h(this,V)}set autoTitle(e){u(this,V,e)}get model(){return h(this,X)}set model(e){u(this,X,e)}get params(){return h(this,Y)}set params(e){u(this,Y,e)}get systemMessage(){return h(this,Q)}set systemMessage(e){u(this,Q,e)}get retrieval(){return h(this,Z)}set retrieval(e){u(this,Z,e)}get metadata(){return h(this,ee)}set metadata(e){u(this,ee,e)}get embed(){return h(this,te)}set embed(e){u(this,te,e)}get position(){return h(this,ie)}set position(e){u(this,ie,e)}get sidebar(){return h(this,se)}set sidebar(e){u(this,se,e)}get showTitle(){return h(this,ae)}set showTitle(e){u(this,ae,e)}get chatIdAttr(){return h(this,re)}set chatIdAttr(e){u(this,re,e)}get assistantName(){return h(this,ne)}set assistantName(e){u(this,ne,e)}get logoUrl(){return h(this,oe)}set logoUrl(e){u(this,oe,e)}get heading(){return h(this,le)}set heading(e){u(this,le,e)}get description(){return h(this,ce)}set description(e){u(this,ce,e)}get eyebrow(){return h(this,de)}set eyebrow(e){u(this,de,e)}get prompts(){return h(this,he)}set prompts(e){u(this,he,e)}get bubbleText(){return h(this,pe)}set bubbleText(e){u(this,pe,e)}get greetingBubble(){return h(this,ue)}set greetingBubble(e){u(this,ue,e)}get unreadBadge(){return h(this,ge)}set unreadBadge(e){u(this,ge,e)}get allowUpload(){return h(this,me)}set allowUpload(e){u(this,me,e)}get allowExport(){return h(this,be)}set allowExport(e){u(this,be,e)}get allowCopy(){return h(this,fe)}set allowCopy(e){u(this,fe,e)}get allowRegenerate(){return h(this,xe)}set allowRegenerate(e){u(this,xe,e)}get allowBookmark(){return h(this,ve)}set allowBookmark(e){u(this,ve,e)}get allowDelete(){return h(this,ye)}set allowDelete(e){u(this,ye,e)}get allowRename(){return h(this,we)}set allowRename(e){u(this,we,e)}get allowFeedback(){return h(this,ke)}set allowFeedback(e){u(this,ke,e)}get showComposer(){return h(this,$e)}set showComposer(e){u(this,$e,e)}get showTime(){return h(this,Ce)}set showTime(e){u(this,Ce,e)}get footnote(){return h(this,Se)}set footnote(e){u(this,Se,e)}get allowRaw(){return h(this,Te)}set allowRaw(e){u(this,Te,e)}get branding(){return h(this,Oe)}set branding(e){u(this,Oe,e)}get brandingText(){return h(this,Ie)}set brandingText(e){u(this,Ie,e)}get brandingUrl(){return h(this,Me)}set brandingUrl(e){u(this,Me,e)}get chatList(){return h(this,ze)}set chatList(e){u(this,ze,e)}get listState(){return h(this,_e)}set listState(e){u(this,_e,e)}get activeId(){return h(this,Le)}set activeId(e){u(this,Le,e)}get chatTitle(){return h(this,je)}set chatTitle(e){u(this,je,e)}get bookmarked(){return h(this,Ne)}set bookmarked(e){u(this,Ne,e)}get msgs(){return h(this,Ae)}set msgs(e){u(this,Ae,e)}get loadingThread(){return h(this,Re)}set loadingThread(e){u(this,Re,e)}get threadError(){return h(this,Ee)}set threadError(e){u(this,Ee,e)}get busy(){return h(this,Be)}set busy(e){u(this,Be,e)}get draft(){return h(this,De)}set draft(e){u(this,De,e)}get files(){return h(this,Fe)}set files(e){u(this,Fe,e)}get search(){return h(this,Ue)}set search(e){u(this,Ue,e)}get sidebarOpen(){return h(this,Pe)}set sidebarOpen(e){u(this,Pe,e)}get width(){return h(this,Ke)}set width(e){u(this,Ke,e)}get panel(){return h(this,We)}set panel(e){u(this,We,e)}get menuOpen(){return h(this,Je)}set menuOpen(e){u(this,Je,e)}get editingKey(){return h(this,He)}set editingKey(e){u(this,He,e)}get editDraft(){return h(this,qe)}set editDraft(e){u(this,qe,e)}get editingTitle(){return h(this,Ge)}set editingTitle(e){u(this,Ge,e)}get renamingId(){return h(this,Ve)}set renamingId(e){u(this,Ve,e)}get toast(){return h(this,Xe)}set toast(e){u(this,Xe,e)}get copiedKey(){return h(this,Ye)}set copiedKey(e){u(this,Ye,e)}get retrievalOpen(){return h(this,Qe)}set retrievalOpen(e){u(this,Qe,e)}get rawKeys(){return h(this,Ze)}set rawKeys(e){u(this,Ze,e)}get hasSidebarContent(){return h(this,et)}set hasSidebarContent(e){u(this,et,e)}get sorts(){return h(this,tt)}set sorts(e){u(this,tt,e)}get arrivedKey(){return h(this,it)}set arrivedKey(e){u(this,it,e)}get dragging(){return h(this,st)}set dragging(e){u(this,st,e)}get showJump(){return h(this,at)}set showJump(e){u(this,at,e)}get offline(){return h(this,rt)}set offline(e){u(this,rt,e)}get isOpen(){return h(this,nt)}set isOpen(e){u(this,nt,e)}get expanded(){return h(this,ot)}set expanded(e){u(this,ot,e)}get bubble(){return h(this,lt)}set bubble(e){u(this,lt,e)}get seen(){return h(this,ct)}set seen(e){u(this,ct,e)}get mobile(){return h(this,dt)}set mobile(e){u(this,dt,e)}get msg(){return At(this.messages)}get resolvedClient(){return this.client??Ht.getDefaultClient()??null}get chatId(){return this.activeId}get thread(){return this.msgs}get formatLevel(){return["raw","plain","advanced","rich"].includes(this.format)?this.format:"advanced"}get chats(){return this.chatList}set config(e){if(!e)return;const t=this;"client"in e&&(this.client=e.client??null);for(const i of St)i in e&&(t[i]=e[i]);e.chatId&&e.chatId!==this.activeId&&(this.hasUpdated?this.openChat(e.chatId):this.chatIdAttr=e.chatId)}configure(e){return this.config=e,this}get config(){const e=this;return{client:this.client,chatId:this.activeId??"",...Object.fromEntries(St.map(t=>[t,e[t]]))}}connectedCallback(){var e,t;super.connectedCallback(),this.offline=typeof navigator<"u"&&navigator.onLine===!1,window.addEventListener("online",this.onNetwork),window.addEventListener("offline",this.onNetwork),this.media=typeof matchMedia<"u"?matchMedia("(max-width: 559px)"):null,this.mobile=!!((e=this.media)!=null&&e.matches),(t=this.media)==null||t.addEventListener("change",this.onMedia)}disconnectedCallback(){var e,t;super.disconnectedCallback(),window.removeEventListener("online",this.onNetwork),window.removeEventListener("offline",this.onNetwork),(e=this.media)==null||e.removeEventListener("change",this.onMedia),(t=this.observer)==null||t.disconnect(),this.observer=null,this.observed=null,this.flushToast(),this.halt(),this.timers.forEach(clearTimeout),this.timers.clear()}willUpdate(e){if(e.has("retrieval")&&!Array.isArray(this.retrieval)){const t=this.retrieval;this.retrieval=t&&typeof t=="object"?[t]:[]}e.has("params")&&(!this.params||typeof this.params!="object")&&(this.params={}),e.has("metadata")&&(!this.metadata||typeof this.metadata!="object")&&(this.metadata={}),e.has("sidebar")&&(this.sidebar==="open"?this.sidebarOpen=!0:this.sidebar==="closed"||this.sidebar==="none"?this.sidebarOpen=!1:this.width&&(this.sidebarOpen=this.docked)),this.embed==="launcher"&&this.greetingBubble&&!this.bubbleScheduled&&(this.bubbleScheduled=!0,this.later(()=>{!this.isOpen&&!this.seen&&(this.bubble=!0)},1200))}firstUpdated(){this.chatIdAttr&&this.openChat(this.chatIdAttr)}updated(){var t;const e=this.renderRoot.querySelector(".root");if(e!==this.observed&&((t=this.observer)==null||t.disconnect(),this.observed=e,e&&typeof ResizeObserver<"u"&&(this.observer??(this.observer=new ResizeObserver(([i])=>{const a=Math.round(i.contentRect.width);a!==this.width&&(this.width=a,this.sidebarOpen===null&&(this.sidebarOpen=this.sidebar==="auto"&&this.docked))})),this.observer.observe(e))),this.sidebarOpen&&this.listState==="idle"&&this.resolvedClient&&this.loadChats(),this.pendingChatId&&this.resolvedClient&&this.openChat(this.pendingChatId),this.focusNext){const i=this.renderRoot.querySelector(this.focusNext);this.focusNext="",i&&(i.focus(),"select"in i&&i.tagName==="INPUT"&&i.select())}}later(e,t){const i=setTimeout(()=>{this.timers.delete(i),e()},t);this.timers.add(i)}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}get docked(){return this.embed==="page"&&this.width>=ui}get panelDocked(){const e=this.docked&&this.sidebarOpen?pi:0;return this.width-e>=gi}newChat(){this.halt(),this.pendingChatId="",this.loadingThread=!1,this.activeId=null,this.chatTitle="",this.bookmarked=!1,this.msgs=[],this.threadError="",this.resetViewState(),this.focusNext="textarea.input"}async openChat(e){const t=this.resolvedClient;if(!e)return;this.halt();const i=this.chatList.find(r=>r._id===e);if(this.activeId=e,this.chatTitle=(i==null?void 0:i.title)??"",this.bookmarked=!!(i!=null&&i.bookmarked),this.msgs=[],this.threadError="",this.resetViewState(),!t){this.pendingChatId=e,this.loadingThread=!0;return}const a=++this.run;this.pendingChatId="",this.loadingThread=!0;try{const r=await t.llm.call("get_chat",{_id:e});if(a!==this.run)return;this.chatTitle=(r==null?void 0:r.title)??"",this.bookmarked=!!(r!=null&&r.bookmarked),this.msgs=((r==null?void 0:r.messages)??[]).filter(n=>n&&(n.role==="user"||n.role==="assistant")).map(n=>this.fromServer(n)),this.upsertChat({...i,...r,_id:e}),this.stick=!0,this.scrollToBottom()}catch(r){if(a!==this.run)return;_t(r)?(this.chatList=this.chatList.filter(n=>n._id!==e),this.newChat(),this.showToast(this.msg.errNotFound)):this.threadError=this.msg.errLoad}finally{a===this.run&&(this.loadingThread=!1)}}async send(e){const t=(typeof e=="string"?e:this.draft).trim();if(!t||this.busy)return;const i=this.files;this.draft="",this.files=[];const a=this.renderRoot.querySelector("textarea.input");a&&(a.style.height="auto"),await this.runTurn(this.userMessage(t,i))}stop(){if(!this.busy)return;const e=this.msgs[this.msgs.length-1];this.halt(),(e==null?void 0:e.role)==="assistant"&&(e.phase==="pending"||e.phase==="streaming")&&(e.phase="done",e.stopped=!0,e.followups=[],this.msgs=[...this.msgs])}exportChat(e="md"){var M;if(!this.msgs.length)return;this.menuOpen=!1;const t=this.chatTitle||this.msg.untitled,i=x=>x.role==="user"?this.msg.you:this.assistantName,a=x=>new Date(x||Date.now()).toLocaleString(),r=x=>x.sources.map(($,w)=>{const z=L($,w+1);return`[${z.n}] ${z.title}${z.path?` — ${z.path}`:""}`}),n=x=>(x.attachments??[]).map($=>$.name);let d,c="text/markdown",b="md";if(e==="json"?(d=JSON.stringify({exportedAt:new Date().toISOString(),id:this.activeId,title:t,mode:this.mode,bookmarked:this.bookmarked,messages:this.msgs.map(x=>({role:x.role,text:x.content,at:new Date(x.at||Date.now()).toISOString(),bookmarked:x.bookmarked,attachments:n(x),sources:r(x)}))},null,2),c="application/json",b="json"):e==="txt"?(d=`${t}
2472
+ ${"=".repeat(t.length)}
2473
+
2474
+ `+this.msgs.map(x=>[`${i(x)} · ${a(x.at)}`,n(x).length?`Attachments: ${n(x).join(", ")}`:"",x.content,r(x).length?`Sources:
2475
+ ${r(x).join(`
2476
+ `)}`:""].filter(Boolean).join(`
2477
+ `)).join(`
2478
+
2479
+ `),c="text/plain",b="txt"):d=`# ${t}
2480
+
2481
+ `+this.msgs.map(x=>[`### ${i(x)} · ${a(x.at)}`,n(x).length?`Attachments: ${n(x).join(", ")}`:"",x.content,r(x).length?`**Sources**
2482
+
2483
+ ${r(x).map($=>`- ${$}`).join(`
2484
+ `)}`:""].filter(Boolean).join(`
2485
+
2486
+ `)).join(`
2487
+
2488
+ ---
2489
+
2490
+ `)+`
2491
+ `,this.emit("singlebase-chat-export",{chatId:this.activeId,format:e}),e==="copy"){(M=navigator.clipboard)==null||M.writeText(d).catch(()=>{}),this.showToast(this.msg.copiedMarkdown);return}const k=`${t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"chat"}-${new Date().toISOString().slice(0,10)}.${b}`,C=URL.createObjectURL(new Blob([d],{type:c})),v=document.createElement("a");v.href=C,v.download=k,document.body.appendChild(v),v.click(),v.remove(),setTimeout(()=>URL.revokeObjectURL(C),2e3),this.showToast(T.fill(this.msg.exported,{name:k}))}expand(){this.expanded=!0,this.emit("singlebase-chat-expand",{expanded:!0})}collapse(){this.expanded=!1,this.emit("singlebase-chat-expand",{expanded:!1})}open(){this.isOpen=!0,this.seen=!0,this.bubble=!1,this.focusNext="textarea.input",this.emit("singlebase-chat-open",{})}close(){this.isOpen=!1,this.expanded=!1,this.emit("singlebase-chat-close",{})}userMessage(e,t=[]){return{key:pt(),id:null,role:"user",content:e,at:Date.now(),bookmarked:!1,sources:[],followups:[],phase:"done",attachments:t}}systemPrompt(){return[this.systemMessage,Mt[this.mode]??Mt.chat,yi[this.formatLevel],this.followups?wi:""].filter(Boolean).join(`
2492
+
2493
+ `)}payloadFor(e){const t={message:e.content,format:"markdown"};this.activeId?t._id=this.activeId:(t.title=ai(e.content),t.system_message=this.systemPrompt()),this.model&&(t.model=this.model),Object.keys(this.params??{}).length&&(t.params=this.params);const i=(e.attachments??[]).map(r=>r.name);(Object.keys(this.metadata??{}).length||i.length)&&(t.metadata={...this.metadata,...i.length?{attachments:i}:{}});const a=[...this.retrieval??[],...Si(e.attachments??[])];return a.length&&(t.retrieval=a),t}async runTurn(e){const t={key:pt(),id:null,role:"assistant",content:"",at:Date.now(),bookmarked:!1,sources:[],followups:[],phase:"pending"};this.msgs=[...this.msgs,e,t],this.busy=!0,this.panel=null,this.stick=!0,this.scrollToBottom(),this.emit("singlebase-chat-send",{chatId:this.activeId,text:e.content});const i=this.resolvedClient;if(!i){this.failTurn(t,this.msg.errNoClient,"NO_CLIENT"),this.busy=!1;return}const a=++this.run,r=new AbortController;this.abort=r;const n=!this.activeId;let d=this.payloadFor(e);if(this.beforeSend){let c;try{c=await this.beforeSend(d,{chatId:this.activeId,isNew:n,message:e})}catch(f){c=f}if(a!==this.run)return;if(c===!1){this.msgs=this.msgs.filter(f=>f!==e&&f!==t),this.draft=e.content,this.busy=!1,this.abort=null;return}if(!(!!c&&typeof c=="object"&&typeof c.message=="string")||!c.message.trim()){console.error("[singlebase-chat] beforeSend must return the request object (with a message) or false to cancel; the message was not sent.",c),this.failTurn(t,this.msg.errGeneric,"BEFORE_SEND_INVALID"),this.busy=!1,this.abort=null;return}d=c}try{const c=await i.llm.call("chat",d,{signal:r.signal}),b=(c==null?void 0:c._id)||(c==null?void 0:c.chat_id)||this.activeId;if(n&&b&&this.upsertChat({_id:b,title:(c==null?void 0:c.title)||d.title,bookmarked:!!(c!=null&&c.bookmarked),_modified_at:new Date().toISOString()}),a!==this.run)return;b&&(this.activeId=b),n?(this.chatTitle=(c==null?void 0:c.title)||d.title,this.bookmarked=!!(c!=null&&c.bookmarked)):b&&this.touchChat(b);const f=(c==null?void 0:c.message)??{},k=typeof f.content=="string"?f.content:(c==null?void 0:c.json)!==void 0?JSON.stringify(c.json,null,2):"",{text:C,followups:v}=gt(k);e.id=f.reply_to??null,Object.assign(t,{id:f._id??null,content:C,sources:Array.isArray(f.sources)?f.sources:[],followups:v,execTime:typeof f.exec_time=="number"?f.exec_time:void 0,model:f.model,at:Date.now()}),this.emit("singlebase-chat-response",{chatId:b,message:t}),await this.reveal(t,a),n&&b&&this.autoTitle&&this.retitle(b,e.content,t.content)}catch(c){if(a!==this.run)return;const b=_t(c);b&&(this.chatList=this.chatList.filter(f=>f._id!==this.activeId),this.activeId=null),this.failTurn(t,b?this.msg.errNotFound:this.msg.errGeneric,$i(c))}finally{a===this.run&&(this.busy=!1,this.abort=null,this.stick&&this.scrollToBottom())}}failTurn(e,t,i){e.phase="error",e.error=t,this.msgs=[...this.msgs],this.emit("singlebase-chat-error",{chatId:this.activeId,code:i,message:t})}reveal(e,t){const i=e.content.length,a=()=>{e.phase="done",this.msgs=[...this.msgs],this.arrivedKey=e.key,this.later(()=>{this.arrivedKey===e.key&&(this.arrivedKey="")},vi),this.stick?this.scrollToBottom():this.showJump=!0};if(!i||Ci())return a(),Promise.resolve();const r=e.content,n=Math.max(4,Math.ceil(i/90));let d=0;return e.phase="streaming",e.content="",new Promise(c=>{this.revealTimer=setInterval(()=>{if(t!==this.run){clearInterval(this.revealTimer),c();return}if(d=Math.min(i,d+n),e.content=r.slice(0,d),d>=i){clearInterval(this.revealTimer),a(),c();return}this.msgs=[...this.msgs],this.stick&&this.scrollToBottom()},16)})}halt(){var e;this.run++,(e=this.abort)==null||e.abort(),this.abort=null,clearInterval(this.revealTimer),this.busy=!1}async retitle(e,t,i){const a=this.resolvedClient;if(!(!a||this.renamed.has(e)))try{const r=await a.llm.call("generate",{user_input:`user: ${t}
2494
+ assistant: ${i.slice(0,1500)}`,custom_instructions:"Write a concise title (3–6 words, sentence case, no quotes, no trailing punctuation) for this conversation.",format:"text"}),n=ri(r==null?void 0:r.result);if(!n||this.renamed.has(e))return;await a.llm.call("update_chat",{_id:e,title:n}),this.applyTitle(e,n,!0)}catch{}}applyTitle(e,t,i){this.chatList=this.chatList.map(a=>a._id===e?{...a,title:t}:a),this.activeId===e&&(this.chatTitle=t),this.emit("singlebase-chat-title",{chatId:e,title:t,auto:i})}commitTitle(e){this.editingTitle&&(this.editingTitle=!1,this.activeId&&this.renameChat(this.activeId,e))}commitRename(e,t){this.renamingId===e&&(this.renamingId="",this.renameChat(e,t))}async renameChat(e,t){var r,n;const i=t.trim().slice(0,80),a=((r=this.chatList.find(d=>d._id===e))==null?void 0:r.title)??this.chatTitle;if(!(!i||i===a)){this.renamed.add(e),this.applyTitle(e,i,!1);try{await((n=this.resolvedClient)==null?void 0:n.llm.call("update_chat",{_id:e,title:i}))}catch{this.applyTitle(e,a??"",!1),this.showToast(this.msg.errGeneric)}}}fromServer(e){const t=e.role==="assistant",{text:i,followups:a}=t?gt(String(e.content??"")):{text:String(e.content??""),followups:[]};return{key:pt(),id:e._id??null,role:t?"assistant":"user",content:i,at:Date.parse(e._created_at??"")||0,bookmarked:!!e.bookmarked,sources:Array.isArray(e.sources)?e.sources:[],followups:a,phase:"done",execTime:typeof e.exec_time=="number"?e.exec_time:void 0,model:e.model}}async loadChats(){const e=this.resolvedClient;if(e){this.listState="loading";try{const t=await e.llm.call("list_chats",{limit:100});this.chatList=[...(t==null?void 0:t.items)??[]],this.listState="ready"}catch{this.listState="error"}}}upsertChat(e){const t=this.chatList.filter(a=>a._id!==e._id),i=this.chatList.find(a=>a._id===e._id);this.chatList=[{...i,...e},...t]}touchChat(e){const t=this.chatList.find(i=>i._id===e);t&&this.upsertChat({...t,_modified_at:new Date().toISOString()})}resetViewState(){this.panel=null,this.menuOpen=!1,this.editingKey="",this.editingTitle=!1,this.showJump=!1,this.retrievalOpen=new Set,this.sidebarOpen&&!this.docked&&(this.sidebarOpen=!1)}async deleteOnServer(e){const t=this.resolvedClient,i=this.activeId;if(!(!t||!i))for(const a of e)a&&await t.llm.call("delete_chat_message",{_id:i,message_id:a}).catch(()=>{})}async regenerate(){if(this.busy)return;const e=this.msgs.map(a=>a.role).lastIndexOf("assistant"),t=this.msgs[e-1];if(e<1||(t==null?void 0:t.role)!=="user")return;const i=this.msgs.slice(e-1);this.msgs=this.msgs.slice(0,e-1),await this.deleteOnServer(i.map(a=>a.id)),await this.runTurn(this.userMessage(t.content,t.attachments))}async retry(e){if(this.busy)return;const t=this.msgs.indexOf(e),i=this.msgs[t-1];(i==null?void 0:i.role)==="user"&&(this.msgs=this.msgs.slice(0,t-1),await this.runTurn(this.userMessage(i.content,i.attachments)))}async saveEdit(e){const t=this.editDraft.trim(),i=this.msgs.indexOf(e);if(this.editingKey="",!t||i<0||this.busy)return;const a=this.msgs.slice(i);this.msgs=this.msgs.slice(0,i),await this.deleteOnServer(a.map(r=>r.id)),await this.runTurn(this.userMessage(t,e.attachments))}toggleRaw(e){const t=new Set(this.rawKeys);t.has(e)?t.delete(e):t.add(e),this.rawKeys=t}copy(e,t){var i;(i=navigator.clipboard)==null||i.writeText(t).catch(()=>{}),this.copiedKey=e,this.later(()=>{this.copiedKey===e&&(this.copiedKey="")},1400)}async toggleMessageBookmark(e){var i;const t=this.activeId;if(!(!t||!e.id)){e.bookmarked=!e.bookmarked,this.msgs=[...this.msgs],this.showToast(e.bookmarked?this.msg.messageBookmarked:this.msg.bookmarkRemoved),this.emit("singlebase-chat-bookmark",{chatId:t,messageId:e.id,bookmarked:e.bookmarked});try{await((i=this.resolvedClient)==null?void 0:i.llm.call("bookmark_chat_message",{_id:t,message_id:e.id,bookmarked:e.bookmarked}))}catch{e.bookmarked=!e.bookmarked,this.msgs=[...this.msgs],this.showToast(this.msg.errGeneric)}}}async toggleChatBookmark(e){var r,n;const t=((r=this.chatList.find(d=>d._id===e))==null?void 0:r.bookmarked)??(e===this.activeId?this.bookmarked:!1),i=!t,a=d=>{this.chatList=this.chatList.map(c=>c._id===e?{...c,bookmarked:d}:c),e===this.activeId&&(this.bookmarked=d)};a(i),this.showToast(i?this.msg.chatBookmarked:this.msg.chatUnbookmarked),this.emit("singlebase-chat-bookmark",{chatId:e,bookmarked:i});try{await((n=this.resolvedClient)==null?void 0:n.llm.call("bookmark_chat",{_id:e,bookmarked:i}))}catch{a(t),this.showToast(this.msg.errGeneric)}}deleteMessage(e){var a;const t=this.activeId,i=this.msgs.indexOf(e);i<0||(this.msgs=this.msgs.filter(r=>r!==e),((a=this.panel)==null?void 0:a.key)===e.key&&(this.panel=null),this.showToast(this.msg.messageDeleted,{undo:()=>{if(this.activeId!==t)return;const r=[...this.msgs];r.splice(i,0,e),this.msgs=r},commit:()=>{var r;this.emit("singlebase-chat-message-delete",{chatId:t,messageId:e.id}),t&&e.id&&((r=this.resolvedClient)==null||r.llm.call("delete_chat_message",{_id:t,message_id:e.id}).catch(()=>{}))}}))}deleteChat(e){const t=this.chatList.findIndex(n=>n._id===e),i=this.chatList[t]??{_id:e,title:this.chatTitle,bookmarked:this.bookmarked},a=e===this.activeId,r=a?{title:this.chatTitle,bookmarked:this.bookmarked,msgs:this.msgs}:null;this.chatList=this.chatList.filter(n=>n._id!==e),a&&this.newChat(),this.showToast(this.msg.chatDeleted,{undo:()=>{const n=[...this.chatList];n.splice(Math.max(0,t),0,i),this.chatList=n,r&&!this.activeId&&!this.msgs.length&&(this.activeId=e,this.chatTitle=r.title,this.bookmarked=r.bookmarked,this.msgs=r.msgs)},commit:()=>{var n;this.emit("singlebase-chat-delete",{chatId:e}),(n=this.resolvedClient)==null||n.llm.call("delete_chat",{_id:e}).catch(()=>{})}})}feedback(e,t){e.feedback=t,this.msgs=[...this.msgs],this.emit("singlebase-chat-feedback",{chatId:this.activeId,messageId:e.id,value:t,text:e.content})}showToast(e,t={}){this.flushToast();const i={key:Date.now(),text:e,...t};this.toast=i,this.toastTimer=setTimeout(()=>{this.toast===i&&this.flushToast()},bi)}flushToast(){var t;const e=this.toast;clearTimeout(this.toastTimer),this.toast=null,(t=e==null?void 0:e.commit)==null||t.call(e)}undo(){var t;const e=this.toast;clearTimeout(this.toastTimer),this.toast=null,(t=e==null?void 0:e.undo)==null||t.call(e)}async addFiles(e){const t=Array.from(e??[]);if(!t.length)return;const i=[];for(const a of t){if(this.files.length+i.length>=Tt){this.showToast(T.fill(this.msg.tooManyFiles,{n:Tt}));break}if(!mi.test(a.name)&&!a.type.startsWith("text/")){this.showToast(T.fill(this.msg.fileType,{name:a.name}));continue}if(a.size>Ot){this.showToast(T.fill(this.msg.fileTooLarge,{name:a.name,size:T.formatSize(Ot)}));continue}i.push({name:a.name,size:a.size,content:await a.text()})}i.length&&(this.files=[...this.files,...i],this.emit("singlebase-chat-files",{files:i.map(({name:a,size:r})=>({name:a,size:r}))}))}async scrollToBottom(){await this.updateComplete;const e=this.renderRoot.querySelector(".scroller");e&&(e.scrollTop=e.scrollHeight),this.showJump=!1}onScroll(e){const t=e.currentTarget;this.stick=t.scrollHeight-t.scrollTop-t.clientHeight<80,this.stick&&(this.showJump=!1)}jumpToLatest(){this.stick=!0,this.scrollToBottom()}onKeydown(e){if(e.key==="Escape"){if(this.menuOpen)this.menuOpen=!1;else if(this.panel)this.panel=null;else if(this.sidebarOpen&&!this.docked)this.sidebarOpen=!1;else if(this.expanded)this.collapse();else if(this.embed==="launcher"&&this.isOpen)this.close();else return;e.stopPropagation()}}onComposerKey(e){e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this.send())}onComposerInput(e){const t=e.target;t.style.height="auto",t.style.height=`${Math.min(176,t.scrollHeight)}px`,this.draft=t.value}onDragEnter(e){var t;!this.allowUpload||!this.showComposer||Array.from(((t=e.dataTransfer)==null?void 0:t.types)??[]).includes("Files")&&(e.preventDefault(),this.dragging=!0)}onDragLeave(e){e.currentTarget.contains(e.relatedTarget)||(this.dragging=!1)}onDrop(e){var t;e.preventDefault(),this.dragging=!1,this.allowUpload&&this.addFiles((t=e.dataTransfer)==null?void 0:t.files)}render(){if(this.embed==="launcher")return this.renderLauncher();const e=["frame",this.embed==="inline"?"inline boxed":"",this.expanded?"expanded boxed":""].join(" ");return s.html`<div class=${e} part="frame">${this.renderWorkspace()}</div>`}renderLauncher(){const e=this.msg,t=["frame launcher boxed",this.expanded?"expanded":"",this.mobile?"full":""].join(" "),i=this.isOpen?s.html`<div class=${t} role="dialog" aria-label=${this.assistantName} part="frame">
2495
+ ${this.renderWorkspace()}
2496
+ </div>`:s.nothing,a=this.bubble&&!this.isOpen?s.html`<div class="bubble" part="bubble">
2497
+ <button type="button" class="bubble-text" @click=${()=>this.open()}>
2498
+ ${this.bubbleText||e.bubbleText}
2499
+ </button>
2500
+ <button
2501
+ type="button"
2502
+ class="icon sm"
2503
+ aria-label=${e.dismiss}
2504
+ title=${e.dismiss}
2505
+ @click=${()=>this.bubble=!1}
2506
+ >
2507
+ ${y.close()}
2508
+ </button>
2509
+ </div>`:s.nothing,n=this.isOpen&&(this.expanded||this.mobile)?s.nothing:s.html`<button
2510
+ type="button"
2511
+ class="launcher-btn"
2512
+ part="launcher"
2513
+ aria-label=${this.isOpen?e.closeChat:e.openChat}
2514
+ aria-expanded=${this.isOpen?"true":"false"}
2515
+ @click=${()=>this.isOpen?this.close():this.open()}
2516
+ >
2517
+ ${this.isOpen?y.chevronDown():y.chat()}
2518
+ ${this.unreadBadge&&!this.seen&&!this.isOpen?s.html`<span class="badge"></span>`:s.nothing}
2519
+ </button>`;return s.html`${i}${a}${n}`}renderWorkspace(){const e=!this.docked;return s.html`<div class="root" @keydown=${this.onKeydown}>
2520
+ ${this.sidebarOpen&&e?s.html`<div class="scrim" @click=${()=>this.sidebarOpen=!1}></div>`:s.nothing}
2521
+ ${this.sidebarOpen&&this.sidebar!=="none"?this.renderSidebar(e):s.nothing}
2522
+ <main
2523
+ class="main"
2524
+ @dragenter=${this.onDragEnter}
2525
+ @dragover=${t=>t.preventDefault()}
2526
+ >
2527
+ ${this.renderHeader()}
2528
+ ${this.offline?s.html`<div class="banner" role="status">${this.msg.offline}</div>`:s.nothing}
2529
+ <div
2530
+ class="scroller"
2531
+ role="log"
2532
+ aria-live="polite"
2533
+ aria-busy=${this.busy?"true":"false"}
2534
+ part="messages"
2535
+ @scroll=${this.onScroll}
2536
+ >
2537
+ ${this.msgs.length||this.loadingThread||this.threadError?this.renderThread():this.renderWelcome()}
2538
+ </div>
2539
+ ${this.showJump?s.html`<button type="button" class="jump" @click=${this.jumpToLatest}>
2540
+ ↓ ${this.msg.newReply}
2541
+ </button>`:s.nothing}
2542
+ ${this.renderComposer()}
2543
+ ${T.renderBranding(this.branding,this.brandingText,this.msg.brandingLabel,this.brandingUrl)}
2544
+ ${this.toast?s.html`<div class="toast" role="status">
2545
+ <span>${this.toast.text}</span>
2546
+ ${this.toast.undo?s.html`<button type="button" @click=${this.undo}>${this.msg.undo}</button>`:s.nothing}
2547
+ </div>`:s.nothing}
2548
+ ${this.dragging?s.html`<div
2549
+ class="drop"
2550
+ @dragover=${t=>t.preventDefault()}
2551
+ @dragleave=${this.onDragLeave}
2552
+ @drop=${this.onDrop}
2553
+ >
2554
+ <strong>${this.msg.dropTitle}</strong><span>${this.msg.dropSub}</span>
2555
+ </div>`:s.nothing}
2556
+ </main>
2557
+ ${this.renderPanel()}
2558
+ </div>`}renderSidebar(e){const t=this.msg,i=this.allowSearch?this.search.trim().toLowerCase():"",a=this.chatList.filter(b=>!i||(b.title??"").toLowerCase().includes(i)),r=b=>this.showBookmarked&&!!b.bookmarked,n=b=>a.filter(f=>!r(f)&&Ti(f._modified_at??f._created_at)===b),d=[[t.groupBookmarked,a.filter(r)],[t.groupToday,n("today")],[t.groupYesterday,n("yesterday")],[t.groupWeek,n("week")],[t.groupOlder,n("older")]];let c;return this.listState==="loading"&&!this.chatList.length?c=s.html`<div aria-label=${t.loadingChats}>
2559
+ ${[1,2,3,4].map(()=>s.html`<div class="skeleton"></div>`)}
2560
+ </div>`:a.length?c=d.filter(([,b])=>b.length).map(([b,f])=>s.html`<div class="group">${b}</div>
2561
+ ${f.map(k=>this.renderThreadRow(k))}`):c=s.html`<span class="side-note"
2562
+ >${i?T.fill(t.noMatch,{query:this.search.trim()}):t.noChats}</span
2563
+ >`,s.html`<aside
2564
+ class="sidebar ${e?"overlay":"docked"}"
2565
+ part="sidebar"
2566
+ aria-label=${t.chats}
2567
+ >
2568
+ <div class="side-head">
2569
+ <span class="label">${t.chats}</span>
2570
+ <button
2571
+ type="button"
2572
+ class="icon"
2573
+ title=${t.hideSidebar}
2574
+ aria-label=${t.hideSidebar}
2575
+ @click=${()=>this.sidebarOpen=!1}
2576
+ >
2577
+ ${y.sidebar()}
2578
+ </button>
2579
+ </div>
2580
+ <div class="side-tools">
2581
+ ${this.showNewChat?s.html`<button type="button" class="new-chat" @click=${()=>this.newChat()}>
2582
+ ${y.plus()}<span>${t.newChat}</span>
2583
+ </button>`:s.nothing}
2584
+ ${this.allowSearch?s.html`<input
2585
+ class="search"
2586
+ type="search"
2587
+ placeholder=${t.searchChats}
2588
+ aria-label=${t.searchChats}
2589
+ .value=${this.search}
2590
+ @input=${b=>this.search=b.target.value}
2591
+ />`:s.nothing}
2592
+ </div>
2593
+ <div class="threads">${c}</div>
2594
+ <div class="side-extra ${this.hasSidebarContent?"filled":""}" part="sidebar-extra">
2595
+ <slot
2596
+ name="sidebar"
2597
+ @slotchange=${b=>this.hasSidebarContent=b.target.assignedNodes().length>0}
2598
+ ></slot>
2599
+ </div>
2600
+ </aside>`}renderThreadRow(e){const t=this.msg,i=e._id===this.activeId,a=e.title||t.untitled;if(this.renamingId===e._id)return s.html`<div class="thread active">
2601
+ <input
2602
+ class="thread-rename"
2603
+ maxlength="80"
2604
+ .value=${a}
2605
+ aria-label=${t.renameChat}
2606
+ @keydown=${n=>{n.key==="Enter"&&this.commitRename(e._id,n.target.value),n.key==="Escape"&&(n.stopPropagation(),this.renamingId="")}}
2607
+ @blur=${n=>this.commitRename(e._id,n.target.value)}
2608
+ />
2609
+ </div>`;const r=n=>d=>{d.stopPropagation(),n()};return s.html`<div
2610
+ class="thread ${i?"active":""}"
2611
+ role="button"
2612
+ tabindex="0"
2613
+ aria-current=${i?"true":"false"}
2614
+ @click=${()=>this.openChat(e._id)}
2615
+ @keydown=${n=>n.key==="Enter"&&this.openChat(e._id)}
2616
+ >
2617
+ <span class="thread-title">${a}</span>
2618
+ <span class="thread-actions">
2619
+ ${this.allowBookmark?s.html`<button
2620
+ type="button"
2621
+ class="icon sm ${e.bookmarked?"on":""}"
2622
+ title=${e.bookmarked?t.unbookmarkChat:t.bookmarkChat}
2623
+ aria-label=${e.bookmarked?t.unbookmarkChat:t.bookmarkChat}
2624
+ @click=${r(()=>this.toggleChatBookmark(e._id))}
2625
+ >
2626
+ ${y.bookmark(!!e.bookmarked)}
2627
+ </button>`:s.nothing}
2628
+ ${this.allowRename?s.html`<button
2629
+ type="button"
2630
+ class="icon sm"
2631
+ title=${t.renameChat}
2632
+ aria-label=${t.renameChat}
2633
+ @click=${r(()=>{this.renamingId=e._id,this.focusNext="input.thread-rename"})}
2634
+ >
2635
+ ${y.pencil()}
2636
+ </button>`:s.nothing}
2637
+ ${this.allowDelete?s.html`<button
2638
+ type="button"
2639
+ class="icon sm danger"
2640
+ title=${t.deleteChat}
2641
+ aria-label=${t.deleteChat}
2642
+ @click=${r(()=>this.deleteChat(e._id))}
2643
+ >
2644
+ ${y.trash()}
2645
+ </button>`:s.nothing}
2646
+ </span>
2647
+ </div>`}renderHeader(){const e=this.msg,t=!!this.activeId,i=(this.embed==="inline"||this.embed==="launcher")&&!this.mobile,a=this.embed==="launcher"?()=>this.close():this.expanded?()=>this.collapse():null;let r=s.nothing;return this.showTitle&&(r=this.editingTitle?s.html`<input
2648
+ class="title-input"
2649
+ maxlength="80"
2650
+ .value=${this.chatTitle}
2651
+ aria-label=${e.renameChat}
2652
+ @keydown=${n=>{n.key==="Enter"&&this.commitTitle(n.target.value),n.key==="Escape"&&(n.stopPropagation(),this.editingTitle=!1)}}
2653
+ @blur=${n=>this.commitTitle(n.target.value)}
2654
+ />`:s.html`<button
2655
+ type="button"
2656
+ class="title"
2657
+ part="title"
2658
+ ?disabled=${!t||!this.allowRename}
2659
+ title=${t&&this.allowRename?e.renameChat:""}
2660
+ @click=${()=>{this.editingTitle=!0,this.focusNext="input.title-input"}}
2661
+ >
2662
+ ${this.chatTitle||e.untitled}
2663
+ </button>`),s.html`<header class="header" part="header">
2664
+ <div class="header-left">
2665
+ ${this.sidebar==="none"||this.sidebarOpen&&this.docked?s.nothing:s.html`<button
2666
+ type="button"
2667
+ class="icon"
2668
+ title=${e.showChats}
2669
+ aria-label=${e.showChats}
2670
+ @click=${()=>this.sidebarOpen=!0}
2671
+ >
2672
+ ${y.sidebar()}
2673
+ </button>`}
2674
+ ${r}
2675
+ </div>
2676
+ <div class="header-right">
2677
+ ${this.sidebar==="none"&&this.showNewChat?s.html`<button
2678
+ type="button"
2679
+ class="icon"
2680
+ ?disabled=${!this.msgs.length&&!t}
2681
+ title=${e.newChat}
2682
+ aria-label=${e.newChat}
2683
+ @click=${()=>this.newChat()}
2684
+ >
2685
+ ${y.plus()}
2686
+ </button>`:s.nothing}
2687
+ ${this.allowBookmark?s.html`<button
2688
+ type="button"
2689
+ class="icon ${this.bookmarked?"on":""}"
2690
+ ?disabled=${!t}
2691
+ title=${this.bookmarked?e.unbookmarkChat:e.bookmarkChat}
2692
+ aria-label=${this.bookmarked?e.unbookmarkChat:e.bookmarkChat}
2693
+ @click=${()=>this.activeId&&this.toggleChatBookmark(this.activeId)}
2694
+ >
2695
+ ${y.bookmark(this.bookmarked)}
2696
+ </button>`:s.nothing}
2697
+ ${this.allowExport?s.html`<div class="menu-wrap">
2698
+ <button
2699
+ type="button"
2700
+ class="icon ${this.menuOpen?"on":""}"
2701
+ ?disabled=${!this.msgs.length}
2702
+ title=${e.exportChat}
2703
+ aria-label=${e.exportChat}
2704
+ aria-haspopup="menu"
2705
+ aria-expanded=${this.menuOpen?"true":"false"}
2706
+ @click=${()=>this.menuOpen=!this.menuOpen}
2707
+ >
2708
+ ${y.download()}
2709
+ </button>
2710
+ ${this.menuOpen?this.renderExportMenu():s.nothing}
2711
+ </div>`:s.nothing}
2712
+ ${this.allowDelete?s.html`<button
2713
+ type="button"
2714
+ class="icon danger"
2715
+ ?disabled=${!t}
2716
+ title=${e.deleteChat}
2717
+ aria-label=${e.deleteChat}
2718
+ @click=${()=>this.activeId&&this.deleteChat(this.activeId)}
2719
+ >
2720
+ ${y.trash()}
2721
+ </button>`:s.nothing}
2722
+ ${i||a?s.html`<span class="divider"></span> ${i?s.html`<button
2723
+ type="button"
2724
+ class="icon"
2725
+ title=${this.expanded?e.restore:e.expand}
2726
+ aria-label=${this.expanded?e.restore:e.expand}
2727
+ @click=${()=>this.expanded?this.collapse():this.expand()}
2728
+ >
2729
+ ${this.expanded?y.restore():y.expand()}
2730
+ </button>`:s.nothing}
2731
+ ${a?s.html`<button
2732
+ type="button"
2733
+ class="icon"
2734
+ title=${e.minimize}
2735
+ aria-label=${e.minimize}
2736
+ @click=${a}
2737
+ >
2738
+ ${y.minimize()}
2739
+ </button>`:s.nothing}`:s.nothing}
2740
+ </div>
2741
+ </header>`}renderExportMenu(){const e=this.msg,t=[[e.exportMarkdown,".md","md"],[e.exportJson,".json","json"],[e.exportText,".txt","txt"],[e.exportCopy,"","copy"]];return s.html`<div class="menu-scrim" @click=${()=>this.menuOpen=!1}></div>
2742
+ <div class="menu" role="menu">
2743
+ <span class="label">${e.exportHeading}</span>
2744
+ ${t.map(([i,a,r])=>s.html`<button
2745
+ type="button"
2746
+ role="menuitem"
2747
+ class="menu-item"
2748
+ @click=${()=>this.exportChat(r)}
2749
+ >
2750
+ <span>${i}</span><span class="ext">${a}</span>
2751
+ </button>`)}
2752
+ </div>`}promptList(){const e=this.prompts;return Array.isArray(e)?e.map(t=>typeof t=="string"?{text:t}:t).filter(t=>t==null?void 0:t.text).slice(0,4):typeof e=="string"&&e.trim().toLowerCase()==="none"?[]:typeof e=="string"&&e.trim()?e.split("|").map(t=>t.trim()).filter(Boolean).slice(0,4).map(t=>({text:t})):(zt[this.mode]??zt.chat).map(([t,i])=>({label:t,text:i}))}renderWelcome(){const e=this.msg,t=this.mode==="rag"?"Rag":"Chat",i=n=>e[`${n}${t}`],a=this.eyebrow??i("eyebrow"),r=this.promptList();return s.html`<div class="welcome-slot">
2753
+ <slot name="welcome"
2754
+ ><div class="welcome" part="welcome">
2755
+ <div class="welcome-head">
2756
+ ${this.logoUrl&&Ct(this.logoUrl,!0)?s.html`<img class="welcome-logo" src=${this.logoUrl} alt="" />`:s.nothing}
2757
+ ${a?s.html`<span class="label">${a}</span>`:s.nothing}
2758
+ <h2>${this.heading||i("heading")}</h2>
2759
+ <p>${this.description||i("description")}</p>
2760
+ </div>
2761
+ ${r.length?s.html`<div class="prompts">
2762
+ ${r.map(n=>s.html`<button
2763
+ type="button"
2764
+ class="prompt"
2765
+ part="prompt"
2766
+ @click=${()=>this.send(n.text)}
2767
+ >
2768
+ <span class="label">${n.label||"Suggested"}</span>
2769
+ <span class="prompt-text">${n.text}</span>
2770
+ </button>`)}
2771
+ </div>`:s.nothing}
2772
+ </div></slot
2773
+ >
2774
+ </div>`}renderThread(){const e=this.msgs.map(t=>t.role).lastIndexOf("assistant");return s.html`<div class="thread-view">
2775
+ ${this.threadError?s.html`<div class="error-card" role="alert">
2776
+ <span>${this.threadError}</span>
2777
+ ${this.activeId?s.html`<button
2778
+ type="button"
2779
+ class="btn"
2780
+ @click=${()=>this.openChat(this.activeId)}
2781
+ >
2782
+ ${this.msg.retry}
2783
+ </button>`:s.nothing}
2784
+ </div>`:s.nothing}
2785
+ ${this.loadingThread?s.html`${[1,2].map(()=>s.html`<div class="skeleton" style="height:48px"></div>`)}`:s.nothing}
2786
+ ${Jt.repeat(this.msgs,t=>t.key,(t,i)=>t.role==="user"?this.renderUser(t):this.renderBot(t,i===e))}
2787
+ </div>`}renderUser(e){const t=this.msg,i=e.at?new Date(e.at).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}):"",a=e.attachments??[];return s.html`<div class="msg user" part="message user">
2788
+ ${a.length?s.html`<div class="attachments">
2789
+ ${a.map(r=>s.html`<span class="doc-chip"><span class="ext">${Lt(r.name)}</span><span class="name">${r.name}</span></span>`)}
2790
+ </div>`:s.nothing}
2791
+ ${this.editingKey===e.key?s.html`<div class="edit-box">
2792
+ <textarea
2793
+ rows="3"
2794
+ class="edit-input"
2795
+ .value=${this.editDraft}
2796
+ @input=${r=>this.editDraft=r.target.value}
2797
+ @keydown=${r=>{r.key==="Escape"&&(r.stopPropagation(),this.editingKey="")}}
2798
+ ></textarea>
2799
+ <div class="row-end">
2800
+ <button type="button" class="btn" @click=${()=>this.editingKey=""}>
2801
+ ${t.cancel}
2802
+ </button>
2803
+ <button type="button" class="btn primary" @click=${()=>this.saveEdit(e)}>
2804
+ ${t.saveResend}
2805
+ </button>
2806
+ </div>
2807
+ </div>`:s.html`<div class="bubble-user">${e.content}</div>
2808
+ <div class="toolbar">
2809
+ ${this.allowBookmark&&e.bookmarked?s.html`<span class="saved">${y.bookmark(!0)}${t.saved}</span>`:s.nothing}
2810
+ ${this.showTime?s.html`<span class="time">${i}</span>`:s.nothing}
2811
+ ${this.busy?s.nothing:s.html`<button
2812
+ type="button"
2813
+ class="icon"
2814
+ title=${t.edit}
2815
+ aria-label=${t.edit}
2816
+ @click=${()=>{this.editingKey=e.key,this.editDraft=e.content,this.focusNext="textarea.edit-input"}}
2817
+ >
2818
+ ${y.pencil()}
2819
+ </button>`}
2820
+ ${this.allowCopy?s.html`<button
2821
+ type="button"
2822
+ class="icon"
2823
+ title=${this.copiedKey===e.key?t.copied:t.copy}
2824
+ aria-label=${t.copy}
2825
+ @click=${()=>this.copy(e.key,e.content)}
2826
+ >
2827
+ ${y.copy()}
2828
+ </button>`:s.nothing}
2829
+ ${this.allowBookmark&&e.id?s.html`<button
2830
+ type="button"
2831
+ class="icon ${e.bookmarked?"on":""}"
2832
+ title=${e.bookmarked?t.unbookmarkMessage:t.bookmarkMessage}
2833
+ aria-label=${e.bookmarked?t.unbookmarkMessage:t.bookmarkMessage}
2834
+ @click=${()=>this.toggleMessageBookmark(e)}
2835
+ >
2836
+ ${y.bookmark(e.bookmarked)}
2837
+ </button>`:s.nothing}
2838
+ ${this.allowDelete?s.html`<button
2839
+ type="button"
2840
+ class="icon danger"
2841
+ title=${t.deleteMessage}
2842
+ aria-label=${t.deleteMessage}
2843
+ @click=${()=>this.deleteMessage(e)}
2844
+ >
2845
+ ${y.trash()}
2846
+ </button>`:s.nothing}
2847
+ </div>`}
2848
+ </div>`}pillLabel(){return this.mode==="rag"?this.msg.searching:this.msg.thinking}renderBot(e,t){const i=this.msg,a=e.phase==="pending",r=e.phase==="done",n=e.sources.length,d=ut(e.content),c=e.sources.map((v,M)=>L(v,M+1)),b=d.size?c.filter(v=>d.has(v.n)):c,f=e.at?new Date(e.at).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}):"",k=e.content+(b.length?`
2849
+
2850
+ Sources:
2851
+ ${b.map(v=>`[${v.n}] ${v.title}`).join(`
2852
+ `)}`:""),C=this.retrievalOpen.has(e.key);return s.html`<div class="msg bot" part="message assistant">
2853
+ ${a?s.html`<div class="halo"></div>`:s.nothing}
2854
+ ${this.arrivedKey===e.key?s.html`<div class="arrived">
2855
+ <div class="wash"></div>
2856
+ <div class="ring"></div>
2857
+ <div class="sweep"></div>
2858
+ </div>`:s.nothing}
2859
+ <div class="bot-body">
2860
+ ${this.allowBookmark&&e.bookmarked?s.html`<span class="saved">${y.bookmark(!0)}${i.saved}</span>`:s.nothing}
2861
+ ${a?s.html`<div class="pill" role="status">
2862
+ <span class="ring"></span><span class="dot"></span>
2863
+ <span class="shimmer">${this.pillLabel()}</span>
2864
+ </div>`:s.nothing}
2865
+ ${this.showSources&&n&&!a?s.html`<div class="retrieval">
2866
+ <button
2867
+ type="button"
2868
+ class="retrieval-toggle"
2869
+ aria-expanded=${C?"true":"false"}
2870
+ @click=${()=>{const v=new Set(this.retrievalOpen);v.has(e.key)?v.delete(e.key):v.add(e.key),this.retrievalOpen=v}}
2871
+ >
2872
+ <span class="chev">${C?"▾":"▸"}</span>
2873
+ <span style="flex:1">${T.fill(i.searchedSources,{n})}</span>
2874
+ ${e.execTime!==void 0?s.html`<span class="ms">${e.execTime.toFixed(1)}s</span>`:s.nothing}
2875
+ </button>
2876
+ ${C?s.html`<div class="retrieval-list">
2877
+ ${c.map(v=>s.html`<button
2878
+ type="button"
2879
+ class="passage"
2880
+ @click=${()=>this.panel={key:e.key,n:v.n}}
2881
+ >
2882
+ <span class="n">${v.n}</span>
2883
+ <span class="what"
2884
+ ><span>${v.title}</span><span>${v.collection||v.path}</span></span
2885
+ >
2886
+ ${v.score!==null?s.html`<span class="relevance"
2887
+ ><span class="score">${v.score.toFixed(2)}</span>
2888
+ <span class="relevance-track"
2889
+ ><span
2890
+ class="relevance-fill"
2891
+ style="width:${Math.round(v.score*100)}%"
2892
+ ></span></span
2893
+ ></span>`:s.html`<span></span>`}
2894
+ </button>`)}
2895
+ </div>`:s.nothing}
2896
+ </div>`:s.nothing}
2897
+ ${a?s.nothing:this.renderAnswer(e)}
2898
+ ${e.phase==="streaming"?s.html`<span class="caret"></span>`:s.nothing}
2899
+ ${e.phase==="error"?s.html`<div class="error-card" role="alert">
2900
+ <span>${e.error}</span>
2901
+ <button type="button" class="btn" @click=${()=>this.retry(e)}>
2902
+ ${i.retry}
2903
+ </button>
2904
+ </div>`:s.nothing}
2905
+ ${this.showSources&&r&&b.length?s.html`<div class="cards">
2906
+ <span class="label">${d.size?i.sourcesCited:i.sourcesRetrieved}</span>
2907
+ <div class="card-grid">
2908
+ ${b.map(v=>{var M;return s.html`<button
2909
+ type="button"
2910
+ class="source-card ${((M=this.panel)==null?void 0:M.key)===e.key&&this.panel.n===v.n?"active":""}"
2911
+ @click=${()=>this.panel={key:e.key,n:v.n}}
2912
+ >
2913
+ <span class="top"
2914
+ ><span class="num">${v.n}</span
2915
+ >${v.collection?s.html`<span class="label">${v.collection}</span>`:s.nothing}</span
2916
+ >
2917
+ <span class="t">${v.title}</span>
2918
+ <span class="s">${v.text}</span>
2919
+ </button>`})}
2920
+ </div>
2921
+ </div>`:s.nothing}
2922
+ ${r?s.html`<div class="toolbar ${t?"pinned":""}">
2923
+ ${this.allowCopy?s.html`<button
2924
+ type="button"
2925
+ class="icon"
2926
+ title=${this.copiedKey===e.key?i.copied:i.copy}
2927
+ aria-label=${i.copy}
2928
+ @click=${()=>this.copy(e.key,k)}
2929
+ >
2930
+ ${y.copy()}
2931
+ </button>`:s.nothing}
2932
+ ${this.allowRaw&&this.formatLevel!=="raw"&&e.content?s.html`<button
2933
+ type="button"
2934
+ class="icon ${this.rawKeys.has(e.key)?"on":""}"
2935
+ title=${this.rawKeys.has(e.key)?i.showFormatted:i.showRaw}
2936
+ aria-label=${i.showRaw}
2937
+ aria-pressed=${this.rawKeys.has(e.key)?"true":"false"}
2938
+ @click=${()=>this.toggleRaw(e.key)}
2939
+ >
2940
+ ${y.raw()}
2941
+ </button>`:s.nothing}
2942
+ ${this.allowRegenerate&&t&&!this.busy?s.html`<button
2943
+ type="button"
2944
+ class="icon"
2945
+ title=${i.regenerate}
2946
+ aria-label=${i.regenerate}
2947
+ @click=${()=>this.regenerate()}
2948
+ >
2949
+ ${y.refresh()}
2950
+ </button>`:s.nothing}
2951
+ ${this.allowBookmark&&e.id?s.html`<button
2952
+ type="button"
2953
+ class="icon ${e.bookmarked?"on":""}"
2954
+ title=${e.bookmarked?i.unbookmarkMessage:i.bookmarkMessage}
2955
+ aria-label=${e.bookmarked?i.unbookmarkMessage:i.bookmarkMessage}
2956
+ @click=${()=>this.toggleMessageBookmark(e)}
2957
+ >
2958
+ ${y.bookmark(e.bookmarked)}
2959
+ </button>`:s.nothing}
2960
+ ${this.allowDelete?s.html`<button
2961
+ type="button"
2962
+ class="icon danger"
2963
+ title=${i.deleteMessage}
2964
+ aria-label=${i.deleteMessage}
2965
+ @click=${()=>this.deleteMessage(e)}
2966
+ >
2967
+ ${y.trash()}
2968
+ </button>`:s.nothing}
2969
+ ${this.showTime?s.html`<span class="time">${f}</span>`:s.nothing}
2970
+ ${e.stopped?s.html`<span class="note">${i.stopped}</span>`:s.nothing}
2971
+ <span class="spacer"></span>
2972
+ ${this.allowFeedback?e.feedback?s.html`<span class="note"
2973
+ >${e.feedback==="up"?i.markedHelpful:i.thanksFeedback}</span
2974
+ >`:s.html`<button
2975
+ type="button"
2976
+ class="icon"
2977
+ title=${i.helpful}
2978
+ aria-label=${i.helpful}
2979
+ @click=${()=>this.feedback(e,"up")}
2980
+ >
2981
+ ${y.thumb()}
2982
+ </button>
2983
+ <button
2984
+ type="button"
2985
+ class="icon"
2986
+ title=${i.notHelpful}
2987
+ aria-label=${i.notHelpful}
2988
+ @click=${()=>this.feedback(e,"down")}
2989
+ >
2990
+ ${y.thumb(!0)}
2991
+ </button>`:s.nothing}
2992
+ </div>`:s.nothing}
2993
+ ${this.showFollowups&&r&&t&&!this.busy&&e.followups.length?s.html`<div class="followups">
2994
+ ${e.followups.map(v=>s.html`<button type="button" class="followup" @click=${()=>this.send(v)}>
2995
+ <span class="arrow">↳</span><span>${v}</span>
2996
+ </button>`)}
2997
+ </div>`:s.nothing}
2998
+ </div>
2999
+ </div>`}renderAnswer(e){if(e.phase==="error"&&!e.content)return s.nothing;if(e.phase==="done"&&!e.content)return e.stopped?s.nothing:s.html`<div class="answer"><p class="note">${this.msg.emptyReply}</p></div>`;const t=this.formatLevel;if(t==="raw"||this.allowRaw&&this.rawKeys.has(e.key))return s.html`<div class="answer" part="answer"><p class="raw">${e.content}</p></div>`;const i=e.phase==="streaming"?Dt(e.content):e.content;let a=Ft(Rt(i),t);if(this.afterParse)try{const n=this.afterParse(a,{message:e,format:t});Array.isArray(n)?a=n:console.warn("[singlebase-chat] afterParse must return an array of blocks; showing the original.")}catch(n){console.warn("[singlebase-chat] afterParse failed; showing the original.",n)}const r=e.sources.length;return s.html`<div class="answer" part="answer">
3000
+ ${a.map((n,d)=>this.renderBlock(n,e,r,d))}
3001
+ </div>`}renderInline(e,t,i){return Bt(e,i).map(a=>{var r;switch(a.type){case"bold":return s.html`<strong>${a.text}</strong>`;case"italic":return s.html`<em>${a.text}</em>`;case"strike":return s.html`<s>${a.text}</s>`;case"code":return s.html`<code class="inline">${a.text}</code>`;case"link":return s.html`<a href=${a.href} target="_blank" rel="noopener noreferrer nofollow"
3002
+ >${a.text}</a
3003
+ >`;case"cite":{const n=((r=this.panel)==null?void 0:r.key)===t.key&&this.panel.n===a.n?"cite active":"cite",d=T.fill(this.msg.openSource,{n:a.n}),c=()=>this.panel={key:t.key,n:a.n};return s.html`<button type="button" class=${n} aria-label=${d} @click=${c}>${a.n}</button>`}default:return a.text}})}renderBlock(e,t,i,a){switch(e.type){case"p":return s.html`<p>${this.renderInline(e.text,t,i)}</p>`;case"raw":return s.html`<p class="raw">${e.text}</p>`;case"h":return s.html`<h3 class="h${e.level}">${this.renderInline(e.text,t,i)}</h3>`;case"hr":return s.html`<hr />`;case"list":return this.renderList(e.ordered,e.items,t,i);case"quote":return s.html`<div class="quote">${this.renderInline(e.text,t,i)}</div>`;case"callout":return s.html`<div class="callout ${e.kind}" role="note" part="callout">
3004
+ <strong class="callout-title"
3005
+ >${e.title||this.msg[xi[e.kind]]}</strong
3006
+ >
3007
+ ${e.text.split(`
3008
+ `).filter(r=>r.trim()).map(r=>s.html`<p>${this.renderInline(r,t,i)}</p>`)}
3009
+ </div>`;case"code":return this.renderCustom(e.lang,e.text,t)??this.renderCode(e.lang,e.text,`${t.key}:${a}`);case"table":return this.renderTable(e.head,e.rows,e.align,t,i,`${t.key}:${a}`);case"json":return this.renderJsonBlock(e.value,e.source,`${t.key}:${a}`);case"svg":{const r=Ut(e.source);if(!r)return this.renderCode("svg",e.source,`${t.key}:${a}`);const n=`${t.key}:${a}`;return s.html`<figure class="svg" part="svg">
3010
+ <img src=${r} alt="Drawing" />
3011
+ <figcaption>
3012
+ <button type="button" class="text-btn" @click=${()=>this.copy(n,e.source)}>
3013
+ ${this.copiedKey===n?this.msg.copied:this.msg.copySvg}
3014
+ </button>
3015
+ </figcaption>
3016
+ </figure>`}case"pending":return s.html`<div class="chart-pending">
3017
+ <span class="label"
3018
+ >${e.kind==="svg"?this.msg.renderingSvg:this.msg.renderingChart}</span
3019
+ >
3020
+ </div>`;case"chart":return this.renderChart(e.spec);case"img":return s.html`<div class="gallery ${e.images.length>1?"many":""}">
3021
+ ${e.images.map(r=>s.html`<figure>
3022
+ ${r.src&&Ct(r.src,!0)?s.html`<img
3023
+ src=${r.src}
3024
+ alt=${r.alt}
3025
+ loading="lazy"
3026
+ referrerpolicy="no-referrer"
3027
+ />`:s.html`<div class="img-missing"><span class="label">Image</span></div>`}
3028
+ ${r.alt?s.html`<figcaption>${r.alt}</figcaption>`:s.nothing}
3029
+ </figure>`)}
3030
+ </div>`;default:return s.nothing}}renderList(e,t,i,a){const r=t.map(n=>s.html`<li
3031
+ class=${n.checked===null?"":"task"}
3032
+ style=${n.depth?`margin-left:${n.depth*20}px`:""}
3033
+ >
3034
+ ${n.checked===null?s.nothing:s.html`<input type="checkbox" disabled .checked=${n.checked} aria-hidden="true" />`}
3035
+ ${this.renderInline(n.text,i,a)}
3036
+ </li>`);return e?s.html`<ol>
3037
+ ${r}
3038
+ </ol>`:s.html`<ul>
3039
+ ${r}
3040
+ </ul>`}renderCode(e,t,i){return s.html`<div class="code">
3041
+ <div class="code-head">
3042
+ <span class="label">${e}</span>
3043
+ <button type="button" class="text-btn" @click=${()=>this.copy(i,t)}>
3044
+ ${this.copiedKey===i?this.msg.copied:this.msg.copy}
3045
+ </button>
3046
+ </div>
3047
+ <pre><code>${t}</code></pre>
3048
+ </div>`}renderCustom(e,t,i){var r;const a=this.formatLevel==="rich"?(r=this.renderers)==null?void 0:r[e]:void 0;if(typeof a!="function"||i.phase==="streaming")return null;try{const n=a(t,{lang:e,message:i});return n==null?null:s.html`<div class="custom-block">${n}</div>`}catch(n){return console.warn(`[singlebase-chat] the "${e}" renderer failed; showing the source`,n),null}}renderTable(e,t,i,a,r,n){const d=x=>/^[-+]?[$€£¥]?\s?[\d,.]+\s?%?$/.test(x.trim())&&/\d/.test(x),c=x=>Number(x.replace(/[^\d.+-]/g,"")),b=e.map((x,$)=>{if(i[$])return i[$];const w=t.map(z=>z[$]??"").filter(Boolean);return w.length&&w.filter(d).length/w.length>=.8?"right":null}),f=this.sorts.get(n);let k=t;f&&(k=[...t].sort((x,$)=>{const w=x[f.col]??"",z=$[f.col]??"";return(d(w)&&d(z)?c(w)-c(z):w.localeCompare(z,void 0,{numeric:!0}))*f.dir}));const C=k.length;k=k.slice(0,fi);const v=x=>{const $=new Map(this.sorts),w=$.get(n);(w==null?void 0:w.col)===x&&w.dir===-1?$.delete(n):$.set(n,{col:x,dir:(w==null?void 0:w.col)===x?-1:1}),this.sorts=$},M=x=>b[x]?`text-align:${b[x]}`:"";return s.html`<div class="table" part="table">
3049
+ <table>
3050
+ <thead>
3051
+ <tr>
3052
+ ${e.map((x,$)=>{const w=(f==null?void 0:f.col)===$?f.dir===1?"ascending":"descending":"none";return s.html`<th style=${M($)} aria-sort=${w}>
3053
+ ${t.length>1?s.html`<button type="button" class="sort" @click=${()=>v($)}>
3054
+ ${this.renderInline(x,a,r)}<span class="arrow"
3055
+ >${w==="ascending"?"↑":w==="descending"?"↓":"↕"}</span
3056
+ >
3057
+ </button>`:this.renderInline(x,a,r)}
3058
+ </th>`})}
3059
+ </tr>
3060
+ </thead>
3061
+ <tbody>
3062
+ ${k.map(x=>s.html`<tr>
3063
+ ${e.map(($,w)=>s.html`<td style=${M(w)}>
3064
+ ${this.renderInline(x[w]??"",a,r)}
3065
+ </td>`)}
3066
+ </tr>`)}
3067
+ </tbody>
3068
+ </table>
3069
+ ${C>k.length?s.html`<div class="table-note">
3070
+ ${T.fill(this.msg.showingRows,{n:k.length,total:C})}
3071
+ </div>`:s.nothing}
3072
+ </div>`}renderJsonBlock(e,t,i){let a=0;const r=d=>{a++,a<=It&&d&&typeof d=="object"&&Object.values(d).forEach(r)};if(r(e),a>It)return this.renderCode("json",t,i);const n=(d,c,b)=>{const f=b===void 0?s.nothing:s.html`<span class="jkey">${b}</span>: `;if(d&&typeof d=="object"){const C=Object.entries(d),v=Array.isArray(d)?`[${C.length}]`:`{${C.length}}`;return s.html`<details class="jnode" ?open=${c<2}>
3073
+ <summary>${f}<span class="jmeta">${v}</span></summary>
3074
+ <div class="jkids">${C.map(([M,x])=>n(x,c+1,M))}</div>
3075
+ </details>`}const k=d===null?"null":typeof d;return s.html`<div class="jleaf">
3076
+ ${f}<span class="jv ${k}">${JSON.stringify(d)}</span>
3077
+ </div>`};return s.html`<div class="code json" part="json">
3078
+ <div class="code-head">
3079
+ <span class="label">json</span>
3080
+ <button type="button" class="text-btn" @click=${()=>this.copy(i,t)}>
3081
+ ${this.copiedKey===i?this.msg.copied:this.msg.copy}
3082
+ </button>
3083
+ </div>
3084
+ <div class="jtree">${n(e,0)}</div>
3085
+ </div>`}renderChart(e){const t=e.series.length>1?s.html`<span class="legend">
3086
+ ${e.series.map((n,d)=>s.html`<span
3087
+ ><span
3088
+ class="swatch"
3089
+ style="background:${_[d%_.length]}"
3090
+ ></span
3091
+ >${n.name}</span
3092
+ >`)}
3093
+ </span>`:s.nothing,i=s.html`<div class="chart-head">
3094
+ <span class="chart-title">${e.title}</span>${t}
3095
+ </div>`;if(e.type==="line"){const n=Math.max(0,...e.series.flatMap(f=>f.values)),d=Math.pow(10,Math.floor(Math.log10(n||1))),c=Math.ceil(n/d*2)/2*d||1,b=Math.max(e.labels.length,...e.series.map(f=>f.values.length));return s.html`<figure class="chart" part="chart" aria-label=${e.title}>
3096
+ ${i}
3097
+ <div class="line-chart">
3098
+ <div class="plot">
3099
+ ${[1,.5,0].map(f=>s.html`<div class="tick ${f===0?"base":""}" style="top:${(1-f)*100}%">
3100
+ <span>${ht(Math.round(c*f),e.unit)}</span>
3101
+ </div>`)}
3102
+ <svg
3103
+ viewBox="0 0 600 170"
3104
+ preserveAspectRatio="none"
3105
+ role="img"
3106
+ aria-label=${e.title}
3107
+ >
3108
+ ${e.series.map((f,k)=>s.svg`<polyline pathLength="1" stroke=${_[k%_.length]}
3109
+ points=${f.values.map((C,v)=>`${(b>1?v/(b-1)*600:300).toFixed(1)},${(170-C/c*170).toFixed(1)}`).join(" ")}><title>${f.name}: ${f.values.map(C=>ht(C,e.unit)).join(", ")}</title></polyline>`)}
3110
+ </svg>
3111
+ </div>
3112
+ <div class="x-labels">${e.labels.map(f=>s.html`<span>${f}</span>`)}</div>
3113
+ </div>
3114
+ </figure>`}const a=e.labels.map((n,d)=>e.series.reduce((c,b)=>c+(b.values[d]||0),0)),r=Math.max(0,...a)||1;return s.html`<figure class="chart" part="chart" aria-label=${e.title}>
3115
+ ${i}
3116
+ <div class="bars">
3117
+ ${e.labels.map((n,d)=>s.html`<div class="bar-row" title="${n}: ${ht(a[d],e.unit)}">
3118
+ <span class="bar-label">${n}</span>
3119
+ <span class="bar-track"
3120
+ ><span class="bar-fill" style="width:${Math.max(0,a[d])/r*100}%">
3121
+ ${e.series.map((c,b)=>s.html`<span
3122
+ style="flex:${Math.max(0,c.values[d]||0)};background:${e.series.length>1?_[b%_.length]:"var(--c-ink)"}"
3123
+ ></span>`)}
3124
+ </span></span
3125
+ >
3126
+ <span class="bar-value">${ht(a[d],e.unit)}</span>
3127
+ </div>`)}
3128
+ </div>
3129
+ </figure>`}renderPanel(){if(!this.panel)return s.nothing;const e=this.msgs.find(f=>f.key===this.panel.key),t=e==null?void 0:e.sources[this.panel.n-1];if(!e||!t)return s.nothing;const i=this.msg,a=L(t,this.panel.n),r=ut(e.content),n=e.sources.map((f,k)=>L(f,k+1)).filter(f=>f.n!==a.n&&(!r.size||r.has(f.n))),d=`ref:${e.key}:${a.n}`,c=`"${a.text}"
3130
+ — ${a.title} [${a.n}]${a.path?`
3131
+ ${a.path}`:""}${a.updated?` · Updated ${a.updated}`:""}`,b=[a.updated?`Updated ${a.updated}`:"",a.score!==null?`Relevance ${a.score.toFixed(2)}`:""].filter(Boolean).join(" · ");return s.html`<aside
3132
+ class="panel ${this.panelDocked?"docked":"overlay"}"
3133
+ part="panel"
3134
+ role="region"
3135
+ aria-label=${T.fill(i.sourceLabel,{n:a.n})}
3136
+ >
3137
+ <div class="panel-head">
3138
+ <span class="label"
3139
+ >${T.fill(i.sourceLabel,{n:a.n})}${a.collection?` · ${a.collection}`:""}</span
3140
+ >
3141
+ <button type="button" class="text-btn underline" @click=${()=>this.panel=null}>
3142
+ ${i.close}
3143
+ </button>
3144
+ </div>
3145
+ <div class="panel-body">
3146
+ <div class="panel-meta">
3147
+ <h3>${a.title}</h3>
3148
+ ${a.path?s.html`<span class="path">${a.path}</span>`:s.nothing}
3149
+ ${b?s.html`<span class="meta">${b}</span>`:s.nothing}
3150
+ </div>
3151
+ <div class="passage-box">
3152
+ <span class="text">${a.text}</span>
3153
+ <div class="passage-foot">
3154
+ <span class="label">${i.citedPassage}</span>
3155
+ <button
3156
+ type="button"
3157
+ class="copy-ref"
3158
+ title=${i.copyReference}
3159
+ aria-label=${i.copyReference}
3160
+ @click=${()=>this.copy(d,c)}
3161
+ >
3162
+ ${y.copy()}<span>${this.copiedKey===d?i.copied:i.copy}</span>
3163
+ </button>
3164
+ </div>
3165
+ </div>
3166
+ </div>
3167
+ ${n.length?s.html`<div class="panel-foot">
3168
+ <span class="label">${i.alsoCited}</span>
3169
+ <div class="chips">
3170
+ ${n.map(f=>s.html`<button
3171
+ type="button"
3172
+ class="chip"
3173
+ @click=${()=>this.panel={key:e.key,n:f.n}}
3174
+ >
3175
+ ${f.n} · ${f.title}
3176
+ </button>`)}
3177
+ </div>
3178
+ </div>`:s.nothing}
3179
+ </aside>`}renderComposer(){const e=this.msg,t=this.mode==="rag"?e.placeholderRag:T.fill(e.placeholderChat,{name:this.assistantName}),i=!this.draft.trim(),a=this.footnote===""?s.nothing:s.html`<span class="footnote" part="footnote"
3180
+ >${this.footnote??T.fill(e.footnote,{name:this.assistantName})}</span
3181
+ >`;return this.showComposer?s.html`<div class="composer-wrap">
3182
+ <div class="composer-col">
3183
+ <input
3184
+ type="file"
3185
+ multiple
3186
+ hidden
3187
+ accept=".md,.markdown,.txt,.csv,.tsv,.json,.html,.htm,.yaml,.yml,.xml,.log,text/*"
3188
+ @change=${r=>{const n=r.target;this.addFiles(n.files).then(()=>n.value="")}}
3189
+ />
3190
+ <div class="composer-box">
3191
+ ${this.busy?s.html`<div class="composer-glow"></div>`:s.nothing}
3192
+ <div class="composer ${this.busy?"busy":""}" part="composer">
3193
+ ${this.files.length?s.html`<div class="pending-files">
3194
+ ${this.files.map(r=>s.html`<div class="pending-file">
3195
+ <span class="ext">${Lt(r.name)}</span>
3196
+ <span class="meta"
3197
+ ><span class="name">${r.name}</span
3198
+ ><span class="size">${T.formatSize(r.size)}</span></span
3199
+ >
3200
+ <button
3201
+ type="button"
3202
+ aria-label=${e.removeFile}
3203
+ title=${e.removeFile}
3204
+ @click=${()=>this.files=this.files.filter(n=>n!==r)}
3205
+ >
3206
+ ×
3207
+ </button>
3208
+ </div>`)}
3209
+ </div>`:s.nothing}
3210
+ <textarea
3211
+ class="input"
3212
+ rows="1"
3213
+ placeholder=${t}
3214
+ aria-label=${t}
3215
+ .value=${this.draft}
3216
+ @input=${this.onComposerInput}
3217
+ @keydown=${this.onComposerKey}
3218
+ ></textarea>
3219
+ <div class="composer-row">
3220
+ <div>
3221
+ ${this.allowUpload?s.html`<button
3222
+ type="button"
3223
+ class="attach"
3224
+ title=${e.attach}
3225
+ aria-label=${e.attach}
3226
+ @click=${()=>{var r;return(r=this.renderRoot.querySelector("input[type=file]"))==null?void 0:r.click()}}
3227
+ >
3228
+ ${y.clip()}
3229
+ </button>`:s.nothing}
3230
+ </div>
3231
+ ${this.busy?s.html`<button
3232
+ type="button"
3233
+ class="send stop"
3234
+ title=${e.stop}
3235
+ aria-label=${e.stop}
3236
+ @click=${()=>this.stop()}
3237
+ >
3238
+ ${y.stop()}
3239
+ </button>`:s.html`<button
3240
+ type="button"
3241
+ class="send"
3242
+ title=${e.send}
3243
+ aria-label=${e.send}
3244
+ ?disabled=${i}
3245
+ @click=${()=>this.send()}
3246
+ >
3247
+ ${y.up()}
3248
+ </button>`}
3249
+ </div>
3250
+ </div>
3251
+ ${this.busy?s.html`<div class="composer-ring"><div class="ring"></div></div>`:s.nothing}
3252
+ </div>
3253
+ ${a}
3254
+ </div>
3255
+ </div>`:s.html`<div class="composer-wrap reader">
3256
+ <div class="composer-col">${a}</div>
3257
+ </div>`}},j=new WeakMap,N=new WeakMap,A=new WeakMap,R=new WeakMap,E=new WeakMap,B=new WeakMap,D=new WeakMap,F=new WeakMap,U=new WeakMap,P=new WeakMap,K=new WeakMap,W=new WeakMap,J=new WeakMap,H=new WeakMap,q=new WeakMap,G=new WeakMap,V=new WeakMap,X=new WeakMap,Y=new WeakMap,Q=new WeakMap,Z=new WeakMap,ee=new WeakMap,te=new WeakMap,ie=new WeakMap,se=new WeakMap,ae=new WeakMap,re=new WeakMap,ne=new WeakMap,oe=new WeakMap,le=new WeakMap,ce=new WeakMap,de=new WeakMap,he=new WeakMap,pe=new WeakMap,ue=new WeakMap,ge=new WeakMap,me=new WeakMap,be=new WeakMap,fe=new WeakMap,xe=new WeakMap,ve=new WeakMap,ye=new WeakMap,we=new WeakMap,ke=new WeakMap,$e=new WeakMap,Ce=new WeakMap,Se=new WeakMap,Te=new WeakMap,Oe=new WeakMap,Ie=new WeakMap,Me=new WeakMap,ze=new WeakMap,_e=new WeakMap,Le=new WeakMap,je=new WeakMap,Ne=new WeakMap,Ae=new WeakMap,Re=new WeakMap,Ee=new WeakMap,Be=new WeakMap,De=new WeakMap,Fe=new WeakMap,Ue=new WeakMap,Pe=new WeakMap,Ke=new WeakMap,We=new WeakMap,Je=new WeakMap,He=new WeakMap,qe=new WeakMap,Ge=new WeakMap,Ve=new WeakMap,Xe=new WeakMap,Ye=new WeakMap,Qe=new WeakMap,Ze=new WeakMap,et=new WeakMap,tt=new WeakMap,it=new WeakMap,st=new WeakMap,at=new WeakMap,rt=new WeakMap,nt=new WeakMap,ot=new WeakMap,lt=new WeakMap,ct=new WeakMap,dt=new WeakMap,jt);di(exports.SinglebaseChat,"styles",[T.tokenDefaults,T.brandingStyles,qt]);m([g.property({attribute:!1})],exports.SinglebaseChat.prototype,"client",1);m([g.property({attribute:!1})],exports.SinglebaseChat.prototype,"messages",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"theme",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"radius",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"mode",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"format",1);m([g.property({attribute:!1})],exports.SinglebaseChat.prototype,"renderers",1);m([g.property({attribute:!1})],exports.SinglebaseChat.prototype,"beforeSend",1);m([g.property({attribute:!1})],exports.SinglebaseChat.prototype,"afterParse",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"glow",1);m([g.property({converter:S})],exports.SinglebaseChat.prototype,"followups",1);m([g.property({converter:S,attribute:"show-sources"})],exports.SinglebaseChat.prototype,"showSources",1);m([g.property({converter:S,attribute:"show-new-chat"})],exports.SinglebaseChat.prototype,"showNewChat",1);m([g.property({converter:S,attribute:"show-bookmarked"})],exports.SinglebaseChat.prototype,"showBookmarked",1);m([g.property({converter:S,attribute:"show-followups"})],exports.SinglebaseChat.prototype,"showFollowups",1);m([g.property({converter:S,attribute:"allow-search"})],exports.SinglebaseChat.prototype,"allowSearch",1);m([g.property({converter:S,attribute:"auto-title"})],exports.SinglebaseChat.prototype,"autoTitle",1);m([g.property()],exports.SinglebaseChat.prototype,"model",1);m([g.property({converter:mt})],exports.SinglebaseChat.prototype,"params",1);m([g.property({attribute:"system-message"})],exports.SinglebaseChat.prototype,"systemMessage",1);m([g.property({converter:mt})],exports.SinglebaseChat.prototype,"retrieval",1);m([g.property({converter:mt})],exports.SinglebaseChat.prototype,"metadata",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"embed",1);m([g.property({reflect:!0})],exports.SinglebaseChat.prototype,"position",1);m([g.property({converter:hi})],exports.SinglebaseChat.prototype,"sidebar",1);m([g.property({converter:S,attribute:"show-title"})],exports.SinglebaseChat.prototype,"showTitle",1);m([g.property({attribute:"chat-id"})],exports.SinglebaseChat.prototype,"chatIdAttr",1);m([g.property({attribute:"assistant-name"})],exports.SinglebaseChat.prototype,"assistantName",1);m([g.property({attribute:"logo-url"})],exports.SinglebaseChat.prototype,"logoUrl",1);m([g.property()],exports.SinglebaseChat.prototype,"heading",1);m([g.property()],exports.SinglebaseChat.prototype,"description",1);m([g.property()],exports.SinglebaseChat.prototype,"eyebrow",1);m([g.property()],exports.SinglebaseChat.prototype,"prompts",1);m([g.property({attribute:"bubble-text"})],exports.SinglebaseChat.prototype,"bubbleText",1);m([g.property({type:Boolean,attribute:"greeting-bubble"})],exports.SinglebaseChat.prototype,"greetingBubble",1);m([g.property({type:Boolean,attribute:"unread-badge"})],exports.SinglebaseChat.prototype,"unreadBadge",1);m([g.property({converter:S,attribute:"allow-upload"})],exports.SinglebaseChat.prototype,"allowUpload",1);m([g.property({converter:S,attribute:"allow-export"})],exports.SinglebaseChat.prototype,"allowExport",1);m([g.property({converter:S,attribute:"allow-copy"})],exports.SinglebaseChat.prototype,"allowCopy",1);m([g.property({converter:S,attribute:"allow-regenerate"})],exports.SinglebaseChat.prototype,"allowRegenerate",1);m([g.property({converter:S,attribute:"allow-bookmark"})],exports.SinglebaseChat.prototype,"allowBookmark",1);m([g.property({converter:S,attribute:"allow-delete"})],exports.SinglebaseChat.prototype,"allowDelete",1);m([g.property({converter:S,attribute:"allow-rename"})],exports.SinglebaseChat.prototype,"allowRename",1);m([g.property({converter:S,attribute:"allow-feedback"})],exports.SinglebaseChat.prototype,"allowFeedback",1);m([g.property({converter:S,attribute:"show-composer"})],exports.SinglebaseChat.prototype,"showComposer",1);m([g.property({converter:S,attribute:"show-time"})],exports.SinglebaseChat.prototype,"showTime",1);m([g.property()],exports.SinglebaseChat.prototype,"footnote",1);m([g.property({type:Boolean,attribute:"allow-raw"})],exports.SinglebaseChat.prototype,"allowRaw",1);m([g.property({converter:S})],exports.SinglebaseChat.prototype,"branding",1);m([g.property({attribute:"branding-text"})],exports.SinglebaseChat.prototype,"brandingText",1);m([g.property({attribute:"branding-url"})],exports.SinglebaseChat.prototype,"brandingUrl",1);m([g.state()],exports.SinglebaseChat.prototype,"chatList",1);m([g.state()],exports.SinglebaseChat.prototype,"listState",1);m([g.state()],exports.SinglebaseChat.prototype,"activeId",1);m([g.state()],exports.SinglebaseChat.prototype,"chatTitle",1);m([g.state()],exports.SinglebaseChat.prototype,"bookmarked",1);m([g.state()],exports.SinglebaseChat.prototype,"msgs",1);m([g.state()],exports.SinglebaseChat.prototype,"loadingThread",1);m([g.state()],exports.SinglebaseChat.prototype,"threadError",1);m([g.state()],exports.SinglebaseChat.prototype,"busy",1);m([g.state()],exports.SinglebaseChat.prototype,"draft",1);m([g.state()],exports.SinglebaseChat.prototype,"files",1);m([g.state()],exports.SinglebaseChat.prototype,"search",1);m([g.state()],exports.SinglebaseChat.prototype,"sidebarOpen",1);m([g.state()],exports.SinglebaseChat.prototype,"width",1);m([g.state()],exports.SinglebaseChat.prototype,"panel",1);m([g.state()],exports.SinglebaseChat.prototype,"menuOpen",1);m([g.state()],exports.SinglebaseChat.prototype,"editingKey",1);m([g.state()],exports.SinglebaseChat.prototype,"editDraft",1);m([g.state()],exports.SinglebaseChat.prototype,"editingTitle",1);m([g.state()],exports.SinglebaseChat.prototype,"renamingId",1);m([g.state()],exports.SinglebaseChat.prototype,"toast",1);m([g.state()],exports.SinglebaseChat.prototype,"copiedKey",1);m([g.state()],exports.SinglebaseChat.prototype,"retrievalOpen",1);m([g.state()],exports.SinglebaseChat.prototype,"rawKeys",1);m([g.state()],exports.SinglebaseChat.prototype,"hasSidebarContent",1);m([g.state()],exports.SinglebaseChat.prototype,"sorts",1);m([g.state()],exports.SinglebaseChat.prototype,"arrivedKey",1);m([g.state()],exports.SinglebaseChat.prototype,"dragging",1);m([g.state()],exports.SinglebaseChat.prototype,"showJump",1);m([g.state()],exports.SinglebaseChat.prototype,"offline",1);m([g.state()],exports.SinglebaseChat.prototype,"isOpen",1);m([g.state()],exports.SinglebaseChat.prototype,"expanded",1);m([g.state()],exports.SinglebaseChat.prototype,"bubble",1);m([g.state()],exports.SinglebaseChat.prototype,"seen",1);m([g.state()],exports.SinglebaseChat.prototype,"mobile",1);exports.SinglebaseChat=m([g.customElement("singlebase-chat")],exports.SinglebaseChat);exports.adaptBlocks=Ft;exports.citedNumbers=ut;exports.defaultChatMessages=Nt;exports.describeSource=L;exports.parseInline=Bt;exports.parseMarkdown=Rt;exports.resolveChatMessages=At;exports.settleStreaming=Dt;exports.splitFollowups=gt;exports.svgDataUrl=Ut;
3258
+ //# sourceMappingURL=chat-C-gsskho.cjs.map