quassel 0.1.1 → 0.2.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 (59) hide show
  1. package/ChatInputToolbar.d.ts +35 -6
  2. package/ChatMessages.d.ts +19 -15
  3. package/ChatPanel.d.ts +4 -2
  4. package/ChatSendContext.d.ts +7 -12
  5. package/DetailModeSwitch.d.ts +1 -1
  6. package/Markdown.d.ts +4 -11
  7. package/MessageActions.d.ts +1 -10
  8. package/PendingActionCard.d.ts +13 -0
  9. package/QuasselProvider.d.ts +76 -0
  10. package/README.md +39 -38
  11. package/StepPopover.d.ts +1 -1
  12. package/TimestampSwitch.d.ts +2 -2
  13. package/WorkingScenes.d.ts +3 -1
  14. package/attachments.d.ts +24 -0
  15. package/chat-attachments.d.ts +6 -0
  16. package/chat-scroll.d.ts +12 -0
  17. package/chat.css +2051 -0
  18. package/chunk-IGCFQJZB.js +183 -0
  19. package/chunk-IGCFQJZB.js.map +7 -0
  20. package/events.d.ts +74 -17
  21. package/events.js +11 -1
  22. package/index.d.ts +17 -10
  23. package/index.js +1615 -988
  24. package/index.js.map +4 -4
  25. package/options.d.ts +1 -1
  26. package/package.json +12 -10
  27. package/texts.d.ts +38 -11
  28. package/timestamps.d.ts +6 -4
  29. package/types.d.ts +6 -6
  30. package/ui/button.d.ts +8 -0
  31. package/ui/card.d.ts +5 -0
  32. package/ui/cn.d.ts +2 -0
  33. package/ui/popover.d.ts +4 -0
  34. package/ui/spinner.d.ts +2 -0
  35. package/ui/stop-button.d.ts +10 -0
  36. package/ui/toggle.d.ts +8 -0
  37. package/ui/useFileInput.d.ts +20 -0
  38. package/useChatAction.d.ts +6 -0
  39. package/QuestionCard.d.ts +0 -12
  40. package/chunk-DOLTANTM.js +0 -84
  41. package/chunk-DOLTANTM.js.map +0 -7
  42. package/css/chat.css +0 -927
  43. package/css/foundation/base.css +0 -24
  44. package/css/foundation/index.css +0 -3
  45. package/css/foundation/panel.css +0 -111
  46. package/css/foundation/tokens.css +0 -68
  47. package/css/foundation/wash.css +0 -26
  48. package/css/question.css +0 -149
  49. package/icons.d.ts +0 -15
  50. package/server/http.d.ts +0 -17
  51. package/server/index.d.ts +0 -6
  52. package/server/index.js +0 -478
  53. package/server/index.js.map +0 -7
  54. package/server/manager.d.ts +0 -12
  55. package/server/openai.d.ts +0 -16
  56. package/server/session.d.ts +0 -27
  57. package/server/store.d.ts +0 -18
  58. package/server/types.d.ts +0 -62
  59. package/useChat.d.ts +0 -14
package/css/chat.css DELETED
@@ -1,927 +0,0 @@
1
- /* Chat-Bausteine auf Basis der foundation-Tokens. */
2
- @import "./foundation/tokens.css";
3
- /* Die Rückfrage-Karte (QuestionCard). */
4
- @import "./question.css";
5
-
6
- /* Eigenes Fundament, damit die Bausteine ohne foundation/base.css eines Hosts tragen. */
7
- :is(.qsl-chat-panel, .qsl-chat-wrap, .qsl-input-card, .qsl-popover, .qsl-popover-backdrop),
8
- :is(.qsl-chat-panel, .qsl-chat-wrap, .qsl-input-card, .qsl-popover, .qsl-popover-backdrop) * {
9
- box-sizing: border-box;
10
- }
11
-
12
- /* Waagerechte Rollbalken bleiben sichtbar - sonst ist der Ueberlauf nicht auffindbar. */
13
- :is(.qsl-md-scroll, .qsl-md pre) {
14
- scrollbar-width: thin;
15
- }
16
-
17
- :is(.qsl-md-scroll, .qsl-md pre)::-webkit-scrollbar {
18
- display: block;
19
- height: 8px;
20
- }
21
-
22
- :is(.qsl-md-scroll, .qsl-md pre)::-webkit-scrollbar-thumb {
23
- border-radius: 999px;
24
- background: var(--qsl-line);
25
- }
26
-
27
- .qsl-chat-panel {
28
- --qsl-thread-pad-bottom: calc(var(--qsl-composer-height, 0px) + 16px);
29
- --qsl-jump-bottom: calc(var(--qsl-composer-height, 0px) + 12px);
30
- position: relative;
31
- display: flex;
32
- flex-direction: column;
33
- min-width: 0;
34
- min-height: 0;
35
- overflow: hidden;
36
- }
37
-
38
- .qsl-chat-panel__composer {
39
- position: absolute;
40
- z-index: 5;
41
- right: 0;
42
- bottom: 0;
43
- left: 0;
44
- }
45
-
46
- .qsl-chat-wrap {
47
- container: qsl-chat / inline-size;
48
- position: relative;
49
- flex: 1;
50
- min-height: 0;
51
- display: flex;
52
- flex-direction: column;
53
- }
54
-
55
- .qsl-chat {
56
- flex: 1;
57
- min-height: 0;
58
- overflow-y: auto;
59
- font-family: var(--qsl-font);
60
- font-size: var(--qsl-chat-font-size, 13px);
61
- color: var(--qsl-ink);
62
- }
63
-
64
- .qsl-thread {
65
- width: 100%;
66
- max-width: var(--qsl-thread-max-width, none);
67
- margin: 0 auto;
68
- padding: 8px var(--qsl-thread-padding-inline, 0px) var(--qsl-thread-pad-bottom, 40px);
69
- }
70
-
71
- .qsl-step {
72
- display: block;
73
- margin-top: var(--qsl-message-gap, 16px);
74
- }
75
-
76
- .qsl-step--dense {
77
- margin-top: var(--qsl-dense-message-gap, 8px);
78
- }
79
-
80
- /* Optionale Zeitspalte: schmal, tabellarische Ziffern, bewusst zurueckhaltend. */
81
-
82
- .qsl-line {
83
- display: flex;
84
- gap: 8px;
85
- align-items: flex-start;
86
- margin-top: var(--qsl-message-gap, 16px);
87
- }
88
-
89
- /* Der Zeilenabstand haengt an der Zeile statt am ersten Schritt: so fluchtet die Zeit mit dem Text. */
90
- .qsl-line:has(> .qsl-line-body > .qsl-step--dense:first-child) {
91
- margin-top: var(--qsl-dense-message-gap, 8px);
92
- }
93
-
94
- .qsl-line > .qsl-line-body > .qsl-step:first-child {
95
- margin-top: 0;
96
- }
97
-
98
- .qsl-line > .qsl-time {
99
- flex-shrink: 0;
100
- width: 34px;
101
- padding-top: 2px;
102
- color: var(--qsl-muted);
103
- font-size: 10.5px;
104
- font-variant-numeric: tabular-nums;
105
- opacity: 0.85;
106
- }
107
-
108
- .qsl-line-body {
109
- flex: 1;
110
- min-width: 0;
111
- }
112
-
113
- .qsl-user {
114
- display: flex;
115
- justify-content: flex-end;
116
- }
117
-
118
- .qsl-user > div {
119
- max-width: 86%;
120
- padding: 8px 12px;
121
- border-radius: var(--qsl-radius);
122
- background: var(--qsl-accent);
123
- color: #ffffff;
124
- line-height: var(--qsl-chat-line-height, 1.625);
125
- overflow-wrap: anywhere;
126
- }
127
-
128
- /* Farbige Sprechblasen (Mehrparteien): Seite und Farbe kommen aus Message.bubble. */
129
-
130
- .qsl-bubble {
131
- display: flex;
132
- justify-content: flex-start;
133
- }
134
-
135
- .qsl-bubble--end {
136
- justify-content: flex-end;
137
- }
138
-
139
- .qsl-bubble > div {
140
- max-width: 86%;
141
- padding: 8px 12px;
142
- border-radius: var(--qsl-radius);
143
- color: #ffffff;
144
- line-height: var(--qsl-chat-line-height, 1.625);
145
- overflow-wrap: anywhere;
146
- }
147
-
148
- .qsl-bubble__label {
149
- display: table;
150
- margin-bottom: 5px;
151
- padding: 1px 7px;
152
- border: 1px solid rgba(255, 255, 255, 0.32);
153
- border-radius: 999px;
154
- background: rgba(0, 0, 0, 0.14);
155
- font-size: 0.72rem;
156
- font-weight: 600;
157
- letter-spacing: 0.02em;
158
- line-height: 1.45;
159
- }
160
-
161
- /* Markdown in farbigen Bubbles: weiss auf Farbe, Code und Links bleiben lesbar. */
162
-
163
- .qsl-user .qsl-md,
164
- .qsl-bubble > div .qsl-md {
165
- color: inherit;
166
- }
167
-
168
- .qsl-user .qsl-md-scroll,
169
- .qsl-bubble > div .qsl-md-scroll {
170
- --qsl-scroll-cover: var(--qsl-accent);
171
- }
172
-
173
- .qsl-user .qsl-md a,
174
- .qsl-bubble > div .qsl-md a {
175
- color: inherit;
176
- text-decoration: underline;
177
- }
178
-
179
- .qsl-user .qsl-md code,
180
- .qsl-bubble > div .qsl-md code {
181
- background: rgba(255, 255, 255, 0.18);
182
- color: inherit;
183
- }
184
-
185
- .qsl-user .qsl-md pre,
186
- .qsl-bubble > div .qsl-md pre {
187
- background: rgba(0, 0, 0, 0.28);
188
- color: inherit;
189
- }
190
-
191
- .qsl-user .qsl-md blockquote,
192
- .qsl-bubble > div .qsl-md blockquote {
193
- border-left-color: rgba(255, 255, 255, 0.5);
194
- color: inherit;
195
- }
196
-
197
- .qsl-user .qsl-md-bullet > span:first-child,
198
- .qsl-bubble > div .qsl-md-bullet > span:first-child {
199
- color: inherit;
200
- }
201
-
202
- .qsl-user .qsl-md th,
203
- .qsl-bubble > div .qsl-md th {
204
- background: rgba(255, 255, 255, 0.14);
205
- color: inherit;
206
- }
207
-
208
- .qsl-user .qsl-md th,
209
- .qsl-user .qsl-md td,
210
- .qsl-bubble > div .qsl-md th,
211
- .qsl-bubble > div .qsl-md td {
212
- border-color: rgba(255, 255, 255, 0.35);
213
- }
214
-
215
- .qsl-answer {
216
- max-width: 100%;
217
- line-height: var(--qsl-chat-line-height, 1.625);
218
- color: var(--qsl-ink);
219
- }
220
-
221
- .qsl-system {
222
- padding-left: 12px;
223
- border-left: 2px solid color-mix(in srgb, var(--qsl-danger) 50%, transparent);
224
- font-size: 12px;
225
- color: var(--qsl-muted);
226
- }
227
-
228
- .qsl-trace {
229
- display: flex;
230
- gap: 8px;
231
- width: 100%;
232
- padding: 0 0 0 24px;
233
- border: 0;
234
- background: none;
235
- text-align: left;
236
- font-family: inherit;
237
- font-size: 11px;
238
- line-height: 1.375;
239
- color: var(--qsl-muted);
240
- }
241
-
242
- button.qsl-trace {
243
- padding: 4px 8px 4px 24px;
244
- border-radius: 6px;
245
- cursor: pointer;
246
- transition: background-color .12s ease, color .12s ease;
247
- }
248
-
249
- button.qsl-trace:hover,
250
- button.qsl-trace:focus-visible {
251
- background: var(--qsl-surface);
252
- color: var(--qsl-ink);
253
- outline: none;
254
- }
255
-
256
- .qsl-trace__icon {
257
- flex: 0 0 auto;
258
- margin-top: 2px;
259
- opacity: .6;
260
- }
261
-
262
- .qsl-trace__icon--error {
263
- color: var(--qsl-danger);
264
- opacity: 1;
265
- }
266
-
267
- .qsl-trace__body {
268
- min-width: 0;
269
- flex: 1;
270
- }
271
-
272
- .qsl-trace__line {
273
- min-width: 0;
274
- font-family: var(--qsl-mono);
275
- overflow-wrap: anywhere;
276
- }
277
-
278
- .qsl-trace--compact .qsl-trace__line {
279
- overflow: hidden;
280
- text-overflow: ellipsis;
281
- white-space: nowrap;
282
- }
283
-
284
- .qsl-trace--thinking .qsl-trace__line {
285
- font-family: inherit;
286
- font-style: italic;
287
- white-space: pre-wrap;
288
- }
289
-
290
- .qsl-trace--compact.qsl-trace--thinking .qsl-trace__line {
291
- white-space: nowrap;
292
- }
293
-
294
- .qsl-trace__running {
295
- margin-left: 6px;
296
- opacity: .6;
297
- }
298
-
299
- /* --- Schritte gruppiert: Kopfzeile klappt die einzeiligen Schritte auf und zu --- */
300
-
301
- button.qsl-stepgroup__toggle {
302
- align-items: center;
303
- padding-left: 4px;
304
- }
305
-
306
- .qsl-stepgroup__chevron {
307
- flex: 0 0 auto;
308
- opacity: .6;
309
- transition: transform .12s ease;
310
- }
311
-
312
- .qsl-stepgroup__toggle[aria-expanded="true"] > .qsl-stepgroup__chevron {
313
- transform: rotate(90deg);
314
- }
315
-
316
- .qsl-stepgroup__collapse > .qsl-stepgroup__chevron {
317
- transform: rotate(-90deg);
318
- }
319
-
320
- .qsl-stepgroup__lines {
321
- display: flex;
322
- flex-direction: column;
323
- gap: 2px;
324
- margin-top: 2px;
325
- }
326
-
327
- /* --- Schritte als Chips: nebeneinander, Umbruch bei Platzmangel --- */
328
-
329
- .qsl-steprow {
330
- display: flex;
331
- flex-wrap: wrap;
332
- align-items: center;
333
- gap: 4px 6px;
334
- padding-left: 24px;
335
- }
336
-
337
- .qsl-chip {
338
- display: inline-flex;
339
- align-items: center;
340
- gap: 5px;
341
- max-width: 220px;
342
- padding: 2px 9px;
343
- border: 1px solid var(--qsl-line-soft);
344
- border-radius: 999px;
345
- background: none;
346
- color: var(--qsl-muted);
347
- font-family: var(--qsl-mono);
348
- font-size: 10.5px;
349
- line-height: 1.6;
350
- cursor: pointer;
351
- transition: background-color .12s ease, color .12s ease, border-color .12s ease;
352
- }
353
-
354
- span.qsl-chip--still,
355
- span.qsl-chip--still:hover {
356
- cursor: default;
357
- background: none;
358
- border-color: var(--qsl-line-soft);
359
- color: var(--qsl-muted);
360
- }
361
-
362
- .qsl-chip:hover,
363
- .qsl-chip:focus-visible {
364
- background: var(--qsl-surface);
365
- border-color: var(--qsl-line);
366
- color: var(--qsl-ink);
367
- outline: none;
368
- }
369
-
370
- .qsl-chip--icon {
371
- padding: 4px;
372
- }
373
-
374
- .qsl-chip__label {
375
- min-width: 0;
376
- overflow: hidden;
377
- text-overflow: ellipsis;
378
- white-space: nowrap;
379
- }
380
-
381
- /* Fixed slot for the state mark, so a state change never resizes the chip. */
382
- .qsl-chip__state {
383
- flex: none;
384
- display: inline-flex;
385
- align-items: center;
386
- justify-content: center;
387
- width: 10px;
388
- color: var(--qsl-success);
389
- }
390
-
391
- .qsl-chip__icon--error {
392
- color: var(--qsl-danger);
393
- }
394
-
395
- /* The four step states; doubled class beats the border of the non-clickable chip. */
396
-
397
- .qsl-chip.qsl-chip--running,
398
- .qsl-chip.qsl-chip--thinking {
399
- border-color: color-mix(in srgb, var(--qsl-accent) 40%, var(--qsl-line-soft));
400
- }
401
-
402
- .qsl-chip.qsl-chip--error {
403
- border-color: color-mix(in srgb, var(--qsl-danger) 45%, var(--qsl-line-soft));
404
- }
405
-
406
- .qsl-chip--done {
407
- opacity: .85;
408
- }
409
-
410
- .qsl-chip--done:hover,
411
- .qsl-chip--done:focus-visible {
412
- opacity: 1;
413
- }
414
-
415
- .qsl-icon-button--active {
416
- color: var(--qsl-ink);
417
- background: var(--qsl-surface);
418
- }
419
-
420
- .qsl-details {
421
- margin-top: 2px;
422
- padding-left: 8px;
423
- border-left: 2px solid var(--qsl-line-soft);
424
- }
425
-
426
- .qsl-details pre {
427
- margin: 0 0 2px;
428
- max-height: 208px;
429
- overflow: auto;
430
- font-family: var(--qsl-mono);
431
- font-size: 10.5px;
432
- line-height: 1.375;
433
- white-space: pre-wrap;
434
- word-break: break-all;
435
- opacity: .8;
436
- }
437
-
438
- .qsl-details pre.qsl-details__pre--error {
439
- color: var(--qsl-danger);
440
- opacity: 1;
441
- }
442
-
443
- .qsl-busy {
444
- margin-top: var(--qsl-message-gap, 16px);
445
- font-size: 11px;
446
- color: var(--qsl-muted);
447
- animation: qsl-pulse 1.9s cubic-bezier(0.2, 0.6, 0.35, 1) infinite;
448
- }
449
-
450
- /* Der Default-Working-Indikator: kleine Text-Szenen auf fester Buehne. */
451
- .qsl-working {
452
- margin-top: var(--qsl-message-gap, 16px);
453
- display: flex;
454
- align-items: center;
455
- gap: 10px;
456
- font-size: var(--qsl-chat-font-size, 13px);
457
- color: var(--qsl-ink);
458
- }
459
-
460
- .qsl-working::before {
461
- content: ">";
462
- color: var(--qsl-muted);
463
- opacity: 0.7;
464
- }
465
-
466
- .qsl-working__stage {
467
- display: inline-block;
468
- width: 15rem;
469
- flex-shrink: 0;
470
- font-family: ui-monospace, "SF Mono", monospace;
471
- font-variant-ligatures: none;
472
- }
473
-
474
- /* Die Bewegung steckt im Text selbst - jede Szene zeichnet ihre Zeile neu. */
475
- .qsl-working__character {
476
- white-space: pre;
477
- letter-spacing: 0.02em;
478
- }
479
-
480
- /* Eine Zelle je Figur: Emoji laufen breiter als Satzzeichen, ohne festes Raster
481
- wuerde eine Figur bei jedem Bildwechsel vor- und zurueckspringen. */
482
- .qsl-working__cell {
483
- display: inline-block;
484
- width: 1.35em;
485
- text-align: center;
486
- }
487
-
488
- @media (prefers-reduced-motion: reduce) {
489
- .qsl-working__character {
490
- opacity: 0.6;
491
- }
492
- }
493
-
494
- .qsl-jump {
495
- pointer-events: none;
496
- position: absolute;
497
- right: 0;
498
- bottom: var(--qsl-jump-bottom, 12px);
499
- left: 0;
500
- z-index: 10;
501
- display: flex;
502
- justify-content: center;
503
- }
504
-
505
- .qsl-jump button {
506
- pointer-events: auto;
507
- display: grid;
508
- place-items: center;
509
- width: 36px;
510
- height: 36px;
511
- border: 1px solid var(--qsl-line);
512
- border-radius: 50%;
513
- background: var(--qsl-content);
514
- color: var(--qsl-muted);
515
- cursor: pointer;
516
- box-shadow: var(--qsl-shadow-bar);
517
- transition: color .12s ease;
518
- }
519
-
520
- .qsl-jump button:hover {
521
- color: var(--qsl-ink);
522
- }
523
-
524
- /* --- Popover fuer Denk- und Werkzeug-Details --- */
525
-
526
- .qsl-popover-backdrop {
527
- position: fixed;
528
- inset: 0;
529
- z-index: 30;
530
- }
531
-
532
- .qsl-popover {
533
- position: fixed;
534
- z-index: 40;
535
- display: flex;
536
- flex-direction: column;
537
- max-height: min(70vh, 620px);
538
- width: min(680px, calc(100vw - 32px));
539
- overflow: hidden;
540
- border: 1px solid var(--qsl-line);
541
- border-radius: var(--qsl-radius-large);
542
- background: var(--qsl-content);
543
- box-shadow: var(--qsl-shadow-pop);
544
- font-family: var(--qsl-font);
545
- font-size: var(--qsl-chat-font-size, 13px);
546
- color: var(--qsl-ink);
547
- }
548
-
549
- .qsl-popover__head {
550
- display: flex;
551
- align-items: center;
552
- gap: 8px;
553
- flex-shrink: 0;
554
- padding: 10px 16px;
555
- border-bottom: 1px solid var(--qsl-line-soft);
556
- }
557
-
558
- .qsl-popover__icon {
559
- color: var(--qsl-muted);
560
- }
561
-
562
- .qsl-popover__icon--error {
563
- color: var(--qsl-danger);
564
- }
565
-
566
- .qsl-popover__title {
567
- min-width: 0;
568
- flex: 1;
569
- overflow: hidden;
570
- text-overflow: ellipsis;
571
- white-space: nowrap;
572
- font-weight: 500;
573
- }
574
-
575
- .qsl-popover__close {
576
- display: grid;
577
- place-items: center;
578
- width: 28px;
579
- height: 28px;
580
- flex-shrink: 0;
581
- border: 0;
582
- border-radius: var(--qsl-radius);
583
- background: none;
584
- color: var(--qsl-muted);
585
- cursor: pointer;
586
- transition: background-color .12s ease, color .12s ease;
587
- }
588
-
589
- .qsl-popover__close:hover {
590
- background: var(--qsl-surface);
591
- color: var(--qsl-ink);
592
- }
593
-
594
- .qsl-popover__body {
595
- min-height: 0;
596
- overflow: auto;
597
- padding: 16px;
598
- }
599
-
600
- .qsl-popover__thinking {
601
- white-space: pre-wrap;
602
- font-size: 12px;
603
- line-height: var(--qsl-chat-line-height, 1.625);
604
- }
605
-
606
- .qsl-popover__sections {
607
- display: flex;
608
- flex-direction: column;
609
- gap: 16px;
610
- }
611
-
612
- .qsl-popover__toolname {
613
- font-family: var(--qsl-mono);
614
- font-size: 12px;
615
- }
616
-
617
- .qsl-popover__sections h3 {
618
- margin: 0 0 6px;
619
- font-size: 11px;
620
- font-weight: 600;
621
- text-transform: uppercase;
622
- letter-spacing: .04em;
623
- color: var(--qsl-muted);
624
- }
625
-
626
- .qsl-popover__pre {
627
- margin: 0;
628
- padding: 12px;
629
- border-radius: var(--qsl-radius);
630
- background: var(--qsl-surface);
631
- font-family: var(--qsl-mono);
632
- font-size: 11px;
633
- line-height: var(--qsl-chat-line-height, 1.625);
634
- white-space: pre-wrap;
635
- word-break: break-all;
636
- }
637
-
638
- .qsl-popover__pre--error {
639
- color: var(--qsl-danger);
640
- }
641
-
642
- .qsl-popover__running {
643
- font-size: 12px;
644
- color: var(--qsl-muted);
645
- }
646
-
647
- /* --- Eingabe-Karte: Textarea oben, Toolbar unter der Haarlinie --- */
648
-
649
- .qsl-input-card {
650
- display: flex;
651
- flex-direction: column;
652
- flex-shrink: 0;
653
- border: 1px solid var(--qsl-line);
654
- border-radius: var(--qsl-input-card-radius, var(--qsl-radius-large));
655
- background: var(--qsl-content);
656
- overflow: hidden;
657
- font-family: var(--qsl-font);
658
- transition: border-color .12s ease;
659
- }
660
-
661
- .qsl-input-card:focus-within {
662
- border-color: var(--qsl-accent);
663
- }
664
-
665
- .qsl-input-card textarea {
666
- resize: none;
667
- border: none;
668
- background: transparent;
669
- padding: 12px 12px 8px;
670
- color: var(--qsl-ink);
671
- font: inherit;
672
- font-size: var(--qsl-chat-font-size, 13px);
673
- line-height: var(--qsl-chat-line-height, 1.5);
674
- }
675
-
676
- .qsl-input-card textarea:focus {
677
- outline: none;
678
- }
679
-
680
- .qsl-input-card textarea::placeholder {
681
- color: var(--qsl-muted);
682
- }
683
-
684
- /* Eine Zeile, die nie umbricht: links waechst, rechts schrumpft, Senden bleibt immer da. */
685
- .qsl-input-card__toolbar {
686
- display: flex;
687
- flex-wrap: nowrap;
688
- align-items: center;
689
- gap: 8px;
690
- padding: 6px 8px;
691
- border-top: 1px solid var(--qsl-line-soft);
692
- }
693
-
694
- .qsl-input-card__left {
695
- flex: 1 1 auto;
696
- }
697
-
698
- .qsl-input-card__right {
699
- flex: 0 1 auto;
700
- }
701
-
702
- .qsl-input-card__left,
703
- .qsl-input-card__right {
704
- display: flex;
705
- align-items: center;
706
- gap: 8px;
707
- min-width: 0;
708
- }
709
-
710
- .qsl-input-card--compact .qsl-collapsible {
711
- display: none;
712
- }
713
-
714
- .qsl-icon-button {
715
- display: inline-flex;
716
- align-items: center;
717
- justify-content: center;
718
- gap: 5px;
719
- height: 28px;
720
- min-width: 28px;
721
- padding: 0 5px;
722
- flex-shrink: 0;
723
- border: none;
724
- border-radius: var(--qsl-radius);
725
- background: transparent;
726
- color: var(--qsl-muted);
727
- font: inherit;
728
- font-size: 11px;
729
- cursor: pointer;
730
- transition: background-color .12s ease, color .12s ease;
731
- }
732
-
733
- .qsl-icon-button:hover:not(:disabled) {
734
- color: var(--qsl-ink);
735
- background: var(--qsl-surface);
736
- }
737
-
738
- .qsl-icon-button:disabled {
739
- opacity: 0.4;
740
- cursor: default;
741
- }
742
-
743
- .qsl-send {
744
- display: inline-flex;
745
- align-items: center;
746
- justify-content: center;
747
- width: 28px;
748
- height: 28px;
749
- flex-shrink: 0;
750
- border: none;
751
- border-radius: 999px;
752
- background: var(--qsl-accent);
753
- color: #ffffff;
754
- cursor: pointer;
755
- transition: opacity .12s ease;
756
- }
757
-
758
- .qsl-send:disabled {
759
- opacity: 0.35;
760
- cursor: default;
761
- }
762
-
763
- .qsl-send--stop {
764
- background: var(--qsl-surface);
765
- color: var(--qsl-ink);
766
- }
767
-
768
- /* --- Markdown --- */
769
-
770
- .qsl-md > *:first-child {
771
- margin-top: 0;
772
- }
773
-
774
- /* h1/h2 mitnehmen, sonst erbt der Chat die Ueberschriften der Gastseite. */
775
- .qsl-md h1,
776
- .qsl-md h2,
777
- .qsl-md h3 {
778
- margin: 12px 0 4px;
779
- font-family: inherit;
780
- font-size: 15px;
781
- font-weight: 500;
782
- }
783
-
784
- .qsl-md h1 {
785
- font-size: 16px;
786
- font-weight: 600;
787
- }
788
-
789
- .qsl-md h4 {
790
- margin: 8px 0 4px;
791
- font-size: 14px;
792
- font-weight: 500;
793
- }
794
-
795
- .qsl-md p {
796
- margin: 0;
797
- }
798
-
799
- .qsl-md-gap {
800
- height: 8px;
801
- }
802
-
803
- .qsl-md-bullet {
804
- display: flex;
805
- gap: 8px;
806
- }
807
-
808
- .qsl-md-bullet > span:first-child {
809
- color: var(--qsl-muted);
810
- font-variant-numeric: tabular-nums;
811
- }
812
-
813
- .qsl-md-bullet > span:last-child {
814
- min-width: 0;
815
- }
816
-
817
- .qsl-md blockquote {
818
- margin: 4px 0;
819
- padding-left: 12px;
820
- border-left: 2px solid var(--qsl-line);
821
- color: var(--qsl-muted);
822
- }
823
-
824
- .qsl-md a {
825
- color: var(--qsl-accent);
826
- text-underline-offset: 2px;
827
- }
828
-
829
- .qsl-md strong {
830
- font-weight: 500;
831
- }
832
-
833
- .qsl-md code {
834
- padding: 2px 4px;
835
- border-radius: var(--qsl-radius-small);
836
- background: var(--qsl-surface);
837
- font-family: var(--qsl-mono);
838
- font-size: 12px;
839
- overflow-wrap: anywhere;
840
- }
841
-
842
- .qsl-md pre {
843
- margin: 8px 0;
844
- padding: 8px 12px;
845
- border-radius: var(--qsl-radius);
846
- background: var(--qsl-surface);
847
- font-family: var(--qsl-mono);
848
- font-size: 12px;
849
- line-height: var(--qsl-chat-line-height, 1.625);
850
- overflow-x: auto;
851
- }
852
-
853
- .qsl-md pre code {
854
- padding: 0;
855
- background: none;
856
- }
857
-
858
- .qsl-md-scroll {
859
- margin: 8px 0;
860
- overflow-x: auto;
861
- background:
862
- linear-gradient(to right, var(--qsl-scroll-cover, var(--qsl-content)) 50%, transparent) left / 20px 100% no-repeat local,
863
- linear-gradient(to left, var(--qsl-scroll-cover, var(--qsl-content)) 50%, transparent) right / 20px 100% no-repeat local,
864
- linear-gradient(to right, rgba(0, 0, 0, 0.28), transparent) left / 14px 100% no-repeat scroll,
865
- linear-gradient(to left, rgba(0, 0, 0, 0.28), transparent) right / 14px 100% no-repeat scroll;
866
- }
867
-
868
- /* Ohne max-content schrumpft die Tabelle auf den Container und stapelt Buchstaben. */
869
- .qsl-md table {
870
- width: max-content;
871
- min-width: 100%;
872
- border-collapse: collapse;
873
- font-size: 12px;
874
- }
875
-
876
- .qsl-md th,
877
- .qsl-md td {
878
- max-width: 44ch;
879
- border: 1px solid var(--qsl-line);
880
- padding: 4px 8px;
881
- text-align: left;
882
- vertical-align: top;
883
- }
884
-
885
- .qsl-md th {
886
- background: var(--qsl-surface);
887
- font-weight: 500;
888
- }
889
-
890
- @container qsl-chat (max-width: 620px) {
891
- .qsl-user > div,
892
- .qsl-bubble > div,
893
- .qsl-answer {
894
- max-width: 100%;
895
- }
896
- }
897
-
898
- .qsl-message-actions {
899
- display: flex;
900
- flex-wrap: wrap;
901
- align-items: center;
902
- gap: 4px;
903
- margin-top: 4px;
904
- }
905
-
906
- .qsl-action-error {
907
- color: var(--qsl-danger);
908
- font-size: 12px;
909
- overflow-wrap: anywhere;
910
- }
911
-
912
- .qsl-day-separator {
913
- margin-top: var(--qsl-message-gap, 16px);
914
- padding: 8px 0;
915
- border-bottom: 1px solid var(--qsl-line-soft);
916
- color: var(--qsl-muted);
917
- font-size: 12px;
918
- text-align: center;
919
- }
920
-
921
- .qsl-code-block {
922
- margin: 8px 0;
923
- }
924
-
925
- .qsl-code-block > pre {
926
- margin-top: 4px;
927
- }