@helpway/react 0.17.0 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1572 -770
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/themed/styles.css +344 -81
package/dist/index.js
CHANGED
|
@@ -55,7 +55,11 @@ function createWidgetClient(config) {
|
|
|
55
55
|
headers() {
|
|
56
56
|
return {
|
|
57
57
|
"X-Public-Key": config.apiKey,
|
|
58
|
-
"X-Visitor-Id": getOrCreateVisitorId(config.apiKey)
|
|
58
|
+
"X-Visitor-Id": getOrCreateVisitorId(config.apiKey),
|
|
59
|
+
/* Only when it is not the default. A header on every web
|
|
60
|
+
request to say "web" is a byte per call to tell the server
|
|
61
|
+
what it already assumes. */
|
|
62
|
+
...config.surface === "mobile" ? { "X-Visitor-Surface": "mobile" } : {}
|
|
59
63
|
};
|
|
60
64
|
},
|
|
61
65
|
fetch(url, options) {
|
|
@@ -66,6 +70,17 @@ function createWidgetClient(config) {
|
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
72
|
|
|
73
|
+
// ../types/src/enums.ts
|
|
74
|
+
var MemberRole = {
|
|
75
|
+
Owner: "owner",
|
|
76
|
+
Admin: "admin",
|
|
77
|
+
Agent: "agent",
|
|
78
|
+
Member: "member"
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// ../types/src/visitor.ts
|
|
82
|
+
var ONLINE_WINDOW_MS = 5 * 6e4;
|
|
83
|
+
|
|
69
84
|
// ../types/src/model-registry.ts
|
|
70
85
|
var AI_MODELS = {
|
|
71
86
|
"openai/gpt-5.5": {
|
|
@@ -373,8 +388,31 @@ var DOC_NAV_ICON_MAP = Object.fromEntries(
|
|
|
373
388
|
DOC_NAV_ICONS.map((i) => [i.name, i])
|
|
374
389
|
);
|
|
375
390
|
|
|
391
|
+
// ../types/src/upload.ts
|
|
392
|
+
var ALLOWED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
393
|
+
// Images — the only kind anyone has sent in volume.
|
|
394
|
+
"image/png",
|
|
395
|
+
"image/jpeg",
|
|
396
|
+
"image/gif",
|
|
397
|
+
"image/webp",
|
|
398
|
+
// Documents
|
|
399
|
+
"application/pdf",
|
|
400
|
+
// Text — inert by definition.
|
|
401
|
+
"text/plain",
|
|
402
|
+
"text/csv"
|
|
403
|
+
]);
|
|
404
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
405
|
+
var MAX_BASE64_LENGTH = Math.ceil(MAX_FILE_SIZE * 1.37);
|
|
406
|
+
function acceptAttribute() {
|
|
407
|
+
return [...ALLOWED_MIME_TYPES].sort().join(",");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ../types/src/member-roles.ts
|
|
411
|
+
var MEMBER_ROLES = [MemberRole.Owner, MemberRole.Admin, MemberRole.Member];
|
|
412
|
+
var ASSIGNABLE_ROLES = [MemberRole.Admin, MemberRole.Member];
|
|
413
|
+
|
|
376
414
|
// ../widget-core/src/version.ts
|
|
377
|
-
var SDK_VERSION = "0.17.
|
|
415
|
+
var SDK_VERSION = "0.17.2".length > 0 ? "0.17.2" : "dev";
|
|
378
416
|
|
|
379
417
|
// ../widget-core/src/ws.ts
|
|
380
418
|
var WebSocketManager = class {
|
|
@@ -386,7 +424,17 @@ var WebSocketManager = class {
|
|
|
386
424
|
reconnectTimer = null;
|
|
387
425
|
pingTimer = null;
|
|
388
426
|
isDestroyed = false;
|
|
427
|
+
/* What the "Reconnecting…" notice needs and `isConnected` cannot say: a
|
|
428
|
+
socket that has never been open is CONNECTING, not reconnecting, and one
|
|
429
|
+
nobody has asked to connect yet is neither (connection-notice.ts). */
|
|
430
|
+
openedOnce = false;
|
|
431
|
+
firstConnectAt = null;
|
|
389
432
|
visibilityHandler = null;
|
|
433
|
+
/* The retry budget is spent and nothing is scheduled. Until this existed the
|
|
434
|
+
manager simply went quiet after its tenth attempt, and the widget kept
|
|
435
|
+
saying "Reconnecting…" about a socket nobody was reconnecting. */
|
|
436
|
+
gaveUp = false;
|
|
437
|
+
onlineHandler = null;
|
|
390
438
|
constructor(config) {
|
|
391
439
|
this.config = config;
|
|
392
440
|
this.setupVisibilityListener();
|
|
@@ -403,6 +451,15 @@ var WebSocketManager = class {
|
|
|
403
451
|
};
|
|
404
452
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
405
453
|
}
|
|
454
|
+
/* The browser saying the network is back is the best moment to try again,
|
|
455
|
+
and after giving up it is the only automatic one. */
|
|
456
|
+
setupOnlineListener() {
|
|
457
|
+
if (typeof window === "undefined" || this.onlineHandler) return;
|
|
458
|
+
this.onlineHandler = () => {
|
|
459
|
+
if (!this.isDestroyed && !this.isConnected) this.retryNow();
|
|
460
|
+
};
|
|
461
|
+
window.addEventListener("online", this.onlineHandler);
|
|
462
|
+
}
|
|
406
463
|
/** Update connection parameters (call before connect) */
|
|
407
464
|
configure(params) {
|
|
408
465
|
Object.assign(this.config, params);
|
|
@@ -411,6 +468,8 @@ var WebSocketManager = class {
|
|
|
411
468
|
connect() {
|
|
412
469
|
if (this.ws?.readyState === WebSocket.OPEN) return;
|
|
413
470
|
this.isDestroyed = false;
|
|
471
|
+
if (this.firstConnectAt === null) this.firstConnectAt = Date.now();
|
|
472
|
+
this.setupOnlineListener();
|
|
414
473
|
const protocol = this.config.apiUrl.startsWith("https") ? "wss" : "ws";
|
|
415
474
|
const base = this.config.apiUrl.replace(/^https?/, protocol);
|
|
416
475
|
const params = new URLSearchParams({
|
|
@@ -424,6 +483,8 @@ var WebSocketManager = class {
|
|
|
424
483
|
const ws = new WebSocket(`${base}/ws?${params}`);
|
|
425
484
|
ws.onopen = () => {
|
|
426
485
|
this.reconnectAttempts = 0;
|
|
486
|
+
this.openedOnce = true;
|
|
487
|
+
this.gaveUp = false;
|
|
427
488
|
if (typeof document === "undefined" || document.visibilityState === "visible") {
|
|
428
489
|
this.startPing();
|
|
429
490
|
}
|
|
@@ -463,6 +524,10 @@ var WebSocketManager = class {
|
|
|
463
524
|
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
464
525
|
this.visibilityHandler = null;
|
|
465
526
|
}
|
|
527
|
+
if (this.onlineHandler && typeof window !== "undefined") {
|
|
528
|
+
window.removeEventListener("online", this.onlineHandler);
|
|
529
|
+
this.onlineHandler = null;
|
|
530
|
+
}
|
|
466
531
|
if (this.ws) {
|
|
467
532
|
this.ws.close(1e3, "Client disconnect");
|
|
468
533
|
this.ws = null;
|
|
@@ -489,9 +554,39 @@ var WebSocketManager = class {
|
|
|
489
554
|
get isConnected() {
|
|
490
555
|
return this.ws?.readyState === WebSocket.OPEN;
|
|
491
556
|
}
|
|
557
|
+
/** True once the socket has been open at least once. */
|
|
558
|
+
get hasOpened() {
|
|
559
|
+
return this.openedOnce;
|
|
560
|
+
}
|
|
561
|
+
/** When `connect()` was first called (ms epoch); null before that. */
|
|
562
|
+
get connectStartedAt() {
|
|
563
|
+
return this.firstConnectAt;
|
|
564
|
+
}
|
|
565
|
+
/** True once every automatic retry has failed and none is scheduled. */
|
|
566
|
+
get hasGivenUp() {
|
|
567
|
+
return this.gaveUp;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Start over with a full retry budget: the visitor pressed "Retry", or the
|
|
571
|
+
* browser came back online. Safe to call at any time; a no-op while
|
|
572
|
+
* connected or after `disconnect()`.
|
|
573
|
+
*/
|
|
574
|
+
retryNow() {
|
|
575
|
+
if (this.isDestroyed || this.isConnected) return;
|
|
576
|
+
if (this.reconnectTimer) {
|
|
577
|
+
clearTimeout(this.reconnectTimer);
|
|
578
|
+
this.reconnectTimer = null;
|
|
579
|
+
}
|
|
580
|
+
this.reconnectAttempts = 0;
|
|
581
|
+
this.gaveUp = false;
|
|
582
|
+
this.connect();
|
|
583
|
+
}
|
|
492
584
|
// ── Private ──────────────────────────────────────────
|
|
493
585
|
scheduleReconnect() {
|
|
494
|
-
if (this.reconnectAttempts >= this.maxReconnectAttempts)
|
|
586
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
587
|
+
this.gaveUp = true;
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
495
590
|
const delay = Math.min(1e3 * 2 ** this.reconnectAttempts, 3e4);
|
|
496
591
|
this.reconnectAttempts++;
|
|
497
592
|
this.reconnectTimer = setTimeout(() => {
|
|
@@ -512,6 +607,100 @@ var WebSocketManager = class {
|
|
|
512
607
|
}
|
|
513
608
|
};
|
|
514
609
|
|
|
610
|
+
// ../widget-core/src/dock-ink.ts
|
|
611
|
+
var WHITE = [255, 255, 255];
|
|
612
|
+
var NEAR_BLACK = [5, 5, 7];
|
|
613
|
+
var BLACK = [0, 0, 0];
|
|
614
|
+
var clamp = (n) => Math.min(255, Math.max(0, Math.round(n)));
|
|
615
|
+
function fromHsl(h, s, l) {
|
|
616
|
+
const a = s * Math.min(l, 1 - l);
|
|
617
|
+
const f = (n) => {
|
|
618
|
+
const k = (n + h / 30) % 12;
|
|
619
|
+
return clamp(255 * (l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1))));
|
|
620
|
+
};
|
|
621
|
+
return [f(0), f(8), f(4)];
|
|
622
|
+
}
|
|
623
|
+
function parseColor(input) {
|
|
624
|
+
if (!input) return null;
|
|
625
|
+
const v = input.trim().toLowerCase();
|
|
626
|
+
if (v.startsWith("#")) {
|
|
627
|
+
const short = /^#([0-9a-f])([0-9a-f])([0-9a-f])[0-9a-f]?$/.exec(v);
|
|
628
|
+
const long = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})(?:[0-9a-f]{2})?$/.exec(v);
|
|
629
|
+
const [, r, g, b] = short ?? long ?? [];
|
|
630
|
+
if (r === void 0 || g === void 0 || b === void 0) return null;
|
|
631
|
+
const channel = (digits) => Number.parseInt(short ? digits + digits : digits, 16);
|
|
632
|
+
return [channel(r), channel(g), channel(b)];
|
|
633
|
+
}
|
|
634
|
+
const [, kind, body] = /^(rgb|hsl)a?\(([^)]+)\)$/.exec(v) ?? [];
|
|
635
|
+
if (kind === void 0 || body === void 0) return null;
|
|
636
|
+
const [p0, p1, p2] = body.split(/[\s,/]+/).filter(Boolean);
|
|
637
|
+
if (p0 === void 0 || p1 === void 0 || p2 === void 0) return null;
|
|
638
|
+
const n0 = Number.parseFloat(p0);
|
|
639
|
+
const n1 = Number.parseFloat(p1);
|
|
640
|
+
const n2 = Number.parseFloat(p2);
|
|
641
|
+
if (Number.isNaN(n0) || Number.isNaN(n1) || Number.isNaN(n2)) return null;
|
|
642
|
+
if (kind === "rgb") {
|
|
643
|
+
const channel = (part, n) => clamp(part.endsWith("%") ? n * 2.55 : n);
|
|
644
|
+
return [channel(p0, n0), channel(p1, n1), channel(p2, n2)];
|
|
645
|
+
}
|
|
646
|
+
return fromHsl((n0 % 360 + 360) % 360, n1 / 100, n2 / 100);
|
|
647
|
+
}
|
|
648
|
+
function luminance([r, g, b]) {
|
|
649
|
+
const f = (c) => {
|
|
650
|
+
const s = c / 255;
|
|
651
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
652
|
+
};
|
|
653
|
+
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
|
|
654
|
+
}
|
|
655
|
+
function contrast(a, b) {
|
|
656
|
+
const la = luminance(a);
|
|
657
|
+
const lb = luminance(b);
|
|
658
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
659
|
+
}
|
|
660
|
+
function mix(a, b, amount) {
|
|
661
|
+
const channel = (x, y) => clamp(x * amount + y * (1 - amount));
|
|
662
|
+
return [channel(a[0], b[0]), channel(a[1], b[1]), channel(a[2], b[2])];
|
|
663
|
+
}
|
|
664
|
+
var toHex = (c) => `#${c.map((n) => n.toString(16).padStart(2, "0")).join("")}`;
|
|
665
|
+
function quiet(ink, tint, from, floor) {
|
|
666
|
+
for (let amount = from; amount < 1; amount += 0.02) {
|
|
667
|
+
const c = mix(ink, tint, amount);
|
|
668
|
+
if (contrast(c, tint) >= floor) return c;
|
|
669
|
+
}
|
|
670
|
+
return ink;
|
|
671
|
+
}
|
|
672
|
+
function dockInk(primaryColor) {
|
|
673
|
+
const tint = parseColor(primaryColor);
|
|
674
|
+
if (!tint) return null;
|
|
675
|
+
const onLight = contrast(WHITE, tint);
|
|
676
|
+
const useLight = onLight >= 4.5 || onLight >= contrast(NEAR_BLACK, tint);
|
|
677
|
+
const ink = useLight ? WHITE : NEAR_BLACK;
|
|
678
|
+
const shade = useLight ? BLACK : WHITE;
|
|
679
|
+
return {
|
|
680
|
+
tint: toHex(tint),
|
|
681
|
+
ink: toHex(ink),
|
|
682
|
+
shade: toHex(shade),
|
|
683
|
+
wash: toHex(contrast(ink, tint) >= 7 ? ink : shade),
|
|
684
|
+
ink2: toHex(quiet(ink, tint, 0.8, 4.5)),
|
|
685
|
+
ink3: toHex(quiet(ink, tint, 0.68, 4.5)),
|
|
686
|
+
ink4: toHex(quiet(ink, tint, 0.5, 3))
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// ../widget-core/src/connection-notice.ts
|
|
691
|
+
var RECONNECT_GRACE_MS = 2e3;
|
|
692
|
+
var FIRST_CONNECT_GRACE_MS = 8e3;
|
|
693
|
+
function connectionNotice(s) {
|
|
694
|
+
if (s.connected) return "none";
|
|
695
|
+
if (s.gaveUp) return "lost";
|
|
696
|
+
return showReconnecting(s) ? "reconnecting" : "none";
|
|
697
|
+
}
|
|
698
|
+
function showReconnecting(s) {
|
|
699
|
+
if (s.connected || s.startedAt === null) return false;
|
|
700
|
+
if (!s.hasOpened) return s.now - s.startedAt >= FIRST_CONNECT_GRACE_MS;
|
|
701
|
+
return s.downSince !== null && s.now - s.downSince >= RECONNECT_GRACE_MS;
|
|
702
|
+
}
|
|
703
|
+
|
|
515
704
|
// ../widget-core/src/store.ts
|
|
516
705
|
import { createStore } from "zustand/vanilla";
|
|
517
706
|
|
|
@@ -544,10 +733,12 @@ var en = {
|
|
|
544
733
|
// Composer
|
|
545
734
|
"widget.placeholder": "Send a message...",
|
|
546
735
|
"widget.placeholder_new": "How can we help?",
|
|
736
|
+
"widget.placeholder_resolved": "Reply to reopen this conversation\u2026",
|
|
547
737
|
"widget.drop_files": "Drop files here",
|
|
548
738
|
// CSAT
|
|
549
739
|
"widget.csat_label": "How was your experience?",
|
|
550
740
|
"widget.csat_thanks": "Thanks for your feedback!",
|
|
741
|
+
"widget.csat_error": "Couldn't save your rating. Please try again.",
|
|
551
742
|
// Inline email collection (after AI reply)
|
|
552
743
|
"widget.email_title": "Don't miss our reply",
|
|
553
744
|
"widget.email_subtitle": "We'll email you when we respond",
|
|
@@ -560,6 +751,7 @@ var en = {
|
|
|
560
751
|
"widget.error_desc": "Failed to load. Please try again.",
|
|
561
752
|
"widget.retry": "Retry",
|
|
562
753
|
"widget.reconnecting": "Reconnecting...",
|
|
754
|
+
"widget.connection_lost": "Connection lost",
|
|
563
755
|
"widget.send_error": "Message not sent",
|
|
564
756
|
// Date separators (today is implicit — never rendered)
|
|
565
757
|
"widget.yesterday": "Yesterday",
|
|
@@ -581,6 +773,13 @@ var en = {
|
|
|
581
773
|
// Copy
|
|
582
774
|
"widget.copy": "Copy message",
|
|
583
775
|
"widget.copied": "Copied",
|
|
776
|
+
/* The code-block button is its own three strings, not a reuse of the pair
|
|
777
|
+
above: that one copies a whole message and reads "Copy message", this one
|
|
778
|
+
sits inside a fenced block where the label has to stay one short word
|
|
779
|
+
(helpway#88). */
|
|
780
|
+
"widget.code_copy": "Copy",
|
|
781
|
+
"widget.code_copy_aria": "Copy code",
|
|
782
|
+
"widget.code_copy_failed": "Failed",
|
|
584
783
|
// File upload
|
|
585
784
|
"widget.file_too_large": "File too large (max 10 MB)",
|
|
586
785
|
"widget.click_to_open": "Click to open",
|
|
@@ -859,6 +1058,7 @@ function latestAssignee(items) {
|
|
|
859
1058
|
return null;
|
|
860
1059
|
}
|
|
861
1060
|
var AI_INDICATOR_MAX_MS = 45e3;
|
|
1061
|
+
var TYPING_IDLE_MS = 5e3;
|
|
862
1062
|
function createWidgetStore() {
|
|
863
1063
|
const indicatorWatchdogs = /* @__PURE__ */ new Map();
|
|
864
1064
|
const clearWatchdog = (conversationId) => {
|
|
@@ -868,6 +1068,14 @@ function createWidgetStore() {
|
|
|
868
1068
|
indicatorWatchdogs.delete(conversationId);
|
|
869
1069
|
}
|
|
870
1070
|
};
|
|
1071
|
+
const typingTimers = /* @__PURE__ */ new Map();
|
|
1072
|
+
const clearTypingTimer = (conversationId) => {
|
|
1073
|
+
const timer = typingTimers.get(conversationId);
|
|
1074
|
+
if (timer !== void 0) {
|
|
1075
|
+
clearTimeout(timer);
|
|
1076
|
+
typingTimers.delete(conversationId);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
871
1079
|
const store = createStore((set, get) => ({
|
|
872
1080
|
// Initial state
|
|
873
1081
|
isReady: false,
|
|
@@ -1027,6 +1235,7 @@ function createWidgetStore() {
|
|
|
1027
1235
|
});
|
|
1028
1236
|
},
|
|
1029
1237
|
remapConversationId(oldId, newId) {
|
|
1238
|
+
clearTypingTimer(oldId);
|
|
1030
1239
|
if (indicatorWatchdogs.has(oldId)) {
|
|
1031
1240
|
clearWatchdog(oldId);
|
|
1032
1241
|
indicatorWatchdogs.set(
|
|
@@ -1044,12 +1253,12 @@ function createWidgetStore() {
|
|
|
1044
1253
|
const existingItems = nextMessages.get(newId) ?? [];
|
|
1045
1254
|
const tempRewritten = tempItems.map((m) => ({ ...m, conversationId: newId }));
|
|
1046
1255
|
const isAgentMsg = (m) => !!m.aiAgentId && !m.visitorId && !m.userId;
|
|
1047
|
-
const
|
|
1256
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
1048
1257
|
const merged = [];
|
|
1049
1258
|
let keptAgentWelcome = false;
|
|
1050
1259
|
for (const m of tempRewritten) {
|
|
1051
|
-
if (
|
|
1052
|
-
|
|
1260
|
+
if (seen2.has(m.id)) continue;
|
|
1261
|
+
seen2.add(m.id);
|
|
1053
1262
|
merged.push(m);
|
|
1054
1263
|
if (isAgentMsg(m) && merged.length === 1) keptAgentWelcome = true;
|
|
1055
1264
|
}
|
|
@@ -1063,7 +1272,7 @@ function createWidgetStore() {
|
|
|
1063
1272
|
});
|
|
1064
1273
|
let graftedWelcome = false;
|
|
1065
1274
|
for (const m of existingItems) {
|
|
1066
|
-
if (
|
|
1275
|
+
if (seen2.has(m.id)) continue;
|
|
1067
1276
|
if (isVisitorMsg(m) && typeof m.text === "string" && pendingVisitor.has(m.text)) {
|
|
1068
1277
|
const idx = pendingVisitor.get(m.text);
|
|
1069
1278
|
pendingVisitor.delete(m.text);
|
|
@@ -1072,7 +1281,7 @@ function createWidgetStore() {
|
|
|
1072
1281
|
...m,
|
|
1073
1282
|
_stableKey: optimistic ? optimistic._stableKey ?? optimistic.id : m.id
|
|
1074
1283
|
};
|
|
1075
|
-
|
|
1284
|
+
seen2.add(m.id);
|
|
1076
1285
|
continue;
|
|
1077
1286
|
}
|
|
1078
1287
|
const isWelcomeEcho = isAgentMsg(m) && keptAgentWelcome && !graftedWelcome && (!serverVisitorTs || m.createdAt <= serverVisitorTs);
|
|
@@ -1082,11 +1291,11 @@ function createWidgetStore() {
|
|
|
1082
1291
|
...m,
|
|
1083
1292
|
_stableKey: seed ? seed._stableKey ?? seed.id : m.id
|
|
1084
1293
|
};
|
|
1085
|
-
|
|
1294
|
+
seen2.add(m.id);
|
|
1086
1295
|
graftedWelcome = true;
|
|
1087
1296
|
continue;
|
|
1088
1297
|
}
|
|
1089
|
-
|
|
1298
|
+
seen2.add(m.id);
|
|
1090
1299
|
merged.push(m);
|
|
1091
1300
|
}
|
|
1092
1301
|
nextMessages.delete(oldId);
|
|
@@ -1233,7 +1442,11 @@ function createWidgetStore() {
|
|
|
1233
1442
|
},
|
|
1234
1443
|
// ── Content Cache ────────────────────────────────
|
|
1235
1444
|
setContentCache(key, data) {
|
|
1236
|
-
|
|
1445
|
+
set((s) => {
|
|
1446
|
+
const next = new Map(s.contentCache);
|
|
1447
|
+
next.set(key, { data, ts: Date.now() });
|
|
1448
|
+
return { contentCache: next };
|
|
1449
|
+
});
|
|
1237
1450
|
},
|
|
1238
1451
|
// ── Realtime Event Handler ───────────────────────
|
|
1239
1452
|
handleRealtimeEvent(event) {
|
|
@@ -1309,10 +1522,15 @@ function createWidgetStore() {
|
|
|
1309
1522
|
case WsEventType.ConversationTyping: {
|
|
1310
1523
|
if (!event.visitorId) {
|
|
1311
1524
|
state.setTyping(event.conversationId, event.isTyping);
|
|
1525
|
+
clearTypingTimer(event.conversationId);
|
|
1312
1526
|
if (event.isTyping) {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1527
|
+
typingTimers.set(
|
|
1528
|
+
event.conversationId,
|
|
1529
|
+
setTimeout(() => {
|
|
1530
|
+
typingTimers.delete(event.conversationId);
|
|
1531
|
+
state.setTyping(event.conversationId, false);
|
|
1532
|
+
}, TYPING_IDLE_MS)
|
|
1533
|
+
);
|
|
1316
1534
|
}
|
|
1317
1535
|
}
|
|
1318
1536
|
break;
|
|
@@ -1396,7 +1614,7 @@ function installCallable(methods) {
|
|
|
1396
1614
|
return callable;
|
|
1397
1615
|
}
|
|
1398
1616
|
function createHelpwayAPI(deps) {
|
|
1399
|
-
const { store, emitter, identify, apiKey } = deps;
|
|
1617
|
+
const { store, emitter, identify, apiKey, apiUrl } = deps;
|
|
1400
1618
|
return {
|
|
1401
1619
|
open() {
|
|
1402
1620
|
store.getState().setOpen(true);
|
|
@@ -1431,6 +1649,14 @@ function createHelpwayAPI(deps) {
|
|
|
1431
1649
|
if (typeof document !== "undefined") {
|
|
1432
1650
|
document.cookie = "hw_visitor=; Path=/; Max-Age=0";
|
|
1433
1651
|
}
|
|
1652
|
+
if (apiUrl && typeof fetch !== "undefined") {
|
|
1653
|
+
void fetch(`${apiUrl.replace(/\/+$/, "")}/widget/reset-visitor`, {
|
|
1654
|
+
method: "POST",
|
|
1655
|
+
credentials: "include",
|
|
1656
|
+
headers: { "x-public-key": apiKey }
|
|
1657
|
+
}).catch(() => {
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1434
1660
|
},
|
|
1435
1661
|
identify,
|
|
1436
1662
|
newConversation(prefill) {
|
|
@@ -1503,6 +1729,21 @@ function applyTheme(host, theme) {
|
|
|
1503
1729
|
host.style.removeProperty("--hw-window-left");
|
|
1504
1730
|
}
|
|
1505
1731
|
if (theme.placement) host.dataset.hwPlacement = theme.placement;
|
|
1732
|
+
if (theme.dockSurface === "brand") {
|
|
1733
|
+
host.dataset.hwDockSurface = "brand";
|
|
1734
|
+
const ink = dockInk(theme.primaryColor);
|
|
1735
|
+
if (ink) {
|
|
1736
|
+
setVar(host, "--hw-dock-tint", ink.tint);
|
|
1737
|
+
setVar(host, "--hw-dock-ink", ink.ink);
|
|
1738
|
+
setVar(host, "--hw-dock-shade", ink.shade);
|
|
1739
|
+
setVar(host, "--hw-dock-wash", ink.wash);
|
|
1740
|
+
setVar(host, "--hw-dock-ink-2", ink.ink2);
|
|
1741
|
+
setVar(host, "--hw-dock-ink-3", ink.ink3);
|
|
1742
|
+
setVar(host, "--hw-dock-ink-4", ink.ink4);
|
|
1743
|
+
}
|
|
1744
|
+
} else if (theme.dockSurface === "glass") {
|
|
1745
|
+
delete host.dataset.hwDockSurface;
|
|
1746
|
+
}
|
|
1506
1747
|
if (theme.colorScheme === "light" || theme.colorScheme === "dark") {
|
|
1507
1748
|
host.dataset.theme = theme.colorScheme;
|
|
1508
1749
|
} else if (theme.colorScheme === "system") {
|
|
@@ -1626,6 +1867,43 @@ import {
|
|
|
1626
1867
|
useState
|
|
1627
1868
|
} from "react";
|
|
1628
1869
|
import { useStore } from "zustand";
|
|
1870
|
+
|
|
1871
|
+
// src/map-conversation.ts
|
|
1872
|
+
function mapConversation(c) {
|
|
1873
|
+
return {
|
|
1874
|
+
id: c.id,
|
|
1875
|
+
title: c.title,
|
|
1876
|
+
status: c.status,
|
|
1877
|
+
lastMessageText: c.lastMessageText,
|
|
1878
|
+
lastMessageAt: c.lastMessageAt,
|
|
1879
|
+
lastMessageSenderType: c.lastMessageSenderType,
|
|
1880
|
+
lastMessageSenderName: c.lastMessageSenderName,
|
|
1881
|
+
lastMessageSenderImage: c.lastMessageSenderImage,
|
|
1882
|
+
/* The server's count, not a zero.
|
|
1883
|
+
|
|
1884
|
+
This was the literal `0`, which meant `useUnread()` answered 0 on every
|
|
1885
|
+
page load however many replies were waiting — the value described
|
|
1886
|
+
"messages that arrived while this tab has been open", not "unread". A
|
|
1887
|
+
badge shipped against the hook downstream never rendered once, with an
|
|
1888
|
+
unanswered agent message on screen.
|
|
1889
|
+
|
|
1890
|
+
Still defaulted, because a widget on an older API build gets a payload
|
|
1891
|
+
without the field, and 0 is the honest answer there — the socket path
|
|
1892
|
+
raises it from there as messages land. */
|
|
1893
|
+
unreadCount: c.unreadCount ?? 0,
|
|
1894
|
+
/* `?? null`, not left undefined: the store type says `string | null`, and
|
|
1895
|
+
undefined would satisfy it structurally while meaning something else to
|
|
1896
|
+
every reader downstream. */
|
|
1897
|
+
assigneeName: c.assigneeName ?? null,
|
|
1898
|
+
assigneeImage: c.assigneeImage ?? null,
|
|
1899
|
+
/* The visitor's own answer. Without it the resolved block asked "How was
|
|
1900
|
+
your experience?" again on every page load, to someone who had already
|
|
1901
|
+
said, and the server then refused the second answer. */
|
|
1902
|
+
csatRating: c.csatRating ?? null
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// src/provider.tsx
|
|
1629
1907
|
import { jsx } from "react/jsx-runtime";
|
|
1630
1908
|
var WidgetContext = createContext(null);
|
|
1631
1909
|
function useWidgetContext() {
|
|
@@ -1650,6 +1928,7 @@ function useWidgetClient() {
|
|
|
1650
1928
|
function SupportProvider({
|
|
1651
1929
|
apiKey,
|
|
1652
1930
|
apiUrl,
|
|
1931
|
+
surface,
|
|
1653
1932
|
locale,
|
|
1654
1933
|
initialConversationId,
|
|
1655
1934
|
deepLinkToken,
|
|
@@ -1664,6 +1943,7 @@ function SupportProvider({
|
|
|
1664
1943
|
const initRef = useRef(null);
|
|
1665
1944
|
const [hasBootstrapError, setHasBootstrapError] = useState(false);
|
|
1666
1945
|
const [wsDisconnected, setWsDisconnected] = useState(false);
|
|
1946
|
+
const [wsLost, setWsLost] = useState(false);
|
|
1667
1947
|
const [bootstrapAttempt, setBootstrapAttempt] = useState(0);
|
|
1668
1948
|
const sourceLocaleRef = useRef(locale);
|
|
1669
1949
|
const getSourceLocale = useCallback(() => sourceLocaleRef.current, []);
|
|
@@ -1671,7 +1951,8 @@ function SupportProvider({
|
|
|
1671
1951
|
const resolvedApiUrl = apiUrl ?? inferApiUrl();
|
|
1672
1952
|
const client2 = createWidgetClient({
|
|
1673
1953
|
apiUrl: resolvedApiUrl,
|
|
1674
|
-
apiKey
|
|
1954
|
+
apiKey,
|
|
1955
|
+
surface
|
|
1675
1956
|
});
|
|
1676
1957
|
const store2 = createWidgetStore();
|
|
1677
1958
|
const emitter2 = new WidgetEventEmitter();
|
|
@@ -1700,7 +1981,7 @@ function SupportProvider({
|
|
|
1700
1981
|
console.error("[Helpway] identify failed:", err);
|
|
1701
1982
|
}
|
|
1702
1983
|
};
|
|
1703
|
-
const api2 = createHelpwayAPI({ store: store2, emitter: emitter2, identify: identify2, apiKey });
|
|
1984
|
+
const api2 = createHelpwayAPI({ store: store2, emitter: emitter2, identify: identify2, apiKey, apiUrl: resolvedApiUrl });
|
|
1704
1985
|
initRef.current = { client: client2, store: store2, ws: ws2, identify: identify2, api: api2, emitter: emitter2 };
|
|
1705
1986
|
}
|
|
1706
1987
|
const { client, store, ws, identify, api, emitter } = initRef.current;
|
|
@@ -1726,28 +2007,6 @@ function SupportProvider({
|
|
|
1726
2007
|
}
|
|
1727
2008
|
const convData = await client.widget.listConversations.query();
|
|
1728
2009
|
if (cancelled) return;
|
|
1729
|
-
const mapConversation = (c) => ({
|
|
1730
|
-
id: c.id,
|
|
1731
|
-
title: c.title,
|
|
1732
|
-
status: c.status,
|
|
1733
|
-
lastMessageText: c.lastMessageText,
|
|
1734
|
-
lastMessageAt: c.lastMessageAt,
|
|
1735
|
-
lastMessageSenderType: c.lastMessageSenderType,
|
|
1736
|
-
lastMessageSenderName: c.lastMessageSenderName,
|
|
1737
|
-
lastMessageSenderImage: c.lastMessageSenderImage,
|
|
1738
|
-
/* The server's count, not a zero.
|
|
1739
|
-
|
|
1740
|
-
This was the literal `0`, which meant `useUnread()` answered 0 on
|
|
1741
|
-
every page load however many replies were waiting — the value
|
|
1742
|
-
described "messages that arrived while this tab has been open",
|
|
1743
|
-
not "unread". A badge shipped against the hook downstream never
|
|
1744
|
-
rendered once, with an unanswered agent message on screen.
|
|
1745
|
-
|
|
1746
|
-
Still defaulted, because a widget on an older API build gets a
|
|
1747
|
-
payload without the field, and 0 is the honest answer there — the
|
|
1748
|
-
socket path raises it from there as messages land. */
|
|
1749
|
-
unreadCount: c.unreadCount ?? 0
|
|
1750
|
-
});
|
|
1751
2010
|
store.getState().setConversations(convData.conversations.map(mapConversation));
|
|
1752
2011
|
if (data.website?.id && data.visitor?.id) {
|
|
1753
2012
|
ws.configure({ websiteId: data.website.id, visitorId: data.visitor.id });
|
|
@@ -1882,16 +2141,21 @@ function SupportProvider({
|
|
|
1882
2141
|
if (isViewing) scheduleMarkSeen(event.conversationId);
|
|
1883
2142
|
}
|
|
1884
2143
|
});
|
|
1885
|
-
const DOWN_GRACE_MS = 2e3;
|
|
1886
2144
|
let downSince = null;
|
|
1887
2145
|
const wsCheck = setInterval(() => {
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2146
|
+
const connected = ws.isConnected;
|
|
2147
|
+
if (connected) downSince = null;
|
|
2148
|
+
else if (downSince === null) downSince = Date.now();
|
|
2149
|
+
const notice = connectionNotice({
|
|
2150
|
+
connected,
|
|
2151
|
+
hasOpened: ws.hasOpened ?? false,
|
|
2152
|
+
startedAt: ws.connectStartedAt ?? null,
|
|
2153
|
+
downSince,
|
|
2154
|
+
now: Date.now(),
|
|
2155
|
+
gaveUp: ws.hasGivenUp ?? false
|
|
2156
|
+
});
|
|
2157
|
+
setWsDisconnected(notice === "reconnecting");
|
|
2158
|
+
setWsLost(notice === "lost");
|
|
1895
2159
|
}, 1e3);
|
|
1896
2160
|
return () => {
|
|
1897
2161
|
cancelled = true;
|
|
@@ -1982,6 +2246,14 @@ function SupportProvider({
|
|
|
1982
2246
|
emitter,
|
|
1983
2247
|
hasBootstrapError,
|
|
1984
2248
|
wsDisconnected,
|
|
2249
|
+
wsLost,
|
|
2250
|
+
/* Answer the press on screen at once: the strip goes back to
|
|
2251
|
+
"Reconnecting…" now, not at the next one-second sample. */
|
|
2252
|
+
retryConnection: () => {
|
|
2253
|
+
ws.retryNow?.();
|
|
2254
|
+
setWsLost(false);
|
|
2255
|
+
setWsDisconnected(true);
|
|
2256
|
+
},
|
|
1985
2257
|
retryBootstrap,
|
|
1986
2258
|
getSourceLocale
|
|
1987
2259
|
};
|
|
@@ -2083,7 +2355,7 @@ function inferApiUrl() {
|
|
|
2083
2355
|
}
|
|
2084
2356
|
|
|
2085
2357
|
// src/themed/default-widget.tsx
|
|
2086
|
-
import { createContext as createContext2, useCallback as
|
|
2358
|
+
import { createContext as createContext2, useCallback as useCallback14, useContext as useContext2, useEffect as useEffect16, useRef as useRef17, useState as useState17 } from "react";
|
|
2087
2359
|
|
|
2088
2360
|
// src/hooks/use-announcements.ts
|
|
2089
2361
|
import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
|
|
@@ -2108,22 +2380,22 @@ function getSeenSlugs(websiteId, visitorId) {
|
|
|
2108
2380
|
}
|
|
2109
2381
|
function addSeenSlug(websiteId, visitorId, slug) {
|
|
2110
2382
|
try {
|
|
2111
|
-
const
|
|
2112
|
-
|
|
2113
|
-
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...
|
|
2383
|
+
const seen2 = getSeenSlugs(websiteId, visitorId);
|
|
2384
|
+
seen2.add(slug);
|
|
2385
|
+
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen2]));
|
|
2114
2386
|
} catch {
|
|
2115
2387
|
}
|
|
2116
2388
|
}
|
|
2117
2389
|
function addSeenSlugs(websiteId, visitorId, slugs) {
|
|
2118
2390
|
try {
|
|
2119
|
-
const
|
|
2120
|
-
for (const s of slugs)
|
|
2121
|
-
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...
|
|
2391
|
+
const seen2 = getSeenSlugs(websiteId, visitorId);
|
|
2392
|
+
for (const s of slugs) seen2.add(s);
|
|
2393
|
+
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen2]));
|
|
2122
2394
|
} catch {
|
|
2123
2395
|
}
|
|
2124
2396
|
}
|
|
2125
|
-
function filterUnseen(entries,
|
|
2126
|
-
return entries.filter((e) => !
|
|
2397
|
+
function filterUnseen(entries, seen2) {
|
|
2398
|
+
return entries.filter((e) => !seen2.has(e.slug));
|
|
2127
2399
|
}
|
|
2128
2400
|
var EMPTY_TABS = [];
|
|
2129
2401
|
function useAnnouncements() {
|
|
@@ -2149,8 +2421,8 @@ function useAnnouncements() {
|
|
|
2149
2421
|
function onTabDone(entries, tab) {
|
|
2150
2422
|
allSlugs.push(...entries.map((e) => e.slug));
|
|
2151
2423
|
if (!(isFirstVisit && !isAnonymous) && entries.length > 0) {
|
|
2152
|
-
const
|
|
2153
|
-
const unseen = filterUnseen(entries,
|
|
2424
|
+
const seen2 = getSeenSlugs(websiteId, visitorId);
|
|
2425
|
+
const unseen = filterUnseen(entries, seen2);
|
|
2154
2426
|
totalUnseen += unseen.length;
|
|
2155
2427
|
const newest = unseen[0];
|
|
2156
2428
|
if (newest && !store.getState().isOpen) {
|
|
@@ -2196,13 +2468,13 @@ function useAnnouncements() {
|
|
|
2196
2468
|
(slug) => {
|
|
2197
2469
|
if (!websiteId || !visitorId || announcementTabs.length === 0) return;
|
|
2198
2470
|
addSeenSlug(websiteId, visitorId, slug);
|
|
2199
|
-
const
|
|
2471
|
+
const seen2 = getSeenSlugs(websiteId, visitorId);
|
|
2200
2472
|
let total = 0;
|
|
2201
2473
|
for (const tab of announcementTabs) {
|
|
2202
2474
|
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
2203
2475
|
const cached = store.getState().contentCache.get(cacheKey);
|
|
2204
2476
|
if (cached) {
|
|
2205
|
-
total += filterUnseen(cached.data,
|
|
2477
|
+
total += filterUnseen(cached.data, seen2).length;
|
|
2206
2478
|
}
|
|
2207
2479
|
}
|
|
2208
2480
|
store.getState().setUnseenAnnouncementCount(total);
|
|
@@ -2225,13 +2497,13 @@ function useAnnouncements() {
|
|
|
2225
2497
|
}, [websiteId, visitorId, announcementTabs, store]);
|
|
2226
2498
|
const getUnseenEntries = useCallback2(() => {
|
|
2227
2499
|
if (announcementTabs.length === 0 || !websiteId || !visitorId) return [];
|
|
2228
|
-
const
|
|
2500
|
+
const seen2 = getSeenSlugs(websiteId, visitorId);
|
|
2229
2501
|
const result = [];
|
|
2230
2502
|
for (const tab of announcementTabs) {
|
|
2231
2503
|
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
2232
2504
|
const cached = store.getState().contentCache.get(cacheKey);
|
|
2233
2505
|
if (cached) {
|
|
2234
|
-
for (const entry of filterUnseen(cached.data,
|
|
2506
|
+
for (const entry of filterUnseen(cached.data, seen2)) {
|
|
2235
2507
|
result.push({ ...entry, tabId: tab.id });
|
|
2236
2508
|
}
|
|
2237
2509
|
}
|
|
@@ -2252,7 +2524,7 @@ function useAwaitingReply() {
|
|
|
2252
2524
|
}
|
|
2253
2525
|
|
|
2254
2526
|
// src/hooks/use-composer.ts
|
|
2255
|
-
import { useCallback as useCallback3, useState as useState2 } from "react";
|
|
2527
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
2256
2528
|
function currentPagePayload() {
|
|
2257
2529
|
if (typeof window === "undefined") return {};
|
|
2258
2530
|
const url = window.location.href;
|
|
@@ -2260,28 +2532,27 @@ function currentPagePayload() {
|
|
|
2260
2532
|
return { page: { url, title: document.title || window.location.pathname } };
|
|
2261
2533
|
}
|
|
2262
2534
|
var MAX_ATTACHMENTS = 10;
|
|
2263
|
-
var
|
|
2264
|
-
var ACCEPTED_TYPES =
|
|
2265
|
-
"image/png",
|
|
2266
|
-
"image/jpeg",
|
|
2267
|
-
"image/gif",
|
|
2268
|
-
"image/webp",
|
|
2269
|
-
"image/svg+xml",
|
|
2270
|
-
"application/pdf",
|
|
2271
|
-
"text/plain",
|
|
2272
|
-
"text/csv",
|
|
2273
|
-
"application/zip",
|
|
2274
|
-
"application/msword",
|
|
2275
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
2276
|
-
"application/vnd.ms-excel",
|
|
2277
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
2278
|
-
].join(",");
|
|
2535
|
+
var MAX_FILE_SIZE2 = 10 * 1024 * 1024;
|
|
2536
|
+
var ACCEPTED_TYPES = acceptAttribute();
|
|
2279
2537
|
function useComposer(boundConversationId) {
|
|
2280
2538
|
const { client, ws, store, getSourceLocale } = useWidgetContext();
|
|
2281
2539
|
const conversationId = boundConversationId;
|
|
2282
2540
|
const [text, setText] = useState2("");
|
|
2283
2541
|
const [isSubmitting, setIsSubmitting] = useState2(false);
|
|
2284
2542
|
const [attachments, setAttachments] = useState2([]);
|
|
2543
|
+
const liveUrls = useRef3(/* @__PURE__ */ new Set());
|
|
2544
|
+
useEffect3(() => {
|
|
2545
|
+
const urls = liveUrls.current;
|
|
2546
|
+
return () => {
|
|
2547
|
+
for (const url of urls) URL.revokeObjectURL(url);
|
|
2548
|
+
urls.clear();
|
|
2549
|
+
};
|
|
2550
|
+
}, []);
|
|
2551
|
+
const revoke = useCallback3((url) => {
|
|
2552
|
+
if (!url) return;
|
|
2553
|
+
URL.revokeObjectURL(url);
|
|
2554
|
+
liveUrls.current.delete(url);
|
|
2555
|
+
}, []);
|
|
2285
2556
|
const [sendError, setSendError] = useState2(null);
|
|
2286
2557
|
const [emailGateConvId, setEmailGateConvId] = useState2(null);
|
|
2287
2558
|
const addFiles = useCallback3(
|
|
@@ -2290,10 +2561,15 @@ function useComposer(boundConversationId) {
|
|
|
2290
2561
|
const remaining = MAX_ATTACHMENTS - attachments.length;
|
|
2291
2562
|
const toAdd = files.slice(0, remaining);
|
|
2292
2563
|
if (toAdd.length === 0) return;
|
|
2564
|
+
const makePreviewUrl = (file) => {
|
|
2565
|
+
const url = URL.createObjectURL(file);
|
|
2566
|
+
liveUrls.current.add(url);
|
|
2567
|
+
return url;
|
|
2568
|
+
};
|
|
2293
2569
|
const pending = toAdd.map((file) => ({
|
|
2294
2570
|
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
2295
2571
|
file,
|
|
2296
|
-
previewUrl: file.type.startsWith("image/") ?
|
|
2572
|
+
previewUrl: file.type.startsWith("image/") ? makePreviewUrl(file) : null,
|
|
2297
2573
|
isUploading: true,
|
|
2298
2574
|
error: null,
|
|
2299
2575
|
part: null
|
|
@@ -2301,7 +2577,7 @@ function useComposer(boundConversationId) {
|
|
|
2301
2577
|
setAttachments((prev) => [...prev, ...pending]);
|
|
2302
2578
|
for (const item of pending) {
|
|
2303
2579
|
try {
|
|
2304
|
-
if (item.file.size >
|
|
2580
|
+
if (item.file.size > MAX_FILE_SIZE2) {
|
|
2305
2581
|
throw new Error(t("widget.file_too_large"));
|
|
2306
2582
|
}
|
|
2307
2583
|
const base64 = await fileToBase64(item.file);
|
|
@@ -2327,13 +2603,13 @@ function useComposer(boundConversationId) {
|
|
|
2327
2603
|
},
|
|
2328
2604
|
[conversationId, attachments.length, client]
|
|
2329
2605
|
);
|
|
2330
|
-
const removeAttachment = useCallback3(
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2606
|
+
const removeAttachment = useCallback3(
|
|
2607
|
+
(id) => {
|
|
2608
|
+
revoke(attachments.find((a) => a.id === id)?.previewUrl);
|
|
2609
|
+
setAttachments((prev) => prev.filter((a) => a.id !== id));
|
|
2610
|
+
},
|
|
2611
|
+
[attachments, revoke]
|
|
2612
|
+
);
|
|
2337
2613
|
const submit = useCallback3(
|
|
2338
2614
|
async (override) => {
|
|
2339
2615
|
const conversationId2 = override?.conversationId ?? boundConversationId;
|
|
@@ -2432,9 +2708,7 @@ function useComposer(boundConversationId) {
|
|
|
2432
2708
|
});
|
|
2433
2709
|
store.getState().replaceMessage(conversationId2, optimisticId, result.item);
|
|
2434
2710
|
}
|
|
2435
|
-
for (const a of attachmentsSnapshot)
|
|
2436
|
-
if (a.previewUrl) URL.revokeObjectURL(a.previewUrl);
|
|
2437
|
-
}
|
|
2711
|
+
for (const a of attachmentsSnapshot) revoke(a.previewUrl);
|
|
2438
2712
|
} catch (err) {
|
|
2439
2713
|
console.error("[useComposer] Send failed:", err);
|
|
2440
2714
|
store.getState().removeMessage(conversationId2, optimisticId);
|
|
@@ -2478,16 +2752,16 @@ function fileToBase64(file) {
|
|
|
2478
2752
|
}
|
|
2479
2753
|
|
|
2480
2754
|
// src/hooks/use-conversations.ts
|
|
2481
|
-
import { useCallback as useCallback4, useEffect as
|
|
2755
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4, useState as useState3 } from "react";
|
|
2482
2756
|
function useConversations() {
|
|
2483
2757
|
const { client, store, getSourceLocale } = useWidgetContext();
|
|
2484
2758
|
const conversations = useWidgetStore((s) => s.conversations);
|
|
2485
2759
|
const setActiveConversation = useWidgetStore((s) => s.setActiveConversation);
|
|
2486
2760
|
const [isCreating, setIsCreating] = useState3(false);
|
|
2487
|
-
const clientRef =
|
|
2488
|
-
const storeRef =
|
|
2489
|
-
const getSourceLocaleRef =
|
|
2490
|
-
|
|
2761
|
+
const clientRef = useRef4(client);
|
|
2762
|
+
const storeRef = useRef4(store);
|
|
2763
|
+
const getSourceLocaleRef = useRef4(getSourceLocale);
|
|
2764
|
+
useEffect4(() => {
|
|
2491
2765
|
clientRef.current = client;
|
|
2492
2766
|
storeRef.current = store;
|
|
2493
2767
|
getSourceLocaleRef.current = getSourceLocale;
|
|
@@ -2588,10 +2862,10 @@ function useHeaderIdentity() {
|
|
|
2588
2862
|
}
|
|
2589
2863
|
|
|
2590
2864
|
// src/hooks/use-i18n.ts
|
|
2591
|
-
import { useEffect as
|
|
2865
|
+
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
2592
2866
|
function useI18n() {
|
|
2593
2867
|
const [rev, setRev] = useState4(() => getI18nRevision());
|
|
2594
|
-
|
|
2868
|
+
useEffect5(() => {
|
|
2595
2869
|
return onLocaleChange(() => {
|
|
2596
2870
|
setRev(getI18nRevision());
|
|
2597
2871
|
});
|
|
@@ -2600,7 +2874,7 @@ function useI18n() {
|
|
|
2600
2874
|
}
|
|
2601
2875
|
|
|
2602
2876
|
// src/hooks/use-presence.ts
|
|
2603
|
-
import { useCallback as useCallback5, useRef as
|
|
2877
|
+
import { useCallback as useCallback5, useRef as useRef5 } from "react";
|
|
2604
2878
|
function usePresence(conversationId) {
|
|
2605
2879
|
const { ws } = useWidgetContext();
|
|
2606
2880
|
const isTyping = useWidgetStore(
|
|
@@ -2609,8 +2883,8 @@ function usePresence(conversationId) {
|
|
|
2609
2883
|
const isAiProcessing = useWidgetStore(
|
|
2610
2884
|
(s) => conversationId ? s.aiProcessing.get(conversationId) ?? false : false
|
|
2611
2885
|
);
|
|
2612
|
-
const typingTimer =
|
|
2613
|
-
const isSendingTyping =
|
|
2886
|
+
const typingTimer = useRef5(null);
|
|
2887
|
+
const isSendingTyping = useRef5(false);
|
|
2614
2888
|
const setTyping = useCallback5(
|
|
2615
2889
|
(typing) => {
|
|
2616
2890
|
if (!conversationId) return;
|
|
@@ -2637,7 +2911,7 @@ function usePresence(conversationId) {
|
|
|
2637
2911
|
}
|
|
2638
2912
|
|
|
2639
2913
|
// src/hooks/use-timeline.ts
|
|
2640
|
-
import { useCallback as useCallback6, useEffect as
|
|
2914
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
|
|
2641
2915
|
var EMPTY_ITEMS = [];
|
|
2642
2916
|
function useTimeline(conversationId) {
|
|
2643
2917
|
const { client, store } = useWidgetContext();
|
|
@@ -2646,14 +2920,14 @@ function useTimeline(conversationId) {
|
|
|
2646
2920
|
);
|
|
2647
2921
|
const [isLoading, setIsLoading] = useState5(false);
|
|
2648
2922
|
const [hasMore, setHasMore] = useState5(false);
|
|
2649
|
-
const cursorRef =
|
|
2650
|
-
const clientRef =
|
|
2651
|
-
const storeRef =
|
|
2652
|
-
|
|
2923
|
+
const cursorRef = useRef6(void 0);
|
|
2924
|
+
const clientRef = useRef6(client);
|
|
2925
|
+
const storeRef = useRef6(store);
|
|
2926
|
+
useEffect6(() => {
|
|
2653
2927
|
clientRef.current = client;
|
|
2654
2928
|
storeRef.current = store;
|
|
2655
2929
|
});
|
|
2656
|
-
|
|
2930
|
+
useEffect6(() => {
|
|
2657
2931
|
if (!conversationId) return;
|
|
2658
2932
|
if (conversationId.startsWith("temp-")) return;
|
|
2659
2933
|
let cancelled = false;
|
|
@@ -2737,10 +3011,10 @@ function useWidget() {
|
|
|
2737
3011
|
}
|
|
2738
3012
|
|
|
2739
3013
|
// src/shell/docked-bar.tsx
|
|
2740
|
-
import { useCallback as useCallback8, useEffect as
|
|
3014
|
+
import { useCallback as useCallback8, useEffect as useEffect7, useRef as useRef8, useState as useState7 } from "react";
|
|
2741
3015
|
|
|
2742
3016
|
// src/themed/composer.tsx
|
|
2743
|
-
import { useCallback as useCallback7, useRef as
|
|
3017
|
+
import { useCallback as useCallback7, useRef as useRef7, useState as useState6 } from "react";
|
|
2744
3018
|
|
|
2745
3019
|
// src/themed/icons.tsx
|
|
2746
3020
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
@@ -2964,22 +3238,48 @@ function StarIcon({ size = 24, ...props }) {
|
|
|
2964
3238
|
}
|
|
2965
3239
|
);
|
|
2966
3240
|
}
|
|
2967
|
-
function
|
|
2968
|
-
return /* @__PURE__ */
|
|
3241
|
+
function CheckCircleIcon({ size = 24, ...props }) {
|
|
3242
|
+
return /* @__PURE__ */ jsx2(
|
|
2969
3243
|
"svg",
|
|
2970
3244
|
{
|
|
2971
|
-
width: size,
|
|
2972
|
-
height: size,
|
|
3245
|
+
width: typeof size === "number" ? `${size}px` : size,
|
|
3246
|
+
height: typeof size === "number" ? `${size}px` : size,
|
|
2973
3247
|
viewBox: "0 0 24 24",
|
|
2974
3248
|
fill: "none",
|
|
3249
|
+
"aria-hidden": true,
|
|
2975
3250
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2976
|
-
"aria-hidden": "true",
|
|
2977
3251
|
...props,
|
|
2978
|
-
children:
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
3252
|
+
children: /* @__PURE__ */ jsx2("path", { d: "M15 9.5L10.5 15L8.5 13M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
3253
|
+
}
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3256
|
+
function ThumbsUpIcon({ size = 24, ...props }) {
|
|
3257
|
+
return /* @__PURE__ */ jsx2(
|
|
3258
|
+
"svg",
|
|
3259
|
+
{
|
|
3260
|
+
width: typeof size === "number" ? `${size}px` : size,
|
|
3261
|
+
height: typeof size === "number" ? `${size}px` : size,
|
|
3262
|
+
viewBox: "0 0 24 24",
|
|
3263
|
+
fill: "none",
|
|
3264
|
+
"aria-hidden": true,
|
|
3265
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3266
|
+
...props,
|
|
3267
|
+
children: /* @__PURE__ */ jsx2("path", { d: "M7 11H4C3.44772 11 3 11.4477 3 12V19C3 19.5523 3.44772 20 4 20H7M7 11V20M7 11L11 3H11.6156C12.843 3 13.7808 4.09535 13.5917 5.3081L13.0161 9H18.0631C19.8811 9 21.2813 10.6041 21.0356 12.4053L20.3538 17.4053C20.1511 18.8918 18.8815 20 17.3813 20H7", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })
|
|
3268
|
+
}
|
|
3269
|
+
);
|
|
3270
|
+
}
|
|
3271
|
+
function ThumbsDownIcon({ size = 24, ...props }) {
|
|
3272
|
+
return /* @__PURE__ */ jsx2(
|
|
3273
|
+
"svg",
|
|
3274
|
+
{
|
|
3275
|
+
width: typeof size === "number" ? `${size}px` : size,
|
|
3276
|
+
height: typeof size === "number" ? `${size}px` : size,
|
|
3277
|
+
viewBox: "0 0 24 24",
|
|
3278
|
+
fill: "none",
|
|
3279
|
+
"aria-hidden": true,
|
|
3280
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3281
|
+
...props,
|
|
3282
|
+
children: /* @__PURE__ */ jsx2("path", { d: "M17 13H20C20.5523 13 21 12.5523 21 12L21 5C21 4.44772 20.5523 4 20 4H17M17 13L17 4M17 13L13.301 20.4505C13.1339 20.7871 12.7905 21 12.4147 21V21C11.1917 21 10.2572 19.9046 10.4456 18.6919L11.0192 15L5.98994 15C4.17839 15 2.78316 13.3959 3.02793 11.5947L3.70735 6.59466C3.90933 5.1082 5.17443 4 6.66936 4H17", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })
|
|
2983
3283
|
}
|
|
2984
3284
|
);
|
|
2985
3285
|
}
|
|
@@ -3001,9 +3301,9 @@ function Composer({
|
|
|
3001
3301
|
onRemoveAttachment,
|
|
3002
3302
|
disabled
|
|
3003
3303
|
}) {
|
|
3004
|
-
const ref =
|
|
3005
|
-
const fileInputRef =
|
|
3006
|
-
const supportsFieldSizing =
|
|
3304
|
+
const ref = useRef7(null);
|
|
3305
|
+
const fileInputRef = useRef7(null);
|
|
3306
|
+
const supportsFieldSizing = useRef7(
|
|
3007
3307
|
typeof CSS !== "undefined" && CSS.supports?.("field-sizing", "content")
|
|
3008
3308
|
);
|
|
3009
3309
|
const handleKeyDown = useCallback7(
|
|
@@ -3043,7 +3343,7 @@ function Composer({
|
|
|
3043
3343
|
[onAddFiles]
|
|
3044
3344
|
);
|
|
3045
3345
|
const [isDragging, setIsDragging] = useState6(false);
|
|
3046
|
-
const dragCountRef =
|
|
3346
|
+
const dragCountRef = useRef7(0);
|
|
3047
3347
|
const handleDragEnter = useCallback7((e) => {
|
|
3048
3348
|
e.preventDefault();
|
|
3049
3349
|
dragCountRef.current++;
|
|
@@ -3209,13 +3509,13 @@ function recognitionCtor() {
|
|
|
3209
3509
|
}
|
|
3210
3510
|
function useDictation(onText) {
|
|
3211
3511
|
const [listening, setListening] = useState7(false);
|
|
3212
|
-
const recRef =
|
|
3213
|
-
const onTextRef =
|
|
3214
|
-
|
|
3512
|
+
const recRef = useRef8(null);
|
|
3513
|
+
const onTextRef = useRef8(onText);
|
|
3514
|
+
useEffect7(() => {
|
|
3215
3515
|
onTextRef.current = onText;
|
|
3216
3516
|
}, [onText]);
|
|
3217
3517
|
const [supported] = useState7(() => recognitionCtor() !== null);
|
|
3218
|
-
|
|
3518
|
+
useEffect7(
|
|
3219
3519
|
() => () => {
|
|
3220
3520
|
recRef.current?.stop();
|
|
3221
3521
|
recRef.current = null;
|
|
@@ -3284,9 +3584,9 @@ function DockedBar({
|
|
|
3284
3584
|
leading
|
|
3285
3585
|
}) {
|
|
3286
3586
|
const [focused, setFocused] = useState7(false);
|
|
3287
|
-
const inputRef =
|
|
3288
|
-
const boxRef =
|
|
3289
|
-
const fileInputRef =
|
|
3587
|
+
const inputRef = useRef8(null);
|
|
3588
|
+
const boxRef = useRef8(null);
|
|
3589
|
+
const fileInputRef = useRef8(null);
|
|
3290
3590
|
const { questions: visibleQuestions, dismiss: dismissOffer } = useDismissableOffer(suggestions);
|
|
3291
3591
|
const dictation = useDictation((chunk) => {
|
|
3292
3592
|
const current = inputRef.current?.value ?? value;
|
|
@@ -3302,7 +3602,7 @@ function DockedBar({
|
|
|
3302
3602
|
el.style.height = `${next}px`;
|
|
3303
3603
|
box.dataset.grown = next > GROWN_AT ? "true" : "false";
|
|
3304
3604
|
}, []);
|
|
3305
|
-
|
|
3605
|
+
useEffect7(grow, [grow, value]);
|
|
3306
3606
|
const handleKeyDown = useCallback8(
|
|
3307
3607
|
(event) => {
|
|
3308
3608
|
if (event.key !== "Enter" || event.shiftKey) return;
|
|
@@ -3599,11 +3899,50 @@ function AnnouncementPreviewItem({
|
|
|
3599
3899
|
);
|
|
3600
3900
|
}
|
|
3601
3901
|
|
|
3902
|
+
// src/themed/connection-strip.tsx
|
|
3903
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3904
|
+
function ConnectionStrip({
|
|
3905
|
+
reconnecting,
|
|
3906
|
+
lost,
|
|
3907
|
+
onRetry
|
|
3908
|
+
}) {
|
|
3909
|
+
if (lost) {
|
|
3910
|
+
return (
|
|
3911
|
+
// biome-ignore lint/a11y/useSemanticElements: <output> is a form element and is styled by host pages; a div with the role is announced the same
|
|
3912
|
+
/* @__PURE__ */ jsxs5("div", { className: "hw-disconnect", role: "status", children: [
|
|
3913
|
+
/* @__PURE__ */ jsx6("span", { children: t("widget.connection_lost") }),
|
|
3914
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "hw-disconnect-retry", onClick: onRetry, children: t("widget.retry") })
|
|
3915
|
+
] })
|
|
3916
|
+
);
|
|
3917
|
+
}
|
|
3918
|
+
if (reconnecting) {
|
|
3919
|
+
return /* @__PURE__ */ jsxs5("div", { className: "hw-disconnect", children: [
|
|
3920
|
+
/* @__PURE__ */ jsx6("div", { className: "hw-disconnect-spinner" }),
|
|
3921
|
+
t("widget.reconnecting")
|
|
3922
|
+
] });
|
|
3923
|
+
}
|
|
3924
|
+
return null;
|
|
3925
|
+
}
|
|
3926
|
+
|
|
3602
3927
|
// src/themed/content/content-tab-view.tsx
|
|
3603
|
-
import { useCallback as
|
|
3928
|
+
import { useCallback as useCallback13, useEffect as useEffect11 } from "react";
|
|
3929
|
+
|
|
3930
|
+
// src/hooks/use-content-tab.ts
|
|
3931
|
+
import { useCallback as useCallback10, useEffect as useEffect8, useState as useState10 } from "react";
|
|
3932
|
+
|
|
3933
|
+
// src/hooks/use-mirrored-state.ts
|
|
3934
|
+
import { useCallback as useCallback9, useRef as useRef9, useState as useState9 } from "react";
|
|
3935
|
+
function useMirroredState(initial) {
|
|
3936
|
+
const [value, setValue] = useState9(initial);
|
|
3937
|
+
const ref = useRef9(value);
|
|
3938
|
+
const set = useCallback9((next) => {
|
|
3939
|
+
ref.current = next;
|
|
3940
|
+
setValue(next);
|
|
3941
|
+
}, []);
|
|
3942
|
+
return [value, set, ref];
|
|
3943
|
+
}
|
|
3604
3944
|
|
|
3605
3945
|
// src/hooks/use-content-tab.ts
|
|
3606
|
-
import { useCallback as useCallback9, useEffect as useEffect7, useState as useState9 } from "react";
|
|
3607
3946
|
var EMPTY_TABS2 = [];
|
|
3608
3947
|
function listKey(tabId, lang) {
|
|
3609
3948
|
return `flat:${tabId}:${lang}:list`;
|
|
@@ -3623,22 +3962,22 @@ function useContentTab(tabId) {
|
|
|
3623
3962
|
const tab = contentTabs.find((t2) => t2.id === tabId) ?? null;
|
|
3624
3963
|
const lang = getLocale();
|
|
3625
3964
|
const cache = store.getState().contentCache;
|
|
3626
|
-
const [entries, setEntries] =
|
|
3965
|
+
const [entries, setEntries, entriesRef] = useMirroredState(
|
|
3627
3966
|
() => readCache(cache, listKey(tabId, lang))?.items ?? []
|
|
3628
3967
|
);
|
|
3629
|
-
const [detail, setDetail] =
|
|
3630
|
-
const [isLoading, setIsLoading] =
|
|
3631
|
-
const [isLoadingDetail, setIsLoadingDetail] =
|
|
3632
|
-
const [hasMore, setHasMore] =
|
|
3968
|
+
const [detail, setDetail] = useState10(null);
|
|
3969
|
+
const [isLoading, setIsLoading] = useState10(false);
|
|
3970
|
+
const [isLoadingDetail, setIsLoadingDetail] = useState10(false);
|
|
3971
|
+
const [hasMore, setHasMore] = useState10(
|
|
3633
3972
|
() => readCache(cache, listKey(tabId, lang))?.hasMore ?? false
|
|
3634
3973
|
);
|
|
3635
|
-
const [total, setTotal] =
|
|
3974
|
+
const [total, setTotal] = useState10(
|
|
3636
3975
|
() => readCache(cache, listKey(tabId, lang))?.total ?? 0
|
|
3637
3976
|
);
|
|
3638
|
-
const [page, setPage] =
|
|
3977
|
+
const [page, setPage] = useState10(
|
|
3639
3978
|
() => readCache(cache, listKey(tabId, lang))?.page ?? 1
|
|
3640
3979
|
);
|
|
3641
|
-
const fetchEntries =
|
|
3980
|
+
const fetchEntries = useCallback10(
|
|
3642
3981
|
async (opts) => {
|
|
3643
3982
|
if (!tab) return;
|
|
3644
3983
|
const p = opts?.page ?? 1;
|
|
@@ -3653,18 +3992,16 @@ function useContentTab(tabId) {
|
|
|
3653
3992
|
language: getLocale()
|
|
3654
3993
|
});
|
|
3655
3994
|
if (result.items) {
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
return nextItems;
|
|
3667
|
-
});
|
|
3995
|
+
const nextItems = reset ? result.items : [...entriesRef.current, ...result.items];
|
|
3996
|
+
setEntries(nextItems);
|
|
3997
|
+
if (!opts?.search) {
|
|
3998
|
+
store.getState().setContentCache(listKey(tabId, getLocale()), {
|
|
3999
|
+
items: nextItems,
|
|
4000
|
+
total: result.total,
|
|
4001
|
+
hasMore: result.hasMore,
|
|
4002
|
+
page: p
|
|
4003
|
+
});
|
|
4004
|
+
}
|
|
3668
4005
|
setHasMore(result.hasMore);
|
|
3669
4006
|
setTotal(result.total);
|
|
3670
4007
|
setPage(p);
|
|
@@ -3675,13 +4012,13 @@ function useContentTab(tabId) {
|
|
|
3675
4012
|
setIsLoading(false);
|
|
3676
4013
|
}
|
|
3677
4014
|
},
|
|
3678
|
-
[client, tabId, tab, store]
|
|
4015
|
+
[client, tabId, tab, store, setEntries, entriesRef]
|
|
3679
4016
|
);
|
|
3680
|
-
const loadMore =
|
|
4017
|
+
const loadMore = useCallback10(() => {
|
|
3681
4018
|
if (!hasMore || isLoading) return;
|
|
3682
4019
|
fetchEntries({ page: page + 1 });
|
|
3683
4020
|
}, [fetchEntries, hasMore, isLoading, page]);
|
|
3684
|
-
const fetchDetail =
|
|
4021
|
+
const fetchDetail = useCallback10(
|
|
3685
4022
|
async (slug) => {
|
|
3686
4023
|
if (!tab) return;
|
|
3687
4024
|
const cached = readCache(
|
|
@@ -3702,10 +4039,7 @@ function useContentTab(tabId) {
|
|
|
3702
4039
|
if (result.entry) {
|
|
3703
4040
|
const entry = result.entry;
|
|
3704
4041
|
setDetail(entry);
|
|
3705
|
-
store.getState().setContentCache(
|
|
3706
|
-
detailKey(tabId, getLocale(), slug),
|
|
3707
|
-
entry
|
|
3708
|
-
);
|
|
4042
|
+
store.getState().setContentCache(detailKey(tabId, getLocale(), slug), entry);
|
|
3709
4043
|
}
|
|
3710
4044
|
} catch (err) {
|
|
3711
4045
|
console.error("[useContentTab] detail error:", err);
|
|
@@ -3715,10 +4049,10 @@ function useContentTab(tabId) {
|
|
|
3715
4049
|
},
|
|
3716
4050
|
[client, tabId, tab, store]
|
|
3717
4051
|
);
|
|
3718
|
-
const clearDetail =
|
|
4052
|
+
const clearDetail = useCallback10(() => {
|
|
3719
4053
|
setDetail(null);
|
|
3720
4054
|
}, []);
|
|
3721
|
-
|
|
4055
|
+
useEffect8(() => {
|
|
3722
4056
|
if (tab && entries.length === 0) {
|
|
3723
4057
|
fetchEntries({ page: 1, reset: true });
|
|
3724
4058
|
}
|
|
@@ -3739,8 +4073,11 @@ function useContentTab(tabId) {
|
|
|
3739
4073
|
}
|
|
3740
4074
|
|
|
3741
4075
|
// src/themed/content/simple-markdown.tsx
|
|
3742
|
-
import { useEffect as
|
|
3743
|
-
import { jsx as
|
|
4076
|
+
import { useEffect as useEffect9, useRef as useRef10 } from "react";
|
|
4077
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
4078
|
+
function esc(value) {
|
|
4079
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4080
|
+
}
|
|
3744
4081
|
var COPY_ICON = `<svg class="hw-code-copy-icon" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M15 9V4.25C15 3.55964 14.4404 3 13.75 3H4.25C3.55964 3 3 3.55964 3 4.25V13.75C3 14.4404 3.55964 15 4.25 15H9M10.25 9H19.75C20.4404 9 21 9.55964 21 10.25V19.75C21 20.4404 20.4404 21 19.75 21H10.25C9.55964 21 9 20.4404 9 19.75V10.25C9 9.55964 9.55964 9 10.25 9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
3745
4082
|
var CHECK_ICON = `<svg class="hw-code-check-icon" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M8 13L11 16L16 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
3746
4083
|
function inferCodeLanguage(code, lang) {
|
|
@@ -3780,7 +4117,7 @@ function renderMarkdown(md) {
|
|
|
3780
4117
|
const className = langLabel !== "code" ? ` class="language-${langLabel}"` : "";
|
|
3781
4118
|
const trimmed = escaped.replace(/\n$/, "");
|
|
3782
4119
|
codeBlocks.push(
|
|
3783
|
-
`<div class="hw-code" data-hw-code="1"><div class="hw-code-header"><span class="hw-code-lang">${langLabel}</span><div class="hw-code-actions"><button type="button" class="hw-code-action hw-code-copy" aria-label="
|
|
4120
|
+
`<div class="hw-code" data-hw-code="1"><div class="hw-code-header"><span class="hw-code-lang">${langLabel}</span><div class="hw-code-actions"><button type="button" class="hw-code-action hw-code-copy" aria-label="${esc(t("widget.code_copy_aria"))}" title="${esc(t("widget.code_copy_aria"))}">${COPY_ICON}${CHECK_ICON}<span class="hw-code-copy-label">${esc(t("widget.code_copy"))}</span></button></div></div><pre><code${className}>${trimmed}</code></pre></div>`
|
|
3784
4121
|
);
|
|
3785
4122
|
return `
|
|
3786
4123
|
|
|
@@ -3804,7 +4141,9 @@ ${codeBlockPlaceholder(codeBlocks.length - 1)}
|
|
|
3804
4141
|
(_match, headerLine, bodyLines) => {
|
|
3805
4142
|
const cells = (line) => line.trim().replace(/^\||\|$/g, "").split("|").map((c) => c.trim());
|
|
3806
4143
|
const head = cells(headerLine).map((c) => `<th>${c}</th>`).join("");
|
|
3807
|
-
const rows = bodyLines.trim().split("\n").map(
|
|
4144
|
+
const rows = bodyLines.trim().split("\n").map(
|
|
4145
|
+
(line) => `<tr>${cells(line).map((c) => `<td>${c}</td>`).join("")}</tr>`
|
|
4146
|
+
).join("");
|
|
3808
4147
|
tables.push(
|
|
3809
4148
|
`<div class="hw-table-wrap"><table class="hw-table"><thead><tr>${head}</tr></thead><tbody>${rows}</tbody></table></div>`
|
|
3810
4149
|
);
|
|
@@ -3854,15 +4193,13 @@ function MarkdownContent({
|
|
|
3854
4193
|
bodyMarkdown,
|
|
3855
4194
|
className
|
|
3856
4195
|
}) {
|
|
3857
|
-
const rootRef =
|
|
4196
|
+
const rootRef = useRef10(null);
|
|
3858
4197
|
const html = bodyHtml ?? (bodyMarkdown ? renderMarkdown(bodyMarkdown) : "");
|
|
3859
|
-
|
|
4198
|
+
useEffect9(() => {
|
|
3860
4199
|
const root = rootRef.current;
|
|
3861
4200
|
if (!root) return;
|
|
3862
4201
|
const isWhitespaceOnly = (el) => {
|
|
3863
|
-
const hasNonBrChild = Array.from(el.children).some(
|
|
3864
|
-
(c) => c.tagName !== "BR"
|
|
3865
|
-
);
|
|
4202
|
+
const hasNonBrChild = Array.from(el.children).some((c) => c.tagName !== "BR");
|
|
3866
4203
|
if (hasNonBrChild) return false;
|
|
3867
4204
|
const text = el.textContent ?? "";
|
|
3868
4205
|
return text.replace(/[\s ]/g, "") === "";
|
|
@@ -3875,7 +4212,7 @@ function MarkdownContent({
|
|
|
3875
4212
|
};
|
|
3876
4213
|
removeEmpties();
|
|
3877
4214
|
}, [html]);
|
|
3878
|
-
|
|
4215
|
+
useEffect9(() => {
|
|
3879
4216
|
const root = rootRef.current;
|
|
3880
4217
|
if (!root) return;
|
|
3881
4218
|
const handler = (e) => {
|
|
@@ -3887,7 +4224,7 @@ function MarkdownContent({
|
|
|
3887
4224
|
};
|
|
3888
4225
|
}, []);
|
|
3889
4226
|
if (!html) return null;
|
|
3890
|
-
return /* @__PURE__ */
|
|
4227
|
+
return /* @__PURE__ */ jsx7(
|
|
3891
4228
|
"div",
|
|
3892
4229
|
{
|
|
3893
4230
|
ref: rootRef,
|
|
@@ -3899,8 +4236,8 @@ function MarkdownContent({
|
|
|
3899
4236
|
function flashCopied(btn, failed = false) {
|
|
3900
4237
|
const label = btn.querySelector(".hw-code-copy-label");
|
|
3901
4238
|
if (!label) return;
|
|
3902
|
-
const original = label.textContent ?? "
|
|
3903
|
-
label.textContent = failed ? "
|
|
4239
|
+
const original = label.textContent ?? t("widget.code_copy");
|
|
4240
|
+
label.textContent = failed ? t("widget.code_copy_failed") : t("widget.copied");
|
|
3904
4241
|
btn.classList.add(failed ? "hw-code-copy--failed" : "hw-code-copy--copied");
|
|
3905
4242
|
setTimeout(() => {
|
|
3906
4243
|
label.textContent = original;
|
|
@@ -3917,24 +4254,24 @@ function closeDanglingMarkdown(partial) {
|
|
|
3917
4254
|
}
|
|
3918
4255
|
|
|
3919
4256
|
// src/themed/content/content-detail-view.tsx
|
|
3920
|
-
import { Fragment as Fragment2, jsx as
|
|
4257
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3921
4258
|
function ContentDetailView({
|
|
3922
4259
|
entry,
|
|
3923
4260
|
isLoading
|
|
3924
4261
|
}) {
|
|
3925
4262
|
if (isLoading || !entry) {
|
|
3926
|
-
return /* @__PURE__ */
|
|
4263
|
+
return /* @__PURE__ */ jsx8(ArticleSkeleton, {});
|
|
3927
4264
|
}
|
|
3928
4265
|
const badge = entry.customFields.version ?? entry.customFields.priority ?? entry.customFields.type ?? null;
|
|
3929
|
-
return /* @__PURE__ */
|
|
3930
|
-
/* @__PURE__ */
|
|
3931
|
-
/* @__PURE__ */
|
|
3932
|
-
(badge || entry.publishedAt) && /* @__PURE__ */
|
|
3933
|
-
badge && /* @__PURE__ */
|
|
3934
|
-
entry.publishedAt && /* @__PURE__ */
|
|
4266
|
+
return /* @__PURE__ */ jsxs6("div", { className: "hw-content-detail", children: [
|
|
4267
|
+
/* @__PURE__ */ jsxs6("div", { className: "hw-content-detail-header", children: [
|
|
4268
|
+
/* @__PURE__ */ jsx8("h1", { className: "hw-content-detail-title", children: entry.title }),
|
|
4269
|
+
(badge || entry.publishedAt) && /* @__PURE__ */ jsxs6("div", { className: "hw-content-detail-meta", children: [
|
|
4270
|
+
badge && /* @__PURE__ */ jsx8("span", { className: "hw-content-entry-badge", children: badge }),
|
|
4271
|
+
entry.publishedAt && /* @__PURE__ */ jsx8("span", { className: "hw-content-detail-date", children: formatRelativeTime(entry.publishedAt) })
|
|
3935
4272
|
] })
|
|
3936
4273
|
] }),
|
|
3937
|
-
(entry.body || entry.bodyHtml) && /* @__PURE__ */
|
|
4274
|
+
(entry.body || entry.bodyHtml) && /* @__PURE__ */ jsx8("div", { className: "hw-content-detail-body", children: /* @__PURE__ */ jsx8(MarkdownContent, { bodyHtml: entry.bodyHtml, bodyMarkdown: entry.body }) })
|
|
3938
4275
|
] });
|
|
3939
4276
|
}
|
|
3940
4277
|
function ArticleSkeleton() {
|
|
@@ -3955,15 +4292,15 @@ function ArticleSkeleton() {
|
|
|
3955
4292
|
]
|
|
3956
4293
|
}
|
|
3957
4294
|
];
|
|
3958
|
-
return /* @__PURE__ */
|
|
3959
|
-
/* @__PURE__ */
|
|
3960
|
-
/* @__PURE__ */
|
|
3961
|
-
/* @__PURE__ */
|
|
3962
|
-
/* @__PURE__ */
|
|
3963
|
-
/* @__PURE__ */
|
|
4295
|
+
return /* @__PURE__ */ jsxs6("div", { className: "hw-content-detail", children: [
|
|
4296
|
+
/* @__PURE__ */ jsxs6("div", { className: "hw-content-detail-header", children: [
|
|
4297
|
+
/* @__PURE__ */ jsx8("h1", { className: "hw-content-detail-title", children: /* @__PURE__ */ jsx8("span", { className: "hw-skeleton hw-skeleton-title" }) }),
|
|
4298
|
+
/* @__PURE__ */ jsxs6("div", { className: "hw-content-detail-meta", children: [
|
|
4299
|
+
/* @__PURE__ */ jsx8("span", { className: "hw-skeleton hw-skeleton-badge" }),
|
|
4300
|
+
/* @__PURE__ */ jsx8("span", { className: "hw-skeleton hw-skeleton-date" })
|
|
3964
4301
|
] })
|
|
3965
4302
|
] }),
|
|
3966
|
-
/* @__PURE__ */
|
|
4303
|
+
/* @__PURE__ */ jsx8("div", { className: "hw-content-detail-body", children: /* @__PURE__ */ jsx8("div", { className: "hw-markdown", children: sections.map((s, i) => /* @__PURE__ */ jsx8(
|
|
3967
4304
|
SkeletonSection,
|
|
3968
4305
|
{
|
|
3969
4306
|
headerWidth: s.headerWidth,
|
|
@@ -3977,23 +4314,23 @@ function SkeletonSection({
|
|
|
3977
4314
|
headerWidth,
|
|
3978
4315
|
items
|
|
3979
4316
|
}) {
|
|
3980
|
-
return /* @__PURE__ */
|
|
3981
|
-
/* @__PURE__ */
|
|
4317
|
+
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
4318
|
+
/* @__PURE__ */ jsx8("h2", { children: /* @__PURE__ */ jsx8(
|
|
3982
4319
|
"span",
|
|
3983
4320
|
{
|
|
3984
4321
|
className: "hw-skeleton hw-skeleton-h2",
|
|
3985
4322
|
style: { display: "block", width: headerWidth }
|
|
3986
4323
|
}
|
|
3987
4324
|
) }),
|
|
3988
|
-
items.map((item, j) => /* @__PURE__ */
|
|
3989
|
-
/* @__PURE__ */
|
|
4325
|
+
items.map((item, j) => /* @__PURE__ */ jsx8("ul", { children: /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsxs6("div", { className: "hw-skeleton-bullet-lines", children: [
|
|
4326
|
+
/* @__PURE__ */ jsx8(
|
|
3990
4327
|
"span",
|
|
3991
4328
|
{
|
|
3992
4329
|
className: "hw-skeleton hw-skeleton-bullet-line",
|
|
3993
4330
|
style: { display: "block", width: item.l1 }
|
|
3994
4331
|
}
|
|
3995
4332
|
),
|
|
3996
|
-
/* @__PURE__ */
|
|
4333
|
+
/* @__PURE__ */ jsx8(
|
|
3997
4334
|
"span",
|
|
3998
4335
|
{
|
|
3999
4336
|
className: "hw-skeleton hw-skeleton-bullet-line",
|
|
@@ -4005,8 +4342,8 @@ function SkeletonSection({
|
|
|
4005
4342
|
}
|
|
4006
4343
|
|
|
4007
4344
|
// src/themed/content/content-list-view.tsx
|
|
4008
|
-
import { useCallback as
|
|
4009
|
-
import { jsx as
|
|
4345
|
+
import { useCallback as useCallback11, useRef as useRef11, useState as useState11 } from "react";
|
|
4346
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4010
4347
|
function ContentListView({
|
|
4011
4348
|
entries,
|
|
4012
4349
|
isLoading,
|
|
@@ -4017,9 +4354,9 @@ function ContentListView({
|
|
|
4017
4354
|
searchPlaceholder,
|
|
4018
4355
|
display
|
|
4019
4356
|
}) {
|
|
4020
|
-
const [searchText, setSearchText] =
|
|
4021
|
-
const debounceRef =
|
|
4022
|
-
const handleSearch =
|
|
4357
|
+
const [searchText, setSearchText] = useState11("");
|
|
4358
|
+
const debounceRef = useRef11(void 0);
|
|
4359
|
+
const handleSearch = useCallback11(
|
|
4023
4360
|
(value) => {
|
|
4024
4361
|
setSearchText(value);
|
|
4025
4362
|
if (!onSearch) return;
|
|
@@ -4030,13 +4367,13 @@ function ContentListView({
|
|
|
4030
4367
|
},
|
|
4031
4368
|
[onSearch]
|
|
4032
4369
|
);
|
|
4033
|
-
return /* @__PURE__ */
|
|
4034
|
-
onSearch && /* @__PURE__ */
|
|
4035
|
-
/* @__PURE__ */
|
|
4036
|
-
/* @__PURE__ */
|
|
4037
|
-
/* @__PURE__ */
|
|
4370
|
+
return /* @__PURE__ */ jsxs7("div", { className: "hw-content-list", children: [
|
|
4371
|
+
onSearch && /* @__PURE__ */ jsx9("div", { className: "hw-content-search", children: /* @__PURE__ */ jsxs7("div", { className: "hw-content-search-box", children: [
|
|
4372
|
+
/* @__PURE__ */ jsxs7("svg", { className: "hw-content-search-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4373
|
+
/* @__PURE__ */ jsx9("circle", { cx: "11", cy: "11", r: "8" }),
|
|
4374
|
+
/* @__PURE__ */ jsx9("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
4038
4375
|
] }),
|
|
4039
|
-
/* @__PURE__ */
|
|
4376
|
+
/* @__PURE__ */ jsx9(
|
|
4040
4377
|
"input",
|
|
4041
4378
|
{
|
|
4042
4379
|
type: "text",
|
|
@@ -4047,18 +4384,18 @@ function ContentListView({
|
|
|
4047
4384
|
}
|
|
4048
4385
|
)
|
|
4049
4386
|
] }) }),
|
|
4050
|
-
isLoading && entries.length === 0 && /* @__PURE__ */
|
|
4051
|
-
/* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4053
|
-
/* @__PURE__ */
|
|
4387
|
+
isLoading && entries.length === 0 && /* @__PURE__ */ jsx9("div", { className: "hw-skeleton-content", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs7("div", { className: "hw-skeleton-content-item", children: [
|
|
4388
|
+
/* @__PURE__ */ jsx9("div", { className: "hw-skeleton hw-skeleton-line", style: { width: "70%", height: 14 } }),
|
|
4389
|
+
/* @__PURE__ */ jsx9("div", { className: "hw-skeleton hw-skeleton-line", style: { width: "90%", height: 12 } }),
|
|
4390
|
+
/* @__PURE__ */ jsx9("div", { className: "hw-skeleton hw-skeleton-line", style: { width: "40%", height: 10 } })
|
|
4054
4391
|
] }, i)) }),
|
|
4055
|
-
!isLoading && entries.length === 0 && /* @__PURE__ */
|
|
4056
|
-
/* @__PURE__ */
|
|
4057
|
-
/* @__PURE__ */
|
|
4392
|
+
!isLoading && entries.length === 0 && /* @__PURE__ */ jsxs7("div", { className: "hw-content-empty", children: [
|
|
4393
|
+
/* @__PURE__ */ jsx9("div", { className: "hw-content-empty-title", children: searchText ? t("widget.no_results") : t("widget.nothing_yet") }),
|
|
4394
|
+
/* @__PURE__ */ jsx9("div", { className: "hw-content-empty-desc", children: searchText ? t("widget.try_different") : t("widget.check_back") })
|
|
4058
4395
|
] }),
|
|
4059
|
-
entries.length > 0 && /* @__PURE__ */
|
|
4060
|
-
entries.map((entry) => /* @__PURE__ */
|
|
4061
|
-
hasMore && /* @__PURE__ */
|
|
4396
|
+
entries.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "hw-content-entries", children: [
|
|
4397
|
+
entries.map((entry) => /* @__PURE__ */ jsx9(ContentEntryCard, { entry, onSelect, display }, entry.slug)),
|
|
4398
|
+
hasMore && /* @__PURE__ */ jsx9(
|
|
4062
4399
|
"button",
|
|
4063
4400
|
{
|
|
4064
4401
|
type: "button",
|
|
@@ -4085,24 +4422,24 @@ function ContentEntryCard({
|
|
|
4085
4422
|
const badge = display?.badgeField ? customFields[display.badgeField] ?? null : customFields.version ?? customFields.priority ?? customFields.type ?? null;
|
|
4086
4423
|
const subtitleValue = display?.subtitleField ? (display.subtitleField === "body" ? entry.body : customFields[display.subtitleField]) ?? null : customFields.excerpt ?? customFields.summary ?? customFields.description ?? null;
|
|
4087
4424
|
const preview = subtitleValue ? truncateText(subtitleValue) : truncateText(entry.body);
|
|
4088
|
-
return /* @__PURE__ */
|
|
4089
|
-
/* @__PURE__ */
|
|
4090
|
-
/* @__PURE__ */
|
|
4091
|
-
preview && /* @__PURE__ */
|
|
4092
|
-
(badge || entry.publishedAt) && /* @__PURE__ */
|
|
4093
|
-
badge && /* @__PURE__ */
|
|
4094
|
-
entry.publishedAt && /* @__PURE__ */
|
|
4425
|
+
return /* @__PURE__ */ jsx9("button", { type: "button", className: "hw-content-entry", onClick: () => onSelect(entry.slug), children: /* @__PURE__ */ jsxs7("div", { className: "hw-content-entry-main", children: [
|
|
4426
|
+
/* @__PURE__ */ jsxs7("div", { className: "hw-content-entry-text", children: [
|
|
4427
|
+
/* @__PURE__ */ jsx9("span", { className: "hw-content-entry-title", children: entry.title }),
|
|
4428
|
+
preview && /* @__PURE__ */ jsx9("span", { className: "hw-content-entry-desc", children: preview }),
|
|
4429
|
+
(badge || entry.publishedAt) && /* @__PURE__ */ jsxs7("div", { className: "hw-content-entry-meta", children: [
|
|
4430
|
+
badge && /* @__PURE__ */ jsx9("span", { className: "hw-content-entry-badge", children: badge }),
|
|
4431
|
+
entry.publishedAt && /* @__PURE__ */ jsx9("span", { className: "hw-content-entry-date", children: formatRelativeTime(entry.publishedAt) })
|
|
4095
4432
|
] })
|
|
4096
4433
|
] }),
|
|
4097
|
-
/* @__PURE__ */
|
|
4434
|
+
/* @__PURE__ */ jsx9("svg", { className: "hw-content-entry-chevron", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx9("polyline", { points: "9 18 15 12 9 6" }) })
|
|
4098
4435
|
] }) });
|
|
4099
4436
|
}
|
|
4100
4437
|
|
|
4101
4438
|
// src/themed/content/grouped-content-tab-view.tsx
|
|
4102
|
-
import { useEffect as
|
|
4439
|
+
import { useEffect as useEffect10, useRef as useRef13 } from "react";
|
|
4103
4440
|
|
|
4104
4441
|
// src/hooks/use-grouped-content-tab.ts
|
|
4105
|
-
import { useCallback as
|
|
4442
|
+
import { useCallback as useCallback12, useRef as useRef12, useState as useState12 } from "react";
|
|
4106
4443
|
var EMPTY_TABS3 = [];
|
|
4107
4444
|
function categoriesKey(tabId, lang) {
|
|
4108
4445
|
return `grouped:${tabId}:${lang}:categories`;
|
|
@@ -4126,17 +4463,17 @@ function useGroupedContentTab(tabId) {
|
|
|
4126
4463
|
const lang = getLocale();
|
|
4127
4464
|
const cache = store.getState().contentCache;
|
|
4128
4465
|
const cachedCategories = readCache2(cache, categoriesKey(tabId, lang));
|
|
4129
|
-
const [categories, setCategories] =
|
|
4130
|
-
const [isCategoriesLoading, setIsCategoriesLoading] =
|
|
4131
|
-
const [items, setItems] =
|
|
4132
|
-
const [isItemsLoading, setIsItemsLoading] =
|
|
4133
|
-
const [itemsHasMore, setItemsHasMore] =
|
|
4134
|
-
const itemsPageRef =
|
|
4135
|
-
const [detail, setDetail] =
|
|
4136
|
-
const [isLoadingDetail, setIsLoadingDetail] =
|
|
4137
|
-
const [activeCategory, setActiveCategory] =
|
|
4138
|
-
const allCategoriesRef =
|
|
4139
|
-
const fetchCategories =
|
|
4466
|
+
const [categories, setCategories] = useState12(cachedCategories ?? []);
|
|
4467
|
+
const [isCategoriesLoading, setIsCategoriesLoading] = useState12(false);
|
|
4468
|
+
const [items, setItems, itemsRef] = useMirroredState([]);
|
|
4469
|
+
const [isItemsLoading, setIsItemsLoading] = useState12(false);
|
|
4470
|
+
const [itemsHasMore, setItemsHasMore] = useState12(false);
|
|
4471
|
+
const itemsPageRef = useRef12(1);
|
|
4472
|
+
const [detail, setDetail] = useState12(null);
|
|
4473
|
+
const [isLoadingDetail, setIsLoadingDetail] = useState12(false);
|
|
4474
|
+
const [activeCategory, setActiveCategory] = useState12(null);
|
|
4475
|
+
const allCategoriesRef = useRef12(cachedCategories ?? []);
|
|
4476
|
+
const fetchCategories = useCallback12(async () => {
|
|
4140
4477
|
if (!tab) return;
|
|
4141
4478
|
setIsCategoriesLoading(true);
|
|
4142
4479
|
try {
|
|
@@ -4157,12 +4494,12 @@ function useGroupedContentTab(tabId) {
|
|
|
4157
4494
|
setIsCategoriesLoading(false);
|
|
4158
4495
|
}
|
|
4159
4496
|
}, [client, tabId, tab, store]);
|
|
4160
|
-
const initFetch =
|
|
4497
|
+
const initFetch = useCallback12(() => {
|
|
4161
4498
|
if (tab && categories.length === 0) {
|
|
4162
4499
|
fetchCategories();
|
|
4163
4500
|
}
|
|
4164
4501
|
}, [fetchCategories, tab, categories.length]);
|
|
4165
|
-
const fetchItems =
|
|
4502
|
+
const fetchItems = useCallback12(
|
|
4166
4503
|
async (opts) => {
|
|
4167
4504
|
if (!tab?.itemsModelSlug) return;
|
|
4168
4505
|
const p = opts?.page ?? 1;
|
|
@@ -4179,16 +4516,15 @@ function useGroupedContentTab(tabId) {
|
|
|
4179
4516
|
language: getLocale()
|
|
4180
4517
|
});
|
|
4181
4518
|
if (result.items) {
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
}
|
|
4190
|
-
|
|
4191
|
-
});
|
|
4519
|
+
const nextItems = reset ? result.items : [...itemsRef.current, ...result.items];
|
|
4520
|
+
setItems(nextItems);
|
|
4521
|
+
if (!opts?.search && opts?.groupSlug) {
|
|
4522
|
+
store.getState().setContentCache(itemsKey(tabId, getLocale(), opts.groupSlug), {
|
|
4523
|
+
items: nextItems,
|
|
4524
|
+
hasMore: result.hasMore,
|
|
4525
|
+
page: p
|
|
4526
|
+
});
|
|
4527
|
+
}
|
|
4192
4528
|
setItemsHasMore(result.hasMore);
|
|
4193
4529
|
itemsPageRef.current = p;
|
|
4194
4530
|
}
|
|
@@ -4198,9 +4534,9 @@ function useGroupedContentTab(tabId) {
|
|
|
4198
4534
|
setIsItemsLoading(false);
|
|
4199
4535
|
}
|
|
4200
4536
|
},
|
|
4201
|
-
[client, tabId, tab, store]
|
|
4537
|
+
[client, tabId, tab, store, setItems, itemsRef]
|
|
4202
4538
|
);
|
|
4203
|
-
const selectCategory =
|
|
4539
|
+
const selectCategory = useCallback12(
|
|
4204
4540
|
(category) => {
|
|
4205
4541
|
setActiveCategory(category);
|
|
4206
4542
|
setDetail(null);
|
|
@@ -4217,16 +4553,16 @@ function useGroupedContentTab(tabId) {
|
|
|
4217
4553
|
setItems([]);
|
|
4218
4554
|
fetchItems({ page: 1, reset: true, groupSlug: category.slug });
|
|
4219
4555
|
},
|
|
4220
|
-
[fetchItems, store, tabId]
|
|
4556
|
+
[fetchItems, store, tabId, setItems]
|
|
4221
4557
|
);
|
|
4222
|
-
const loadMoreItems =
|
|
4558
|
+
const loadMoreItems = useCallback12(() => {
|
|
4223
4559
|
if (!itemsHasMore || isItemsLoading || !activeCategory) return;
|
|
4224
4560
|
fetchItems({
|
|
4225
4561
|
page: itemsPageRef.current + 1,
|
|
4226
4562
|
groupSlug: activeCategory.slug
|
|
4227
4563
|
});
|
|
4228
4564
|
}, [fetchItems, itemsHasMore, isItemsLoading, activeCategory]);
|
|
4229
|
-
const searchItems =
|
|
4565
|
+
const searchItems = useCallback12(
|
|
4230
4566
|
(query) => {
|
|
4231
4567
|
setItems([]);
|
|
4232
4568
|
fetchItems({
|
|
@@ -4236,9 +4572,9 @@ function useGroupedContentTab(tabId) {
|
|
|
4236
4572
|
groupSlug: query ? void 0 : activeCategory?.slug
|
|
4237
4573
|
});
|
|
4238
4574
|
},
|
|
4239
|
-
[fetchItems, activeCategory]
|
|
4575
|
+
[fetchItems, activeCategory, setItems]
|
|
4240
4576
|
);
|
|
4241
|
-
const fetchDetail =
|
|
4577
|
+
const fetchDetail = useCallback12(
|
|
4242
4578
|
async (slug) => {
|
|
4243
4579
|
if (!tab?.itemsModelSlug) return;
|
|
4244
4580
|
const cached = readCache2(
|
|
@@ -4260,10 +4596,7 @@ function useGroupedContentTab(tabId) {
|
|
|
4260
4596
|
if (result.entry) {
|
|
4261
4597
|
const entry = result.entry;
|
|
4262
4598
|
setDetail(entry);
|
|
4263
|
-
store.getState().setContentCache(
|
|
4264
|
-
detailKey2(tabId, getLocale(), slug),
|
|
4265
|
-
entry
|
|
4266
|
-
);
|
|
4599
|
+
store.getState().setContentCache(detailKey2(tabId, getLocale(), slug), entry);
|
|
4267
4600
|
}
|
|
4268
4601
|
} catch (err) {
|
|
4269
4602
|
console.error("[useGroupedContentTab] detail error:", err);
|
|
@@ -4273,29 +4606,26 @@ function useGroupedContentTab(tabId) {
|
|
|
4273
4606
|
},
|
|
4274
4607
|
[client, tabId, tab, store]
|
|
4275
4608
|
);
|
|
4276
|
-
const searchCategories =
|
|
4277
|
-
(query)
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
[]
|
|
4290
|
-
);
|
|
4291
|
-
const clearDetail = useCallback11(() => {
|
|
4609
|
+
const searchCategories = useCallback12((query) => {
|
|
4610
|
+
if (!query.trim()) {
|
|
4611
|
+
setCategories(allCategoriesRef.current);
|
|
4612
|
+
return;
|
|
4613
|
+
}
|
|
4614
|
+
const q = query.toLowerCase();
|
|
4615
|
+
setCategories(
|
|
4616
|
+
allCategoriesRef.current.filter(
|
|
4617
|
+
(cat) => cat.title.toLowerCase().includes(q) || (cat.customFields.description ?? "").toLowerCase().includes(q)
|
|
4618
|
+
)
|
|
4619
|
+
);
|
|
4620
|
+
}, []);
|
|
4621
|
+
const clearDetail = useCallback12(() => {
|
|
4292
4622
|
setDetail(null);
|
|
4293
4623
|
}, []);
|
|
4294
|
-
const clearCategory =
|
|
4624
|
+
const clearCategory = useCallback12(() => {
|
|
4295
4625
|
setActiveCategory(null);
|
|
4296
4626
|
setItems([]);
|
|
4297
4627
|
setDetail(null);
|
|
4298
|
-
}, []);
|
|
4628
|
+
}, [setItems]);
|
|
4299
4629
|
return {
|
|
4300
4630
|
tab,
|
|
4301
4631
|
categories,
|
|
@@ -4318,7 +4648,7 @@ function useGroupedContentTab(tabId) {
|
|
|
4318
4648
|
}
|
|
4319
4649
|
|
|
4320
4650
|
// src/themed/content/grouped-content-tab-view.tsx
|
|
4321
|
-
import { jsx as
|
|
4651
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
4322
4652
|
function GroupedContentTabView({
|
|
4323
4653
|
tab,
|
|
4324
4654
|
subView,
|
|
@@ -4343,26 +4673,26 @@ function GroupedContentTabView({
|
|
|
4343
4673
|
fetchDetail,
|
|
4344
4674
|
clearCategory
|
|
4345
4675
|
} = useGroupedContentTab(tab.id);
|
|
4346
|
-
|
|
4676
|
+
useEffect10(() => {
|
|
4347
4677
|
initFetch();
|
|
4348
4678
|
}, [initFetch]);
|
|
4349
|
-
|
|
4679
|
+
useEffect10(() => {
|
|
4350
4680
|
if (detailSlug && subView === "content-detail") {
|
|
4351
4681
|
fetchDetail(detailSlug);
|
|
4352
4682
|
}
|
|
4353
4683
|
}, [detailSlug, subView, fetchDetail]);
|
|
4354
|
-
const prevSubView =
|
|
4355
|
-
|
|
4684
|
+
const prevSubView = useRef13(subView);
|
|
4685
|
+
useEffect10(() => {
|
|
4356
4686
|
if (prevSubView.current === "content-category" && subView === null) {
|
|
4357
4687
|
clearCategory();
|
|
4358
4688
|
}
|
|
4359
4689
|
prevSubView.current = subView;
|
|
4360
4690
|
}, [subView, clearCategory]);
|
|
4361
4691
|
if (subView === "content-detail" && detailSlug) {
|
|
4362
|
-
return /* @__PURE__ */
|
|
4692
|
+
return /* @__PURE__ */ jsx10(ContentDetailView, { entry: detail, isLoading: isLoadingDetail });
|
|
4363
4693
|
}
|
|
4364
4694
|
if (subView === "content-category" && activeCategory) {
|
|
4365
|
-
return /* @__PURE__ */
|
|
4695
|
+
return /* @__PURE__ */ jsx10(
|
|
4366
4696
|
ContentListView,
|
|
4367
4697
|
{
|
|
4368
4698
|
entries: items,
|
|
@@ -4376,7 +4706,7 @@ function GroupedContentTabView({
|
|
|
4376
4706
|
}
|
|
4377
4707
|
);
|
|
4378
4708
|
}
|
|
4379
|
-
return /* @__PURE__ */
|
|
4709
|
+
return /* @__PURE__ */ jsx10(
|
|
4380
4710
|
ContentListView,
|
|
4381
4711
|
{
|
|
4382
4712
|
entries: categories,
|
|
@@ -4398,7 +4728,7 @@ function GroupedContentTabView({
|
|
|
4398
4728
|
}
|
|
4399
4729
|
|
|
4400
4730
|
// src/themed/content/content-tab-view.tsx
|
|
4401
|
-
import { jsx as
|
|
4731
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
4402
4732
|
function ContentTabView({
|
|
4403
4733
|
tab,
|
|
4404
4734
|
showDetail,
|
|
@@ -4408,7 +4738,7 @@ function ContentTabView({
|
|
|
4408
4738
|
onSelectCategory
|
|
4409
4739
|
}) {
|
|
4410
4740
|
if (tab.tabType === "grouped" && tab.itemsModelSlug) {
|
|
4411
|
-
return /* @__PURE__ */
|
|
4741
|
+
return /* @__PURE__ */ jsx11(
|
|
4412
4742
|
GroupedContentTabView,
|
|
4413
4743
|
{
|
|
4414
4744
|
tab,
|
|
@@ -4420,7 +4750,7 @@ function ContentTabView({
|
|
|
4420
4750
|
}
|
|
4421
4751
|
);
|
|
4422
4752
|
}
|
|
4423
|
-
return /* @__PURE__ */
|
|
4753
|
+
return /* @__PURE__ */ jsx11(
|
|
4424
4754
|
FlatContentTabView,
|
|
4425
4755
|
{
|
|
4426
4756
|
tab,
|
|
@@ -4446,19 +4776,19 @@ function FlatContentTabView({
|
|
|
4446
4776
|
loadMore,
|
|
4447
4777
|
fetchDetail
|
|
4448
4778
|
} = useContentTab(tab.id);
|
|
4449
|
-
|
|
4779
|
+
useEffect11(() => {
|
|
4450
4780
|
if (detailSlug) fetchDetail(detailSlug);
|
|
4451
4781
|
}, [detailSlug, fetchDetail]);
|
|
4452
|
-
const handleSearch =
|
|
4782
|
+
const handleSearch = useCallback13(
|
|
4453
4783
|
(query) => {
|
|
4454
4784
|
fetchEntries({ page: 1, search: query || void 0, reset: true });
|
|
4455
4785
|
},
|
|
4456
4786
|
[fetchEntries]
|
|
4457
4787
|
);
|
|
4458
4788
|
if (showDetail && detailSlug) {
|
|
4459
|
-
return /* @__PURE__ */
|
|
4789
|
+
return /* @__PURE__ */ jsx11(ContentDetailView, { entry: detail, isLoading: isLoadingDetail });
|
|
4460
4790
|
}
|
|
4461
|
-
return /* @__PURE__ */
|
|
4791
|
+
return /* @__PURE__ */ jsx11(
|
|
4462
4792
|
ContentListView,
|
|
4463
4793
|
{
|
|
4464
4794
|
entries,
|
|
@@ -4474,7 +4804,7 @@ function FlatContentTabView({
|
|
|
4474
4804
|
}
|
|
4475
4805
|
|
|
4476
4806
|
// src/themed/content/tab-icon.tsx
|
|
4477
|
-
import { jsx as
|
|
4807
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
4478
4808
|
var ICON_MAP = {
|
|
4479
4809
|
book: BookIcon,
|
|
4480
4810
|
megaphone: MegaphoneIcon,
|
|
@@ -4485,12 +4815,12 @@ var ICON_MAP = {
|
|
|
4485
4815
|
};
|
|
4486
4816
|
function ContentTabIconComponent({ icon }) {
|
|
4487
4817
|
const Icon = ICON_MAP[icon] ?? BookIcon;
|
|
4488
|
-
return /* @__PURE__ */
|
|
4818
|
+
return /* @__PURE__ */ jsx12(Icon, {});
|
|
4489
4819
|
}
|
|
4490
4820
|
|
|
4491
4821
|
// src/themed/debug-overlay.tsx
|
|
4492
|
-
import { useEffect as
|
|
4493
|
-
import { jsx as
|
|
4822
|
+
import { useEffect as useEffect12, useMemo as useMemo2, useRef as useRef14, useState as useState13 } from "react";
|
|
4823
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4494
4824
|
var MAX_EVENTS = 60;
|
|
4495
4825
|
function isDebugEnabled() {
|
|
4496
4826
|
if (typeof window === "undefined") return false;
|
|
@@ -4507,16 +4837,16 @@ function senderOf(item) {
|
|
|
4507
4837
|
return item.type;
|
|
4508
4838
|
}
|
|
4509
4839
|
function WidgetDebugOverlay() {
|
|
4510
|
-
const [enabled, setEnabled] =
|
|
4511
|
-
const [open, setOpen] =
|
|
4512
|
-
const [events, setEvents] =
|
|
4513
|
-
const eventsRef =
|
|
4840
|
+
const [enabled, setEnabled] = useState13(false);
|
|
4841
|
+
const [open, setOpen] = useState13(true);
|
|
4842
|
+
const [events, setEvents] = useState13([]);
|
|
4843
|
+
const eventsRef = useRef14([]);
|
|
4514
4844
|
const activeId = useWidgetStore((s) => s.activeConversationId);
|
|
4515
4845
|
const messagesMap = useWidgetStore((s) => s.messages);
|
|
4516
4846
|
const typingUsers = useWidgetStore((s) => s.typingUsers);
|
|
4517
4847
|
const aiProcessingMap = useWidgetStore((s) => s.aiProcessing);
|
|
4518
4848
|
const { store } = useWidgetContext();
|
|
4519
|
-
|
|
4849
|
+
useEffect12(() => {
|
|
4520
4850
|
setEnabled(isDebugEnabled());
|
|
4521
4851
|
}, []);
|
|
4522
4852
|
const pushEvent = useMemo2(
|
|
@@ -4531,7 +4861,7 @@ function WidgetDebugOverlay() {
|
|
|
4531
4861
|
},
|
|
4532
4862
|
[]
|
|
4533
4863
|
);
|
|
4534
|
-
|
|
4864
|
+
useEffect12(() => {
|
|
4535
4865
|
if (!enabled) return;
|
|
4536
4866
|
if (typeof window === "undefined" || typeof window.fetch !== "function") return;
|
|
4537
4867
|
const originalFetch = window.fetch.bind(window);
|
|
@@ -4563,7 +4893,7 @@ function WidgetDebugOverlay() {
|
|
|
4563
4893
|
window.fetch = originalFetch;
|
|
4564
4894
|
};
|
|
4565
4895
|
}, [enabled, pushEvent]);
|
|
4566
|
-
|
|
4896
|
+
useEffect12(() => {
|
|
4567
4897
|
if (!enabled) return;
|
|
4568
4898
|
const original = store.getState().handleRealtimeEvent;
|
|
4569
4899
|
store.setState({
|
|
@@ -4581,8 +4911,8 @@ function WidgetDebugOverlay() {
|
|
|
4581
4911
|
() => activeMessages.map((m) => `${m.id}:${senderOf(m)}:${m.createdAt}`).join("|"),
|
|
4582
4912
|
[activeMessages]
|
|
4583
4913
|
);
|
|
4584
|
-
const prevSigRef =
|
|
4585
|
-
|
|
4914
|
+
const prevSigRef = useRef14(lastMsgSignature);
|
|
4915
|
+
useEffect12(() => {
|
|
4586
4916
|
if (!enabled) return;
|
|
4587
4917
|
if (prevSigRef.current !== lastMsgSignature) {
|
|
4588
4918
|
prevSigRef.current = lastMsgSignature;
|
|
@@ -4596,10 +4926,10 @@ function WidgetDebugOverlay() {
|
|
|
4596
4926
|
if (!enabled) return null;
|
|
4597
4927
|
const isTyping = activeId ? typingUsers.get(activeId) : false;
|
|
4598
4928
|
const isAi = activeId ? aiProcessingMap.get(activeId) : false;
|
|
4599
|
-
return /* @__PURE__ */
|
|
4600
|
-
/* @__PURE__ */
|
|
4601
|
-
/* @__PURE__ */
|
|
4602
|
-
/* @__PURE__ */
|
|
4929
|
+
return /* @__PURE__ */ jsxs8("div", { style: styles.wrap, children: [
|
|
4930
|
+
/* @__PURE__ */ jsxs8("div", { style: styles.header, children: [
|
|
4931
|
+
/* @__PURE__ */ jsx13("strong", { children: "hw debug" }),
|
|
4932
|
+
/* @__PURE__ */ jsxs8("span", { style: styles.meta, children: [
|
|
4603
4933
|
" ",
|
|
4604
4934
|
"\xB7 conv ",
|
|
4605
4935
|
activeId ? activeId.slice(0, 10) : "\u2014",
|
|
@@ -4610,29 +4940,29 @@ function WidgetDebugOverlay() {
|
|
|
4610
4940
|
" \xB7 ai ",
|
|
4611
4941
|
isAi ? "Y" : "n"
|
|
4612
4942
|
] }),
|
|
4613
|
-
/* @__PURE__ */
|
|
4614
|
-
/* @__PURE__ */
|
|
4943
|
+
/* @__PURE__ */ jsx13("button", { type: "button", style: styles.btn, onClick: () => setOpen((v) => !v), children: open ? "hide" : "show" }),
|
|
4944
|
+
/* @__PURE__ */ jsx13("button", { type: "button", style: styles.btn, onClick: () => {
|
|
4615
4945
|
eventsRef.current = [];
|
|
4616
4946
|
setEvents([]);
|
|
4617
4947
|
}, children: "clear" })
|
|
4618
4948
|
] }),
|
|
4619
|
-
open && /* @__PURE__ */
|
|
4620
|
-
/* @__PURE__ */
|
|
4621
|
-
/* @__PURE__ */
|
|
4622
|
-
activeMessages.length === 0 ? /* @__PURE__ */
|
|
4623
|
-
/* @__PURE__ */
|
|
4624
|
-
/* @__PURE__ */
|
|
4625
|
-
/* @__PURE__ */
|
|
4626
|
-
/* @__PURE__ */
|
|
4949
|
+
open && /* @__PURE__ */ jsxs8("div", { style: styles.body, children: [
|
|
4950
|
+
/* @__PURE__ */ jsxs8("div", { style: styles.section, children: [
|
|
4951
|
+
/* @__PURE__ */ jsx13("div", { style: styles.sectionTitle, children: "messages (active)" }),
|
|
4952
|
+
activeMessages.length === 0 ? /* @__PURE__ */ jsx13("div", { style: styles.empty, children: "empty" }) : activeMessages.map((m, i) => /* @__PURE__ */ jsxs8("div", { style: styles.row, children: [
|
|
4953
|
+
/* @__PURE__ */ jsx13("span", { style: { ...styles.badge, background: colorFor(senderOf(m)) }, children: i }),
|
|
4954
|
+
/* @__PURE__ */ jsx13("span", { style: styles.sender, children: senderOf(m) }),
|
|
4955
|
+
/* @__PURE__ */ jsx13("span", { style: styles.ts, children: m.createdAt.slice(11, 23) }),
|
|
4956
|
+
/* @__PURE__ */ jsx13("span", { style: styles.text, children: (m.text ?? "").slice(0, 60) })
|
|
4627
4957
|
] }, m.id))
|
|
4628
4958
|
] }),
|
|
4629
|
-
/* @__PURE__ */
|
|
4630
|
-
/* @__PURE__ */
|
|
4631
|
-
events.length === 0 ? /* @__PURE__ */
|
|
4632
|
-
/* @__PURE__ */
|
|
4633
|
-
/* @__PURE__ */
|
|
4634
|
-
/* @__PURE__ */
|
|
4635
|
-
e.detail && /* @__PURE__ */
|
|
4959
|
+
/* @__PURE__ */ jsxs8("div", { style: styles.section, children: [
|
|
4960
|
+
/* @__PURE__ */ jsx13("div", { style: styles.sectionTitle, children: "events" }),
|
|
4961
|
+
events.length === 0 ? /* @__PURE__ */ jsx13("div", { style: styles.empty, children: "no events yet \u2014 send a message" }) : events.map((e) => /* @__PURE__ */ jsxs8("div", { style: styles.row, children: [
|
|
4962
|
+
/* @__PURE__ */ jsx13("span", { style: { ...styles.badge, background: kindColor(e.kind) }, children: e.kind }),
|
|
4963
|
+
/* @__PURE__ */ jsx13("span", { style: styles.ts, children: new Date(e.t).toISOString().slice(11, 23) }),
|
|
4964
|
+
/* @__PURE__ */ jsx13("span", { style: styles.evLabel, children: e.label }),
|
|
4965
|
+
e.detail && /* @__PURE__ */ jsx13("span", { style: styles.detail, children: e.detail })
|
|
4636
4966
|
] }, e.id))
|
|
4637
4967
|
] })
|
|
4638
4968
|
] })
|
|
@@ -4734,10 +5064,403 @@ var styles = {
|
|
|
4734
5064
|
empty: { color: "#52525b", fontStyle: "italic", fontSize: 10 }
|
|
4735
5065
|
};
|
|
4736
5066
|
|
|
5067
|
+
// src/themed/icons-local.tsx
|
|
5068
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5069
|
+
function DotsIcon({ size = 24, ...props }) {
|
|
5070
|
+
return /* @__PURE__ */ jsxs9(
|
|
5071
|
+
"svg",
|
|
5072
|
+
{
|
|
5073
|
+
width: size,
|
|
5074
|
+
height: size,
|
|
5075
|
+
viewBox: "0 0 24 24",
|
|
5076
|
+
fill: "none",
|
|
5077
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
5078
|
+
"aria-hidden": "true",
|
|
5079
|
+
...props,
|
|
5080
|
+
children: [
|
|
5081
|
+
/* @__PURE__ */ jsx14("circle", { cx: "5", cy: "12", r: "1.7", fill: "currentColor" }),
|
|
5082
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "1.7", fill: "currentColor" }),
|
|
5083
|
+
/* @__PURE__ */ jsx14("circle", { cx: "19", cy: "12", r: "1.7", fill: "currentColor" })
|
|
5084
|
+
]
|
|
5085
|
+
}
|
|
5086
|
+
);
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
// src/themed/message-bubble.tsx
|
|
5090
|
+
import { useEffect as useEffect13, useLayoutEffect, useRef as useRef15, useState as useState14 } from "react";
|
|
5091
|
+
|
|
5092
|
+
// src/themed/image-fallback.ts
|
|
5093
|
+
function imageFileName(url) {
|
|
5094
|
+
try {
|
|
5095
|
+
const { pathname, host } = new URL(url);
|
|
5096
|
+
const last = pathname.split("/").filter(Boolean).pop();
|
|
5097
|
+
if (!last) return host;
|
|
5098
|
+
try {
|
|
5099
|
+
return decodeURIComponent(last);
|
|
5100
|
+
} catch {
|
|
5101
|
+
return last;
|
|
5102
|
+
}
|
|
5103
|
+
} catch {
|
|
5104
|
+
return url.split(/[?#]/)[0]?.split("/").filter(Boolean).pop() ?? url;
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
function fileExt(name) {
|
|
5108
|
+
const dot = name.lastIndexOf(".");
|
|
5109
|
+
return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
|
|
5110
|
+
}
|
|
5111
|
+
|
|
5112
|
+
// ../types/src/link-preview.ts
|
|
5113
|
+
var FILE_ENDINGS = /* @__PURE__ */ new Set([
|
|
5114
|
+
"js",
|
|
5115
|
+
"jsx",
|
|
5116
|
+
"ts",
|
|
5117
|
+
"tsx",
|
|
5118
|
+
"mjs",
|
|
5119
|
+
"cjs",
|
|
5120
|
+
"css",
|
|
5121
|
+
"scss",
|
|
5122
|
+
"html",
|
|
5123
|
+
"htm",
|
|
5124
|
+
"json",
|
|
5125
|
+
"yaml",
|
|
5126
|
+
"yml",
|
|
5127
|
+
"toml",
|
|
5128
|
+
"xml",
|
|
5129
|
+
"txt",
|
|
5130
|
+
"log",
|
|
5131
|
+
"csv",
|
|
5132
|
+
"pdf",
|
|
5133
|
+
"png",
|
|
5134
|
+
"jpg",
|
|
5135
|
+
"jpeg",
|
|
5136
|
+
"gif",
|
|
5137
|
+
"svg",
|
|
5138
|
+
"webp",
|
|
5139
|
+
"php",
|
|
5140
|
+
"rb",
|
|
5141
|
+
"cpp",
|
|
5142
|
+
"exe",
|
|
5143
|
+
"lock",
|
|
5144
|
+
"map",
|
|
5145
|
+
"env",
|
|
5146
|
+
"md",
|
|
5147
|
+
"gz",
|
|
5148
|
+
"tar"
|
|
5149
|
+
]);
|
|
5150
|
+
var FILE_MIDDLES = /* @__PURE__ */ new Set([
|
|
5151
|
+
"config",
|
|
5152
|
+
"spec",
|
|
5153
|
+
"test",
|
|
5154
|
+
"min",
|
|
5155
|
+
"d",
|
|
5156
|
+
"module",
|
|
5157
|
+
"stories",
|
|
5158
|
+
"setup",
|
|
5159
|
+
"types",
|
|
5160
|
+
"bundle",
|
|
5161
|
+
"schema"
|
|
5162
|
+
]);
|
|
5163
|
+
var KNOWN_NAMES = /* @__PURE__ */ new Set(["asp.net", "ado.net", "vb.net"]);
|
|
5164
|
+
var DOT_LETTERS = /* @__PURE__ */ new Set(["\uA4F8", "\uA78F"]);
|
|
5165
|
+
var make = (source, flags) => new RegExp(source, flags);
|
|
5166
|
+
var one = (set) => make(`^[${set}]$`, "u");
|
|
5167
|
+
var engine;
|
|
5168
|
+
function patterns() {
|
|
5169
|
+
if (engine !== void 0) return engine;
|
|
5170
|
+
try {
|
|
5171
|
+
const lgc = "\\p{sc=Latn}\\p{sc=Grek}\\p{sc=Cyrl}\\p{sc=Zyyy}";
|
|
5172
|
+
engine = {
|
|
5173
|
+
/* Controls, line separators and the bidi controls: a space, not
|
|
5174
|
+
nothing, because they separated something. */
|
|
5175
|
+
control: make("[\\p{Cc}\\p{Zl}\\p{Zp}\\u202a-\\u202e\\u2066-\\u2069]", "gu"),
|
|
5176
|
+
invisible: make("[\\p{Cf}\\p{Me}\\p{Default_Ignorable_Code_Point}]", "gu"),
|
|
5177
|
+
looseMark: make(`(^|[${lgc}])\\p{Mn}+`, "gu"),
|
|
5178
|
+
anyMark: make("\\p{M}", "gu"),
|
|
5179
|
+
letter: one("\\p{L}"),
|
|
5180
|
+
modifier: one("\\p{Lm}"),
|
|
5181
|
+
digit: one("\\p{Nd}"),
|
|
5182
|
+
number: one("\\p{N}"),
|
|
5183
|
+
punctOrSymbol: one("\\p{P}\\p{S}"),
|
|
5184
|
+
/* Dashes and quotation marks are not drawn as a dot. */
|
|
5185
|
+
notAJoiner: one("\\p{Pd}\\p{Pi}\\p{Pf}"),
|
|
5186
|
+
latin: one("\\p{sc=Latn}"),
|
|
5187
|
+
greek: one("\\p{sc=Grek}"),
|
|
5188
|
+
cyrillic: one("\\p{sc=Cyrl}"),
|
|
5189
|
+
noSpace: one(
|
|
5190
|
+
"\\p{sc=Hani}\\p{sc=Hira}\\p{sc=Kana}\\p{sc=Hang}\\p{sc=Bopo}\\p{sc=Thai}\\p{sc=Laoo}\\p{sc=Khmr}\\p{sc=Mymr}\\p{sc=Tibt}"
|
|
5191
|
+
),
|
|
5192
|
+
common: one("\\p{sc=Zyyy}\\p{sc=Zinh}"),
|
|
5193
|
+
tld: make("^\\p{L}{2,}$", "u"),
|
|
5194
|
+
ipv6Bracket: make("\\[[0-9a-f:.]*:[0-9a-f:.]*\\]", "g"),
|
|
5195
|
+
ipv6Bare: make("(^|[^\\p{L}\\p{N}:.])([0-9a-f:]{3,})(?![\\p{L}\\p{N}:.])", "gu")
|
|
5196
|
+
};
|
|
5197
|
+
} catch {
|
|
5198
|
+
engine = null;
|
|
5199
|
+
}
|
|
5200
|
+
return engine;
|
|
5201
|
+
}
|
|
5202
|
+
function foldPreviewText(value) {
|
|
5203
|
+
const rx = patterns();
|
|
5204
|
+
if (!rx) throw new Error("link-preview: no Unicode property support");
|
|
5205
|
+
return value.normalize("NFKC").replace(rx.control, " ").replace(rx.invisible, "").replace(rx.looseMark, "$1").replace(/\s+/g, " ").trim();
|
|
5206
|
+
}
|
|
5207
|
+
function cleanPreviewText(value, cap) {
|
|
5208
|
+
if (typeof value !== "string") return null;
|
|
5209
|
+
let text;
|
|
5210
|
+
try {
|
|
5211
|
+
text = foldPreviewText(value);
|
|
5212
|
+
} catch {
|
|
5213
|
+
return null;
|
|
5214
|
+
}
|
|
5215
|
+
if (!text) return null;
|
|
5216
|
+
return text.length > cap ? `${text.slice(0, cap - 1).trimEnd()}\u2026` : text;
|
|
5217
|
+
}
|
|
5218
|
+
var BREAK = { kind: "break", script: "common" };
|
|
5219
|
+
var seen = /* @__PURE__ */ new Map();
|
|
5220
|
+
function scriptOf(ch, rx) {
|
|
5221
|
+
if (rx.latin.test(ch)) return "latin";
|
|
5222
|
+
if (rx.noSpace.test(ch)) return "nospace";
|
|
5223
|
+
if (rx.cyrillic.test(ch)) return "cyrillic";
|
|
5224
|
+
if (rx.greek.test(ch)) return "greek";
|
|
5225
|
+
if (rx.common.test(ch)) return "common";
|
|
5226
|
+
return "other";
|
|
5227
|
+
}
|
|
5228
|
+
function read(ch, rx) {
|
|
5229
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
5230
|
+
if (code < 128) {
|
|
5231
|
+
if (ch === ".") return { kind: "dot", script: "common" };
|
|
5232
|
+
if (ch === "-" || code >= 48 && code <= 57) return { kind: "word", script: "common" };
|
|
5233
|
+
if (code >= 97 && code <= 122) return { kind: "word", script: "latin" };
|
|
5234
|
+
return BREAK;
|
|
5235
|
+
}
|
|
5236
|
+
const known = seen.get(ch);
|
|
5237
|
+
if (known) return known;
|
|
5238
|
+
let out = BREAK;
|
|
5239
|
+
if (DOT_LETTERS.has(ch) || rx.modifier.test(ch)) out = { kind: "join", script: "common" };
|
|
5240
|
+
else if (rx.letter.test(ch)) out = { kind: "word", script: scriptOf(ch, rx) };
|
|
5241
|
+
else if (rx.digit.test(ch)) out = { kind: "join", script: "common" };
|
|
5242
|
+
else if (rx.number.test(ch)) out = { kind: "word", script: "common" };
|
|
5243
|
+
else if (rx.notAJoiner.test(ch)) out = BREAK;
|
|
5244
|
+
else if (rx.punctOrSymbol.test(ch)) out = { kind: "join", script: "common" };
|
|
5245
|
+
if (seen.size < 4096) seen.set(ch, out);
|
|
5246
|
+
return out;
|
|
5247
|
+
}
|
|
5248
|
+
function shapeOf(checked, rx) {
|
|
5249
|
+
const tokens = [];
|
|
5250
|
+
let mixed = false;
|
|
5251
|
+
let run = "";
|
|
5252
|
+
let letters = 0;
|
|
5253
|
+
let noSpaceLetters = 0;
|
|
5254
|
+
let piece = /* @__PURE__ */ new Set();
|
|
5255
|
+
const endPiece = () => {
|
|
5256
|
+
piece.delete("nospace");
|
|
5257
|
+
piece.delete("common");
|
|
5258
|
+
if (piece.size > 1) mixed = true;
|
|
5259
|
+
piece = /* @__PURE__ */ new Set();
|
|
5260
|
+
};
|
|
5261
|
+
const endRun = () => {
|
|
5262
|
+
if (!run) return;
|
|
5263
|
+
endPiece();
|
|
5264
|
+
if (/[^-]/.test(run)) {
|
|
5265
|
+
tokens.push({
|
|
5266
|
+
kind: "word",
|
|
5267
|
+
text: run,
|
|
5268
|
+
noSpace: letters > 0 && noSpaceLetters === letters,
|
|
5269
|
+
hasLetter: letters > 0
|
|
5270
|
+
});
|
|
5271
|
+
} else {
|
|
5272
|
+
tokens.push({ kind: "break", text: run, noSpace: false, hasLetter: false });
|
|
5273
|
+
}
|
|
5274
|
+
run = "";
|
|
5275
|
+
letters = 0;
|
|
5276
|
+
noSpaceLetters = 0;
|
|
5277
|
+
};
|
|
5278
|
+
for (const ch of checked) {
|
|
5279
|
+
const c = read(ch, rx);
|
|
5280
|
+
if (c.kind === "word") {
|
|
5281
|
+
run += ch;
|
|
5282
|
+
if (ch === "-") endPiece();
|
|
5283
|
+
else if (c.script !== "common") {
|
|
5284
|
+
letters++;
|
|
5285
|
+
if (c.script === "nospace") noSpaceLetters++;
|
|
5286
|
+
piece.add(c.script);
|
|
5287
|
+
}
|
|
5288
|
+
continue;
|
|
5289
|
+
}
|
|
5290
|
+
endRun();
|
|
5291
|
+
tokens.push({ kind: c.kind, text: ch, noSpace: false, hasLetter: false });
|
|
5292
|
+
}
|
|
5293
|
+
endRun();
|
|
5294
|
+
return { tokens, mixed };
|
|
5295
|
+
}
|
|
5296
|
+
function hostOf(labels, rx, asAddress) {
|
|
5297
|
+
const n = labels.length;
|
|
5298
|
+
if (n === 4 && labels.every((l) => /^\d{1,3}$/.test(l))) return labels.join(".");
|
|
5299
|
+
let end = n;
|
|
5300
|
+
if (!asAddress) {
|
|
5301
|
+
let file = false;
|
|
5302
|
+
while (end > 1 && FILE_ENDINGS.has(labels[end - 1] ?? "")) {
|
|
5303
|
+
end--;
|
|
5304
|
+
file = true;
|
|
5305
|
+
}
|
|
5306
|
+
while (file && end > 1 && FILE_MIDDLES.has(labels[end - 1] ?? "")) end--;
|
|
5307
|
+
}
|
|
5308
|
+
for (let i = end - 1; i >= 1; i--) {
|
|
5309
|
+
const ending = (labels[i] ?? "").split("-", 1)[0] ?? "";
|
|
5310
|
+
if (!rx.tld.test(ending)) continue;
|
|
5311
|
+
const host = [...labels.slice(0, i), ending].join(".");
|
|
5312
|
+
return KNOWN_NAMES.has(host) ? null : host;
|
|
5313
|
+
}
|
|
5314
|
+
return null;
|
|
5315
|
+
}
|
|
5316
|
+
function hostsNamedIn(text) {
|
|
5317
|
+
const rx = patterns();
|
|
5318
|
+
if (!rx) return [""];
|
|
5319
|
+
const checked = foldPreviewText(text).replace(rx.anyMark, "").toLowerCase();
|
|
5320
|
+
const out = /* @__PURE__ */ new Set();
|
|
5321
|
+
const { tokens, mixed } = shapeOf(checked, rx);
|
|
5322
|
+
if (mixed) out.add("");
|
|
5323
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
5324
|
+
const first = tokens[i];
|
|
5325
|
+
if (!first || first.kind !== "word") continue;
|
|
5326
|
+
const labels = [first.text];
|
|
5327
|
+
let anyLetter = first.hasLetter;
|
|
5328
|
+
let j = i;
|
|
5329
|
+
for (; ; ) {
|
|
5330
|
+
const sep = tokens[j + 1];
|
|
5331
|
+
const next = tokens[j + 2];
|
|
5332
|
+
const here = tokens[j];
|
|
5333
|
+
if (!sep || !next || !here || next.kind !== "word") break;
|
|
5334
|
+
if (sep.kind === "break") break;
|
|
5335
|
+
if (sep.kind === "join" && here.noSpace && next.noSpace) break;
|
|
5336
|
+
labels.push(next.text);
|
|
5337
|
+
anyLetter ||= next.hasLetter;
|
|
5338
|
+
j += 2;
|
|
5339
|
+
}
|
|
5340
|
+
const before = tokens[i - 1]?.text;
|
|
5341
|
+
const host = labels.length > 1 ? hostOf(labels, rx, before === "@") : null;
|
|
5342
|
+
if (host) out.add(host);
|
|
5343
|
+
const colon = tokens[j + 1];
|
|
5344
|
+
const port = tokens[j + 2];
|
|
5345
|
+
if (!host && anyLetter && colon?.text === ":" && port && /^\d{1,5}$/.test(port.text)) {
|
|
5346
|
+
out.add(labels.join("."));
|
|
5347
|
+
}
|
|
5348
|
+
i = j;
|
|
5349
|
+
}
|
|
5350
|
+
for (let at = checked.indexOf("://"); at !== -1; at = checked.indexOf("://", at + 3)) {
|
|
5351
|
+
const rest = checked.slice(at + 3, at + 3 + 300);
|
|
5352
|
+
const authority = (rest.split(/[\s/?#]/, 1)[0] ?? "").split("@").pop() ?? "";
|
|
5353
|
+
const literal = /^\[[^\]]*\]/.exec(authority)?.[0];
|
|
5354
|
+
out.add(literal ?? authority.replace(/:\d*$/, ""));
|
|
5355
|
+
}
|
|
5356
|
+
for (const m of checked.matchAll(rx.ipv6Bracket)) out.add(m[0]);
|
|
5357
|
+
for (const m of checked.matchAll(rx.ipv6Bare)) {
|
|
5358
|
+
const literal = m[2] ?? "";
|
|
5359
|
+
const colons = literal.split(":").length - 1;
|
|
5360
|
+
if (/[0-9a-f]/.test(literal) && (literal.includes("::") || colons === 7)) out.add(literal);
|
|
5361
|
+
}
|
|
5362
|
+
return [...out];
|
|
5363
|
+
}
|
|
5364
|
+
function bare(host) {
|
|
5365
|
+
const h = host.toLowerCase();
|
|
5366
|
+
const bracketed = /^\[(.*)\](?::\d+)?$/.exec(h);
|
|
5367
|
+
if (bracketed) return bracketed[1] ?? "";
|
|
5368
|
+
if (h.split(":").length > 2) return h;
|
|
5369
|
+
return h.replace(/:\d+$/, "").replace(/\.$/, "").replace(/^www\./, "");
|
|
5370
|
+
}
|
|
5371
|
+
function sameSite(a, b) {
|
|
5372
|
+
const x = bare(a);
|
|
5373
|
+
const y = bare(b);
|
|
5374
|
+
if (!x || !y) return false;
|
|
5375
|
+
return x === y || x.endsWith(`.${y}`) || y.endsWith(`.${x}`);
|
|
5376
|
+
}
|
|
5377
|
+
function ascii(named) {
|
|
5378
|
+
if (/^[\x00-\x7f]*$/.test(named)) return named;
|
|
5379
|
+
try {
|
|
5380
|
+
return new URL(`https://${named}`).hostname;
|
|
5381
|
+
} catch {
|
|
5382
|
+
return null;
|
|
5383
|
+
}
|
|
5384
|
+
}
|
|
5385
|
+
function namesAnotherSite(text, realHost) {
|
|
5386
|
+
let named;
|
|
5387
|
+
try {
|
|
5388
|
+
named = hostsNamedIn(text);
|
|
5389
|
+
} catch {
|
|
5390
|
+
return true;
|
|
5391
|
+
}
|
|
5392
|
+
for (const host of named) {
|
|
5393
|
+
const form = host === "" ? null : ascii(host);
|
|
5394
|
+
if (form === null || !sameSite(form, realHost)) return true;
|
|
5395
|
+
}
|
|
5396
|
+
return false;
|
|
5397
|
+
}
|
|
5398
|
+
var PREVIEW_HOST_CAP = 40;
|
|
5399
|
+
function previewHost(url) {
|
|
5400
|
+
const host = url.host.replace(/^www\./, "");
|
|
5401
|
+
return host.length > PREVIEW_HOST_CAP ? `\u2026${host.slice(host.length - (PREVIEW_HOST_CAP - 1))}` : host;
|
|
5402
|
+
}
|
|
5403
|
+
function previewWords(url, raw, caps = { title: 160, description: 280 }) {
|
|
5404
|
+
const keep = (value, cap) => {
|
|
5405
|
+
if (typeof value !== "string" || namesAnotherSite(value, url.hostname)) return null;
|
|
5406
|
+
return cleanPreviewText(value, cap);
|
|
5407
|
+
};
|
|
5408
|
+
return {
|
|
5409
|
+
title: keep(raw.title, caps.title),
|
|
5410
|
+
description: keep(raw.description, caps.description)
|
|
5411
|
+
};
|
|
5412
|
+
}
|
|
5413
|
+
var PREVIEW_ICON_MAX_BYTES = 32 * 1024;
|
|
5414
|
+
|
|
5415
|
+
// src/themed/link-preview.ts
|
|
5416
|
+
function httpsOnly(value) {
|
|
5417
|
+
if (!value) return null;
|
|
5418
|
+
try {
|
|
5419
|
+
const url = new URL(value);
|
|
5420
|
+
return url.protocol === "https:" && !url.username && !url.password ? url.href : null;
|
|
5421
|
+
} catch {
|
|
5422
|
+
return null;
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
function pictureOnly(image, title) {
|
|
5426
|
+
if (!image || !title) return image;
|
|
5427
|
+
let asked;
|
|
5428
|
+
try {
|
|
5429
|
+
asked = new URL(image).searchParams.get("title");
|
|
5430
|
+
} catch {
|
|
5431
|
+
return image;
|
|
5432
|
+
}
|
|
5433
|
+
if (!asked) return image;
|
|
5434
|
+
const fold = (v) => v.toLowerCase().replace(/\s+/g, " ").trim();
|
|
5435
|
+
const a = fold(asked);
|
|
5436
|
+
const t2 = fold(title);
|
|
5437
|
+
return a.length >= 4 && (t2.includes(a) || a.includes(t2)) ? null : image;
|
|
5438
|
+
}
|
|
5439
|
+
function linkPreviewView(preview) {
|
|
5440
|
+
let url;
|
|
5441
|
+
try {
|
|
5442
|
+
url = new URL(preview.url);
|
|
5443
|
+
} catch {
|
|
5444
|
+
return null;
|
|
5445
|
+
}
|
|
5446
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password) {
|
|
5447
|
+
return null;
|
|
5448
|
+
}
|
|
5449
|
+
const { title, description } = previewWords(url, preview);
|
|
5450
|
+
if (!title && !description) return null;
|
|
5451
|
+
return {
|
|
5452
|
+
href: url.href,
|
|
5453
|
+
host: previewHost(url),
|
|
5454
|
+
title,
|
|
5455
|
+
description,
|
|
5456
|
+
image: pictureOnly(httpsOnly(preview.imageUrl), title),
|
|
5457
|
+
favicon: httpsOnly(preview.favicon)
|
|
5458
|
+
};
|
|
5459
|
+
}
|
|
5460
|
+
|
|
4737
5461
|
// src/themed/message-bubble.tsx
|
|
4738
|
-
import { useEffect as useEffect12, useLayoutEffect, useRef as useRef13, useState as useState13 } from "react";
|
|
4739
5462
|
import { createPortal } from "react-dom";
|
|
4740
|
-
import { Fragment as Fragment3, jsx as
|
|
5463
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4741
5464
|
function MessageBubble({
|
|
4742
5465
|
text,
|
|
4743
5466
|
sender,
|
|
@@ -4750,7 +5473,7 @@ function MessageBubble({
|
|
|
4750
5473
|
streaming
|
|
4751
5474
|
}) {
|
|
4752
5475
|
const senderClass = `hw-msg--${sender}`;
|
|
4753
|
-
const bubbleRef =
|
|
5476
|
+
const bubbleRef = useRef15(null);
|
|
4754
5477
|
const imageParts = parts?.filter((p) => p.type === "image") ?? [];
|
|
4755
5478
|
const fileParts = parts?.filter((p) => p.type === "file") ?? [];
|
|
4756
5479
|
const linkPreviews = parts?.filter(
|
|
@@ -4760,7 +5483,7 @@ function MessageBubble({
|
|
|
4760
5483
|
(p) => p.type === "source"
|
|
4761
5484
|
) ?? [];
|
|
4762
5485
|
const hasText = text.length > 0;
|
|
4763
|
-
|
|
5486
|
+
useEffect13(() => {
|
|
4764
5487
|
const bubble = bubbleRef.current;
|
|
4765
5488
|
if (!bubble || sender !== "ai" && sender !== "team") return;
|
|
4766
5489
|
const handleClick = (event) => {
|
|
@@ -4771,23 +5494,23 @@ function MessageBubble({
|
|
|
4771
5494
|
bubble.removeEventListener("click", handleClick);
|
|
4772
5495
|
};
|
|
4773
5496
|
}, [sender]);
|
|
4774
|
-
return /* @__PURE__ */
|
|
4775
|
-
imageParts.length > 0 && /* @__PURE__ */
|
|
4776
|
-
hasText && /* @__PURE__ */
|
|
4777
|
-
sender === "ai" || sender === "team" ? /* @__PURE__ */
|
|
5497
|
+
return /* @__PURE__ */ jsx15("div", { className: `hw-msg ${senderClass}`, children: /* @__PURE__ */ jsxs10("div", { className: "hw-msg-body", children: [
|
|
5498
|
+
imageParts.length > 0 && /* @__PURE__ */ jsx15("div", { className: "hw-msg-images", children: imageParts.map((img, i) => /* @__PURE__ */ jsx15(PreviewableThumbnail, { src: img.url }, i)) }),
|
|
5499
|
+
hasText && /* @__PURE__ */ jsxs10("div", { className: "hw-msg-bubble", ref: bubbleRef, children: [
|
|
5500
|
+
sender === "ai" || sender === "team" ? /* @__PURE__ */ jsx15(
|
|
4778
5501
|
"span",
|
|
4779
5502
|
{
|
|
4780
5503
|
dangerouslySetInnerHTML: {
|
|
4781
5504
|
__html: renderMarkdown(streaming ? closeDanglingMarkdown(text) : text)
|
|
4782
5505
|
}
|
|
4783
5506
|
}
|
|
4784
|
-
) : /* @__PURE__ */
|
|
4785
|
-
streaming && /* @__PURE__ */
|
|
5507
|
+
) : /* @__PURE__ */ jsx15("span", { dangerouslySetInnerHTML: { __html: linkifyText(text) } }),
|
|
5508
|
+
streaming && /* @__PURE__ */ jsx15("span", { className: "hw-streaming-cursor" })
|
|
4786
5509
|
] }),
|
|
4787
|
-
fileParts.length > 0 && /* @__PURE__ */
|
|
4788
|
-
linkPreviews.length > 0 && /* @__PURE__ */
|
|
4789
|
-
sources.length > 0 && /* @__PURE__ */
|
|
4790
|
-
(src, i) => src.sourceUrl ? /* @__PURE__ */
|
|
5510
|
+
fileParts.length > 0 && /* @__PURE__ */ jsx15("div", { className: "hw-msg-files", children: fileParts.map((file, i) => /* @__PURE__ */ jsx15(FileCard, { file }, i)) }),
|
|
5511
|
+
linkPreviews.length > 0 && /* @__PURE__ */ jsx15("div", { className: "hw-msg-links", children: linkPreviews.map((lp, i) => /* @__PURE__ */ jsx15(LinkPreviewCard, { preview: lp }, i)) }),
|
|
5512
|
+
sources.length > 0 && /* @__PURE__ */ jsx15("div", { className: "hw-sources", children: sources.map(
|
|
5513
|
+
(src, i) => src.sourceUrl ? /* @__PURE__ */ jsxs10(
|
|
4791
5514
|
"a",
|
|
4792
5515
|
{
|
|
4793
5516
|
href: src.sourceUrl,
|
|
@@ -4796,26 +5519,26 @@ function MessageBubble({
|
|
|
4796
5519
|
className: "hw-source",
|
|
4797
5520
|
onClick: (e) => e.stopPropagation(),
|
|
4798
5521
|
children: [
|
|
4799
|
-
/* @__PURE__ */
|
|
4800
|
-
/* @__PURE__ */
|
|
5522
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-source-n", children: i + 1 }),
|
|
5523
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-source-title", children: src.title })
|
|
4801
5524
|
]
|
|
4802
5525
|
},
|
|
4803
5526
|
src.knowledgeId
|
|
4804
|
-
) : /* @__PURE__ */
|
|
4805
|
-
/* @__PURE__ */
|
|
4806
|
-
/* @__PURE__ */
|
|
5527
|
+
) : /* @__PURE__ */ jsxs10("div", { className: "hw-source", children: [
|
|
5528
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-source-n", children: i + 1 }),
|
|
5529
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-source-title", children: src.title })
|
|
4807
5530
|
] }, src.knowledgeId)
|
|
4808
5531
|
) }),
|
|
4809
|
-
metadata?.kind === "quick_replies" && /* @__PURE__ */
|
|
5532
|
+
metadata?.kind === "quick_replies" && /* @__PURE__ */ jsx15(QuickReplyButtons, { metadata, onTap: onQuickReplyTap }),
|
|
4810
5533
|
(() => {
|
|
4811
5534
|
const isVisitor = sender === "visitor";
|
|
4812
5535
|
const lead = isVisitor ? null : senderName ?? null;
|
|
4813
5536
|
const withLead = (showAuthor ?? !!timestamp) && !!lead;
|
|
4814
5537
|
if (!withLead && !timestamp) return null;
|
|
4815
|
-
return /* @__PURE__ */
|
|
4816
|
-
withLead && /* @__PURE__ */
|
|
4817
|
-
withLead && timestamp && /* @__PURE__ */
|
|
4818
|
-
timestamp && /* @__PURE__ */
|
|
5538
|
+
return /* @__PURE__ */ jsxs10("div", { className: "hw-msg-meta", children: [
|
|
5539
|
+
withLead && /* @__PURE__ */ jsx15("span", { className: "hw-msg-author", children: lead }),
|
|
5540
|
+
withLead && timestamp && /* @__PURE__ */ jsx15("span", { className: "hw-msg-meta-sep", children: "\xB7" }),
|
|
5541
|
+
timestamp && /* @__PURE__ */ jsx15("span", { className: "hw-msg-time", children: timestamp })
|
|
4819
5542
|
] });
|
|
4820
5543
|
})()
|
|
4821
5544
|
] }) });
|
|
@@ -4824,21 +5547,21 @@ function QuickReplyButtons({
|
|
|
4824
5547
|
metadata,
|
|
4825
5548
|
onTap
|
|
4826
5549
|
}) {
|
|
4827
|
-
const [tappedId, setTappedId] =
|
|
5550
|
+
const [tappedId, setTappedId] = useState14(null);
|
|
4828
5551
|
const isLocked = metadata.cancelled || tappedId !== null;
|
|
4829
5552
|
const handleTap = (optionId) => {
|
|
4830
5553
|
if (isLocked) return;
|
|
4831
5554
|
setTappedId(optionId);
|
|
4832
5555
|
onTap?.(optionId, metadata.stepId);
|
|
4833
5556
|
};
|
|
4834
|
-
return /* @__PURE__ */
|
|
5557
|
+
return /* @__PURE__ */ jsx15(
|
|
4835
5558
|
"div",
|
|
4836
5559
|
{
|
|
4837
5560
|
className: "hw-quick-replies",
|
|
4838
5561
|
"data-cancelled": metadata.cancelled ? "true" : void 0,
|
|
4839
5562
|
children: metadata.options.map((opt) => {
|
|
4840
5563
|
const isTapped = tappedId === opt.id;
|
|
4841
|
-
return /* @__PURE__ */
|
|
5564
|
+
return /* @__PURE__ */ jsx15(
|
|
4842
5565
|
"button",
|
|
4843
5566
|
{
|
|
4844
5567
|
type: "button",
|
|
@@ -4855,10 +5578,18 @@ function QuickReplyButtons({
|
|
|
4855
5578
|
);
|
|
4856
5579
|
}
|
|
4857
5580
|
function PreviewableThumbnail({ src }) {
|
|
4858
|
-
const [hover, setHover] =
|
|
4859
|
-
const
|
|
4860
|
-
|
|
4861
|
-
|
|
5581
|
+
const [hover, setHover] = useState14(false);
|
|
5582
|
+
const [broken, setBroken] = useState14(false);
|
|
5583
|
+
const ref = useRef15(null);
|
|
5584
|
+
if (broken) {
|
|
5585
|
+
const name = imageFileName(src);
|
|
5586
|
+
return /* @__PURE__ */ jsxs10("a", { href: src, target: "_blank", rel: "noopener noreferrer", className: "hw-msg-file", children: [
|
|
5587
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-msg-file-icon", children: /* @__PURE__ */ jsx15(FileTypeIcon, { ext: fileExt(name) }) }),
|
|
5588
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-msg-file-info", children: /* @__PURE__ */ jsx15("span", { className: "hw-msg-file-name", children: name }) })
|
|
5589
|
+
] });
|
|
5590
|
+
}
|
|
5591
|
+
return /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5592
|
+
/* @__PURE__ */ jsx15(
|
|
4862
5593
|
"a",
|
|
4863
5594
|
{
|
|
4864
5595
|
ref,
|
|
@@ -4869,21 +5600,21 @@ function PreviewableThumbnail({ src }) {
|
|
|
4869
5600
|
"aria-label": t("widget.aria_open_image"),
|
|
4870
5601
|
onMouseEnter: () => setHover(true),
|
|
4871
5602
|
onMouseLeave: () => setHover(false),
|
|
4872
|
-
children: /* @__PURE__ */
|
|
5603
|
+
children: /* @__PURE__ */ jsx15("img", { src, alt: "", className: "hw-msg-image", loading: "lazy", onError: () => setBroken(true) })
|
|
4873
5604
|
}
|
|
4874
5605
|
),
|
|
4875
|
-
hover && /* @__PURE__ */
|
|
5606
|
+
hover && /* @__PURE__ */ jsx15(AnchoredPreview, { src, anchorRef: ref, href: src })
|
|
4876
5607
|
] });
|
|
4877
5608
|
}
|
|
4878
5609
|
var PREVIEWABLE_EXTS = /* @__PURE__ */ new Set(["pdf", "csv", "png", "jpg", "jpeg", "gif", "webp", "svg"]);
|
|
4879
5610
|
function FileCard({ file }) {
|
|
4880
|
-
const [hover, setHover] =
|
|
4881
|
-
const ref =
|
|
5611
|
+
const [hover, setHover] = useState14(false);
|
|
5612
|
+
const ref = useRef15(null);
|
|
4882
5613
|
const ext = file.fileName.split(".").pop()?.toLowerCase() ?? "";
|
|
4883
5614
|
const isPreviewable = PREVIEWABLE_EXTS.has(ext);
|
|
4884
5615
|
const isImage = file.mimeType.startsWith("image/");
|
|
4885
|
-
return /* @__PURE__ */
|
|
4886
|
-
/* @__PURE__ */
|
|
5616
|
+
return /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5617
|
+
/* @__PURE__ */ jsxs10(
|
|
4887
5618
|
"a",
|
|
4888
5619
|
{
|
|
4889
5620
|
ref,
|
|
@@ -4894,15 +5625,15 @@ function FileCard({ file }) {
|
|
|
4894
5625
|
onMouseEnter: () => isPreviewable && setHover(true),
|
|
4895
5626
|
onMouseLeave: () => setHover(false),
|
|
4896
5627
|
children: [
|
|
4897
|
-
/* @__PURE__ */
|
|
4898
|
-
/* @__PURE__ */
|
|
4899
|
-
/* @__PURE__ */
|
|
4900
|
-
/* @__PURE__ */
|
|
5628
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-msg-file-icon", children: /* @__PURE__ */ jsx15(FileTypeIcon, { ext }) }),
|
|
5629
|
+
/* @__PURE__ */ jsxs10("span", { className: "hw-msg-file-info", children: [
|
|
5630
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-msg-file-name", children: file.fileName }),
|
|
5631
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-msg-file-size", children: formatFileSize(file.fileSize) })
|
|
4901
5632
|
] })
|
|
4902
5633
|
]
|
|
4903
5634
|
}
|
|
4904
5635
|
),
|
|
4905
|
-
hover && isPreviewable && (isImage ? /* @__PURE__ */
|
|
5636
|
+
hover && isPreviewable && (isImage ? /* @__PURE__ */ jsx15(AnchoredPreview, { src: file.url, anchorRef: ref, href: file.url }) : /* @__PURE__ */ jsx15(AnchoredDocPreview, { fileName: file.fileName, ext, anchorRef: ref, href: file.url }))
|
|
4906
5637
|
] });
|
|
4907
5638
|
}
|
|
4908
5639
|
function AnchoredPreview({
|
|
@@ -4911,8 +5642,8 @@ function AnchoredPreview({
|
|
|
4911
5642
|
href,
|
|
4912
5643
|
onOpen
|
|
4913
5644
|
}) {
|
|
4914
|
-
const [style, setStyle] =
|
|
4915
|
-
const [portalTarget, setPortalTarget] =
|
|
5645
|
+
const [style, setStyle] = useState14({ opacity: 0 });
|
|
5646
|
+
const [portalTarget, setPortalTarget] = useState14(null);
|
|
4916
5647
|
useLayoutEffect(() => {
|
|
4917
5648
|
const anchor = anchorRef.current;
|
|
4918
5649
|
if (!anchor) return;
|
|
@@ -4936,7 +5667,7 @@ function AnchoredPreview({
|
|
|
4936
5667
|
};
|
|
4937
5668
|
if (!portalTarget) return null;
|
|
4938
5669
|
return createPortal(
|
|
4939
|
-
/* @__PURE__ */
|
|
5670
|
+
/* @__PURE__ */ jsx15("div", { className: "hw-hover-preview", style, onClick: handleClick, children: /* @__PURE__ */ jsx15("img", { src, alt: "", className: "hw-hover-preview-img" }) }),
|
|
4940
5671
|
portalTarget
|
|
4941
5672
|
);
|
|
4942
5673
|
}
|
|
@@ -4946,8 +5677,8 @@ function AnchoredDocPreview({
|
|
|
4946
5677
|
anchorRef,
|
|
4947
5678
|
href
|
|
4948
5679
|
}) {
|
|
4949
|
-
const [style, setStyle] =
|
|
4950
|
-
const [portalTarget, setPortalTarget] =
|
|
5680
|
+
const [style, setStyle] = useState14({ opacity: 0 });
|
|
5681
|
+
const [portalTarget, setPortalTarget] = useState14(null);
|
|
4951
5682
|
useLayoutEffect(() => {
|
|
4952
5683
|
const anchor = anchorRef.current;
|
|
4953
5684
|
if (!anchor) return;
|
|
@@ -4967,17 +5698,17 @@ function AnchoredDocPreview({
|
|
|
4967
5698
|
}, [anchorRef]);
|
|
4968
5699
|
if (!portalTarget) return null;
|
|
4969
5700
|
return createPortal(
|
|
4970
|
-
/* @__PURE__ */
|
|
5701
|
+
/* @__PURE__ */ jsxs10(
|
|
4971
5702
|
"div",
|
|
4972
5703
|
{
|
|
4973
5704
|
className: "hw-hover-preview hw-hover-preview--doc",
|
|
4974
5705
|
style,
|
|
4975
5706
|
onClick: () => window.open(href, "_blank", "noopener,noreferrer"),
|
|
4976
5707
|
children: [
|
|
4977
|
-
/* @__PURE__ */
|
|
4978
|
-
/* @__PURE__ */
|
|
4979
|
-
/* @__PURE__ */
|
|
4980
|
-
/* @__PURE__ */
|
|
5708
|
+
/* @__PURE__ */ jsx15("div", { className: "hw-hover-preview-doc-icon", children: /* @__PURE__ */ jsx15(FileTypeIcon, { ext }) }),
|
|
5709
|
+
/* @__PURE__ */ jsxs10("div", { className: "hw-hover-preview-doc-info", children: [
|
|
5710
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-hover-preview-doc-name", children: fileName }),
|
|
5711
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-hover-preview-doc-hint", children: t("widget.click_to_open") })
|
|
4981
5712
|
] })
|
|
4982
5713
|
]
|
|
4983
5714
|
}
|
|
@@ -5002,7 +5733,7 @@ var FILE_TYPE_COLORS = {
|
|
|
5002
5733
|
};
|
|
5003
5734
|
function FileTypeIcon({ ext }) {
|
|
5004
5735
|
const color = FILE_TYPE_COLORS[ext] ?? "currentColor";
|
|
5005
|
-
return /* @__PURE__ */
|
|
5736
|
+
return /* @__PURE__ */ jsxs10(
|
|
5006
5737
|
"svg",
|
|
5007
5738
|
{
|
|
5008
5739
|
viewBox: "0 0 24 24",
|
|
@@ -5012,60 +5743,60 @@ function FileTypeIcon({ ext }) {
|
|
|
5012
5743
|
strokeLinecap: "round",
|
|
5013
5744
|
strokeLinejoin: "round",
|
|
5014
5745
|
children: [
|
|
5015
|
-
/* @__PURE__ */
|
|
5016
|
-
/* @__PURE__ */
|
|
5017
|
-
ext === "pdf" && /* @__PURE__ */
|
|
5018
|
-
ext === "csv" && /* @__PURE__ */
|
|
5746
|
+
/* @__PURE__ */ jsx15("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
5747
|
+
/* @__PURE__ */ jsx15("polyline", { points: "14 2 14 8 20 8" }),
|
|
5748
|
+
ext === "pdf" && /* @__PURE__ */ jsx15("text", { x: "8", y: "18", fontSize: "6", fill: color, stroke: "none", fontWeight: "700", children: "PDF" }),
|
|
5749
|
+
ext === "csv" && /* @__PURE__ */ jsx15("text", { x: "7", y: "18", fontSize: "6", fill: color, stroke: "none", fontWeight: "700", children: "CSV" })
|
|
5019
5750
|
]
|
|
5020
5751
|
}
|
|
5021
5752
|
);
|
|
5022
5753
|
}
|
|
5023
5754
|
function LinkPreviewCard({ preview }) {
|
|
5024
|
-
const
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
}
|
|
5030
|
-
})();
|
|
5031
|
-
return /* @__PURE__ */ jsxs8(
|
|
5755
|
+
const view = linkPreviewView(preview);
|
|
5756
|
+
const [imageFailed, setImageFailed] = useState14(false);
|
|
5757
|
+
const [faviconFailed, setFaviconFailed] = useState14(false);
|
|
5758
|
+
if (!view) return null;
|
|
5759
|
+
return /* @__PURE__ */ jsxs10(
|
|
5032
5760
|
"a",
|
|
5033
5761
|
{
|
|
5034
|
-
href:
|
|
5762
|
+
href: view.href,
|
|
5035
5763
|
target: "_blank",
|
|
5036
5764
|
rel: "noopener noreferrer",
|
|
5037
5765
|
className: "hw-link-preview",
|
|
5038
5766
|
onClick: (e) => e.stopPropagation(),
|
|
5039
5767
|
children: [
|
|
5040
|
-
|
|
5768
|
+
view.image && !imageFailed && /* @__PURE__ */ jsx15(
|
|
5041
5769
|
"img",
|
|
5042
5770
|
{
|
|
5043
|
-
src:
|
|
5771
|
+
src: view.image,
|
|
5044
5772
|
alt: "",
|
|
5045
5773
|
className: "hw-link-preview-img",
|
|
5046
5774
|
loading: "lazy",
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5775
|
+
decoding: "async",
|
|
5776
|
+
referrerPolicy: "no-referrer",
|
|
5777
|
+
onError: () => setImageFailed(true)
|
|
5050
5778
|
}
|
|
5051
5779
|
),
|
|
5052
|
-
/* @__PURE__ */
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5780
|
+
/* @__PURE__ */ jsxs10("div", { className: "hw-link-preview-body", children: [
|
|
5781
|
+
/* @__PURE__ */ jsxs10("div", { className: "hw-link-preview-url", children: [
|
|
5782
|
+
view.favicon && !faviconFailed && /* @__PURE__ */ jsx15(
|
|
5783
|
+
"img",
|
|
5784
|
+
{
|
|
5785
|
+
src: view.favicon,
|
|
5786
|
+
alt: "",
|
|
5787
|
+
className: "hw-link-preview-favicon",
|
|
5788
|
+
width: 14,
|
|
5789
|
+
height: 14,
|
|
5790
|
+
loading: "lazy",
|
|
5791
|
+
decoding: "async",
|
|
5792
|
+
referrerPolicy: "no-referrer",
|
|
5793
|
+
onError: () => setFaviconFailed(true)
|
|
5063
5794
|
}
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
/* @__PURE__ */
|
|
5795
|
+
),
|
|
5796
|
+
/* @__PURE__ */ jsx15("span", { className: "hw-link-preview-host", children: view.host })
|
|
5797
|
+
] }),
|
|
5798
|
+
view.title && /* @__PURE__ */ jsx15("div", { className: "hw-link-preview-title", dir: "auto", children: view.title }),
|
|
5799
|
+
view.description && /* @__PURE__ */ jsx15("div", { className: "hw-link-preview-desc", dir: "auto", children: view.description })
|
|
5069
5800
|
] })
|
|
5070
5801
|
]
|
|
5071
5802
|
}
|
|
@@ -5073,8 +5804,8 @@ function LinkPreviewCard({ preview }) {
|
|
|
5073
5804
|
}
|
|
5074
5805
|
|
|
5075
5806
|
// src/themed/message-list.tsx
|
|
5076
|
-
import React, { useEffect as
|
|
5077
|
-
import { jsx as
|
|
5807
|
+
import React, { useEffect as useEffect14, useRef as useRef16 } from "react";
|
|
5808
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5078
5809
|
function parseParts(raw) {
|
|
5079
5810
|
if (!raw) return null;
|
|
5080
5811
|
if (Array.isArray(raw)) return raw;
|
|
@@ -5108,12 +5839,12 @@ function MessageList({
|
|
|
5108
5839
|
onLoadMore,
|
|
5109
5840
|
renderAfterMessages
|
|
5110
5841
|
}) {
|
|
5111
|
-
const bottomRef =
|
|
5112
|
-
const topRef =
|
|
5113
|
-
const containerRef =
|
|
5114
|
-
const prevItemCountRef =
|
|
5115
|
-
const isInitialLoadRef =
|
|
5116
|
-
const hadStreamRef =
|
|
5842
|
+
const bottomRef = useRef16(null);
|
|
5843
|
+
const topRef = useRef16(null);
|
|
5844
|
+
const containerRef = useRef16(null);
|
|
5845
|
+
const prevItemCountRef = useRef16(items.length);
|
|
5846
|
+
const isInitialLoadRef = useRef16(true);
|
|
5847
|
+
const hadStreamRef = useRef16(false);
|
|
5117
5848
|
const client = useWidgetClient();
|
|
5118
5849
|
const activeConversationId = useWidgetStore((s) => s.activeConversationId);
|
|
5119
5850
|
const handleQuickReplyTap = React.useCallback(
|
|
@@ -5125,7 +5856,7 @@ function MessageList({
|
|
|
5125
5856
|
},
|
|
5126
5857
|
[client, activeConversationId]
|
|
5127
5858
|
);
|
|
5128
|
-
|
|
5859
|
+
useEffect14(() => {
|
|
5129
5860
|
const prevCount = prevItemCountRef.current;
|
|
5130
5861
|
const newCount = items.length;
|
|
5131
5862
|
prevItemCountRef.current = newCount;
|
|
@@ -5141,18 +5872,18 @@ function MessageList({
|
|
|
5141
5872
|
isInitialLoadRef.current = false;
|
|
5142
5873
|
}
|
|
5143
5874
|
}, [items]);
|
|
5144
|
-
|
|
5875
|
+
useEffect14(() => {
|
|
5145
5876
|
if (streamingText) {
|
|
5146
5877
|
bottomRef.current?.scrollIntoView({ behavior: "instant" });
|
|
5147
5878
|
}
|
|
5148
5879
|
hadStreamRef.current = !!streamingText;
|
|
5149
5880
|
}, [streamingText]);
|
|
5150
|
-
|
|
5881
|
+
useEffect14(() => {
|
|
5151
5882
|
if (isTyping || isAiProcessing) {
|
|
5152
5883
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
5153
5884
|
}
|
|
5154
5885
|
}, [isTyping, isAiProcessing]);
|
|
5155
|
-
|
|
5886
|
+
useEffect14(() => {
|
|
5156
5887
|
if (!hasMore || !onLoadMore || !topRef.current) return;
|
|
5157
5888
|
const observer = new IntersectionObserver(
|
|
5158
5889
|
(entries) => {
|
|
@@ -5175,16 +5906,16 @@ function MessageList({
|
|
|
5175
5906
|
return () => observer.disconnect();
|
|
5176
5907
|
}, [hasMore, onLoadMore, isLoadingMore]);
|
|
5177
5908
|
if (items.length === 0) {
|
|
5178
|
-
return /* @__PURE__ */
|
|
5909
|
+
return /* @__PURE__ */ jsx16(
|
|
5179
5910
|
"div",
|
|
5180
5911
|
{
|
|
5181
5912
|
className: "hw-messages",
|
|
5182
5913
|
role: "log",
|
|
5183
5914
|
"aria-label": t("widget.aria_messages"),
|
|
5184
5915
|
"aria-live": "polite",
|
|
5185
|
-
children: /* @__PURE__ */
|
|
5186
|
-
/* @__PURE__ */
|
|
5187
|
-
/* @__PURE__ */
|
|
5916
|
+
children: /* @__PURE__ */ jsxs11("div", { className: "hw-empty", children: [
|
|
5917
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-empty-icon", children: /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx16("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) }) }),
|
|
5918
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-empty-text", children: t("widget.start_a_conversation") })
|
|
5188
5919
|
] })
|
|
5189
5920
|
}
|
|
5190
5921
|
);
|
|
@@ -5194,7 +5925,7 @@ function MessageList({
|
|
|
5194
5925
|
const yesterday = /* @__PURE__ */ new Date();
|
|
5195
5926
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
5196
5927
|
const yesterdayKey = DATE_KEY_FMT.format(yesterday);
|
|
5197
|
-
return /* @__PURE__ */
|
|
5928
|
+
return /* @__PURE__ */ jsxs11(
|
|
5198
5929
|
"div",
|
|
5199
5930
|
{
|
|
5200
5931
|
ref: containerRef,
|
|
@@ -5203,15 +5934,15 @@ function MessageList({
|
|
|
5203
5934
|
"aria-label": t("widget.aria_messages"),
|
|
5204
5935
|
"aria-live": "polite",
|
|
5205
5936
|
children: [
|
|
5206
|
-
/* @__PURE__ */
|
|
5207
|
-
/* @__PURE__ */
|
|
5208
|
-
/* @__PURE__ */
|
|
5209
|
-
/* @__PURE__ */
|
|
5937
|
+
/* @__PURE__ */ jsx16("div", { ref: topRef, className: "hw-load-more-trigger", children: isLoadingMore && /* @__PURE__ */ jsxs11("div", { className: "hw-load-more-spinner", children: [
|
|
5938
|
+
/* @__PURE__ */ jsx16("div", {}),
|
|
5939
|
+
/* @__PURE__ */ jsx16("div", {}),
|
|
5940
|
+
/* @__PURE__ */ jsx16("div", {})
|
|
5210
5941
|
] }) }),
|
|
5211
5942
|
[
|
|
5212
5943
|
...items.map((item) => {
|
|
5213
5944
|
if (item.type === "event") {
|
|
5214
|
-
return /* @__PURE__ */
|
|
5945
|
+
return /* @__PURE__ */ jsx16(
|
|
5215
5946
|
EventCard,
|
|
5216
5947
|
{
|
|
5217
5948
|
text: item.text ?? ""
|
|
@@ -5226,16 +5957,16 @@ function MessageList({
|
|
|
5226
5957
|
const showDateSep = isNewBucket && dateKey !== todayKey;
|
|
5227
5958
|
const dateLabel = dateKey === yesterdayKey ? t("widget.yesterday") : displayDateFormatter(getLocale()).format(itemDate);
|
|
5228
5959
|
const sender = item.visitorId ? "visitor" : item.aiAgentId ? "ai" : "team";
|
|
5229
|
-
return /* @__PURE__ */
|
|
5960
|
+
return /* @__PURE__ */ jsxs11(
|
|
5230
5961
|
React.Fragment,
|
|
5231
5962
|
{
|
|
5232
5963
|
children: [
|
|
5233
|
-
showDateSep && /* @__PURE__ */
|
|
5234
|
-
/* @__PURE__ */
|
|
5235
|
-
/* @__PURE__ */
|
|
5236
|
-
/* @__PURE__ */
|
|
5964
|
+
showDateSep && /* @__PURE__ */ jsxs11("div", { className: "hw-date-sep", children: [
|
|
5965
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-date-sep-line" }),
|
|
5966
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-date-sep-text", children: dateLabel }),
|
|
5967
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-date-sep-line" })
|
|
5237
5968
|
] }),
|
|
5238
|
-
/* @__PURE__ */
|
|
5969
|
+
/* @__PURE__ */ jsx16(
|
|
5239
5970
|
MessageBubble,
|
|
5240
5971
|
{
|
|
5241
5972
|
text: item.text ?? "",
|
|
@@ -5267,19 +5998,19 @@ function MessageList({
|
|
|
5267
5998
|
its place, .hw-msg replayed hw-msg-appear (styles.css:1326), and the
|
|
5268
5999
|
answer visibly animated in a second time just as it finished. */
|
|
5269
6000
|
...streamingText && activeConversationId ? [
|
|
5270
|
-
/* @__PURE__ */
|
|
6001
|
+
/* @__PURE__ */ jsxs11(React.Fragment, { children: [
|
|
5271
6002
|
null,
|
|
5272
|
-
/* @__PURE__ */
|
|
6003
|
+
/* @__PURE__ */ jsx16(MessageBubble, { text: streamingText, sender: "ai", parts: null, streaming: true })
|
|
5273
6004
|
] }, streamingKeyFor(activeConversationId))
|
|
5274
6005
|
] : []
|
|
5275
6006
|
],
|
|
5276
6007
|
renderAfterMessages,
|
|
5277
|
-
(isAiProcessing || isTyping) && !streamingText && /* @__PURE__ */
|
|
5278
|
-
/* @__PURE__ */
|
|
5279
|
-
/* @__PURE__ */
|
|
5280
|
-
/* @__PURE__ */
|
|
6008
|
+
(isAiProcessing || isTyping) && !streamingText && /* @__PURE__ */ jsx16("div", { className: "hw-typing", children: /* @__PURE__ */ jsxs11("div", { className: "hw-typing-dots", children: [
|
|
6009
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-typing-dot" }),
|
|
6010
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-typing-dot" }),
|
|
6011
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-typing-dot" })
|
|
5281
6012
|
] }) }),
|
|
5282
|
-
/* @__PURE__ */
|
|
6013
|
+
/* @__PURE__ */ jsx16("div", { ref: bottomRef })
|
|
5283
6014
|
]
|
|
5284
6015
|
}
|
|
5285
6016
|
);
|
|
@@ -5297,8 +6028,8 @@ function EventCard({ text }) {
|
|
|
5297
6028
|
const data = parseEventData(text);
|
|
5298
6029
|
if (data) {
|
|
5299
6030
|
const message = data.action === "joined" ? t("widget.joined") : t("widget.left");
|
|
5300
|
-
return /* @__PURE__ */
|
|
5301
|
-
/* @__PURE__ */
|
|
6031
|
+
return /* @__PURE__ */ jsxs11("div", { className: "hw-event hw-event--card", children: [
|
|
6032
|
+
/* @__PURE__ */ jsx16("div", { className: "hw-event-avatar", children: data.image ? /* @__PURE__ */ jsx16(
|
|
5302
6033
|
"img",
|
|
5303
6034
|
{
|
|
5304
6035
|
src: data.image,
|
|
@@ -5306,20 +6037,20 @@ function EventCard({ text }) {
|
|
|
5306
6037
|
className: "hw-event-avatar-img",
|
|
5307
6038
|
referrerPolicy: "no-referrer"
|
|
5308
6039
|
}
|
|
5309
|
-
) : /* @__PURE__ */
|
|
5310
|
-
/* @__PURE__ */
|
|
5311
|
-
/* @__PURE__ */
|
|
6040
|
+
) : /* @__PURE__ */ jsx16("span", { children: getInitials(data.name) }) }),
|
|
6041
|
+
/* @__PURE__ */ jsxs11("div", { className: "hw-event-body", children: [
|
|
6042
|
+
/* @__PURE__ */ jsx16("span", { className: "hw-event-name", children: data.name }),
|
|
5312
6043
|
" ",
|
|
5313
|
-
/* @__PURE__ */
|
|
6044
|
+
/* @__PURE__ */ jsx16("span", { className: "hw-event-action", children: message })
|
|
5314
6045
|
] })
|
|
5315
6046
|
] });
|
|
5316
6047
|
}
|
|
5317
|
-
return /* @__PURE__ */
|
|
6048
|
+
return /* @__PURE__ */ jsx16("div", { className: "hw-event", children: /* @__PURE__ */ jsx16("div", { className: "hw-event-text", children: text }) });
|
|
5318
6049
|
}
|
|
5319
6050
|
|
|
5320
6051
|
// src/themed/message-preview.tsx
|
|
5321
|
-
import { useEffect as
|
|
5322
|
-
import { Fragment as Fragment4, jsx as
|
|
6052
|
+
import { useEffect as useEffect15, useState as useState15 } from "react";
|
|
6053
|
+
import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5323
6054
|
function MessagePreview({
|
|
5324
6055
|
onOpen,
|
|
5325
6056
|
avatar,
|
|
@@ -5334,8 +6065,8 @@ function MessagePreview({
|
|
|
5334
6065
|
const client = useWidgetClient();
|
|
5335
6066
|
const senderName = preview?.senderName || agentName;
|
|
5336
6067
|
const senderImage = preview?.senderImage || null;
|
|
5337
|
-
const [closing, setClosing] =
|
|
5338
|
-
|
|
6068
|
+
const [closing, setClosing] = useState15(false);
|
|
6069
|
+
useEffect15(() => {
|
|
5339
6070
|
if (!preview || preview.quickReplies) return;
|
|
5340
6071
|
if (autoDismissMs == null || autoDismissMs <= 0) return;
|
|
5341
6072
|
const timer = setTimeout(() => {
|
|
@@ -5376,7 +6107,7 @@ function MessagePreview({
|
|
|
5376
6107
|
);
|
|
5377
6108
|
const qr = preview.quickReplies && preview.quickReplies.options.length > 0 ? preview.quickReplies : null;
|
|
5378
6109
|
const placementClass = placement === "anchored" ? "hw-preview--anchored " : "";
|
|
5379
|
-
return /* @__PURE__ */
|
|
6110
|
+
return /* @__PURE__ */ jsxs12(
|
|
5380
6111
|
"div",
|
|
5381
6112
|
{
|
|
5382
6113
|
className: `hw-preview ${placementClass}${closing ? "hw-preview--closing" : ""}`,
|
|
@@ -5390,17 +6121,17 @@ function MessagePreview({
|
|
|
5390
6121
|
role: "button",
|
|
5391
6122
|
tabIndex: 0,
|
|
5392
6123
|
children: [
|
|
5393
|
-
/* @__PURE__ */
|
|
5394
|
-
/* @__PURE__ */
|
|
5395
|
-
/* @__PURE__ */
|
|
5396
|
-
/* @__PURE__ */
|
|
6124
|
+
/* @__PURE__ */ jsxs12("div", { className: "hw-preview-header", children: [
|
|
6125
|
+
/* @__PURE__ */ jsx17("div", { className: "hw-preview-avatar", children: senderImage ? /* @__PURE__ */ jsx17("img", { src: senderImage, alt: "", referrerPolicy: "no-referrer" }) : avatar }),
|
|
6126
|
+
/* @__PURE__ */ jsx17("div", { className: "hw-preview-name", children: senderName }),
|
|
6127
|
+
/* @__PURE__ */ jsx17(
|
|
5397
6128
|
"button",
|
|
5398
6129
|
{
|
|
5399
6130
|
type: "button",
|
|
5400
6131
|
className: "hw-preview-close",
|
|
5401
6132
|
onClick: handleClose,
|
|
5402
6133
|
"aria-label": t("widget.aria_dismiss"),
|
|
5403
|
-
children: /* @__PURE__ */
|
|
6134
|
+
children: /* @__PURE__ */ jsx17(XIcon, { size: 20 })
|
|
5404
6135
|
}
|
|
5405
6136
|
)
|
|
5406
6137
|
] }),
|
|
@@ -5409,11 +6140,11 @@ function MessagePreview({
|
|
|
5409
6140
|
consecutive messages, so two identical ones would already be a bug
|
|
5410
6141
|
upstream, and an index key hands React the wrong bubble to reuse the
|
|
5411
6142
|
moment a new message lands mid-animation. */
|
|
5412
|
-
/* @__PURE__ */
|
|
6143
|
+
/* @__PURE__ */ jsx17("div", { className: "hw-preview-body", children: truncatePreviewBody(m.text) }, m.text)
|
|
5413
6144
|
)),
|
|
5414
|
-
qr && /* @__PURE__ */
|
|
5415
|
-
qr.prompt && /* @__PURE__ */
|
|
5416
|
-
/* @__PURE__ */
|
|
6145
|
+
qr && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
6146
|
+
qr.prompt && /* @__PURE__ */ jsx17("div", { className: "hw-preview-body", children: qr.prompt }),
|
|
6147
|
+
/* @__PURE__ */ jsx17("div", { className: "hw-preview-quick-replies hw-quick-replies", children: qr.options.map((opt) => /* @__PURE__ */ jsx17(
|
|
5417
6148
|
"button",
|
|
5418
6149
|
{
|
|
5419
6150
|
type: "button",
|
|
@@ -5427,14 +6158,92 @@ function MessagePreview({
|
|
|
5427
6158
|
opt.id
|
|
5428
6159
|
)) })
|
|
5429
6160
|
] }),
|
|
5430
|
-
footer != null && footer !== false && /* @__PURE__ */
|
|
6161
|
+
footer != null && footer !== false && /* @__PURE__ */ jsx17("div", { className: "hw-preview-footer", children: footer })
|
|
5431
6162
|
]
|
|
5432
6163
|
}
|
|
5433
6164
|
);
|
|
5434
6165
|
}
|
|
5435
6166
|
|
|
6167
|
+
// src/themed/resolved-banner.tsx
|
|
6168
|
+
import { useId, useState as useState16 } from "react";
|
|
6169
|
+
|
|
6170
|
+
// src/themed/resolved-rating.ts
|
|
6171
|
+
function asCsatRating(value) {
|
|
6172
|
+
return value === "good" || value === "bad" ? value : null;
|
|
6173
|
+
}
|
|
6174
|
+
async function saveRating(client, store, conversationId, rating) {
|
|
6175
|
+
try {
|
|
6176
|
+
await client.widget.sendCsat.mutate({ conversationId, rating });
|
|
6177
|
+
} catch {
|
|
6178
|
+
return false;
|
|
6179
|
+
}
|
|
6180
|
+
store.setState((s) => ({
|
|
6181
|
+
conversations: s.conversations.map(
|
|
6182
|
+
(c) => c.id === conversationId ? { ...c, csatRating: rating } : c
|
|
6183
|
+
)
|
|
6184
|
+
}));
|
|
6185
|
+
return true;
|
|
6186
|
+
}
|
|
6187
|
+
|
|
6188
|
+
// src/themed/resolved-banner.tsx
|
|
6189
|
+
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6190
|
+
var OPTIONS = [
|
|
6191
|
+
{ value: "good", labelKey: "widget.aria_good", Icon: ThumbsUpIcon },
|
|
6192
|
+
{ value: "bad", labelKey: "widget.aria_bad", Icon: ThumbsDownIcon }
|
|
6193
|
+
];
|
|
6194
|
+
function ResolvedBlock({
|
|
6195
|
+
rating,
|
|
6196
|
+
failed = false,
|
|
6197
|
+
onRate
|
|
6198
|
+
}) {
|
|
6199
|
+
const labelId = useId();
|
|
6200
|
+
return /* @__PURE__ */ jsxs13("div", { className: "hw-resolved", children: [
|
|
6201
|
+
/* @__PURE__ */ jsxs13("div", { className: "hw-resolved-status", role: "status", children: [
|
|
6202
|
+
/* @__PURE__ */ jsx18(CheckCircleIcon, { size: 16 }),
|
|
6203
|
+
/* @__PURE__ */ jsx18("span", { children: t("widget.resolved_text") })
|
|
6204
|
+
] }),
|
|
6205
|
+
/* @__PURE__ */ jsxs13("div", { className: "hw-csat", role: "group", "aria-labelledby": labelId, children: [
|
|
6206
|
+
/* @__PURE__ */ jsx18("span", { className: "hw-csat-label", id: labelId, children: rating ? t("widget.csat_thanks") : t("widget.csat_label") }),
|
|
6207
|
+
/* @__PURE__ */ jsx18("span", { className: "hw-csat-buttons", children: OPTIONS.filter((o) => !rating || o.value === rating).map(({ value, labelKey, Icon }) => /* @__PURE__ */ jsxs13(
|
|
6208
|
+
"button",
|
|
6209
|
+
{
|
|
6210
|
+
type: "button",
|
|
6211
|
+
className: "hw-csat-btn",
|
|
6212
|
+
"aria-pressed": rating === value,
|
|
6213
|
+
"aria-disabled": rating ? true : void 0,
|
|
6214
|
+
onClick: rating ? void 0 : () => onRate(value),
|
|
6215
|
+
children: [
|
|
6216
|
+
/* @__PURE__ */ jsx18(Icon, { size: 14 }),
|
|
6217
|
+
t(labelKey)
|
|
6218
|
+
]
|
|
6219
|
+
},
|
|
6220
|
+
value
|
|
6221
|
+
)) })
|
|
6222
|
+
] }),
|
|
6223
|
+
failed && !rating && /* @__PURE__ */ jsx18("div", { className: "hw-csat-error", role: "alert", children: t("widget.csat_error") })
|
|
6224
|
+
] });
|
|
6225
|
+
}
|
|
6226
|
+
function ResolvedBanner({ conversationId }) {
|
|
6227
|
+
const { client, store } = useWidgetContext();
|
|
6228
|
+
const saved = useWidgetStore(
|
|
6229
|
+
(s) => asCsatRating(s.conversations.find((c) => c.id === conversationId)?.csatRating)
|
|
6230
|
+
);
|
|
6231
|
+
const [pending, setPending] = useState16(null);
|
|
6232
|
+
const [failed, setFailed] = useState16(false);
|
|
6233
|
+
const rate = (rating) => {
|
|
6234
|
+
setPending(rating);
|
|
6235
|
+
setFailed(false);
|
|
6236
|
+
void saveRating(client, store, conversationId, rating).then((ok) => {
|
|
6237
|
+
if (ok) return;
|
|
6238
|
+
setPending(null);
|
|
6239
|
+
setFailed(true);
|
|
6240
|
+
});
|
|
6241
|
+
};
|
|
6242
|
+
return /* @__PURE__ */ jsx18(ResolvedBlock, { rating: saved ?? pending, failed, onRate: rate });
|
|
6243
|
+
}
|
|
6244
|
+
|
|
5436
6245
|
// src/themed/default-widget.tsx
|
|
5437
|
-
import { Fragment as Fragment5, jsx as
|
|
6246
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5438
6247
|
function resolveLabel2(label) {
|
|
5439
6248
|
if (!label.startsWith("widget.")) return label;
|
|
5440
6249
|
const resolved = t(label);
|
|
@@ -5446,7 +6255,7 @@ var EMPTY_CONTENT_TABS = [];
|
|
|
5446
6255
|
var DEFAULT_EN_WELCOME = "Hi there \u{1F44B}\nHow can we help?";
|
|
5447
6256
|
var DEFAULT_EN_SUBTITLE = "Usually replies in minutes";
|
|
5448
6257
|
function HelpwayMark({ className }) {
|
|
5449
|
-
return /* @__PURE__ */
|
|
6258
|
+
return /* @__PURE__ */ jsx19(
|
|
5450
6259
|
"svg",
|
|
5451
6260
|
{
|
|
5452
6261
|
className,
|
|
@@ -5456,7 +6265,7 @@ function HelpwayMark({ className }) {
|
|
|
5456
6265
|
fill: "none",
|
|
5457
6266
|
xmlns: "http://www.w3.org/2000/svg",
|
|
5458
6267
|
"aria-hidden": "true",
|
|
5459
|
-
children: /* @__PURE__ */
|
|
6268
|
+
children: /* @__PURE__ */ jsx19(
|
|
5460
6269
|
"path",
|
|
5461
6270
|
{
|
|
5462
6271
|
d: "M28.7 0H12.8L0 12.8V28.7L12.8 41.5H28.7L41.5 28.7V12.8L28.7 0ZM15 28.9L6.80002 20.7L15 12.5C18.1 9.4 23.2 9.4 26.3 12.5L34.5 20.7L26.3 28.9C23.2 32 18.2 32 15 28.9Z",
|
|
@@ -5483,7 +6292,7 @@ function WidgetLogo({
|
|
|
5483
6292
|
});
|
|
5484
6293
|
const logoClass = forceAgent ? "hw-agent-img--logo" : "";
|
|
5485
6294
|
if (!forceAgent && activeId && assignee?.assigneeImage) {
|
|
5486
|
-
return /* @__PURE__ */
|
|
6295
|
+
return /* @__PURE__ */ jsx19(
|
|
5487
6296
|
"img",
|
|
5488
6297
|
{
|
|
5489
6298
|
src: assignee.assigneeImage,
|
|
@@ -5494,7 +6303,7 @@ function WidgetLogo({
|
|
|
5494
6303
|
);
|
|
5495
6304
|
}
|
|
5496
6305
|
if (customAvatar) {
|
|
5497
|
-
return /* @__PURE__ */
|
|
6306
|
+
return /* @__PURE__ */ jsx19(
|
|
5498
6307
|
"span",
|
|
5499
6308
|
{
|
|
5500
6309
|
className: `hw-agent-icon hw-agent-custom ${className ?? ""}`,
|
|
@@ -5504,7 +6313,7 @@ function WidgetLogo({
|
|
|
5504
6313
|
);
|
|
5505
6314
|
}
|
|
5506
6315
|
if (agentConfig?.avatarUrl) {
|
|
5507
|
-
return /* @__PURE__ */
|
|
6316
|
+
return /* @__PURE__ */ jsx19(
|
|
5508
6317
|
"img",
|
|
5509
6318
|
{
|
|
5510
6319
|
src: agentConfig.avatarUrl,
|
|
@@ -5514,7 +6323,7 @@ function WidgetLogo({
|
|
|
5514
6323
|
);
|
|
5515
6324
|
}
|
|
5516
6325
|
if (agentConfig?.avatarPreset) {
|
|
5517
|
-
return /* @__PURE__ */
|
|
6326
|
+
return /* @__PURE__ */ jsx19(
|
|
5518
6327
|
"div",
|
|
5519
6328
|
{
|
|
5520
6329
|
className: `hw-agent-icon ${className ?? ""}`,
|
|
@@ -5525,20 +6334,20 @@ function WidgetLogo({
|
|
|
5525
6334
|
justifyContent: "center",
|
|
5526
6335
|
borderRadius: 8
|
|
5527
6336
|
},
|
|
5528
|
-
children: /* @__PURE__ */
|
|
6337
|
+
children: /* @__PURE__ */ jsx19(AgentPresetIcon, { presetId: agentConfig.avatarPreset })
|
|
5529
6338
|
}
|
|
5530
6339
|
);
|
|
5531
6340
|
}
|
|
5532
6341
|
if (logoUrl) {
|
|
5533
|
-
return /* @__PURE__ */
|
|
6342
|
+
return /* @__PURE__ */ jsx19("img", { src: logoUrl, alt: "", className: `hw-agent-img hw-agent-img--logo ${className ?? ""}` });
|
|
5534
6343
|
}
|
|
5535
|
-
return /* @__PURE__ */
|
|
6344
|
+
return /* @__PURE__ */ jsx19(HelpwayMark, { className });
|
|
5536
6345
|
}
|
|
5537
6346
|
function LauncherIcon({ className }) {
|
|
5538
6347
|
const agentConfig = useWidgetStore((s) => s.agentConfig);
|
|
5539
|
-
const [imgLoaded, setImgLoaded] =
|
|
6348
|
+
const [imgLoaded, setImgLoaded] = useState17(false);
|
|
5540
6349
|
const imgSrc = agentConfig?.launcherIconUrl ?? null;
|
|
5541
|
-
|
|
6350
|
+
useEffect16(() => {
|
|
5542
6351
|
if (!imgSrc) return;
|
|
5543
6352
|
setImgLoaded(false);
|
|
5544
6353
|
const img = new Image();
|
|
@@ -5551,7 +6360,7 @@ function LauncherIcon({ className }) {
|
|
|
5551
6360
|
img.onerror = () => setImgLoaded(true);
|
|
5552
6361
|
}, [imgSrc]);
|
|
5553
6362
|
if (imgSrc) {
|
|
5554
|
-
return /* @__PURE__ */
|
|
6363
|
+
return /* @__PURE__ */ jsx19(
|
|
5555
6364
|
"img",
|
|
5556
6365
|
{
|
|
5557
6366
|
src: imgSrc,
|
|
@@ -5561,7 +6370,7 @@ function LauncherIcon({ className }) {
|
|
|
5561
6370
|
}
|
|
5562
6371
|
);
|
|
5563
6372
|
}
|
|
5564
|
-
return /* @__PURE__ */
|
|
6373
|
+
return /* @__PURE__ */ jsx19(WidgetLogo, { className, forceAgent: true });
|
|
5565
6374
|
}
|
|
5566
6375
|
var PRESET_SVG = {
|
|
5567
6376
|
// Helpway brand mark — octagonal chamfer with stylized "W" inside.
|
|
@@ -5620,7 +6429,7 @@ function AgentPresetIcon({ presetId }) {
|
|
|
5620
6429
|
const svgContent = PRESET_SVG[presetId] ?? PRESET_SVG.sparkle;
|
|
5621
6430
|
return (
|
|
5622
6431
|
// biome-ignore lint: trusted static SVG content from our icon library
|
|
5623
|
-
/* @__PURE__ */
|
|
6432
|
+
/* @__PURE__ */ jsx19(
|
|
5624
6433
|
"svg",
|
|
5625
6434
|
{
|
|
5626
6435
|
viewBox: "0 0 24 24",
|
|
@@ -5633,8 +6442,8 @@ function AgentPresetIcon({ presetId }) {
|
|
|
5633
6442
|
);
|
|
5634
6443
|
}
|
|
5635
6444
|
function CloseGlyph({ docked }) {
|
|
5636
|
-
if (!docked) return /* @__PURE__ */
|
|
5637
|
-
return /* @__PURE__ */
|
|
6445
|
+
if (!docked) return /* @__PURE__ */ jsx19(XIcon, { size: 20 });
|
|
6446
|
+
return /* @__PURE__ */ jsx19(
|
|
5638
6447
|
"svg",
|
|
5639
6448
|
{
|
|
5640
6449
|
width: "20",
|
|
@@ -5646,7 +6455,7 @@ function CloseGlyph({ docked }) {
|
|
|
5646
6455
|
strokeLinecap: "round",
|
|
5647
6456
|
strokeLinejoin: "round",
|
|
5648
6457
|
"aria-hidden": "true",
|
|
5649
|
-
children: /* @__PURE__ */
|
|
6458
|
+
children: /* @__PURE__ */ jsx19("path", { d: "M6 9.5 12 15.5 18 9.5" })
|
|
5650
6459
|
}
|
|
5651
6460
|
);
|
|
5652
6461
|
}
|
|
@@ -5659,7 +6468,15 @@ function DefaultWidget({
|
|
|
5659
6468
|
const { isReady, website, agentConfig } = useWidget();
|
|
5660
6469
|
const customAvatar = useContext2(AgentAvatarContext);
|
|
5661
6470
|
useI18n();
|
|
5662
|
-
const {
|
|
6471
|
+
const {
|
|
6472
|
+
client,
|
|
6473
|
+
store,
|
|
6474
|
+
hasBootstrapError,
|
|
6475
|
+
wsDisconnected,
|
|
6476
|
+
wsLost,
|
|
6477
|
+
retryConnection,
|
|
6478
|
+
retryBootstrap
|
|
6479
|
+
} = useWidgetContext();
|
|
5663
6480
|
const { conversations, create, isCreating, setActiveConversation } = useConversations();
|
|
5664
6481
|
const activeId = useWidgetStore((s) => s.activeConversationId);
|
|
5665
6482
|
const isDismissed = useWidgetStore((s) => s.isDismissed);
|
|
@@ -5678,22 +6495,22 @@ function DefaultWidget({
|
|
|
5678
6495
|
});
|
|
5679
6496
|
}
|
|
5680
6497
|
const storeIsOpen = useWidgetStore((s) => s.isOpen);
|
|
5681
|
-
const [isClosing, setIsClosing] =
|
|
6498
|
+
const [isClosing, setIsClosing] = useState17(false);
|
|
5682
6499
|
const isOpen = storeIsOpen || isClosing;
|
|
5683
|
-
const [activeTab, setActiveTab] =
|
|
5684
|
-
const [subView, setSubView] =
|
|
5685
|
-
const [newText, setNewText] =
|
|
5686
|
-
const [contentDetailSlug, setContentDetailSlug] =
|
|
5687
|
-
const [contentCategoryName, setContentCategoryName] =
|
|
5688
|
-
const prevActiveIdRef =
|
|
5689
|
-
|
|
6500
|
+
const [activeTab, setActiveTab] = useState17("home");
|
|
6501
|
+
const [subView, setSubView] = useState17(null);
|
|
6502
|
+
const [newText, setNewText] = useState17("");
|
|
6503
|
+
const [contentDetailSlug, setContentDetailSlug] = useState17(null);
|
|
6504
|
+
const [contentCategoryName, setContentCategoryName] = useState17(null);
|
|
6505
|
+
const prevActiveIdRef = useRef17(activeId);
|
|
6506
|
+
useEffect16(() => {
|
|
5690
6507
|
if (activeId && activeId !== prevActiveIdRef.current && subView !== "conversation") {
|
|
5691
6508
|
setSubView("conversation");
|
|
5692
6509
|
}
|
|
5693
6510
|
prevActiveIdRef.current = activeId;
|
|
5694
6511
|
}, [activeId, subView]);
|
|
5695
6512
|
const prefill = useWidgetStore((s) => s.newConversationPrefill);
|
|
5696
|
-
|
|
6513
|
+
useEffect16(() => {
|
|
5697
6514
|
if (prefill !== null) {
|
|
5698
6515
|
if (prefill.length > 0) setNewText(prefill);
|
|
5699
6516
|
setSubView("new");
|
|
@@ -5701,18 +6518,18 @@ function DefaultWidget({
|
|
|
5701
6518
|
store.getState().setNewConversationPrefill(null);
|
|
5702
6519
|
}
|
|
5703
6520
|
}, [prefill, store]);
|
|
5704
|
-
const closeTimerRef =
|
|
6521
|
+
const closeTimerRef = useRef17(void 0);
|
|
5705
6522
|
const welcomeMsgRaw = agentConfig?.welcomeMessage;
|
|
5706
6523
|
const welcomeIsFactoryDefault = !welcomeMsgRaw || welcomeMsgRaw === DEFAULT_EN_WELCOME;
|
|
5707
6524
|
const welcomeMessage = welcomeMsgRaw?.startsWith("widget.") ? t(welcomeMsgRaw) : welcomeIsFactoryDefault ? t("widget.welcome_message") : welcomeMsgRaw;
|
|
5708
|
-
const openConversation =
|
|
6525
|
+
const openConversation = useCallback14(
|
|
5709
6526
|
(id) => {
|
|
5710
6527
|
setActiveConversation(id);
|
|
5711
6528
|
setSubView("conversation");
|
|
5712
6529
|
},
|
|
5713
6530
|
[setActiveConversation]
|
|
5714
6531
|
);
|
|
5715
|
-
const openNewConversation =
|
|
6532
|
+
const openNewConversation = useCallback14(() => {
|
|
5716
6533
|
const agentId = agentConfig?.id;
|
|
5717
6534
|
if (!agentId) {
|
|
5718
6535
|
setSubView("new");
|
|
@@ -5738,8 +6555,8 @@ function DefaultWidget({
|
|
|
5738
6555
|
setActiveConversation(tempId);
|
|
5739
6556
|
setSubView("conversation");
|
|
5740
6557
|
}, [agentConfig?.id, store, setActiveConversation, welcomeMessage]);
|
|
5741
|
-
const didAutoOpenRef =
|
|
5742
|
-
|
|
6558
|
+
const didAutoOpenRef = useRef17(false);
|
|
6559
|
+
useEffect16(() => {
|
|
5743
6560
|
if (!isOpen) {
|
|
5744
6561
|
didAutoOpenRef.current = false;
|
|
5745
6562
|
return;
|
|
@@ -5752,19 +6569,19 @@ function DefaultWidget({
|
|
|
5752
6569
|
else openNewConversation();
|
|
5753
6570
|
}, [isOpen, isReady, subView, conversations, openConversation, openNewConversation]);
|
|
5754
6571
|
const dockComposer = useComposer(activeId);
|
|
5755
|
-
const dockRef =
|
|
5756
|
-
|
|
6572
|
+
const dockRef = useRef17(dockComposer);
|
|
6573
|
+
useEffect16(() => {
|
|
5757
6574
|
dockRef.current = dockComposer;
|
|
5758
6575
|
});
|
|
5759
|
-
const pendingDockText =
|
|
5760
|
-
const reopenFromDock =
|
|
6576
|
+
const pendingDockText = useRef17(null);
|
|
6577
|
+
const reopenFromDock = useCallback14(() => {
|
|
5761
6578
|
const state = store.getState();
|
|
5762
6579
|
if (state.isOpen) return;
|
|
5763
6580
|
const resumable = state.conversations.some((conv) => !conv.id.startsWith("temp-"));
|
|
5764
6581
|
if (!resumable) return;
|
|
5765
6582
|
state.setOpen(true);
|
|
5766
6583
|
}, [store]);
|
|
5767
|
-
const submitFromDock =
|
|
6584
|
+
const submitFromDock = useCallback14(
|
|
5768
6585
|
(override) => {
|
|
5769
6586
|
const text = (override ?? dockRef.current.text).trim();
|
|
5770
6587
|
const stagedAttachment = dockRef.current.attachments.some((a) => a.part !== null);
|
|
@@ -5786,14 +6603,14 @@ function DefaultWidget({
|
|
|
5786
6603
|
},
|
|
5787
6604
|
[activeId, openNewConversation, store]
|
|
5788
6605
|
);
|
|
5789
|
-
|
|
6606
|
+
useEffect16(() => {
|
|
5790
6607
|
if (!activeId || pendingDockText.current == null) return;
|
|
5791
6608
|
const text = pendingDockText.current;
|
|
5792
6609
|
pendingDockText.current = null;
|
|
5793
6610
|
void dockRef.current.submit({ text, conversationId: activeId });
|
|
5794
6611
|
}, [activeId]);
|
|
5795
|
-
const [menuOpen, setMenuOpen] =
|
|
5796
|
-
|
|
6612
|
+
const [menuOpen, setMenuOpen] = useState17(false);
|
|
6613
|
+
useEffect16(() => {
|
|
5797
6614
|
if (!menuOpen) return;
|
|
5798
6615
|
const close = () => setMenuOpen(false);
|
|
5799
6616
|
const onKey = (event) => {
|
|
@@ -5806,7 +6623,7 @@ function DefaultWidget({
|
|
|
5806
6623
|
document.removeEventListener("keydown", onKey);
|
|
5807
6624
|
};
|
|
5808
6625
|
}, [menuOpen]);
|
|
5809
|
-
const goBack =
|
|
6626
|
+
const goBack = useCallback14(() => {
|
|
5810
6627
|
if (subView === "content-detail") {
|
|
5811
6628
|
const tabId = activeTab.startsWith("content:") ? activeTab.slice(8) : null;
|
|
5812
6629
|
const activeContentTab = tabId ? contentTabs.find((t2) => t2.id === tabId) : null;
|
|
@@ -5833,7 +6650,7 @@ function DefaultWidget({
|
|
|
5833
6650
|
setActiveConversation(null);
|
|
5834
6651
|
setSubView(null);
|
|
5835
6652
|
}, [setActiveConversation, subView, activeTab, contentTabs, contentCategoryName, client, store]);
|
|
5836
|
-
const switchTab =
|
|
6653
|
+
const switchTab = useCallback14(
|
|
5837
6654
|
(tab) => {
|
|
5838
6655
|
tabStateRef.current[activeTab] = { subView, activeId };
|
|
5839
6656
|
const saved = tabStateRef.current[tab];
|
|
@@ -5848,7 +6665,7 @@ function DefaultWidget({
|
|
|
5848
6665
|
[activeTab, subView, activeId, setActiveConversation]
|
|
5849
6666
|
);
|
|
5850
6667
|
const pendingContentDetail = useWidgetStore((s) => s.pendingContentDetail);
|
|
5851
|
-
|
|
6668
|
+
useEffect16(() => {
|
|
5852
6669
|
if (!pendingContentDetail) return;
|
|
5853
6670
|
const { slug, tabId } = pendingContentDetail;
|
|
5854
6671
|
markEntrySeen(slug);
|
|
@@ -5858,7 +6675,7 @@ function DefaultWidget({
|
|
|
5858
6675
|
store.getState().setPendingContentDetail(null);
|
|
5859
6676
|
}, [pendingContentDetail, markEntrySeen, switchTab, store]);
|
|
5860
6677
|
const setStoreOpen = useWidgetStore((s) => s.setOpen);
|
|
5861
|
-
const handleBubbleClick =
|
|
6678
|
+
const handleBubbleClick = useCallback14(() => {
|
|
5862
6679
|
if (storeIsOpen) {
|
|
5863
6680
|
const leavingId = store.getState().activeConversationId;
|
|
5864
6681
|
if (leavingId && !leavingId.startsWith("temp-")) {
|
|
@@ -5878,7 +6695,7 @@ function DefaultWidget({
|
|
|
5878
6695
|
setStoreOpen(true);
|
|
5879
6696
|
}
|
|
5880
6697
|
}, [storeIsOpen, setStoreOpen, client, store]);
|
|
5881
|
-
const handleClose =
|
|
6698
|
+
const handleClose = useCallback14(() => {
|
|
5882
6699
|
const leavingId = store.getState().activeConversationId;
|
|
5883
6700
|
if (leavingId && !leavingId.startsWith("temp-")) {
|
|
5884
6701
|
store.getState().clearUnread(leavingId);
|
|
@@ -5891,7 +6708,7 @@ function DefaultWidget({
|
|
|
5891
6708
|
setStoreOpen(false);
|
|
5892
6709
|
}, 200);
|
|
5893
6710
|
}, [setStoreOpen, client, store]);
|
|
5894
|
-
const handleNewConversation =
|
|
6711
|
+
const handleNewConversation = useCallback14(async () => {
|
|
5895
6712
|
const trimmed = newText.trim();
|
|
5896
6713
|
if (!trimmed || isCreating) return;
|
|
5897
6714
|
const conv = await create(trimmed);
|
|
@@ -5900,16 +6717,16 @@ function DefaultWidget({
|
|
|
5900
6717
|
setSubView("conversation");
|
|
5901
6718
|
}
|
|
5902
6719
|
}, [newText, isCreating, create]);
|
|
5903
|
-
const windowRef =
|
|
5904
|
-
const bubbleRef =
|
|
5905
|
-
const tabStateRef =
|
|
5906
|
-
const touchStartY =
|
|
5907
|
-
const touchDeltaY =
|
|
5908
|
-
const handleTouchStart =
|
|
6720
|
+
const windowRef = useRef17(null);
|
|
6721
|
+
const bubbleRef = useRef17(null);
|
|
6722
|
+
const tabStateRef = useRef17({});
|
|
6723
|
+
const touchStartY = useRef17(0);
|
|
6724
|
+
const touchDeltaY = useRef17(0);
|
|
6725
|
+
const handleTouchStart = useCallback14((e) => {
|
|
5909
6726
|
touchStartY.current = e.touches[0]?.clientY ?? 0;
|
|
5910
6727
|
touchDeltaY.current = 0;
|
|
5911
6728
|
}, []);
|
|
5912
|
-
const handleTouchMove =
|
|
6729
|
+
const handleTouchMove = useCallback14((e) => {
|
|
5913
6730
|
const delta = (e.touches[0]?.clientY ?? 0) - touchStartY.current;
|
|
5914
6731
|
touchDeltaY.current = delta;
|
|
5915
6732
|
if (delta > 0 && windowRef.current) {
|
|
@@ -5917,7 +6734,7 @@ function DefaultWidget({
|
|
|
5917
6734
|
windowRef.current.style.opacity = `${Math.max(1 - delta / 400, 0.5)}`;
|
|
5918
6735
|
}
|
|
5919
6736
|
}, []);
|
|
5920
|
-
const handleTouchEnd =
|
|
6737
|
+
const handleTouchEnd = useCallback14(() => {
|
|
5921
6738
|
if (windowRef.current) {
|
|
5922
6739
|
windowRef.current.style.transform = "";
|
|
5923
6740
|
windowRef.current.style.opacity = "";
|
|
@@ -5926,13 +6743,14 @@ function DefaultWidget({
|
|
|
5926
6743
|
handleClose();
|
|
5927
6744
|
}
|
|
5928
6745
|
}, [handleClose]);
|
|
5929
|
-
|
|
6746
|
+
useEffect16(() => {
|
|
5930
6747
|
if (!isOpen || !windowRef.current) return;
|
|
5931
6748
|
const vv = window.visualViewport;
|
|
5932
6749
|
if (!vv) return;
|
|
5933
6750
|
const win = windowRef.current;
|
|
5934
6751
|
const applyHeight = () => {
|
|
5935
6752
|
win.style.setProperty("--hw-visible-height", `${vv.height}px`);
|
|
6753
|
+
win.toggleAttribute("data-hw-keyboard", window.innerHeight - vv.height > 120);
|
|
5936
6754
|
};
|
|
5937
6755
|
applyHeight();
|
|
5938
6756
|
vv.addEventListener("resize", applyHeight);
|
|
@@ -5941,9 +6759,10 @@ function DefaultWidget({
|
|
|
5941
6759
|
vv.removeEventListener("resize", applyHeight);
|
|
5942
6760
|
vv.removeEventListener("scroll", applyHeight);
|
|
5943
6761
|
win.style.removeProperty("--hw-visible-height");
|
|
6762
|
+
win.removeAttribute("data-hw-keyboard");
|
|
5944
6763
|
};
|
|
5945
6764
|
}, [isOpen]);
|
|
5946
|
-
|
|
6765
|
+
useEffect16(() => {
|
|
5947
6766
|
if (!isOpen || !windowRef.current) return;
|
|
5948
6767
|
const win = windowRef.current;
|
|
5949
6768
|
const handleKeyDown = (e) => {
|
|
@@ -5959,7 +6778,7 @@ function DefaultWidget({
|
|
|
5959
6778
|
win.addEventListener("keydown", handleKeyDown);
|
|
5960
6779
|
return () => win.removeEventListener("keydown", handleKeyDown);
|
|
5961
6780
|
}, [isOpen, subView, handleClose, goBack]);
|
|
5962
|
-
|
|
6781
|
+
useEffect16(() => {
|
|
5963
6782
|
if (!isOpen || !windowRef.current || hideLauncher) return;
|
|
5964
6783
|
const win = windowRef.current;
|
|
5965
6784
|
const getFocusable = () => win.querySelectorAll(
|
|
@@ -6002,7 +6821,7 @@ function DefaultWidget({
|
|
|
6002
6821
|
const launcherStyle = agentConfig?.launcherStyle ?? "icon";
|
|
6003
6822
|
const bubbleStyle = agentConfig?.bubbleStyle ?? "rounded";
|
|
6004
6823
|
const hasUploadedAvatar = !!agentConfig?.avatarUrl;
|
|
6005
|
-
return /* @__PURE__ */
|
|
6824
|
+
return /* @__PURE__ */ jsxs14(
|
|
6006
6825
|
"div",
|
|
6007
6826
|
{
|
|
6008
6827
|
className: "hw-widget",
|
|
@@ -6018,7 +6837,7 @@ function DefaultWidget({
|
|
|
6018
6837
|
"--hw-window-left": widgetPosition === "bottom-left" ? "0" : "auto"
|
|
6019
6838
|
},
|
|
6020
6839
|
children: [
|
|
6021
|
-
placement === "docked" && isReady && /* @__PURE__ */
|
|
6840
|
+
placement === "docked" && isReady && /* @__PURE__ */ jsx19(
|
|
6022
6841
|
DockedBar,
|
|
6023
6842
|
{
|
|
6024
6843
|
value: dockComposer.text,
|
|
@@ -6033,19 +6852,20 @@ function DefaultWidget({
|
|
|
6033
6852
|
onReopen: reopenFromDock,
|
|
6034
6853
|
sendError: dockComposer.sendError,
|
|
6035
6854
|
onClearSendError: dockComposer.clearSendError,
|
|
6036
|
-
leading: customAvatar
|
|
6855
|
+
leading: customAvatar,
|
|
6856
|
+
placeholder: conversations.find((c) => c.id === activeId)?.status === "resolved" ? t("widget.placeholder_resolved") : void 0
|
|
6037
6857
|
}
|
|
6038
6858
|
),
|
|
6039
|
-
isOpen && !isReady && !hasBootstrapError && /* @__PURE__ */
|
|
6040
|
-
/* @__PURE__ */
|
|
6041
|
-
/* @__PURE__ */
|
|
6042
|
-
/* @__PURE__ */
|
|
6859
|
+
isOpen && !isReady && !hasBootstrapError && /* @__PURE__ */ jsx19("div", { className: `hw-window ${isClosing ? "hw-window--closing" : ""}`, children: /* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-loading", children: [
|
|
6860
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 120 } }),
|
|
6861
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 200 } }),
|
|
6862
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 160 } })
|
|
6043
6863
|
] }) }),
|
|
6044
|
-
isOpen && hasBootstrapError && /* @__PURE__ */
|
|
6045
|
-
/* @__PURE__ */
|
|
6046
|
-
/* @__PURE__ */
|
|
6864
|
+
isOpen && hasBootstrapError && /* @__PURE__ */ jsx19("div", { className: `hw-window ${isClosing ? "hw-window--closing" : ""}`, children: /* @__PURE__ */ jsxs14("div", { className: "hw-bootstrap-error", children: [
|
|
6865
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-bootstrap-error-text", children: t("widget.error_desc") }),
|
|
6866
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "hw-bootstrap-error-retry", onClick: retryBootstrap, children: t("widget.retry") })
|
|
6047
6867
|
] }) }),
|
|
6048
|
-
isOpen && isReady && /* @__PURE__ */
|
|
6868
|
+
isOpen && isReady && /* @__PURE__ */ jsxs14(
|
|
6049
6869
|
"div",
|
|
6050
6870
|
{
|
|
6051
6871
|
ref: windowRef,
|
|
@@ -6057,24 +6877,28 @@ function DefaultWidget({
|
|
|
6057
6877
|
onTouchMove: handleTouchMove,
|
|
6058
6878
|
onTouchEnd: handleTouchEnd,
|
|
6059
6879
|
children: [
|
|
6060
|
-
/* @__PURE__ */
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6880
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-drag-handle", children: /* @__PURE__ */ jsx19("div", { className: "hw-drag-handle-pill" }) }),
|
|
6881
|
+
/* @__PURE__ */ jsx19(
|
|
6882
|
+
ConnectionStrip,
|
|
6883
|
+
{
|
|
6884
|
+
reconnecting: wsDisconnected,
|
|
6885
|
+
lost: wsLost,
|
|
6886
|
+
onRetry: retryConnection
|
|
6887
|
+
}
|
|
6888
|
+
),
|
|
6065
6889
|
(subView === "content-detail" || subView === "content-category") && (() => {
|
|
6066
6890
|
const tabId = activeTab.replace("content:", "");
|
|
6067
6891
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
6068
6892
|
const headerTitle = subView === "content-category" && contentCategoryName ? contentCategoryName : contentTab?.label ? resolveLabel2(contentTab.label) : t("widget.content");
|
|
6069
|
-
return /* @__PURE__ */
|
|
6070
|
-
/* @__PURE__ */
|
|
6893
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-header hw-header--centered", children: [
|
|
6894
|
+
/* @__PURE__ */ jsx19(
|
|
6071
6895
|
"button",
|
|
6072
6896
|
{
|
|
6073
6897
|
type: "button",
|
|
6074
6898
|
className: "hw-header-back",
|
|
6075
6899
|
onClick: goBack,
|
|
6076
6900
|
"aria-label": t("widget.aria_back"),
|
|
6077
|
-
children: /* @__PURE__ */
|
|
6901
|
+
children: /* @__PURE__ */ jsx19(
|
|
6078
6902
|
"svg",
|
|
6079
6903
|
{
|
|
6080
6904
|
viewBox: "0 0 24 24",
|
|
@@ -6083,33 +6907,33 @@ function DefaultWidget({
|
|
|
6083
6907
|
strokeWidth: 2,
|
|
6084
6908
|
strokeLinecap: "round",
|
|
6085
6909
|
strokeLinejoin: "round",
|
|
6086
|
-
children: /* @__PURE__ */
|
|
6910
|
+
children: /* @__PURE__ */ jsx19("path", { d: "M15 18l-6-6 6-6" })
|
|
6087
6911
|
}
|
|
6088
6912
|
)
|
|
6089
6913
|
}
|
|
6090
6914
|
),
|
|
6091
|
-
/* @__PURE__ */
|
|
6092
|
-
/* @__PURE__ */
|
|
6915
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-title", children: headerTitle }),
|
|
6916
|
+
/* @__PURE__ */ jsx19(
|
|
6093
6917
|
"button",
|
|
6094
6918
|
{
|
|
6095
6919
|
type: "button",
|
|
6096
6920
|
className: "hw-header-close",
|
|
6097
6921
|
onClick: handleClose,
|
|
6098
6922
|
"aria-label": t("widget.aria_close"),
|
|
6099
|
-
children: /* @__PURE__ */
|
|
6923
|
+
children: /* @__PURE__ */ jsx19(CloseGlyph, { docked: placement === "docked" })
|
|
6100
6924
|
}
|
|
6101
6925
|
)
|
|
6102
6926
|
] });
|
|
6103
6927
|
})(),
|
|
6104
|
-
subView !== null && subView !== "content-detail" && subView !== "content-category" && /* @__PURE__ */
|
|
6105
|
-
/* @__PURE__ */
|
|
6928
|
+
subView !== null && subView !== "content-detail" && subView !== "content-category" && /* @__PURE__ */ jsxs14("div", { className: "hw-header hw-header--sub", children: [
|
|
6929
|
+
/* @__PURE__ */ jsx19(
|
|
6106
6930
|
"button",
|
|
6107
6931
|
{
|
|
6108
6932
|
type: "button",
|
|
6109
6933
|
className: "hw-header-back",
|
|
6110
6934
|
onClick: goBack,
|
|
6111
6935
|
"aria-label": t("widget.aria_back"),
|
|
6112
|
-
children: /* @__PURE__ */
|
|
6936
|
+
children: /* @__PURE__ */ jsx19(
|
|
6113
6937
|
"svg",
|
|
6114
6938
|
{
|
|
6115
6939
|
viewBox: "0 0 24 24",
|
|
@@ -6118,26 +6942,34 @@ function DefaultWidget({
|
|
|
6118
6942
|
strokeWidth: 2,
|
|
6119
6943
|
strokeLinecap: "round",
|
|
6120
6944
|
strokeLinejoin: "round",
|
|
6121
|
-
children: /* @__PURE__ */
|
|
6945
|
+
children: /* @__PURE__ */ jsx19("path", { d: "M15 18l-6-6 6-6" })
|
|
6122
6946
|
}
|
|
6123
6947
|
)
|
|
6124
6948
|
}
|
|
6125
6949
|
),
|
|
6126
|
-
/* @__PURE__ */
|
|
6127
|
-
/* @__PURE__ */
|
|
6950
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-header-identity", children: [
|
|
6951
|
+
/* @__PURE__ */ jsx19(
|
|
6128
6952
|
"div",
|
|
6129
6953
|
{
|
|
6130
6954
|
className: `hw-header-bot-icon${hasTeamAgent ? " hw-header-bot-icon--team" : ""}`,
|
|
6131
|
-
children: hasTeamAgent && humanImage ? /* @__PURE__ */
|
|
6955
|
+
children: hasTeamAgent && humanImage ? /* @__PURE__ */ jsx19(
|
|
6956
|
+
"img",
|
|
6957
|
+
{
|
|
6958
|
+
src: humanImage,
|
|
6959
|
+
alt: headerName,
|
|
6960
|
+
className: "hw-header-agent-img",
|
|
6961
|
+
referrerPolicy: "no-referrer"
|
|
6962
|
+
}
|
|
6963
|
+
) : hasTeamAgent ? /* @__PURE__ */ jsx19("span", { className: "hw-header-agent-initials", children: headerName.split(" ").map((w) => w[0]).join("").slice(0, 2).toUpperCase() }) : /* @__PURE__ */ jsx19(WidgetLogo, {})
|
|
6132
6964
|
}
|
|
6133
6965
|
),
|
|
6134
|
-
/* @__PURE__ */
|
|
6135
|
-
/* @__PURE__ */
|
|
6136
|
-
/* @__PURE__ */
|
|
6966
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-header-info", children: [
|
|
6967
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-name", children: headerName }),
|
|
6968
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-status", children: subtitleText })
|
|
6137
6969
|
] })
|
|
6138
6970
|
] }),
|
|
6139
|
-
/* @__PURE__ */
|
|
6140
|
-
/* @__PURE__ */
|
|
6971
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-header-actions", children: [
|
|
6972
|
+
/* @__PURE__ */ jsx19(
|
|
6141
6973
|
"button",
|
|
6142
6974
|
{
|
|
6143
6975
|
type: "button",
|
|
@@ -6149,21 +6981,21 @@ function DefaultWidget({
|
|
|
6149
6981
|
event.stopPropagation();
|
|
6150
6982
|
setMenuOpen((open) => !open);
|
|
6151
6983
|
},
|
|
6152
|
-
children: /* @__PURE__ */
|
|
6984
|
+
children: /* @__PURE__ */ jsx19(DotsIcon, { size: 18 })
|
|
6153
6985
|
}
|
|
6154
6986
|
),
|
|
6155
|
-
/* @__PURE__ */
|
|
6987
|
+
/* @__PURE__ */ jsx19(
|
|
6156
6988
|
"button",
|
|
6157
6989
|
{
|
|
6158
6990
|
type: "button",
|
|
6159
6991
|
className: "hw-header-close",
|
|
6160
6992
|
onClick: handleClose,
|
|
6161
6993
|
"aria-label": t("widget.aria_close"),
|
|
6162
|
-
children: /* @__PURE__ */
|
|
6994
|
+
children: /* @__PURE__ */ jsx19(CloseGlyph, { docked: placement === "docked" })
|
|
6163
6995
|
}
|
|
6164
6996
|
),
|
|
6165
|
-
menuOpen && /* @__PURE__ */
|
|
6166
|
-
conversations.length > 0 && /* @__PURE__ */
|
|
6997
|
+
menuOpen && /* @__PURE__ */ jsxs14("div", { className: "hw-header-menu", role: "menu", children: [
|
|
6998
|
+
conversations.length > 0 && /* @__PURE__ */ jsx19("div", { className: "hw-header-menu-convs", children: conversations.slice(0, 3).map((conv) => /* @__PURE__ */ jsxs14(
|
|
6167
6999
|
"button",
|
|
6168
7000
|
{
|
|
6169
7001
|
type: "button",
|
|
@@ -6175,16 +7007,16 @@ function DefaultWidget({
|
|
|
6175
7007
|
openConversation(conv.id);
|
|
6176
7008
|
},
|
|
6177
7009
|
children: [
|
|
6178
|
-
/* @__PURE__ */
|
|
6179
|
-
/* @__PURE__ */
|
|
6180
|
-
conv.lastMessageAt && /* @__PURE__ */
|
|
7010
|
+
/* @__PURE__ */ jsxs14("span", { className: "hw-header-menu-conv-top", children: [
|
|
7011
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-header-menu-conv-name", children: conversationIdentity(conv).humanName ?? companyName }),
|
|
7012
|
+
conv.lastMessageAt && /* @__PURE__ */ jsx19("span", { className: "hw-header-menu-conv-time", children: formatRelativeTime(conv.lastMessageAt) })
|
|
6181
7013
|
] }),
|
|
6182
|
-
/* @__PURE__ */
|
|
7014
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-header-menu-conv-preview", children: conv.lastMessageText ?? t("widget.no_preview") })
|
|
6183
7015
|
]
|
|
6184
7016
|
},
|
|
6185
7017
|
conv.id
|
|
6186
7018
|
)) }),
|
|
6187
|
-
/* @__PURE__ */
|
|
7019
|
+
/* @__PURE__ */ jsxs14(
|
|
6188
7020
|
"button",
|
|
6189
7021
|
{
|
|
6190
7022
|
type: "button",
|
|
@@ -6194,7 +7026,7 @@ function DefaultWidget({
|
|
|
6194
7026
|
openNewConversation();
|
|
6195
7027
|
},
|
|
6196
7028
|
children: [
|
|
6197
|
-
/* @__PURE__ */
|
|
7029
|
+
/* @__PURE__ */ jsx19(NewChatIcon, { size: 16 }),
|
|
6198
7030
|
t("widget.new_conversation")
|
|
6199
7031
|
]
|
|
6200
7032
|
}
|
|
@@ -6202,43 +7034,43 @@ function DefaultWidget({
|
|
|
6202
7034
|
] })
|
|
6203
7035
|
] })
|
|
6204
7036
|
] }),
|
|
6205
|
-
subView === null && activeTab === "home" && /* @__PURE__ */
|
|
6206
|
-
/* @__PURE__ */
|
|
6207
|
-
/* @__PURE__ */
|
|
6208
|
-
/* @__PURE__ */
|
|
6209
|
-
/* @__PURE__ */
|
|
7037
|
+
subView === null && activeTab === "home" && /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
7038
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-hero", children: [
|
|
7039
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-hero-top", children: [
|
|
7040
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-hero-bot-icon", children: /* @__PURE__ */ jsx19(WidgetLogo, {}) }),
|
|
7041
|
+
/* @__PURE__ */ jsx19(
|
|
6210
7042
|
"button",
|
|
6211
7043
|
{
|
|
6212
7044
|
type: "button",
|
|
6213
7045
|
className: "hw-hero-close",
|
|
6214
7046
|
onClick: handleClose,
|
|
6215
7047
|
"aria-label": t("widget.aria_close"),
|
|
6216
|
-
children: /* @__PURE__ */
|
|
7048
|
+
children: /* @__PURE__ */ jsx19(CloseGlyph, { docked: placement === "docked" })
|
|
6217
7049
|
}
|
|
6218
7050
|
)
|
|
6219
7051
|
] }),
|
|
6220
|
-
/* @__PURE__ */
|
|
7052
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-hero-greeting", children: welcomeMessage.split("\n").map((line, i) => /* @__PURE__ */ jsxs14(
|
|
6221
7053
|
"span",
|
|
6222
7054
|
{
|
|
6223
7055
|
className: i === 0 ? "hw-hero-greeting-name" : "hw-hero-greeting-question",
|
|
6224
7056
|
children: [
|
|
6225
|
-
i > 0 && /* @__PURE__ */
|
|
7057
|
+
i > 0 && /* @__PURE__ */ jsx19("br", {}),
|
|
6226
7058
|
line
|
|
6227
7059
|
]
|
|
6228
7060
|
},
|
|
6229
7061
|
i
|
|
6230
7062
|
)) }),
|
|
6231
|
-
/* @__PURE__ */
|
|
7063
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-hero-subtitle", children: subtitleText })
|
|
6232
7064
|
] }),
|
|
6233
|
-
/* @__PURE__ */
|
|
6234
|
-
/* @__PURE__ */
|
|
6235
|
-
/* @__PURE__ */
|
|
6236
|
-
/* @__PURE__ */
|
|
6237
|
-
/* @__PURE__ */
|
|
7065
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-sheet", children: /* @__PURE__ */ jsxs14("div", { className: "hw-sheet-inner", children: [
|
|
7066
|
+
/* @__PURE__ */ jsxs14("button", { type: "button", className: "hw-card", onClick: openNewConversation, children: [
|
|
7067
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-card-body", children: [
|
|
7068
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-card-title", children: t("widget.send_us_message") }),
|
|
7069
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-card-meta", children: t("widget.reply_time") })
|
|
6238
7070
|
] }),
|
|
6239
|
-
/* @__PURE__ */
|
|
7071
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-card-arrow", children: /* @__PURE__ */ jsx19(SendIcon, {}) })
|
|
6240
7072
|
] }),
|
|
6241
|
-
announcementTabs.length > 0 && /* @__PURE__ */
|
|
7073
|
+
announcementTabs.length > 0 && /* @__PURE__ */ jsx19(
|
|
6242
7074
|
WhatsNewCard,
|
|
6243
7075
|
{
|
|
6244
7076
|
getUnseenEntries,
|
|
@@ -6254,7 +7086,7 @@ function DefaultWidget({
|
|
|
6254
7086
|
}
|
|
6255
7087
|
}
|
|
6256
7088
|
),
|
|
6257
|
-
/* @__PURE__ */
|
|
7089
|
+
/* @__PURE__ */ jsx19(
|
|
6258
7090
|
HomeView,
|
|
6259
7091
|
{
|
|
6260
7092
|
conversations,
|
|
@@ -6264,17 +7096,17 @@ function DefaultWidget({
|
|
|
6264
7096
|
)
|
|
6265
7097
|
] }) })
|
|
6266
7098
|
] }),
|
|
6267
|
-
subView === null && activeTab === "messages" && /* @__PURE__ */
|
|
6268
|
-
/* @__PURE__ */
|
|
6269
|
-
/* @__PURE__ */
|
|
6270
|
-
/* @__PURE__ */
|
|
7099
|
+
subView === null && activeTab === "messages" && /* @__PURE__ */ jsxs14("div", { className: "hw-header hw-header--centered", children: [
|
|
7100
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-spacer" }),
|
|
7101
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-title", children: t("widget.messages") }),
|
|
7102
|
+
/* @__PURE__ */ jsx19(
|
|
6271
7103
|
"button",
|
|
6272
7104
|
{
|
|
6273
7105
|
type: "button",
|
|
6274
7106
|
className: "hw-header-close",
|
|
6275
7107
|
onClick: handleClose,
|
|
6276
7108
|
"aria-label": t("widget.aria_close"),
|
|
6277
|
-
children: /* @__PURE__ */
|
|
7109
|
+
children: /* @__PURE__ */ jsx19(CloseGlyph, { docked: placement === "docked" })
|
|
6278
7110
|
}
|
|
6279
7111
|
)
|
|
6280
7112
|
] }),
|
|
@@ -6282,23 +7114,23 @@ function DefaultWidget({
|
|
|
6282
7114
|
const tabId = activeTab.replace("content:", "");
|
|
6283
7115
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
6284
7116
|
if (!contentTab) return null;
|
|
6285
|
-
return /* @__PURE__ */
|
|
6286
|
-
/* @__PURE__ */
|
|
6287
|
-
/* @__PURE__ */
|
|
6288
|
-
/* @__PURE__ */
|
|
7117
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-header hw-header--centered", children: [
|
|
7118
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-spacer" }),
|
|
7119
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-header-title", children: resolveLabel2(contentTab.label) }),
|
|
7120
|
+
/* @__PURE__ */ jsx19(
|
|
6289
7121
|
"button",
|
|
6290
7122
|
{
|
|
6291
7123
|
type: "button",
|
|
6292
7124
|
className: "hw-header-close",
|
|
6293
7125
|
onClick: handleClose,
|
|
6294
7126
|
"aria-label": t("widget.aria_close"),
|
|
6295
|
-
children: /* @__PURE__ */
|
|
7127
|
+
children: /* @__PURE__ */ jsx19(CloseGlyph, { docked: placement === "docked" })
|
|
6296
7128
|
}
|
|
6297
7129
|
)
|
|
6298
7130
|
] });
|
|
6299
7131
|
})(),
|
|
6300
|
-
(subView !== null || activeTab !== "home") && /* @__PURE__ */
|
|
6301
|
-
subView === null && activeTab === "messages" && /* @__PURE__ */
|
|
7132
|
+
(subView !== null || activeTab !== "home") && /* @__PURE__ */ jsxs14("div", { className: "hw-content", children: [
|
|
7133
|
+
subView === null && activeTab === "messages" && /* @__PURE__ */ jsx19(
|
|
6302
7134
|
MessagesView,
|
|
6303
7135
|
{
|
|
6304
7136
|
conversations,
|
|
@@ -6306,7 +7138,7 @@ function DefaultWidget({
|
|
|
6306
7138
|
onNewClick: openNewConversation
|
|
6307
7139
|
}
|
|
6308
7140
|
),
|
|
6309
|
-
subView === "new" && /* @__PURE__ */
|
|
7141
|
+
subView === "new" && /* @__PURE__ */ jsx19(
|
|
6310
7142
|
NewConversationView,
|
|
6311
7143
|
{
|
|
6312
7144
|
text: newText,
|
|
@@ -6316,12 +7148,12 @@ function DefaultWidget({
|
|
|
6316
7148
|
welcomeMessage
|
|
6317
7149
|
}
|
|
6318
7150
|
),
|
|
6319
|
-
subView === "conversation" && activeId && /* @__PURE__ */
|
|
7151
|
+
subView === "conversation" && activeId && /* @__PURE__ */ jsx19(ConversationView, { conversationId: activeId, starters: dockSuggestions }),
|
|
6320
7152
|
activeTab.startsWith("content:") && (() => {
|
|
6321
7153
|
const tabId = activeTab.replace("content:", "");
|
|
6322
7154
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
6323
7155
|
if (!contentTab) return null;
|
|
6324
|
-
return /* @__PURE__ */
|
|
7156
|
+
return /* @__PURE__ */ jsx19(
|
|
6325
7157
|
ContentTabView,
|
|
6326
7158
|
{
|
|
6327
7159
|
tab: contentTab,
|
|
@@ -6341,7 +7173,7 @@ function DefaultWidget({
|
|
|
6341
7173
|
);
|
|
6342
7174
|
})()
|
|
6343
7175
|
] }),
|
|
6344
|
-
showTabBar && /* @__PURE__ */
|
|
7176
|
+
showTabBar && /* @__PURE__ */ jsx19(
|
|
6345
7177
|
TabBar,
|
|
6346
7178
|
{
|
|
6347
7179
|
activeTab,
|
|
@@ -6352,20 +7184,20 @@ function DefaultWidget({
|
|
|
6352
7184
|
unseenAnnouncementCount
|
|
6353
7185
|
}
|
|
6354
7186
|
),
|
|
6355
|
-
/* @__PURE__ */
|
|
7187
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-powered", children: [
|
|
6356
7188
|
t("widget.powered_by"),
|
|
6357
7189
|
" ",
|
|
6358
|
-
/* @__PURE__ */
|
|
7190
|
+
/* @__PURE__ */ jsx19("a", { href: "https://helpway.ai", target: "_blank", rel: "noopener noreferrer", children: "Helpway" })
|
|
6359
7191
|
] })
|
|
6360
7192
|
]
|
|
6361
7193
|
}
|
|
6362
7194
|
),
|
|
6363
|
-
isReady && !isOpen && !isDismissed && !hideLauncher && /* @__PURE__ */
|
|
6364
|
-
/* @__PURE__ */
|
|
7195
|
+
isReady && !isOpen && !isDismissed && !hideLauncher && /* @__PURE__ */ jsxs14("div", { className: "hw-preview-dock", children: [
|
|
7196
|
+
/* @__PURE__ */ jsx19(
|
|
6365
7197
|
AnnouncementPreviews,
|
|
6366
7198
|
{
|
|
6367
7199
|
maxVisible: incomingPreview ? 1 : 2,
|
|
6368
|
-
avatar: /* @__PURE__ */
|
|
7200
|
+
avatar: /* @__PURE__ */ jsx19(WidgetLogo, {}),
|
|
6369
7201
|
onOpen: (slug, tabId) => {
|
|
6370
7202
|
markEntrySeen(slug);
|
|
6371
7203
|
handleBubbleClick();
|
|
@@ -6377,10 +7209,10 @@ function DefaultWidget({
|
|
|
6377
7209
|
}
|
|
6378
7210
|
}
|
|
6379
7211
|
),
|
|
6380
|
-
/* @__PURE__ */
|
|
7212
|
+
/* @__PURE__ */ jsx19(MessagePreview, { onOpen: handleBubbleClick, avatar: /* @__PURE__ */ jsx19(WidgetLogo, {}), autoDismissMs: null })
|
|
6381
7213
|
] }),
|
|
6382
|
-
/* @__PURE__ */
|
|
6383
|
-
isReady && !isDismissed && (!hideLauncher || isOpen) && /* @__PURE__ */
|
|
7214
|
+
/* @__PURE__ */ jsx19(WidgetDebugOverlay, {}),
|
|
7215
|
+
isReady && !isDismissed && (!hideLauncher || isOpen) && /* @__PURE__ */ jsxs14(
|
|
6384
7216
|
"button",
|
|
6385
7217
|
{
|
|
6386
7218
|
ref: bubbleRef,
|
|
@@ -6397,24 +7229,24 @@ function DefaultWidget({
|
|
|
6397
7229
|
"aria-expanded": isOpen,
|
|
6398
7230
|
"aria-haspopup": "dialog",
|
|
6399
7231
|
children: [
|
|
6400
|
-
/* @__PURE__ */
|
|
7232
|
+
/* @__PURE__ */ jsx19(
|
|
6401
7233
|
"span",
|
|
6402
7234
|
{
|
|
6403
7235
|
className: `hw-bubble-icon hw-bubble-icon--bot ${isOpen ? "hw-bubble-icon--hidden" : ""}`,
|
|
6404
|
-
children: /* @__PURE__ */
|
|
7236
|
+
children: /* @__PURE__ */ jsx19(LauncherIcon, {})
|
|
6405
7237
|
}
|
|
6406
7238
|
),
|
|
6407
|
-
/* @__PURE__ */
|
|
7239
|
+
/* @__PURE__ */ jsx19(
|
|
6408
7240
|
"span",
|
|
6409
7241
|
{
|
|
6410
7242
|
className: `hw-bubble-icon hw-bubble-icon--close ${!isOpen ? "hw-bubble-icon--hidden" : ""}`,
|
|
6411
|
-
children: /* @__PURE__ */
|
|
7243
|
+
children: /* @__PURE__ */ jsx19(XIcon, { size: 24 })
|
|
6412
7244
|
}
|
|
6413
7245
|
),
|
|
6414
|
-
launcherStyle !== "icon" && !isOpen && /* @__PURE__ */
|
|
6415
|
-
!isOpen && (totalUnread > 0 || awaitingReply > 0 || unseenAnnouncementCount > 0) && /* @__PURE__ */
|
|
7246
|
+
launcherStyle !== "icon" && !isOpen && /* @__PURE__ */ jsx19("span", { className: "hw-bubble-label", children: launcherStyle === "help" ? t("widget.help") : companyName }),
|
|
7247
|
+
!isOpen && (totalUnread > 0 || awaitingReply > 0 || unseenAnnouncementCount > 0) && /* @__PURE__ */ jsxs14("div", { className: "hw-bubble-badge", children: [
|
|
6416
7248
|
totalUnread > 0 ? totalUnread : "",
|
|
6417
|
-
totalUnread === 0 && (awaitingReply > 0 || unseenAnnouncementCount > 0) && /* @__PURE__ */
|
|
7249
|
+
totalUnread === 0 && (awaitingReply > 0 || unseenAnnouncementCount > 0) && /* @__PURE__ */ jsx19("span", { className: "hw-bubble-badge-dot" })
|
|
6418
7250
|
] })
|
|
6419
7251
|
]
|
|
6420
7252
|
}
|
|
@@ -6431,8 +7263,8 @@ function TabBar({
|
|
|
6431
7263
|
showMessagesTab = true,
|
|
6432
7264
|
unseenAnnouncementCount = 0
|
|
6433
7265
|
}) {
|
|
6434
|
-
return /* @__PURE__ */
|
|
6435
|
-
/* @__PURE__ */
|
|
7266
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-tabs", role: "tablist", children: [
|
|
7267
|
+
/* @__PURE__ */ jsxs14(
|
|
6436
7268
|
"button",
|
|
6437
7269
|
{
|
|
6438
7270
|
type: "button",
|
|
@@ -6441,12 +7273,12 @@ function TabBar({
|
|
|
6441
7273
|
role: "tab",
|
|
6442
7274
|
"aria-selected": activeTab === "home",
|
|
6443
7275
|
children: [
|
|
6444
|
-
/* @__PURE__ */
|
|
6445
|
-
/* @__PURE__ */
|
|
7276
|
+
/* @__PURE__ */ jsx19(HomeIcon, {}),
|
|
7277
|
+
/* @__PURE__ */ jsx19("span", { children: t("widget.home") })
|
|
6446
7278
|
]
|
|
6447
7279
|
}
|
|
6448
7280
|
),
|
|
6449
|
-
showMessagesTab && /* @__PURE__ */
|
|
7281
|
+
showMessagesTab && /* @__PURE__ */ jsxs14(
|
|
6450
7282
|
"button",
|
|
6451
7283
|
{
|
|
6452
7284
|
type: "button",
|
|
@@ -6455,15 +7287,15 @@ function TabBar({
|
|
|
6455
7287
|
role: "tab",
|
|
6456
7288
|
"aria-selected": activeTab === "messages",
|
|
6457
7289
|
children: [
|
|
6458
|
-
/* @__PURE__ */
|
|
6459
|
-
/* @__PURE__ */
|
|
6460
|
-
unreadCount > 0 && /* @__PURE__ */
|
|
7290
|
+
/* @__PURE__ */ jsxs14("span", { className: "hw-tabs-icon-wrap", children: [
|
|
7291
|
+
/* @__PURE__ */ jsx19(MessagesIcon, {}),
|
|
7292
|
+
unreadCount > 0 && /* @__PURE__ */ jsx19("span", { className: "hw-tabs-badge", children: unreadCount > 99 ? "99+" : unreadCount })
|
|
6461
7293
|
] }),
|
|
6462
|
-
/* @__PURE__ */
|
|
7294
|
+
/* @__PURE__ */ jsx19("span", { children: t("widget.messages") })
|
|
6463
7295
|
]
|
|
6464
7296
|
}
|
|
6465
7297
|
),
|
|
6466
|
-
contentTabs.map((tab) => /* @__PURE__ */
|
|
7298
|
+
contentTabs.map((tab) => /* @__PURE__ */ jsxs14(
|
|
6467
7299
|
"button",
|
|
6468
7300
|
{
|
|
6469
7301
|
type: "button",
|
|
@@ -6472,11 +7304,11 @@ function TabBar({
|
|
|
6472
7304
|
role: "tab",
|
|
6473
7305
|
"aria-selected": activeTab === `content:${tab.id}`,
|
|
6474
7306
|
children: [
|
|
6475
|
-
/* @__PURE__ */
|
|
6476
|
-
/* @__PURE__ */
|
|
6477
|
-
tab.isAnnouncements && unseenAnnouncementCount > 0 && /* @__PURE__ */
|
|
7307
|
+
/* @__PURE__ */ jsxs14("span", { className: "hw-tabs-icon-wrap", children: [
|
|
7308
|
+
/* @__PURE__ */ jsx19(ContentTabIconComponent, { icon: tab.icon }),
|
|
7309
|
+
tab.isAnnouncements && unseenAnnouncementCount > 0 && /* @__PURE__ */ jsx19("span", { className: "hw-tabs-dot" })
|
|
6478
7310
|
] }),
|
|
6479
|
-
/* @__PURE__ */
|
|
7311
|
+
/* @__PURE__ */ jsx19("span", { children: resolveLabel2(tab.label) })
|
|
6480
7312
|
]
|
|
6481
7313
|
},
|
|
6482
7314
|
tab.id
|
|
@@ -6490,9 +7322,9 @@ function HomeView({
|
|
|
6490
7322
|
}) {
|
|
6491
7323
|
const recent = conversations.slice(0, 3);
|
|
6492
7324
|
if (recent.length === 0) return null;
|
|
6493
|
-
return /* @__PURE__ */
|
|
6494
|
-
/* @__PURE__ */
|
|
6495
|
-
recent.map((conv, i) => /* @__PURE__ */
|
|
7325
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-recent-card", children: [
|
|
7326
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-recent-header", children: t("widget.recent_conversations") }),
|
|
7327
|
+
recent.map((conv, i) => /* @__PURE__ */ jsx19(
|
|
6496
7328
|
ConversationRow,
|
|
6497
7329
|
{
|
|
6498
7330
|
conversation: conv,
|
|
@@ -6501,7 +7333,7 @@ function HomeView({
|
|
|
6501
7333
|
},
|
|
6502
7334
|
conv.id
|
|
6503
7335
|
)),
|
|
6504
|
-
conversations.length > 3 && /* @__PURE__ */
|
|
7336
|
+
conversations.length > 3 && /* @__PURE__ */ jsx19("button", { type: "button", className: "hw-recent-see-all", onClick: onMessagesClick, children: t("widget.see_all") })
|
|
6505
7337
|
] });
|
|
6506
7338
|
}
|
|
6507
7339
|
function MessagesView({
|
|
@@ -6510,14 +7342,14 @@ function MessagesView({
|
|
|
6510
7342
|
onNewClick
|
|
6511
7343
|
}) {
|
|
6512
7344
|
if (conversations.length === 0) {
|
|
6513
|
-
return /* @__PURE__ */
|
|
6514
|
-
/* @__PURE__ */
|
|
6515
|
-
/* @__PURE__ */
|
|
6516
|
-
/* @__PURE__ */
|
|
6517
|
-
/* @__PURE__ */
|
|
7345
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-empty-state", children: [
|
|
7346
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-empty-icon-wrap", children: /* @__PURE__ */ jsx19(MessagesIcon, {}) }),
|
|
7347
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-empty-title", children: t("widget.no_messages") }),
|
|
7348
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-empty-desc", children: t("widget.no_messages_desc") }),
|
|
7349
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "hw-empty-btn", onClick: onNewClick, children: t("widget.start_conversation") })
|
|
6518
7350
|
] });
|
|
6519
7351
|
}
|
|
6520
|
-
return /* @__PURE__ */
|
|
7352
|
+
return /* @__PURE__ */ jsx19("div", { className: "hw-msgs-tab", children: conversations.map((conv) => /* @__PURE__ */ jsx19(ConversationCard, { conversation: conv, onSelect }, conv.id)) });
|
|
6521
7353
|
}
|
|
6522
7354
|
function ConvCardBody({ conv }) {
|
|
6523
7355
|
const agentName = useWidgetStore((s) => s.agentConfig?.name) ?? "Support";
|
|
@@ -6525,14 +7357,22 @@ function ConvCardBody({ conv }) {
|
|
|
6525
7357
|
const isTeam = !!humanName;
|
|
6526
7358
|
const displayName = humanName ?? agentName;
|
|
6527
7359
|
const preview = conv.lastMessageText ?? t("widget.no_preview");
|
|
6528
|
-
return /* @__PURE__ */
|
|
6529
|
-
/* @__PURE__ */
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
7360
|
+
return /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
7361
|
+
/* @__PURE__ */ jsx19("div", { className: `hw-conv-card-avatar${isTeam ? " hw-conv-card-avatar--team" : ""}`, children: isTeam ? humanImage ? /* @__PURE__ */ jsx19(
|
|
7362
|
+
"img",
|
|
7363
|
+
{
|
|
7364
|
+
src: humanImage,
|
|
7365
|
+
alt: displayName,
|
|
7366
|
+
className: "hw-conv-card-avatar-img",
|
|
7367
|
+
referrerPolicy: "no-referrer"
|
|
7368
|
+
}
|
|
7369
|
+
) : /* @__PURE__ */ jsx19("span", { className: "hw-conv-card-avatar-initials", children: displayName.split(" ").map((w) => w[0]).join("").slice(0, 2).toUpperCase() }) : /* @__PURE__ */ jsx19(WidgetLogo, {}) }),
|
|
7370
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-conv-card-content", children: [
|
|
7371
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-conv-card-top", children: [
|
|
7372
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-conv-card-name", children: displayName }),
|
|
7373
|
+
conv.lastMessageAt && /* @__PURE__ */ jsx19("span", { className: "hw-conv-card-time", children: formatRelativeTime(conv.lastMessageAt) })
|
|
6534
7374
|
] }),
|
|
6535
|
-
/* @__PURE__ */
|
|
7375
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-conv-card-preview", children: preview })
|
|
6536
7376
|
] })
|
|
6537
7377
|
] });
|
|
6538
7378
|
}
|
|
@@ -6542,16 +7382,16 @@ function ConversationCard({
|
|
|
6542
7382
|
}) {
|
|
6543
7383
|
const hasUnread = conv.unreadCount > 0;
|
|
6544
7384
|
const awaiting = !hasUnread && isAwaitingVisitorReply(conv);
|
|
6545
|
-
return /* @__PURE__ */
|
|
7385
|
+
return /* @__PURE__ */ jsxs14(
|
|
6546
7386
|
"button",
|
|
6547
7387
|
{
|
|
6548
7388
|
type: "button",
|
|
6549
7389
|
className: `hw-conv-card ${hasUnread ? "hw-conv-card--unread" : ""}`,
|
|
6550
7390
|
onClick: () => onSelect(conv.id),
|
|
6551
7391
|
children: [
|
|
6552
|
-
/* @__PURE__ */
|
|
6553
|
-
hasUnread && /* @__PURE__ */
|
|
6554
|
-
awaiting && /* @__PURE__ */
|
|
7392
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-conv-card-row", children: /* @__PURE__ */ jsx19(ConvCardBody, { conv }) }),
|
|
7393
|
+
hasUnread && /* @__PURE__ */ jsx19("div", { className: "hw-conv-card-badge", children: conv.unreadCount }),
|
|
7394
|
+
awaiting && /* @__PURE__ */ jsx19("div", { className: "hw-awaiting", children: t("widget.awaiting_your_reply") })
|
|
6555
7395
|
]
|
|
6556
7396
|
}
|
|
6557
7397
|
);
|
|
@@ -6563,16 +7403,16 @@ function ConversationRow({
|
|
|
6563
7403
|
}) {
|
|
6564
7404
|
const hasUnread = conv.unreadCount > 0;
|
|
6565
7405
|
const awaiting = !hasUnread && isAwaitingVisitorReply(conv);
|
|
6566
|
-
return /* @__PURE__ */
|
|
7406
|
+
return /* @__PURE__ */ jsxs14(
|
|
6567
7407
|
"button",
|
|
6568
7408
|
{
|
|
6569
7409
|
type: "button",
|
|
6570
7410
|
className: `hw-recent-row ${hasUnread ? "hw-recent-row--unread" : ""} ${isLast ? "hw-recent-row--last" : ""}`,
|
|
6571
7411
|
onClick: () => onSelect(conv.id),
|
|
6572
7412
|
children: [
|
|
6573
|
-
/* @__PURE__ */
|
|
6574
|
-
hasUnread && /* @__PURE__ */
|
|
6575
|
-
awaiting && /* @__PURE__ */
|
|
7413
|
+
/* @__PURE__ */ jsx19(ConvCardBody, { conv }),
|
|
7414
|
+
hasUnread && /* @__PURE__ */ jsx19("div", { className: "hw-recent-row-badge", children: conv.unreadCount }),
|
|
7415
|
+
awaiting && /* @__PURE__ */ jsx19("div", { className: "hw-awaiting", children: t("widget.awaiting_your_reply") })
|
|
6576
7416
|
]
|
|
6577
7417
|
}
|
|
6578
7418
|
);
|
|
@@ -6580,10 +7420,10 @@ function ConversationRow({
|
|
|
6580
7420
|
function InlineEmailPrompt({ conversationId }) {
|
|
6581
7421
|
const { client, store } = useWidgetContext();
|
|
6582
7422
|
const updateContact = useWidgetStore((s) => s.updateVisitorContact);
|
|
6583
|
-
const [email, setEmail] =
|
|
6584
|
-
const [isSubmitting, setIsSubmitting] =
|
|
6585
|
-
const [isSuccess, setIsSuccess] =
|
|
6586
|
-
const [hasError, setHasError] =
|
|
7423
|
+
const [email, setEmail] = useState17("");
|
|
7424
|
+
const [isSubmitting, setIsSubmitting] = useState17(false);
|
|
7425
|
+
const [isSuccess, setIsSuccess] = useState17(false);
|
|
7426
|
+
const [hasError, setHasError] = useState17(false);
|
|
6587
7427
|
const handleSubmit = async () => {
|
|
6588
7428
|
const trimmed = email.trim();
|
|
6589
7429
|
if (!trimmed || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed)) {
|
|
@@ -6624,8 +7464,8 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6624
7464
|
}
|
|
6625
7465
|
};
|
|
6626
7466
|
if (isSuccess) {
|
|
6627
|
-
return /* @__PURE__ */
|
|
6628
|
-
/* @__PURE__ */
|
|
7467
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-email-card hw-email-card--success", children: [
|
|
7468
|
+
/* @__PURE__ */ jsx19(
|
|
6629
7469
|
"svg",
|
|
6630
7470
|
{
|
|
6631
7471
|
width: "15",
|
|
@@ -6636,17 +7476,17 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6636
7476
|
strokeWidth: 2.5,
|
|
6637
7477
|
strokeLinecap: "round",
|
|
6638
7478
|
strokeLinejoin: "round",
|
|
6639
|
-
children: /* @__PURE__ */
|
|
7479
|
+
children: /* @__PURE__ */ jsx19("polyline", { points: "20 6 9 17 4 12" })
|
|
6640
7480
|
}
|
|
6641
7481
|
),
|
|
6642
7482
|
t("widget.email_saved")
|
|
6643
7483
|
] });
|
|
6644
7484
|
}
|
|
6645
|
-
return /* @__PURE__ */
|
|
6646
|
-
/* @__PURE__ */
|
|
6647
|
-
/* @__PURE__ */
|
|
6648
|
-
/* @__PURE__ */
|
|
6649
|
-
/* @__PURE__ */
|
|
7485
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-email-card", children: [
|
|
7486
|
+
/* @__PURE__ */ jsx19("p", { className: "hw-email-card-title", children: t("widget.email_title") }),
|
|
7487
|
+
/* @__PURE__ */ jsx19("p", { className: "hw-email-card-subtitle", children: t("widget.email_subtitle") }),
|
|
7488
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-email-card-row", children: [
|
|
7489
|
+
/* @__PURE__ */ jsx19(
|
|
6650
7490
|
"input",
|
|
6651
7491
|
{
|
|
6652
7492
|
type: "email",
|
|
@@ -6662,7 +7502,7 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6662
7502
|
placeholder: t("widget.email_placeholder")
|
|
6663
7503
|
}
|
|
6664
7504
|
),
|
|
6665
|
-
/* @__PURE__ */
|
|
7505
|
+
/* @__PURE__ */ jsx19(
|
|
6666
7506
|
"button",
|
|
6667
7507
|
{
|
|
6668
7508
|
type: "button",
|
|
@@ -6670,7 +7510,7 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6670
7510
|
onClick: handleSubmit,
|
|
6671
7511
|
disabled: isSubmitting || !email.trim(),
|
|
6672
7512
|
"aria-label": t("widget.email_continue"),
|
|
6673
|
-
children: isSubmitting ? /* @__PURE__ */
|
|
7513
|
+
children: isSubmitting ? /* @__PURE__ */ jsx19(
|
|
6674
7514
|
"svg",
|
|
6675
7515
|
{
|
|
6676
7516
|
width: "14",
|
|
@@ -6680,7 +7520,7 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6680
7520
|
stroke: "currentColor",
|
|
6681
7521
|
strokeWidth: 2,
|
|
6682
7522
|
"aria-hidden": "true",
|
|
6683
|
-
children: /* @__PURE__ */
|
|
7523
|
+
children: /* @__PURE__ */ jsx19("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "32", strokeDashoffset: "32", children: /* @__PURE__ */ jsx19(
|
|
6684
7524
|
"animate",
|
|
6685
7525
|
{
|
|
6686
7526
|
attributeName: "stroke-dashoffset",
|
|
@@ -6690,7 +7530,7 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6690
7530
|
}
|
|
6691
7531
|
) })
|
|
6692
7532
|
}
|
|
6693
|
-
) : /* @__PURE__ */
|
|
7533
|
+
) : /* @__PURE__ */ jsx19(
|
|
6694
7534
|
"svg",
|
|
6695
7535
|
{
|
|
6696
7536
|
width: "15",
|
|
@@ -6702,7 +7542,7 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
6702
7542
|
strokeLinecap: "round",
|
|
6703
7543
|
strokeLinejoin: "round",
|
|
6704
7544
|
"aria-hidden": "true",
|
|
6705
|
-
children: /* @__PURE__ */
|
|
7545
|
+
children: /* @__PURE__ */ jsx19("path", { d: "M5 12h13M12 5l7 7-7 7" })
|
|
6706
7546
|
}
|
|
6707
7547
|
)
|
|
6708
7548
|
}
|
|
@@ -6717,9 +7557,9 @@ function NewConversationView({
|
|
|
6717
7557
|
isSubmitting,
|
|
6718
7558
|
welcomeMessage
|
|
6719
7559
|
}) {
|
|
6720
|
-
return /* @__PURE__ */
|
|
6721
|
-
/* @__PURE__ */
|
|
6722
|
-
/* @__PURE__ */
|
|
7560
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-new", children: [
|
|
7561
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-new-welcome", children: /* @__PURE__ */ jsx19(MessageBubble, { text: welcomeMessage, sender: "ai", parts: null }) }),
|
|
7562
|
+
/* @__PURE__ */ jsx19(
|
|
6723
7563
|
Composer,
|
|
6724
7564
|
{
|
|
6725
7565
|
text,
|
|
@@ -6768,27 +7608,27 @@ function ConversationView({
|
|
|
6768
7608
|
const needsEmailPostReply = !!agentConfig?.requireVisitorEmail && !hasEmail && visitorMessageCount >= 2 && hasAiReply;
|
|
6769
7609
|
const needsEmail = needsEmailPostReply || !!emailGateConvId;
|
|
6770
7610
|
if (isLoading && items.length === 0) {
|
|
6771
|
-
return /* @__PURE__ */
|
|
6772
|
-
/* @__PURE__ */
|
|
6773
|
-
/* @__PURE__ */
|
|
6774
|
-
/* @__PURE__ */
|
|
6775
|
-
/* @__PURE__ */
|
|
6776
|
-
/* @__PURE__ */
|
|
7611
|
+
return /* @__PURE__ */ jsx19("div", { className: "hw-messages", children: /* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-messages", children: [
|
|
7612
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-msg", children: [
|
|
7613
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-avatar" }),
|
|
7614
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-bubble", children: [
|
|
7615
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 140 } }),
|
|
7616
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 200 } })
|
|
6777
7617
|
] })
|
|
6778
7618
|
] }),
|
|
6779
|
-
/* @__PURE__ */
|
|
6780
|
-
/* @__PURE__ */
|
|
6781
|
-
/* @__PURE__ */
|
|
6782
|
-
/* @__PURE__ */
|
|
6783
|
-
/* @__PURE__ */
|
|
6784
|
-
/* @__PURE__ */
|
|
6785
|
-
/* @__PURE__ */
|
|
7619
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton-msg hw-skeleton-msg--right", children: /* @__PURE__ */ jsx19("div", { className: "hw-skeleton-bubble", style: { alignItems: "flex-end" }, children: /* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 160 } }) }) }),
|
|
7620
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-msg", children: [
|
|
7621
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-avatar" }),
|
|
7622
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-skeleton-bubble", children: [
|
|
7623
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 180 } }),
|
|
7624
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 120 } }),
|
|
7625
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 80 } })
|
|
6786
7626
|
] })
|
|
6787
7627
|
] })
|
|
6788
7628
|
] }) });
|
|
6789
7629
|
}
|
|
6790
|
-
return /* @__PURE__ */
|
|
6791
|
-
/* @__PURE__ */
|
|
7630
|
+
return /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
7631
|
+
/* @__PURE__ */ jsx19(
|
|
6792
7632
|
MessageList,
|
|
6793
7633
|
{
|
|
6794
7634
|
items,
|
|
@@ -6798,12 +7638,12 @@ function ConversationView({
|
|
|
6798
7638
|
hasMore,
|
|
6799
7639
|
isLoadingMore: isLoading,
|
|
6800
7640
|
onLoadMore: loadMore,
|
|
6801
|
-
renderAfterMessages: needsEmail || showStarters ? /* @__PURE__ */
|
|
6802
|
-
needsEmail && /* @__PURE__ */
|
|
6803
|
-
showStarters && /* @__PURE__ */
|
|
7641
|
+
renderAfterMessages: needsEmail || showStarters ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
7642
|
+
needsEmail && /* @__PURE__ */ jsx19(InlineEmailPrompt, { conversationId: emailGateConvId ?? void 0 }),
|
|
7643
|
+
showStarters && /* @__PURE__ */ jsx19("div", { className: "hw-starters", children: starters?.map((entry, index) => {
|
|
6804
7644
|
const question = typeof entry === "string" ? entry : entry.question;
|
|
6805
7645
|
const label = typeof entry === "string" ? null : entry.label;
|
|
6806
|
-
return /* @__PURE__ */
|
|
7646
|
+
return /* @__PURE__ */ jsxs14(
|
|
6807
7647
|
"button",
|
|
6808
7648
|
{
|
|
6809
7649
|
type: "button",
|
|
@@ -6813,11 +7653,11 @@ function ConversationView({
|
|
|
6813
7653
|
void submit({ text: question });
|
|
6814
7654
|
},
|
|
6815
7655
|
children: [
|
|
6816
|
-
/* @__PURE__ */
|
|
6817
|
-
/* @__PURE__ */
|
|
6818
|
-
label && /* @__PURE__ */
|
|
7656
|
+
/* @__PURE__ */ jsxs14("span", { className: "hw-starter-text", children: [
|
|
7657
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-starter-k", children: label ?? question }),
|
|
7658
|
+
label && /* @__PURE__ */ jsx19("span", { className: "hw-starter-q", children: question })
|
|
6819
7659
|
] }),
|
|
6820
|
-
/* @__PURE__ */
|
|
7660
|
+
/* @__PURE__ */ jsx19(ChevronRightIcon, { size: 14 })
|
|
6821
7661
|
]
|
|
6822
7662
|
},
|
|
6823
7663
|
question
|
|
@@ -6826,10 +7666,10 @@ function ConversationView({
|
|
|
6826
7666
|
] }) : void 0
|
|
6827
7667
|
}
|
|
6828
7668
|
),
|
|
6829
|
-
isResolved && /* @__PURE__ */
|
|
6830
|
-
sendError && /* @__PURE__ */
|
|
7669
|
+
isResolved && /* @__PURE__ */ jsx19(ResolvedBanner, { conversationId }),
|
|
7670
|
+
sendError && /* @__PURE__ */ jsxs14("div", { className: "hw-send-error", children: [
|
|
6831
7671
|
sendError,
|
|
6832
|
-
/* @__PURE__ */
|
|
7672
|
+
/* @__PURE__ */ jsx19(
|
|
6833
7673
|
"button",
|
|
6834
7674
|
{
|
|
6835
7675
|
type: "button",
|
|
@@ -6842,7 +7682,7 @@ function ConversationView({
|
|
|
6842
7682
|
}
|
|
6843
7683
|
)
|
|
6844
7684
|
] }),
|
|
6845
|
-
/* @__PURE__ */
|
|
7685
|
+
/* @__PURE__ */ jsx19(
|
|
6846
7686
|
Composer,
|
|
6847
7687
|
{
|
|
6848
7688
|
text,
|
|
@@ -6853,50 +7693,12 @@ function ConversationView({
|
|
|
6853
7693
|
attachments,
|
|
6854
7694
|
onAddFiles: addFiles,
|
|
6855
7695
|
onRemoveAttachment: removeAttachment,
|
|
6856
|
-
disabled: needsEmail
|
|
7696
|
+
disabled: needsEmail,
|
|
7697
|
+
placeholder: isResolved ? t("widget.placeholder_resolved") : void 0
|
|
6857
7698
|
}
|
|
6858
7699
|
)
|
|
6859
7700
|
] });
|
|
6860
7701
|
}
|
|
6861
|
-
function ResolvedBanner({ conversationId }) {
|
|
6862
|
-
const { client } = useWidgetContext();
|
|
6863
|
-
const [csatRating, setCsatRating] = useState15(null);
|
|
6864
|
-
const [csatSubmitted, setCsatSubmitted] = useState15(false);
|
|
6865
|
-
const handleCsat = (rating) => {
|
|
6866
|
-
setCsatRating(rating);
|
|
6867
|
-
setCsatSubmitted(true);
|
|
6868
|
-
client.widget.sendCsat.mutate({ conversationId, rating }).catch(() => {
|
|
6869
|
-
});
|
|
6870
|
-
};
|
|
6871
|
-
return /* @__PURE__ */ jsxs11("div", { className: "hw-resolved", children: [
|
|
6872
|
-
/* @__PURE__ */ jsx16("div", { className: "hw-resolved-text", children: t("widget.resolved_text") }),
|
|
6873
|
-
!csatSubmitted ? /* @__PURE__ */ jsxs11("div", { className: "hw-csat", children: [
|
|
6874
|
-
/* @__PURE__ */ jsx16("div", { className: "hw-csat-label", children: t("widget.csat_label") }),
|
|
6875
|
-
/* @__PURE__ */ jsxs11("div", { className: "hw-csat-buttons", children: [
|
|
6876
|
-
/* @__PURE__ */ jsx16(
|
|
6877
|
-
"button",
|
|
6878
|
-
{
|
|
6879
|
-
type: "button",
|
|
6880
|
-
className: `hw-csat-btn ${csatRating === "good" ? "hw-csat-btn--selected" : ""}`,
|
|
6881
|
-
onClick: () => handleCsat("good"),
|
|
6882
|
-
"aria-label": t("widget.aria_good"),
|
|
6883
|
-
children: "\u{1F44D}"
|
|
6884
|
-
}
|
|
6885
|
-
),
|
|
6886
|
-
/* @__PURE__ */ jsx16(
|
|
6887
|
-
"button",
|
|
6888
|
-
{
|
|
6889
|
-
type: "button",
|
|
6890
|
-
className: `hw-csat-btn ${csatRating === "bad" ? "hw-csat-btn--selected" : ""}`,
|
|
6891
|
-
onClick: () => handleCsat("bad"),
|
|
6892
|
-
"aria-label": t("widget.aria_bad"),
|
|
6893
|
-
children: "\u{1F44E}"
|
|
6894
|
-
}
|
|
6895
|
-
)
|
|
6896
|
-
] })
|
|
6897
|
-
] }) : /* @__PURE__ */ jsx16("div", { className: "hw-csat-thanks", children: t("widget.csat_thanks") })
|
|
6898
|
-
] });
|
|
6899
|
-
}
|
|
6900
7702
|
function WhatsNewCard({
|
|
6901
7703
|
getUnseenEntries,
|
|
6902
7704
|
announcementTabs,
|
|
@@ -6907,34 +7709,34 @@ function WhatsNewCard({
|
|
|
6907
7709
|
if (unseen.length === 0) return null;
|
|
6908
7710
|
const display = unseen.slice(0, 3);
|
|
6909
7711
|
const badgeFieldMap = new Map(announcementTabs.map((t2) => [t2.id, t2.display?.badgeField]));
|
|
6910
|
-
return /* @__PURE__ */
|
|
6911
|
-
/* @__PURE__ */
|
|
6912
|
-
/* @__PURE__ */
|
|
6913
|
-
/* @__PURE__ */
|
|
7712
|
+
return /* @__PURE__ */ jsxs14("div", { className: "hw-whats-new", children: [
|
|
7713
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-whats-new-header", children: [
|
|
7714
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-whats-new-title", children: resolveLabel2("widget.whats_new") }),
|
|
7715
|
+
/* @__PURE__ */ jsxs14("button", { type: "button", className: "hw-whats-new-view-all", onClick: onViewAll, children: [
|
|
6914
7716
|
resolveLabel2("widget.view_all"),
|
|
6915
7717
|
" \u2192"
|
|
6916
7718
|
] })
|
|
6917
7719
|
] }),
|
|
6918
|
-
/* @__PURE__ */
|
|
7720
|
+
/* @__PURE__ */ jsx19("div", { className: "hw-whats-new-list", children: display.map((entry) => {
|
|
6919
7721
|
const badgeField = badgeFieldMap.get(entry.tabId);
|
|
6920
|
-
return /* @__PURE__ */
|
|
7722
|
+
return /* @__PURE__ */ jsxs14(
|
|
6921
7723
|
"button",
|
|
6922
7724
|
{
|
|
6923
7725
|
type: "button",
|
|
6924
7726
|
className: "hw-whats-new-item",
|
|
6925
7727
|
onClick: () => onSelect(entry.slug, entry.tabId),
|
|
6926
7728
|
children: [
|
|
6927
|
-
badgeField && entry.customFields[badgeField] && /* @__PURE__ */
|
|
6928
|
-
/* @__PURE__ */
|
|
6929
|
-
entry.publishedAt && /* @__PURE__ */
|
|
7729
|
+
badgeField && entry.customFields[badgeField] && /* @__PURE__ */ jsxs14("div", { className: "hw-whats-new-item-top", children: [
|
|
7730
|
+
/* @__PURE__ */ jsx19("span", { className: "hw-whats-new-badge", children: entry.customFields[badgeField] }),
|
|
7731
|
+
entry.publishedAt && /* @__PURE__ */ jsx19("span", { className: "hw-whats-new-time", children: formatRelativeTime(entry.publishedAt) })
|
|
6930
7732
|
] }),
|
|
6931
|
-
/* @__PURE__ */
|
|
7733
|
+
/* @__PURE__ */ jsxs14("div", { className: "hw-whats-new-item-title", children: [
|
|
6932
7734
|
entry.title,
|
|
6933
|
-
!badgeField && entry.publishedAt && /* @__PURE__ */
|
|
7735
|
+
!badgeField && entry.publishedAt && /* @__PURE__ */ jsx19("span", { className: "hw-whats-new-time-inline", children: formatRelativeTime(entry.publishedAt) })
|
|
6934
7736
|
] }),
|
|
6935
7737
|
entry.body && (() => {
|
|
6936
7738
|
const clean = stripMarkdown(entry.body);
|
|
6937
|
-
return /* @__PURE__ */
|
|
7739
|
+
return /* @__PURE__ */ jsx19("div", { className: "hw-whats-new-item-body", children: clean.length > 80 ? `${clean.slice(0, 80)}\u2026` : clean });
|
|
6938
7740
|
})()
|
|
6939
7741
|
]
|
|
6940
7742
|
},
|
|
@@ -6967,10 +7769,10 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
6967
7769
|
}
|
|
6968
7770
|
|
|
6969
7771
|
// src/themed/styles.css
|
|
6970
|
-
styleInject(':host {\n all: initial;\n font-family:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #1a1a1a;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.hw-widget {\n font-family:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #1a1a1a;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.hw-widget *,\n.hw-widget *::before,\n.hw-widget *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n:where(.hw-widget) {\n --hw-primary: #171717;\n --hw-primary-hover: #2a2a2a;\n --hw-brand: #171717;\n --hw-on-brand: #ffffff;\n --hw-focus-border: #9ca3af;\n --hw-focus-ring: rgba(0, 0, 0, 0.06);\n --hw-accent: #6366f1;\n --hw-bg: #ffffff;\n --hw-bg-subtle: #fafaf9;\n --hw-bg-hover: #f5f5f4;\n --hw-border: #ebe9e5;\n --hw-border-md: #e5e5e5;\n --hw-text: #1c1b19;\n --hw-text-1: #111;\n --hw-text-2: #666;\n --hw-text-3: #8a847c;\n --hw-text-4: #a8a29a;\n --hw-radius: 20px;\n --hw-visitor-bubble-bg: #f5f5f4;\n --hw-visitor-bubble-text: #1a1a1a;\n --hw-font:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n}\n.hw-agent-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-agent-icon {\n width: 100%;\n height: 100%;\n border-radius: inherit;\n}\n.hw-widget :is(.hw-header-bot-icon, .hw-hero-bot-icon, .hw-conv-card-avatar, .hw-event-avatar, .hw-bubble-icon--bot):has(> .hw-agent-custom) {\n border-radius: 50%;\n background: transparent;\n padding: 0;\n}\n.hw-widget :focus-visible {\n outline: 2px solid var(--hw-primary);\n outline-offset: 2px;\n}\n.hw-widget :focus:not(:focus-visible) {\n outline: none;\n}\n.hw-widget {\n position: fixed;\n bottom: 20px;\n right: var(--hw-position-right, 20px);\n left: var(--hw-position-left, auto);\n z-index: 999999;\n font-family: var(--hw-font);\n}\n@keyframes hw-bubble-enter {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n.hw-bubble {\n width: 48px;\n height: 48px;\n border-radius: 14px;\n background: var(--hw-primary);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease;\n position: relative;\n overflow: visible;\n animation: hw-bubble-enter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) both;\n}\n.hw-bubble--rounded {\n border-radius: 14px;\n}\n.hw-bubble--square {\n border-radius: 8px;\n}\n.hw-bubble--pill {\n border-radius: 24px;\n}\n.hw-bubble--launcher-bubble,\n.hw-bubble--launcher-help {\n width: auto;\n padding: 0 16px 0 12px;\n gap: 8px;\n border-radius: 24px;\n}\n.hw-bubble--launcher-bubble.hw-bubble--square,\n.hw-bubble--launcher-help.hw-bubble--square {\n border-radius: 8px;\n}\n.hw-bubble--launcher-bubble.hw-bubble--rounded,\n.hw-bubble--launcher-help.hw-bubble--rounded {\n border-radius: 14px;\n}\n.hw-bubble-label {\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n line-height: 1;\n position: static;\n opacity: 1;\n transform: none;\n}\n.hw-bubble--launcher-bubble .hw-bubble-icon,\n.hw-bubble--launcher-help .hw-bubble-icon {\n position: static;\n}\n.hw-bubble:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n}\n.hw-bubble:active {\n transform: scale(0.95);\n}\n.hw-bubble--open {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n}\n.hw-bubble:focus-visible {\n outline: 2px solid white;\n outline-offset: 2px;\n}\n.hw-bubble-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;\n}\n.hw-bubble-icon svg:not(.hw-agent-custom svg) {\n width: 22px;\n height: 22px;\n}\n.hw-bubble-icon--hidden {\n transform: scale(0.3) rotate(90deg);\n opacity: 0;\n}\n.hw-bubble-icon--bot {\n}\n.hw-bubble--avatar .hw-bubble-icon--bot {\n width: 100%;\n height: 100%;\n}\n.hw-bubble--avatar .hw-bubble-icon--bot .hw-agent-img {\n width: 100%;\n height: 100%;\n border-radius: 0;\n}\n.hw-agent-img.hw-agent-img--logo {\n object-fit: contain;\n padding: 10px;\n box-sizing: border-box;\n}\n.hw-bubble--avatar .hw-bubble-icon--bot .hw-agent-img.hw-agent-img--logo {\n padding: 10px;\n box-sizing: border-box;\n object-fit: contain;\n}\n.hw-bubble-icon--close svg {\n width: 22px;\n height: 22px;\n}\n.hw-bubble-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n border-radius: 10px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n border: 2px solid white;\n animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n@keyframes hw-badge-pop {\n from {\n transform: scale(0);\n }\n to {\n transform: scale(1);\n }\n}\n.hw-bubble-badge::after {\n content: "";\n position: absolute;\n inset: -2px;\n border-radius: inherit;\n background: var(--hw-primary);\n opacity: 0;\n animation: hw-badge-pulse 2s ease-out infinite;\n}\n@keyframes hw-badge-pulse {\n 0% {\n opacity: 0.5;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(1.8);\n }\n}\n.hw-window {\n position: absolute;\n bottom: 72px;\n right: var(--hw-window-right, 0);\n left: var(--hw-window-left, auto);\n width: 440px;\n height: 640px;\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n border-radius: var(--hw-radius);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: hw-window-open 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);\n transition: width 280ms cubic-bezier(0.4, 0, 0.2, 1), height 280ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n.hw-window--reading {\n width: min(720px, calc(100vw - 40px));\n height: min(800px, calc(100vh - 112px));\n}\n@keyframes hw-window-open {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.hw-window--closing {\n animation: hw-window-close 0.2s ease forwards;\n}\n@keyframes hw-window-close {\n from {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.98);\n }\n}\n.hw-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-window,\n .hw-window--closing,\n .hw-content,\n .hw-msg,\n .hw-bubble,\n .hw-bubble-icon,\n .hw-bubble-badge,\n .hw-bubble-badge::after,\n .hw-typing-dot,\n .hw-loading-dot {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n.hw-hero {\n flex-shrink: 0;\n background:\n linear-gradient(\n 160deg,\n color-mix(in srgb, var(--hw-primary) 60%, black) 0%,\n var(--hw-primary) 50%,\n color-mix(in srgb, var(--hw-primary) 40%, black) 100%);\n color: white;\n padding: 20px 22px 40px;\n}\n.hw-hero-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n.hw-hero-close {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n border: none;\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n.hw-hero-close:hover {\n background: rgba(255, 255, 255, 0.2);\n color: white;\n}\n.hw-hero-close:active {\n transform: scale(0.92);\n transition:\n transform 0.14s cubic-bezier(0.23, 1, 0.32, 1),\n background 0.15s,\n color 0.15s;\n}\n.hw-hero-close svg {\n width: 20px;\n height: 20px;\n}\n.hw-hero-bot-icon {\n width: 36px;\n height: 36px;\n flex-shrink: 0;\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n}\n.hw-hero-bot-icon > svg,\n.hw-hero-bot-icon > .hw-agent-icon > svg {\n width: 32px;\n height: 32px;\n}\n.hw-hero-bot-icon .hw-agent-img,\n.hw-hero-bot-icon .hw-agent-icon {\n border-radius: inherit;\n overflow: hidden;\n object-fit: contain;\n}\n.hw-hero-greeting {\n font-size: 26px;\n font-weight: 700;\n line-height: 1.15;\n margin-bottom: 6px;\n}\n.hw-hero-greeting-name {\n font-weight: 300;\n}\n.hw-hero-greeting-question {\n font-weight: 700;\n}\n.hw-hero-subtitle {\n font-size: 15px;\n color: rgba(255, 255, 255, 0.5);\n line-height: 1.35;\n}\n.hw-sheet {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n background: #ffffff;\n border-radius: 20px 20px 0 0;\n margin-top: -24px;\n box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);\n position: relative;\n z-index: 1;\n}\n.hw-sheet-inner {\n padding: 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.hw-header {\n display: flex;\n align-items: center;\n padding: 14px 12px 14px 16px;\n background: var(--hw-primary);\n color: white;\n flex-shrink: 0;\n gap: 10px;\n}\n.hw-header--sub {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header-back {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n flex-shrink: 0;\n}\n.hw-header-back svg {\n width: 18px;\n height: 18px;\n}\n.hw-header-back:hover {\n color: var(--hw-text);\n background: var(--hw-bg-subtle);\n}\n.hw-header-identity {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n.hw-header-bot-icon {\n width: 32px;\n height: 32px;\n flex-shrink: 0;\n color: var(--hw-text);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 9px;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));\n}\n.hw-header-bot-icon > svg,\n.hw-header-bot-icon > .hw-agent-icon > svg {\n width: 24px;\n height: 24px;\n}\n.hw-header-bot-icon--team {\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n}\n.hw-header-agent-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n}\n.hw-header-bot-icon .hw-agent-img,\n.hw-header-bot-icon .hw-agent-icon {\n border-radius: inherit;\n overflow: hidden;\n}\n.hw-header-bot-icon .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-widget[data-has-avatar=true] {\n --hw-agent-bg-default: var(--hw-primary);\n --hw-agent-fit-default: contain;\n --hw-agent-pad-default: 6px;\n}\n.hw-header-agent-initials {\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n}\n.hw-header-info {\n flex: 1;\n min-width: 0;\n}\n.hw-header-name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.3;\n}\n.hw-header-status {\n font-size: 11px;\n color: var(--hw-text-3);\n line-height: 1.3;\n}\n.hw-header-close {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n flex-shrink: 0;\n}\n.hw-header-close svg {\n width: 20px;\n height: 20px;\n}\n.hw-header-close:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n}\n.hw-header-close:active {\n transform: scale(0.92);\n}\n.hw-header--centered {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header--centered .hw-header-title {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100% - 88px);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n text-align: center;\n}\n.hw-header-spacer {\n width: 28px;\n flex-shrink: 0;\n}\n.hw-header--messages {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header-title {\n font-size: 16px;\n font-weight: 600;\n}\n.hw-header-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.hw-header-action {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n.hw-header-action svg {\n width: 16px;\n height: 16px;\n}\n.hw-header-action:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n}\n.hw-header-action:active {\n transform: scale(0.94);\n}\n.hw-card {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n padding: 14px 16px;\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n cursor: pointer;\n transition: box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1), transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\n text-align: left;\n color: var(--hw-text);\n font-family: inherit;\n}\n.hw-card:hover {\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.05);\n transform: translateY(-1px);\n}\n.hw-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 120ms;\n}\n.hw-card-body {\n flex: 1;\n min-width: 0;\n}\n.hw-card-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: var(--hw-text);\n}\n.hw-card-meta {\n font-size: 12px;\n color: var(--hw-text-3);\n line-height: 1.3;\n margin-top: 1px;\n}\n.hw-card-arrow {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--hw-primary);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.hw-card-arrow svg {\n width: 14px;\n height: 14px;\n}\n.hw-msgs-tab {\n flex: 1;\n overflow-y: auto;\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-recent-card {\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n overflow: hidden;\n}\n.hw-recent-header {\n font-size: 12px;\n font-weight: 600;\n color: var(--hw-text-2);\n padding: 12px 14px 0;\n}\n.hw-recent-row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 14px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n transition: background-color 140ms cubic-bezier(0.23, 1, 0.32, 1), transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n position: relative;\n}\n.hw-recent-row:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n.hw-recent-row:active {\n transform: scale(0.995);\n}\n.hw-recent-row--last {\n border-bottom: none;\n}\n.hw-recent-row .hw-conv-card-avatar {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n}\n.hw-recent-row .hw-conv-card-avatar svg:not(.hw-agent-custom svg) {\n width: 18px;\n height: 18px;\n}\n.hw-recent-row .hw-conv-card-name {\n font-size: 13px;\n}\n.hw-recent-row .hw-conv-card-preview {\n font-size: 12px;\n}\n.hw-recent-row--unread .hw-conv-card-name {\n color: var(--hw-text);\n}\n.hw-recent-row--unread .hw-conv-card-time {\n color: var(--hw-primary);\n font-weight: 500;\n}\n.hw-recent-row-badge {\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n.hw-recent-see-all {\n display: block;\n width: 100%;\n padding: 10px 14px;\n text-align: center;\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-text);\n background: none;\n border: none;\n border-top: 1px solid var(--hw-border);\n cursor: pointer;\n font-family: inherit;\n transition: background 0.1s;\n}\n.hw-recent-see-all:hover {\n background: rgba(0, 0, 0, 0.02);\n}\n.hw-conv-card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n padding: 14px 16px;\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n cursor: pointer;\n transition: box-shadow 0.15s, transform 0.1s;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n}\n.hw-conv-card:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n.hw-conv-card:active {\n transform: scale(0.99);\n}\n.hw-conv-card-row {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hw-conv-card-avatar {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-subtle)));\n color: var(--hw-text-3);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-conv-card-avatar svg:not(.hw-agent-custom svg) {\n width: 20px;\n height: 20px;\n}\n.hw-conv-card-avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-conv-card-avatar .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-conv-card-avatar--team {\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n}\n.hw-conv-card-avatar-initials {\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n letter-spacing: 0.02em;\n}\n.hw-conv-card-content {\n flex: 1;\n min-width: 0;\n}\n.hw-conv-card-top {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.hw-conv-card-name {\n flex: 1;\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-conv-card-time {\n font-size: 11px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n.hw-conv-card-preview {\n font-size: 13px;\n color: var(--hw-text-2);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 1.4;\n margin-top: 1px;\n}\n.hw-conv-card--unread .hw-conv-card-name {\n color: var(--hw-text);\n}\n.hw-conv-card--unread .hw-conv-card-time {\n color: var(--hw-primary);\n font-weight: 500;\n}\n.hw-conv-card-badge {\n position: absolute;\n top: 12px;\n right: 12px;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n font-variant-numeric: tabular-nums;\n}\n.hw-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n text-align: center;\n}\n.hw-empty-icon-wrap {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--hw-bg-subtle);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 16px;\n color: var(--hw-text-3);\n}\n.hw-empty-icon-wrap svg {\n width: 24px;\n height: 24px;\n}\n.hw-empty-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--hw-text);\n margin-bottom: 4px;\n}\n.hw-empty-desc {\n font-size: 13px;\n color: var(--hw-text-3);\n margin-bottom: 20px;\n}\n.hw-empty-btn {\n padding: 8px 20px;\n border-radius: 10px;\n background: var(--hw-primary);\n color: white;\n border: none;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 0.15s;\n}\n.hw-empty-btn:hover {\n background: var(--hw-primary-hover);\n}\n.hw-tabs {\n display: flex;\n border-top: 1px solid var(--hw-border);\n flex-shrink: 0;\n background: var(--hw-bg-subtle);\n}\n.hw-tabs-item {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n padding: 8px 0;\n border: none;\n background: none;\n cursor: pointer;\n font-family: inherit;\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n transition: color 0.15s;\n}\n.hw-tabs-item svg {\n width: 22px;\n height: 22px;\n overflow: visible;\n}\n.hw-tabs-item--active {\n color: var(--hw-text);\n}\n.hw-tabs-item:hover {\n color: var(--hw-text-2);\n}\n.hw-tabs-item:active {\n transform: scale(0.94);\n transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), color 0.15s;\n}\n.hw-tabs-icon-wrap {\n position: relative;\n display: inline-flex;\n}\n.hw-tabs-badge {\n position: absolute;\n top: -6px;\n right: -10px;\n min-width: 16px;\n height: 16px;\n border-radius: 8px;\n background: var(--hw-primary);\n color: white;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n font-variant-numeric: tabular-nums;\n}\n.hw-messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px 14px 8px;\n background: var(--hw-bg-subtle);\n display: flex;\n flex-direction: column;\n gap: 14px;\n overscroll-behavior: contain;\n min-width: 0;\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\n scrollbar-width: thin;\n}\n.hw-messages::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n.hw-messages::-webkit-scrollbar-track {\n background: transparent;\n}\n.hw-messages::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.16);\n background-clip: content-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n.hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.28);\n background-clip: content-box;\n}\n.hw-widget[data-theme=dark] .hw-messages {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n}\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n background-clip: content-box;\n}\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n}\n.hw-empty {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--hw-text-3);\n text-align: center;\n}\n.hw-empty-icon {\n width: 40px;\n height: 40px;\n margin-bottom: 12px;\n opacity: 0.3;\n}\n.hw-empty-text {\n font-size: 13px;\n}\n.hw-date-sep {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 0;\n}\n.hw-date-sep-line {\n flex: 1;\n height: 1px;\n background: var(--hw-border-md);\n}\n.hw-date-sep-text {\n font-size: 11px;\n color: var(--hw-text-3);\n font-weight: 500;\n white-space: nowrap;\n}\n.hw-msg {\n display: flex;\n padding: 4px 0;\n max-width: 75%;\n min-width: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n@keyframes hw-msg-appear {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-msg--visitor {\n align-self: flex-end;\n}\n.hw-msg--team,\n.hw-msg--ai {\n align-self: flex-start;\n}\n.hw-msg--ai {\n width: 100%;\n max-width: 100%;\n}\n.hw-msg-body {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: 100%;\n}\n.hw-msg-bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n max-width: 100%;\n}\n.hw-msg--visitor .hw-msg-bubble {\n background: var(--hw-primary);\n color: white;\n border-bottom-right-radius: 4px;\n}\n.hw-msg--team .hw-msg-bubble {\n background: var(--hw-visitor-bubble-bg);\n color: var(--hw-visitor-bubble-text);\n border-bottom-left-radius: 4px;\n}\n.hw-msg--ai .hw-msg-bubble {\n background: var(--hw-visitor-bubble-bg);\n color: var(--hw-text);\n border-bottom-left-radius: 4px;\n white-space: normal;\n max-width: min(100%, 640px);\n}\n.hw-msg--ai .hw-msg-body {\n width: 100%;\n}\n.hw-msg--ai .hw-msg-bubble:has(.hw-code),\n.hw-msg--ai .hw-msg-bubble:has(pre) {\n width: 100%;\n}\n.hw-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n.hw-quick-reply-btn {\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n padding: 6px 14px;\n border-radius: 18px;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n background: var(--hw-bg, #fff);\n color: var(--hw-text-1, #1a1a1a);\n cursor: pointer;\n transition:\n background 120ms ease,\n border-color 120ms ease,\n box-shadow 120ms ease,\n transform 80ms ease;\n line-height: 1.3;\n}\n.hw-quick-reply-btn:hover:not(:disabled) {\n border-color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 8%, transparent);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n}\n.hw-quick-reply-btn:active:not(:disabled) {\n transform: scale(0.97);\n}\n.hw-quick-reply-btn:disabled {\n cursor: default;\n opacity: 0.4;\n}\n.hw-quick-reply-btn[data-tapped=true] {\n background: var(--hw-primary);\n color: white;\n border-color: var(--hw-primary);\n opacity: 1;\n}\n.hw-quick-replies[data-cancelled=true] .hw-quick-reply-btn {\n border-color: var(--hw-border);\n color: var(--hw-text-3);\n}\n.hw-msg--ai .hw-code {\n width: 100%;\n box-sizing: border-box;\n}\n.hw-msg-meta {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--hw-text-2);\n margin-top: 2px;\n padding: 0 4px;\n font-variant-numeric: tabular-nums;\n}\n.hw-msg-time {\n white-space: nowrap;\n}\n.hw-msg--visitor .hw-msg-meta {\n text-align: right;\n}\n.hw-msg--team .hw-msg-body,\n.hw-msg--ai .hw-msg-body {\n align-items: flex-start;\n}\n.hw-msg--visitor .hw-msg-body {\n align-items: flex-end;\n}\n.hw-typing {\n display: flex;\n flex-direction: column;\n gap: 3px;\n padding: 8px 0;\n width: fit-content;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-typing-dots {\n display: flex;\n gap: 3px;\n padding: 6px 2px;\n width: fit-content;\n}\n.hw-typing-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--hw-text-3);\n animation: hw-typing-bounce 1.4s infinite;\n}\n.hw-typing-dot:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-typing-dot:nth-child(3) {\n animation-delay: 0.4s;\n}\n@keyframes hw-typing-bounce {\n 0%, 60%, 100% {\n transform: translateY(0);\n }\n 30% {\n transform: translateY(-4px);\n }\n}\n.hw-streaming-cursor {\n display: inline-block;\n width: 2px;\n height: 1em;\n background: currentColor;\n opacity: 0.6;\n margin-left: 1px;\n vertical-align: text-bottom;\n animation: hw-cursor-blink 0.8s step-end infinite;\n}\n@keyframes hw-cursor-blink {\n 50% {\n opacity: 0;\n }\n}\n.hw-link-preview {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n border-radius: 10px;\n overflow: hidden;\n text-decoration: none;\n color: inherit;\n margin-top: 6px;\n transition: background 0.15s;\n}\n.hw-link-preview:hover {\n background: var(--hw-bg-hover, rgba(0, 0, 0, 0.02));\n}\n.hw-link-preview-img {\n width: 100%;\n height: 56px;\n flex: 0 0 56px;\n object-fit: cover;\n object-position: top;\n border-radius: 0;\n}\n.hw-link-preview-body {\n padding: 8px 10px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n justify-content: center;\n}\n.hw-link-preview-favicon {\n width: 16px;\n height: 16px;\n border-radius: 2px;\n}\n.hw-link-preview-title {\n font-size: 12.5px;\n font-weight: 600;\n line-height: 1.3;\n color: var(--hw-text, #1a1a1a);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.hw-link-preview-desc {\n font-size: 11.5px;\n line-height: 1.4;\n color: var(--hw-text-2, #6b7280);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.hw-link-preview-url {\n font-size: 11px;\n color: var(--hw-text-2);\n}\n.hw-msg-links {\n display: flex;\n flex-direction: column;\n gap: 6px;\n max-width: 240px;\n}\n.hw-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-loading-dots {\n display: flex;\n gap: 4px;\n}\n.hw-loading-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--hw-text-4);\n animation: hw-loading-pulse 1.4s infinite;\n}\n.hw-loading-dot:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-loading-dot:nth-child(3) {\n animation-delay: 0.4s;\n}\n@keyframes hw-loading-pulse {\n 0%, 60%, 100% {\n opacity: 0.3;\n transform: scale(0.8);\n }\n 30% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes hw-skeleton-shimmer {\n 0% {\n background-position: -200px 0;\n }\n 100% {\n background-position: calc(200px + 100%) 0;\n }\n}\n.hw-skeleton {\n background:\n linear-gradient(\n 90deg,\n var(--hw-bg-subtle) 25%,\n rgba(0, 0, 0, 0.04) 50%,\n var(--hw-bg-subtle) 75%);\n background-size: 200px 100%;\n animation: hw-skeleton-shimmer 1.5s ease-in-out infinite;\n border-radius: 6px;\n}\n.hw-skeleton-messages {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 16px;\n gap: 16px;\n}\n.hw-skeleton-msg {\n display: flex;\n gap: 10px;\n align-items: flex-start;\n}\n.hw-skeleton-msg--right {\n flex-direction: row-reverse;\n}\n.hw-skeleton-avatar {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n flex-shrink: 0;\n}\n.hw-skeleton-bubble {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.hw-skeleton-line {\n height: 12px;\n border-radius: 6px;\n}\n.hw-skeleton-convs {\n display: flex;\n flex-direction: column;\n padding: 8px 0;\n}\n.hw-skeleton-conv {\n display: flex;\n gap: 10px;\n align-items: center;\n padding: 10px 16px;\n}\n.hw-skeleton-conv-avatar {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n flex-shrink: 0;\n}\n.hw-skeleton-conv-lines {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.hw-skeleton-content {\n display: flex;\n flex-direction: column;\n padding: 12px 16px;\n gap: 12px;\n}\n.hw-skeleton-content-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n border-radius: 10px;\n background: var(--hw-bg);\n}\n.hw-skeleton-title {\n height: 22px;\n width: 65%;\n border-radius: 6px;\n}\n.hw-skeleton-badge {\n width: 42px;\n height: 18px;\n border-radius: 9px;\n}\n.hw-skeleton-date {\n width: 60px;\n height: 12px;\n border-radius: 6px;\n}\n.hw-skeleton-h2 {\n height: 16px;\n border-radius: 6px;\n}\n.hw-skeleton-bullet {\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-skeleton-bullet-line {\n height: 14px;\n border-radius: 7px;\n}\n.hw-email-card {\n max-width: min(100%, 340px);\n margin: 0;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: none;\n box-shadow: none;\n animation: hw-email-slide-in 0.25s ease-out;\n}\n@keyframes hw-email-slide-in {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-email-card-title {\n font-size: 14px;\n font-weight: 550;\n color: var(--hw-text, #1a1a1a);\n line-height: 1.3;\n margin: 0 0 2px;\n}\n.hw-email-card-subtitle {\n font-size: 12px;\n color: var(--hw-text-2, #888);\n line-height: 1.4;\n margin: 0;\n}\n.hw-email-card-row {\n max-width: 300px;\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 9px;\n padding: 3px 3px 3px 12px;\n border-radius: 999px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.1));\n background: var(--hw-bg-subtle, #fafafa);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-email-card-row:focus-within {\n border-color: var(--hw-focus-border, rgba(0,0,0,0.2));\n box-shadow: 0 0 0 2px var(--hw-focus-ring, rgba(0,0,0,0.06));\n}\n.hw-email-card-input {\n flex: 1;\n min-width: 0;\n padding: 6px 0;\n border: 0;\n background: transparent;\n color: var(--hw-text, #1a1a1a);\n font: inherit;\n font-size: 13px;\n outline: none;\n}\n.hw-email-card-input::placeholder {\n color: var(--hw-text-3, #999);\n}\n.hw-email-card-row:has(.hw-email-card-input--error) {\n border-color: #ef4444;\n}\n.hw-email-card-submit {\n flex: none;\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n cursor: pointer;\n transition: opacity 0.15s, transform 0.15s;\n}\n.hw-email-card-submit:hover:not(:disabled) {\n transform: scale(1.06);\n}\n.hw-email-card-submit:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.hw-email-card--success {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 13px;\n color: var(--hw-text-2, #888);\n animation: hw-email-slide-in 0.2s ease-out;\n}\n.hw-email-card--success svg {\n flex-shrink: 0;\n}\n.hw-composer {\n display: flex;\n flex-direction: column;\n padding: 12px 16px;\n background: transparent;\n flex-shrink: 0;\n}\n.hw-composer--compact {\n padding: 8px 12px;\n}\n.hw-composer-box {\n display: flex;\n flex-direction: column;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n border-radius: 16px;\n overflow: hidden;\n transition: border-color 0.2s;\n background: var(--hw-bg);\n}\n.hw-composer-box:focus-within {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n}\n.hw-composer-input {\n resize: none;\n border: none;\n padding: 12px 16px 4px;\n font-size: 14px;\n font-family: inherit;\n line-height: 1.4;\n outline: none;\n min-height: 40px;\n max-height: 220px;\n background: transparent;\n color: var(--hw-text);\n field-sizing: content;\n}\n.hw-composer-input:focus {\n outline: none;\n}\n.hw-composer-input:focus-visible {\n outline: none;\n}\n.hw-composer-input::placeholder {\n color: var(--hw-text-4);\n}\n.hw-composer-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px 10px;\n}\n.hw-composer-toolbar-left {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.hw-composer-send {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n.hw-composer-send:active:not(:disabled) {\n transform: scale(0.9);\n}\n.hw-composer-send--active {\n background: var(--hw-primary);\n color: white;\n}\n.hw-composer-send--inactive {\n background: var(--hw-border);\n color: var(--hw-text-4);\n cursor: default;\n}\n.hw-composer-send svg {\n width: 14px;\n height: 14px;\n}\n.hw-composer-charcount {\n font-size: 11px;\n color: var(--hw-text-3);\n font-variant-numeric: tabular-nums;\n opacity: 1;\n transform: translateY(0);\n transition:\n color 180ms cubic-bezier(0.23, 1, 0.32, 1),\n opacity 180ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n@starting-style {\n .hw-composer-charcount {\n opacity: 0;\n transform: translateY(3px);\n }\n}\n.hw-composer-charcount--over {\n color: #ef4444;\n font-weight: 600;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-composer-charcount {\n transform: none;\n transition: color 160ms ease, opacity 160ms ease;\n }\n @starting-style {\n .hw-composer-charcount {\n transform: none;\n }\n }\n}\n.hw-composer-previews {\n display: flex;\n gap: 6px;\n padding: 8px 10px 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.hw-composer-previews::-webkit-scrollbar {\n display: none;\n}\n.hw-composer-preview {\n position: relative;\n width: 48px;\n height: 48px;\n border-radius: 8px;\n overflow: hidden;\n flex-shrink: 0;\n background: var(--hw-border);\n cursor: pointer;\n}\n.hw-composer-preview--error {\n outline: 2px solid #ef4444;\n outline-offset: -2px;\n}\n.hw-composer-preview-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-composer-preview-file {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--hw-bg-subtle);\n}\n.hw-composer-preview-ext {\n font-size: 10px;\n font-weight: 700;\n color: var(--hw-text-3);\n text-transform: uppercase;\n}\n.hw-composer-preview-loader {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-composer-preview-loader::after {\n content: "";\n width: 16px;\n height: 16px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: white;\n border-radius: 50%;\n animation: hw-spin 0.6s linear infinite;\n}\n@keyframes hw-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.hw-composer-preview-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #ef4444;\n color: white;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-composer-preview-remove {\n position: absolute;\n top: 2px;\n right: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: rgba(0, 0, 0, 0.55);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.hw-composer-preview-remove svg {\n width: 10px;\n height: 10px;\n}\n.hw-composer-preview:hover .hw-composer-preview-remove {\n opacity: 1;\n}\n.hw-composer-attach {\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n opacity: 0.7;\n transition: opacity 0.15s;\n}\n.hw-composer-attach:hover {\n opacity: 1;\n}\n.hw-composer-attach svg {\n width: 16px;\n height: 16px;\n}\n.hw-msg-images {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-bottom: 4px;\n}\n.hw-msg-image-link {\n display: block;\n border-radius: 14px;\n overflow: hidden;\n line-height: 0;\n}\n.hw-msg-image {\n max-width: 140px;\n max-height: 80px;\n object-fit: cover;\n border-radius: 8px;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-msg-files {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 4px;\n}\n.hw-msg-file {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 10px;\n background: var(--hw-bg-subtle);\n text-decoration: none;\n color: var(--hw-text);\n transition: background 0.15s;\n}\n.hw-msg-file:hover {\n background: var(--hw-border);\n}\n.hw-msg-file-icon {\n flex-shrink: 0;\n width: 20px;\n height: 20px;\n color: var(--hw-text-3);\n}\n.hw-msg-file-icon svg {\n width: 100%;\n height: 100%;\n}\n.hw-msg-file-info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.hw-msg-file-name {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.hw-msg-file-size {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-msg-image-link {\n cursor: pointer;\n border: none;\n padding: 0;\n background: none;\n display: block;\n line-height: 0;\n}\n.hw-hover-preview {\n position: fixed;\n z-index: 2147483001;\n padding: 6px;\n border-radius: 14px;\n background: white;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.06);\n cursor: pointer;\n animation: hw-hover-in 0.15s ease-out;\n}\n@media (prefers-color-scheme: dark) {\n .hw-hover-preview {\n background: #1c1c1e;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08);\n }\n}\n@keyframes hw-hover-in {\n from {\n opacity: 0;\n transform: scale(0.96) translateY(4px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n.hw-hover-preview-img {\n width: 100%;\n max-height: 200px;\n object-fit: contain;\n border-radius: 10px;\n display: block;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-hover-preview--doc {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n}\n.hw-hover-preview-doc-icon {\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n}\n.hw-hover-preview-doc-icon svg {\n width: 100%;\n height: 100%;\n}\n.hw-hover-preview-doc-info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.hw-hover-preview-doc-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.hw-hover-preview-doc-hint {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-event {\n display: flex;\n justify-content: center;\n padding: 8px 16px;\n}\n.hw-event-text {\n font-size: 12px;\n color: var(--hw-text-3);\n text-align: center;\n}\n.hw-event--card {\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n background: var(--hw-bg-subtle);\n padding: 10px 14px;\n border-radius: 12px;\n margin: 4px 16px;\n}\n.hw-event-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-hover, #e0e0e0)));\n color: var(--hw-text-2, #555);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-event-avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-event-avatar .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-event-body {\n font-size: 13px;\n line-height: 1.3;\n}\n.hw-event-name {\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-event-action {\n color: var(--hw-text-2);\n}\n.hw-resolved-banner {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 12px 16px;\n border-top: 1px solid var(--hw-border);\n background: var(--hw-bg-subtle);\n color: var(--hw-text-2);\n font-size: 13px;\n flex-shrink: 0;\n}\n.hw-new {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--hw-bg-subtle);\n}\n.hw-new-body {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 24px;\n text-align: center;\n}\n.hw-new-welcome {\n flex: 1;\n padding: 16px 20px;\n overflow-y: auto;\n}\n.hw-new-heading {\n font-size: 17px;\n font-weight: 600;\n color: var(--hw-text);\n margin-bottom: 6px;\n}\n.hw-new-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n margin-bottom: 24px;\n}\n.hw-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--hw-text-4);\n flex-shrink: 0;\n}\n.hw-powered a {\n color: var(--hw-text-2);\n text-decoration: none;\n font-weight: 500;\n}\n.hw-powered a:hover {\n color: var(--hw-text);\n}\n@media (max-width: 479px) {\n .hw-widget {\n bottom: 16px;\n right: 16px;\n left: auto;\n }\n .hw-window {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n height: var(--hw-visible-height, 100%);\n border-radius: 0;\n animation: hw-mob-up 0.3s cubic-bezier(0.22, 1, 0.36, 1);\n }\n .hw-window--closing {\n animation: hw-mob-down 0.2s ease forwards;\n }\n @keyframes hw-mob-up {\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n @keyframes hw-mob-down {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n }\n .hw-hero {\n padding-top: calc(20px + env(safe-area-inset-top, 0px));\n }\n .hw-header {\n padding-top: env(safe-area-inset-top, 0px);\n }\n .hw-tabs {\n padding-bottom: env(safe-area-inset-bottom, 0px);\n }\n .hw-composer {\n padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));\n }\n .hw-powered {\n padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));\n }\n .hw-header-close,\n .hw-header-back,\n .hw-header-action {\n width: 34px;\n height: 34px;\n }\n .hw-composer-send {\n width: 40px;\n height: 40px;\n }\n .hw-window ~ .hw-bubble {\n display: none;\n }\n .hw-messages {\n padding: 12px 14px;\n }\n .hw-msg {\n max-width: 82%;\n }\n .hw-msg--ai {\n max-width: 100%;\n }\n}\n.hw-preview {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n width: 300px;\n max-width: calc(100vw - 40px);\n background: var(--hw-bg);\n border: 1px solid var(--hw-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);\n animation: hw-preview-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n overflow: hidden;\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n}\n.hw-preview.hw-preview--anchored {\n position: static;\n bottom: auto;\n right: auto;\n width: 100%;\n max-width: 100%;\n}\n.hw-preview.hw-preview--anchored .hw-preview-avatar {\n background: none;\n}\n.hw-preview.hw-preview--anchored .hw-preview-avatar img,\n.hw-preview.hw-preview--anchored .hw-preview-avatar svg:not(.hw-agent-custom svg) {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n.hw-preview:hover {\n transform: translateY(-2px);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n@keyframes hw-preview-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n@keyframes hw-preview-out {\n from {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.95);\n }\n}\n.hw-preview-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 14px 0;\n}\n.hw-preview-avatar {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background:\n linear-gradient(\n 135deg,\n var(--hw-primary),\n color-mix(in srgb, var(--hw-primary) 50%, black));\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-preview-avatar svg:not(.hw-agent-custom svg) {\n width: 16px;\n height: 16px;\n}\n.hw-preview-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n.hw-preview-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--hw-text);\n flex: 1;\n}\n.hw-preview-close {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: background 0.15s, color 0.15s;\n flex-shrink: 0;\n}\n.hw-preview-close:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text-2);\n}\n.hw-preview-close:active {\n transform: scale(0.90);\n transition:\n transform 0.14s cubic-bezier(0.23, 1, 0.32, 1),\n background 0.15s,\n color 0.15s;\n}\n.hw-preview-close svg {\n width: 12px;\n height: 12px;\n}\n.hw-preview-body {\n padding: 4px 14px;\n font-size: 14px;\n line-height: 1.45;\n color: var(--hw-text-2);\n}\n.hw-preview-body:first-of-type {\n padding-top: 8px;\n}\n.hw-preview-body:last-child {\n padding-bottom: 14px;\n}\n.hw-preview-footer {\n margin-top: 2px;\n padding: 8px 14px 12px;\n border-top: 1px solid var(--hw-border);\n font-size: 11px;\n line-height: 1.3;\n color: var(--hw-text-2);\n opacity: 0.65;\n}\n.hw-preview-prompt {\n padding: 2px 14px 6px;\n font-size: 14px;\n font-weight: 500;\n color: var(--hw-text-1);\n}\n.hw-preview-quick-replies {\n padding: 0 14px 14px;\n margin-top: 0;\n}\n.hw-awaiting {\n margin-top: 2px;\n padding-left: 44px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-preview-dock {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 8px;\n pointer-events: none;\n}\n.hw-preview-dock > .hw-preview,\n.hw-preview-dock > .hw-preview-stack {\n position: relative;\n bottom: auto;\n right: auto;\n pointer-events: auto;\n}\n.hw-preview--closing {\n animation: hw-preview-out 0.2s ease-in forwards;\n}\n.hw-preview-stack {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-preview-stack .hw-preview {\n position: relative;\n bottom: auto;\n right: auto;\n}\n.hw-preview-stack.hw-preview-stack--anchored {\n position: static;\n bottom: auto;\n right: auto;\n width: 100%;\n}\n.hw-preview-more {\n align-self: flex-end;\n padding: 4px 10px;\n border: 0;\n border-radius: 999px;\n background: var(--hw-bg);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), inset 0 0 0 1px var(--hw-border);\n color: var(--hw-text-2);\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n transition: background 0.12s, color 0.12s;\n}\n.hw-preview-more:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n}\n.hw-preview--announcement {\n width: 340px;\n}\n.hw-preview--announcement .hw-preview-body--title {\n font-weight: 600;\n color: var(--hw-text);\n font-size: 15px;\n line-height: 1.3;\n padding-top: 10px;\n}\n.hw-preview--announcement .hw-preview-body--desc {\n font-size: 13px;\n color: var(--hw-text-2);\n line-height: 1.5;\n padding-bottom: 16px;\n}\n.hw-announcement-badge {\n display: inline-block;\n margin: 8px 14px 0;\n padding: 2px 8px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 10%, transparent);\n border-radius: 4px;\n}\n.hw-whats-new {\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n overflow: hidden;\n}\n.hw-whats-new-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px 0;\n}\n.hw-whats-new-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--hw-text-2);\n}\n.hw-whats-new-view-all {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-primary);\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n.hw-whats-new-view-all:hover {\n opacity: 0.8;\n}\n.hw-whats-new-list {\n display: flex;\n flex-direction: column;\n}\n.hw-whats-new-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n padding: 10px 14px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n transition: background-color 140ms ease;\n}\n.hw-whats-new-item:last-child {\n border-bottom: none;\n}\n.hw-whats-new-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n.hw-whats-new-item-top {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.hw-whats-new-badge {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--hw-primary);\n}\n.hw-whats-new-time {\n font-size: 11px;\n color: var(--hw-text-3);\n margin-left: auto;\n}\n.hw-whats-new-item-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--hw-text);\n line-height: 1.3;\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.hw-whats-new-time-inline {\n font-size: 11px;\n font-weight: 400;\n color: var(--hw-text-3);\n margin-left: auto;\n flex-shrink: 0;\n}\n.hw-whats-new-item-body {\n font-size: 12px;\n color: var(--hw-text-2);\n line-height: 1.4;\n}\n.hw-tabs-dot {\n position: absolute;\n top: -2px;\n right: -6px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--hw-primary);\n animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n.hw-bubble-badge-dot {\n display: block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: white;\n}\n.hw-content-search {\n padding: 10px 16px;\n}\n.hw-content-search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--hw-bg);\n border: 1px solid var(--hw-border-md);\n border-radius: 10px;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-content-search-box:focus-within {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n}\n.hw-content-search-input {\n flex: 1;\n border: none !important;\n outline: none !important;\n box-shadow: none !important;\n background: none;\n font-size: 13px;\n color: var(--hw-text-1);\n font-family: inherit;\n line-height: 1;\n -webkit-appearance: none;\n}\n.hw-content-search-input:focus,\n.hw-content-search-input:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n border: none !important;\n}\n.hw-content-search-input::placeholder {\n color: var(--hw-text-3);\n}\n.hw-content-search-icon {\n width: 15px;\n height: 15px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n}\n.hw-content-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.hw-content-entries {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.hw-content-entry {\n display: block;\n width: 100%;\n padding: 14px 16px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n transition: background-color 0.15s ease;\n -webkit-tap-highlight-color: transparent;\n}\n.hw-content-entry:hover {\n background: var(--hw-bg-hover);\n}\n.hw-content-entry:active {\n background: var(--hw-border);\n}\n.hw-content-entry:last-child {\n border-bottom: none;\n}\n.hw-content-entry-main {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hw-content-entry-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n.hw-content-entry-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text-1);\n line-height: 1.3;\n}\n.hw-content-entry-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.hw-content-entry-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n}\n.hw-content-entry-badge {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n background: var(--hw-bg-hover);\n padding: 1px 6px;\n border-radius: 4px;\n}\n.hw-content-entry-date {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-content-entry-chevron {\n width: 16px;\n height: 16px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n opacity: 0.5;\n}\n.hw-content-detail {\n padding: 16px;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n.hw-content-detail-header {\n margin-bottom: 16px;\n}\n.hw-content-detail-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--hw-text-1);\n margin: 0 0 6px;\n line-height: 1.3;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.hw-content-detail-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n.hw-content-detail-date {\n font-size: 12px;\n color: var(--hw-text-3);\n}\n.hw-content-detail-body {\n font-size: 14px;\n line-height: 1.6;\n color: var(--hw-text-1);\n}\n.hw-markdown h1 {\n font-size: 17px;\n font-weight: 700;\n margin: 0;\n}\n.hw-markdown h2 {\n font-size: 15px;\n font-weight: 600;\n margin: 0;\n}\n.hw-markdown h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 0;\n}\n.hw-markdown p {\n margin: 0;\n}\n.hw-markdown p:empty,\n.hw-markdown div:empty,\n.hw-markdown p:has(> br:only-child),\n.hw-markdown div:has(> br:only-child) {\n display: none;\n}\n.hw-markdown > * + * {\n margin-top: 12px;\n}\n.hw-markdown > * + h1,\n.hw-markdown > * + h2 {\n margin-top: 20px;\n}\n.hw-markdown > * + h3 {\n margin-top: 16px;\n}\n.hw-markdown > h1 + *,\n.hw-markdown > h2 + *,\n.hw-markdown > h3 + * {\n margin-top: 8px;\n}\n.hw-markdown > *:first-child {\n margin-top: 0;\n}\n.hw-markdown > *:last-child {\n margin-bottom: 0;\n}\n.hw-markdown > br {\n display: none;\n}\n.hw-markdown ul,\n.hw-markdown ol {\n margin: 0;\n padding-left: 20px;\n}\n.hw-markdown li {\n margin: 4px 0;\n}\n.hw-markdown code {\n font-family:\n ui-monospace,\n "SF Mono",\n monospace;\n font-size: 12px;\n background: var(--hw-bg-hover);\n padding: 1px 5px;\n border-radius: 4px;\n}\n.hw-table-wrap {\n margin: 10px 0;\n overflow-x: auto;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n border-radius: 10px;\n}\n.hw-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.hw-table th {\n text-align: left;\n font-weight: 600;\n font-size: 12px;\n padding: 8px 12px;\n background: var(--hw-bg-hover, #f5f5f4);\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n}\n.hw-table td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\n vertical-align: top;\n}\n.hw-table tbody tr:last-child td {\n border-bottom: none;\n}\n.hw-code {\n margin: 10px 0;\n border-radius: 10px;\n overflow: hidden;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n background: var(--hw-bg-hover, #f5f5f4);\n font-family:\n ui-monospace,\n "SF Mono",\n "Menlo",\n monospace;\n}\n.hw-code-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 7px 8px 7px 12px;\n font-size: 11px;\n color: var(--hw-text-2, #6b7280);\n background: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\n}\n.hw-code-lang {\n text-transform: lowercase;\n letter-spacing: 0.02em;\n font-weight: 500;\n}\n.hw-code-actions {\n display: inline-flex;\n align-items: center;\n gap: 1px;\n}\n.hw-code-action {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n padding: 0;\n font-family: inherit;\n color: var(--hw-text-2, #6b7280);\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0.62;\n transition:\n background 120ms ease,\n color 120ms ease,\n opacity 120ms ease,\n scale 120ms ease;\n}\n.hw-code-action:hover {\n color: var(--hw-text, #111);\n background: rgba(0, 0, 0, 0.06);\n opacity: 1;\n}\n.hw-code-action:active {\n scale: 0.96;\n}\n.hw-code-action svg {\n width: 13px;\n height: 13px;\n}\n.hw-code-copy-icon,\n.hw-code-check-icon {\n position: absolute;\n inset: 50% auto auto 50%;\n transition:\n opacity 180ms cubic-bezier(0.2, 0, 0, 1),\n scale 180ms cubic-bezier(0.2, 0, 0, 1),\n filter 180ms cubic-bezier(0.2, 0, 0, 1);\n translate: -50% -50%;\n}\n.hw-code-check-icon {\n filter: blur(4px);\n opacity: 0;\n scale: 0.25;\n}\n.hw-code-copy--copied .hw-code-copy-icon {\n filter: blur(4px);\n opacity: 0;\n scale: 0.25;\n}\n.hw-code-copy--copied .hw-code-check-icon {\n filter: blur(0);\n opacity: 1;\n scale: 1;\n}\n.hw-code-copy-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n}\n.hw-code-copy--copied {\n color: #16a34a;\n}\n.hw-code-copy--failed {\n color: #dc2626;\n}\n.hw-code pre {\n margin: 0;\n padding: 10px 12px;\n background: transparent;\n border-radius: 0;\n overflow-x: auto;\n max-width: 100%;\n max-height: 320px;\n scrollbar-color: rgba(0, 0, 0, 0.22) transparent;\n scrollbar-width: thin;\n}\n.hw-code pre::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n.hw-code pre::-webkit-scrollbar-track {\n background: transparent;\n}\n.hw-code pre::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.18);\n background-clip: content-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n.hw-code pre::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.28);\n background-clip: content-box;\n}\n.hw-code pre code {\n display: block;\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.55;\n white-space: pre;\n color: var(--hw-text, #111);\n}\n@media (prefers-color-scheme: dark) {\n .hw-code {\n background: rgba(255, 255, 255, 0.04);\n border-color: rgba(255, 255, 255, 0.08);\n }\n .hw-code-header {\n background: rgba(255, 255, 255, 0.03);\n border-bottom-color: rgba(255, 255, 255, 0.06);\n }\n .hw-code-action:hover,\n .hw-code-action:focus-visible {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-code pre {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n }\n .hw-code pre::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.22);\n background-clip: content-box;\n }\n .hw-code pre::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n }\n}\n.hw-markdown pre {\n margin: 8px 0;\n padding: 10px 12px;\n background: var(--hw-bg-hover);\n border-radius: 8px;\n overflow-x: auto;\n max-width: 100%;\n}\n.hw-markdown pre code {\n display: block;\n background: transparent;\n padding: 0;\n border-radius: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n word-break: normal;\n color: inherit;\n}\n.hw-msg-bubble pre {\n margin: 6px 0;\n padding: 8px 10px;\n background: rgba(0, 0, 0, 0.06);\n border-radius: 6px;\n overflow-x: auto;\n max-width: 100%;\n}\n.hw-msg-bubble pre code {\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n}\n.hw-msg-bubble .hw-code pre {\n margin: 0;\n padding: 10px 12px;\n background: transparent;\n border-radius: 0;\n}\n.hw-msg-bubble .hw-code pre code {\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.55;\n}\n.hw-msg--team .hw-msg-bubble pre,\n.hw-msg--visitor .hw-msg-bubble pre {\n background: rgba(255, 255, 255, 0.12);\n}\n.hw-markdown blockquote {\n margin: 0 0 12px;\n padding: 8px 12px;\n border-left: 3px solid var(--hw-border);\n color: var(--hw-text-2);\n font-style: italic;\n}\n.hw-markdown a {\n color: var(--hw-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.hw-markdown img {\n max-width: 100%;\n border-radius: 8px;\n margin: 8px 0;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-markdown hr {\n border: none;\n border-top: 1px solid var(--hw-border);\n margin: 16px 0;\n}\n.hw-content-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n.hw-content-empty-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text-1);\n margin-bottom: 4px;\n}\n.hw-content-empty-desc {\n font-size: 12px;\n color: var(--hw-text-3);\n}\n.hw-content-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n.hw-content-load-more {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: none;\n color: var(--hw-primary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n text-align: center;\n}\n.hw-content-load-more:hover {\n background: var(--hw-bg-hover);\n}\n.hw-content-load-more:disabled {\n opacity: 0.5;\n cursor: default;\n}\n@media (hover: none) {\n .hw-composer-preview-remove {\n opacity: 0.7;\n }\n}\n.hw-composer--dragging .hw-composer-box {\n border-color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 4%, transparent);\n}\n.hw-composer-drop-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--hw-bg) 90%, transparent);\n border: 2px dashed var(--hw-primary);\n border-radius: 12px;\n z-index: 10;\n pointer-events: none;\n animation: hw-drop-pulse 1.5s ease-in-out infinite;\n}\n.hw-composer-drop-text {\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-primary);\n}\n@keyframes hw-drop-pulse {\n 0%, 100% {\n opacity: 0.8;\n }\n 50% {\n opacity: 1;\n }\n}\n.hw-disconnect {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 7px;\n padding: 7px 14px;\n background: var(--hw-bg-hover);\n color: var(--hw-text-2);\n font-size: 11.5px;\n font-weight: 500;\n letter-spacing: -0.01em;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n animation: hw-disconnect-in 0.18s cubic-bezier(0.22, 1, 0.36, 1);\n}\n@keyframes hw-disconnect-in {\n from {\n opacity: 0;\n transform: translateY(-100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-disconnect-spinner {\n width: 9px;\n height: 9px;\n border: 1.5px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n opacity: 0.75;\n flex-shrink: 0;\n animation: hw-spin 0.7s linear infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-disconnect {\n animation: none;\n }\n .hw-disconnect-spinner {\n animation: none;\n border-top-color: currentColor;\n opacity: 0.5;\n }\n}\n.hw-error-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 24px;\n text-align: center;\n gap: 12px;\n}\n.hw-error-icon {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: #fef2f2;\n color: #ef4444;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-error-icon svg {\n width: 24px;\n height: 24px;\n}\n.hw-error-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-error-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n}\n.hw-error-btn {\n padding: 8px 20px;\n border: 1px solid var(--hw-border-md);\n border-radius: 8px;\n background: var(--hw-bg);\n color: var(--hw-text);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n.hw-error-btn:hover {\n background: var(--hw-bg-hover);\n}\n.hw-send-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #fef2f2;\n color: #dc2626;\n font-size: 12px;\n font-weight: 500;\n flex-shrink: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-send-error-retry {\n margin-left: auto;\n padding: 2px 8px;\n border: 1px solid #fca5a5;\n border-radius: 4px;\n background: none;\n color: #dc2626;\n font-size: 11px;\n font-weight: 600;\n cursor: pointer;\n}\n.hw-send-error-retry:hover {\n background: #fee2e2;\n}\n.hw-resolved {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid var(--hw-border);\n flex-shrink: 0;\n}\n.hw-resolved-text {\n font-size: 13px;\n color: var(--hw-text-3);\n font-weight: 500;\n}\n.hw-resolved-actions {\n display: flex;\n gap: 8px;\n}\n.hw-resolved-reopen {\n padding: 6px 16px;\n border: 1px solid var(--hw-border-md);\n border-radius: 8px;\n background: var(--hw-bg);\n color: var(--hw-text);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n.hw-resolved-reopen:hover {\n background: var(--hw-bg-hover);\n}\n.hw-csat {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n.hw-csat-label {\n font-size: 12px;\n color: var(--hw-text-3);\n}\n.hw-csat-buttons {\n display: flex;\n gap: 8px;\n}\n.hw-csat-btn {\n width: 36px;\n height: 36px;\n border: 1px solid var(--hw-border-md);\n border-radius: 8px;\n background: var(--hw-bg);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n transition:\n transform 0.15s,\n border-color 0.15s,\n background 0.15s;\n}\n.hw-csat-btn:hover {\n transform: scale(1.1);\n border-color: var(--hw-text-3);\n}\n.hw-csat-btn--selected {\n border-color: var(--hw-primary);\n background: var(--hw-bg-hover);\n transform: scale(1.15);\n}\n.hw-csat-thanks {\n font-size: 12px;\n color: #22c55e;\n font-weight: 500;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-load-more-trigger {\n display: flex;\n justify-content: center;\n min-height: 1px;\n}\n.hw-load-more-trigger:has(.hw-load-more-spinner) {\n padding: 8px 0;\n}\n.hw-load-more-spinner {\n display: flex;\n gap: 3px;\n}\n.hw-load-more-spinner > div {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--hw-text-4);\n animation: hw-loading-pulse 1.4s infinite;\n}\n.hw-load-more-spinner > div:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-load-more-spinner > div:nth-child(3) {\n animation-delay: 0.4s;\n}\n.hw-drag-handle {\n display: none;\n}\n@media (max-width: 479px) {\n .hw-drag-handle {\n display: flex;\n justify-content: center;\n padding: 8px 0 4px;\n flex-shrink: 0;\n }\n .hw-drag-handle-pill {\n width: 32px;\n height: 4px;\n border-radius: 2px;\n background: var(--hw-text-4);\n }\n}\n.hw-msg-bubble p {\n margin: 0 0 8px;\n}\n.hw-msg-bubble p:last-child {\n margin-bottom: 0;\n}\n.hw-msg-bubble strong {\n font-weight: 600;\n}\n.hw-msg-bubble em {\n font-style: italic;\n}\n.hw-msg-bubble a {\n color: inherit;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);\n word-break: normal;\n overflow-wrap: anywhere;\n}\n.hw-msg-bubble a:hover {\n opacity: 0.8;\n}\n.hw-msg--visitor .hw-msg-bubble a {\n color: rgba(255, 255, 255, 0.9);\n}\n.hw-msg--visitor .hw-msg-bubble a:hover {\n color: white;\n}\n.hw-msg-bubble ul,\n.hw-msg-bubble ol {\n margin: 4px 0 8px;\n padding-left: 20px;\n}\n.hw-msg-bubble li {\n margin: 2px 0;\n}\n.hw-msg-bubble code {\n padding: 1px 4px;\n border-radius: 3px;\n background: rgba(0, 0, 0, 0.06);\n font-size: 0.9em;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n}\n.hw-msg-bubble pre {\n margin: 4px 0 8px;\n padding: 8px 10px;\n border-radius: 6px;\n background: rgba(0, 0, 0, 0.06);\n overflow-x: auto;\n font-size: 0.85em;\n}\n.hw-msg-bubble pre code {\n padding: 0;\n background: none;\n}\n.hw-msg-bubble blockquote {\n margin: 4px 0 8px;\n padding: 4px 0 4px 12px;\n border-left: 3px solid var(--hw-border-md);\n color: var(--hw-text-2);\n}\n.hw-widget[data-theme=dark] {\n --hw-bg: #1c1c1e;\n --hw-bg-subtle: #161618;\n --hw-bg-hover: #2c2c2e;\n --hw-border: rgba(255, 255, 255, 0.08);\n --hw-border-md: rgba(255, 255, 255, 0.14);\n --hw-text: #f5f5f5;\n --hw-text-1: #f5f5f5;\n --hw-text-2: #a1a1aa;\n --hw-text-3: #71717a;\n --hw-text-4: #52525b;\n --hw-visitor-bubble-bg: #2c2c2e;\n --hw-visitor-bubble-text: #f5f5f5;\n --hw-focus-border: rgba(255, 255, 255, 0.28);\n --hw-focus-ring: rgba(255, 255, 255, 0.08);\n --hw-brand: #f5f5f5;\n --hw-on-brand: #1c1c1e;\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light]) .hw-messages {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n }\n .hw-widget:not([data-theme=light]) .hw-messages::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n background-clip: content-box;\n }\n .hw-widget:not([data-theme=light]) .hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n }\n .hw-widget:not([data-theme=light]) {\n --hw-bg: #1c1c1e;\n --hw-bg-subtle: #161618;\n --hw-bg-hover: #2c2c2e;\n --hw-border: rgba(255, 255, 255, 0.08);\n --hw-border-md: rgba(255, 255, 255, 0.14);\n --hw-text: #f5f5f5;\n --hw-text-1: #f5f5f5;\n --hw-text-2: #a1a1aa;\n --hw-text-3: #71717a;\n --hw-text-4: #52525b;\n --hw-visitor-bubble-bg: #2c2c2e;\n --hw-visitor-bubble-text: #f5f5f5;\n --hw-focus-border: rgba(255, 255, 255, 0.28);\n --hw-focus-ring: rgba(255, 255, 255, 0.08);\n --hw-brand: #f5f5f5;\n --hw-on-brand: #1c1c1e;\n }\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light]) .hw-header {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-header-bot-icon {\n background: var(--hw-bg-hover);\n }\n .hw-header-name,\n .hw-header-title {\n color: var(--hw-text);\n }\n .hw-header-status {\n color: var(--hw-text-2);\n }\n .hw-header-close,\n .hw-header-back {\n color: var(--hw-text-2);\n }\n .hw-header-close:hover,\n .hw-header-back:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n }\n .hw-content-entry {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-content-entry:hover {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border-md);\n }\n .hw-content-empty,\n .hw-empty {\n color: var(--hw-text-3);\n }\n .hw-conv-card {\n border-color: var(--hw-border);\n }\n .hw-recent-row {\n border-color: var(--hw-border);\n }\n .hw-composer-drop-overlay {\n background: rgba(0, 0, 0, 0.6);\n color: var(--hw-text);\n }\n .hw-composer--dragging .hw-composer-box {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n }\n .hw-hero {\n background:\n linear-gradient(\n 160deg,\n color-mix(in srgb, var(--hw-primary) 40%, black) 0%,\n var(--hw-primary) 50%,\n color-mix(in srgb, var(--hw-primary) 25%, black) 100%);\n }\n .hw-sheet {\n background: var(--hw-bg);\n }\n .hw-card {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border);\n }\n .hw-card:hover {\n background: #333;\n }\n .hw-window {\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n .hw-bubble:focus-visible {\n outline-color: var(--hw-text-3);\n }\n .hw-msg--visitor .hw-msg-bubble {\n background: var(--hw-primary);\n color: white;\n }\n .hw-msg-bubble code {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-msg-bubble pre {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-composer-box {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-composer-input {\n color: var(--hw-text);\n }\n .hw-tabs {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-conv-card:hover,\n .hw-recent-row:hover {\n background: var(--hw-bg-hover);\n }\n .hw-send-error {\n background: #450a0a;\n color: #fca5a5;\n }\n .hw-error-icon {\n background: #450a0a;\n color: #f87171;\n }\n .hw-resolved {\n border-color: var(--hw-border);\n }\n .hw-resolved-reopen,\n .hw-csat-btn {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border-md);\n color: var(--hw-text);\n }\n .hw-hover-preview {\n background: #1c1c1e;\n border-color: var(--hw-border);\n }\n .hw-content-search-box {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border-md);\n }\n .hw-preview {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n}\n.hw-widget[data-hw-placement=docked] {\n --hw-dock-width: 600px;\n --hw-dock-bar-width: 480px;\n --hw-dock-inset: 24px;\n --hw-bar-max-height: 148px;\n --hw-dock-surface: #ffffff;\n --hw-dock-on-surface: #111111;\n --hw-dock-pill-bg: rgba(44, 44, 48, 0.66);\n --hw-dock-pill-fg: rgba(255, 255, 255, 0.94);\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\n}\n.hw-widget[data-hw-placement=docked] {\n z-index: 2147483000;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock {\n position: fixed;\n left: 0;\n right: 0;\n bottom: var(--hw-dock-inset);\n z-index: 2147483000;\n display: flex;\n flex-direction: column;\n align-items: center;\n pointer-events: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock > * {\n pointer-events: auto;\n}\n.hw-dock-suggestions {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 9px;\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n margin-bottom: 14px;\n}\n.hw-dock-pill-row {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n animation: hw-dock-pill-in 0.42s cubic-bezier(0.2, 0.9, 0.3, 1) both;\n}\n.hw-dock-pill-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n padding: 0;\n border: 0;\n background: none;\n color: var(--hw-dock-pill-fg);\n cursor: pointer;\n align-self: flex-start;\n margin-top: 8px;\n opacity: 0;\n transform: scale(0.85);\n transition:\n opacity 0.12s linear,\n transform 0.12s cubic-bezier(0.25, 1, 0.5, 1),\n color 0.12s linear;\n}\n.hw-dock-pill-dismiss svg {\n width: 11px;\n height: 11px;\n}\n.hw-dock-suggestions:hover .hw-dock-pill-dismiss,\n.hw-dock-suggestions:focus-within .hw-dock-pill-dismiss {\n opacity: 1;\n transform: none;\n}\n.hw-dock-pill-dismiss:hover {\n color: var(--hw-dock-on-surface);\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-pill-dismiss {\n transition: none;\n }\n}\n@media (hover: none) {\n .hw-dock-pill-dismiss {\n opacity: 1;\n transform: none;\n }\n}\n.hw-dock-pill {\n align-self: flex-start;\n padding: 10px 18px;\n border: 1px solid var(--hw-dock-pill-border, transparent);\n border-radius: 999px;\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 500;\n text-align: left;\n background: var(--hw-dock-pill-bg);\n color: var(--hw-dock-pill-fg);\n backdrop-filter: blur(10px) saturate(1.2);\n -webkit-backdrop-filter: blur(10px) saturate(1.2);\n box-shadow: 0 4px 14px -8px rgba(12, 11, 10, 0.28);\n transition:\n background 0.16s,\n border-color 0.16s,\n transform 0.16s;\n}\n.hw-dock-pill {\n backdrop-filter: blur(18px);\n -webkit-backdrop-filter: blur(18px);\n}\n.hw-dock-pill:hover {\n background: color-mix(in srgb, var(--hw-dock-pill-bg) 100%, var(--hw-dock-on-surface) 8%);\n border-color: color-mix(in srgb, var(--hw-dock-pill-border) 100%, var(--hw-dock-on-surface) 10%);\n transform: translateX(3px);\n}\n@keyframes hw-dock-pill-in {\n from {\n opacity: 0;\n transform: translateY(10px) scale(0.97);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-dock-bar {\n display: flex;\n align-items: flex-end;\n gap: 10px;\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n min-height: 52px;\n padding: 10px 10px 10px 18px;\n border: 0;\n border-radius: 26px;\n background: var(--hw-dock-surface);\n color: var(--hw-dock-on-surface);\n box-shadow:\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\n 0 0 0 1px color-mix(in srgb, var(--hw-dock-on-surface) 7%, transparent),\n 0 2px 6px rgba(12, 11, 10, 0.18),\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\n transition:\n border-radius 0.18s ease,\n box-shadow 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),\n width 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.hw-dock-bar:focus-within {\n box-shadow:\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\n 0 0 0 1px color-mix(in srgb, var(--hw-primary, #fb923c) 60%, transparent),\n 0 2px 6px rgba(12, 11, 10, 0.18),\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\n}\n.hw-dock-bar[data-grown=true] {\n border-radius: 20px;\n}\n.hw-dock-input {\n flex: 1;\n min-width: 0;\n min-height: 20px;\n max-height: var(--hw-bar-max-height);\n padding: 6px 0;\n border: 0;\n outline: none;\n resize: none;\n overflow-y: auto;\n background: transparent;\n color: var(--hw-dock-on-surface);\n font: inherit;\n font-size: 14px;\n line-height: 1.45;\n transition: height 0.12s ease;\n}\n.hw-dock-input::placeholder {\n color: color-mix(in srgb, var(--hw-dock-on-surface) 45%, transparent);\n}\n.hw-dock-send {\n flex: none;\n width: 32px;\n height: 32px;\n margin-bottom: 1px;\n border: 0;\n border-radius: 50%;\n display: grid;\n place-items: center;\n cursor: pointer;\n background: var(--hw-primary, #fb923c);\n color: var(--hw-on-brand, #fff);\n transition: transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.16s;\n}\n.hw-dock-send:hover:not(:disabled) {\n transform: scale(1.06);\n}\n.hw-dock-send:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n position: fixed;\n left: 50%;\n right: auto;\n margin-left: calc(var(--hw-dock-width) / -2);\n bottom: calc(var(--hw-dock-inset) + 66px);\n width: var(--hw-dock-width);\n max-width: calc(100vw - 32px);\n height: 420px;\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n left: 16px;\n right: 16px;\n margin-left: 0;\n width: auto;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-bubble {\n display: none;\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-window {\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-suggestions {\n display: none;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-pill,\n .hw-dock-bar,\n .hw-dock-input,\n .hw-dock-send {\n animation: none;\n transition: none;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-composer,\n.hw-widget[data-hw-placement=docked] .hw-tabs,\n.hw-widget[data-hw-placement=docked] .hw-footer-tabs {\n display: none;\n}\n.hw-starters {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n border-radius: 14px;\n overflow: hidden;\n background: var(--hw-bg);\n box-shadow: inset 0 0 0 1px var(--hw-border);\n}\n.hw-starter {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 11px 14px;\n border: 0;\n border-radius: 0;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text);\n font: inherit;\n text-align: left;\n animation: hw-starter-in 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) both;\n transition: background 0.12s;\n}\n.hw-starter + .hw-starter {\n box-shadow: inset 0 1px 0 var(--hw-border);\n}\n.hw-starter:hover {\n background: var(--hw-bg-hover);\n}\n.hw-starter-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.hw-starter-k {\n font-size: 13px;\n font-weight: 550;\n line-height: 1.35;\n color: var(--hw-text);\n}\n.hw-starter-q {\n font-size: 12px;\n line-height: 1.35;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-starter svg {\n flex: none;\n color: var(--hw-text-3, var(--hw-text-muted));\n opacity: 0.45;\n transition: opacity 0.15s, transform 0.15s;\n}\n.hw-starter:hover svg {\n opacity: 0.9;\n transform: translateX(2px);\n}\n@keyframes hw-starter-in {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-header-back {\n display: none;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-starter {\n animation: none;\n }\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light])[data-hw-placement=docked] {\n --hw-dock-surface: #1f1f23;\n --hw-dock-on-surface: #f4f4f6;\n --hw-dock-pill-bg: rgba(255, 255, 255, 0.1);\n --hw-dock-pill-fg: #e4e4e7;\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\n }\n}\n.hw-widget[data-theme=dark][data-hw-placement=docked] {\n --hw-dock-surface: #1f1f23;\n --hw-dock-on-surface: #f4f4f6;\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n --hw-bg: rgba(255, 255, 255, 0.08);\n --hw-bg-subtle: transparent;\n --hw-bg-hover: rgba(255, 255, 255, 0.1);\n --hw-border: rgba(255, 255, 255, 0.14);\n --hw-border-md: rgba(255, 255, 255, 0.22);\n --hw-text: rgba(255, 255, 255, 0.94);\n --hw-text-1: #ffffff;\n --hw-text-2: rgba(255, 255, 255, 0.72);\n --hw-text-3: rgba(255, 255, 255, 0.62);\n --hw-text-4: rgba(255, 255, 255, 0.46);\n --hw-visitor-bubble-bg: rgba(255, 255, 255, 0.16);\n --hw-visitor-bubble-text: #ffffff;\n --hw-brand: rgba(255, 255, 255, 0.92);\n --hw-on-brand: #17161a;\n --hw-focus-border: rgba(255, 255, 255, 0.34);\n --hw-focus-ring: rgba(255, 255, 255, 0.1);\n height: 500px;\n max-height: calc(100vh - 180px);\n border-radius: 24px;\n color: var(--hw-text);\n background:\n linear-gradient(\n 180deg,\n rgba(40, 40, 44, 0.72) 0%,\n rgba(46, 46, 50, 0.7) 55%,\n rgba(52, 52, 56, 0.68) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n background: #2c2c2e;\n }\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n height: min(60vh, 460px);\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-header--sub {\n padding: 14px 12px 8px 16px;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-status {\n display: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-name {\n font-size: 15.5px;\n font-weight: 560;\n letter-spacing: -0.006em;\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu-conv-name,\n.hw-widget[data-hw-placement=docked] .hw-event-name {\n font-weight: 545;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-bot-icon {\n border-radius: 50%;\n overflow: hidden;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-close:hover,\n.hw-widget[data-hw-placement=docked] .hw-header-menu-btn:hover {\n background: rgba(255, 255, 255, 0.12);\n color: #ffffff;\n}\n.hw-widget[data-hw-placement=docked] .hw-messages {\n padding: 4px 22px 16px;\n gap: 18px;\n -webkit-mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 16px);\n mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 16px);\n}\n.hw-widget[data-hw-placement=docked] .hw-msg--ai .hw-msg-bubble,\n.hw-widget[data-hw-placement=docked] .hw-msg--team .hw-msg-bubble {\n padding: 0;\n background: transparent;\n border-radius: 0;\n font-size: 15px;\n line-height: 1.55;\n color: var(--hw-text);\n}\n.hw-widget[data-hw-placement=docked] .hw-msg--visitor .hw-msg-bubble {\n background: rgba(255, 255, 255, 0.16);\n color: #ffffff;\n font-size: 14.5px;\n line-height: 1.5;\n}\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble pre,\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble code {\n background: rgba(0, 0, 0, 0.28);\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-row {\n background: rgba(0, 0, 0, 0.26);\n border-color: rgba(255, 255, 255, 0.14);\n}\n.hw-widget[data-hw-placement=docked] .hw-window :focus-visible {\n outline-color: rgba(255, 255, 255, 0.55);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus,\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus-visible {\n outline: none;\n box-shadow: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-row:focus-within {\n border-color: rgba(255, 255, 255, 0.42);\n box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.08);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-submit {\n background: #ffffff;\n color: #17161a;\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\n position: relative;\n z-index: 3;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu {\n background: #3a3a3f;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 18px 44px -12px rgba(12, 11, 10, 0.62);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu button:hover {\n background: rgba(255, 255, 255, 0.11);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu button.hw-header-menu-conv[data-active=true] {\n background: rgba(255, 255, 255, 0.09);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu-convs {\n border-bottom-color: rgba(255, 255, 255, 0.12);\n}\n.hw-widget[data-hw-placement=docked] .hw-event--card {\n margin: 0;\n background: rgba(255, 255, 255, 0.08);\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);\n}\n.hw-widget[data-hw-placement=docked] .hw-event-avatar {\n background: rgba(255, 255, 255, 0.14);\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview {\n position: fixed;\n left: 50%;\n right: auto;\n margin-left: calc(var(--hw-dock-bar-width, var(--hw-dock-width)) / -2);\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n border: 0;\n border-radius: 24px;\n color: rgba(255, 255, 255, 0.94);\n background:\n linear-gradient(\n 180deg,\n rgba(40, 40, 44, 0.74) 0%,\n rgba(52, 52, 56, 0.7) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-name,\n.hw-widget[data-hw-placement=docked] .hw-preview-body {\n color: rgba(255, 255, 255, 0.94);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-close {\n color: rgba(255, 255, 255, 0.6);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-close:hover {\n background: rgba(255, 255, 255, 0.12);\n color: #ffffff;\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-footer {\n color: rgba(255, 255, 255, 0.55);\n border-top-color: rgba(255, 255, 255, 0.1);\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-preview {\n left: 16px;\n right: 16px;\n margin-left: 0;\n width: auto;\n }\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-preview {\n background: #2c2c2e;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn {\n padding: 7px 14px;\n font-size: 13px;\n font-weight: 550;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.94);\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\n color: #17161a;\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn:hover:not(:disabled) {\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\n transform: translateY(-1px);\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn[data-tapped=true] {\n background: rgba(255, 255, 255, 0.22);\n color: #ffffff;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);\n transform: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn svg {\n opacity: 0.55;\n}\n.hw-widget[data-hw-placement=docked] .hw-offer {\n padding: 7px 14px;\n font-size: 13px;\n background: rgba(255, 255, 255, 0.94);\n color: #17161a;\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\n transition:\n background 0.15s,\n box-shadow 0.15s,\n transform 0.15s;\n}\n.hw-widget[data-hw-placement=docked] .hw-offer:hover {\n background: #ffffff;\n color: #17161a;\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\n transform: translateY(-1px);\n}\n.hw-widget[data-hw-placement=docked] .hw-offer svg {\n opacity: 0.55;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-bar {\n --hw-dock-on-surface: rgba(255, 255, 255, 0.94);\n color: rgba(255, 255, 255, 0.94);\n background:\n linear-gradient(\n 180deg,\n rgba(44, 44, 48, 0.74) 0%,\n rgba(52, 52, 56, 0.72) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 18px 40px -16px rgba(12, 11, 10, 0.45);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\n width: var(--hw-dock-width);\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-bar:focus-within {\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.26), 0 18px 40px -16px rgba(12, 11, 10, 0.5);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14), 0 22px 52px -18px rgba(12, 11, 10, 0.52);\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-send:not(:disabled) {\n background: #ffffff;\n color: #17161a;\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-dock-bar {\n background: #2c2c2e;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n transform-origin: 50% 100%;\n animation: hw-dock-panel-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n}\n.hw-widget[data-hw-placement=docked] .hw-window--closing {\n animation: hw-dock-panel-out 0.18s cubic-bezier(0.4, 0, 1, 1) forwards;\n}\n@keyframes hw-dock-panel-in {\n from {\n opacity: 0;\n transform: translateY(14px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@keyframes hw-dock-panel-out {\n from {\n opacity: 1;\n transform: none;\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.99);\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\n animation: hw-dock-settle 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.06s both;\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\n animation: hw-dock-settle 0.34s cubic-bezier(0.16, 1, 0.3, 1) 0.11s both;\n}\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-header--sub,\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-messages {\n animation: none;\n}\n@keyframes hw-dock-settle {\n from {\n opacity: 0;\n transform: translateY(7px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-widget[data-hw-placement=docked] .hw-window,\n .hw-widget[data-hw-placement=docked] .hw-window--closing,\n .hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub,\n .hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\n animation: none;\n }\n}\n.hw-dock-bar {\n flex-wrap: wrap;\n padding-left: 18px;\n padding-right: 8px;\n}\n.hw-dock-error {\n width: var(--hw-dock-width);\n max-width: calc(100vw - 32px);\n margin-bottom: 8px;\n padding: 8px 14px;\n border-radius: 14px;\n background: rgba(190, 24, 40, 0.92);\n color: #ffffff;\n font-size: 12.5px;\n line-height: 1.35;\n box-shadow: 0 10px 26px -12px rgba(12, 11, 10, 0.5);\n animation: hw-dock-settle 0.22s cubic-bezier(0.16, 1, 0.3, 1) both;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-error {\n animation: none;\n }\n}\n.hw-dock-previews {\n flex: 0 0 100%;\n order: -1;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 2px 0 8px;\n}\n.hw-dock-lead {\n flex: none;\n display: grid;\n place-items: center;\n width: 32px;\n height: 32px;\n margin-left: -8px;\n}\n.hw-dock-actions {\n flex: none;\n display: flex;\n align-items: center;\n gap: 2px;\n margin-bottom: 1px;\n}\n.hw-dock-tool {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 0;\n border-radius: 50%;\n background: transparent;\n color: color-mix(in srgb, var(--hw-dock-on-surface) 52%, transparent);\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n.hw-dock-tool:hover:not(:disabled) {\n background: color-mix(in srgb, var(--hw-dock-on-surface) 8%, transparent);\n color: var(--hw-dock-on-surface);\n}\n.hw-dock-tool:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.hw-dock-tool[data-active=true] {\n color: #e11d48;\n background: rgba(225, 29, 72, 0.12);\n animation: hw-dock-listening 1.4s ease-in-out infinite;\n}\n@keyframes hw-dock-listening {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(225, 29, 72, 0.35);\n }\n 50% {\n box-shadow: 0 0 0 4px rgba(225, 29, 72, 0);\n }\n}\n.hw-dock-send:disabled {\n opacity: 1;\n background: color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent);\n color: color-mix(in srgb, var(--hw-dock-on-surface) 38%, transparent);\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-tool[data-active=true] {\n animation: none;\n }\n .hw-dock-bar {\n transition: none;\n }\n}\n.hw-dock-input:focus,\n.hw-dock-input:focus-visible {\n outline: none;\n box-shadow: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-powered {\n display: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-disconnect {\n border-radius: 20px 20px 0 0;\n}\n.hw-msg-meta {\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.hw-msg-author {\n font-weight: 550;\n}\n.hw-msg-meta-sep {\n opacity: 0.55;\n}\n.hw-header-actions {\n position: relative;\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.hw-header-menu-btn {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text-2, var(--hw-text-muted));\n transition: background 0.15s, color 0.15s;\n}\n.hw-header-menu-btn:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n}\n.hw-header-menu {\n position: absolute;\n top: 36px;\n right: 0;\n z-index: 6;\n min-width: 236px;\n max-width: 288px;\n padding: 5px;\n border-radius: 14px;\n background: var(--hw-bg);\n color: var(--hw-text);\n box-shadow: 0 0 0 1px var(--hw-border), 0 12px 32px -10px rgba(0, 0, 0, 0.32);\n animation: hw-menu-in 0.16s cubic-bezier(0.2, 0.8, 0.2, 1) both;\n}\n@keyframes hw-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-header-menu button {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n border-radius: 9px;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text);\n font: inherit;\n font-size: 13px;\n text-align: left;\n transition: background 0.14s;\n}\n.hw-header-menu button:hover {\n background: var(--hw-bg-hover);\n}\n.hw-header-menu button svg {\n flex: none;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-header-menu button:hover svg {\n color: var(--hw-brand, var(--hw-primary));\n}\n.hw-header-menu-convs {\n display: flex;\n flex-direction: column;\n max-height: 168px;\n overflow-y: auto;\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px solid var(--hw-border);\n}\n.hw-header-menu button.hw-header-menu-conv {\n flex-direction: column;\n align-items: stretch;\n gap: 2px;\n padding: 8px 10px;\n}\n.hw-header-menu button.hw-header-menu-conv[data-active=true] {\n background: var(--hw-bg-hover);\n}\n.hw-header-menu-conv-top {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n}\n.hw-header-menu-conv-name {\n overflow: hidden;\n font-size: 12.5px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.hw-header-menu-conv-time {\n flex: none;\n font-size: 11px;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-header-menu-conv-preview {\n overflow: hidden;\n font-size: 12px;\n color: var(--hw-text-2);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.hw-offers {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 10px;\n}\n.hw-offer {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n border: 0;\n border-radius: 999px;\n cursor: pointer;\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n font: inherit;\n font-size: 12.5px;\n font-weight: 550;\n transition: background 0.15s, color 0.15s;\n}\n.hw-offer:hover {\n background: var(--hw-brand, var(--hw-primary));\n color: var(--hw-on-brand, #fff);\n}\n.hw-offer svg {\n flex: none;\n}\n.hw-sources {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 8px;\n}\n.hw-source {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 7px 10px;\n border-radius: 9px;\n background: transparent;\n color: var(--hw-text);\n text-decoration: none;\n transition: background 0.15s;\n}\na.hw-source {\n cursor: pointer;\n}\na.hw-source:hover {\n background: var(--hw-bg-hover);\n}\n.hw-source-n {\n display: grid;\n place-items: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 4px;\n background: var(--hw-brand, var(--hw-primary));\n color: var(--hw-on-brand, #fff);\n font-size: 10px;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n}\n.hw-source-title {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n font-weight: 550;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n');
|
|
7772
|
+
styleInject(':host {\n all: initial;\n font-family:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #1a1a1a;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.hw-widget {\n font-family:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #1a1a1a;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.hw-widget *,\n.hw-widget *::before,\n.hw-widget *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n.hw-widget :where(p, li, strong, b, em, i, u, s, small, a, code, pre, blockquote, h1, h2, h3, h4, h5, h6) {\n color: inherit;\n}\n:where(.hw-widget) {\n --hw-primary: #171717;\n --hw-primary-hover: #2a2a2a;\n --hw-brand: #171717;\n --hw-on-brand: #ffffff;\n --hw-focus-border: #9ca3af;\n --hw-focus-ring: rgba(0, 0, 0, 0.06);\n --hw-accent: #6366f1;\n --hw-bg: #ffffff;\n --hw-bg-subtle: #fafaf9;\n --hw-bg-hover: #f5f5f4;\n --hw-border: #ebe9e5;\n --hw-border-md: #e5e5e5;\n --hw-text: #1c1b19;\n --hw-text-1: #111;\n --hw-text-2: #666;\n --hw-text-3: #8a847c;\n --hw-text-4: #a8a29a;\n --hw-radius: 20px;\n --hw-visitor-bubble-bg: #f5f5f4;\n --hw-visitor-bubble-text: #1a1a1a;\n --hw-font:\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n Roboto,\n "Helvetica Neue",\n Arial,\n sans-serif;\n}\n.hw-agent-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-agent-icon {\n width: 100%;\n height: 100%;\n border-radius: inherit;\n}\n.hw-widget :is(.hw-header-bot-icon, .hw-hero-bot-icon, .hw-conv-card-avatar, .hw-event-avatar, .hw-bubble-icon--bot):has(> .hw-agent-custom) {\n border-radius: 50%;\n background: transparent;\n padding: 0;\n}\n.hw-widget :focus-visible {\n outline: 2px solid var(--hw-primary);\n outline-offset: 2px;\n}\n.hw-widget :focus:not(:focus-visible) {\n outline: none;\n}\n.hw-widget {\n position: fixed;\n bottom: 20px;\n right: var(--hw-position-right, 20px);\n left: var(--hw-position-left, auto);\n z-index: 999999;\n font-family: var(--hw-font);\n}\n@keyframes hw-bubble-enter {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n.hw-bubble {\n width: 48px;\n height: 48px;\n border-radius: 14px;\n background: var(--hw-primary);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease;\n position: relative;\n overflow: visible;\n animation: hw-bubble-enter 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) both;\n}\n.hw-bubble--rounded {\n border-radius: 14px;\n}\n.hw-bubble--square {\n border-radius: 8px;\n}\n.hw-bubble--pill {\n border-radius: 24px;\n}\n.hw-bubble--launcher-bubble,\n.hw-bubble--launcher-help {\n width: auto;\n padding: 0 16px 0 12px;\n gap: 8px;\n border-radius: 24px;\n}\n.hw-bubble--launcher-bubble.hw-bubble--square,\n.hw-bubble--launcher-help.hw-bubble--square {\n border-radius: 8px;\n}\n.hw-bubble--launcher-bubble.hw-bubble--rounded,\n.hw-bubble--launcher-help.hw-bubble--rounded {\n border-radius: 14px;\n}\n.hw-bubble-label {\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n line-height: 1;\n position: static;\n opacity: 1;\n transform: none;\n}\n.hw-bubble--launcher-bubble .hw-bubble-icon,\n.hw-bubble--launcher-help .hw-bubble-icon {\n position: static;\n}\n.hw-bubble:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n}\n.hw-bubble:active {\n transform: scale(0.95);\n}\n.hw-bubble--open {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n}\n.hw-bubble:focus-visible {\n outline: 2px solid white;\n outline-offset: 2px;\n}\n.hw-bubble-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;\n}\n.hw-bubble-icon svg:not(.hw-agent-custom svg) {\n width: 22px;\n height: 22px;\n}\n.hw-bubble-icon--hidden {\n transform: scale(0.3) rotate(90deg);\n opacity: 0;\n}\n.hw-bubble-icon--bot {\n}\n.hw-bubble--avatar .hw-bubble-icon--bot {\n width: 100%;\n height: 100%;\n}\n.hw-bubble--avatar .hw-bubble-icon--bot .hw-agent-img {\n width: 100%;\n height: 100%;\n border-radius: 0;\n}\n.hw-agent-img.hw-agent-img--logo {\n object-fit: contain;\n padding: 10px;\n box-sizing: border-box;\n}\n.hw-bubble--avatar .hw-bubble-icon--bot .hw-agent-img.hw-agent-img--logo {\n padding: 10px;\n box-sizing: border-box;\n object-fit: contain;\n}\n.hw-bubble-icon--close svg {\n width: 22px;\n height: 22px;\n}\n.hw-bubble-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n border-radius: 10px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n border: 2px solid white;\n animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n@keyframes hw-badge-pop {\n from {\n transform: scale(0);\n }\n to {\n transform: scale(1);\n }\n}\n.hw-bubble-badge::after {\n content: "";\n position: absolute;\n inset: -2px;\n border-radius: inherit;\n background: var(--hw-primary);\n opacity: 0;\n animation: hw-badge-pulse 2s ease-out infinite;\n}\n@keyframes hw-badge-pulse {\n 0% {\n opacity: 0.5;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(1.8);\n }\n}\n.hw-window {\n position: absolute;\n bottom: 72px;\n right: var(--hw-window-right, 0);\n left: var(--hw-window-left, auto);\n width: 440px;\n height: 640px;\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n border-radius: var(--hw-radius);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: hw-window-open 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);\n transition: width 280ms cubic-bezier(0.4, 0, 0.2, 1), height 280ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n.hw-window--reading {\n width: min(720px, calc(100vw - 40px));\n height: min(800px, calc(100vh - 112px));\n}\n:host([data-hw-mode="mobile"]) .hw-window,\n:host([data-hw-mode="mobile"]) .hw-window--reading {\n position: fixed;\n inset: 0;\n width: 100%;\n height: var(--hw-visible-height, 100%);\n border-radius: 0;\n box-shadow: none;\n animation: none;\n}\n:host([data-hw-mode="mobile"]) .hw-hero {\n background-color: color-mix(in srgb, var(--hw-primary) 60%, black);\n}\n:host([data-hw-mode="mobile"]) .hw-bubble {\n display: none;\n}\n.hw-window[data-hw-keyboard] .hw-composer {\n padding-bottom: 8px;\n}\n.hw-window[data-hw-keyboard] .hw-powered {\n display: none;\n}\n@keyframes hw-window-open {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n.hw-window--closing {\n animation: hw-window-close 0.2s ease forwards;\n}\n@keyframes hw-window-close {\n from {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.98);\n }\n}\n.hw-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-window,\n .hw-window--closing,\n .hw-content,\n .hw-msg,\n .hw-bubble,\n .hw-bubble-icon,\n .hw-bubble-badge,\n .hw-bubble-badge::after,\n .hw-typing-dot,\n .hw-loading-dot {\n animation-duration: 0.01ms !important;\n transition-duration: 0.01ms !important;\n }\n}\n.hw-hero {\n flex-shrink: 0;\n background:\n linear-gradient(\n 160deg,\n color-mix(in srgb, var(--hw-primary) 60%, black) 0%,\n var(--hw-primary) 50%,\n color-mix(in srgb, var(--hw-primary) 40%, black) 100%);\n color: white;\n padding: 20px 22px 40px;\n}\n.hw-hero-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 16px;\n}\n.hw-hero-close {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n border: none;\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n.hw-hero-close:hover {\n background: rgba(255, 255, 255, 0.2);\n color: white;\n}\n.hw-hero-close:active {\n transform: scale(0.92);\n transition:\n transform 0.14s cubic-bezier(0.23, 1, 0.32, 1),\n background 0.15s,\n color 0.15s;\n}\n.hw-hero-close svg {\n width: 20px;\n height: 20px;\n}\n.hw-hero-bot-icon {\n width: 36px;\n height: 36px;\n flex-shrink: 0;\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n}\n.hw-hero-bot-icon > svg,\n.hw-hero-bot-icon > .hw-agent-icon > svg {\n width: 32px;\n height: 32px;\n}\n.hw-hero-bot-icon .hw-agent-img,\n.hw-hero-bot-icon .hw-agent-icon {\n border-radius: inherit;\n overflow: hidden;\n object-fit: contain;\n}\n.hw-hero-greeting {\n font-size: 26px;\n font-weight: 700;\n line-height: 1.15;\n margin-bottom: 6px;\n}\n.hw-hero-greeting-name {\n font-weight: 300;\n}\n.hw-hero-greeting-question {\n font-weight: 700;\n}\n.hw-hero-subtitle {\n font-size: 15px;\n color: rgba(255, 255, 255, 0.5);\n line-height: 1.35;\n}\n.hw-sheet {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n background: #ffffff;\n border-radius: 20px 20px 0 0;\n margin-top: -24px;\n box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);\n position: relative;\n z-index: 1;\n}\n.hw-sheet-inner {\n padding: 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.hw-header {\n display: flex;\n align-items: center;\n padding: 14px 12px 14px 16px;\n background: var(--hw-primary);\n color: white;\n flex-shrink: 0;\n gap: 10px;\n}\n.hw-header--sub {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header-back {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n flex-shrink: 0;\n}\n.hw-header-back svg {\n width: 18px;\n height: 18px;\n}\n.hw-header-back:hover {\n color: var(--hw-text);\n background: var(--hw-bg-subtle);\n}\n.hw-header-identity {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n}\n.hw-header-bot-icon {\n width: 32px;\n height: 32px;\n flex-shrink: 0;\n color: var(--hw-text);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 9px;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));\n}\n.hw-header-bot-icon > svg,\n.hw-header-bot-icon > .hw-agent-icon > svg {\n width: 24px;\n height: 24px;\n}\n.hw-header-bot-icon--team {\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n}\n.hw-header-agent-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n}\n.hw-header-bot-icon .hw-agent-img,\n.hw-header-bot-icon .hw-agent-icon {\n border-radius: inherit;\n overflow: hidden;\n}\n.hw-header-bot-icon .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-widget[data-has-avatar=true] {\n --hw-agent-bg-default: var(--hw-primary);\n --hw-agent-fit-default: contain;\n --hw-agent-pad-default: 6px;\n}\n.hw-header-agent-initials {\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n}\n.hw-header-info {\n flex: 1;\n min-width: 0;\n}\n.hw-header-name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.3;\n}\n.hw-header-status {\n font-size: 11px;\n color: var(--hw-text-3);\n line-height: 1.3;\n}\n.hw-header-close {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n flex-shrink: 0;\n}\n.hw-header-close svg {\n width: 20px;\n height: 20px;\n}\n.hw-header-close:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n}\n.hw-header-close:active {\n transform: scale(0.92);\n}\n.hw-header--centered {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header--centered .hw-header-title {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100% - 88px);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n text-align: center;\n}\n.hw-header-spacer {\n width: 28px;\n flex-shrink: 0;\n}\n.hw-header--messages {\n justify-content: space-between;\n background: transparent;\n color: var(--hw-text);\n border-bottom: 0;\n}\n.hw-header-title {\n font-size: 16px;\n font-weight: 600;\n}\n.hw-header-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.hw-header-action {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n.hw-header-action svg {\n width: 16px;\n height: 16px;\n}\n.hw-header-action:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text);\n}\n.hw-header-action:active {\n transform: scale(0.94);\n}\n.hw-card {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n padding: 14px 16px;\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n cursor: pointer;\n transition: box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1), transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\n text-align: left;\n color: var(--hw-text);\n font-family: inherit;\n}\n.hw-card:hover {\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.05);\n transform: translateY(-1px);\n}\n.hw-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 120ms;\n}\n.hw-card-body {\n flex: 1;\n min-width: 0;\n}\n.hw-card-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: var(--hw-text);\n}\n.hw-card-meta {\n font-size: 12px;\n color: var(--hw-text-3);\n line-height: 1.3;\n margin-top: 1px;\n}\n.hw-card-arrow {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--hw-primary);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.hw-card-arrow svg {\n width: 14px;\n height: 14px;\n}\n.hw-msgs-tab {\n flex: 1;\n overflow-y: auto;\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-recent-card {\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n overflow: hidden;\n}\n.hw-recent-header {\n font-size: 12px;\n font-weight: 600;\n color: var(--hw-text-2);\n padding: 12px 14px 0;\n}\n.hw-recent-row {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 14px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n transition: background-color 140ms cubic-bezier(0.23, 1, 0.32, 1), transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n position: relative;\n}\n.hw-recent-row:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n.hw-recent-row:active {\n transform: scale(0.995);\n}\n.hw-recent-row--last {\n border-bottom: none;\n}\n.hw-recent-row .hw-conv-card-avatar {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n}\n.hw-recent-row .hw-conv-card-avatar svg:not(.hw-agent-custom svg) {\n width: 18px;\n height: 18px;\n}\n.hw-recent-row .hw-conv-card-name {\n font-size: 13px;\n}\n.hw-recent-row .hw-conv-card-preview {\n font-size: 12px;\n}\n.hw-recent-row--unread .hw-conv-card-name {\n color: var(--hw-text);\n}\n.hw-recent-row--unread .hw-conv-card-time {\n color: var(--hw-primary);\n font-weight: 500;\n}\n.hw-recent-row-badge {\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n.hw-recent-see-all {\n display: block;\n width: 100%;\n padding: 10px 14px;\n text-align: center;\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-text);\n background: none;\n border: none;\n border-top: 1px solid var(--hw-border);\n cursor: pointer;\n font-family: inherit;\n transition: background 0.1s;\n}\n.hw-recent-see-all:hover {\n background: rgba(0, 0, 0, 0.02);\n}\n.hw-conv-card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 4px;\n width: 100%;\n padding: 14px 16px;\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n cursor: pointer;\n transition: box-shadow 0.15s, transform 0.1s;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n}\n.hw-conv-card:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);\n}\n.hw-conv-card:active {\n transform: scale(0.99);\n}\n.hw-conv-card-row {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hw-conv-card-avatar {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-subtle)));\n color: var(--hw-text-3);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-conv-card-avatar svg:not(.hw-agent-custom svg) {\n width: 20px;\n height: 20px;\n}\n.hw-conv-card-avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-conv-card-avatar .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-conv-card-avatar--team {\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n}\n.hw-conv-card-avatar-initials {\n font-size: 12px;\n font-weight: 600;\n line-height: 1;\n letter-spacing: 0.02em;\n}\n.hw-conv-card-content {\n flex: 1;\n min-width: 0;\n}\n.hw-conv-card-top {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.hw-conv-card-name {\n flex: 1;\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-conv-card-time {\n font-size: 11px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n.hw-conv-card-preview {\n font-size: 13px;\n color: var(--hw-text-2);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 1.4;\n margin-top: 1px;\n}\n.hw-conv-card--unread .hw-conv-card-name {\n color: var(--hw-text);\n}\n.hw-conv-card--unread .hw-conv-card-time {\n color: var(--hw-primary);\n font-weight: 500;\n}\n.hw-conv-card-badge {\n position: absolute;\n top: 12px;\n right: 12px;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: var(--hw-primary);\n color: white;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 5px;\n font-variant-numeric: tabular-nums;\n}\n.hw-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n text-align: center;\n}\n.hw-empty-icon-wrap {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--hw-bg-subtle);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 16px;\n color: var(--hw-text-3);\n}\n.hw-empty-icon-wrap svg {\n width: 24px;\n height: 24px;\n}\n.hw-empty-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--hw-text);\n margin-bottom: 4px;\n}\n.hw-empty-desc {\n font-size: 13px;\n color: var(--hw-text-3);\n margin-bottom: 20px;\n}\n.hw-empty-btn {\n padding: 8px 20px;\n border-radius: 10px;\n background: var(--hw-primary);\n color: white;\n border: none;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 0.15s;\n}\n.hw-empty-btn:hover {\n background: var(--hw-primary-hover);\n}\n.hw-tabs {\n display: flex;\n border-top: 1px solid var(--hw-border);\n flex-shrink: 0;\n background: var(--hw-bg-subtle);\n}\n.hw-tabs-item {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n padding: 8px 0;\n border: none;\n background: none;\n cursor: pointer;\n font-family: inherit;\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n transition: color 0.15s;\n}\n.hw-tabs-item svg {\n width: 22px;\n height: 22px;\n overflow: visible;\n}\n.hw-tabs-item--active {\n color: var(--hw-text);\n}\n.hw-tabs-item:hover {\n color: var(--hw-text-2);\n}\n.hw-tabs-item:active {\n transform: scale(0.94);\n transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1), color 0.15s;\n}\n.hw-tabs-icon-wrap {\n position: relative;\n display: inline-flex;\n}\n.hw-tabs-badge {\n position: absolute;\n top: -6px;\n right: -10px;\n min-width: 16px;\n height: 16px;\n border-radius: 8px;\n background: var(--hw-primary);\n color: white;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n font-variant-numeric: tabular-nums;\n}\n.hw-messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px 14px 8px;\n background: var(--hw-bg-subtle);\n display: flex;\n flex-direction: column;\n gap: 14px;\n overscroll-behavior: contain;\n min-width: 0;\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\n scrollbar-width: thin;\n -webkit-mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 12px);\n mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 12px);\n}\n.hw-messages::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n.hw-messages::-webkit-scrollbar-track {\n background: transparent;\n}\n.hw-messages::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.16);\n background-clip: content-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n.hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.28);\n background-clip: content-box;\n}\n.hw-widget[data-theme=dark] .hw-messages {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n}\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n background-clip: content-box;\n}\n.hw-widget[data-theme=dark] .hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n}\n.hw-empty {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--hw-text-3);\n text-align: center;\n}\n.hw-empty-icon {\n width: 40px;\n height: 40px;\n margin-bottom: 12px;\n opacity: 0.3;\n}\n.hw-empty-text {\n font-size: 13px;\n}\n.hw-date-sep {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 0;\n}\n.hw-date-sep-line {\n flex: 1;\n height: 1px;\n background: var(--hw-border-md);\n}\n.hw-date-sep-text {\n font-size: 11px;\n color: var(--hw-text-3);\n font-weight: 500;\n white-space: nowrap;\n}\n.hw-msg {\n display: flex;\n padding: 4px 0;\n max-width: 75%;\n min-width: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n@keyframes hw-msg-appear {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-msg--visitor {\n align-self: flex-end;\n}\n.hw-msg--team,\n.hw-msg--ai {\n align-self: flex-start;\n}\n.hw-msg--ai {\n width: 100%;\n max-width: 100%;\n}\n.hw-msg-body {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: 100%;\n}\n.hw-msg-bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n max-width: 100%;\n}\n.hw-msg--visitor .hw-msg-bubble {\n background: var(--hw-primary);\n color: white;\n border-bottom-right-radius: 4px;\n}\n.hw-msg--team .hw-msg-bubble {\n background: var(--hw-visitor-bubble-bg);\n color: var(--hw-visitor-bubble-text);\n border-bottom-left-radius: 4px;\n}\n.hw-msg--ai .hw-msg-bubble {\n background: var(--hw-visitor-bubble-bg);\n color: var(--hw-text);\n border-bottom-left-radius: 4px;\n white-space: normal;\n max-width: min(100%, 640px);\n}\n.hw-msg--ai .hw-msg-body {\n width: 100%;\n}\n.hw-msg--ai .hw-msg-bubble:has(.hw-code),\n.hw-msg--ai .hw-msg-bubble:has(pre) {\n width: 100%;\n}\n.hw-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 8px;\n}\n.hw-quick-reply-btn {\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n padding: 6px 14px;\n border-radius: 18px;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n background: var(--hw-bg, #fff);\n color: var(--hw-text-1, #1a1a1a);\n cursor: pointer;\n transition:\n background 120ms ease,\n border-color 120ms ease,\n box-shadow 120ms ease,\n transform 80ms ease;\n line-height: 1.3;\n}\n.hw-quick-reply-btn:hover:not(:disabled) {\n border-color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 8%, transparent);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n}\n.hw-quick-reply-btn:active:not(:disabled) {\n transform: scale(0.97);\n}\n.hw-quick-reply-btn:disabled {\n cursor: default;\n opacity: 0.4;\n}\n.hw-quick-reply-btn[data-tapped=true] {\n background: var(--hw-primary);\n color: white;\n border-color: var(--hw-primary);\n opacity: 1;\n}\n.hw-quick-replies[data-cancelled=true] .hw-quick-reply-btn {\n border-color: var(--hw-border);\n color: var(--hw-text-3);\n}\n.hw-msg--ai .hw-code {\n width: 100%;\n box-sizing: border-box;\n}\n.hw-msg-meta {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n color: var(--hw-text-2);\n margin-top: 2px;\n padding: 0 4px;\n font-variant-numeric: tabular-nums;\n}\n.hw-msg-time {\n white-space: nowrap;\n}\n.hw-msg--visitor .hw-msg-meta {\n text-align: right;\n}\n.hw-msg--team .hw-msg-body,\n.hw-msg--ai .hw-msg-body {\n align-items: flex-start;\n}\n.hw-msg--visitor .hw-msg-body {\n align-items: flex-end;\n}\n.hw-typing {\n display: flex;\n flex-direction: column;\n gap: 3px;\n padding: 8px 0;\n width: fit-content;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-typing-dots {\n display: flex;\n gap: 3px;\n padding: 6px 2px;\n width: fit-content;\n}\n.hw-typing-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--hw-text-3);\n animation: hw-typing-bounce 1.4s infinite;\n}\n.hw-typing-dot:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-typing-dot:nth-child(3) {\n animation-delay: 0.4s;\n}\n@keyframes hw-typing-bounce {\n 0%, 60%, 100% {\n transform: translateY(0);\n }\n 30% {\n transform: translateY(-4px);\n }\n}\n.hw-streaming-cursor {\n display: inline-block;\n width: 2px;\n height: 1em;\n background: currentColor;\n opacity: 0.6;\n margin-left: 1px;\n vertical-align: text-bottom;\n animation: hw-cursor-blink 0.8s step-end infinite;\n}\n@keyframes hw-cursor-blink {\n 50% {\n opacity: 0;\n }\n}\n.hw-link-preview {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n border-radius: 10px;\n overflow: hidden;\n text-decoration: none;\n color: inherit;\n margin-top: 6px;\n transition: background 0.15s;\n min-height: 44px;\n max-width: 100%;\n text-align: start;\n}\n.hw-link-preview:hover {\n background: var(--hw-bg-hover, rgba(0, 0, 0, 0.02));\n}\n.hw-link-preview-img {\n width: 100%;\n height: 56px;\n flex: 0 0 56px;\n object-fit: cover;\n object-position: top;\n border-radius: 0;\n}\n.hw-link-preview-body {\n padding: 8px 10px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n justify-content: center;\n}\n.hw-link-preview-favicon {\n width: 14px;\n height: 14px;\n flex: 0 0 14px;\n border-radius: 3px;\n}\n.hw-widget[data-hw-placement=docked] .hw-link-preview-favicon {\n box-sizing: content-box;\n padding: 2px;\n background: #ffffff;\n}\n.hw-link-preview-host {\n direction: ltr;\n min-width: 0;\n overflow-wrap: anywhere;\n word-break: break-all;\n}\n.hw-link-preview-title {\n font-size: 12.5px;\n font-weight: 600;\n line-height: 1.3;\n color: var(--hw-text, #1a1a1a);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.hw-link-preview-desc {\n font-size: 11.5px;\n line-height: 1.4;\n color: var(--hw-text-2, #6b7280);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.hw-link-preview-url {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n font-size: 11px;\n color: var(--hw-text-2);\n}\n.hw-msg-links {\n display: flex;\n flex-direction: column;\n gap: 6px;\n max-width: 240px;\n}\n.hw-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-loading-dots {\n display: flex;\n gap: 4px;\n}\n.hw-loading-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--hw-text-4);\n animation: hw-loading-pulse 1.4s infinite;\n}\n.hw-loading-dot:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-loading-dot:nth-child(3) {\n animation-delay: 0.4s;\n}\n@keyframes hw-loading-pulse {\n 0%, 60%, 100% {\n opacity: 0.3;\n transform: scale(0.8);\n }\n 30% {\n opacity: 1;\n transform: scale(1);\n }\n}\n@keyframes hw-skeleton-shimmer {\n 0% {\n background-position: -200px 0;\n }\n 100% {\n background-position: calc(200px + 100%) 0;\n }\n}\n.hw-skeleton {\n background:\n linear-gradient(\n 90deg,\n var(--hw-bg-subtle) 25%,\n rgba(0, 0, 0, 0.04) 50%,\n var(--hw-bg-subtle) 75%);\n background-size: 200px 100%;\n animation: hw-skeleton-shimmer 1.5s ease-in-out infinite;\n border-radius: 6px;\n}\n.hw-skeleton-messages {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 16px;\n gap: 16px;\n}\n.hw-skeleton-msg {\n display: flex;\n gap: 10px;\n align-items: flex-start;\n}\n.hw-skeleton-msg--right {\n flex-direction: row-reverse;\n}\n.hw-skeleton-avatar {\n width: 28px;\n height: 28px;\n border-radius: 8px;\n flex-shrink: 0;\n}\n.hw-skeleton-bubble {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.hw-skeleton-line {\n height: 12px;\n border-radius: 6px;\n}\n.hw-skeleton-convs {\n display: flex;\n flex-direction: column;\n padding: 8px 0;\n}\n.hw-skeleton-conv {\n display: flex;\n gap: 10px;\n align-items: center;\n padding: 10px 16px;\n}\n.hw-skeleton-conv-avatar {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n flex-shrink: 0;\n}\n.hw-skeleton-conv-lines {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.hw-skeleton-content {\n display: flex;\n flex-direction: column;\n padding: 12px 16px;\n gap: 12px;\n}\n.hw-skeleton-content-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n border-radius: 10px;\n background: var(--hw-bg);\n}\n.hw-skeleton-title {\n height: 22px;\n width: 65%;\n border-radius: 6px;\n}\n.hw-skeleton-badge {\n width: 42px;\n height: 18px;\n border-radius: 9px;\n}\n.hw-skeleton-date {\n width: 60px;\n height: 12px;\n border-radius: 6px;\n}\n.hw-skeleton-h2 {\n height: 16px;\n border-radius: 6px;\n}\n.hw-skeleton-bullet {\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-skeleton-bullet-line {\n height: 14px;\n border-radius: 7px;\n}\n.hw-email-card {\n max-width: min(100%, 340px);\n margin: 0;\n padding: 0;\n border: 0;\n border-radius: 0;\n background: none;\n box-shadow: none;\n animation: hw-email-slide-in 0.25s ease-out;\n}\n@keyframes hw-email-slide-in {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-email-card-title {\n font-size: 14px;\n font-weight: 550;\n color: var(--hw-text, #1a1a1a);\n line-height: 1.3;\n margin: 0 0 2px;\n}\n.hw-email-card-subtitle {\n font-size: 12px;\n color: var(--hw-text-2, #888);\n line-height: 1.4;\n margin: 0;\n}\n.hw-email-card-row {\n max-width: 300px;\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 9px;\n padding: 3px 3px 3px 12px;\n border-radius: 999px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.1));\n background: var(--hw-bg-subtle, #fafafa);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-email-card-row:focus-within {\n border-color: var(--hw-focus-border, rgba(0,0,0,0.2));\n box-shadow: 0 0 0 2px var(--hw-focus-ring, rgba(0,0,0,0.06));\n}\n.hw-email-card-input {\n flex: 1;\n min-width: 0;\n padding: 6px 0;\n border: 0;\n background: transparent;\n color: var(--hw-text, #1a1a1a);\n font: inherit;\n font-size: 13px;\n outline: none;\n}\n.hw-email-card-input::placeholder {\n color: var(--hw-text-3, #999);\n}\n.hw-email-card-row:has(.hw-email-card-input--error) {\n border-color: #ef4444;\n}\n.hw-email-card-submit {\n flex: none;\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n cursor: pointer;\n transition: opacity 0.15s, transform 0.15s;\n}\n.hw-email-card-submit:hover:not(:disabled) {\n transform: scale(1.06);\n}\n.hw-email-card-submit:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.hw-email-card--success {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 13px;\n color: var(--hw-text-2, #888);\n animation: hw-email-slide-in 0.2s ease-out;\n}\n.hw-email-card--success svg {\n flex-shrink: 0;\n}\n.hw-composer {\n display: flex;\n flex-direction: column;\n padding: 12px 16px;\n background: transparent;\n flex-shrink: 0;\n}\n.hw-composer--compact {\n padding: 8px 12px;\n}\n.hw-composer-box {\n display: flex;\n flex-direction: column;\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n border-radius: 16px;\n overflow: hidden;\n transition: border-color 0.2s;\n background: var(--hw-bg);\n}\n.hw-composer-box:focus-within {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n}\n.hw-composer-input {\n resize: none;\n border: none;\n padding: 12px 16px 4px;\n font-size: 14px;\n font-family: inherit;\n line-height: 1.4;\n outline: none;\n min-height: 40px;\n max-height: 220px;\n background: transparent;\n color: var(--hw-text);\n field-sizing: content;\n}\n.hw-composer-input:focus {\n outline: none;\n}\n.hw-composer-input:focus-visible {\n outline: none;\n}\n.hw-composer-input::placeholder {\n color: var(--hw-text-4);\n}\n.hw-composer-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px 10px;\n}\n.hw-composer-toolbar-left {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.hw-composer-send {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n background-color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n color 140ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 140ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n.hw-composer-send:active:not(:disabled) {\n transform: scale(0.9);\n}\n.hw-composer-send--active {\n background: var(--hw-primary);\n color: white;\n}\n.hw-composer-send--inactive {\n background: var(--hw-border);\n color: var(--hw-text-4);\n cursor: default;\n}\n.hw-composer-send svg {\n width: 14px;\n height: 14px;\n}\n.hw-composer-charcount {\n font-size: 11px;\n color: var(--hw-text-3);\n font-variant-numeric: tabular-nums;\n opacity: 1;\n transform: translateY(0);\n transition:\n color 180ms cubic-bezier(0.23, 1, 0.32, 1),\n opacity 180ms cubic-bezier(0.23, 1, 0.32, 1),\n transform 180ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n@starting-style {\n .hw-composer-charcount {\n opacity: 0;\n transform: translateY(3px);\n }\n}\n.hw-composer-charcount--over {\n color: #ef4444;\n font-weight: 600;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-composer-charcount {\n transform: none;\n transition: color 160ms ease, opacity 160ms ease;\n }\n @starting-style {\n .hw-composer-charcount {\n transform: none;\n }\n }\n}\n.hw-composer-previews {\n display: flex;\n gap: 6px;\n padding: 8px 10px 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.hw-composer-previews::-webkit-scrollbar {\n display: none;\n}\n.hw-composer-preview {\n position: relative;\n width: 48px;\n height: 48px;\n border-radius: 8px;\n overflow: hidden;\n flex-shrink: 0;\n background: var(--hw-border);\n cursor: pointer;\n}\n.hw-composer-preview--error {\n outline: 2px solid #ef4444;\n outline-offset: -2px;\n}\n.hw-composer-preview-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-composer-preview-file {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--hw-bg-subtle);\n}\n.hw-composer-preview-ext {\n font-size: 10px;\n font-weight: 700;\n color: var(--hw-text-3);\n text-transform: uppercase;\n}\n.hw-composer-preview-loader {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-composer-preview-loader::after {\n content: "";\n width: 16px;\n height: 16px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-top-color: white;\n border-radius: 50%;\n animation: hw-spin 0.6s linear infinite;\n}\n@keyframes hw-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.hw-composer-preview-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #ef4444;\n color: white;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-composer-preview-remove {\n position: absolute;\n top: 2px;\n right: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: rgba(0, 0, 0, 0.55);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.hw-composer-preview-remove svg {\n width: 10px;\n height: 10px;\n}\n.hw-composer-preview:hover .hw-composer-preview-remove {\n opacity: 1;\n}\n.hw-composer-attach {\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n opacity: 0.7;\n transition: opacity 0.15s;\n}\n.hw-composer-attach:hover {\n opacity: 1;\n}\n.hw-composer-attach svg {\n width: 16px;\n height: 16px;\n}\n.hw-msg-images {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-bottom: 4px;\n}\n.hw-msg-image-link {\n display: block;\n border-radius: 14px;\n overflow: hidden;\n line-height: 0;\n}\n.hw-msg-image {\n max-width: 140px;\n max-height: 80px;\n object-fit: cover;\n border-radius: 8px;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-msg-files {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 4px;\n}\n.hw-msg-file {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 10px;\n background: var(--hw-bg-subtle);\n text-decoration: none;\n color: var(--hw-text);\n transition: background 0.15s;\n}\n.hw-msg-file:hover {\n background: var(--hw-border);\n}\n.hw-msg-file-icon {\n flex-shrink: 0;\n width: 20px;\n height: 20px;\n color: var(--hw-text-3);\n}\n.hw-msg-file-icon svg {\n width: 100%;\n height: 100%;\n}\n.hw-msg-file-info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.hw-msg-file-name {\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.hw-msg-file-size {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-msg-image-link {\n cursor: pointer;\n border: none;\n padding: 0;\n background: none;\n display: block;\n line-height: 0;\n}\n.hw-hover-preview {\n position: fixed;\n z-index: 2147483001;\n padding: 6px;\n border-radius: 14px;\n background: white;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.06);\n cursor: pointer;\n animation: hw-hover-in 0.15s ease-out;\n}\n@media (prefers-color-scheme: dark) {\n .hw-hover-preview {\n background: #1c1c1e;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08);\n }\n}\n@keyframes hw-hover-in {\n from {\n opacity: 0;\n transform: scale(0.96) translateY(4px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n.hw-hover-preview-img {\n width: 100%;\n max-height: 200px;\n object-fit: contain;\n border-radius: 10px;\n display: block;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-hover-preview--doc {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n}\n.hw-hover-preview-doc-icon {\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n}\n.hw-hover-preview-doc-icon svg {\n width: 100%;\n height: 100%;\n}\n.hw-hover-preview-doc-info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.hw-hover-preview-doc-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.hw-hover-preview-doc-hint {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-event {\n display: flex;\n justify-content: center;\n padding: 8px 16px;\n}\n.hw-event-text {\n font-size: 12px;\n color: var(--hw-text-3);\n text-align: center;\n}\n.hw-event--card {\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n background: var(--hw-bg-subtle);\n padding: 10px 14px;\n border-radius: 12px;\n margin: 4px 16px;\n}\n.hw-event-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, var(--hw-bg-hover, #e0e0e0)));\n color: var(--hw-text-2, #555);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-event-avatar-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n.hw-event-avatar .hw-agent-img {\n object-fit: var(--hw-agent-fit, var(--hw-agent-fit-default, cover));\n padding: var(--hw-agent-pad, var(--hw-agent-pad-default, 0));\n box-sizing: border-box;\n}\n.hw-event-body {\n font-size: 13px;\n line-height: 1.3;\n}\n.hw-event-name {\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-event-action {\n color: var(--hw-text-2);\n}\n.hw-new {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--hw-bg-subtle);\n}\n.hw-new-body {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 24px;\n text-align: center;\n}\n.hw-new-welcome {\n flex: 1;\n padding: 16px 20px;\n overflow-y: auto;\n}\n.hw-new-heading {\n font-size: 17px;\n font-weight: 600;\n color: var(--hw-text);\n margin-bottom: 6px;\n}\n.hw-new-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n margin-bottom: 24px;\n}\n.hw-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--hw-text-4);\n flex-shrink: 0;\n}\n.hw-powered a {\n color: var(--hw-text-2);\n text-decoration: none;\n font-weight: 500;\n}\n.hw-powered a:hover {\n color: var(--hw-text);\n}\n@media (max-width: 479px) {\n .hw-widget {\n bottom: 16px;\n right: 16px;\n left: auto;\n }\n .hw-window {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n height: var(--hw-visible-height, 100%);\n border-radius: 0;\n animation: hw-mob-up 0.3s cubic-bezier(0.22, 1, 0.36, 1);\n }\n .hw-window--closing {\n animation: hw-mob-down 0.2s ease forwards;\n }\n @keyframes hw-mob-up {\n from {\n opacity: 0;\n transform: translateY(100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n @keyframes hw-mob-down {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(100%);\n }\n }\n .hw-hero {\n padding-top: calc(20px + env(safe-area-inset-top, 0px));\n }\n .hw-header {\n padding-top: env(safe-area-inset-top, 0px);\n }\n .hw-tabs {\n padding-bottom: env(safe-area-inset-bottom, 0px);\n }\n .hw-composer {\n padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));\n }\n .hw-powered {\n padding-bottom: calc(5px + env(safe-area-inset-bottom, 0px));\n }\n .hw-window:has(.hw-powered) .hw-composer {\n padding-bottom: 8px;\n }\n .hw-window:has(.hw-powered) .hw-tabs {\n padding-bottom: 0;\n }\n .hw-header-close,\n .hw-header-back,\n .hw-header-action {\n width: 34px;\n height: 34px;\n }\n .hw-composer-send {\n width: 40px;\n height: 40px;\n }\n .hw-window ~ .hw-bubble {\n display: none;\n }\n .hw-messages {\n padding: 12px 14px;\n }\n .hw-msg {\n max-width: 82%;\n }\n .hw-msg--ai {\n max-width: 100%;\n }\n}\n.hw-preview {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n width: 300px;\n max-width: calc(100vw - 40px);\n background: var(--hw-bg);\n border: 1px solid var(--hw-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);\n animation: hw-preview-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n overflow: hidden;\n cursor: pointer;\n transition: transform 0.15s, box-shadow 0.15s;\n}\n.hw-preview.hw-preview--anchored {\n position: static;\n bottom: auto;\n right: auto;\n width: 100%;\n max-width: 100%;\n}\n.hw-preview.hw-preview--anchored .hw-preview-avatar {\n background: none;\n}\n.hw-preview.hw-preview--anchored .hw-preview-avatar img,\n.hw-preview.hw-preview--anchored .hw-preview-avatar svg:not(.hw-agent-custom svg) {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n.hw-preview:hover {\n transform: translateY(-2px);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n@keyframes hw-preview-in {\n from {\n opacity: 0;\n transform: translateY(8px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n@keyframes hw-preview-out {\n from {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.95);\n }\n}\n.hw-preview-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 14px 0;\n}\n.hw-preview-avatar {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background:\n linear-gradient(\n 135deg,\n var(--hw-primary),\n color-mix(in srgb, var(--hw-primary) 50%, black));\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n flex-shrink: 0;\n overflow: hidden;\n}\n.hw-preview-avatar svg:not(.hw-agent-custom svg) {\n width: 16px;\n height: 16px;\n}\n.hw-preview-avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n.hw-preview-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--hw-text);\n flex: 1;\n}\n.hw-preview-close {\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n color: var(--hw-text-3);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: background 0.15s, color 0.15s;\n flex-shrink: 0;\n}\n.hw-preview-close:hover {\n background: var(--hw-bg-subtle);\n color: var(--hw-text-2);\n}\n.hw-preview-close:active {\n transform: scale(0.90);\n transition:\n transform 0.14s cubic-bezier(0.23, 1, 0.32, 1),\n background 0.15s,\n color 0.15s;\n}\n.hw-preview-close svg {\n width: 12px;\n height: 12px;\n}\n.hw-preview-body {\n padding: 4px 14px;\n font-size: 14px;\n line-height: 1.45;\n color: var(--hw-text-2);\n}\n.hw-preview-body:first-of-type {\n padding-top: 8px;\n}\n.hw-preview-body:last-child {\n padding-bottom: 14px;\n}\n.hw-preview-footer {\n margin-top: 2px;\n padding: 8px 14px 12px;\n border-top: 1px solid var(--hw-border);\n font-size: 11px;\n line-height: 1.3;\n color: var(--hw-text-2);\n opacity: 0.65;\n}\n.hw-preview-prompt {\n padding: 2px 14px 6px;\n font-size: 14px;\n font-weight: 500;\n color: var(--hw-text-1);\n}\n.hw-preview-quick-replies {\n padding: 0 14px 14px;\n margin-top: 0;\n}\n.hw-awaiting {\n margin-top: 2px;\n padding-left: 44px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-preview-dock {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 8px;\n pointer-events: none;\n}\n.hw-preview-dock > .hw-preview,\n.hw-preview-dock > .hw-preview-stack {\n position: relative;\n bottom: auto;\n right: auto;\n pointer-events: auto;\n}\n.hw-preview--closing {\n animation: hw-preview-out 0.2s ease-in forwards;\n}\n.hw-preview-stack {\n position: absolute;\n bottom: calc(100% + 12px);\n right: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hw-preview-stack .hw-preview {\n position: relative;\n bottom: auto;\n right: auto;\n}\n.hw-preview-stack.hw-preview-stack--anchored {\n position: static;\n bottom: auto;\n right: auto;\n width: 100%;\n}\n.hw-preview-more {\n align-self: flex-end;\n padding: 4px 10px;\n border: 0;\n border-radius: 999px;\n background: var(--hw-bg);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), inset 0 0 0 1px var(--hw-border);\n color: var(--hw-text-2);\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n transition: background 0.12s, color 0.12s;\n}\n.hw-preview-more:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n}\n.hw-preview--announcement {\n width: 340px;\n}\n.hw-preview--announcement .hw-preview-body--title {\n font-weight: 600;\n color: var(--hw-text);\n font-size: 15px;\n line-height: 1.3;\n padding-top: 10px;\n}\n.hw-preview--announcement .hw-preview-body--desc {\n font-size: 13px;\n color: var(--hw-text-2);\n line-height: 1.5;\n padding-bottom: 16px;\n}\n.hw-announcement-badge {\n display: inline-block;\n margin: 8px 14px 0;\n padding: 2px 8px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 10%, transparent);\n border-radius: 4px;\n}\n.hw-whats-new {\n border-radius: 14px;\n background: var(--hw-bg);\n border: 0;\n box-shadow: inset 0 0 0 1px var(--hw-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.03);\n overflow: hidden;\n}\n.hw-whats-new-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px 0;\n}\n.hw-whats-new-title {\n font-size: 12px;\n font-weight: 600;\n color: var(--hw-text-2);\n}\n.hw-whats-new-view-all {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-primary);\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n font-family: inherit;\n}\n.hw-whats-new-view-all:hover {\n opacity: 0.8;\n}\n.hw-whats-new-list {\n display: flex;\n flex-direction: column;\n}\n.hw-whats-new-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n padding: 10px 14px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n font-family: inherit;\n color: var(--hw-text);\n transition: background-color 140ms ease;\n}\n.hw-whats-new-item:last-child {\n border-bottom: none;\n}\n.hw-whats-new-item:hover {\n background: rgba(0, 0, 0, 0.03);\n}\n.hw-whats-new-item-top {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.hw-whats-new-badge {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--hw-primary);\n}\n.hw-whats-new-time {\n font-size: 11px;\n color: var(--hw-text-3);\n margin-left: auto;\n}\n.hw-whats-new-item-title {\n font-size: 13px;\n font-weight: 600;\n color: var(--hw-text);\n line-height: 1.3;\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n.hw-whats-new-time-inline {\n font-size: 11px;\n font-weight: 400;\n color: var(--hw-text-3);\n margin-left: auto;\n flex-shrink: 0;\n}\n.hw-whats-new-item-body {\n font-size: 12px;\n color: var(--hw-text-2);\n line-height: 1.4;\n}\n.hw-tabs-dot {\n position: absolute;\n top: -2px;\n right: -6px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--hw-primary);\n animation: hw-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n.hw-bubble-badge-dot {\n display: block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: white;\n}\n.hw-content-search {\n padding: 10px 16px;\n}\n.hw-content-search-box {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--hw-bg);\n border: 1px solid var(--hw-border-md);\n border-radius: 10px;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-content-search-box:focus-within {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n}\n.hw-content-search-input {\n flex: 1;\n border: none !important;\n outline: none !important;\n box-shadow: none !important;\n background: none;\n font-size: 13px;\n color: var(--hw-text-1);\n font-family: inherit;\n line-height: 1;\n -webkit-appearance: none;\n}\n.hw-content-search-input:focus,\n.hw-content-search-input:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n border: none !important;\n}\n.hw-content-search-input::placeholder {\n color: var(--hw-text-3);\n}\n.hw-content-search-icon {\n width: 15px;\n height: 15px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n}\n.hw-content-list {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.hw-content-entries {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n.hw-content-entry {\n display: block;\n width: 100%;\n padding: 14px 16px;\n border: none;\n border-bottom: 1px solid var(--hw-border);\n background: none;\n cursor: pointer;\n text-align: left;\n transition: background-color 0.15s ease;\n -webkit-tap-highlight-color: transparent;\n}\n.hw-content-entry:hover {\n background: var(--hw-bg-hover);\n}\n.hw-content-entry:active {\n background: var(--hw-border);\n}\n.hw-content-entry:last-child {\n border-bottom: none;\n}\n.hw-content-entry-main {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hw-content-entry-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n.hw-content-entry-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text-1);\n line-height: 1.3;\n}\n.hw-content-entry-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.hw-content-entry-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 2px;\n}\n.hw-content-entry-badge {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n background: var(--hw-bg-hover);\n padding: 1px 6px;\n border-radius: 4px;\n}\n.hw-content-entry-date {\n font-size: 11px;\n color: var(--hw-text-3);\n}\n.hw-content-entry-chevron {\n width: 16px;\n height: 16px;\n color: var(--hw-text-3);\n flex-shrink: 0;\n opacity: 0.5;\n}\n.hw-content-detail {\n padding: 16px;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n.hw-content-detail-header {\n margin-bottom: 16px;\n}\n.hw-content-detail-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--hw-text-1);\n margin: 0 0 6px;\n line-height: 1.3;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.hw-content-detail-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n.hw-content-detail-date {\n font-size: 12px;\n color: var(--hw-text-3);\n}\n.hw-content-detail-body {\n font-size: 14px;\n line-height: 1.6;\n color: var(--hw-text-1);\n}\n.hw-markdown h1 {\n font-size: 17px;\n font-weight: 700;\n margin: 0;\n}\n.hw-markdown h2 {\n font-size: 15px;\n font-weight: 600;\n margin: 0;\n}\n.hw-markdown h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 0;\n}\n.hw-markdown p {\n margin: 0;\n}\n.hw-markdown p:empty,\n.hw-markdown div:empty,\n.hw-markdown p:has(> br:only-child),\n.hw-markdown div:has(> br:only-child) {\n display: none;\n}\n.hw-markdown > * + * {\n margin-top: 12px;\n}\n.hw-markdown > * + h1,\n.hw-markdown > * + h2 {\n margin-top: 20px;\n}\n.hw-markdown > * + h3 {\n margin-top: 16px;\n}\n.hw-markdown > h1 + *,\n.hw-markdown > h2 + *,\n.hw-markdown > h3 + * {\n margin-top: 8px;\n}\n.hw-markdown > *:first-child {\n margin-top: 0;\n}\n.hw-markdown > *:last-child {\n margin-bottom: 0;\n}\n.hw-markdown > br {\n display: none;\n}\n.hw-markdown ul,\n.hw-markdown ol {\n margin: 0;\n padding-left: 20px;\n}\n.hw-markdown li {\n margin: 4px 0;\n}\n.hw-markdown code {\n font-family:\n ui-monospace,\n "SF Mono",\n monospace;\n font-size: 12px;\n background: var(--hw-bg-hover);\n padding: 1px 5px;\n border-radius: 4px;\n}\n.hw-table-wrap {\n margin: 10px 0;\n overflow-x: auto;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n border-radius: 10px;\n}\n.hw-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n.hw-table th {\n text-align: left;\n font-weight: 600;\n font-size: 12px;\n padding: 8px 12px;\n background: var(--hw-bg-hover, #f5f5f4);\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n}\n.hw-table td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\n vertical-align: top;\n}\n.hw-table tbody tr:last-child td {\n border-bottom: none;\n}\n.hw-code {\n margin: 10px 0;\n border-radius: 10px;\n overflow: hidden;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.08));\n background: var(--hw-bg-hover, #f5f5f4);\n font-family:\n ui-monospace,\n "SF Mono",\n "Menlo",\n monospace;\n}\n.hw-code-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 7px 8px 7px 12px;\n font-size: 11px;\n color: var(--hw-text-2, #6b7280);\n background: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid var(--hw-border, rgba(0, 0, 0, 0.06));\n}\n.hw-code-lang {\n text-transform: lowercase;\n letter-spacing: 0.02em;\n font-weight: 500;\n}\n.hw-code-actions {\n display: inline-flex;\n align-items: center;\n gap: 1px;\n}\n.hw-code-action {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n padding: 0;\n font-family: inherit;\n color: var(--hw-text-2, #6b7280);\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0.62;\n transition:\n background 120ms ease,\n color 120ms ease,\n opacity 120ms ease,\n scale 120ms ease;\n}\n.hw-code-action:hover {\n color: var(--hw-text, #111);\n background: rgba(0, 0, 0, 0.06);\n opacity: 1;\n}\n.hw-code-action:active {\n scale: 0.96;\n}\n.hw-code-action svg {\n width: 13px;\n height: 13px;\n}\n.hw-code-copy-icon,\n.hw-code-check-icon {\n position: absolute;\n inset: 50% auto auto 50%;\n transition:\n opacity 180ms cubic-bezier(0.2, 0, 0, 1),\n scale 180ms cubic-bezier(0.2, 0, 0, 1),\n filter 180ms cubic-bezier(0.2, 0, 0, 1);\n translate: -50% -50%;\n}\n.hw-code-check-icon {\n filter: blur(4px);\n opacity: 0;\n scale: 0.25;\n}\n.hw-code-copy--copied .hw-code-copy-icon {\n filter: blur(4px);\n opacity: 0;\n scale: 0.25;\n}\n.hw-code-copy--copied .hw-code-check-icon {\n filter: blur(0);\n opacity: 1;\n scale: 1;\n}\n.hw-code-copy-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n}\n.hw-code-copy--copied {\n color: #16a34a;\n}\n.hw-code-copy--failed {\n color: #dc2626;\n}\n.hw-code pre {\n margin: 0;\n padding: 10px 12px;\n background: transparent;\n border-radius: 0;\n overflow-x: auto;\n max-width: 100%;\n max-height: 320px;\n scrollbar-color: rgba(0, 0, 0, 0.22) transparent;\n scrollbar-width: thin;\n}\n.hw-code pre::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n.hw-code pre::-webkit-scrollbar-track {\n background: transparent;\n}\n.hw-code pre::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.18);\n background-clip: content-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n.hw-code pre::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.28);\n background-clip: content-box;\n}\n.hw-code pre code {\n display: block;\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.55;\n white-space: pre;\n color: var(--hw-text, #111);\n}\n@media (prefers-color-scheme: dark) {\n .hw-code {\n background: rgba(255, 255, 255, 0.04);\n border-color: rgba(255, 255, 255, 0.08);\n }\n .hw-code-header {\n background: rgba(255, 255, 255, 0.03);\n border-bottom-color: rgba(255, 255, 255, 0.06);\n }\n .hw-code-action:hover,\n .hw-code-action:focus-visible {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-code pre {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n }\n .hw-code pre::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.22);\n background-clip: content-box;\n }\n .hw-code pre::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n }\n}\n.hw-markdown pre {\n margin: 8px 0;\n padding: 10px 12px;\n background: var(--hw-bg-hover);\n border-radius: 8px;\n overflow-x: auto;\n max-width: 100%;\n}\n.hw-markdown pre code {\n display: block;\n background: transparent;\n padding: 0;\n border-radius: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n word-break: normal;\n color: inherit;\n}\n.hw-msg-bubble pre {\n margin: 6px 0;\n padding: 8px 10px;\n background: rgba(0, 0, 0, 0.06);\n border-radius: 6px;\n overflow-x: auto;\n max-width: 100%;\n}\n.hw-msg-bubble pre code {\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n}\n.hw-msg-bubble .hw-code pre {\n margin: 0;\n padding: 10px 12px;\n background: transparent;\n border-radius: 0;\n}\n.hw-msg-bubble .hw-code pre code {\n background: transparent;\n padding: 0;\n font-size: 12px;\n line-height: 1.55;\n}\n.hw-msg--team .hw-msg-bubble pre,\n.hw-msg--visitor .hw-msg-bubble pre {\n background: rgba(255, 255, 255, 0.12);\n}\n.hw-markdown blockquote {\n margin: 0 0 12px;\n padding: 8px 12px;\n border-left: 3px solid var(--hw-border);\n color: var(--hw-text-2);\n font-style: italic;\n}\n.hw-markdown a {\n color: var(--hw-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.hw-markdown img {\n max-width: 100%;\n border-radius: 8px;\n margin: 8px 0;\n outline: 1px solid rgba(0, 0, 0, 0.08);\n outline-offset: -1px;\n}\n.hw-markdown hr {\n border: none;\n border-top: 1px solid var(--hw-border);\n margin: 16px 0;\n}\n.hw-content-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n.hw-content-empty-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--hw-text-1);\n margin-bottom: 4px;\n}\n.hw-content-empty-desc {\n font-size: 12px;\n color: var(--hw-text-3);\n}\n.hw-content-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n.hw-content-load-more {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: none;\n color: var(--hw-primary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n text-align: center;\n}\n.hw-content-load-more:hover {\n background: var(--hw-bg-hover);\n}\n.hw-content-load-more:disabled {\n opacity: 0.5;\n cursor: default;\n}\n@media (hover: none) {\n .hw-composer-preview-remove {\n opacity: 0.7;\n }\n}\n.hw-composer--dragging .hw-composer-box {\n border-color: var(--hw-primary);\n background: color-mix(in srgb, var(--hw-primary) 4%, transparent);\n}\n.hw-composer-drop-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--hw-bg) 90%, transparent);\n border: 2px dashed var(--hw-primary);\n border-radius: 12px;\n z-index: 10;\n pointer-events: none;\n animation: hw-drop-pulse 1.5s ease-in-out infinite;\n}\n.hw-composer-drop-text {\n font-size: 13px;\n font-weight: 500;\n color: var(--hw-primary);\n}\n@keyframes hw-drop-pulse {\n 0%, 100% {\n opacity: 0.8;\n }\n 50% {\n opacity: 1;\n }\n}\n.hw-disconnect {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 7px;\n padding: 7px 14px;\n background: var(--hw-bg-hover);\n color: var(--hw-text-2);\n font-size: 11.5px;\n font-weight: 500;\n letter-spacing: -0.01em;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 0;\n animation: hw-disconnect-in 0.18s cubic-bezier(0.22, 1, 0.36, 1);\n}\n@keyframes hw-disconnect-in {\n from {\n opacity: 0;\n transform: translateY(-100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.hw-disconnect-retry {\n flex: none;\n padding: 2px 4px;\n margin: -2px 0;\n border: 0;\n border-radius: 4px;\n background: none;\n color: var(--hw-text);\n font: inherit;\n font-weight: 600;\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n}\n.hw-disconnect-retry:hover {\n text-decoration-thickness: 2px;\n}\n.hw-disconnect-retry:focus-visible {\n outline: 2px solid var(--hw-text);\n outline-offset: 1px;\n}\n.hw-disconnect-spinner {\n width: 9px;\n height: 9px;\n border: 1.5px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n opacity: 0.75;\n flex-shrink: 0;\n animation: hw-spin 0.7s linear infinite;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-disconnect {\n animation: none;\n }\n .hw-disconnect-spinner {\n animation: none;\n border-top-color: currentColor;\n opacity: 0.5;\n }\n}\n.hw-error-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px 24px;\n text-align: center;\n gap: 12px;\n}\n.hw-error-icon {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: #fef2f2;\n color: #ef4444;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hw-error-icon svg {\n width: 24px;\n height: 24px;\n}\n.hw-error-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--hw-text);\n}\n.hw-error-desc {\n font-size: 13px;\n color: var(--hw-text-2);\n}\n.hw-error-btn {\n padding: 8px 20px;\n border: 1px solid var(--hw-border-md);\n border-radius: 8px;\n background: var(--hw-bg);\n color: var(--hw-text);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n.hw-error-btn:hover {\n background: var(--hw-bg-hover);\n}\n.hw-send-error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #fef2f2;\n color: #dc2626;\n font-size: 12px;\n font-weight: 500;\n flex-shrink: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-send-error-retry {\n margin-left: auto;\n padding: 2px 8px;\n border: 1px solid #fca5a5;\n border-radius: 4px;\n background: none;\n color: #dc2626;\n font-size: 11px;\n font-weight: 600;\n cursor: pointer;\n}\n.hw-send-error-retry:hover {\n background: #fee2e2;\n}\n.hw-resolved {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 14px;\n border-top: 1px solid var(--hw-border);\n flex-shrink: 0;\n}\n.hw-resolved-status {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12.5px;\n font-weight: 550;\n color: var(--hw-text);\n}\n.hw-resolved-status svg {\n flex: none;\n color: var(--hw-text-2);\n}\n.hw-csat {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 6px 10px;\n}\n.hw-csat-label,\n.hw-csat-error {\n font-size: 12px;\n color: var(--hw-text-2);\n}\n.hw-csat-error {\n color: var(--hw-text);\n}\n.hw-csat-buttons {\n display: flex;\n gap: 6px;\n}\n.hw-csat-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 30px;\n padding: 0 11px;\n border: 1px solid var(--hw-border-md);\n border-radius: 999px;\n background: var(--hw-bg);\n color: var(--hw-text);\n font: inherit;\n font-size: 12px;\n font-weight: 550;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n.hw-csat-btn svg {\n flex: none;\n}\n.hw-csat-btn:hover {\n background: var(--hw-bg-hover);\n}\n.hw-csat-btn:focus-visible {\n outline: 2px solid var(--hw-text);\n outline-offset: 2px;\n}\n.hw-csat-btn[aria-pressed=true] {\n background: var(--hw-bg-hover);\n border-color: var(--hw-brand, var(--hw-primary));\n box-shadow: inset 0 0 0 1px var(--hw-brand, var(--hw-primary));\n cursor: default;\n}\n.hw-load-more-trigger {\n display: flex;\n justify-content: center;\n min-height: 1px;\n}\n.hw-load-more-trigger:has(.hw-load-more-spinner) {\n padding: 8px 0;\n}\n.hw-load-more-spinner {\n display: flex;\n gap: 3px;\n}\n.hw-load-more-spinner > div {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--hw-text-4);\n animation: hw-loading-pulse 1.4s infinite;\n}\n.hw-load-more-spinner > div:nth-child(2) {\n animation-delay: 0.2s;\n}\n.hw-load-more-spinner > div:nth-child(3) {\n animation-delay: 0.4s;\n}\n.hw-drag-handle {\n display: none;\n}\n@media (max-width: 479px) {\n .hw-drag-handle {\n display: flex;\n justify-content: center;\n padding: 8px 0 4px;\n flex-shrink: 0;\n }\n .hw-drag-handle-pill {\n width: 32px;\n height: 4px;\n border-radius: 2px;\n background: var(--hw-text-4);\n }\n}\n.hw-msg-bubble p {\n margin: 0 0 8px;\n}\n.hw-msg-bubble p:last-child {\n margin-bottom: 0;\n}\n.hw-msg-bubble strong {\n font-weight: 600;\n}\n.hw-msg-bubble em {\n font-style: italic;\n}\n.hw-msg-bubble a {\n color: inherit;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);\n word-break: normal;\n overflow-wrap: anywhere;\n}\n.hw-msg-bubble a:hover {\n opacity: 0.8;\n}\n.hw-msg--visitor .hw-msg-bubble a {\n color: rgba(255, 255, 255, 0.9);\n}\n.hw-msg--visitor .hw-msg-bubble a:hover {\n color: white;\n}\n.hw-msg-bubble ul,\n.hw-msg-bubble ol {\n margin: 4px 0 8px;\n padding-left: 20px;\n}\n.hw-msg-bubble li {\n margin: 2px 0;\n}\n.hw-msg-bubble code {\n padding: 1px 4px;\n border-radius: 3px;\n background: rgba(0, 0, 0, 0.06);\n font-size: 0.9em;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n}\n.hw-msg-bubble pre {\n margin: 4px 0 8px;\n padding: 8px 10px;\n border-radius: 6px;\n background: rgba(0, 0, 0, 0.06);\n overflow-x: auto;\n font-size: 0.85em;\n}\n.hw-msg-bubble pre code {\n padding: 0;\n background: none;\n}\n.hw-msg-bubble blockquote {\n margin: 4px 0 8px;\n padding: 4px 0 4px 12px;\n border-left: 3px solid var(--hw-border-md);\n color: var(--hw-text-2);\n}\n.hw-widget[data-theme=dark] {\n --hw-bg: #1c1c1e;\n --hw-bg-subtle: #161618;\n --hw-bg-hover: #2c2c2e;\n --hw-border: rgba(255, 255, 255, 0.08);\n --hw-border-md: rgba(255, 255, 255, 0.14);\n --hw-text: #f5f5f5;\n --hw-text-1: #f5f5f5;\n --hw-text-2: #a1a1aa;\n --hw-text-3: #71717a;\n --hw-text-4: #52525b;\n --hw-visitor-bubble-bg: #2c2c2e;\n --hw-visitor-bubble-text: #f5f5f5;\n --hw-focus-border: rgba(255, 255, 255, 0.28);\n --hw-focus-ring: rgba(255, 255, 255, 0.08);\n --hw-brand: #f5f5f5;\n --hw-on-brand: #1c1c1e;\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light]) .hw-messages {\n scrollbar-color: rgba(255, 255, 255, 0.26) transparent;\n }\n .hw-widget:not([data-theme=light]) .hw-messages::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n background-clip: content-box;\n }\n .hw-widget:not([data-theme=light]) .hw-messages::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.32);\n background-clip: content-box;\n }\n .hw-widget:not([data-theme=light]) {\n --hw-bg: #1c1c1e;\n --hw-bg-subtle: #161618;\n --hw-bg-hover: #2c2c2e;\n --hw-border: rgba(255, 255, 255, 0.08);\n --hw-border-md: rgba(255, 255, 255, 0.14);\n --hw-text: #f5f5f5;\n --hw-text-1: #f5f5f5;\n --hw-text-2: #a1a1aa;\n --hw-text-3: #71717a;\n --hw-text-4: #52525b;\n --hw-visitor-bubble-bg: #2c2c2e;\n --hw-visitor-bubble-text: #f5f5f5;\n --hw-focus-border: rgba(255, 255, 255, 0.28);\n --hw-focus-ring: rgba(255, 255, 255, 0.08);\n --hw-brand: #f5f5f5;\n --hw-on-brand: #1c1c1e;\n }\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light]) .hw-header {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-header-bot-icon {\n background: var(--hw-bg-hover);\n }\n .hw-header-name,\n .hw-header-title {\n color: var(--hw-text);\n }\n .hw-header-status {\n color: var(--hw-text-2);\n }\n .hw-header-close,\n .hw-header-back {\n color: var(--hw-text-2);\n }\n .hw-header-close:hover,\n .hw-header-back:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n }\n .hw-content-entry {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-content-entry:hover {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border-md);\n }\n .hw-content-empty,\n .hw-empty {\n color: var(--hw-text-3);\n }\n .hw-conv-card {\n border-color: var(--hw-border);\n }\n .hw-recent-row {\n border-color: var(--hw-border);\n }\n .hw-composer-drop-overlay {\n background: rgba(0, 0, 0, 0.6);\n color: var(--hw-text);\n }\n .hw-composer--dragging .hw-composer-box {\n border-color: var(--hw-focus-border);\n box-shadow: 0 0 0 3px var(--hw-focus-ring);\n }\n .hw-hero {\n background:\n linear-gradient(\n 160deg,\n color-mix(in srgb, var(--hw-primary) 40%, black) 0%,\n var(--hw-primary) 50%,\n color-mix(in srgb, var(--hw-primary) 25%, black) 100%);\n }\n .hw-sheet {\n background: var(--hw-bg);\n }\n .hw-card {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border);\n }\n .hw-card:hover {\n background: #333;\n }\n .hw-window {\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n .hw-bubble:focus-visible {\n outline-color: var(--hw-text-3);\n }\n .hw-msg--visitor .hw-msg-bubble {\n background: var(--hw-primary);\n color: white;\n }\n .hw-msg-bubble code {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-msg-bubble pre {\n background: rgba(255, 255, 255, 0.08);\n }\n .hw-composer-box {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-composer-input {\n color: var(--hw-text);\n }\n .hw-tabs {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n .hw-conv-card:hover,\n .hw-recent-row:hover {\n background: var(--hw-bg-hover);\n }\n .hw-send-error {\n background: #450a0a;\n color: #fca5a5;\n }\n .hw-error-icon {\n background: #450a0a;\n color: #f87171;\n }\n .hw-hover-preview {\n background: #1c1c1e;\n border-color: var(--hw-border);\n }\n .hw-content-search-box {\n background: var(--hw-bg-hover);\n border-color: var(--hw-border-md);\n }\n .hw-preview {\n background: var(--hw-bg);\n border-color: var(--hw-border);\n }\n}\n.hw-widget[data-hw-placement=docked] {\n --hw-dock-width: 600px;\n --hw-dock-bar-width: 480px;\n --hw-dock-inset: 24px;\n --hw-bar-max-height: 148px;\n --hw-dock-surface: #ffffff;\n --hw-dock-on-surface: #111111;\n --hw-dock-pill-bg: rgba(44, 44, 48, 0.66);\n --hw-dock-pill-fg: rgba(255, 255, 255, 0.94);\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\n}\n.hw-widget[data-hw-placement=docked] {\n z-index: 2147483000;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock {\n position: fixed;\n left: 0;\n right: 0;\n bottom: var(--hw-dock-inset);\n z-index: 2147483000;\n display: flex;\n flex-direction: column;\n align-items: center;\n pointer-events: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock > * {\n pointer-events: auto;\n}\n.hw-dock-suggestions {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 9px;\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n margin-bottom: 14px;\n}\n.hw-dock-pill-row {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n animation: hw-dock-pill-in 0.42s cubic-bezier(0.2, 0.9, 0.3, 1) both;\n}\n.hw-dock-pill-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n padding: 0;\n border: 0;\n background: none;\n color: var(--hw-dock-pill-fg);\n cursor: pointer;\n align-self: flex-start;\n margin-top: 8px;\n opacity: 0;\n transform: scale(0.85);\n transition:\n opacity 0.12s linear,\n transform 0.12s cubic-bezier(0.25, 1, 0.5, 1),\n color 0.12s linear;\n}\n.hw-dock-pill-dismiss svg {\n width: 11px;\n height: 11px;\n}\n.hw-dock-suggestions:hover .hw-dock-pill-dismiss,\n.hw-dock-suggestions:focus-within .hw-dock-pill-dismiss {\n opacity: 1;\n transform: none;\n}\n.hw-dock-pill-dismiss:hover {\n color: var(--hw-dock-on-surface);\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-pill-dismiss {\n transition: none;\n }\n}\n@media (hover: none) {\n .hw-dock-pill-dismiss {\n opacity: 1;\n transform: none;\n }\n}\n.hw-dock-pill {\n align-self: flex-start;\n padding: 10px 18px;\n border: 1px solid var(--hw-dock-pill-border, transparent);\n border-radius: 999px;\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 500;\n text-align: left;\n background: var(--hw-dock-pill-bg);\n color: var(--hw-dock-pill-fg);\n backdrop-filter: blur(10px) saturate(1.2);\n -webkit-backdrop-filter: blur(10px) saturate(1.2);\n box-shadow: 0 4px 14px -8px rgba(12, 11, 10, 0.28);\n transition:\n background 0.16s,\n border-color 0.16s,\n transform 0.16s;\n}\n.hw-dock-pill {\n backdrop-filter: blur(18px);\n -webkit-backdrop-filter: blur(18px);\n}\n.hw-dock-pill:hover {\n background: color-mix(in srgb, var(--hw-dock-pill-bg) 100%, var(--hw-dock-on-surface) 8%);\n border-color: color-mix(in srgb, var(--hw-dock-pill-border) 100%, var(--hw-dock-on-surface) 10%);\n transform: translateX(3px);\n}\n@keyframes hw-dock-pill-in {\n from {\n opacity: 0;\n transform: translateY(10px) scale(0.97);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-dock-bar {\n display: flex;\n align-items: flex-end;\n gap: 10px;\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n min-height: 52px;\n padding: 10px 10px 10px 18px;\n border: 0;\n border-radius: 26px;\n background: var(--hw-dock-surface);\n color: var(--hw-dock-on-surface);\n box-shadow:\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\n 0 0 0 1px color-mix(in srgb, var(--hw-dock-on-surface) 7%, transparent),\n 0 2px 6px rgba(12, 11, 10, 0.18),\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\n transition:\n border-radius 0.18s ease,\n box-shadow 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),\n width 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.hw-dock-bar:focus-within {\n box-shadow:\n inset 0 1px 0 color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent),\n 0 0 0 1px color-mix(in srgb, var(--hw-primary, #fb923c) 60%, transparent),\n 0 2px 6px rgba(12, 11, 10, 0.18),\n 0 20px 48px -14px rgba(12, 11, 10, 0.45);\n}\n.hw-dock-bar[data-grown=true] {\n border-radius: 20px;\n}\n.hw-dock-input {\n flex: 1;\n min-width: 0;\n min-height: 20px;\n max-height: var(--hw-bar-max-height);\n padding: 6px 0;\n border: 0;\n outline: none;\n resize: none;\n overflow-y: auto;\n background: transparent;\n color: var(--hw-dock-on-surface);\n font: inherit;\n font-size: 14px;\n line-height: 1.45;\n transition: height 0.12s ease;\n}\n.hw-dock-input::placeholder {\n color: color-mix(in srgb, var(--hw-dock-on-surface) 45%, transparent);\n}\n.hw-dock-send {\n flex: none;\n width: 32px;\n height: 32px;\n margin-bottom: 1px;\n border: 0;\n border-radius: 50%;\n display: grid;\n place-items: center;\n cursor: pointer;\n background: var(--hw-primary, #fb923c);\n color: var(--hw-on-brand, #fff);\n transition: transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.16s;\n}\n.hw-dock-send:hover:not(:disabled) {\n transform: scale(1.06);\n}\n.hw-dock-send:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n position: fixed;\n left: 50%;\n right: auto;\n margin-left: calc(var(--hw-dock-width) / -2);\n bottom: calc(var(--hw-dock-inset) + 66px);\n width: var(--hw-dock-width);\n max-width: calc(100vw - 32px);\n height: 420px;\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n left: 16px;\n right: 16px;\n margin-left: 0;\n width: auto;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-bubble {\n display: none;\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-window {\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-suggestions {\n display: none;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-pill,\n .hw-dock-bar,\n .hw-dock-input,\n .hw-dock-send {\n animation: none;\n transition: none;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-composer,\n.hw-widget[data-hw-placement=docked] .hw-tabs,\n.hw-widget[data-hw-placement=docked] .hw-footer-tabs {\n display: none;\n}\n.hw-starters {\n display: flex;\n flex-direction: column;\n margin-top: 10px;\n border-radius: 14px;\n overflow: hidden;\n background: var(--hw-bg);\n box-shadow: inset 0 0 0 1px var(--hw-border);\n}\n.hw-starter {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 11px 14px;\n border: 0;\n border-radius: 0;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text);\n font: inherit;\n text-align: left;\n animation: hw-starter-in 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) both;\n transition: background 0.12s;\n}\n.hw-starter + .hw-starter {\n box-shadow: inset 0 1px 0 var(--hw-border);\n}\n.hw-starter:hover {\n background: var(--hw-bg-hover);\n}\n.hw-starter-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.hw-starter-k {\n font-size: 13px;\n font-weight: 550;\n line-height: 1.35;\n color: var(--hw-text);\n}\n.hw-starter-q {\n font-size: 12px;\n line-height: 1.35;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-starter svg {\n flex: none;\n color: var(--hw-text-3, var(--hw-text-muted));\n opacity: 0.45;\n transition: opacity 0.15s, transform 0.15s;\n}\n.hw-starter:hover svg {\n opacity: 0.9;\n transform: translateX(2px);\n}\n@keyframes hw-starter-in {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-header-back {\n display: none;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-starter {\n animation: none;\n }\n}\n@media (prefers-color-scheme: dark) {\n .hw-widget:not([data-theme=light])[data-hw-placement=docked] {\n --hw-dock-surface: #1f1f23;\n --hw-dock-on-surface: #f4f4f6;\n --hw-dock-pill-bg: rgba(255, 255, 255, 0.1);\n --hw-dock-pill-fg: #e4e4e7;\n --hw-dock-pill-border: rgba(255, 255, 255, 0.14);\n }\n}\n.hw-widget[data-theme=dark][data-hw-placement=docked] {\n --hw-dock-surface: #1f1f23;\n --hw-dock-on-surface: #f4f4f6;\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n --hw-bg: rgba(255, 255, 255, 0.08);\n --hw-bg-subtle: transparent;\n --hw-bg-hover: rgba(255, 255, 255, 0.1);\n --hw-border: rgba(255, 255, 255, 0.14);\n --hw-border-md: rgba(255, 255, 255, 0.22);\n --hw-text: rgba(255, 255, 255, 0.94);\n --hw-text-1: #ffffff;\n --hw-text-2: rgba(255, 255, 255, 0.72);\n --hw-text-3: rgba(255, 255, 255, 0.62);\n --hw-text-4: rgba(255, 255, 255, 0.46);\n --hw-visitor-bubble-bg: rgba(255, 255, 255, 0.16);\n --hw-visitor-bubble-text: #ffffff;\n --hw-brand: rgba(255, 255, 255, 0.92);\n --hw-on-brand: #17161a;\n --hw-focus-border: rgba(255, 255, 255, 0.34);\n --hw-focus-ring: rgba(255, 255, 255, 0.1);\n height: 500px;\n max-height: calc(100vh - 180px);\n border-radius: 24px;\n color: var(--hw-text);\n background:\n linear-gradient(\n 180deg,\n rgba(40, 40, 44, 0.72) 0%,\n rgba(46, 46, 50, 0.7) 55%,\n rgba(52, 52, 56, 0.68) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n background: #2c2c2e;\n }\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-window {\n height: min(60vh, 460px);\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-header--sub {\n padding: 14px 12px 8px 16px;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-status {\n display: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-name {\n font-size: 15.5px;\n font-weight: 560;\n letter-spacing: -0.006em;\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu-conv-name,\n.hw-widget[data-hw-placement=docked] .hw-event-name {\n font-weight: 545;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-bot-icon {\n border-radius: 50%;\n overflow: hidden;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-close:hover,\n.hw-widget[data-hw-placement=docked] .hw-header-menu-btn:hover {\n background: rgba(255, 255, 255, 0.12);\n color: #ffffff;\n}\n.hw-widget[data-hw-placement=docked] .hw-messages {\n padding: 4px 22px 16px;\n gap: 18px;\n -webkit-mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 16px);\n mask-image:\n linear-gradient(\n 180deg,\n transparent 0,\n #000 16px);\n}\n.hw-widget[data-hw-placement=docked] .hw-msg--ai .hw-msg-bubble,\n.hw-widget[data-hw-placement=docked] .hw-msg--team .hw-msg-bubble {\n padding: 0;\n background: transparent;\n border-radius: 0;\n font-size: 15px;\n line-height: 1.55;\n color: var(--hw-text);\n}\n.hw-widget[data-hw-placement=docked] .hw-msg--visitor .hw-msg-bubble {\n background: rgba(255, 255, 255, 0.16);\n color: #ffffff;\n font-size: 14.5px;\n line-height: 1.5;\n}\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble pre,\n.hw-widget[data-hw-placement=docked] .hw-msg-bubble code {\n background: rgba(0, 0, 0, 0.28);\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-row {\n background: rgba(0, 0, 0, 0.26);\n border-color: rgba(255, 255, 255, 0.14);\n}\n.hw-widget[data-hw-placement=docked] .hw-window :focus-visible {\n outline-color: rgba(255, 255, 255, 0.55);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus,\n.hw-widget[data-hw-placement=docked] .hw-email-card-input:focus-visible {\n outline: none;\n box-shadow: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-row:focus-within {\n border-color: rgba(255, 255, 255, 0.42);\n box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.08);\n}\n.hw-widget[data-hw-placement=docked] .hw-email-card-submit {\n background: #ffffff;\n color: #17161a;\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\n position: relative;\n z-index: 3;\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu {\n background: #3a3a3f;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 18px 44px -12px rgba(12, 11, 10, 0.62);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu button:hover {\n background: rgba(255, 255, 255, 0.11);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu button.hw-header-menu-conv[data-active=true] {\n background: rgba(255, 255, 255, 0.09);\n}\n.hw-widget[data-hw-placement=docked] .hw-header-menu-convs {\n border-bottom-color: rgba(255, 255, 255, 0.12);\n}\n.hw-widget[data-hw-placement=docked] .hw-event--card {\n margin: 0;\n background: rgba(255, 255, 255, 0.08);\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);\n}\n.hw-widget[data-hw-placement=docked] .hw-event-avatar {\n background: rgba(255, 255, 255, 0.14);\n color: var(--hw-text-1);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview {\n position: fixed;\n left: 50%;\n right: auto;\n margin-left: calc(var(--hw-dock-bar-width, var(--hw-dock-width)) / -2);\n bottom: calc(var(--hw-dock-inset) + 52px + 12px);\n width: var(--hw-dock-bar-width, var(--hw-dock-width));\n max-width: calc(100vw - 32px);\n border: 0;\n border-radius: 24px;\n color: rgba(255, 255, 255, 0.94);\n background:\n linear-gradient(\n 180deg,\n rgba(40, 40, 44, 0.74) 0%,\n rgba(52, 52, 56, 0.7) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-name,\n.hw-widget[data-hw-placement=docked] .hw-preview-body {\n color: rgba(255, 255, 255, 0.94);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-close {\n color: rgba(255, 255, 255, 0.6);\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-close:hover {\n background: rgba(255, 255, 255, 0.12);\n color: #ffffff;\n}\n.hw-widget[data-hw-placement=docked] .hw-preview-footer {\n color: rgba(255, 255, 255, 0.55);\n border-top-color: rgba(255, 255, 255, 0.1);\n}\n@media (max-width: 640px) {\n .hw-widget[data-hw-placement=docked] .hw-preview {\n left: 16px;\n right: 16px;\n margin-left: 0;\n width: auto;\n }\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-preview {\n background: #2c2c2e;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn {\n padding: 7px 14px;\n font-size: 13px;\n font-weight: 550;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.94);\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\n color: #17161a;\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn:hover:not(:disabled) {\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\n transform: translateY(-1px);\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn[data-tapped=true] {\n background: rgba(255, 255, 255, 0.22);\n color: #ffffff;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);\n transform: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-quick-reply-btn svg {\n opacity: 0.55;\n}\n.hw-widget[data-hw-placement=docked] .hw-offer {\n padding: 7px 14px;\n font-size: 13px;\n background: rgba(255, 255, 255, 0.94);\n color: #17161a;\n box-shadow: 0 1px 3px rgba(12, 11, 10, 0.22);\n transition:\n background 0.15s,\n box-shadow 0.15s,\n transform 0.15s;\n}\n.hw-widget[data-hw-placement=docked] .hw-offer:hover {\n background: #ffffff;\n color: #17161a;\n box-shadow: 0 4px 12px rgba(12, 11, 10, 0.28);\n transform: translateY(-1px);\n}\n.hw-widget[data-hw-placement=docked] .hw-offer svg {\n opacity: 0.55;\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-bar {\n --hw-dock-on-surface: rgba(255, 255, 255, 0.94);\n color: rgba(255, 255, 255, 0.94);\n background:\n linear-gradient(\n 180deg,\n rgba(44, 44, 48, 0.74) 0%,\n rgba(52, 52, 56, 0.72) 100%);\n backdrop-filter: blur(30px);\n -webkit-backdrop-filter: blur(30px);\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 18px 40px -16px rgba(12, 11, 10, 0.45);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\n width: var(--hw-dock-width);\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-bar:focus-within {\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.26), 0 18px 40px -16px rgba(12, 11, 10, 0.5);\n}\n.hw-widget[data-hw-placement=docked][data-hw-open=true] .hw-dock-bar {\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14), 0 22px 52px -18px rgba(12, 11, 10, 0.52);\n}\n.hw-widget[data-hw-placement=docked] .hw-dock-send:not(:disabled) {\n background: #ffffff;\n color: #17161a;\n}\n@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {\n .hw-widget[data-hw-placement=docked] .hw-dock-bar {\n background: #2c2c2e;\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-window {\n transform-origin: 50% 100%;\n animation: hw-dock-panel-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n}\n.hw-widget[data-hw-placement=docked] .hw-window--closing {\n animation: hw-dock-panel-out 0.18s cubic-bezier(0.4, 0, 1, 1) forwards;\n}\n@keyframes hw-dock-panel-in {\n from {\n opacity: 0;\n transform: translateY(14px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@keyframes hw-dock-panel-out {\n from {\n opacity: 1;\n transform: none;\n }\n to {\n opacity: 0;\n transform: translateY(8px) scale(0.99);\n }\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub {\n animation: hw-dock-settle 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.06s both;\n}\n.hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\n animation: hw-dock-settle 0.34s cubic-bezier(0.16, 1, 0.3, 1) 0.11s both;\n}\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-header--sub,\n.hw-widget[data-hw-placement=docked] .hw-window--closing .hw-messages {\n animation: none;\n}\n@keyframes hw-dock-settle {\n from {\n opacity: 0;\n transform: translateY(7px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-widget[data-hw-placement=docked] .hw-window,\n .hw-widget[data-hw-placement=docked] .hw-window--closing,\n .hw-widget[data-hw-placement=docked] .hw-window .hw-header--sub,\n .hw-widget[data-hw-placement=docked] .hw-window .hw-messages {\n animation: none;\n }\n}\n.hw-dock-bar {\n flex-wrap: wrap;\n padding-left: 18px;\n padding-right: 8px;\n}\n.hw-dock-error {\n width: var(--hw-dock-width);\n max-width: calc(100vw - 32px);\n margin-bottom: 8px;\n padding: 8px 14px;\n border-radius: 14px;\n background: rgba(190, 24, 40, 0.92);\n color: #ffffff;\n font-size: 12.5px;\n line-height: 1.35;\n box-shadow: 0 10px 26px -12px rgba(12, 11, 10, 0.5);\n animation: hw-dock-settle 0.22s cubic-bezier(0.16, 1, 0.3, 1) both;\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-error {\n animation: none;\n }\n}\n.hw-dock-previews {\n flex: 0 0 100%;\n order: -1;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 2px 0 8px;\n}\n.hw-dock-lead {\n flex: none;\n display: grid;\n place-items: center;\n width: 32px;\n height: 32px;\n margin-left: -8px;\n}\n.hw-dock-actions {\n flex: none;\n display: flex;\n align-items: center;\n gap: 2px;\n margin-bottom: 1px;\n}\n.hw-dock-tool {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 0;\n border-radius: 50%;\n background: transparent;\n color: color-mix(in srgb, var(--hw-dock-on-surface) 52%, transparent);\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n.hw-dock-tool:hover:not(:disabled) {\n background: color-mix(in srgb, var(--hw-dock-on-surface) 8%, transparent);\n color: var(--hw-dock-on-surface);\n}\n.hw-dock-tool:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.hw-dock-tool[data-active=true] {\n color: #e11d48;\n background: rgba(225, 29, 72, 0.12);\n animation: hw-dock-listening 1.4s ease-in-out infinite;\n}\n@keyframes hw-dock-listening {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(225, 29, 72, 0.35);\n }\n 50% {\n box-shadow: 0 0 0 4px rgba(225, 29, 72, 0);\n }\n}\n.hw-dock-send:disabled {\n opacity: 1;\n background: color-mix(in srgb, var(--hw-dock-on-surface) 9%, transparent);\n color: color-mix(in srgb, var(--hw-dock-on-surface) 38%, transparent);\n}\n@media (prefers-reduced-motion: reduce) {\n .hw-dock-tool[data-active=true] {\n animation: none;\n }\n .hw-dock-bar {\n transition: none;\n }\n}\n.hw-dock-input:focus,\n.hw-dock-input:focus-visible {\n outline: none;\n box-shadow: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-powered {\n display: none;\n}\n.hw-widget[data-hw-placement=docked] .hw-disconnect {\n border-radius: 20px 20px 0 0;\n}\n.hw-msg-meta {\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.hw-msg-author {\n font-weight: 550;\n}\n.hw-msg-meta-sep {\n opacity: 0.55;\n}\n.hw-header-actions {\n position: relative;\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.hw-header-menu-btn {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text-2, var(--hw-text-muted));\n transition: background 0.15s, color 0.15s;\n}\n.hw-header-menu-btn:hover {\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n}\n.hw-header-menu {\n position: absolute;\n top: 36px;\n right: 0;\n z-index: 6;\n min-width: 236px;\n max-width: 288px;\n padding: 5px;\n border-radius: 14px;\n background: var(--hw-bg);\n color: var(--hw-text);\n box-shadow: 0 0 0 1px var(--hw-border), 0 12px 32px -10px rgba(0, 0, 0, 0.32);\n animation: hw-menu-in 0.16s cubic-bezier(0.2, 0.8, 0.2, 1) both;\n}\n@keyframes hw-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px) scale(0.98);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.hw-header-menu button {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 9px 10px;\n border: 0;\n border-radius: 9px;\n cursor: pointer;\n background: transparent;\n color: var(--hw-text);\n font: inherit;\n font-size: 13px;\n text-align: left;\n transition: background 0.14s;\n}\n.hw-header-menu button:hover {\n background: var(--hw-bg-hover);\n}\n.hw-header-menu button svg {\n flex: none;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-header-menu button:hover svg {\n color: var(--hw-brand, var(--hw-primary));\n}\n.hw-header-menu-convs {\n display: flex;\n flex-direction: column;\n max-height: 168px;\n overflow-y: auto;\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px solid var(--hw-border);\n}\n.hw-header-menu button.hw-header-menu-conv {\n flex-direction: column;\n align-items: stretch;\n gap: 2px;\n padding: 8px 10px;\n}\n.hw-header-menu button.hw-header-menu-conv[data-active=true] {\n background: var(--hw-bg-hover);\n}\n.hw-header-menu-conv-top {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n}\n.hw-header-menu-conv-name {\n overflow: hidden;\n font-size: 12.5px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.hw-header-menu-conv-time {\n flex: none;\n font-size: 11px;\n color: var(--hw-text-3, var(--hw-text-muted));\n}\n.hw-header-menu-conv-preview {\n overflow: hidden;\n font-size: 12px;\n color: var(--hw-text-2);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.hw-offers {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 10px;\n}\n.hw-offer {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n border: 0;\n border-radius: 999px;\n cursor: pointer;\n background: var(--hw-bg-hover);\n color: var(--hw-text);\n font: inherit;\n font-size: 12.5px;\n font-weight: 550;\n transition: background 0.15s, color 0.15s;\n}\n.hw-offer:hover {\n background: var(--hw-brand, var(--hw-primary));\n color: var(--hw-on-brand, #fff);\n}\n.hw-offer svg {\n flex: none;\n}\n.hw-sources {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 4px;\n}\n.hw-source {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 5px 14px;\n border-radius: 9px;\n background: transparent;\n color: var(--hw-text);\n text-decoration: none;\n transition: background 0.15s;\n}\n.hw-widget[data-hw-placement=docked] .hw-source {\n margin-inline: -8px;\n padding-inline: 8px;\n}\na.hw-source {\n cursor: pointer;\n}\na.hw-source:hover {\n background: var(--hw-bg-hover);\n}\n.hw-source-n {\n display: grid;\n place-items: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 4px;\n background: var(--hw-brand, var(--hw-primary));\n color: var(--hw-on-brand, #fff);\n font-size: 10px;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n}\n.hw-source-title {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n font-weight: 550;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] {\n --hw-dock-tint: var(--hw-primary);\n --hw-dock-ink: #ffffff;\n --hw-dock-shade: #000000;\n --hw-dock-wash: var(--hw-dock-shade);\n --hw-dock-ink-2: color-mix(in srgb, var(--hw-dock-ink) 86%, var(--hw-dock-tint));\n --hw-dock-ink-3: color-mix(in srgb, var(--hw-dock-ink) 78%, var(--hw-dock-tint));\n --hw-dock-ink-4: color-mix(in srgb, var(--hw-dock-ink) 60%, var(--hw-dock-tint));\n --hw-dock-pill-bg: var(--hw-dock-tint);\n --hw-dock-pill-fg: var(--hw-dock-ink);\n --hw-dock-pill-border: color-mix(in srgb, var(--hw-dock-ink) 30%, transparent);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] :is(.hw-window, .hw-dock-bar, .hw-preview) {\n --hw-text: var(--hw-dock-ink);\n --hw-text-1: var(--hw-dock-ink);\n --hw-text-2: var(--hw-dock-ink-2);\n --hw-text-3: var(--hw-dock-ink-3);\n --hw-text-4: var(--hw-dock-ink-4);\n --hw-text-muted: var(--hw-dock-ink-2);\n --hw-bg: color-mix(in srgb, var(--hw-dock-wash) 12%, transparent);\n --hw-bg-subtle: transparent;\n --hw-bg-hover: color-mix(in srgb, var(--hw-dock-wash) 18%, transparent);\n --hw-border: color-mix(in srgb, var(--hw-dock-ink) 22%, transparent);\n --hw-border-md: color-mix(in srgb, var(--hw-dock-ink) 34%, transparent);\n --hw-focus-border: color-mix(in srgb, var(--hw-dock-ink) 60%, transparent);\n --hw-focus-ring: color-mix(in srgb, var(--hw-dock-ink) 18%, transparent);\n --hw-visitor-bubble-bg: color-mix(in srgb, var(--hw-dock-wash) 14%, transparent);\n --hw-visitor-bubble-text: var(--hw-dock-ink);\n --hw-primary: var(--hw-dock-ink);\n --hw-primary-hover: var(--hw-dock-ink);\n --hw-brand: var(--hw-dock-ink);\n --hw-on-brand: var(--hw-dock-tint);\n --hw-dock-surface: transparent;\n --hw-dock-on-surface: var(--hw-dock-ink);\n color: var(--hw-dock-ink);\n background:\n radial-gradient(\n 70% 60% at 86% 8%,\n var(--hw-dock-tint),\n transparent 64%),\n linear-gradient(\n 165deg,\n color-mix(in srgb, var(--hw-dock-shade) 12%, var(--hw-dock-tint)) 0%,\n color-mix(in srgb, var(--hw-dock-shade) 30%, var(--hw-dock-tint)) 100%);\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n box-shadow: 0 24px 60px -20px rgba(12, 11, 10, 0.5), inset 0 0 0 1px color-mix(in srgb, var(--hw-dock-ink) 16%, transparent);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-msg--visitor .hw-msg-bubble {\n background: var(--hw-dock-ink);\n color: var(--hw-dock-tint);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-msg--visitor .hw-msg-bubble a,\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-msg--visitor .hw-msg-bubble a:hover {\n color: inherit;\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] :is(.hw-dock-send:not(:disabled), .hw-quick-reply-btn, .hw-quick-reply-btn:hover:not(:disabled), .hw-email-card-submit, .hw-offer, .hw-offer:hover) {\n background: var(--hw-dock-ink);\n color: var(--hw-dock-tint);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] :is(.hw-preview-body, .hw-header-close:hover, .hw-header-menu-btn:hover, .hw-preview-close:hover, .hw-quick-reply-btn[data-tapped=true]) {\n color: var(--hw-dock-ink);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] :is(.hw-preview-close, .hw-preview-footer) {\n color: var(--hw-dock-ink-2);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-quick-reply-btn[data-tapped=true] {\n background: color-mix(in srgb, var(--hw-dock-wash) 22%, transparent);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-window :focus-visible {\n outline-color: var(--hw-dock-ink);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-msg-bubble :is(pre, code),\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-email-card-row {\n background: color-mix(in srgb, var(--hw-dock-shade) 26%, transparent);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-header-menu {\n background: color-mix(in srgb, var(--hw-dock-shade) 34%, var(--hw-dock-tint));\n color: var(--hw-dock-ink);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] :is(.hw-header-bot-icon--team, .hw-event-avatar) {\n background: var(--hw-dock-ink);\n color: var(--hw-dock-tint);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-dock-input::placeholder {\n color: var(--hw-dock-ink-3);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-typing-dot {\n background: var(--hw-dock-ink-2);\n}\n.hw-widget[data-hw-placement=docked][data-hw-dock-surface=brand] .hw-disconnect {\n background: color-mix(in srgb, var(--hw-dock-shade) 16%, transparent);\n color: var(--hw-dock-ink-2);\n}\n');
|
|
6971
7773
|
|
|
6972
7774
|
// src/helpway-widget.tsx
|
|
6973
|
-
import { jsx as
|
|
7775
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
6974
7776
|
function HelpwayWidget({
|
|
6975
7777
|
apiKey,
|
|
6976
7778
|
apiUrl,
|
|
@@ -6992,7 +7794,7 @@ function HelpwayWidget({
|
|
|
6992
7794
|
src
|
|
6993
7795
|
}) {
|
|
6994
7796
|
const resolvedApiUrl = apiUrl ?? (src ? src.replace(/\/widget\.js$/, "") : void 0);
|
|
6995
|
-
return /* @__PURE__ */
|
|
7797
|
+
return /* @__PURE__ */ jsx20(
|
|
6996
7798
|
SupportProvider,
|
|
6997
7799
|
{
|
|
6998
7800
|
apiKey,
|
|
@@ -7006,7 +7808,7 @@ function HelpwayWidget({
|
|
|
7006
7808
|
onClose,
|
|
7007
7809
|
onUnreadChange,
|
|
7008
7810
|
theme,
|
|
7009
|
-
children: /* @__PURE__ */
|
|
7811
|
+
children: /* @__PURE__ */ jsx20(AgentAvatarProvider, { value: agentAvatar ?? null, children: /* @__PURE__ */ jsx20(
|
|
7010
7812
|
DefaultWidget,
|
|
7011
7813
|
{
|
|
7012
7814
|
hideLauncher,
|
|
@@ -7020,14 +7822,14 @@ function HelpwayWidget({
|
|
|
7020
7822
|
}
|
|
7021
7823
|
|
|
7022
7824
|
// src/hooks/use-realtime.ts
|
|
7023
|
-
import { useEffect as
|
|
7825
|
+
import { useEffect as useEffect17, useRef as useRef18 } from "react";
|
|
7024
7826
|
function useRealtime(handler) {
|
|
7025
7827
|
const { ws } = useWidgetContext();
|
|
7026
|
-
const handlerRef =
|
|
7027
|
-
|
|
7828
|
+
const handlerRef = useRef18(handler);
|
|
7829
|
+
useEffect17(() => {
|
|
7028
7830
|
handlerRef.current = handler;
|
|
7029
7831
|
});
|
|
7030
|
-
|
|
7832
|
+
useEffect17(() => {
|
|
7031
7833
|
return ws.onEvent((event) => handlerRef.current(event));
|
|
7032
7834
|
}, [ws]);
|
|
7033
7835
|
}
|