@helpway/react 0.1.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.
@@ -0,0 +1,3475 @@
1
+ /* ═══ Helpway Widget — Premium Intercom-Style ═══
2
+ Vanilla CSS for Shadow DOM. Gradient hero, card-based actions,
3
+ avatar-first conversation rows, bottom tab navigation. */
4
+
5
+ /* ── Reset ─────────────────────────────────────── */
6
+ :host {
7
+ all: initial;
8
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
9
+ sans-serif;
10
+ font-size: 14px;
11
+ line-height: 1.5;
12
+ color: #1a1a1a;
13
+ -webkit-font-smoothing: antialiased;
14
+ -moz-osx-font-smoothing: grayscale;
15
+ }
16
+
17
+ .hw-widget *,
18
+ .hw-widget *::before,
19
+ .hw-widget *::after {
20
+ box-sizing: border-box;
21
+ margin: 0;
22
+ padding: 0;
23
+ }
24
+
25
+ /* ── Tokens ────────────────────────────────────── */
26
+ .hw-widget {
27
+ --hw-primary: #171717;
28
+ --hw-primary-hover: #2a2a2a;
29
+ /* Focus ring tokens — used by composer + content search + any future
30
+ input. Kept as variables so the dark override gets a proper contrast
31
+ pair instead of a one-off per-component tweak. */
32
+ --hw-focus-border: #9ca3af;
33
+ --hw-focus-ring: rgba(0, 0, 0, 0.06);
34
+ --hw-accent: #6366f1;
35
+ --hw-bg: #ffffff;
36
+ --hw-bg-subtle: #fafafa;
37
+ --hw-bg-hover: #f5f5f5;
38
+ --hw-border: #f0f0f0;
39
+ --hw-border-md: #e5e5e5;
40
+ --hw-text: #111;
41
+ --hw-text-1: #111;
42
+ --hw-text-2: #666;
43
+ --hw-text-3: #999;
44
+ --hw-text-4: #bbb;
45
+ --hw-radius: 16px;
46
+ --hw-visitor-bubble-bg: #f0f0f0;
47
+ --hw-visitor-bubble-text: #1a1a1a;
48
+ --hw-font: inherit;
49
+ }
50
+
51
+ /* ── Agent Avatar Image / Icon ────────────────── */
52
+ .hw-agent-img {
53
+ width: 100%;
54
+ height: 100%;
55
+ object-fit: cover;
56
+ }
57
+ .hw-agent-icon {
58
+ width: 100%;
59
+ height: 100%;
60
+ border-radius: inherit;
61
+ }
62
+
63
+ /* ── Focus Styles ──────────────────────────────── */
64
+ .hw-widget :focus-visible {
65
+ outline: 2px solid var(--hw-primary);
66
+ outline-offset: 2px;
67
+ }
68
+
69
+ .hw-widget :focus:not(:focus-visible) {
70
+ outline: none;
71
+ }
72
+
73
+ /* ── Widget Container ─────────────────────────── */
74
+ .hw-widget {
75
+ position: fixed;
76
+ bottom: 20px;
77
+ right: var(--hw-position-right, 20px);
78
+ left: var(--hw-position-left, auto);
79
+ z-index: 999999;
80
+ font-family: var(--hw-font);
81
+ }
82
+
83
+ /* ════════════════════════════════════════════════
84
+ BUBBLE (FAB)
85
+ ════════════════════════════════════════════════ */
86
+
87
+ .hw-bubble {
88
+ width: 48px;
89
+ height: 48px;
90
+ border-radius: 14px;
91
+ background: var(--hw-primary);
92
+ color: white;
93
+ border: none;
94
+ cursor: pointer;
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
99
+ transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease;
100
+ position: relative;
101
+ overflow: visible;
102
+ }
103
+
104
+ /* bubbleStyle variants — override border-radius */
105
+ .hw-bubble--rounded {
106
+ border-radius: 14px;
107
+ }
108
+ .hw-bubble--square {
109
+ border-radius: 8px;
110
+ }
111
+ .hw-bubble--pill {
112
+ border-radius: 24px;
113
+ }
114
+
115
+ /* launcherStyle: bubble / help — wider pill with icon + label side by side */
116
+ .hw-bubble--launcher-bubble,
117
+ .hw-bubble--launcher-help {
118
+ width: auto;
119
+ padding: 0 16px 0 12px;
120
+ gap: 8px;
121
+ border-radius: 24px; /* pill shape for labelled launcher */
122
+ }
123
+
124
+ /* When bubbleStyle is square or rounded on a labelled launcher, respect shape */
125
+ .hw-bubble--launcher-bubble.hw-bubble--square,
126
+ .hw-bubble--launcher-help.hw-bubble--square {
127
+ border-radius: 8px;
128
+ }
129
+ .hw-bubble--launcher-bubble.hw-bubble--rounded,
130
+ .hw-bubble--launcher-help.hw-bubble--rounded {
131
+ border-radius: 14px;
132
+ }
133
+
134
+ /* Label text inside the launcher */
135
+ .hw-bubble-label {
136
+ font-size: 14px;
137
+ font-weight: 600;
138
+ white-space: nowrap;
139
+ line-height: 1;
140
+ /* not absolute-positioned, flows next to icons in flex row */
141
+ position: static;
142
+ opacity: 1;
143
+ transform: none;
144
+ }
145
+
146
+ /* Icons become static (not absolute) in labelled launcher so label can sit beside them */
147
+ .hw-bubble--launcher-bubble .hw-bubble-icon,
148
+ .hw-bubble--launcher-help .hw-bubble-icon {
149
+ position: static;
150
+ }
151
+
152
+ .hw-bubble:hover {
153
+ transform: scale(1.05);
154
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
155
+ }
156
+
157
+ .hw-bubble:active {
158
+ transform: scale(0.95);
159
+ }
160
+
161
+ .hw-bubble--open {
162
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
163
+ }
164
+
165
+ .hw-bubble:focus-visible {
166
+ outline: 2px solid white;
167
+ outline-offset: 2px;
168
+ }
169
+
170
+ .hw-bubble-icon {
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: center;
174
+ position: absolute;
175
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
176
+ }
177
+
178
+ .hw-bubble-icon svg {
179
+ width: 22px;
180
+ height: 22px;
181
+ }
182
+
183
+ .hw-bubble-icon--hidden {
184
+ transform: scale(0.3) rotate(90deg);
185
+ opacity: 0;
186
+ }
187
+
188
+ /* Bot icon — static brand mark, no rotation */
189
+ .hw-bubble-icon--bot {
190
+ /* Rotation removed: the launcher bubble should feel stable and
191
+ intentional; the previous 8s slow spin read as "loading" to some
192
+ visitors and added visual noise on every page load. */
193
+ }
194
+
195
+ /* When agent has a custom avatar image — fill the bubble */
196
+ .hw-bubble--avatar .hw-bubble-icon--bot {
197
+ width: 100%;
198
+ height: 100%;
199
+ }
200
+ .hw-bubble--avatar .hw-bubble-icon--bot .hw-agent-img {
201
+ width: 100%;
202
+ height: 100%;
203
+ border-radius: 0; /* bubble itself handles rounding */
204
+ }
205
+
206
+ .hw-bubble-icon--close svg {
207
+ width: 22px;
208
+ height: 22px;
209
+ }
210
+
211
+ .hw-bubble-badge {
212
+ position: absolute;
213
+ top: -4px;
214
+ right: -4px;
215
+ min-width: 20px;
216
+ height: 20px;
217
+ border-radius: 10px;
218
+ background: var(--hw-primary);
219
+ color: white;
220
+ font-size: 11px;
221
+ font-weight: 700;
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ padding: 0 5px;
226
+ border: 2px solid white;
227
+ animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
228
+ }
229
+
230
+ @keyframes hw-badge-pop {
231
+ from {
232
+ transform: scale(0);
233
+ }
234
+ to {
235
+ transform: scale(1);
236
+ }
237
+ }
238
+
239
+ .hw-bubble-badge::after {
240
+ content: "";
241
+ position: absolute;
242
+ inset: -2px;
243
+ border-radius: inherit;
244
+ background: var(--hw-primary);
245
+ opacity: 0;
246
+ animation: hw-badge-pulse 2s ease-out infinite;
247
+ }
248
+
249
+ @keyframes hw-badge-pulse {
250
+ 0% {
251
+ opacity: 0.5;
252
+ transform: scale(1);
253
+ }
254
+ 100% {
255
+ opacity: 0;
256
+ transform: scale(1.8);
257
+ }
258
+ }
259
+
260
+ /* ════════════════════════════════════════════════
261
+ CHAT WINDOW
262
+ ════════════════════════════════════════════════ */
263
+
264
+ .hw-window {
265
+ position: absolute;
266
+ bottom: 72px;
267
+ right: var(--hw-window-right, 0);
268
+ left: var(--hw-window-left, auto);
269
+ width: 440px;
270
+ height: 640px;
271
+ background: var(--hw-bg-subtle);
272
+ /* Explicit text color so the host page's Tailwind / shadcn `color:
273
+ var(--foreground)` cascade doesn't bleed through — without this,
274
+ dashboard-embedded previews render widget text as the page's
275
+ foreground color instead of the widget theme's --hw-text. */
276
+ color: var(--hw-text);
277
+ border-radius: var(--hw-radius);
278
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);
279
+ display: flex;
280
+ flex-direction: column;
281
+ overflow: hidden;
282
+ animation: hw-window-open 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
283
+ }
284
+
285
+ @keyframes hw-window-open {
286
+ from {
287
+ opacity: 0;
288
+ transform: translateY(12px) scale(0.96);
289
+ }
290
+ to {
291
+ opacity: 1;
292
+ transform: translateY(0) scale(1);
293
+ }
294
+ }
295
+
296
+ .hw-window--closing {
297
+ animation: hw-window-close 0.2s ease forwards;
298
+ }
299
+
300
+ @keyframes hw-window-close {
301
+ from {
302
+ opacity: 1;
303
+ transform: translateY(0) scale(1);
304
+ }
305
+ to {
306
+ opacity: 0;
307
+ transform: translateY(8px) scale(0.98);
308
+ }
309
+ }
310
+
311
+ /* Content area — fills between header/hero and footer */
312
+ .hw-content {
313
+ flex: 1;
314
+ display: flex;
315
+ flex-direction: column;
316
+ overflow: hidden;
317
+ min-height: 0;
318
+ }
319
+
320
+ /* Reduced motion */
321
+ @media (prefers-reduced-motion: reduce) {
322
+ .hw-window,
323
+ .hw-window--closing,
324
+ .hw-content,
325
+ .hw-msg,
326
+ .hw-bubble-icon,
327
+ .hw-bubble-badge,
328
+ .hw-bubble-badge::after,
329
+ .hw-typing-dot,
330
+ .hw-loading-dot {
331
+ animation-duration: 0.01ms !important;
332
+ transition-duration: 0.01ms !important;
333
+ }
334
+ }
335
+
336
+ /* ════════════════════════════════════════════════
337
+ HERO (Home tab — gradient header + floating cards)
338
+ ════════════════════════════════════════════════ */
339
+
340
+ .hw-hero {
341
+ flex-shrink: 0;
342
+ /* Brand-aware gradient — derives its edges from --hw-primary via
343
+ color-mix() instead of hardcoded neutrals. Previous version had
344
+ #2d2d2d and #1a1a2e at the ends, so a pink or yellow brand color
345
+ read as dark slate at the corners and broke identity. Now: full
346
+ brand at 50% (the visual focal point), darker-mix at both edges
347
+ for depth. Supported: Chrome 111+, Safari 16.2+, Firefox 113+. */
348
+ background: linear-gradient(
349
+ 160deg,
350
+ color-mix(in srgb, var(--hw-primary) 60%, black) 0%,
351
+ var(--hw-primary) 50%,
352
+ color-mix(in srgb, var(--hw-primary) 40%, black) 100%
353
+ );
354
+ color: white;
355
+ padding: 20px 22px 40px; /* reduced — sheet overlap handles spacing */
356
+ }
357
+
358
+ .hw-hero-top {
359
+ display: flex;
360
+ align-items: center;
361
+ justify-content: space-between;
362
+ margin-bottom: 16px;
363
+ }
364
+
365
+ .hw-hero-close {
366
+ width: 30px;
367
+ height: 30px;
368
+ border-radius: 50%;
369
+ border: none;
370
+ background: rgba(255, 255, 255, 0.1);
371
+ color: rgba(255, 255, 255, 0.6);
372
+ cursor: pointer;
373
+ display: flex;
374
+ align-items: center;
375
+ justify-content: center;
376
+ transition: background 0.15s, color 0.15s;
377
+ }
378
+ .hw-hero-close:hover {
379
+ background: rgba(255, 255, 255, 0.2);
380
+ color: white;
381
+ }
382
+ .hw-hero-close:active {
383
+ transform: scale(0.92);
384
+ transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), background 0.15s, color 0.15s;
385
+ }
386
+ .hw-hero-close svg {
387
+ width: 20px;
388
+ height: 20px;
389
+ }
390
+
391
+ .hw-hero-bot-icon {
392
+ width: 36px;
393
+ height: 36px;
394
+ flex-shrink: 0;
395
+ color: white;
396
+ display: flex;
397
+ align-items: center;
398
+ justify-content: center;
399
+ border-radius: 10px;
400
+ overflow: hidden;
401
+ }
402
+ .hw-hero-bot-icon svg {
403
+ width: 32px;
404
+ height: 32px;
405
+ }
406
+
407
+ .hw-hero-greeting {
408
+ font-size: 26px;
409
+ font-weight: 700;
410
+ line-height: 1.15;
411
+ margin-bottom: 6px;
412
+ }
413
+ .hw-hero-greeting-name {
414
+ font-weight: 300;
415
+ }
416
+ .hw-hero-greeting-question {
417
+ font-weight: 700;
418
+ }
419
+ .hw-hero-subtitle {
420
+ font-size: 15px;
421
+ color: rgba(255, 255, 255, 0.5);
422
+ line-height: 1.35;
423
+ }
424
+
425
+ /* ── Content Sheet — overlaps hero, Intercom-style drawer ── */
426
+ .hw-sheet {
427
+ flex: 1;
428
+ overflow-y: auto;
429
+ min-height: 0;
430
+ background: #ffffff;
431
+ border-radius: 20px 20px 0 0;
432
+ margin-top: -24px;
433
+ box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
434
+ position: relative;
435
+ z-index: 1;
436
+ }
437
+
438
+ .hw-sheet-inner {
439
+ padding: 20px 16px;
440
+ display: flex;
441
+ flex-direction: column;
442
+ gap: 12px;
443
+ }
444
+
445
+ /* ════════════════════════════════════════════════
446
+ HEADER (Sub-view / Messages tab — compact 44px)
447
+ ════════════════════════════════════════════════ */
448
+
449
+ .hw-header {
450
+ display: flex;
451
+ align-items: center;
452
+ padding: 12px 16px;
453
+ background: var(--hw-primary);
454
+ color: white;
455
+ flex-shrink: 0;
456
+ gap: 10px;
457
+ }
458
+
459
+ /* Sub-view header (back + identity + close) — transparent */
460
+ .hw-header--sub {
461
+ justify-content: space-between;
462
+ background: transparent;
463
+ color: var(--hw-text);
464
+ border-bottom: 1px solid var(--hw-border);
465
+ }
466
+
467
+ .hw-header-back {
468
+ width: 28px;
469
+ height: 28px;
470
+ border-radius: 8px;
471
+ border: none;
472
+ background: transparent;
473
+ color: var(--hw-text-3);
474
+ cursor: pointer;
475
+ display: flex;
476
+ align-items: center;
477
+ justify-content: center;
478
+ transition: color 0.15s, background 0.15s;
479
+ flex-shrink: 0;
480
+ }
481
+ .hw-header-back svg {
482
+ width: 18px;
483
+ height: 18px;
484
+ }
485
+ .hw-header-back:hover {
486
+ color: var(--hw-text);
487
+ background: var(--hw-bg-subtle);
488
+ }
489
+
490
+ .hw-header-identity {
491
+ display: flex;
492
+ align-items: center;
493
+ gap: 10px;
494
+ flex: 1;
495
+ min-width: 0;
496
+ }
497
+
498
+ .hw-header-bot-icon {
499
+ width: 28px;
500
+ height: 28px;
501
+ flex-shrink: 0;
502
+ color: var(--hw-text);
503
+ display: flex;
504
+ align-items: center;
505
+ justify-content: center;
506
+ border-radius: 8px;
507
+ overflow: hidden;
508
+ }
509
+ .hw-header-bot-icon svg {
510
+ width: 24px;
511
+ height: 24px;
512
+ }
513
+
514
+ .hw-header-info {
515
+ flex: 1;
516
+ min-width: 0;
517
+ }
518
+
519
+ .hw-header-name {
520
+ font-size: 14px;
521
+ font-weight: 600;
522
+ line-height: 1.3;
523
+ }
524
+
525
+ .hw-header-status {
526
+ font-size: 12px;
527
+ color: var(--hw-text-3);
528
+ line-height: 1.3;
529
+ }
530
+
531
+ .hw-header-close {
532
+ width: 28px;
533
+ height: 28px;
534
+ border-radius: 8px;
535
+ border: none;
536
+ background: transparent;
537
+ color: var(--hw-text-3);
538
+ cursor: pointer;
539
+ display: flex;
540
+ align-items: center;
541
+ justify-content: center;
542
+ /* Strong ease-out + transform for a subtle press on close — on the
543
+ * widget close button press feels terminal ("I'm done"), so scale
544
+ * goes to 0.92 for a clearly felt dip. */
545
+ transition:
546
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),
547
+ color 140ms cubic-bezier(0.23, 1, 0.32, 1),
548
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
549
+ flex-shrink: 0;
550
+ }
551
+ .hw-header-close svg {
552
+ width: 20px;
553
+ height: 20px;
554
+ }
555
+ .hw-header-close:hover {
556
+ background: var(--hw-bg-subtle);
557
+ color: var(--hw-text);
558
+ }
559
+ .hw-header-close:active {
560
+ transform: scale(0.92);
561
+ }
562
+
563
+ /* Messages / Content tab header — centered title */
564
+ .hw-header--centered {
565
+ justify-content: space-between;
566
+ background: transparent;
567
+ color: var(--hw-text);
568
+ border-bottom: 1px solid var(--hw-border);
569
+ }
570
+ .hw-header--centered .hw-header-title {
571
+ position: absolute;
572
+ left: 50%;
573
+ transform: translateX(-50%);
574
+ max-width: calc(100% - 88px);
575
+ white-space: nowrap;
576
+ overflow: hidden;
577
+ text-overflow: ellipsis;
578
+ text-align: center;
579
+ }
580
+ .hw-header-spacer {
581
+ width: 28px;
582
+ flex-shrink: 0;
583
+ }
584
+
585
+ /* Legacy: keep for backwards compat */
586
+ .hw-header--messages {
587
+ justify-content: space-between;
588
+ background: transparent;
589
+ color: var(--hw-text);
590
+ border-bottom: 1px solid var(--hw-border);
591
+ }
592
+ .hw-header-title {
593
+ font-size: 16px;
594
+ font-weight: 600;
595
+ }
596
+ .hw-header-actions {
597
+ display: flex;
598
+ align-items: center;
599
+ gap: 6px;
600
+ }
601
+ .hw-header-action {
602
+ width: 28px;
603
+ height: 28px;
604
+ border-radius: 8px;
605
+ border: none;
606
+ background: transparent;
607
+ color: var(--hw-text-3);
608
+ cursor: pointer;
609
+ display: flex;
610
+ align-items: center;
611
+ justify-content: center;
612
+ transition:
613
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),
614
+ color 140ms cubic-bezier(0.23, 1, 0.32, 1),
615
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
616
+ }
617
+ .hw-header-action svg {
618
+ width: 16px;
619
+ height: 16px;
620
+ }
621
+ .hw-header-action:hover {
622
+ background: var(--hw-bg-subtle);
623
+ color: var(--hw-text);
624
+ }
625
+ .hw-header-action:active {
626
+ transform: scale(0.94);
627
+ }
628
+
629
+ /* ════════════════════════════════════════════════
630
+ HOME TAB
631
+ ════════════════════════════════════════════════ */
632
+
633
+ /* ── Action Card ─────────────────────────────── */
634
+
635
+ .hw-card {
636
+ display: flex;
637
+ align-items: center;
638
+ gap: 12px;
639
+ width: 100%;
640
+ padding: 14px 16px;
641
+ border-radius: 14px;
642
+ background: var(--hw-bg);
643
+ border: 1px solid rgba(0, 0, 0, 0.06);
644
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);
645
+ cursor: pointer;
646
+ /* Scoped box-shadow + transform on strong ease-out. Hover raises
647
+ * the card visually via deeper shadow; press dips it back. This is
648
+ * the primary home-tab CTA — the subtle lift signals "clickable"
649
+ * better than bg-change alone. */
650
+ transition:
651
+ box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1),
652
+ transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
653
+ text-align: left;
654
+ color: var(--hw-text);
655
+ font-family: inherit;
656
+ }
657
+ .hw-card:hover {
658
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.05);
659
+ transform: translateY(-1px);
660
+ }
661
+ .hw-card:active {
662
+ transform: translateY(0) scale(0.99);
663
+ transition-duration: 120ms;
664
+ }
665
+
666
+ .hw-card-body {
667
+ flex: 1;
668
+ min-width: 0;
669
+ }
670
+ .hw-card-title {
671
+ font-size: 14px;
672
+ font-weight: 600;
673
+ line-height: 1.3;
674
+ color: var(--hw-text);
675
+ }
676
+ .hw-card-meta {
677
+ font-size: 12px;
678
+ color: var(--hw-text-3);
679
+ line-height: 1.3;
680
+ margin-top: 1px;
681
+ }
682
+
683
+ .hw-card-arrow {
684
+ width: 32px;
685
+ height: 32px;
686
+ border-radius: 50%;
687
+ background: var(--hw-primary);
688
+ color: white;
689
+ display: flex;
690
+ align-items: center;
691
+ justify-content: center;
692
+ flex-shrink: 0;
693
+ }
694
+ .hw-card-arrow svg {
695
+ width: 14px;
696
+ height: 14px;
697
+ }
698
+
699
+ /* ════════════════════════════════════════════════
700
+ MESSAGES TAB
701
+ ════════════════════════════════════════════════ */
702
+
703
+ .hw-msgs-tab {
704
+ flex: 1;
705
+ overflow-y: auto;
706
+ padding: 12px 16px;
707
+ display: flex;
708
+ flex-direction: column;
709
+ gap: 8px;
710
+ }
711
+
712
+ /* ── Recent Conversations Card (Home tab — grouped rows) ──── */
713
+ .hw-recent-card {
714
+ border-radius: 14px;
715
+ background: var(--hw-bg);
716
+ border: 1px solid rgba(0, 0, 0, 0.06);
717
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);
718
+ overflow: hidden;
719
+ }
720
+
721
+ .hw-recent-header {
722
+ font-size: 12px;
723
+ font-weight: 600;
724
+ color: var(--hw-text-2);
725
+ padding: 12px 14px 0;
726
+ }
727
+
728
+ .hw-recent-row {
729
+ display: flex;
730
+ align-items: center;
731
+ gap: 10px;
732
+ width: 100%;
733
+ padding: 10px 14px;
734
+ border: none;
735
+ border-bottom: 1px solid var(--hw-border);
736
+ background: none;
737
+ cursor: pointer;
738
+ text-align: left;
739
+ font-family: inherit;
740
+ color: var(--hw-text);
741
+ /* Scoped bg + transform transition on the strong ease-out curve —
742
+ * row now responds to both hover (color) and press (micro scale),
743
+ * matching the dashboard's conversation list feel. */
744
+ transition:
745
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),
746
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
747
+ position: relative;
748
+ }
749
+ .hw-recent-row:hover {
750
+ background: rgba(0, 0, 0, 0.03);
751
+ }
752
+ .hw-recent-row:active {
753
+ transform: scale(0.995);
754
+ }
755
+ .hw-recent-row--last {
756
+ border-bottom: none;
757
+ }
758
+
759
+ .hw-recent-row .hw-conv-card-avatar {
760
+ width: 32px;
761
+ height: 32px;
762
+ border-radius: 8px;
763
+ }
764
+ .hw-recent-row .hw-conv-card-avatar svg {
765
+ width: 18px;
766
+ height: 18px;
767
+ }
768
+ .hw-recent-row .hw-conv-card-name {
769
+ font-size: 13px;
770
+ }
771
+ .hw-recent-row .hw-conv-card-preview {
772
+ font-size: 12px;
773
+ }
774
+
775
+ .hw-recent-row--unread .hw-conv-card-name {
776
+ color: var(--hw-text);
777
+ }
778
+ .hw-recent-row--unread .hw-conv-card-time {
779
+ color: var(--hw-accent);
780
+ font-weight: 500;
781
+ }
782
+
783
+ .hw-recent-row-badge {
784
+ min-width: 18px;
785
+ height: 18px;
786
+ border-radius: 9px;
787
+ background: var(--hw-primary);
788
+ color: white;
789
+ font-size: 11px;
790
+ font-weight: 600;
791
+ display: flex;
792
+ align-items: center;
793
+ justify-content: center;
794
+ padding: 0 5px;
795
+ flex-shrink: 0;
796
+ font-variant-numeric: tabular-nums;
797
+ }
798
+
799
+ .hw-recent-see-all {
800
+ display: block;
801
+ width: 100%;
802
+ padding: 10px 14px;
803
+ text-align: center;
804
+ font-size: 13px;
805
+ font-weight: 500;
806
+ color: var(--hw-text);
807
+ background: none;
808
+ border: none;
809
+ border-top: 1px solid var(--hw-border);
810
+ cursor: pointer;
811
+ font-family: inherit;
812
+ transition: background 0.1s;
813
+ }
814
+ .hw-recent-see-all:hover {
815
+ background: rgba(0, 0, 0, 0.02);
816
+ }
817
+
818
+ /* ── Conversation Card (Messages tab) ──── */
819
+ .hw-conv-card {
820
+ position: relative;
821
+ display: flex;
822
+ flex-direction: column;
823
+ gap: 4px;
824
+ width: 100%;
825
+ padding: 14px 16px;
826
+ border-radius: 14px;
827
+ background: var(--hw-bg);
828
+ border: 1px solid rgba(0, 0, 0, 0.06);
829
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);
830
+ cursor: pointer;
831
+ transition: box-shadow 0.15s, transform 0.1s;
832
+ text-align: left;
833
+ font-family: inherit;
834
+ color: var(--hw-text);
835
+ }
836
+ .hw-conv-card:hover {
837
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);
838
+ }
839
+ .hw-conv-card:active {
840
+ transform: scale(0.99);
841
+ }
842
+
843
+ .hw-conv-card-row {
844
+ display: flex;
845
+ align-items: center;
846
+ gap: 12px;
847
+ }
848
+
849
+ .hw-conv-card-avatar {
850
+ width: 36px;
851
+ height: 36px;
852
+ border-radius: 10px;
853
+ background: var(--hw-bg-subtle);
854
+ color: var(--hw-text-3);
855
+ display: flex;
856
+ align-items: center;
857
+ justify-content: center;
858
+ flex-shrink: 0;
859
+ overflow: hidden;
860
+ }
861
+ .hw-conv-card-avatar svg {
862
+ width: 20px;
863
+ height: 20px;
864
+ }
865
+
866
+ .hw-conv-card-content {
867
+ flex: 1;
868
+ min-width: 0;
869
+ }
870
+
871
+ .hw-conv-card-top {
872
+ display: flex;
873
+ align-items: baseline;
874
+ gap: 8px;
875
+ }
876
+
877
+ .hw-conv-card-name {
878
+ flex: 1;
879
+ font-size: 14px;
880
+ font-weight: 600;
881
+ color: var(--hw-text);
882
+ }
883
+
884
+ .hw-conv-card-time {
885
+ font-size: 11px;
886
+ color: var(--hw-text-3);
887
+ flex-shrink: 0;
888
+ font-variant-numeric: tabular-nums;
889
+ }
890
+
891
+ .hw-conv-card-preview {
892
+ font-size: 13px;
893
+ color: var(--hw-text-2);
894
+ overflow: hidden;
895
+ text-overflow: ellipsis;
896
+ white-space: nowrap;
897
+ line-height: 1.4;
898
+ margin-top: 1px;
899
+ }
900
+
901
+ .hw-conv-card--unread .hw-conv-card-name {
902
+ color: var(--hw-text);
903
+ }
904
+ .hw-conv-card--unread .hw-conv-card-time {
905
+ color: var(--hw-accent);
906
+ font-weight: 500;
907
+ }
908
+
909
+ .hw-conv-card-badge {
910
+ position: absolute;
911
+ top: 12px;
912
+ right: 12px;
913
+ min-width: 18px;
914
+ height: 18px;
915
+ border-radius: 9px;
916
+ background: var(--hw-primary);
917
+ color: white;
918
+ font-size: 11px;
919
+ font-weight: 600;
920
+ display: flex;
921
+ align-items: center;
922
+ justify-content: center;
923
+ padding: 0 5px;
924
+ font-variant-numeric: tabular-nums;
925
+ }
926
+
927
+ /* ── Empty State ─────────────────────────────── */
928
+ .hw-empty-state {
929
+ flex: 1;
930
+ display: flex;
931
+ flex-direction: column;
932
+ align-items: center;
933
+ justify-content: center;
934
+ padding: 32px;
935
+ text-align: center;
936
+ }
937
+
938
+ .hw-empty-icon-wrap {
939
+ width: 48px;
940
+ height: 48px;
941
+ border-radius: 50%;
942
+ background: var(--hw-bg-subtle);
943
+ display: flex;
944
+ align-items: center;
945
+ justify-content: center;
946
+ margin-bottom: 16px;
947
+ color: var(--hw-text-3);
948
+ }
949
+ .hw-empty-icon-wrap svg {
950
+ width: 24px;
951
+ height: 24px;
952
+ }
953
+
954
+ .hw-empty-title {
955
+ font-size: 15px;
956
+ font-weight: 600;
957
+ color: var(--hw-text);
958
+ margin-bottom: 4px;
959
+ }
960
+
961
+ .hw-empty-desc {
962
+ font-size: 13px;
963
+ color: var(--hw-text-3);
964
+ margin-bottom: 20px;
965
+ }
966
+
967
+ .hw-empty-btn {
968
+ padding: 8px 20px;
969
+ border-radius: 10px;
970
+ background: var(--hw-primary);
971
+ color: white;
972
+ border: none;
973
+ font-size: 13px;
974
+ font-weight: 500;
975
+ cursor: pointer;
976
+ font-family: inherit;
977
+ transition: background 0.15s;
978
+ }
979
+ .hw-empty-btn:hover {
980
+ background: var(--hw-primary-hover);
981
+ }
982
+
983
+ /* ════════════════════════════════════════════════
984
+ TAB BAR
985
+ ════════════════════════════════════════════════ */
986
+
987
+ .hw-tabs {
988
+ display: flex;
989
+ border-top: 1px solid var(--hw-border);
990
+ flex-shrink: 0;
991
+ background: var(--hw-bg-subtle);
992
+ }
993
+
994
+ .hw-tabs-item {
995
+ flex: 1;
996
+ display: flex;
997
+ flex-direction: column;
998
+ align-items: center;
999
+ gap: 2px;
1000
+ padding: 8px 0;
1001
+ border: none;
1002
+ background: none;
1003
+ cursor: pointer;
1004
+ font-family: inherit;
1005
+ font-size: 11px;
1006
+ font-weight: 500;
1007
+ color: var(--hw-text-3);
1008
+ transition: color 0.15s;
1009
+ }
1010
+ .hw-tabs-item svg {
1011
+ width: 22px;
1012
+ height: 22px;
1013
+ }
1014
+ .hw-tabs-item--active {
1015
+ color: var(--hw-text);
1016
+ }
1017
+ .hw-tabs-item:hover {
1018
+ color: var(--hw-text-2);
1019
+ }
1020
+ .hw-tabs-item:active {
1021
+ transform: scale(0.94);
1022
+ transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), color 0.15s;
1023
+ }
1024
+
1025
+ .hw-tabs-icon-wrap {
1026
+ position: relative;
1027
+ display: inline-flex;
1028
+ }
1029
+
1030
+ .hw-tabs-badge {
1031
+ position: absolute;
1032
+ top: -6px;
1033
+ right: -10px;
1034
+ min-width: 16px;
1035
+ height: 16px;
1036
+ border-radius: 8px;
1037
+ background: var(--hw-primary);
1038
+ color: white;
1039
+ font-size: 10px;
1040
+ font-weight: 700;
1041
+ display: flex;
1042
+ align-items: center;
1043
+ justify-content: center;
1044
+ padding: 0 4px;
1045
+ font-variant-numeric: tabular-nums;
1046
+ }
1047
+
1048
+ /* ════════════════════════════════════════════════
1049
+ MESSAGES AREA
1050
+ ════════════════════════════════════════════════ */
1051
+
1052
+ .hw-messages {
1053
+ flex: 1;
1054
+ overflow-y: auto;
1055
+ overflow-x: hidden; /* Mobile safeguard — a single stray overflow would create horizontal scroll */
1056
+ padding: 16px 20px;
1057
+ background: var(--hw-bg-subtle);
1058
+ display: flex;
1059
+ flex-direction: column;
1060
+ gap: 2px;
1061
+ overscroll-behavior: contain;
1062
+ /* Flex column with constrained children — min-width:0 allows children to
1063
+ honor their own max-width rather than inflating to content width. */
1064
+ min-width: 0;
1065
+ }
1066
+
1067
+ /* ── Empty Messages ─────────────────────────── */
1068
+ .hw-empty {
1069
+ flex: 1;
1070
+ display: flex;
1071
+ flex-direction: column;
1072
+ align-items: center;
1073
+ justify-content: center;
1074
+ padding: 32px;
1075
+ color: var(--hw-text-3);
1076
+ text-align: center;
1077
+ }
1078
+
1079
+ .hw-empty-icon {
1080
+ width: 40px;
1081
+ height: 40px;
1082
+ margin-bottom: 12px;
1083
+ opacity: 0.3;
1084
+ }
1085
+
1086
+ /* ── Date Separator ──────────────────────────── */
1087
+ .hw-date-sep {
1088
+ display: flex;
1089
+ align-items: center;
1090
+ gap: 12px;
1091
+ padding: 12px 0;
1092
+ }
1093
+
1094
+ .hw-date-sep-line {
1095
+ flex: 1;
1096
+ height: 1px;
1097
+ background: var(--hw-border-md);
1098
+ }
1099
+
1100
+ .hw-date-sep-text {
1101
+ font-size: 11px;
1102
+ color: var(--hw-text-3);
1103
+ font-weight: 500;
1104
+ white-space: nowrap;
1105
+ }
1106
+
1107
+ /* ════════════════════════════════════════════════
1108
+ MESSAGE BUBBLE
1109
+ ════════════════════════════════════════════════ */
1110
+
1111
+ .hw-msg {
1112
+ display: flex;
1113
+ padding: 4px 0;
1114
+ max-width: 75%;
1115
+ /* Critical: prevent flex children from expanding beyond the container.
1116
+ Without min-width:0, long unbreakable content (URLs, Turkish words
1117
+ without soft-break opportunities) stretches the flex item past its
1118
+ max-width and overflows the messages column on mobile. */
1119
+ min-width: 0;
1120
+ animation: hw-msg-appear 0.25s ease-out;
1121
+ }
1122
+
1123
+ @keyframes hw-msg-appear {
1124
+ from {
1125
+ opacity: 0;
1126
+ transform: translateY(6px);
1127
+ }
1128
+ to {
1129
+ opacity: 1;
1130
+ transform: translateY(0);
1131
+ }
1132
+ }
1133
+
1134
+ .hw-msg--visitor {
1135
+ align-self: flex-end;
1136
+ }
1137
+
1138
+ .hw-msg--team,
1139
+ .hw-msg--ai {
1140
+ align-self: flex-start;
1141
+ }
1142
+
1143
+ .hw-msg-body {
1144
+ display: flex;
1145
+ flex-direction: column;
1146
+ /* Inherit parent's width constraint (max-width: 75% on .hw-msg).
1147
+ Without these, flex items inside .hw-msg-body can push the body
1148
+ past its parent's bounds on mobile. */
1149
+ min-width: 0;
1150
+ max-width: 100%;
1151
+ }
1152
+
1153
+ .hw-msg-bubble {
1154
+ padding: 10px 14px;
1155
+ border-radius: 18px;
1156
+ font-size: 14px;
1157
+ line-height: 1.45;
1158
+ white-space: pre-wrap;
1159
+ word-break: break-word;
1160
+ /* overflow-wrap catches long unbreakable tokens that word-break misses
1161
+ in some Safari builds. Keeping both is defensive and cheap. */
1162
+ overflow-wrap: anywhere;
1163
+ /* Constrain to the body — prevents a long URL or run-on word from
1164
+ stretching the bubble past 75% of the messages column on mobile. */
1165
+ max-width: 100%;
1166
+ }
1167
+
1168
+ .hw-msg--visitor .hw-msg-bubble {
1169
+ background: var(--hw-primary);
1170
+ color: white;
1171
+ border-bottom-right-radius: 4px;
1172
+ }
1173
+
1174
+ .hw-msg--team .hw-msg-bubble {
1175
+ background: var(--hw-visitor-bubble-bg);
1176
+ color: var(--hw-visitor-bubble-text);
1177
+ border-bottom-left-radius: 4px;
1178
+ }
1179
+
1180
+ .hw-msg--ai .hw-msg-bubble {
1181
+ background: var(--hw-visitor-bubble-bg);
1182
+ color: var(--hw-text);
1183
+ border-bottom-left-radius: 4px;
1184
+ white-space: normal; /* AI messages use HTML rendering (markdown), not pre-wrap */
1185
+ }
1186
+
1187
+ /* Meta (time + sender label) — hidden, show on hover */
1188
+ .hw-msg-meta {
1189
+ font-size: 11px;
1190
+ color: var(--hw-text-3);
1191
+ margin-top: 3px;
1192
+ padding: 0 4px;
1193
+ opacity: 0;
1194
+ transition: opacity 0.15s;
1195
+ font-variant-numeric: tabular-nums;
1196
+ }
1197
+
1198
+ .hw-msg:hover .hw-msg-meta,
1199
+ .hw-msg:focus-within .hw-msg-meta {
1200
+ opacity: 1;
1201
+ }
1202
+
1203
+ .hw-msg--visitor .hw-msg-meta {
1204
+ text-align: right;
1205
+ }
1206
+
1207
+ .hw-msg--team .hw-msg-body,
1208
+ .hw-msg--ai .hw-msg-body {
1209
+ align-items: flex-start;
1210
+ }
1211
+
1212
+ .hw-msg--visitor .hw-msg-body {
1213
+ align-items: flex-end;
1214
+ }
1215
+
1216
+ /* Sender label above bubble */
1217
+ .hw-msg-sender {
1218
+ font-size: 11px;
1219
+ font-weight: 500;
1220
+ color: var(--hw-text-3);
1221
+ margin-bottom: 3px;
1222
+ padding: 0 4px;
1223
+ }
1224
+
1225
+ /* ════════════════════════════════════════════════
1226
+ TYPING INDICATOR
1227
+ ════════════════════════════════════════════════ */
1228
+
1229
+ .hw-typing {
1230
+ display: flex;
1231
+ flex-direction: column;
1232
+ gap: 3px;
1233
+ padding: 8px 0;
1234
+ width: fit-content;
1235
+ animation: hw-msg-appear 0.25s ease-out;
1236
+ }
1237
+
1238
+ .hw-typing-label {
1239
+ font-size: 11px;
1240
+ font-weight: 500;
1241
+ color: var(--hw-text-3);
1242
+ padding: 0 4px;
1243
+ }
1244
+
1245
+ .hw-typing-dots {
1246
+ display: flex;
1247
+ gap: 3px;
1248
+ padding: 10px 14px;
1249
+ width: fit-content;
1250
+ background: var(--hw-visitor-bubble-bg);
1251
+ border-radius: var(--hw-radius);
1252
+ border-bottom-left-radius: 4px;
1253
+ }
1254
+
1255
+ .hw-typing-dot {
1256
+ width: 6px;
1257
+ height: 6px;
1258
+ border-radius: 50%;
1259
+ background: var(--hw-text-3);
1260
+ animation: hw-typing-bounce 1.4s infinite;
1261
+ }
1262
+
1263
+ .hw-typing-dot:nth-child(2) {
1264
+ animation-delay: 0.2s;
1265
+ }
1266
+ .hw-typing-dot:nth-child(3) {
1267
+ animation-delay: 0.4s;
1268
+ }
1269
+
1270
+ @keyframes hw-typing-bounce {
1271
+ 0%,
1272
+ 60%,
1273
+ 100% {
1274
+ transform: translateY(0);
1275
+ }
1276
+ 30% {
1277
+ transform: translateY(-4px);
1278
+ }
1279
+ }
1280
+
1281
+ /* ════════════════════════════════════════════════
1282
+ LOADING STATE
1283
+ ════════════════════════════════════════════════ */
1284
+
1285
+ .hw-loading {
1286
+ flex: 1;
1287
+ display: flex;
1288
+ align-items: center;
1289
+ justify-content: center;
1290
+ }
1291
+
1292
+ .hw-loading-dots {
1293
+ display: flex;
1294
+ gap: 4px;
1295
+ }
1296
+
1297
+ .hw-loading-dot {
1298
+ width: 8px;
1299
+ height: 8px;
1300
+ border-radius: 50%;
1301
+ background: var(--hw-text-4);
1302
+ animation: hw-loading-pulse 1.4s infinite;
1303
+ }
1304
+
1305
+ .hw-loading-dot:nth-child(2) {
1306
+ animation-delay: 0.2s;
1307
+ }
1308
+ .hw-loading-dot:nth-child(3) {
1309
+ animation-delay: 0.4s;
1310
+ }
1311
+
1312
+ @keyframes hw-loading-pulse {
1313
+ 0%,
1314
+ 60%,
1315
+ 100% {
1316
+ opacity: 0.3;
1317
+ transform: scale(0.8);
1318
+ }
1319
+ 30% {
1320
+ opacity: 1;
1321
+ transform: scale(1);
1322
+ }
1323
+ }
1324
+
1325
+ /* ── Skeleton Loader ──────────────────────────── */
1326
+
1327
+ @keyframes hw-skeleton-shimmer {
1328
+ 0% {
1329
+ background-position: -200px 0;
1330
+ }
1331
+ 100% {
1332
+ background-position: calc(200px + 100%) 0;
1333
+ }
1334
+ }
1335
+
1336
+ .hw-skeleton {
1337
+ background: linear-gradient(
1338
+ 90deg,
1339
+ var(--hw-bg-subtle) 25%,
1340
+ rgba(0, 0, 0, 0.04) 50%,
1341
+ var(--hw-bg-subtle) 75%
1342
+ );
1343
+ background-size: 200px 100%;
1344
+ animation: hw-skeleton-shimmer 1.5s ease-in-out infinite;
1345
+ border-radius: 6px;
1346
+ }
1347
+
1348
+ .hw-skeleton-messages {
1349
+ flex: 1;
1350
+ display: flex;
1351
+ flex-direction: column;
1352
+ padding: 16px;
1353
+ gap: 16px;
1354
+ }
1355
+
1356
+ .hw-skeleton-msg {
1357
+ display: flex;
1358
+ gap: 10px;
1359
+ align-items: flex-start;
1360
+ }
1361
+
1362
+ .hw-skeleton-msg--right {
1363
+ flex-direction: row-reverse;
1364
+ }
1365
+
1366
+ .hw-skeleton-avatar {
1367
+ width: 28px;
1368
+ height: 28px;
1369
+ border-radius: 8px;
1370
+ flex-shrink: 0;
1371
+ }
1372
+
1373
+ .hw-skeleton-bubble {
1374
+ display: flex;
1375
+ flex-direction: column;
1376
+ gap: 6px;
1377
+ }
1378
+
1379
+ .hw-skeleton-line {
1380
+ height: 12px;
1381
+ border-radius: 6px;
1382
+ }
1383
+
1384
+ /* ── Skeleton: Conversation list ──────────────── */
1385
+
1386
+ .hw-skeleton-convs {
1387
+ display: flex;
1388
+ flex-direction: column;
1389
+ padding: 8px 0;
1390
+ }
1391
+
1392
+ .hw-skeleton-conv {
1393
+ display: flex;
1394
+ gap: 10px;
1395
+ align-items: center;
1396
+ padding: 10px 16px;
1397
+ }
1398
+
1399
+ .hw-skeleton-conv-avatar {
1400
+ width: 36px;
1401
+ height: 36px;
1402
+ border-radius: 8px;
1403
+ flex-shrink: 0;
1404
+ }
1405
+
1406
+ .hw-skeleton-conv-lines {
1407
+ flex: 1;
1408
+ display: flex;
1409
+ flex-direction: column;
1410
+ gap: 6px;
1411
+ }
1412
+
1413
+ /* ── Skeleton: Content list ──────────────── */
1414
+
1415
+ .hw-skeleton-content {
1416
+ display: flex;
1417
+ flex-direction: column;
1418
+ padding: 12px 16px;
1419
+ gap: 12px;
1420
+ }
1421
+
1422
+ .hw-skeleton-content-item {
1423
+ display: flex;
1424
+ flex-direction: column;
1425
+ gap: 6px;
1426
+ padding: 12px;
1427
+ border-radius: 10px;
1428
+ background: var(--hw-bg);
1429
+ }
1430
+
1431
+ /* ════════════════════════════════════════════════
1432
+ EMAIL COLLECTION CARD (fixed above composer)
1433
+ ════════════════════════════════════════════════ */
1434
+
1435
+ .hw-email-card {
1436
+ margin: 0 12px;
1437
+ padding: 14px 16px 10px;
1438
+ border: 1px solid var(--hw-border, rgba(0,0,0,0.08));
1439
+ border-radius: 14px;
1440
+ background: var(--hw-surface, #fff);
1441
+ box-shadow: 0 1px 4px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.03);
1442
+ animation: hw-email-slide-in 0.25s ease-out;
1443
+ }
1444
+
1445
+ @keyframes hw-email-slide-in {
1446
+ from { opacity: 0; transform: translateY(8px); }
1447
+ to { opacity: 1; transform: translateY(0); }
1448
+ }
1449
+
1450
+ .hw-email-card-header {
1451
+ display: flex;
1452
+ align-items: flex-start;
1453
+ gap: 10px;
1454
+ margin-bottom: 12px;
1455
+ }
1456
+
1457
+ .hw-email-card-icon {
1458
+ flex-shrink: 0;
1459
+ width: 32px;
1460
+ height: 32px;
1461
+ border-radius: 8px;
1462
+ background: var(--hw-brand, #0a0a0a);
1463
+ display: flex;
1464
+ align-items: center;
1465
+ justify-content: center;
1466
+ color: #fff;
1467
+ }
1468
+
1469
+ .hw-email-card-title {
1470
+ font-size: 13px;
1471
+ font-weight: 600;
1472
+ color: var(--hw-text, #1a1a1a);
1473
+ line-height: 1.3;
1474
+ margin: 0 0 2px;
1475
+ }
1476
+
1477
+ .hw-email-card-subtitle {
1478
+ font-size: 12px;
1479
+ color: var(--hw-text-muted, #888);
1480
+ line-height: 1.4;
1481
+ margin: 0;
1482
+ }
1483
+
1484
+ .hw-email-card-input {
1485
+ width: 100%;
1486
+ padding: 9px 12px;
1487
+ border-radius: 10px;
1488
+ border: 1px solid var(--hw-border, rgba(0,0,0,0.1));
1489
+ background: var(--hw-bg, #fafafa);
1490
+ color: var(--hw-text, #1a1a1a);
1491
+ font-size: 13px;
1492
+ outline: none;
1493
+ margin-bottom: 8px;
1494
+ box-sizing: border-box;
1495
+ transition: border-color 0.15s;
1496
+ }
1497
+
1498
+ .hw-email-card-input:focus {
1499
+ border-color: var(--hw-brand, #0a0a0a);
1500
+ box-shadow: 0 0 0 2px rgba(0,0,0,0.06);
1501
+ }
1502
+
1503
+ .hw-email-card-input--error {
1504
+ border-color: #ef4444;
1505
+ }
1506
+
1507
+ .hw-email-card-submit {
1508
+ width: 100%;
1509
+ padding: 9px;
1510
+ border-radius: 10px;
1511
+ border: none;
1512
+ background: var(--hw-brand, #0a0a0a);
1513
+ color: #fff;
1514
+ font-size: 13px;
1515
+ font-weight: 500;
1516
+ cursor: pointer;
1517
+ transition: opacity 0.15s;
1518
+ display: flex;
1519
+ align-items: center;
1520
+ justify-content: center;
1521
+ gap: 6px;
1522
+ }
1523
+
1524
+ .hw-email-card-submit:hover:not(:disabled) {
1525
+ opacity: 0.88;
1526
+ }
1527
+
1528
+ .hw-email-card-submit:disabled {
1529
+ opacity: 0.5;
1530
+ cursor: not-allowed;
1531
+ }
1532
+
1533
+ .hw-email-card--success {
1534
+ display: flex;
1535
+ align-items: center;
1536
+ justify-content: center;
1537
+ gap: 6px;
1538
+ padding: 10px 16px;
1539
+ font-size: 13px;
1540
+ color: var(--hw-text-muted, #888);
1541
+ animation: hw-email-slide-in 0.2s ease-out;
1542
+ }
1543
+
1544
+ .hw-email-card--success svg {
1545
+ flex-shrink: 0;
1546
+ }
1547
+
1548
+ /* ════════════════════════════════════════════════
1549
+ COMPOSER
1550
+ ════════════════════════════════════════════════ */
1551
+
1552
+ .hw-composer {
1553
+ display: flex;
1554
+ flex-direction: column;
1555
+ padding: 12px 16px;
1556
+ background: transparent;
1557
+ flex-shrink: 0;
1558
+ }
1559
+
1560
+ .hw-composer--compact {
1561
+ padding: 8px 12px;
1562
+ }
1563
+
1564
+ .hw-composer-box {
1565
+ display: flex;
1566
+ flex-direction: column;
1567
+ border: 2px solid var(--hw-border-md);
1568
+ border-radius: 16px;
1569
+ overflow: hidden;
1570
+ transition: border-color 0.2s;
1571
+ background: var(--hw-bg);
1572
+ }
1573
+
1574
+ .hw-composer-box:focus-within {
1575
+ border-color: var(--hw-focus-border);
1576
+ box-shadow: 0 0 0 3px var(--hw-focus-ring);
1577
+ }
1578
+
1579
+ .hw-composer-input {
1580
+ flex: 1;
1581
+ resize: none;
1582
+ border: none;
1583
+ padding: 12px 16px 4px;
1584
+ font-size: 14px;
1585
+ font-family: inherit;
1586
+ line-height: 1.4;
1587
+ outline: none;
1588
+ min-height: 40px;
1589
+ max-height: 120px;
1590
+ background: transparent;
1591
+ color: var(--hw-text);
1592
+ }
1593
+
1594
+ .hw-composer-input:focus {
1595
+ outline: none;
1596
+ }
1597
+
1598
+ .hw-composer-input:focus-visible {
1599
+ outline: none;
1600
+ }
1601
+
1602
+ .hw-composer-input::placeholder {
1603
+ color: var(--hw-text-4);
1604
+ }
1605
+
1606
+ .hw-composer-toolbar {
1607
+ display: flex;
1608
+ align-items: center;
1609
+ justify-content: space-between;
1610
+ padding: 4px 10px 10px;
1611
+ }
1612
+
1613
+ .hw-composer-toolbar-left {
1614
+ display: flex;
1615
+ align-items: center;
1616
+ gap: 4px;
1617
+ }
1618
+
1619
+ /* Send button — tight 140ms transition scoped to only the props that
1620
+ * actually change. Press scale goes to 0.9 (bigger than Button's 0.97
1621
+ * because this is a terminal action — "fire"). Uses the same strong
1622
+ * ease-out curve as the rest of the dashboard. */
1623
+ .hw-composer-send {
1624
+ width: 32px;
1625
+ height: 32px;
1626
+ border-radius: 50%;
1627
+ border: none;
1628
+ cursor: pointer;
1629
+ display: flex;
1630
+ align-items: center;
1631
+ justify-content: center;
1632
+ flex-shrink: 0;
1633
+ transition:
1634
+ background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),
1635
+ color 140ms cubic-bezier(0.23, 1, 0.32, 1),
1636
+ transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
1637
+ }
1638
+
1639
+ .hw-composer-send:active:not(:disabled) {
1640
+ transform: scale(0.9);
1641
+ }
1642
+
1643
+ .hw-composer-send--active {
1644
+ background: var(--hw-primary);
1645
+ color: white;
1646
+ }
1647
+
1648
+ .hw-composer-send--inactive {
1649
+ background: var(--hw-border);
1650
+ color: var(--hw-text-4);
1651
+ cursor: default;
1652
+ }
1653
+
1654
+ .hw-composer-send svg {
1655
+ width: 14px;
1656
+ height: 14px;
1657
+ }
1658
+
1659
+ /* Character count — invisible until the visitor crosses the warn
1660
+ * threshold, then reveals with a subtle rise instead of popping in.
1661
+ * Uses @starting-style so the transition only fires on mount (no
1662
+ * animation on re-renders while the number is updating). */
1663
+ .hw-composer-charcount {
1664
+ font-size: 11px;
1665
+ color: var(--hw-text-3);
1666
+ font-variant-numeric: tabular-nums;
1667
+ opacity: 1;
1668
+ transform: translateY(0);
1669
+ transition:
1670
+ color 180ms cubic-bezier(0.23, 1, 0.32, 1),
1671
+ opacity 180ms cubic-bezier(0.23, 1, 0.32, 1),
1672
+ transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
1673
+ }
1674
+
1675
+ @starting-style {
1676
+ .hw-composer-charcount {
1677
+ opacity: 0;
1678
+ transform: translateY(3px);
1679
+ }
1680
+ }
1681
+
1682
+ .hw-composer-charcount--over {
1683
+ color: #ef4444;
1684
+ font-weight: 600;
1685
+ }
1686
+
1687
+ @media (prefers-reduced-motion: reduce) {
1688
+ .hw-composer-charcount {
1689
+ transform: none;
1690
+ transition: color 160ms ease, opacity 160ms ease;
1691
+ }
1692
+ @starting-style {
1693
+ .hw-composer-charcount {
1694
+ transform: none;
1695
+ }
1696
+ }
1697
+ }
1698
+
1699
+ /* Composer — attachment previews */
1700
+ .hw-composer-previews {
1701
+ display: flex;
1702
+ gap: 6px;
1703
+ padding: 8px 10px 0;
1704
+ overflow-x: auto;
1705
+ scrollbar-width: none;
1706
+ }
1707
+ .hw-composer-previews::-webkit-scrollbar {
1708
+ display: none;
1709
+ }
1710
+
1711
+ .hw-composer-preview {
1712
+ position: relative;
1713
+ width: 48px;
1714
+ height: 48px;
1715
+ border-radius: 8px;
1716
+ overflow: hidden;
1717
+ flex-shrink: 0;
1718
+ background: var(--hw-border);
1719
+ cursor: pointer;
1720
+ }
1721
+
1722
+ .hw-composer-preview--error {
1723
+ outline: 2px solid #ef4444;
1724
+ outline-offset: -2px;
1725
+ }
1726
+
1727
+ .hw-composer-preview-img {
1728
+ width: 100%;
1729
+ height: 100%;
1730
+ object-fit: cover;
1731
+ }
1732
+
1733
+ .hw-composer-preview-file {
1734
+ width: 100%;
1735
+ height: 100%;
1736
+ display: flex;
1737
+ align-items: center;
1738
+ justify-content: center;
1739
+ background: var(--hw-bg-subtle);
1740
+ }
1741
+
1742
+ .hw-composer-preview-ext {
1743
+ font-size: 10px;
1744
+ font-weight: 700;
1745
+ color: var(--hw-text-3);
1746
+ text-transform: uppercase;
1747
+ }
1748
+
1749
+ .hw-composer-preview-loader {
1750
+ position: absolute;
1751
+ inset: 0;
1752
+ background: rgba(0, 0, 0, 0.35);
1753
+ display: flex;
1754
+ align-items: center;
1755
+ justify-content: center;
1756
+ }
1757
+ .hw-composer-preview-loader::after {
1758
+ content: "";
1759
+ width: 16px;
1760
+ height: 16px;
1761
+ border: 2px solid rgba(255, 255, 255, 0.3);
1762
+ border-top-color: white;
1763
+ border-radius: 50%;
1764
+ animation: hw-spin 0.6s linear infinite;
1765
+ }
1766
+
1767
+ @keyframes hw-spin {
1768
+ to {
1769
+ transform: rotate(360deg);
1770
+ }
1771
+ }
1772
+
1773
+ .hw-composer-preview-badge {
1774
+ position: absolute;
1775
+ top: 2px;
1776
+ right: 2px;
1777
+ width: 16px;
1778
+ height: 16px;
1779
+ border-radius: 50%;
1780
+ background: #ef4444;
1781
+ color: white;
1782
+ font-size: 10px;
1783
+ font-weight: 700;
1784
+ display: flex;
1785
+ align-items: center;
1786
+ justify-content: center;
1787
+ }
1788
+
1789
+ .hw-composer-preview-remove {
1790
+ position: absolute;
1791
+ top: 2px;
1792
+ right: 2px;
1793
+ width: 18px;
1794
+ height: 18px;
1795
+ border-radius: 50%;
1796
+ border: none;
1797
+ background: rgba(0, 0, 0, 0.55);
1798
+ color: white;
1799
+ cursor: pointer;
1800
+ display: flex;
1801
+ align-items: center;
1802
+ justify-content: center;
1803
+ opacity: 0;
1804
+ transition: opacity 0.15s;
1805
+ }
1806
+ .hw-composer-preview-remove svg {
1807
+ width: 10px;
1808
+ height: 10px;
1809
+ }
1810
+ .hw-composer-preview:hover .hw-composer-preview-remove {
1811
+ opacity: 1;
1812
+ }
1813
+
1814
+ /* Composer — attach button (active) */
1815
+ .hw-composer-attach {
1816
+ width: 28px;
1817
+ height: 28px;
1818
+ border: none;
1819
+ background: none;
1820
+ color: var(--hw-text-3);
1821
+ cursor: pointer;
1822
+ display: flex;
1823
+ align-items: center;
1824
+ justify-content: center;
1825
+ border-radius: 6px;
1826
+ opacity: 0.7;
1827
+ transition: opacity 0.15s;
1828
+ }
1829
+ .hw-composer-attach:hover {
1830
+ opacity: 1;
1831
+ }
1832
+ .hw-composer-attach svg {
1833
+ width: 16px;
1834
+ height: 16px;
1835
+ }
1836
+
1837
+ /* ── Message — image attachments ────────────────── */
1838
+
1839
+ .hw-msg-images {
1840
+ display: flex;
1841
+ flex-direction: column;
1842
+ gap: 4px;
1843
+ margin-bottom: 4px;
1844
+ }
1845
+
1846
+ .hw-msg-image-link {
1847
+ display: block;
1848
+ border-radius: 14px;
1849
+ overflow: hidden;
1850
+ line-height: 0;
1851
+ }
1852
+
1853
+ .hw-msg-image {
1854
+ max-width: 140px;
1855
+ max-height: 80px;
1856
+ object-fit: cover;
1857
+ border-radius: 8px;
1858
+ outline: 1px solid rgba(0, 0, 0, 0.08);
1859
+ outline-offset: -1px;
1860
+ }
1861
+
1862
+ /* ── Message — file attachments ─────────────────── */
1863
+
1864
+ .hw-msg-files {
1865
+ display: flex;
1866
+ flex-direction: column;
1867
+ gap: 4px;
1868
+ margin-top: 4px;
1869
+ }
1870
+
1871
+ .hw-msg-file {
1872
+ display: flex;
1873
+ align-items: center;
1874
+ gap: 8px;
1875
+ padding: 8px 12px;
1876
+ border-radius: 10px;
1877
+ background: var(--hw-bg-subtle);
1878
+ text-decoration: none;
1879
+ color: var(--hw-text);
1880
+ transition: background 0.15s;
1881
+ }
1882
+ .hw-msg-file:hover {
1883
+ background: var(--hw-border);
1884
+ }
1885
+
1886
+ .hw-msg-file-icon {
1887
+ flex-shrink: 0;
1888
+ width: 20px;
1889
+ height: 20px;
1890
+ color: var(--hw-text-3);
1891
+ }
1892
+ .hw-msg-file-icon svg {
1893
+ width: 100%;
1894
+ height: 100%;
1895
+ }
1896
+
1897
+ .hw-msg-file-info {
1898
+ display: flex;
1899
+ flex-direction: column;
1900
+ min-width: 0;
1901
+ }
1902
+
1903
+ .hw-msg-file-name {
1904
+ font-size: 13px;
1905
+ font-weight: 500;
1906
+ white-space: nowrap;
1907
+ overflow: hidden;
1908
+ text-overflow: ellipsis;
1909
+ }
1910
+
1911
+ .hw-msg-file-size {
1912
+ font-size: 11px;
1913
+ color: var(--hw-text-3);
1914
+ }
1915
+
1916
+ /* Image thumbnail — cursor hint */
1917
+ .hw-msg-image-link {
1918
+ cursor: pointer;
1919
+ border: none;
1920
+ padding: 0;
1921
+ background: none;
1922
+ display: block;
1923
+ line-height: 0;
1924
+ }
1925
+
1926
+ /* ── Hover preview — floating near cursor ─────── */
1927
+
1928
+ .hw-hover-preview {
1929
+ position: fixed;
1930
+ z-index: 99998;
1931
+ padding: 6px;
1932
+ border-radius: 14px;
1933
+ background: white;
1934
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.06);
1935
+ cursor: pointer;
1936
+ animation: hw-hover-in 0.15s ease-out;
1937
+ }
1938
+
1939
+ @media (prefers-color-scheme: dark) {
1940
+ .hw-hover-preview {
1941
+ background: #1c1c1e;
1942
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08);
1943
+ }
1944
+ }
1945
+
1946
+ @keyframes hw-hover-in {
1947
+ from {
1948
+ opacity: 0;
1949
+ transform: scale(0.96) translateY(4px);
1950
+ }
1951
+ to {
1952
+ opacity: 1;
1953
+ transform: scale(1) translateY(0);
1954
+ }
1955
+ }
1956
+
1957
+ .hw-hover-preview-img {
1958
+ width: 100%;
1959
+ max-height: 200px;
1960
+ object-fit: contain;
1961
+ border-radius: 10px;
1962
+ display: block;
1963
+ outline: 1px solid rgba(0, 0, 0, 0.08);
1964
+ outline-offset: -1px;
1965
+ }
1966
+
1967
+ /* Document preview variant */
1968
+ .hw-hover-preview--doc {
1969
+ display: flex;
1970
+ align-items: center;
1971
+ gap: 10px;
1972
+ padding: 10px 14px;
1973
+ }
1974
+
1975
+ .hw-hover-preview-doc-icon {
1976
+ width: 28px;
1977
+ height: 28px;
1978
+ flex-shrink: 0;
1979
+ }
1980
+ .hw-hover-preview-doc-icon svg {
1981
+ width: 100%;
1982
+ height: 100%;
1983
+ }
1984
+
1985
+ .hw-hover-preview-doc-info {
1986
+ display: flex;
1987
+ flex-direction: column;
1988
+ min-width: 0;
1989
+ }
1990
+
1991
+ .hw-hover-preview-doc-name {
1992
+ font-size: 13px;
1993
+ font-weight: 500;
1994
+ color: var(--hw-text);
1995
+ white-space: nowrap;
1996
+ overflow: hidden;
1997
+ text-overflow: ellipsis;
1998
+ }
1999
+
2000
+ .hw-hover-preview-doc-hint {
2001
+ font-size: 11px;
2002
+ color: var(--hw-text-3);
2003
+ }
2004
+
2005
+ /* ════════════════════════════════════════════════
2006
+ EVENT CARD (join/leave/resolve)
2007
+ ════════════════════════════════════════════════ */
2008
+
2009
+ .hw-event {
2010
+ display: flex;
2011
+ justify-content: center;
2012
+ padding: 8px 16px;
2013
+ }
2014
+ .hw-event-text {
2015
+ font-size: 12px;
2016
+ color: var(--hw-text-3);
2017
+ text-align: center;
2018
+ }
2019
+
2020
+ .hw-event--card {
2021
+ justify-content: flex-start;
2022
+ align-items: center;
2023
+ gap: 10px;
2024
+ background: var(--hw-bg-subtle);
2025
+ padding: 10px 14px;
2026
+ border-radius: 12px;
2027
+ margin: 4px 16px;
2028
+ }
2029
+
2030
+ .hw-event-avatar {
2031
+ width: 32px;
2032
+ height: 32px;
2033
+ border-radius: 50%;
2034
+ background: #e0e0e0;
2035
+ color: #555;
2036
+ display: flex;
2037
+ align-items: center;
2038
+ justify-content: center;
2039
+ font-size: 11px;
2040
+ font-weight: 600;
2041
+ flex-shrink: 0;
2042
+ overflow: hidden;
2043
+ }
2044
+ .hw-event-avatar-img {
2045
+ width: 100%;
2046
+ height: 100%;
2047
+ object-fit: cover;
2048
+ }
2049
+
2050
+ .hw-event-body {
2051
+ font-size: 13px;
2052
+ line-height: 1.3;
2053
+ }
2054
+ .hw-event-name {
2055
+ font-weight: 600;
2056
+ color: var(--hw-text);
2057
+ }
2058
+ .hw-event-action {
2059
+ color: var(--hw-text-2);
2060
+ }
2061
+
2062
+ /* ════════════════════════════════════════════════
2063
+ RESOLVED BANNER
2064
+ ════════════════════════════════════════════════ */
2065
+
2066
+ .hw-resolved-banner {
2067
+ display: flex;
2068
+ align-items: center;
2069
+ justify-content: center;
2070
+ padding: 12px 16px;
2071
+ border-top: 1px solid var(--hw-border);
2072
+ background: var(--hw-bg-subtle);
2073
+ color: var(--hw-text-2);
2074
+ font-size: 13px;
2075
+ flex-shrink: 0;
2076
+ }
2077
+
2078
+ /* ════════════════════════════════════════════════
2079
+ NEW CONVERSATION FORM
2080
+ ════════════════════════════════════════════════ */
2081
+
2082
+ .hw-new {
2083
+ flex: 1;
2084
+ display: flex;
2085
+ flex-direction: column;
2086
+ background: var(--hw-bg-subtle);
2087
+ }
2088
+
2089
+ .hw-new-body {
2090
+ flex: 1;
2091
+ display: flex;
2092
+ flex-direction: column;
2093
+ align-items: center;
2094
+ justify-content: center;
2095
+ padding: 32px 24px;
2096
+ text-align: center;
2097
+ }
2098
+
2099
+ .hw-new-welcome {
2100
+ flex: 1;
2101
+ /* Match .hw-messages padding so the welcome bubble doesn't shift
2102
+ horizontally when the view transitions to ConversationView after
2103
+ the visitor sends their first message. */
2104
+ padding: 16px 20px;
2105
+ overflow-y: auto;
2106
+ }
2107
+
2108
+ .hw-new-heading {
2109
+ font-size: 17px;
2110
+ font-weight: 600;
2111
+ color: var(--hw-text);
2112
+ margin-bottom: 6px;
2113
+ }
2114
+
2115
+ .hw-new-desc {
2116
+ font-size: 13px;
2117
+ color: var(--hw-text-2);
2118
+ margin-bottom: 24px;
2119
+ }
2120
+
2121
+ /* ════════════════════════════════════════════════
2122
+ POWERED BY
2123
+ ════════════════════════════════════════════════ */
2124
+
2125
+ .hw-powered {
2126
+ text-align: center;
2127
+ padding: 8px;
2128
+ font-size: 11px;
2129
+ color: var(--hw-text-4);
2130
+ flex-shrink: 0;
2131
+ }
2132
+
2133
+ .hw-powered a {
2134
+ color: var(--hw-text-2);
2135
+ text-decoration: none;
2136
+ font-weight: 500;
2137
+ }
2138
+
2139
+ .hw-powered a:hover {
2140
+ color: var(--hw-text);
2141
+ }
2142
+
2143
+ /* ════════════════════════════════════════════════
2144
+ MOBILE RESPONSIVE (< 480px)
2145
+ ════════════════════════════════════════════════ */
2146
+
2147
+ @media (max-width: 479px) {
2148
+ .hw-widget {
2149
+ bottom: 16px;
2150
+ right: 16px;
2151
+ left: auto;
2152
+ }
2153
+
2154
+ .hw-window {
2155
+ position: fixed;
2156
+ top: 0;
2157
+ left: 0;
2158
+ right: 0;
2159
+ bottom: 0;
2160
+ width: 100%;
2161
+ /* --hw-visible-height is set by default-widget.tsx from
2162
+ visualViewport.height — shrinks when iOS virtual keyboard opens
2163
+ so the composer stays above the keyboard. Falls back to 100% when
2164
+ visualViewport isn't supported or not yet measured. */
2165
+ height: var(--hw-visible-height, 100%);
2166
+ border-radius: 0;
2167
+ animation: hw-mob-up 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
2168
+ }
2169
+ .hw-window--closing {
2170
+ animation: hw-mob-down 0.2s ease forwards;
2171
+ }
2172
+ @keyframes hw-mob-up {
2173
+ from {
2174
+ opacity: 0;
2175
+ transform: translateY(100%);
2176
+ }
2177
+ to {
2178
+ opacity: 1;
2179
+ transform: translateY(0);
2180
+ }
2181
+ }
2182
+ @keyframes hw-mob-down {
2183
+ from {
2184
+ opacity: 1;
2185
+ transform: translateY(0);
2186
+ }
2187
+ to {
2188
+ opacity: 0;
2189
+ transform: translateY(100%);
2190
+ }
2191
+ }
2192
+
2193
+ /* Safe areas */
2194
+ .hw-hero {
2195
+ padding-top: calc(20px + env(safe-area-inset-top, 0px));
2196
+ }
2197
+ .hw-header {
2198
+ padding-top: env(safe-area-inset-top, 0px);
2199
+ }
2200
+ .hw-tabs {
2201
+ padding-bottom: env(safe-area-inset-bottom, 0px);
2202
+ }
2203
+ .hw-composer {
2204
+ padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
2205
+ }
2206
+ .hw-powered {
2207
+ padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));
2208
+ }
2209
+
2210
+ /* Touch targets */
2211
+ .hw-header-close,
2212
+ .hw-header-back,
2213
+ .hw-header-action {
2214
+ width: 34px;
2215
+ height: 34px;
2216
+ }
2217
+
2218
+ .hw-composer-send {
2219
+ width: 40px;
2220
+ height: 40px;
2221
+ }
2222
+
2223
+ /* Hide bubble when fullscreen */
2224
+ .hw-window ~ .hw-bubble {
2225
+ display: none;
2226
+ }
2227
+
2228
+ /* Mobile: tighten message list padding + give bubbles more room.
2229
+ 75% of a 360px viewport with 20px side padding = 240px bubble cap,
2230
+ which truncates even short sentences like "Merhaba!". Bumping to
2231
+ 82% on mobile (~262px) fits Turkish greetings and the body still
2232
+ has visible room for the opposite-side avatar/spacing. */
2233
+ .hw-messages {
2234
+ padding: 12px 14px;
2235
+ }
2236
+ .hw-msg {
2237
+ max-width: 82%;
2238
+ }
2239
+ }
2240
+
2241
+ /* ════════════════════════════════════════════════
2242
+ MESSAGE PREVIEW BUBBLE (shown when widget is closed)
2243
+ ════════════════════════════════════════════════ */
2244
+
2245
+ .hw-preview {
2246
+ position: absolute;
2247
+ bottom: calc(100% + 12px);
2248
+ right: 0;
2249
+ width: 300px;
2250
+ max-width: calc(100vw - 40px);
2251
+ background: var(--hw-bg);
2252
+ border: 1px solid var(--hw-border);
2253
+ border-radius: 16px;
2254
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);
2255
+ animation: hw-preview-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
2256
+ overflow: hidden;
2257
+ cursor: pointer;
2258
+ transition: transform 0.15s, box-shadow 0.15s;
2259
+ }
2260
+
2261
+ .hw-preview:hover {
2262
+ transform: translateY(-2px);
2263
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.08);
2264
+ }
2265
+
2266
+ .hw-preview--closing {
2267
+ animation: hw-preview-out 0.2s ease forwards;
2268
+ }
2269
+
2270
+ @keyframes hw-preview-in {
2271
+ from {
2272
+ opacity: 0;
2273
+ transform: translateY(8px) scale(0.95);
2274
+ }
2275
+ to {
2276
+ opacity: 1;
2277
+ transform: translateY(0) scale(1);
2278
+ }
2279
+ }
2280
+ @keyframes hw-preview-out {
2281
+ from {
2282
+ opacity: 1;
2283
+ transform: translateY(0) scale(1);
2284
+ }
2285
+ to {
2286
+ opacity: 0;
2287
+ transform: translateY(8px) scale(0.95);
2288
+ }
2289
+ }
2290
+
2291
+ .hw-preview-header {
2292
+ display: flex;
2293
+ align-items: center;
2294
+ gap: 8px;
2295
+ padding: 12px 14px 0;
2296
+ }
2297
+
2298
+ .hw-preview-avatar {
2299
+ width: 28px;
2300
+ height: 28px;
2301
+ border-radius: 50%;
2302
+ background: linear-gradient(135deg, var(--hw-primary), color-mix(in srgb, var(--hw-primary) 50%, black));
2303
+ display: flex;
2304
+ align-items: center;
2305
+ justify-content: center;
2306
+ color: white;
2307
+ flex-shrink: 0;
2308
+ overflow: hidden;
2309
+ }
2310
+
2311
+ .hw-preview-avatar svg {
2312
+ width: 16px;
2313
+ height: 16px;
2314
+ }
2315
+
2316
+ .hw-preview-name {
2317
+ font-size: 13px;
2318
+ font-weight: 600;
2319
+ color: var(--hw-text);
2320
+ flex: 1;
2321
+ }
2322
+
2323
+ .hw-preview-close {
2324
+ width: 24px;
2325
+ height: 24px;
2326
+ border: none;
2327
+ background: transparent;
2328
+ color: var(--hw-text-3);
2329
+ cursor: pointer;
2330
+ display: flex;
2331
+ align-items: center;
2332
+ justify-content: center;
2333
+ border-radius: 50%;
2334
+ transition: background 0.15s, color 0.15s;
2335
+ flex-shrink: 0;
2336
+ }
2337
+ .hw-preview-close:hover {
2338
+ background: var(--hw-bg-subtle);
2339
+ color: var(--hw-text-2);
2340
+ }
2341
+ .hw-preview-close:active {
2342
+ transform: scale(0.90);
2343
+ transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), background 0.15s, color 0.15s;
2344
+ }
2345
+ .hw-preview-close svg {
2346
+ width: 12px;
2347
+ height: 12px;
2348
+ }
2349
+
2350
+ .hw-preview-body {
2351
+ padding: 8px 14px 14px;
2352
+ font-size: 14px;
2353
+ line-height: 1.45;
2354
+ color: var(--hw-text-2);
2355
+ display: -webkit-box;
2356
+ -webkit-line-clamp: 3;
2357
+ -webkit-box-orient: vertical;
2358
+ overflow: hidden;
2359
+ }
2360
+
2361
+ /* ═══════════════════════════════════════════════════════════
2362
+ Content Tabs — Better i18n Content CMS integration
2363
+ Generic list → detail pattern for all content types
2364
+ ═══════════════════════════════════════════════════════════ */
2365
+
2366
+ /* ── Search (rounded input card) ────────────────────────── */
2367
+ .hw-content-search {
2368
+ padding: 10px 16px;
2369
+ }
2370
+
2371
+ .hw-content-search-box {
2372
+ display: flex;
2373
+ align-items: center;
2374
+ gap: 8px;
2375
+ padding: 8px 12px;
2376
+ background: var(--hw-bg);
2377
+ border: 1px solid var(--hw-border-md);
2378
+ border-radius: 10px;
2379
+ transition: border-color 0.15s, box-shadow 0.15s;
2380
+ }
2381
+
2382
+ .hw-content-search-box:focus-within {
2383
+ border-color: var(--hw-focus-border);
2384
+ box-shadow: 0 0 0 3px var(--hw-focus-ring);
2385
+ }
2386
+
2387
+ .hw-content-search-input {
2388
+ flex: 1;
2389
+ border: none !important;
2390
+ outline: none !important;
2391
+ box-shadow: none !important;
2392
+ background: none;
2393
+ font-size: 13px;
2394
+ color: var(--hw-text-1);
2395
+ font-family: inherit;
2396
+ line-height: 1;
2397
+ -webkit-appearance: none;
2398
+ }
2399
+
2400
+ .hw-content-search-input:focus,
2401
+ .hw-content-search-input:focus-visible {
2402
+ outline: none !important;
2403
+ box-shadow: none !important;
2404
+ border: none !important;
2405
+ }
2406
+
2407
+ .hw-content-search-input::placeholder {
2408
+ color: var(--hw-text-3);
2409
+ }
2410
+
2411
+ .hw-content-search-icon {
2412
+ width: 15px;
2413
+ height: 15px;
2414
+ color: var(--hw-text-3);
2415
+ flex-shrink: 0;
2416
+ }
2417
+
2418
+ /* ── Entry List ────────────────────────────────────────── */
2419
+ .hw-content-list {
2420
+ display: flex;
2421
+ flex-direction: column;
2422
+ height: 100%;
2423
+ }
2424
+
2425
+ .hw-content-entries {
2426
+ flex: 1;
2427
+ overflow-y: auto;
2428
+ overscroll-behavior: contain;
2429
+ }
2430
+
2431
+ .hw-content-entry {
2432
+ display: block;
2433
+ width: 100%;
2434
+ padding: 14px 16px;
2435
+ border: none;
2436
+ border-bottom: 1px solid var(--hw-border);
2437
+ background: none;
2438
+ cursor: pointer;
2439
+ text-align: left;
2440
+ transition: background-color 0.15s ease;
2441
+ -webkit-tap-highlight-color: transparent;
2442
+ }
2443
+
2444
+ .hw-content-entry:hover {
2445
+ background: var(--hw-bg-hover);
2446
+ }
2447
+
2448
+ .hw-content-entry:active {
2449
+ background: var(--hw-border);
2450
+ }
2451
+
2452
+ .hw-content-entry:last-child {
2453
+ border-bottom: none;
2454
+ }
2455
+
2456
+ .hw-content-entry-main {
2457
+ display: flex;
2458
+ align-items: center;
2459
+ gap: 12px;
2460
+ }
2461
+
2462
+ .hw-content-entry-text {
2463
+ flex: 1;
2464
+ min-width: 0;
2465
+ display: flex;
2466
+ flex-direction: column;
2467
+ gap: 3px;
2468
+ }
2469
+
2470
+ .hw-content-entry-title {
2471
+ font-size: 14px;
2472
+ font-weight: 600;
2473
+ color: var(--hw-text-1);
2474
+ line-height: 1.3;
2475
+ }
2476
+
2477
+ .hw-content-entry-desc {
2478
+ font-size: 13px;
2479
+ color: var(--hw-text-2);
2480
+ line-height: 1.4;
2481
+ display: -webkit-box;
2482
+ -webkit-line-clamp: 2;
2483
+ -webkit-box-orient: vertical;
2484
+ overflow: hidden;
2485
+ }
2486
+
2487
+ .hw-content-entry-meta {
2488
+ display: flex;
2489
+ align-items: center;
2490
+ gap: 6px;
2491
+ margin-top: 2px;
2492
+ }
2493
+
2494
+ .hw-content-entry-badge {
2495
+ font-size: 11px;
2496
+ font-weight: 500;
2497
+ color: var(--hw-text-3);
2498
+ background: var(--hw-bg-hover);
2499
+ padding: 1px 6px;
2500
+ border-radius: 4px;
2501
+ }
2502
+
2503
+ .hw-content-entry-date {
2504
+ font-size: 11px;
2505
+ color: var(--hw-text-3);
2506
+ }
2507
+
2508
+ .hw-content-entry-chevron {
2509
+ width: 16px;
2510
+ height: 16px;
2511
+ color: var(--hw-text-3);
2512
+ flex-shrink: 0;
2513
+ opacity: 0.5;
2514
+ }
2515
+
2516
+ /* ── Detail View ───────────────────────────────────────── */
2517
+ .hw-content-detail {
2518
+ padding: 16px;
2519
+ overflow-y: auto;
2520
+ overscroll-behavior: contain;
2521
+ height: 100%;
2522
+ }
2523
+
2524
+ .hw-content-detail-header {
2525
+ margin-bottom: 16px;
2526
+ }
2527
+
2528
+ .hw-content-detail-title {
2529
+ font-size: 17px;
2530
+ font-weight: 700;
2531
+ color: var(--hw-text-1);
2532
+ margin: 0 0 6px;
2533
+ line-height: 1.3;
2534
+ display: flex;
2535
+ align-items: center;
2536
+ gap: 6px;
2537
+ }
2538
+
2539
+ .hw-content-detail-meta {
2540
+ display: flex;
2541
+ align-items: center;
2542
+ gap: 8px;
2543
+ flex-wrap: wrap;
2544
+ }
2545
+
2546
+ .hw-content-detail-date {
2547
+ font-size: 12px;
2548
+ color: var(--hw-text-3);
2549
+ }
2550
+
2551
+ .hw-content-detail-body {
2552
+ font-size: 14px;
2553
+ line-height: 1.6;
2554
+ color: var(--hw-text-1);
2555
+ }
2556
+
2557
+ /* ── Markdown Rendering ────────────────────────────────── */
2558
+ .hw-markdown h1 {
2559
+ font-size: 17px;
2560
+ font-weight: 700;
2561
+ margin: 20px 0 8px;
2562
+ }
2563
+
2564
+ .hw-markdown h2 {
2565
+ font-size: 15px;
2566
+ font-weight: 600;
2567
+ margin: 16px 0 6px;
2568
+ }
2569
+
2570
+ .hw-markdown h3 {
2571
+ font-size: 14px;
2572
+ font-weight: 600;
2573
+ margin: 12px 0 4px;
2574
+ }
2575
+
2576
+ .hw-markdown p {
2577
+ margin: 0 0 12px;
2578
+ }
2579
+
2580
+ .hw-markdown ul {
2581
+ margin: 0 0 12px;
2582
+ padding-left: 20px;
2583
+ }
2584
+
2585
+ .hw-markdown li {
2586
+ margin: 4px 0;
2587
+ }
2588
+
2589
+ .hw-markdown code {
2590
+ font-family: ui-monospace, "SF Mono", monospace;
2591
+ font-size: 12px;
2592
+ background: var(--hw-bg-hover);
2593
+ padding: 1px 5px;
2594
+ border-radius: 4px;
2595
+ }
2596
+
2597
+ /* ═══ Code block card — header (lang + copy) + body ═══
2598
+ Emitted by renderMarkdown for every triple-backtick fence.
2599
+ Designed to match the Better i18n docs look: subtle header bar,
2600
+ mono body with horizontal scroll for long lines. */
2601
+ .hw-code {
2602
+ margin: 10px 0;
2603
+ border-radius: 10px;
2604
+ overflow: hidden;
2605
+ border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));
2606
+ background: var(--hw-bg-hover, #f5f5f4);
2607
+ font-family: ui-monospace, "SF Mono", "Menlo", monospace;
2608
+ }
2609
+
2610
+ .hw-code-header {
2611
+ display: flex;
2612
+ align-items: center;
2613
+ justify-content: space-between;
2614
+ padding: 6px 12px;
2615
+ font-size: 11px;
2616
+ color: var(--hw-text-2, #6b7280);
2617
+ background: rgba(0, 0, 0, 0.03);
2618
+ border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));
2619
+ }
2620
+
2621
+ .hw-code-lang {
2622
+ text-transform: lowercase;
2623
+ letter-spacing: 0.02em;
2624
+ font-weight: 500;
2625
+ }
2626
+
2627
+ .hw-code-copy {
2628
+ display: inline-flex;
2629
+ align-items: center;
2630
+ gap: 4px;
2631
+ padding: 2px 8px;
2632
+ font-size: 11px;
2633
+ font-family: inherit;
2634
+ color: var(--hw-text-2, #6b7280);
2635
+ background: transparent;
2636
+ border: 1px solid transparent;
2637
+ border-radius: 5px;
2638
+ cursor: pointer;
2639
+ transition: background 120ms ease, color 120ms ease;
2640
+ }
2641
+
2642
+ .hw-code-copy:hover {
2643
+ color: var(--hw-text, #111);
2644
+ background: rgba(0, 0, 0, 0.06);
2645
+ }
2646
+
2647
+ .hw-code-copy--copied {
2648
+ color: #16a34a;
2649
+ }
2650
+
2651
+ .hw-code-copy--failed {
2652
+ color: #dc2626;
2653
+ }
2654
+
2655
+ .hw-code pre {
2656
+ margin: 0;
2657
+ padding: 10px 12px;
2658
+ background: transparent;
2659
+ border-radius: 0;
2660
+ overflow-x: auto;
2661
+ max-width: 100%;
2662
+ }
2663
+
2664
+ .hw-code pre code {
2665
+ display: block;
2666
+ background: transparent;
2667
+ padding: 0;
2668
+ font-size: 12px;
2669
+ line-height: 1.55;
2670
+ white-space: pre;
2671
+ color: var(--hw-text, #111);
2672
+ }
2673
+
2674
+ /* Dark-mode auto-tweaks — widget supports --hw-* tokens so theme adapts.
2675
+ If tokens aren't overridden, browsers honoring prefers-color-scheme get a
2676
+ darker card by default. */
2677
+ @media (prefers-color-scheme: dark) {
2678
+ .hw-code {
2679
+ background: rgba(255, 255, 255, 0.04);
2680
+ border-color: rgba(255, 255, 255, 0.08);
2681
+ }
2682
+ .hw-code-header {
2683
+ background: rgba(255, 255, 255, 0.03);
2684
+ border-bottom-color: rgba(255, 255, 255, 0.06);
2685
+ }
2686
+ .hw-code-copy:hover {
2687
+ background: rgba(255, 255, 255, 0.08);
2688
+ }
2689
+ }
2690
+
2691
+ /* Legacy bare <pre> fallback (rendered by old CMS bodyHtml content that may
2692
+ not have been re-processed). Keep the overflow + wrap behavior so nothing
2693
+ breaks visually while we transition to the card-wrapped variant. */
2694
+ .hw-markdown pre {
2695
+ margin: 8px 0;
2696
+ padding: 10px 12px;
2697
+ background: var(--hw-bg-hover);
2698
+ border-radius: 8px;
2699
+ overflow-x: auto;
2700
+ max-width: 100%;
2701
+ }
2702
+
2703
+ .hw-markdown pre code {
2704
+ display: block;
2705
+ background: transparent;
2706
+ padding: 0;
2707
+ border-radius: 0;
2708
+ font-size: 12px;
2709
+ line-height: 1.5;
2710
+ white-space: pre;
2711
+ word-break: normal;
2712
+ color: inherit;
2713
+ }
2714
+
2715
+ /* Also style fenced blocks that live inside a message bubble (AI replies) —
2716
+ bubbles already have their own bg, so a slightly darker overlay reads. */
2717
+ .hw-msg-bubble pre {
2718
+ margin: 6px 0;
2719
+ padding: 8px 10px;
2720
+ background: rgba(0, 0, 0, 0.06);
2721
+ border-radius: 6px;
2722
+ overflow-x: auto;
2723
+ max-width: 100%;
2724
+ }
2725
+
2726
+ .hw-msg-bubble pre code {
2727
+ background: transparent;
2728
+ padding: 0;
2729
+ font-size: 12px;
2730
+ line-height: 1.5;
2731
+ white-space: pre;
2732
+ }
2733
+
2734
+ .hw-msg--team .hw-msg-bubble pre,
2735
+ .hw-msg--visitor .hw-msg-bubble pre {
2736
+ background: rgba(255, 255, 255, 0.12);
2737
+ }
2738
+
2739
+ .hw-markdown blockquote {
2740
+ margin: 0 0 12px;
2741
+ padding: 8px 12px;
2742
+ border-left: 3px solid var(--hw-border);
2743
+ color: var(--hw-text-2);
2744
+ font-style: italic;
2745
+ }
2746
+
2747
+ .hw-markdown a {
2748
+ color: var(--hw-primary);
2749
+ text-decoration: underline;
2750
+ text-underline-offset: 2px;
2751
+ }
2752
+
2753
+ .hw-markdown img {
2754
+ max-width: 100%;
2755
+ border-radius: 8px;
2756
+ margin: 8px 0;
2757
+ outline: 1px solid rgba(0, 0, 0, 0.08);
2758
+ outline-offset: -1px;
2759
+ }
2760
+
2761
+ .hw-markdown hr {
2762
+ border: none;
2763
+ border-top: 1px solid var(--hw-border);
2764
+ margin: 16px 0;
2765
+ }
2766
+
2767
+ /* ── Empty / Loading ───────────────────────────────────── */
2768
+ .hw-content-empty {
2769
+ display: flex;
2770
+ flex-direction: column;
2771
+ align-items: center;
2772
+ justify-content: center;
2773
+ padding: 40px 20px;
2774
+ text-align: center;
2775
+ }
2776
+
2777
+ .hw-content-empty-title {
2778
+ font-size: 14px;
2779
+ font-weight: 600;
2780
+ color: var(--hw-text-1);
2781
+ margin-bottom: 4px;
2782
+ }
2783
+
2784
+ .hw-content-empty-desc {
2785
+ font-size: 12px;
2786
+ color: var(--hw-text-3);
2787
+ }
2788
+
2789
+ .hw-content-loading {
2790
+ display: flex;
2791
+ align-items: center;
2792
+ justify-content: center;
2793
+ padding: 40px 20px;
2794
+ }
2795
+
2796
+ /* ── Load More ─────────────────────────────────────────── */
2797
+ .hw-content-load-more {
2798
+ display: block;
2799
+ width: 100%;
2800
+ padding: 10px;
2801
+ border: none;
2802
+ background: none;
2803
+ color: var(--hw-primary);
2804
+ font-size: 13px;
2805
+ font-weight: 500;
2806
+ cursor: pointer;
2807
+ text-align: center;
2808
+ }
2809
+
2810
+ .hw-content-load-more:hover {
2811
+ background: var(--hw-bg-hover);
2812
+ }
2813
+
2814
+ .hw-content-load-more:disabled {
2815
+ opacity: 0.5;
2816
+ cursor: default;
2817
+ }
2818
+
2819
+ /* ════════════════════════════════════════════════
2820
+ TOUCH DEVICE FIXES
2821
+ ════════════════════════════════════════════════ */
2822
+
2823
+ @media (hover: none) {
2824
+ .hw-composer-preview-remove {
2825
+ opacity: 0.7;
2826
+ }
2827
+ .hw-msg-meta {
2828
+ opacity: 1;
2829
+ }
2830
+ }
2831
+
2832
+ /* ════════════════════════════════════════════════
2833
+ DRAG & DROP OVERLAY
2834
+ ════════════════════════════════════════════════ */
2835
+
2836
+ .hw-composer--dragging .hw-composer-box {
2837
+ border-color: var(--hw-primary);
2838
+ background: color-mix(in srgb, var(--hw-primary) 4%, transparent);
2839
+ }
2840
+
2841
+ .hw-composer-drop-overlay {
2842
+ position: absolute;
2843
+ inset: 0;
2844
+ display: flex;
2845
+ align-items: center;
2846
+ justify-content: center;
2847
+ background: color-mix(in srgb, var(--hw-bg) 90%, transparent);
2848
+ border: 2px dashed var(--hw-primary);
2849
+ border-radius: 12px;
2850
+ z-index: 10;
2851
+ pointer-events: none;
2852
+ animation: hw-drop-pulse 1.5s ease-in-out infinite;
2853
+ }
2854
+
2855
+ .hw-composer-drop-text {
2856
+ font-size: 13px;
2857
+ font-weight: 500;
2858
+ color: var(--hw-primary);
2859
+ }
2860
+
2861
+ @keyframes hw-drop-pulse {
2862
+ 0%,
2863
+ 100% {
2864
+ opacity: 0.8;
2865
+ }
2866
+ 50% {
2867
+ opacity: 1;
2868
+ }
2869
+ }
2870
+
2871
+ /* ════════════════════════════════════════════════
2872
+ MESSAGE COPY BUTTON
2873
+ ════════════════════════════════════════════════ */
2874
+
2875
+ .hw-msg-copy {
2876
+ display: inline-flex;
2877
+ align-items: center;
2878
+ justify-content: center;
2879
+ width: 20px;
2880
+ height: 20px;
2881
+ margin-left: 4px;
2882
+ border: none;
2883
+ border-radius: 4px;
2884
+ background: none;
2885
+ color: var(--hw-text-4);
2886
+ cursor: pointer;
2887
+ vertical-align: middle;
2888
+ transition: color 0.15s, background 0.15s;
2889
+ padding: 0;
2890
+ flex-shrink: 0;
2891
+ }
2892
+
2893
+ .hw-msg-copy:hover {
2894
+ background: var(--hw-bg-hover);
2895
+ color: var(--hw-text-2);
2896
+ }
2897
+
2898
+ .hw-msg-copy svg {
2899
+ width: 12px;
2900
+ height: 12px;
2901
+ }
2902
+
2903
+ .hw-msg-copy--done {
2904
+ color: #22c55e;
2905
+ }
2906
+
2907
+ /* ════════════════════════════════════════════════
2908
+ DISCONNECT BANNER
2909
+ ════════════════════════════════════════════════ */
2910
+
2911
+ .hw-disconnect {
2912
+ display: flex;
2913
+ align-items: center;
2914
+ justify-content: center;
2915
+ gap: 6px;
2916
+ padding: 6px 12px;
2917
+ background: #fef3c7;
2918
+ color: #92400e;
2919
+ font-size: 12px;
2920
+ font-weight: 500;
2921
+ flex-shrink: 0;
2922
+ animation: hw-msg-appear 0.25s ease-out;
2923
+ }
2924
+
2925
+ .hw-disconnect-dot {
2926
+ width: 6px;
2927
+ height: 6px;
2928
+ border-radius: 50%;
2929
+ background: #f59e0b;
2930
+ animation: hw-loading-pulse 1.4s infinite;
2931
+ }
2932
+
2933
+ /* ════════════════════════════════════════════════
2934
+ ERROR STATE
2935
+ ════════════════════════════════════════════════ */
2936
+
2937
+ .hw-error-state {
2938
+ flex: 1;
2939
+ display: flex;
2940
+ flex-direction: column;
2941
+ align-items: center;
2942
+ justify-content: center;
2943
+ padding: 32px 24px;
2944
+ text-align: center;
2945
+ gap: 12px;
2946
+ }
2947
+
2948
+ .hw-error-icon {
2949
+ width: 48px;
2950
+ height: 48px;
2951
+ border-radius: 50%;
2952
+ background: #fef2f2;
2953
+ color: #ef4444;
2954
+ display: flex;
2955
+ align-items: center;
2956
+ justify-content: center;
2957
+ }
2958
+
2959
+ .hw-error-icon svg {
2960
+ width: 24px;
2961
+ height: 24px;
2962
+ }
2963
+
2964
+ .hw-error-title {
2965
+ font-size: 15px;
2966
+ font-weight: 600;
2967
+ color: var(--hw-text);
2968
+ }
2969
+
2970
+ .hw-error-desc {
2971
+ font-size: 13px;
2972
+ color: var(--hw-text-2);
2973
+ }
2974
+
2975
+ .hw-error-btn {
2976
+ padding: 8px 20px;
2977
+ border: 1px solid var(--hw-border-md);
2978
+ border-radius: 8px;
2979
+ background: var(--hw-bg);
2980
+ color: var(--hw-text);
2981
+ font-size: 13px;
2982
+ font-weight: 500;
2983
+ cursor: pointer;
2984
+ transition: background 0.15s;
2985
+ }
2986
+
2987
+ .hw-error-btn:hover {
2988
+ background: var(--hw-bg-hover);
2989
+ }
2990
+
2991
+ /* ════════════════════════════════════════════════
2992
+ SEND ERROR TOAST
2993
+ ════════════════════════════════════════════════ */
2994
+
2995
+ .hw-send-error {
2996
+ display: flex;
2997
+ align-items: center;
2998
+ gap: 8px;
2999
+ padding: 8px 12px;
3000
+ background: #fef2f2;
3001
+ color: #dc2626;
3002
+ font-size: 12px;
3003
+ font-weight: 500;
3004
+ flex-shrink: 0;
3005
+ animation: hw-msg-appear 0.25s ease-out;
3006
+ }
3007
+
3008
+ .hw-send-error-retry {
3009
+ margin-left: auto;
3010
+ padding: 2px 8px;
3011
+ border: 1px solid #fca5a5;
3012
+ border-radius: 4px;
3013
+ background: none;
3014
+ color: #dc2626;
3015
+ font-size: 11px;
3016
+ font-weight: 600;
3017
+ cursor: pointer;
3018
+ }
3019
+
3020
+ .hw-send-error-retry:hover {
3021
+ background: #fee2e2;
3022
+ }
3023
+
3024
+ /* ════════════════════════════════════════════════
3025
+ RESOLVED CONVERSATION — REOPEN + CSAT
3026
+ ════════════════════════════════════════════════ */
3027
+
3028
+ .hw-resolved {
3029
+ display: flex;
3030
+ flex-direction: column;
3031
+ align-items: center;
3032
+ gap: 12px;
3033
+ padding: 16px 20px;
3034
+ border-top: 1px solid var(--hw-border);
3035
+ flex-shrink: 0;
3036
+ }
3037
+
3038
+ .hw-resolved-text {
3039
+ font-size: 13px;
3040
+ color: var(--hw-text-3);
3041
+ font-weight: 500;
3042
+ }
3043
+
3044
+ .hw-resolved-actions {
3045
+ display: flex;
3046
+ gap: 8px;
3047
+ }
3048
+
3049
+ .hw-resolved-reopen {
3050
+ padding: 6px 16px;
3051
+ border: 1px solid var(--hw-border-md);
3052
+ border-radius: 8px;
3053
+ background: var(--hw-bg);
3054
+ color: var(--hw-text);
3055
+ font-size: 13px;
3056
+ font-weight: 500;
3057
+ cursor: pointer;
3058
+ transition: background 0.15s;
3059
+ }
3060
+
3061
+ .hw-resolved-reopen:hover {
3062
+ background: var(--hw-bg-hover);
3063
+ }
3064
+
3065
+ /* CSAT Rating */
3066
+ .hw-csat {
3067
+ display: flex;
3068
+ flex-direction: column;
3069
+ align-items: center;
3070
+ gap: 8px;
3071
+ }
3072
+
3073
+ .hw-csat-label {
3074
+ font-size: 12px;
3075
+ color: var(--hw-text-3);
3076
+ }
3077
+
3078
+ .hw-csat-buttons {
3079
+ display: flex;
3080
+ gap: 8px;
3081
+ }
3082
+
3083
+ .hw-csat-btn {
3084
+ width: 36px;
3085
+ height: 36px;
3086
+ border: 1px solid var(--hw-border-md);
3087
+ border-radius: 8px;
3088
+ background: var(--hw-bg);
3089
+ cursor: pointer;
3090
+ display: flex;
3091
+ align-items: center;
3092
+ justify-content: center;
3093
+ font-size: 18px;
3094
+ transition: transform 0.15s, border-color 0.15s, background 0.15s;
3095
+ }
3096
+
3097
+ .hw-csat-btn:hover {
3098
+ transform: scale(1.1);
3099
+ border-color: var(--hw-text-3);
3100
+ }
3101
+
3102
+ .hw-csat-btn--selected {
3103
+ border-color: var(--hw-primary);
3104
+ background: var(--hw-bg-hover);
3105
+ transform: scale(1.15);
3106
+ }
3107
+
3108
+ .hw-csat-thanks {
3109
+ font-size: 12px;
3110
+ color: #22c55e;
3111
+ font-weight: 500;
3112
+ animation: hw-msg-appear 0.25s ease-out;
3113
+ }
3114
+
3115
+ /* ════════════════════════════════════════════════
3116
+ INFINITE SCROLL — LOAD MORE TRIGGER
3117
+ ════════════════════════════════════════════════ */
3118
+
3119
+ .hw-load-more-trigger {
3120
+ display: flex;
3121
+ justify-content: center;
3122
+ /* Zero-height by default — only an IntersectionObserver sentinel.
3123
+ The spinner adds its own padding when actively loading. Without
3124
+ this, the trigger reserves 8px of vertical space and shifts the
3125
+ welcome bubble down ~17px when the view transitions from
3126
+ NewConversationView (no trigger) to ConversationView. */
3127
+ min-height: 1px;
3128
+ }
3129
+
3130
+ .hw-load-more-trigger:has(.hw-load-more-spinner) {
3131
+ padding: 8px 0;
3132
+ }
3133
+
3134
+ .hw-load-more-spinner {
3135
+ display: flex;
3136
+ gap: 3px;
3137
+ }
3138
+
3139
+ .hw-load-more-spinner > div {
3140
+ width: 5px;
3141
+ height: 5px;
3142
+ border-radius: 50%;
3143
+ background: var(--hw-text-4);
3144
+ animation: hw-loading-pulse 1.4s infinite;
3145
+ }
3146
+
3147
+ .hw-load-more-spinner > div:nth-child(2) {
3148
+ animation-delay: 0.2s;
3149
+ }
3150
+ .hw-load-more-spinner > div:nth-child(3) {
3151
+ animation-delay: 0.4s;
3152
+ }
3153
+
3154
+ /* ════════════════════════════════════════════════
3155
+ MOBILE SWIPE HANDLE
3156
+ ════════════════════════════════════════════════ */
3157
+
3158
+ .hw-drag-handle {
3159
+ display: none;
3160
+ }
3161
+
3162
+ @media (max-width: 479px) {
3163
+ .hw-drag-handle {
3164
+ display: flex;
3165
+ justify-content: center;
3166
+ padding: 8px 0 4px;
3167
+ flex-shrink: 0;
3168
+ }
3169
+
3170
+ .hw-drag-handle-pill {
3171
+ width: 32px;
3172
+ height: 4px;
3173
+ border-radius: 2px;
3174
+ background: var(--hw-text-4);
3175
+ }
3176
+ }
3177
+
3178
+ /* ════════════════════════════════════════════════
3179
+ MARKDOWN IN MESSAGES
3180
+ ════════════════════════════════════════════════ */
3181
+
3182
+ .hw-msg-bubble p {
3183
+ margin: 0 0 8px;
3184
+ }
3185
+ .hw-msg-bubble p:last-child {
3186
+ margin-bottom: 0;
3187
+ }
3188
+ .hw-msg-bubble strong {
3189
+ font-weight: 600;
3190
+ }
3191
+ .hw-msg-bubble em {
3192
+ font-style: italic;
3193
+ }
3194
+ .hw-msg-bubble a {
3195
+ color: var(--hw-primary);
3196
+ text-decoration: underline;
3197
+ text-underline-offset: 2px;
3198
+ word-break: break-all;
3199
+ }
3200
+ .hw-msg-bubble a:hover {
3201
+ opacity: 0.8;
3202
+ }
3203
+ .hw-msg--visitor .hw-msg-bubble a {
3204
+ color: rgba(255, 255, 255, 0.9);
3205
+ }
3206
+ .hw-msg--visitor .hw-msg-bubble a:hover {
3207
+ color: white;
3208
+ }
3209
+
3210
+ .hw-msg-bubble ul,
3211
+ .hw-msg-bubble ol {
3212
+ margin: 4px 0 8px;
3213
+ padding-left: 20px;
3214
+ }
3215
+
3216
+ .hw-msg-bubble li {
3217
+ margin: 2px 0;
3218
+ }
3219
+
3220
+ .hw-msg-bubble code {
3221
+ padding: 1px 4px;
3222
+ border-radius: 3px;
3223
+ background: rgba(0, 0, 0, 0.06);
3224
+ font-size: 0.9em;
3225
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
3226
+ }
3227
+
3228
+ .hw-msg-bubble pre {
3229
+ margin: 4px 0 8px;
3230
+ padding: 8px 10px;
3231
+ border-radius: 6px;
3232
+ background: rgba(0, 0, 0, 0.06);
3233
+ overflow-x: auto;
3234
+ font-size: 0.85em;
3235
+ }
3236
+
3237
+ .hw-msg-bubble pre code {
3238
+ padding: 0;
3239
+ background: none;
3240
+ }
3241
+
3242
+ .hw-msg-bubble blockquote {
3243
+ margin: 4px 0 8px;
3244
+ padding: 4px 0 4px 12px;
3245
+ border-left: 3px solid var(--hw-border-md);
3246
+ color: var(--hw-text-2);
3247
+ }
3248
+
3249
+ /* ════════════════════════════════════════════════
3250
+ DARK MODE
3251
+ ════════════════════════════════════════════════ */
3252
+
3253
+ /* Explicit dark activation via `data-theme="dark"` on the widget root.
3254
+ Covers the test harness (prefers-color-scheme isn't always reachable in
3255
+ headless automation) and eventual host-app opt-in. Duplicates only the
3256
+ token block — downstream selectors already read through the tokens. */
3257
+ .hw-widget[data-theme="dark"] {
3258
+ --hw-bg: #1c1c1e;
3259
+ --hw-bg-subtle: #161618;
3260
+ --hw-bg-hover: #2c2c2e;
3261
+ --hw-border: rgba(255, 255, 255, 0.08);
3262
+ --hw-border-md: rgba(255, 255, 255, 0.14);
3263
+ --hw-text: #f5f5f5;
3264
+ --hw-text-1: #f5f5f5;
3265
+ --hw-text-2: #a1a1aa;
3266
+ --hw-text-3: #71717a;
3267
+ --hw-text-4: #52525b;
3268
+ --hw-visitor-bubble-bg: #2c2c2e;
3269
+ --hw-visitor-bubble-text: #f5f5f5;
3270
+ --hw-focus-border: rgba(255, 255, 255, 0.28);
3271
+ --hw-focus-ring: rgba(255, 255, 255, 0.08);
3272
+ }
3273
+
3274
+ @media (prefers-color-scheme: dark) {
3275
+ .hw-widget:not([data-theme="light"]) {
3276
+ --hw-bg: #1c1c1e;
3277
+ --hw-bg-subtle: #161618;
3278
+ --hw-bg-hover: #2c2c2e;
3279
+ /* Borders were #2c2c2e — identical to --hw-bg-hover, making every
3280
+ card edge invisible. Semi-transparent whites read over any dark
3281
+ surface and stay consistent when cards sit on each other. */
3282
+ --hw-border: rgba(255, 255, 255, 0.08);
3283
+ --hw-border-md: rgba(255, 255, 255, 0.14);
3284
+ --hw-text: #f5f5f5;
3285
+ --hw-text-1: #f5f5f5;
3286
+ --hw-text-2: #a1a1aa;
3287
+ --hw-text-3: #71717a;
3288
+ --hw-text-4: #52525b;
3289
+ --hw-visitor-bubble-bg: #2c2c2e;
3290
+ --hw-visitor-bubble-text: #f5f5f5;
3291
+ /* Focus ring in dark needs lighter border + subtle halo. */
3292
+ --hw-focus-border: rgba(255, 255, 255, 0.28);
3293
+ --hw-focus-ring: rgba(255, 255, 255, 0.08);
3294
+ }
3295
+ }
3296
+
3297
+ @media (prefers-color-scheme: dark) {
3298
+ /* Header + tab bar sit on the window surface, should match. */
3299
+ .hw-widget:not([data-theme="light"]) .hw-header {
3300
+ background: var(--hw-bg);
3301
+ border-color: var(--hw-border);
3302
+ }
3303
+
3304
+ .hw-header-bot-icon {
3305
+ background: var(--hw-bg-hover);
3306
+ }
3307
+
3308
+ .hw-header-name,
3309
+ .hw-header-title {
3310
+ color: var(--hw-text);
3311
+ }
3312
+
3313
+ .hw-header-status {
3314
+ color: var(--hw-text-2);
3315
+ }
3316
+
3317
+ .hw-header-close,
3318
+ .hw-header-back {
3319
+ color: var(--hw-text-2);
3320
+ }
3321
+
3322
+ .hw-header-close:hover,
3323
+ .hw-header-back:hover {
3324
+ background: var(--hw-bg-hover);
3325
+ color: var(--hw-text);
3326
+ }
3327
+
3328
+ /* Content list entries (changelog / help articles). The border fix at the
3329
+ token level already helps, but the item hover needs a dark variant. */
3330
+ .hw-content-entry {
3331
+ background: var(--hw-bg);
3332
+ border-color: var(--hw-border);
3333
+ }
3334
+
3335
+ .hw-content-entry:hover {
3336
+ background: var(--hw-bg-hover);
3337
+ border-color: var(--hw-border-md);
3338
+ }
3339
+
3340
+ .hw-content-empty,
3341
+ .hw-empty {
3342
+ color: var(--hw-text-3);
3343
+ }
3344
+
3345
+ /* Conversation list rows. */
3346
+ .hw-conv-card {
3347
+ border-color: var(--hw-border);
3348
+ }
3349
+
3350
+ .hw-recent-row {
3351
+ border-color: var(--hw-border);
3352
+ }
3353
+
3354
+ /* Drag-over highlight on composer. */
3355
+ .hw-composer-drop-overlay {
3356
+ background: rgba(0, 0, 0, 0.6);
3357
+ color: var(--hw-text);
3358
+ }
3359
+
3360
+ .hw-composer--dragging .hw-composer-box {
3361
+ border-color: var(--hw-focus-border);
3362
+ box-shadow: 0 0 0 3px var(--hw-focus-ring);
3363
+ }
3364
+
3365
+ .hw-hero {
3366
+ /* Dark mode — same brand-aware pattern, edges go further into black. */
3367
+ background: linear-gradient(
3368
+ 160deg,
3369
+ color-mix(in srgb, var(--hw-primary) 40%, black) 0%,
3370
+ var(--hw-primary) 50%,
3371
+ color-mix(in srgb, var(--hw-primary) 25%, black) 100%
3372
+ );
3373
+ }
3374
+
3375
+ .hw-sheet {
3376
+ background: var(--hw-bg);
3377
+ }
3378
+
3379
+ .hw-card {
3380
+ background: var(--hw-bg-hover);
3381
+ border-color: var(--hw-border);
3382
+ }
3383
+
3384
+ .hw-card:hover {
3385
+ background: #333;
3386
+ }
3387
+
3388
+ .hw-window {
3389
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.06);
3390
+ }
3391
+
3392
+ .hw-bubble:focus-visible {
3393
+ outline-color: var(--hw-text-3);
3394
+ }
3395
+
3396
+ .hw-msg--visitor .hw-msg-bubble {
3397
+ background: var(--hw-primary);
3398
+ color: white;
3399
+ }
3400
+
3401
+ .hw-msg-bubble code {
3402
+ background: rgba(255, 255, 255, 0.08);
3403
+ }
3404
+
3405
+ .hw-msg-bubble pre {
3406
+ background: rgba(255, 255, 255, 0.08);
3407
+ }
3408
+
3409
+ .hw-composer-box {
3410
+ background: var(--hw-bg);
3411
+ border-color: var(--hw-border);
3412
+ }
3413
+
3414
+ .hw-composer-input {
3415
+ color: var(--hw-text);
3416
+ }
3417
+
3418
+ .hw-tabs {
3419
+ background: var(--hw-bg);
3420
+ border-color: var(--hw-border);
3421
+ }
3422
+
3423
+ .hw-conv-card:hover,
3424
+ .hw-recent-row:hover {
3425
+ background: var(--hw-bg-hover);
3426
+ }
3427
+
3428
+ .hw-disconnect {
3429
+ background: #422006;
3430
+ color: #fcd34d;
3431
+ }
3432
+
3433
+ .hw-send-error {
3434
+ background: #450a0a;
3435
+ color: #fca5a5;
3436
+ }
3437
+
3438
+ .hw-error-icon {
3439
+ background: #450a0a;
3440
+ color: #f87171;
3441
+ }
3442
+
3443
+ .hw-msg-copy:hover {
3444
+ background: var(--hw-bg-hover);
3445
+ color: var(--hw-text-2);
3446
+ }
3447
+
3448
+ .hw-resolved {
3449
+ border-color: var(--hw-border);
3450
+ }
3451
+
3452
+ .hw-resolved-reopen,
3453
+ .hw-csat-btn {
3454
+ background: var(--hw-bg-hover);
3455
+ border-color: var(--hw-border-md);
3456
+ color: var(--hw-text);
3457
+ }
3458
+
3459
+ .hw-hover-preview {
3460
+ background: #1c1c1e;
3461
+ border-color: var(--hw-border);
3462
+ }
3463
+
3464
+ /* Search input needs a lifted surface so it reads against the panel;
3465
+ the focus ring already adapts via the --hw-focus-* tokens above. */
3466
+ .hw-content-search-box {
3467
+ background: var(--hw-bg-hover);
3468
+ border-color: var(--hw-border-md);
3469
+ }
3470
+
3471
+ .hw-preview {
3472
+ background: var(--hw-bg);
3473
+ border-color: var(--hw-border);
3474
+ }
3475
+ }