@helpway/react 0.8.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +74 -2
- package/dist/index.js +920 -413
- package/dist/index.js.map +1 -1
- package/package.json +1 -3
- package/src/themed/styles.css +328 -6
package/dist/index.js
CHANGED
|
@@ -17,17 +17,17 @@ function generateId() {
|
|
|
17
17
|
}
|
|
18
18
|
function getOrCreateVisitorId(publicKey) {
|
|
19
19
|
try {
|
|
20
|
-
const
|
|
21
|
-
const existing = localStorage.getItem(
|
|
20
|
+
const storageKey2 = keyFor(publicKey);
|
|
21
|
+
const existing = localStorage.getItem(storageKey2);
|
|
22
22
|
if (existing) return existing;
|
|
23
23
|
const legacy = localStorage.getItem(LEGACY_KEY);
|
|
24
24
|
if (legacy) {
|
|
25
|
-
localStorage.setItem(
|
|
25
|
+
localStorage.setItem(storageKey2, legacy);
|
|
26
26
|
localStorage.removeItem(LEGACY_KEY);
|
|
27
27
|
return legacy;
|
|
28
28
|
}
|
|
29
29
|
const id = generateId();
|
|
30
|
-
localStorage.setItem(
|
|
30
|
+
localStorage.setItem(storageKey2, id);
|
|
31
31
|
return id;
|
|
32
32
|
} catch {
|
|
33
33
|
return generateId();
|
|
@@ -67,6 +67,22 @@ function createWidgetClient(config) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// ../types/src/realtime-events.ts
|
|
70
|
+
var WsEventType = {
|
|
71
|
+
ConnectionEstablished: "connectionEstablished",
|
|
72
|
+
ConversationCreated: "conversationCreated",
|
|
73
|
+
ConversationUpdated: "conversationUpdated",
|
|
74
|
+
TimelineItemCreated: "timelineItemCreated",
|
|
75
|
+
TimelineItemUpdated: "timelineItemUpdated",
|
|
76
|
+
TimelineItemDeleted: "timelineItemDeleted",
|
|
77
|
+
ConversationSeen: "conversationSeen",
|
|
78
|
+
ConversationTyping: "conversationTyping",
|
|
79
|
+
AiProcessingProgress: "aiProcessingProgress",
|
|
80
|
+
AiProcessingCompleted: "aiProcessingCompleted",
|
|
81
|
+
AiStreamChunk: "aiStreamChunk",
|
|
82
|
+
VisitorPresenceChanged: "visitorPresenceChanged",
|
|
83
|
+
MemberUpdated: "memberUpdated",
|
|
84
|
+
WorkspaceUnreadCounts: "workspaceUnreadCounts"
|
|
85
|
+
};
|
|
70
86
|
function isRealtimeEvent(data) {
|
|
71
87
|
return typeof data === "object" && data !== null && "type" in data && typeof data.type === "string";
|
|
72
88
|
}
|
|
@@ -207,8 +223,29 @@ var WebSocketManager = class {
|
|
|
207
223
|
// ../widget-core/src/store.ts
|
|
208
224
|
import { createStore } from "zustand/vanilla";
|
|
209
225
|
var CONTENT_CACHE_TTL = 5 * 60 * 1e3;
|
|
226
|
+
var PREVIEW_STORAGE_KEY = "helpway:incoming-preview";
|
|
227
|
+
function loadPersistedPreview() {
|
|
228
|
+
if (typeof window === "undefined") return null;
|
|
229
|
+
try {
|
|
230
|
+
const raw = window.localStorage.getItem(PREVIEW_STORAGE_KEY);
|
|
231
|
+
return raw ? JSON.parse(raw) : null;
|
|
232
|
+
} catch {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function persistPreview(preview) {
|
|
237
|
+
if (typeof window === "undefined") return;
|
|
238
|
+
try {
|
|
239
|
+
if (preview) {
|
|
240
|
+
window.localStorage.setItem(PREVIEW_STORAGE_KEY, JSON.stringify(preview));
|
|
241
|
+
} else {
|
|
242
|
+
window.localStorage.removeItem(PREVIEW_STORAGE_KEY);
|
|
243
|
+
}
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
}
|
|
210
247
|
function createWidgetStore() {
|
|
211
|
-
|
|
248
|
+
const store = createStore((set, get) => ({
|
|
212
249
|
// Initial state
|
|
213
250
|
isReady: false,
|
|
214
251
|
isConnecting: true,
|
|
@@ -220,10 +257,13 @@ function createWidgetStore() {
|
|
|
220
257
|
messages: /* @__PURE__ */ new Map(),
|
|
221
258
|
typingUsers: /* @__PURE__ */ new Map(),
|
|
222
259
|
aiProcessing: /* @__PURE__ */ new Map(),
|
|
260
|
+
streamingText: /* @__PURE__ */ new Map(),
|
|
223
261
|
isOpen: false,
|
|
224
262
|
isDismissed: false,
|
|
225
263
|
view: "home",
|
|
226
|
-
incomingPreview:
|
|
264
|
+
incomingPreview: loadPersistedPreview(),
|
|
265
|
+
announcementPreviews: [],
|
|
266
|
+
unseenAnnouncementCount: 0,
|
|
227
267
|
newConversationPrefill: null,
|
|
228
268
|
contentCache: /* @__PURE__ */ new Map(),
|
|
229
269
|
// ── Lifecycle ────────────────────────────────────
|
|
@@ -360,6 +400,18 @@ function createWidgetStore() {
|
|
|
360
400
|
return { aiProcessing: next };
|
|
361
401
|
});
|
|
362
402
|
},
|
|
403
|
+
appendStreamChunk(conversationId, delta, done) {
|
|
404
|
+
set((state) => {
|
|
405
|
+
const next = new Map(state.streamingText);
|
|
406
|
+
const prev = next.get(conversationId) ?? "";
|
|
407
|
+
if (done) {
|
|
408
|
+
next.delete(conversationId);
|
|
409
|
+
} else {
|
|
410
|
+
next.set(conversationId, prev + delta);
|
|
411
|
+
}
|
|
412
|
+
return { streamingText: next };
|
|
413
|
+
});
|
|
414
|
+
},
|
|
363
415
|
// ── Identity ─────────────────────────────────────
|
|
364
416
|
updateVisitorContact(contact) {
|
|
365
417
|
set((state) => ({
|
|
@@ -378,7 +430,8 @@ function createWidgetStore() {
|
|
|
378
430
|
setOpen(open) {
|
|
379
431
|
set((s) => ({
|
|
380
432
|
isOpen: open,
|
|
381
|
-
incomingPreview: open ? null : s.incomingPreview
|
|
433
|
+
incomingPreview: open ? null : s.incomingPreview,
|
|
434
|
+
announcementPreviews: open ? [] : s.announcementPreviews
|
|
382
435
|
}));
|
|
383
436
|
},
|
|
384
437
|
setDismissed(dismissed) {
|
|
@@ -393,6 +446,27 @@ function createWidgetStore() {
|
|
|
393
446
|
dismissPreview() {
|
|
394
447
|
set({ incomingPreview: null });
|
|
395
448
|
},
|
|
449
|
+
// ── Announcements ────────────────────────────────
|
|
450
|
+
setAnnouncementPreview(preview) {
|
|
451
|
+
set((s) => ({
|
|
452
|
+
announcementPreviews: [
|
|
453
|
+
...s.announcementPreviews.filter((p) => p.tabId !== preview.tabId),
|
|
454
|
+
preview
|
|
455
|
+
]
|
|
456
|
+
}));
|
|
457
|
+
},
|
|
458
|
+
dismissAnnouncementPreview(slug) {
|
|
459
|
+
if (slug) {
|
|
460
|
+
set((s) => ({
|
|
461
|
+
announcementPreviews: s.announcementPreviews.filter((p) => p.slug !== slug)
|
|
462
|
+
}));
|
|
463
|
+
} else {
|
|
464
|
+
set({ announcementPreviews: [] });
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
setUnseenAnnouncementCount(count) {
|
|
468
|
+
set({ unseenAnnouncementCount: count });
|
|
469
|
+
},
|
|
396
470
|
// ── Content Cache ────────────────────────────────
|
|
397
471
|
setContentCache(key, data) {
|
|
398
472
|
get().contentCache.set(key, { data, ts: Date.now() });
|
|
@@ -401,7 +475,7 @@ function createWidgetStore() {
|
|
|
401
475
|
handleRealtimeEvent(event) {
|
|
402
476
|
const state = get();
|
|
403
477
|
switch (event.type) {
|
|
404
|
-
case
|
|
478
|
+
case WsEventType.TimelineItemCreated: {
|
|
405
479
|
if (event.item.visibility === "public") {
|
|
406
480
|
const isAgentAuthored = !!event.item.aiAgentId && !event.item.visitorId && !event.item.userId;
|
|
407
481
|
const existing = state.messages.get(event.conversationId);
|
|
@@ -442,7 +516,7 @@ function createWidgetStore() {
|
|
|
442
516
|
}
|
|
443
517
|
break;
|
|
444
518
|
}
|
|
445
|
-
case
|
|
519
|
+
case WsEventType.ConversationUpdated: {
|
|
446
520
|
set((s) => ({
|
|
447
521
|
conversations: s.conversations.map(
|
|
448
522
|
(c) => c.id === event.conversationId ? { ...c, ...event.updates } : c
|
|
@@ -450,7 +524,7 @@ function createWidgetStore() {
|
|
|
450
524
|
}));
|
|
451
525
|
break;
|
|
452
526
|
}
|
|
453
|
-
case
|
|
527
|
+
case WsEventType.ConversationTyping: {
|
|
454
528
|
if (!event.visitorId) {
|
|
455
529
|
state.setTyping(event.conversationId, event.isTyping);
|
|
456
530
|
if (event.isTyping) {
|
|
@@ -461,17 +535,23 @@ function createWidgetStore() {
|
|
|
461
535
|
}
|
|
462
536
|
break;
|
|
463
537
|
}
|
|
464
|
-
case
|
|
538
|
+
case WsEventType.AiProcessingProgress: {
|
|
465
539
|
state.setAiProcessing(event.conversationId, true);
|
|
466
540
|
state.setTyping(event.conversationId, true);
|
|
467
541
|
break;
|
|
468
542
|
}
|
|
469
|
-
case
|
|
543
|
+
case WsEventType.AiProcessingCompleted: {
|
|
470
544
|
state.setAiProcessing(event.conversationId, false);
|
|
471
545
|
state.setTyping(event.conversationId, false);
|
|
472
546
|
break;
|
|
473
547
|
}
|
|
474
|
-
case
|
|
548
|
+
case WsEventType.AiStreamChunk: {
|
|
549
|
+
state.setAiProcessing(event.conversationId, false);
|
|
550
|
+
state.setTyping(event.conversationId, false);
|
|
551
|
+
state.appendStreamChunk(event.conversationId, event.delta, event.done);
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
case WsEventType.ConversationCreated: {
|
|
475
555
|
const conv = event.conversation;
|
|
476
556
|
const alreadyPresent = state.conversations.some((c) => c.id === conv.id);
|
|
477
557
|
if (alreadyPresent) break;
|
|
@@ -495,6 +575,16 @@ function createWidgetStore() {
|
|
|
495
575
|
}
|
|
496
576
|
}
|
|
497
577
|
}));
|
|
578
|
+
if (typeof window !== "undefined") {
|
|
579
|
+
let last = store.getState().incomingPreview;
|
|
580
|
+
store.subscribe((s) => {
|
|
581
|
+
if (s.incomingPreview !== last) {
|
|
582
|
+
last = s.incomingPreview;
|
|
583
|
+
persistPreview(s.incomingPreview);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
return store;
|
|
498
588
|
}
|
|
499
589
|
|
|
500
590
|
// ../widget-core/src/api.ts
|
|
@@ -672,6 +762,8 @@ var en = {
|
|
|
672
762
|
"widget.reply_time": "We typically reply in a few minutes",
|
|
673
763
|
"widget.recent_conversations": "Recent conversations",
|
|
674
764
|
"widget.see_all": "See all conversations",
|
|
765
|
+
"widget.whats_new": "What's New",
|
|
766
|
+
"widget.view_all": "View all",
|
|
675
767
|
// Messages tab
|
|
676
768
|
"widget.no_messages": "No messages yet",
|
|
677
769
|
"widget.no_messages_desc": "Start a conversation to get help",
|
|
@@ -690,10 +782,10 @@ var en = {
|
|
|
690
782
|
"widget.csat_label": "How was your experience?",
|
|
691
783
|
"widget.csat_thanks": "Thanks for your feedback!",
|
|
692
784
|
// Inline email collection (after AI reply)
|
|
693
|
-
"widget.email_title": "
|
|
694
|
-
"widget.email_subtitle": "
|
|
785
|
+
"widget.email_title": "Don't miss our reply",
|
|
786
|
+
"widget.email_subtitle": "We'll email you when we respond",
|
|
695
787
|
"widget.email_placeholder": "you@email.com",
|
|
696
|
-
"widget.email_continue": "
|
|
788
|
+
"widget.email_continue": "Send",
|
|
697
789
|
"widget.email_saved": "You'll be notified by email",
|
|
698
790
|
"widget.email_dismiss": "No thanks",
|
|
699
791
|
// Errors
|
|
@@ -1077,6 +1169,29 @@ function SupportProvider({
|
|
|
1077
1169
|
}
|
|
1078
1170
|
}
|
|
1079
1171
|
bootstrap();
|
|
1172
|
+
let pageDebounce = null;
|
|
1173
|
+
const reportPage = () => {
|
|
1174
|
+
if (typeof window === "undefined") return;
|
|
1175
|
+
if (pageDebounce) clearTimeout(pageDebounce);
|
|
1176
|
+
pageDebounce = setTimeout(() => {
|
|
1177
|
+
client.widget.updatePage.mutate({
|
|
1178
|
+
url: window.location.href,
|
|
1179
|
+
title: document.title || window.location.pathname
|
|
1180
|
+
}).catch(() => {
|
|
1181
|
+
});
|
|
1182
|
+
}, 250);
|
|
1183
|
+
};
|
|
1184
|
+
const origPush = window.history.pushState.bind(window.history);
|
|
1185
|
+
const origReplace = window.history.replaceState.bind(window.history);
|
|
1186
|
+
window.history.pushState = function patchedPush(...args) {
|
|
1187
|
+
origPush(...args);
|
|
1188
|
+
reportPage();
|
|
1189
|
+
};
|
|
1190
|
+
window.history.replaceState = function patchedReplace(...args) {
|
|
1191
|
+
origReplace(...args);
|
|
1192
|
+
reportPage();
|
|
1193
|
+
};
|
|
1194
|
+
window.addEventListener("popstate", reportPage);
|
|
1080
1195
|
let markSeenTimer = null;
|
|
1081
1196
|
const scheduleMarkSeen = (conversationId) => {
|
|
1082
1197
|
if (markSeenTimer) clearTimeout(markSeenTimer);
|
|
@@ -1112,6 +1227,10 @@ function SupportProvider({
|
|
|
1112
1227
|
unsub();
|
|
1113
1228
|
clearInterval(wsCheck);
|
|
1114
1229
|
if (markSeenTimer) clearTimeout(markSeenTimer);
|
|
1230
|
+
if (pageDebounce) clearTimeout(pageDebounce);
|
|
1231
|
+
window.history.pushState = origPush;
|
|
1232
|
+
window.history.replaceState = origReplace;
|
|
1233
|
+
window.removeEventListener("popstate", reportPage);
|
|
1115
1234
|
ws.disconnect();
|
|
1116
1235
|
};
|
|
1117
1236
|
}, [client, store, ws, bootstrapAttempt]);
|
|
@@ -1291,10 +1410,171 @@ function inferApiUrl() {
|
|
|
1291
1410
|
}
|
|
1292
1411
|
|
|
1293
1412
|
// src/themed/default-widget.tsx
|
|
1294
|
-
import { useCallback as
|
|
1413
|
+
import { useCallback as useCallback12, useEffect as useEffect13, useRef as useRef14, useState as useState13 } from "react";
|
|
1414
|
+
|
|
1415
|
+
// src/hooks/use-announcements.ts
|
|
1416
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
|
|
1417
|
+
function storageKey(websiteId, visitorId) {
|
|
1418
|
+
return `helpway:${websiteId}:${visitorId}:announcements:seen`;
|
|
1419
|
+
}
|
|
1420
|
+
function hasSeenKey(websiteId, visitorId) {
|
|
1421
|
+
try {
|
|
1422
|
+
return localStorage.getItem(storageKey(websiteId, visitorId)) !== null;
|
|
1423
|
+
} catch {
|
|
1424
|
+
return false;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
function getSeenSlugs(websiteId, visitorId) {
|
|
1428
|
+
try {
|
|
1429
|
+
const raw = localStorage.getItem(storageKey(websiteId, visitorId));
|
|
1430
|
+
if (!raw) return /* @__PURE__ */ new Set();
|
|
1431
|
+
return new Set(JSON.parse(raw));
|
|
1432
|
+
} catch {
|
|
1433
|
+
return /* @__PURE__ */ new Set();
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
function addSeenSlug(websiteId, visitorId, slug) {
|
|
1437
|
+
try {
|
|
1438
|
+
const seen = getSeenSlugs(websiteId, visitorId);
|
|
1439
|
+
seen.add(slug);
|
|
1440
|
+
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));
|
|
1441
|
+
} catch {
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
function addSeenSlugs(websiteId, visitorId, slugs) {
|
|
1445
|
+
try {
|
|
1446
|
+
const seen = getSeenSlugs(websiteId, visitorId);
|
|
1447
|
+
for (const s of slugs) seen.add(s);
|
|
1448
|
+
localStorage.setItem(storageKey(websiteId, visitorId), JSON.stringify([...seen]));
|
|
1449
|
+
} catch {
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
function filterUnseen(entries, seen) {
|
|
1453
|
+
return entries.filter((e) => !seen.has(e.slug));
|
|
1454
|
+
}
|
|
1455
|
+
var EMPTY_TABS = [];
|
|
1456
|
+
function useAnnouncements() {
|
|
1457
|
+
const { client, store } = useWidgetContext();
|
|
1458
|
+
const isReady = useWidgetStore((s) => s.isReady);
|
|
1459
|
+
const websiteId = useWidgetStore((s) => s.website?.id) ?? null;
|
|
1460
|
+
const visitorId = useWidgetStore((s) => s.visitor?.id) ?? null;
|
|
1461
|
+
const isAnonymous = useWidgetStore((s) => !s.visitor?.contact);
|
|
1462
|
+
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS;
|
|
1463
|
+
const announcementTabs = useMemo(
|
|
1464
|
+
() => contentTabs.filter((t2) => t2.isAnnouncements),
|
|
1465
|
+
[contentTabs]
|
|
1466
|
+
);
|
|
1467
|
+
const checkedRef = useRef2(false);
|
|
1468
|
+
useEffect2(() => {
|
|
1469
|
+
if (!isReady || !websiteId || !visitorId || announcementTabs.length === 0) return;
|
|
1470
|
+
if (checkedRef.current) return;
|
|
1471
|
+
checkedRef.current = true;
|
|
1472
|
+
const isFirstVisit = !hasSeenKey(websiteId, visitorId);
|
|
1473
|
+
let pending = announcementTabs.length;
|
|
1474
|
+
let totalUnseen = 0;
|
|
1475
|
+
const allSlugs = [];
|
|
1476
|
+
function onTabDone(entries, tab) {
|
|
1477
|
+
allSlugs.push(...entries.map((e) => e.slug));
|
|
1478
|
+
if (!(isFirstVisit && !isAnonymous) && entries.length > 0) {
|
|
1479
|
+
const seen = getSeenSlugs(websiteId, visitorId);
|
|
1480
|
+
const unseen = filterUnseen(entries, seen);
|
|
1481
|
+
totalUnseen += unseen.length;
|
|
1482
|
+
const newest = unseen[0];
|
|
1483
|
+
if (newest && !store.getState().isOpen) {
|
|
1484
|
+
const badgeField = tab.display?.badgeField;
|
|
1485
|
+
store.getState().setAnnouncementPreview({
|
|
1486
|
+
title: newest.title,
|
|
1487
|
+
body: newest.body,
|
|
1488
|
+
slug: newest.slug,
|
|
1489
|
+
tabId: tab.id,
|
|
1490
|
+
badge: badgeField ? newest.customFields[badgeField] ?? null : null
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
pending--;
|
|
1495
|
+
if (pending === 0) {
|
|
1496
|
+
if (isFirstVisit && !isAnonymous) {
|
|
1497
|
+
if (allSlugs.length > 0) {
|
|
1498
|
+
addSeenSlugs(websiteId, visitorId, allSlugs);
|
|
1499
|
+
}
|
|
1500
|
+
store.getState().setUnseenAnnouncementCount(0);
|
|
1501
|
+
} else {
|
|
1502
|
+
store.getState().setUnseenAnnouncementCount(totalUnseen);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
for (const tab of announcementTabs) {
|
|
1507
|
+
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
1508
|
+
const cached = store.getState().contentCache.get(cacheKey);
|
|
1509
|
+
if (cached && Date.now() - cached.ts < CONTENT_CACHE_TTL) {
|
|
1510
|
+
onTabDone(cached.data, tab);
|
|
1511
|
+
} else {
|
|
1512
|
+
client.widget.getContent.query({ tabId: tab.id, page: 1, limit: 5, language: getLocale() }).then((result) => {
|
|
1513
|
+
const entries = result.items ?? [];
|
|
1514
|
+
store.getState().setContentCache(cacheKey, entries);
|
|
1515
|
+
onTabDone(entries, tab);
|
|
1516
|
+
}).catch(() => {
|
|
1517
|
+
onTabDone([], tab);
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
}, [isReady, websiteId, visitorId, isAnonymous, announcementTabs, client, store]);
|
|
1522
|
+
const markEntrySeen = useCallback2(
|
|
1523
|
+
(slug) => {
|
|
1524
|
+
if (!websiteId || !visitorId || announcementTabs.length === 0) return;
|
|
1525
|
+
addSeenSlug(websiteId, visitorId, slug);
|
|
1526
|
+
const seen = getSeenSlugs(websiteId, visitorId);
|
|
1527
|
+
let total = 0;
|
|
1528
|
+
for (const tab of announcementTabs) {
|
|
1529
|
+
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
1530
|
+
const cached = store.getState().contentCache.get(cacheKey);
|
|
1531
|
+
if (cached) {
|
|
1532
|
+
total += filterUnseen(cached.data, seen).length;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
store.getState().setUnseenAnnouncementCount(total);
|
|
1536
|
+
store.getState().dismissAnnouncementPreview(slug);
|
|
1537
|
+
},
|
|
1538
|
+
[websiteId, visitorId, announcementTabs, store]
|
|
1539
|
+
);
|
|
1540
|
+
const markAllSeen = useCallback2(() => {
|
|
1541
|
+
if (!websiteId || !visitorId || announcementTabs.length === 0) return;
|
|
1542
|
+
for (const tab of announcementTabs) {
|
|
1543
|
+
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
1544
|
+
const cached = store.getState().contentCache.get(cacheKey);
|
|
1545
|
+
if (cached) {
|
|
1546
|
+
const entries = cached.data;
|
|
1547
|
+
addSeenSlugs(websiteId, visitorId, entries.map((e) => e.slug));
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
store.getState().setUnseenAnnouncementCount(0);
|
|
1551
|
+
store.getState().dismissAnnouncementPreview();
|
|
1552
|
+
}, [websiteId, visitorId, announcementTabs, store]);
|
|
1553
|
+
const getUnseenEntries = useCallback2(() => {
|
|
1554
|
+
if (announcementTabs.length === 0 || !websiteId || !visitorId) return [];
|
|
1555
|
+
const seen = getSeenSlugs(websiteId, visitorId);
|
|
1556
|
+
const result = [];
|
|
1557
|
+
for (const tab of announcementTabs) {
|
|
1558
|
+
const cacheKey = `announcements:${tab.id}:${getLocale()}`;
|
|
1559
|
+
const cached = store.getState().contentCache.get(cacheKey);
|
|
1560
|
+
if (cached) {
|
|
1561
|
+
for (const entry of filterUnseen(cached.data, seen)) {
|
|
1562
|
+
result.push({ ...entry, tabId: tab.id });
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return result;
|
|
1567
|
+
}, [announcementTabs, websiteId, visitorId, store]);
|
|
1568
|
+
return {
|
|
1569
|
+
announcementTabs,
|
|
1570
|
+
markEntrySeen,
|
|
1571
|
+
markAllSeen,
|
|
1572
|
+
getUnseenEntries
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1295
1575
|
|
|
1296
1576
|
// src/hooks/use-composer.ts
|
|
1297
|
-
import { useCallback as
|
|
1577
|
+
import { useCallback as useCallback3, useState as useState2 } from "react";
|
|
1298
1578
|
var MAX_ATTACHMENTS = 10;
|
|
1299
1579
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
1300
1580
|
function useComposer(conversationId) {
|
|
@@ -1304,7 +1584,7 @@ function useComposer(conversationId) {
|
|
|
1304
1584
|
const [attachments, setAttachments] = useState2([]);
|
|
1305
1585
|
const [sendError, setSendError] = useState2(null);
|
|
1306
1586
|
const [emailGateConvId, setEmailGateConvId] = useState2(null);
|
|
1307
|
-
const addFiles =
|
|
1587
|
+
const addFiles = useCallback3(
|
|
1308
1588
|
async (files) => {
|
|
1309
1589
|
if (!conversationId) return;
|
|
1310
1590
|
const remaining = MAX_ATTACHMENTS - attachments.length;
|
|
@@ -1347,14 +1627,14 @@ function useComposer(conversationId) {
|
|
|
1347
1627
|
},
|
|
1348
1628
|
[conversationId, attachments.length, client]
|
|
1349
1629
|
);
|
|
1350
|
-
const removeAttachment =
|
|
1630
|
+
const removeAttachment = useCallback3((id) => {
|
|
1351
1631
|
setAttachments((prev) => {
|
|
1352
1632
|
const item = prev.find((a) => a.id === id);
|
|
1353
1633
|
if (item?.previewUrl) URL.revokeObjectURL(item.previewUrl);
|
|
1354
1634
|
return prev.filter((a) => a.id !== id);
|
|
1355
1635
|
});
|
|
1356
1636
|
}, []);
|
|
1357
|
-
const submit =
|
|
1637
|
+
const submit = useCallback3(async () => {
|
|
1358
1638
|
const trimmed = text.trim();
|
|
1359
1639
|
const readyParts = attachments.filter((a) => a.part !== null).map((a) => a.part);
|
|
1360
1640
|
const hasText = trimmed.length > 0;
|
|
@@ -1452,7 +1732,7 @@ function useComposer(conversationId) {
|
|
|
1452
1732
|
setIsSubmitting(false);
|
|
1453
1733
|
}
|
|
1454
1734
|
}, [text, attachments, conversationId, isSubmitting, client, ws, store]);
|
|
1455
|
-
const clearSendError =
|
|
1735
|
+
const clearSendError = useCallback3(() => setSendError(null), []);
|
|
1456
1736
|
return {
|
|
1457
1737
|
text,
|
|
1458
1738
|
setText,
|
|
@@ -1481,17 +1761,17 @@ function fileToBase64(file) {
|
|
|
1481
1761
|
}
|
|
1482
1762
|
|
|
1483
1763
|
// src/hooks/use-conversations.ts
|
|
1484
|
-
import { useCallback as
|
|
1764
|
+
import { useCallback as useCallback4, useRef as useRef3, useState as useState3 } from "react";
|
|
1485
1765
|
function useConversations() {
|
|
1486
1766
|
const { client, store } = useWidgetContext();
|
|
1487
1767
|
const conversations = useWidgetStore((s) => s.conversations);
|
|
1488
1768
|
const setActiveConversation = useWidgetStore((s) => s.setActiveConversation);
|
|
1489
1769
|
const [isCreating, setIsCreating] = useState3(false);
|
|
1490
|
-
const clientRef =
|
|
1491
|
-
const storeRef =
|
|
1770
|
+
const clientRef = useRef3(client);
|
|
1771
|
+
const storeRef = useRef3(store);
|
|
1492
1772
|
clientRef.current = client;
|
|
1493
1773
|
storeRef.current = store;
|
|
1494
|
-
const create =
|
|
1774
|
+
const create = useCallback4(async (text) => {
|
|
1495
1775
|
setIsCreating(true);
|
|
1496
1776
|
const tempConversationId = `temp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
1497
1777
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1555,10 +1835,10 @@ function useConversations() {
|
|
|
1555
1835
|
}
|
|
1556
1836
|
|
|
1557
1837
|
// src/hooks/use-i18n.ts
|
|
1558
|
-
import { useEffect as
|
|
1838
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
1559
1839
|
function useI18n() {
|
|
1560
1840
|
const [rev, setRev] = useState4(() => getI18nRevision());
|
|
1561
|
-
|
|
1841
|
+
useEffect3(() => {
|
|
1562
1842
|
return onLocaleChange(() => {
|
|
1563
1843
|
setRev(getI18nRevision());
|
|
1564
1844
|
});
|
|
@@ -1567,7 +1847,7 @@ function useI18n() {
|
|
|
1567
1847
|
}
|
|
1568
1848
|
|
|
1569
1849
|
// src/hooks/use-presence.ts
|
|
1570
|
-
import { useCallback as
|
|
1850
|
+
import { useCallback as useCallback5, useRef as useRef4 } from "react";
|
|
1571
1851
|
function usePresence(conversationId) {
|
|
1572
1852
|
const { ws } = useWidgetContext();
|
|
1573
1853
|
const isTyping = useWidgetStore(
|
|
@@ -1576,9 +1856,9 @@ function usePresence(conversationId) {
|
|
|
1576
1856
|
const isAiProcessing = useWidgetStore(
|
|
1577
1857
|
(s) => conversationId ? s.aiProcessing.get(conversationId) ?? false : false
|
|
1578
1858
|
);
|
|
1579
|
-
const typingTimer =
|
|
1580
|
-
const isSendingTyping =
|
|
1581
|
-
const setTyping =
|
|
1859
|
+
const typingTimer = useRef4(null);
|
|
1860
|
+
const isSendingTyping = useRef4(false);
|
|
1861
|
+
const setTyping = useCallback5(
|
|
1582
1862
|
(typing) => {
|
|
1583
1863
|
if (!conversationId) return;
|
|
1584
1864
|
if (typingTimer.current) clearTimeout(typingTimer.current);
|
|
@@ -1604,7 +1884,7 @@ function usePresence(conversationId) {
|
|
|
1604
1884
|
}
|
|
1605
1885
|
|
|
1606
1886
|
// src/hooks/use-timeline.ts
|
|
1607
|
-
import { useCallback as
|
|
1887
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useRef as useRef5, useState as useState5 } from "react";
|
|
1608
1888
|
var EMPTY_ITEMS = [];
|
|
1609
1889
|
function useTimeline(conversationId) {
|
|
1610
1890
|
const { client, store } = useWidgetContext();
|
|
@@ -1613,12 +1893,12 @@ function useTimeline(conversationId) {
|
|
|
1613
1893
|
);
|
|
1614
1894
|
const [isLoading, setIsLoading] = useState5(false);
|
|
1615
1895
|
const [hasMore, setHasMore] = useState5(false);
|
|
1616
|
-
const cursorRef =
|
|
1617
|
-
const clientRef =
|
|
1618
|
-
const storeRef =
|
|
1896
|
+
const cursorRef = useRef5(void 0);
|
|
1897
|
+
const clientRef = useRef5(client);
|
|
1898
|
+
const storeRef = useRef5(store);
|
|
1619
1899
|
clientRef.current = client;
|
|
1620
1900
|
storeRef.current = store;
|
|
1621
|
-
|
|
1901
|
+
useEffect4(() => {
|
|
1622
1902
|
if (!conversationId) return;
|
|
1623
1903
|
if (conversationId.startsWith("temp-")) return;
|
|
1624
1904
|
let cancelled = false;
|
|
@@ -1659,7 +1939,7 @@ function useTimeline(conversationId) {
|
|
|
1659
1939
|
cancelled = true;
|
|
1660
1940
|
};
|
|
1661
1941
|
}, [conversationId]);
|
|
1662
|
-
const loadMore =
|
|
1942
|
+
const loadMore = useCallback6(async () => {
|
|
1663
1943
|
if (!conversationId || !hasMore || isLoading) return;
|
|
1664
1944
|
setIsLoading(true);
|
|
1665
1945
|
try {
|
|
@@ -1702,7 +1982,7 @@ function useWidget() {
|
|
|
1702
1982
|
}
|
|
1703
1983
|
|
|
1704
1984
|
// src/themed/composer.tsx
|
|
1705
|
-
import { useCallback as
|
|
1985
|
+
import { useCallback as useCallback7, useRef as useRef8, useState as useState7 } from "react";
|
|
1706
1986
|
|
|
1707
1987
|
// src/themed/icons.tsx
|
|
1708
1988
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
@@ -1880,11 +2160,11 @@ function StarIcon({ size = 24, ...props }) {
|
|
|
1880
2160
|
}
|
|
1881
2161
|
|
|
1882
2162
|
// src/themed/message-bubble.tsx
|
|
1883
|
-
import { useEffect as
|
|
2163
|
+
import { useEffect as useEffect6, useLayoutEffect, useRef as useRef7, useState as useState6 } from "react";
|
|
1884
2164
|
import { createPortal } from "react-dom";
|
|
1885
2165
|
|
|
1886
2166
|
// src/themed/content/simple-markdown.tsx
|
|
1887
|
-
import { useEffect as
|
|
2167
|
+
import { useEffect as useEffect5, useRef as useRef6 } from "react";
|
|
1888
2168
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1889
2169
|
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>`;
|
|
1890
2170
|
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>`;
|
|
@@ -1965,9 +2245,9 @@ function MarkdownContent({
|
|
|
1965
2245
|
bodyMarkdown,
|
|
1966
2246
|
className
|
|
1967
2247
|
}) {
|
|
1968
|
-
const rootRef =
|
|
2248
|
+
const rootRef = useRef6(null);
|
|
1969
2249
|
const html = bodyHtml ?? (bodyMarkdown ? renderMarkdown(bodyMarkdown) : "");
|
|
1970
|
-
|
|
2250
|
+
useEffect5(() => {
|
|
1971
2251
|
const root = rootRef.current;
|
|
1972
2252
|
if (!root) return;
|
|
1973
2253
|
const isWhitespaceOnly = (el) => {
|
|
@@ -1986,7 +2266,7 @@ function MarkdownContent({
|
|
|
1986
2266
|
};
|
|
1987
2267
|
removeEmpties();
|
|
1988
2268
|
}, [html]);
|
|
1989
|
-
|
|
2269
|
+
useEffect5(() => {
|
|
1990
2270
|
const root = rootRef.current;
|
|
1991
2271
|
if (!root) return;
|
|
1992
2272
|
const handler = (e) => {
|
|
@@ -2031,11 +2311,14 @@ function MessageBubble({
|
|
|
2031
2311
|
onQuickReplyTap
|
|
2032
2312
|
}) {
|
|
2033
2313
|
const senderClass = `hw-msg--${sender}`;
|
|
2034
|
-
const bubbleRef =
|
|
2314
|
+
const bubbleRef = useRef7(null);
|
|
2035
2315
|
const imageParts = parts?.filter((p) => p.type === "image") ?? [];
|
|
2036
2316
|
const fileParts = parts?.filter((p) => p.type === "file") ?? [];
|
|
2317
|
+
const linkPreviews = parts?.filter(
|
|
2318
|
+
(p) => p.type === "link-preview"
|
|
2319
|
+
) ?? [];
|
|
2037
2320
|
const hasText = text.length > 0;
|
|
2038
|
-
|
|
2321
|
+
useEffect6(() => {
|
|
2039
2322
|
const bubble = bubbleRef.current;
|
|
2040
2323
|
if (!bubble || sender !== "ai" && sender !== "team") return;
|
|
2041
2324
|
const handleClick = (event) => {
|
|
@@ -2051,6 +2334,7 @@ function MessageBubble({
|
|
|
2051
2334
|
imageParts.length > 0 && /* @__PURE__ */ jsx4("div", { className: "hw-msg-images", children: imageParts.map((img, i) => /* @__PURE__ */ jsx4(PreviewableThumbnail, { src: img.url }, i)) }),
|
|
2052
2335
|
hasText && /* @__PURE__ */ jsx4("div", { className: "hw-msg-bubble", ref: bubbleRef, children: sender === "ai" || sender === "team" ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: renderMarkdown(text) } }) : /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: linkifyText(text) } }) }),
|
|
2053
2336
|
fileParts.length > 0 && /* @__PURE__ */ jsx4("div", { className: "hw-msg-files", children: fileParts.map((file, i) => /* @__PURE__ */ jsx4(FileCard, { file }, i)) }),
|
|
2337
|
+
linkPreviews.length > 0 && /* @__PURE__ */ jsx4("div", { className: "hw-msg-links", children: linkPreviews.map((lp, i) => /* @__PURE__ */ jsx4(LinkPreviewCard, { preview: lp }, i)) }),
|
|
2054
2338
|
metadata?.kind === "quick_replies" && /* @__PURE__ */ jsx4(QuickReplyButtons, { metadata, onTap: onQuickReplyTap }),
|
|
2055
2339
|
timestamp && /* @__PURE__ */ jsx4("div", { className: "hw-msg-meta", children: /* @__PURE__ */ jsx4("span", { className: "hw-msg-time", children: timestamp }) })
|
|
2056
2340
|
] }) });
|
|
@@ -2091,7 +2375,7 @@ function QuickReplyButtons({
|
|
|
2091
2375
|
}
|
|
2092
2376
|
function PreviewableThumbnail({ src }) {
|
|
2093
2377
|
const [hover, setHover] = useState6(false);
|
|
2094
|
-
const ref =
|
|
2378
|
+
const ref = useRef7(null);
|
|
2095
2379
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2096
2380
|
/* @__PURE__ */ jsx4(
|
|
2097
2381
|
"a",
|
|
@@ -2112,7 +2396,7 @@ function PreviewableThumbnail({ src }) {
|
|
|
2112
2396
|
var PREVIEWABLE_EXTS = /* @__PURE__ */ new Set(["pdf", "csv", "png", "jpg", "jpeg", "gif", "webp", "svg"]);
|
|
2113
2397
|
function FileCard({ file }) {
|
|
2114
2398
|
const [hover, setHover] = useState6(false);
|
|
2115
|
-
const ref =
|
|
2399
|
+
const ref = useRef7(null);
|
|
2116
2400
|
const ext = file.fileName.split(".").pop()?.toLowerCase() ?? "";
|
|
2117
2401
|
const isPreviewable = PREVIEWABLE_EXTS.has(ext);
|
|
2118
2402
|
const isImage = file.mimeType.startsWith("image/");
|
|
@@ -2254,6 +2538,57 @@ function FileTypeIcon({ ext }) {
|
|
|
2254
2538
|
}
|
|
2255
2539
|
);
|
|
2256
2540
|
}
|
|
2541
|
+
function LinkPreviewCard({ preview }) {
|
|
2542
|
+
const hostname = (() => {
|
|
2543
|
+
try {
|
|
2544
|
+
return new URL(preview.url).hostname;
|
|
2545
|
+
} catch {
|
|
2546
|
+
return preview.url;
|
|
2547
|
+
}
|
|
2548
|
+
})();
|
|
2549
|
+
return /* @__PURE__ */ jsxs2(
|
|
2550
|
+
"a",
|
|
2551
|
+
{
|
|
2552
|
+
href: preview.url,
|
|
2553
|
+
target: "_blank",
|
|
2554
|
+
rel: "noopener noreferrer",
|
|
2555
|
+
className: "hw-link-preview",
|
|
2556
|
+
onClick: (e) => e.stopPropagation(),
|
|
2557
|
+
children: [
|
|
2558
|
+
preview.imageUrl && /* @__PURE__ */ jsx4(
|
|
2559
|
+
"img",
|
|
2560
|
+
{
|
|
2561
|
+
src: preview.imageUrl,
|
|
2562
|
+
alt: "",
|
|
2563
|
+
className: "hw-link-preview-img",
|
|
2564
|
+
loading: "lazy",
|
|
2565
|
+
onError: (e) => {
|
|
2566
|
+
e.target.style.display = "none";
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
),
|
|
2570
|
+
/* @__PURE__ */ jsxs2("div", { className: "hw-link-preview-body", children: [
|
|
2571
|
+
preview.favicon && /* @__PURE__ */ jsx4(
|
|
2572
|
+
"img",
|
|
2573
|
+
{
|
|
2574
|
+
src: preview.favicon,
|
|
2575
|
+
alt: "",
|
|
2576
|
+
className: "hw-link-preview-favicon",
|
|
2577
|
+
width: 16,
|
|
2578
|
+
height: 16,
|
|
2579
|
+
onError: (e) => {
|
|
2580
|
+
e.target.style.display = "none";
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
),
|
|
2584
|
+
preview.title && /* @__PURE__ */ jsx4("div", { className: "hw-link-preview-title", children: preview.title }),
|
|
2585
|
+
preview.description && /* @__PURE__ */ jsx4("div", { className: "hw-link-preview-desc", children: preview.description.slice(0, 120) }),
|
|
2586
|
+
/* @__PURE__ */ jsx4("div", { className: "hw-link-preview-url", children: hostname })
|
|
2587
|
+
] })
|
|
2588
|
+
]
|
|
2589
|
+
}
|
|
2590
|
+
);
|
|
2591
|
+
}
|
|
2257
2592
|
|
|
2258
2593
|
// src/themed/composer.tsx
|
|
2259
2594
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -2287,9 +2622,12 @@ function Composer({
|
|
|
2287
2622
|
onRemoveAttachment,
|
|
2288
2623
|
disabled
|
|
2289
2624
|
}) {
|
|
2290
|
-
const ref =
|
|
2291
|
-
const fileInputRef =
|
|
2292
|
-
const
|
|
2625
|
+
const ref = useRef8(null);
|
|
2626
|
+
const fileInputRef = useRef8(null);
|
|
2627
|
+
const supportsFieldSizing = useRef8(
|
|
2628
|
+
typeof CSS !== "undefined" && CSS.supports?.("field-sizing", "content")
|
|
2629
|
+
);
|
|
2630
|
+
const handleKeyDown = useCallback7(
|
|
2293
2631
|
(e) => {
|
|
2294
2632
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
2295
2633
|
e.preventDefault();
|
|
@@ -2298,21 +2636,23 @@ function Composer({
|
|
|
2298
2636
|
},
|
|
2299
2637
|
[onSubmit]
|
|
2300
2638
|
);
|
|
2301
|
-
const handleChange =
|
|
2639
|
+
const handleChange = useCallback7(
|
|
2302
2640
|
(e) => {
|
|
2303
2641
|
const value = e.target.value;
|
|
2304
2642
|
if (value.length > MAX_CHARS) return;
|
|
2305
2643
|
onTextChange(value);
|
|
2306
2644
|
onTyping?.(value.length > 0);
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
el
|
|
2310
|
-
|
|
2645
|
+
if (!supportsFieldSizing.current) {
|
|
2646
|
+
const el = ref.current;
|
|
2647
|
+
if (el) {
|
|
2648
|
+
el.style.height = "auto";
|
|
2649
|
+
el.style.height = `${Math.min(el.scrollHeight, 220)}px`;
|
|
2650
|
+
}
|
|
2311
2651
|
}
|
|
2312
2652
|
},
|
|
2313
2653
|
[onTextChange, onTyping]
|
|
2314
2654
|
);
|
|
2315
|
-
const handlePaste =
|
|
2655
|
+
const handlePaste = useCallback7(
|
|
2316
2656
|
(e) => {
|
|
2317
2657
|
if (!onAddFiles) return;
|
|
2318
2658
|
const files = extractFiles(e.clipboardData);
|
|
@@ -2324,22 +2664,22 @@ function Composer({
|
|
|
2324
2664
|
[onAddFiles]
|
|
2325
2665
|
);
|
|
2326
2666
|
const [isDragging, setIsDragging] = useState7(false);
|
|
2327
|
-
const dragCountRef =
|
|
2328
|
-
const handleDragEnter =
|
|
2667
|
+
const dragCountRef = useRef8(0);
|
|
2668
|
+
const handleDragEnter = useCallback7((e) => {
|
|
2329
2669
|
e.preventDefault();
|
|
2330
2670
|
dragCountRef.current++;
|
|
2331
2671
|
if (dragCountRef.current === 1) setIsDragging(true);
|
|
2332
2672
|
}, []);
|
|
2333
|
-
const handleDragLeave =
|
|
2673
|
+
const handleDragLeave = useCallback7((e) => {
|
|
2334
2674
|
e.preventDefault();
|
|
2335
2675
|
dragCountRef.current--;
|
|
2336
2676
|
if (dragCountRef.current === 0) setIsDragging(false);
|
|
2337
2677
|
}, []);
|
|
2338
|
-
const handleDragOver =
|
|
2678
|
+
const handleDragOver = useCallback7((e) => {
|
|
2339
2679
|
e.preventDefault();
|
|
2340
2680
|
e.dataTransfer.dropEffect = "copy";
|
|
2341
2681
|
}, []);
|
|
2342
|
-
const handleDrop =
|
|
2682
|
+
const handleDrop = useCallback7(
|
|
2343
2683
|
(e) => {
|
|
2344
2684
|
e.preventDefault();
|
|
2345
2685
|
dragCountRef.current = 0;
|
|
@@ -2350,10 +2690,10 @@ function Composer({
|
|
|
2350
2690
|
},
|
|
2351
2691
|
[onAddFiles]
|
|
2352
2692
|
);
|
|
2353
|
-
const handleFileClick =
|
|
2693
|
+
const handleFileClick = useCallback7(() => {
|
|
2354
2694
|
fileInputRef.current?.click();
|
|
2355
2695
|
}, []);
|
|
2356
|
-
const handleFileChange =
|
|
2696
|
+
const handleFileChange = useCallback7(
|
|
2357
2697
|
(e) => {
|
|
2358
2698
|
if (!onAddFiles || !e.target.files) return;
|
|
2359
2699
|
onAddFiles(Array.from(e.target.files));
|
|
@@ -2444,7 +2784,7 @@ function Composer({
|
|
|
2444
2784
|
}
|
|
2445
2785
|
function PreviewThumb({ attachment: a, onRemove }) {
|
|
2446
2786
|
const [hover, setHover] = useState7(false);
|
|
2447
|
-
const ref =
|
|
2787
|
+
const ref = useRef8(null);
|
|
2448
2788
|
return /* @__PURE__ */ jsxs3(
|
|
2449
2789
|
"div",
|
|
2450
2790
|
{
|
|
@@ -2483,7 +2823,7 @@ function extractFiles(data) {
|
|
|
2483
2823
|
}
|
|
2484
2824
|
|
|
2485
2825
|
// src/themed/debug-overlay.tsx
|
|
2486
|
-
import { useEffect as
|
|
2826
|
+
import { useEffect as useEffect7, useMemo as useMemo2, useRef as useRef9, useState as useState8 } from "react";
|
|
2487
2827
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2488
2828
|
var MAX_EVENTS = 60;
|
|
2489
2829
|
function isDebugEnabled() {
|
|
@@ -2504,16 +2844,16 @@ function WidgetDebugOverlay() {
|
|
|
2504
2844
|
const [enabled, setEnabled] = useState8(false);
|
|
2505
2845
|
const [open, setOpen] = useState8(true);
|
|
2506
2846
|
const [events, setEvents] = useState8([]);
|
|
2507
|
-
const eventsRef =
|
|
2847
|
+
const eventsRef = useRef9([]);
|
|
2508
2848
|
const activeId = useWidgetStore((s) => s.activeConversationId);
|
|
2509
2849
|
const messagesMap = useWidgetStore((s) => s.messages);
|
|
2510
2850
|
const typingUsers = useWidgetStore((s) => s.typingUsers);
|
|
2511
2851
|
const aiProcessingMap = useWidgetStore((s) => s.aiProcessing);
|
|
2512
2852
|
const { store } = useWidgetContext();
|
|
2513
|
-
|
|
2853
|
+
useEffect7(() => {
|
|
2514
2854
|
setEnabled(isDebugEnabled());
|
|
2515
2855
|
}, []);
|
|
2516
|
-
const pushEvent =
|
|
2856
|
+
const pushEvent = useMemo2(
|
|
2517
2857
|
() => (ev) => {
|
|
2518
2858
|
const e = {
|
|
2519
2859
|
...ev,
|
|
@@ -2525,7 +2865,7 @@ function WidgetDebugOverlay() {
|
|
|
2525
2865
|
},
|
|
2526
2866
|
[]
|
|
2527
2867
|
);
|
|
2528
|
-
|
|
2868
|
+
useEffect7(() => {
|
|
2529
2869
|
if (!enabled) return;
|
|
2530
2870
|
if (typeof window === "undefined" || typeof window.fetch !== "function") return;
|
|
2531
2871
|
const originalFetch = window.fetch.bind(window);
|
|
@@ -2557,7 +2897,7 @@ function WidgetDebugOverlay() {
|
|
|
2557
2897
|
window.fetch = originalFetch;
|
|
2558
2898
|
};
|
|
2559
2899
|
}, [enabled, pushEvent]);
|
|
2560
|
-
|
|
2900
|
+
useEffect7(() => {
|
|
2561
2901
|
if (!enabled) return;
|
|
2562
2902
|
const original = store.getState().handleRealtimeEvent;
|
|
2563
2903
|
store.setState({
|
|
@@ -2571,12 +2911,12 @@ function WidgetDebugOverlay() {
|
|
|
2571
2911
|
};
|
|
2572
2912
|
}, [enabled, store, pushEvent]);
|
|
2573
2913
|
const activeMessages = activeId ? messagesMap.get(activeId) ?? [] : [];
|
|
2574
|
-
const lastMsgSignature =
|
|
2914
|
+
const lastMsgSignature = useMemo2(
|
|
2575
2915
|
() => activeMessages.map((m) => `${m.id}:${senderOf(m)}:${m.createdAt}`).join("|"),
|
|
2576
2916
|
[activeMessages]
|
|
2577
2917
|
);
|
|
2578
|
-
const prevSigRef =
|
|
2579
|
-
|
|
2918
|
+
const prevSigRef = useRef9(lastMsgSignature);
|
|
2919
|
+
useEffect7(() => {
|
|
2580
2920
|
if (!enabled) return;
|
|
2581
2921
|
if (prevSigRef.current !== lastMsgSignature) {
|
|
2582
2922
|
prevSigRef.current = lastMsgSignature;
|
|
@@ -2729,11 +3069,11 @@ var styles = {
|
|
|
2729
3069
|
};
|
|
2730
3070
|
|
|
2731
3071
|
// src/themed/content/content-tab-view.tsx
|
|
2732
|
-
import { useCallback as
|
|
3072
|
+
import { useCallback as useCallback11, useEffect as useEffect10 } from "react";
|
|
2733
3073
|
|
|
2734
3074
|
// src/hooks/use-content-tab.ts
|
|
2735
|
-
import { useCallback as
|
|
2736
|
-
var
|
|
3075
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useState as useState9 } from "react";
|
|
3076
|
+
var EMPTY_TABS2 = [];
|
|
2737
3077
|
function listKey(tabId, lang) {
|
|
2738
3078
|
return `flat:${tabId}:${lang}:list`;
|
|
2739
3079
|
}
|
|
@@ -2748,7 +3088,7 @@ function readCache(cache, key) {
|
|
|
2748
3088
|
}
|
|
2749
3089
|
function useContentTab(tabId) {
|
|
2750
3090
|
const { client, store } = useWidgetContext();
|
|
2751
|
-
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ??
|
|
3091
|
+
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS2;
|
|
2752
3092
|
const tab = contentTabs.find((t2) => t2.id === tabId) ?? null;
|
|
2753
3093
|
const lang = getLocale();
|
|
2754
3094
|
const cache = store.getState().contentCache;
|
|
@@ -2767,7 +3107,7 @@ function useContentTab(tabId) {
|
|
|
2767
3107
|
const [page, setPage] = useState9(
|
|
2768
3108
|
() => readCache(cache, listKey(tabId, lang))?.page ?? 1
|
|
2769
3109
|
);
|
|
2770
|
-
const fetchEntries =
|
|
3110
|
+
const fetchEntries = useCallback8(
|
|
2771
3111
|
async (opts) => {
|
|
2772
3112
|
if (!tab) return;
|
|
2773
3113
|
const p = opts?.page ?? 1;
|
|
@@ -2806,11 +3146,11 @@ function useContentTab(tabId) {
|
|
|
2806
3146
|
},
|
|
2807
3147
|
[client, tabId, tab, store]
|
|
2808
3148
|
);
|
|
2809
|
-
const loadMore =
|
|
3149
|
+
const loadMore = useCallback8(() => {
|
|
2810
3150
|
if (!hasMore || isLoading) return;
|
|
2811
3151
|
fetchEntries({ page: page + 1 });
|
|
2812
3152
|
}, [fetchEntries, hasMore, isLoading, page]);
|
|
2813
|
-
const fetchDetail =
|
|
3153
|
+
const fetchDetail = useCallback8(
|
|
2814
3154
|
async (slug) => {
|
|
2815
3155
|
if (!tab) return;
|
|
2816
3156
|
const cached = readCache(
|
|
@@ -2844,10 +3184,10 @@ function useContentTab(tabId) {
|
|
|
2844
3184
|
},
|
|
2845
3185
|
[client, tabId, tab, store]
|
|
2846
3186
|
);
|
|
2847
|
-
const clearDetail =
|
|
3187
|
+
const clearDetail = useCallback8(() => {
|
|
2848
3188
|
setDetail(null);
|
|
2849
3189
|
}, []);
|
|
2850
|
-
|
|
3190
|
+
useEffect8(() => {
|
|
2851
3191
|
if (tab && entries.length === 0) {
|
|
2852
3192
|
fetchEntries({ page: 1, reset: true });
|
|
2853
3193
|
}
|
|
@@ -2956,7 +3296,7 @@ function SkeletonSection({
|
|
|
2956
3296
|
}
|
|
2957
3297
|
|
|
2958
3298
|
// src/themed/content/content-list-view.tsx
|
|
2959
|
-
import { useCallback as
|
|
3299
|
+
import { useCallback as useCallback9, useRef as useRef10, useState as useState10 } from "react";
|
|
2960
3300
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2961
3301
|
function ContentListView({
|
|
2962
3302
|
entries,
|
|
@@ -2969,8 +3309,8 @@ function ContentListView({
|
|
|
2969
3309
|
display
|
|
2970
3310
|
}) {
|
|
2971
3311
|
const [searchText, setSearchText] = useState10("");
|
|
2972
|
-
const debounceRef =
|
|
2973
|
-
const handleSearch =
|
|
3312
|
+
const debounceRef = useRef10(void 0);
|
|
3313
|
+
const handleSearch = useCallback9(
|
|
2974
3314
|
(value) => {
|
|
2975
3315
|
setSearchText(value);
|
|
2976
3316
|
if (!onSearch) return;
|
|
@@ -3050,11 +3390,11 @@ function ContentEntryCard({
|
|
|
3050
3390
|
}
|
|
3051
3391
|
|
|
3052
3392
|
// src/themed/content/grouped-content-tab-view.tsx
|
|
3053
|
-
import { useEffect as
|
|
3393
|
+
import { useEffect as useEffect9, useRef as useRef12 } from "react";
|
|
3054
3394
|
|
|
3055
3395
|
// src/hooks/use-grouped-content-tab.ts
|
|
3056
|
-
import { useCallback as
|
|
3057
|
-
var
|
|
3396
|
+
import { useCallback as useCallback10, useRef as useRef11, useState as useState11 } from "react";
|
|
3397
|
+
var EMPTY_TABS3 = [];
|
|
3058
3398
|
function categoriesKey(tabId, lang) {
|
|
3059
3399
|
return `grouped:${tabId}:${lang}:categories`;
|
|
3060
3400
|
}
|
|
@@ -3072,7 +3412,7 @@ function readCache2(cache, key) {
|
|
|
3072
3412
|
}
|
|
3073
3413
|
function useGroupedContentTab(tabId) {
|
|
3074
3414
|
const { client, store } = useWidgetContext();
|
|
3075
|
-
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ??
|
|
3415
|
+
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_TABS3;
|
|
3076
3416
|
const tab = contentTabs.find((t2) => t2.id === tabId) ?? null;
|
|
3077
3417
|
const lang = getLocale();
|
|
3078
3418
|
const cache = store.getState().contentCache;
|
|
@@ -3082,12 +3422,12 @@ function useGroupedContentTab(tabId) {
|
|
|
3082
3422
|
const [items, setItems] = useState11([]);
|
|
3083
3423
|
const [isItemsLoading, setIsItemsLoading] = useState11(false);
|
|
3084
3424
|
const [itemsHasMore, setItemsHasMore] = useState11(false);
|
|
3085
|
-
const itemsPageRef =
|
|
3425
|
+
const itemsPageRef = useRef11(1);
|
|
3086
3426
|
const [detail, setDetail] = useState11(null);
|
|
3087
3427
|
const [isLoadingDetail, setIsLoadingDetail] = useState11(false);
|
|
3088
3428
|
const [activeCategory, setActiveCategory] = useState11(null);
|
|
3089
|
-
const allCategoriesRef =
|
|
3090
|
-
const fetchCategories =
|
|
3429
|
+
const allCategoriesRef = useRef11(cachedCategories ?? []);
|
|
3430
|
+
const fetchCategories = useCallback10(async () => {
|
|
3091
3431
|
if (!tab) return;
|
|
3092
3432
|
setIsCategoriesLoading(true);
|
|
3093
3433
|
try {
|
|
@@ -3108,12 +3448,12 @@ function useGroupedContentTab(tabId) {
|
|
|
3108
3448
|
setIsCategoriesLoading(false);
|
|
3109
3449
|
}
|
|
3110
3450
|
}, [client, tabId, tab, store]);
|
|
3111
|
-
const initFetch =
|
|
3451
|
+
const initFetch = useCallback10(() => {
|
|
3112
3452
|
if (tab && categories.length === 0) {
|
|
3113
3453
|
fetchCategories();
|
|
3114
3454
|
}
|
|
3115
3455
|
}, [fetchCategories, tab, categories.length]);
|
|
3116
|
-
const fetchItems =
|
|
3456
|
+
const fetchItems = useCallback10(
|
|
3117
3457
|
async (opts) => {
|
|
3118
3458
|
if (!tab?.itemsModelSlug) return;
|
|
3119
3459
|
const p = opts?.page ?? 1;
|
|
@@ -3151,7 +3491,7 @@ function useGroupedContentTab(tabId) {
|
|
|
3151
3491
|
},
|
|
3152
3492
|
[client, tabId, tab, store]
|
|
3153
3493
|
);
|
|
3154
|
-
const selectCategory =
|
|
3494
|
+
const selectCategory = useCallback10(
|
|
3155
3495
|
(category) => {
|
|
3156
3496
|
setActiveCategory(category);
|
|
3157
3497
|
setDetail(null);
|
|
@@ -3170,14 +3510,14 @@ function useGroupedContentTab(tabId) {
|
|
|
3170
3510
|
},
|
|
3171
3511
|
[fetchItems, store, tabId]
|
|
3172
3512
|
);
|
|
3173
|
-
const loadMoreItems =
|
|
3513
|
+
const loadMoreItems = useCallback10(() => {
|
|
3174
3514
|
if (!itemsHasMore || isItemsLoading || !activeCategory) return;
|
|
3175
3515
|
fetchItems({
|
|
3176
3516
|
page: itemsPageRef.current + 1,
|
|
3177
3517
|
groupSlug: activeCategory.slug
|
|
3178
3518
|
});
|
|
3179
3519
|
}, [fetchItems, itemsHasMore, isItemsLoading, activeCategory]);
|
|
3180
|
-
const searchItems =
|
|
3520
|
+
const searchItems = useCallback10(
|
|
3181
3521
|
(query) => {
|
|
3182
3522
|
setItems([]);
|
|
3183
3523
|
fetchItems({
|
|
@@ -3189,7 +3529,7 @@ function useGroupedContentTab(tabId) {
|
|
|
3189
3529
|
},
|
|
3190
3530
|
[fetchItems, activeCategory]
|
|
3191
3531
|
);
|
|
3192
|
-
const fetchDetail =
|
|
3532
|
+
const fetchDetail = useCallback10(
|
|
3193
3533
|
async (slug) => {
|
|
3194
3534
|
if (!tab?.itemsModelSlug) return;
|
|
3195
3535
|
const cached = readCache2(
|
|
@@ -3224,7 +3564,7 @@ function useGroupedContentTab(tabId) {
|
|
|
3224
3564
|
},
|
|
3225
3565
|
[client, tabId, tab, store]
|
|
3226
3566
|
);
|
|
3227
|
-
const searchCategories =
|
|
3567
|
+
const searchCategories = useCallback10(
|
|
3228
3568
|
(query) => {
|
|
3229
3569
|
if (!query.trim()) {
|
|
3230
3570
|
setCategories(allCategoriesRef.current);
|
|
@@ -3239,10 +3579,10 @@ function useGroupedContentTab(tabId) {
|
|
|
3239
3579
|
},
|
|
3240
3580
|
[]
|
|
3241
3581
|
);
|
|
3242
|
-
const clearDetail =
|
|
3582
|
+
const clearDetail = useCallback10(() => {
|
|
3243
3583
|
setDetail(null);
|
|
3244
3584
|
}, []);
|
|
3245
|
-
const clearCategory =
|
|
3585
|
+
const clearCategory = useCallback10(() => {
|
|
3246
3586
|
setActiveCategory(null);
|
|
3247
3587
|
setItems([]);
|
|
3248
3588
|
setDetail(null);
|
|
@@ -3294,16 +3634,16 @@ function GroupedContentTabView({
|
|
|
3294
3634
|
fetchDetail,
|
|
3295
3635
|
clearCategory
|
|
3296
3636
|
} = useGroupedContentTab(tab.id);
|
|
3297
|
-
|
|
3637
|
+
useEffect9(() => {
|
|
3298
3638
|
initFetch();
|
|
3299
3639
|
}, [initFetch]);
|
|
3300
|
-
|
|
3640
|
+
useEffect9(() => {
|
|
3301
3641
|
if (detailSlug && subView === "content-detail") {
|
|
3302
3642
|
fetchDetail(detailSlug);
|
|
3303
3643
|
}
|
|
3304
3644
|
}, [detailSlug, subView, fetchDetail]);
|
|
3305
|
-
const prevSubView =
|
|
3306
|
-
|
|
3645
|
+
const prevSubView = useRef12(subView);
|
|
3646
|
+
useEffect9(() => {
|
|
3307
3647
|
if (prevSubView.current === "content-category" && subView === null) {
|
|
3308
3648
|
clearCategory();
|
|
3309
3649
|
}
|
|
@@ -3397,10 +3737,10 @@ function FlatContentTabView({
|
|
|
3397
3737
|
loadMore,
|
|
3398
3738
|
fetchDetail
|
|
3399
3739
|
} = useContentTab(tab.id);
|
|
3400
|
-
|
|
3740
|
+
useEffect10(() => {
|
|
3401
3741
|
if (detailSlug) fetchDetail(detailSlug);
|
|
3402
3742
|
}, [detailSlug, fetchDetail]);
|
|
3403
|
-
const handleSearch =
|
|
3743
|
+
const handleSearch = useCallback11(
|
|
3404
3744
|
(query) => {
|
|
3405
3745
|
fetchEntries({ page: 1, search: query || void 0, reset: true });
|
|
3406
3746
|
},
|
|
@@ -3440,7 +3780,7 @@ function ContentTabIconComponent({ icon }) {
|
|
|
3440
3780
|
}
|
|
3441
3781
|
|
|
3442
3782
|
// src/themed/message-list.tsx
|
|
3443
|
-
import React, { useEffect as
|
|
3783
|
+
import React, { useEffect as useEffect11, useRef as useRef13 } from "react";
|
|
3444
3784
|
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3445
3785
|
function parseParts(raw) {
|
|
3446
3786
|
if (!raw) return null;
|
|
@@ -3467,16 +3807,17 @@ function MessageList({
|
|
|
3467
3807
|
visitorName,
|
|
3468
3808
|
isTyping,
|
|
3469
3809
|
isAiProcessing,
|
|
3810
|
+
streamingText,
|
|
3470
3811
|
hasMore,
|
|
3471
3812
|
isLoadingMore,
|
|
3472
3813
|
onLoadMore,
|
|
3473
3814
|
renderAfterMessages
|
|
3474
3815
|
}) {
|
|
3475
|
-
const bottomRef =
|
|
3476
|
-
const topRef =
|
|
3477
|
-
const containerRef =
|
|
3478
|
-
const prevItemCountRef =
|
|
3479
|
-
const isInitialLoadRef =
|
|
3816
|
+
const bottomRef = useRef13(null);
|
|
3817
|
+
const topRef = useRef13(null);
|
|
3818
|
+
const containerRef = useRef13(null);
|
|
3819
|
+
const prevItemCountRef = useRef13(items.length);
|
|
3820
|
+
const isInitialLoadRef = useRef13(true);
|
|
3480
3821
|
const agentName = useWidgetStore((s) => s.agentConfig?.name) ?? t("widget.helpway_ai");
|
|
3481
3822
|
const client = useWidgetClient();
|
|
3482
3823
|
const activeConversationId = useWidgetStore((s) => s.activeConversationId);
|
|
@@ -3489,7 +3830,7 @@ function MessageList({
|
|
|
3489
3830
|
},
|
|
3490
3831
|
[client, activeConversationId]
|
|
3491
3832
|
);
|
|
3492
|
-
|
|
3833
|
+
useEffect11(() => {
|
|
3493
3834
|
const prevCount = prevItemCountRef.current;
|
|
3494
3835
|
const newCount = items.length;
|
|
3495
3836
|
prevItemCountRef.current = newCount;
|
|
@@ -3504,12 +3845,12 @@ function MessageList({
|
|
|
3504
3845
|
isInitialLoadRef.current = false;
|
|
3505
3846
|
}
|
|
3506
3847
|
}, [items]);
|
|
3507
|
-
|
|
3848
|
+
useEffect11(() => {
|
|
3508
3849
|
if (isTyping || isAiProcessing) {
|
|
3509
3850
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3510
3851
|
}
|
|
3511
3852
|
}, [isTyping, isAiProcessing]);
|
|
3512
|
-
|
|
3853
|
+
useEffect11(() => {
|
|
3513
3854
|
if (!hasMore || !onLoadMore || !topRef.current) return;
|
|
3514
3855
|
const observer = new IntersectionObserver(
|
|
3515
3856
|
(entries) => {
|
|
@@ -3608,7 +3949,11 @@ function MessageList({
|
|
|
3608
3949
|
] }, item._stableKey ?? item.id);
|
|
3609
3950
|
}),
|
|
3610
3951
|
renderAfterMessages,
|
|
3611
|
-
|
|
3952
|
+
streamingText && /* @__PURE__ */ jsx12("div", { className: "hw-message hw-message-ai", children: /* @__PURE__ */ jsxs7("div", { className: "hw-bubble hw-bubble-ai", children: [
|
|
3953
|
+
/* @__PURE__ */ jsx12("span", { children: streamingText }),
|
|
3954
|
+
/* @__PURE__ */ jsx12("span", { className: "hw-streaming-cursor" })
|
|
3955
|
+
] }) }),
|
|
3956
|
+
isAiProcessing && !streamingText && /* @__PURE__ */ jsxs7("div", { className: "hw-typing", children: [
|
|
3612
3957
|
/* @__PURE__ */ jsx12("div", { className: "hw-typing-label", children: agentName }),
|
|
3613
3958
|
/* @__PURE__ */ jsxs7("div", { className: "hw-typing-dots", children: [
|
|
3614
3959
|
/* @__PURE__ */ jsx12("div", { className: "hw-typing-dot" }),
|
|
@@ -3651,8 +3996,97 @@ function EventCard({ text }) {
|
|
|
3651
3996
|
return /* @__PURE__ */ jsx12("div", { className: "hw-event", children: /* @__PURE__ */ jsx12("div", { className: "hw-event-text", children: text }) });
|
|
3652
3997
|
}
|
|
3653
3998
|
|
|
3654
|
-
// src/themed/
|
|
3999
|
+
// src/themed/message-preview.tsx
|
|
4000
|
+
import { useEffect as useEffect12, useState as useState12 } from "react";
|
|
3655
4001
|
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4002
|
+
function MessagePreview({
|
|
4003
|
+
onOpen,
|
|
4004
|
+
avatar,
|
|
4005
|
+
placement = "launcher",
|
|
4006
|
+
autoDismissMs = 8e3,
|
|
4007
|
+
footer
|
|
4008
|
+
}) {
|
|
4009
|
+
const preview = useWidgetStore((s) => s.incomingPreview);
|
|
4010
|
+
const dismissPreview = useWidgetStore((s) => s.dismissPreview);
|
|
4011
|
+
const setActiveConversation = useWidgetStore((s) => s.setActiveConversation);
|
|
4012
|
+
const agentName = useWidgetStore((s) => s.agentConfig?.name) ?? "Support";
|
|
4013
|
+
const [closing, setClosing] = useState12(false);
|
|
4014
|
+
useEffect12(() => {
|
|
4015
|
+
if (!preview || preview.quickReplies) return;
|
|
4016
|
+
if (autoDismissMs == null || autoDismissMs <= 0) return;
|
|
4017
|
+
const timer = setTimeout(() => {
|
|
4018
|
+
setClosing(true);
|
|
4019
|
+
setTimeout(() => dismissPreview(), 200);
|
|
4020
|
+
}, autoDismissMs);
|
|
4021
|
+
return () => clearTimeout(timer);
|
|
4022
|
+
}, [preview, dismissPreview, autoDismissMs]);
|
|
4023
|
+
if (!preview) return null;
|
|
4024
|
+
const handleClose = (e) => {
|
|
4025
|
+
e.stopPropagation();
|
|
4026
|
+
setClosing(true);
|
|
4027
|
+
setTimeout(() => {
|
|
4028
|
+
dismissPreview();
|
|
4029
|
+
setClosing(false);
|
|
4030
|
+
}, 200);
|
|
4031
|
+
};
|
|
4032
|
+
const handleClick = () => {
|
|
4033
|
+
const targetConvId = preview.conversationId;
|
|
4034
|
+
dismissPreview();
|
|
4035
|
+
setActiveConversation(targetConvId);
|
|
4036
|
+
onOpen();
|
|
4037
|
+
};
|
|
4038
|
+
const messages = preview.messages?.length ? preview.messages : [{ text: preview.text }];
|
|
4039
|
+
const hasQr = preview.quickReplies && preview.quickReplies.options.length > 0;
|
|
4040
|
+
const placementClass = placement === "anchored" ? "hw-preview--anchored " : "";
|
|
4041
|
+
return /* @__PURE__ */ jsxs8(
|
|
4042
|
+
"div",
|
|
4043
|
+
{
|
|
4044
|
+
className: `hw-preview ${placementClass}${closing ? "hw-preview--closing" : ""}`,
|
|
4045
|
+
onClick: handleClick,
|
|
4046
|
+
role: "button",
|
|
4047
|
+
tabIndex: 0,
|
|
4048
|
+
children: [
|
|
4049
|
+
/* @__PURE__ */ jsxs8("div", { className: "hw-preview-header", children: [
|
|
4050
|
+
/* @__PURE__ */ jsx13("div", { className: "hw-preview-avatar", children: avatar }),
|
|
4051
|
+
/* @__PURE__ */ jsx13("div", { className: "hw-preview-name", children: agentName }),
|
|
4052
|
+
/* @__PURE__ */ jsx13(
|
|
4053
|
+
"button",
|
|
4054
|
+
{
|
|
4055
|
+
type: "button",
|
|
4056
|
+
className: "hw-preview-close",
|
|
4057
|
+
onClick: handleClose,
|
|
4058
|
+
"aria-label": t("widget.aria_dismiss"),
|
|
4059
|
+
children: /* @__PURE__ */ jsx13(XIcon, { size: 20 })
|
|
4060
|
+
}
|
|
4061
|
+
)
|
|
4062
|
+
] }),
|
|
4063
|
+
messages.map((m, i) => /* @__PURE__ */ jsx13("div", { className: "hw-preview-body", children: m.text }, i)),
|
|
4064
|
+
hasQr && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
4065
|
+
preview.quickReplies.prompt && /* @__PURE__ */ jsx13("div", { className: "hw-preview-body", children: preview.quickReplies.prompt }),
|
|
4066
|
+
/* @__PURE__ */ jsx13("div", { className: "hw-preview-quick-replies", children: preview.quickReplies.options.map((opt) => /* @__PURE__ */ jsx13(
|
|
4067
|
+
"button",
|
|
4068
|
+
{
|
|
4069
|
+
type: "button",
|
|
4070
|
+
className: "hw-preview-qr-btn",
|
|
4071
|
+
onClick: (e) => {
|
|
4072
|
+
e.stopPropagation();
|
|
4073
|
+
dismissPreview();
|
|
4074
|
+
setActiveConversation(preview.conversationId);
|
|
4075
|
+
onOpen();
|
|
4076
|
+
},
|
|
4077
|
+
children: opt.label
|
|
4078
|
+
},
|
|
4079
|
+
opt.id
|
|
4080
|
+
)) })
|
|
4081
|
+
] }),
|
|
4082
|
+
footer != null && footer !== false && /* @__PURE__ */ jsx13("div", { className: "hw-preview-footer", children: footer })
|
|
4083
|
+
]
|
|
4084
|
+
}
|
|
4085
|
+
);
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
// src/themed/default-widget.tsx
|
|
4089
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3656
4090
|
function resolveLabel2(label) {
|
|
3657
4091
|
if (!label.startsWith("widget.")) return label;
|
|
3658
4092
|
const resolved = t(label);
|
|
@@ -3664,7 +4098,7 @@ var EMPTY_CONTENT_TABS = [];
|
|
|
3664
4098
|
var DEFAULT_EN_WELCOME = "Hi there \u{1F44B}\nHow can we help?";
|
|
3665
4099
|
var DEFAULT_EN_SUBTITLE = "Usually replies in minutes";
|
|
3666
4100
|
function HelpwayMark({ className }) {
|
|
3667
|
-
return /* @__PURE__ */
|
|
4101
|
+
return /* @__PURE__ */ jsx14(
|
|
3668
4102
|
"svg",
|
|
3669
4103
|
{
|
|
3670
4104
|
className,
|
|
@@ -3674,7 +4108,7 @@ function HelpwayMark({ className }) {
|
|
|
3674
4108
|
fill: "none",
|
|
3675
4109
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3676
4110
|
"aria-hidden": "true",
|
|
3677
|
-
children: /* @__PURE__ */
|
|
4111
|
+
children: /* @__PURE__ */ jsx14(
|
|
3678
4112
|
"path",
|
|
3679
4113
|
{
|
|
3680
4114
|
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",
|
|
@@ -3698,7 +4132,7 @@ function WidgetLogo({
|
|
|
3698
4132
|
});
|
|
3699
4133
|
const logoClass = forceAgent ? "hw-agent-img--logo" : "";
|
|
3700
4134
|
if (!forceAgent && activeId && assignee?.assigneeImage) {
|
|
3701
|
-
return /* @__PURE__ */
|
|
4135
|
+
return /* @__PURE__ */ jsx14(
|
|
3702
4136
|
"img",
|
|
3703
4137
|
{
|
|
3704
4138
|
src: assignee.assigneeImage,
|
|
@@ -3708,10 +4142,10 @@ function WidgetLogo({
|
|
|
3708
4142
|
);
|
|
3709
4143
|
}
|
|
3710
4144
|
if (agentConfig?.avatarUrl) {
|
|
3711
|
-
return /* @__PURE__ */
|
|
4145
|
+
return /* @__PURE__ */ jsx14("img", { src: agentConfig.avatarUrl, alt: "", className: `hw-agent-img ${logoClass} ${className ?? ""}` });
|
|
3712
4146
|
}
|
|
3713
4147
|
if (agentConfig?.avatarPreset) {
|
|
3714
|
-
return /* @__PURE__ */
|
|
4148
|
+
return /* @__PURE__ */ jsx14(
|
|
3715
4149
|
"div",
|
|
3716
4150
|
{
|
|
3717
4151
|
className: `hw-agent-icon ${className ?? ""}`,
|
|
@@ -3722,20 +4156,20 @@ function WidgetLogo({
|
|
|
3722
4156
|
justifyContent: "center",
|
|
3723
4157
|
borderRadius: 8
|
|
3724
4158
|
},
|
|
3725
|
-
children: /* @__PURE__ */
|
|
4159
|
+
children: /* @__PURE__ */ jsx14(AgentPresetIcon, { presetId: agentConfig.avatarPreset })
|
|
3726
4160
|
}
|
|
3727
4161
|
);
|
|
3728
4162
|
}
|
|
3729
4163
|
if (logoUrl) {
|
|
3730
|
-
return /* @__PURE__ */
|
|
4164
|
+
return /* @__PURE__ */ jsx14("img", { src: logoUrl, alt: "", className: `hw-agent-img hw-agent-img--logo ${className ?? ""}` });
|
|
3731
4165
|
}
|
|
3732
|
-
return /* @__PURE__ */
|
|
4166
|
+
return /* @__PURE__ */ jsx14(HelpwayMark, { className });
|
|
3733
4167
|
}
|
|
3734
4168
|
function LauncherIcon({ className }) {
|
|
3735
4169
|
const agentConfig = useWidgetStore((s) => s.agentConfig);
|
|
3736
|
-
const [imgLoaded, setImgLoaded] =
|
|
4170
|
+
const [imgLoaded, setImgLoaded] = useState13(false);
|
|
3737
4171
|
const imgSrc = agentConfig?.launcherIconUrl ?? null;
|
|
3738
|
-
|
|
4172
|
+
useEffect13(() => {
|
|
3739
4173
|
if (!imgSrc) return;
|
|
3740
4174
|
setImgLoaded(false);
|
|
3741
4175
|
const img = new Image();
|
|
@@ -3748,7 +4182,7 @@ function LauncherIcon({ className }) {
|
|
|
3748
4182
|
img.onerror = () => setImgLoaded(true);
|
|
3749
4183
|
}, [imgSrc]);
|
|
3750
4184
|
if (imgSrc) {
|
|
3751
|
-
return /* @__PURE__ */
|
|
4185
|
+
return /* @__PURE__ */ jsx14(
|
|
3752
4186
|
"img",
|
|
3753
4187
|
{
|
|
3754
4188
|
src: imgSrc,
|
|
@@ -3758,7 +4192,7 @@ function LauncherIcon({ className }) {
|
|
|
3758
4192
|
}
|
|
3759
4193
|
);
|
|
3760
4194
|
}
|
|
3761
|
-
return /* @__PURE__ */
|
|
4195
|
+
return /* @__PURE__ */ jsx14(WidgetLogo, { className, forceAgent: true });
|
|
3762
4196
|
}
|
|
3763
4197
|
var PRESET_SVG = {
|
|
3764
4198
|
// Helpway brand mark — octagonal chamfer with stylized "W" inside.
|
|
@@ -3817,7 +4251,7 @@ function AgentPresetIcon({ presetId }) {
|
|
|
3817
4251
|
const svgContent = PRESET_SVG[presetId] ?? PRESET_SVG.sparkle;
|
|
3818
4252
|
return (
|
|
3819
4253
|
// biome-ignore lint: trusted static SVG content from our icon library
|
|
3820
|
-
/* @__PURE__ */
|
|
4254
|
+
/* @__PURE__ */ jsx14(
|
|
3821
4255
|
"svg",
|
|
3822
4256
|
{
|
|
3823
4257
|
viewBox: "0 0 24 24",
|
|
@@ -3838,6 +4272,8 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3838
4272
|
const isDismissed = useWidgetStore((s) => s.isDismissed);
|
|
3839
4273
|
const { totalUnread } = useUnread();
|
|
3840
4274
|
const contentTabs = useWidgetStore((s) => s.agentConfig?.contentTabs) ?? EMPTY_CONTENT_TABS;
|
|
4275
|
+
const { announcementTabs, markEntrySeen, markAllSeen, getUnseenEntries } = useAnnouncements();
|
|
4276
|
+
const unseenAnnouncementCount = useWidgetStore((s) => s.unseenAnnouncementCount);
|
|
3841
4277
|
const visitorContact = useWidgetStore((s) => s.visitor?.contact);
|
|
3842
4278
|
if (process.env.NODE_ENV !== "production") {
|
|
3843
4279
|
console.debug("[Widget]", {
|
|
@@ -3847,22 +4283,22 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3847
4283
|
});
|
|
3848
4284
|
}
|
|
3849
4285
|
const storeIsOpen = useWidgetStore((s) => s.isOpen);
|
|
3850
|
-
const [isClosing, setIsClosing] =
|
|
4286
|
+
const [isClosing, setIsClosing] = useState13(false);
|
|
3851
4287
|
const isOpen = storeIsOpen || isClosing;
|
|
3852
|
-
const [activeTab, setActiveTab] =
|
|
3853
|
-
const [subView, setSubView] =
|
|
3854
|
-
const [newText, setNewText] =
|
|
3855
|
-
const [contentDetailSlug, setContentDetailSlug] =
|
|
3856
|
-
const [contentCategoryName, setContentCategoryName] =
|
|
3857
|
-
const prevActiveIdRef =
|
|
3858
|
-
|
|
4288
|
+
const [activeTab, setActiveTab] = useState13("home");
|
|
4289
|
+
const [subView, setSubView] = useState13(null);
|
|
4290
|
+
const [newText, setNewText] = useState13("");
|
|
4291
|
+
const [contentDetailSlug, setContentDetailSlug] = useState13(null);
|
|
4292
|
+
const [contentCategoryName, setContentCategoryName] = useState13(null);
|
|
4293
|
+
const prevActiveIdRef = useRef14(activeId);
|
|
4294
|
+
useEffect13(() => {
|
|
3859
4295
|
if (activeId && activeId !== prevActiveIdRef.current && subView !== "conversation") {
|
|
3860
4296
|
setSubView("conversation");
|
|
3861
4297
|
}
|
|
3862
4298
|
prevActiveIdRef.current = activeId;
|
|
3863
4299
|
}, [activeId, subView]);
|
|
3864
4300
|
const prefill = useWidgetStore((s) => s.newConversationPrefill);
|
|
3865
|
-
|
|
4301
|
+
useEffect13(() => {
|
|
3866
4302
|
if (prefill !== null) {
|
|
3867
4303
|
if (prefill.length > 0) setNewText(prefill);
|
|
3868
4304
|
setSubView("new");
|
|
@@ -3870,18 +4306,18 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3870
4306
|
store.getState().setNewConversationPrefill(null);
|
|
3871
4307
|
}
|
|
3872
4308
|
}, [prefill, store]);
|
|
3873
|
-
const closeTimerRef =
|
|
4309
|
+
const closeTimerRef = useRef14(void 0);
|
|
3874
4310
|
const welcomeMsgRaw = agentConfig?.welcomeMessage;
|
|
3875
4311
|
const welcomeIsFactoryDefault = !welcomeMsgRaw || welcomeMsgRaw === DEFAULT_EN_WELCOME;
|
|
3876
4312
|
const welcomeMessage = welcomeMsgRaw?.startsWith("widget.") ? t(welcomeMsgRaw) : welcomeIsFactoryDefault ? t("widget.welcome_message") : welcomeMsgRaw;
|
|
3877
|
-
const openConversation =
|
|
4313
|
+
const openConversation = useCallback12(
|
|
3878
4314
|
(id) => {
|
|
3879
4315
|
setActiveConversation(id);
|
|
3880
4316
|
setSubView("conversation");
|
|
3881
4317
|
},
|
|
3882
4318
|
[setActiveConversation]
|
|
3883
4319
|
);
|
|
3884
|
-
const openNewConversation =
|
|
4320
|
+
const openNewConversation = useCallback12(() => {
|
|
3885
4321
|
const agentId = agentConfig?.id;
|
|
3886
4322
|
if (!agentId) {
|
|
3887
4323
|
setSubView("new");
|
|
@@ -3907,7 +4343,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3907
4343
|
setActiveConversation(tempId);
|
|
3908
4344
|
setSubView("conversation");
|
|
3909
4345
|
}, [agentConfig?.id, store, setActiveConversation, welcomeMessage]);
|
|
3910
|
-
const goBack =
|
|
4346
|
+
const goBack = useCallback12(() => {
|
|
3911
4347
|
if (subView === "content-detail") {
|
|
3912
4348
|
const tabId = activeTab.startsWith("content:") ? activeTab.slice(8) : null;
|
|
3913
4349
|
const activeContentTab = tabId ? contentTabs.find((t2) => t2.id === tabId) : null;
|
|
@@ -3934,7 +4370,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3934
4370
|
setActiveConversation(null);
|
|
3935
4371
|
setSubView(null);
|
|
3936
4372
|
}, [setActiveConversation, subView, activeTab, contentTabs, contentCategoryName, client, store]);
|
|
3937
|
-
const switchTab =
|
|
4373
|
+
const switchTab = useCallback12(
|
|
3938
4374
|
(tab) => {
|
|
3939
4375
|
tabStateRef.current[activeTab] = { subView, activeId };
|
|
3940
4376
|
const saved = tabStateRef.current[tab];
|
|
@@ -3949,7 +4385,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3949
4385
|
[activeTab, subView, activeId, setActiveConversation]
|
|
3950
4386
|
);
|
|
3951
4387
|
const setStoreOpen = useWidgetStore((s) => s.setOpen);
|
|
3952
|
-
const handleBubbleClick =
|
|
4388
|
+
const handleBubbleClick = useCallback12(() => {
|
|
3953
4389
|
if (storeIsOpen) {
|
|
3954
4390
|
const leavingId = store.getState().activeConversationId;
|
|
3955
4391
|
if (leavingId && !leavingId.startsWith("temp-")) {
|
|
@@ -3969,7 +4405,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3969
4405
|
setStoreOpen(true);
|
|
3970
4406
|
}
|
|
3971
4407
|
}, [storeIsOpen, setStoreOpen, client, store]);
|
|
3972
|
-
const handleClose =
|
|
4408
|
+
const handleClose = useCallback12(() => {
|
|
3973
4409
|
const leavingId = store.getState().activeConversationId;
|
|
3974
4410
|
if (leavingId && !leavingId.startsWith("temp-")) {
|
|
3975
4411
|
store.getState().clearUnread(leavingId);
|
|
@@ -3982,7 +4418,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3982
4418
|
setStoreOpen(false);
|
|
3983
4419
|
}, 200);
|
|
3984
4420
|
}, [setStoreOpen, client, store]);
|
|
3985
|
-
const handleNewConversation =
|
|
4421
|
+
const handleNewConversation = useCallback12(async () => {
|
|
3986
4422
|
const trimmed = newText.trim();
|
|
3987
4423
|
if (!trimmed || isCreating) return;
|
|
3988
4424
|
const conv = await create(trimmed);
|
|
@@ -3991,16 +4427,16 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
3991
4427
|
setSubView("conversation");
|
|
3992
4428
|
}
|
|
3993
4429
|
}, [newText, isCreating, create]);
|
|
3994
|
-
const windowRef =
|
|
3995
|
-
const bubbleRef =
|
|
3996
|
-
const tabStateRef =
|
|
3997
|
-
const touchStartY =
|
|
3998
|
-
const touchDeltaY =
|
|
3999
|
-
const handleTouchStart =
|
|
4430
|
+
const windowRef = useRef14(null);
|
|
4431
|
+
const bubbleRef = useRef14(null);
|
|
4432
|
+
const tabStateRef = useRef14({});
|
|
4433
|
+
const touchStartY = useRef14(0);
|
|
4434
|
+
const touchDeltaY = useRef14(0);
|
|
4435
|
+
const handleTouchStart = useCallback12((e) => {
|
|
4000
4436
|
touchStartY.current = e.touches[0]?.clientY ?? 0;
|
|
4001
4437
|
touchDeltaY.current = 0;
|
|
4002
4438
|
}, []);
|
|
4003
|
-
const handleTouchMove =
|
|
4439
|
+
const handleTouchMove = useCallback12((e) => {
|
|
4004
4440
|
const delta = (e.touches[0]?.clientY ?? 0) - touchStartY.current;
|
|
4005
4441
|
touchDeltaY.current = delta;
|
|
4006
4442
|
if (delta > 0 && windowRef.current) {
|
|
@@ -4008,7 +4444,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4008
4444
|
windowRef.current.style.opacity = `${Math.max(1 - delta / 400, 0.5)}`;
|
|
4009
4445
|
}
|
|
4010
4446
|
}, []);
|
|
4011
|
-
const handleTouchEnd =
|
|
4447
|
+
const handleTouchEnd = useCallback12(() => {
|
|
4012
4448
|
if (windowRef.current) {
|
|
4013
4449
|
windowRef.current.style.transform = "";
|
|
4014
4450
|
windowRef.current.style.opacity = "";
|
|
@@ -4017,7 +4453,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4017
4453
|
handleClose();
|
|
4018
4454
|
}
|
|
4019
4455
|
}, [handleClose]);
|
|
4020
|
-
|
|
4456
|
+
useEffect13(() => {
|
|
4021
4457
|
if (!isOpen || !windowRef.current) return;
|
|
4022
4458
|
const vv = window.visualViewport;
|
|
4023
4459
|
if (!vv) return;
|
|
@@ -4034,7 +4470,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4034
4470
|
win.style.removeProperty("--hw-visible-height");
|
|
4035
4471
|
};
|
|
4036
4472
|
}, [isOpen]);
|
|
4037
|
-
|
|
4473
|
+
useEffect13(() => {
|
|
4038
4474
|
if (!isOpen || !windowRef.current) return;
|
|
4039
4475
|
const win = windowRef.current;
|
|
4040
4476
|
const handleKeyDown = (e) => {
|
|
@@ -4050,8 +4486,8 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4050
4486
|
win.addEventListener("keydown", handleKeyDown);
|
|
4051
4487
|
return () => win.removeEventListener("keydown", handleKeyDown);
|
|
4052
4488
|
}, [isOpen, subView, handleClose, goBack]);
|
|
4053
|
-
|
|
4054
|
-
if (!isOpen || !windowRef.current) return;
|
|
4489
|
+
useEffect13(() => {
|
|
4490
|
+
if (!isOpen || !windowRef.current || hideLauncher) return;
|
|
4055
4491
|
const win = windowRef.current;
|
|
4056
4492
|
const getFocusable = () => win.querySelectorAll(
|
|
4057
4493
|
'button:not([disabled]), [href], input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
@@ -4080,7 +4516,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4080
4516
|
const focusable = getFocusable();
|
|
4081
4517
|
if (focusable.length > 0) focusable[0]?.focus();
|
|
4082
4518
|
return () => win.removeEventListener("keydown", handleTab);
|
|
4083
|
-
}, [isOpen]);
|
|
4519
|
+
}, [isOpen, hideLauncher]);
|
|
4084
4520
|
const showTabBar = subView === null;
|
|
4085
4521
|
const activeConvSummary = useWidgetStore((s) => {
|
|
4086
4522
|
const id = s.activeConversationId;
|
|
@@ -4098,7 +4534,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4098
4534
|
const launcherStyle = agentConfig?.launcherStyle ?? "icon";
|
|
4099
4535
|
const bubbleStyle = agentConfig?.bubbleStyle ?? "rounded";
|
|
4100
4536
|
const hasUploadedAvatar = !!agentConfig?.avatarUrl;
|
|
4101
|
-
return /* @__PURE__ */
|
|
4537
|
+
return /* @__PURE__ */ jsxs9(
|
|
4102
4538
|
"div",
|
|
4103
4539
|
{
|
|
4104
4540
|
className: "hw-widget",
|
|
@@ -4111,16 +4547,16 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4111
4547
|
"--hw-window-left": widgetPosition === "bottom-left" ? "0" : "auto"
|
|
4112
4548
|
},
|
|
4113
4549
|
children: [
|
|
4114
|
-
isOpen && !isReady && !hasBootstrapError && /* @__PURE__ */
|
|
4115
|
-
/* @__PURE__ */
|
|
4116
|
-
/* @__PURE__ */
|
|
4117
|
-
/* @__PURE__ */
|
|
4550
|
+
isOpen && !isReady && !hasBootstrapError && /* @__PURE__ */ jsx14("div", { className: `hw-window ${isClosing ? "hw-window--closing" : ""}`, children: /* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-loading", children: [
|
|
4551
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 120 } }),
|
|
4552
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 200 } }),
|
|
4553
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 160 } })
|
|
4118
4554
|
] }) }),
|
|
4119
|
-
isOpen && hasBootstrapError && /* @__PURE__ */
|
|
4120
|
-
/* @__PURE__ */
|
|
4121
|
-
/* @__PURE__ */
|
|
4555
|
+
isOpen && hasBootstrapError && /* @__PURE__ */ jsx14("div", { className: `hw-window ${isClosing ? "hw-window--closing" : ""}`, children: /* @__PURE__ */ jsxs9("div", { className: "hw-bootstrap-error", children: [
|
|
4556
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-bootstrap-error-text", children: t("widget.error_desc") }),
|
|
4557
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "hw-bootstrap-error-retry", onClick: retryBootstrap, children: t("widget.retry") })
|
|
4122
4558
|
] }) }),
|
|
4123
|
-
isOpen && isReady && /* @__PURE__ */
|
|
4559
|
+
isOpen && isReady && /* @__PURE__ */ jsxs9(
|
|
4124
4560
|
"div",
|
|
4125
4561
|
{
|
|
4126
4562
|
ref: windowRef,
|
|
@@ -4132,24 +4568,24 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4132
4568
|
onTouchMove: handleTouchMove,
|
|
4133
4569
|
onTouchEnd: handleTouchEnd,
|
|
4134
4570
|
children: [
|
|
4135
|
-
/* @__PURE__ */
|
|
4136
|
-
wsDisconnected && /* @__PURE__ */
|
|
4137
|
-
/* @__PURE__ */
|
|
4571
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-drag-handle", children: /* @__PURE__ */ jsx14("div", { className: "hw-drag-handle-pill" }) }),
|
|
4572
|
+
wsDisconnected && /* @__PURE__ */ jsxs9("div", { className: "hw-disconnect", children: [
|
|
4573
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-disconnect-dot" }),
|
|
4138
4574
|
t("widget.reconnecting")
|
|
4139
4575
|
] }),
|
|
4140
4576
|
(subView === "content-detail" || subView === "content-category") && (() => {
|
|
4141
4577
|
const tabId = activeTab.replace("content:", "");
|
|
4142
4578
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
4143
4579
|
const headerTitle = subView === "content-category" && contentCategoryName ? contentCategoryName : contentTab?.label ? resolveLabel2(contentTab.label) : t("widget.content");
|
|
4144
|
-
return /* @__PURE__ */
|
|
4145
|
-
/* @__PURE__ */
|
|
4580
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-header hw-header--centered", children: [
|
|
4581
|
+
/* @__PURE__ */ jsx14(
|
|
4146
4582
|
"button",
|
|
4147
4583
|
{
|
|
4148
4584
|
type: "button",
|
|
4149
4585
|
className: "hw-header-back",
|
|
4150
4586
|
onClick: goBack,
|
|
4151
4587
|
"aria-label": t("widget.aria_back"),
|
|
4152
|
-
children: /* @__PURE__ */
|
|
4588
|
+
children: /* @__PURE__ */ jsx14(
|
|
4153
4589
|
"svg",
|
|
4154
4590
|
{
|
|
4155
4591
|
viewBox: "0 0 24 24",
|
|
@@ -4158,33 +4594,33 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4158
4594
|
strokeWidth: 2,
|
|
4159
4595
|
strokeLinecap: "round",
|
|
4160
4596
|
strokeLinejoin: "round",
|
|
4161
|
-
children: /* @__PURE__ */
|
|
4597
|
+
children: /* @__PURE__ */ jsx14("path", { d: "M15 18l-6-6 6-6" })
|
|
4162
4598
|
}
|
|
4163
4599
|
)
|
|
4164
4600
|
}
|
|
4165
4601
|
),
|
|
4166
|
-
/* @__PURE__ */
|
|
4167
|
-
/* @__PURE__ */
|
|
4602
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-title", children: headerTitle }),
|
|
4603
|
+
/* @__PURE__ */ jsx14(
|
|
4168
4604
|
"button",
|
|
4169
4605
|
{
|
|
4170
4606
|
type: "button",
|
|
4171
4607
|
className: "hw-header-close",
|
|
4172
4608
|
onClick: handleClose,
|
|
4173
4609
|
"aria-label": t("widget.aria_close"),
|
|
4174
|
-
children: /* @__PURE__ */
|
|
4610
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4175
4611
|
}
|
|
4176
4612
|
)
|
|
4177
4613
|
] });
|
|
4178
4614
|
})(),
|
|
4179
|
-
subView !== null && subView !== "content-detail" && subView !== "content-category" && /* @__PURE__ */
|
|
4180
|
-
/* @__PURE__ */
|
|
4615
|
+
subView !== null && subView !== "content-detail" && subView !== "content-category" && /* @__PURE__ */ jsxs9("div", { className: "hw-header hw-header--sub", children: [
|
|
4616
|
+
/* @__PURE__ */ jsx14(
|
|
4181
4617
|
"button",
|
|
4182
4618
|
{
|
|
4183
4619
|
type: "button",
|
|
4184
4620
|
className: "hw-header-back",
|
|
4185
4621
|
onClick: goBack,
|
|
4186
4622
|
"aria-label": t("widget.aria_back"),
|
|
4187
|
-
children: /* @__PURE__ */
|
|
4623
|
+
children: /* @__PURE__ */ jsx14(
|
|
4188
4624
|
"svg",
|
|
4189
4625
|
{
|
|
4190
4626
|
viewBox: "0 0 24 24",
|
|
@@ -4193,66 +4629,82 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4193
4629
|
strokeWidth: 2,
|
|
4194
4630
|
strokeLinecap: "round",
|
|
4195
4631
|
strokeLinejoin: "round",
|
|
4196
|
-
children: /* @__PURE__ */
|
|
4632
|
+
children: /* @__PURE__ */ jsx14("path", { d: "M15 18l-6-6 6-6" })
|
|
4197
4633
|
}
|
|
4198
4634
|
)
|
|
4199
4635
|
}
|
|
4200
4636
|
),
|
|
4201
|
-
/* @__PURE__ */
|
|
4202
|
-
/* @__PURE__ */
|
|
4203
|
-
/* @__PURE__ */
|
|
4204
|
-
/* @__PURE__ */
|
|
4205
|
-
/* @__PURE__ */
|
|
4637
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-header-identity", children: [
|
|
4638
|
+
/* @__PURE__ */ jsx14("div", { className: `hw-header-bot-icon${hasTeamAgent ? " hw-header-bot-icon--team" : ""}`, children: hasTeamAgent && activeConvSummary?.lastMessageSenderImage ? /* @__PURE__ */ jsx14("img", { src: activeConvSummary.lastMessageSenderImage, alt: headerName, className: "hw-header-agent-img" }) : hasTeamAgent ? /* @__PURE__ */ jsx14("span", { className: "hw-header-agent-initials", children: headerName.split(" ").map((w) => w[0]).join("").slice(0, 2).toUpperCase() }) : /* @__PURE__ */ jsx14(WidgetLogo, {}) }),
|
|
4639
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-header-info", children: [
|
|
4640
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-name", children: headerName }),
|
|
4641
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-status", children: subtitleText })
|
|
4206
4642
|
] })
|
|
4207
4643
|
] }),
|
|
4208
|
-
/* @__PURE__ */
|
|
4644
|
+
/* @__PURE__ */ jsx14(
|
|
4209
4645
|
"button",
|
|
4210
4646
|
{
|
|
4211
4647
|
type: "button",
|
|
4212
4648
|
className: "hw-header-close",
|
|
4213
4649
|
onClick: handleClose,
|
|
4214
4650
|
"aria-label": t("widget.aria_close"),
|
|
4215
|
-
children: /* @__PURE__ */
|
|
4651
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4216
4652
|
}
|
|
4217
4653
|
)
|
|
4218
4654
|
] }),
|
|
4219
|
-
subView === null && activeTab === "home" && /* @__PURE__ */
|
|
4220
|
-
/* @__PURE__ */
|
|
4221
|
-
/* @__PURE__ */
|
|
4222
|
-
/* @__PURE__ */
|
|
4223
|
-
/* @__PURE__ */
|
|
4655
|
+
subView === null && activeTab === "home" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
4656
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-hero", children: [
|
|
4657
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-hero-top", children: [
|
|
4658
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-hero-bot-icon", children: /* @__PURE__ */ jsx14(WidgetLogo, {}) }),
|
|
4659
|
+
/* @__PURE__ */ jsx14(
|
|
4224
4660
|
"button",
|
|
4225
4661
|
{
|
|
4226
4662
|
type: "button",
|
|
4227
4663
|
className: "hw-hero-close",
|
|
4228
4664
|
onClick: handleClose,
|
|
4229
4665
|
"aria-label": t("widget.aria_close"),
|
|
4230
|
-
children: /* @__PURE__ */
|
|
4666
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4231
4667
|
}
|
|
4232
4668
|
)
|
|
4233
4669
|
] }),
|
|
4234
|
-
/* @__PURE__ */
|
|
4670
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-hero-greeting", children: welcomeMessage.split("\n").map((line, i) => /* @__PURE__ */ jsxs9(
|
|
4235
4671
|
"span",
|
|
4236
4672
|
{
|
|
4237
4673
|
className: i === 0 ? "hw-hero-greeting-name" : "hw-hero-greeting-question",
|
|
4238
4674
|
children: [
|
|
4239
|
-
i > 0 && /* @__PURE__ */
|
|
4675
|
+
i > 0 && /* @__PURE__ */ jsx14("br", {}),
|
|
4240
4676
|
line
|
|
4241
4677
|
]
|
|
4242
4678
|
},
|
|
4243
4679
|
i
|
|
4244
4680
|
)) }),
|
|
4245
|
-
/* @__PURE__ */
|
|
4681
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-hero-subtitle", children: subtitleText })
|
|
4246
4682
|
] }),
|
|
4247
|
-
/* @__PURE__ */
|
|
4248
|
-
/* @__PURE__ */
|
|
4249
|
-
/* @__PURE__ */
|
|
4250
|
-
/* @__PURE__ */
|
|
4251
|
-
/* @__PURE__ */
|
|
4683
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-sheet", children: /* @__PURE__ */ jsxs9("div", { className: "hw-sheet-inner", children: [
|
|
4684
|
+
/* @__PURE__ */ jsxs9("button", { type: "button", className: "hw-card", onClick: openNewConversation, children: [
|
|
4685
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-card-body", children: [
|
|
4686
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-card-title", children: t("widget.send_us_message") }),
|
|
4687
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-card-meta", children: t("widget.reply_time") })
|
|
4252
4688
|
] }),
|
|
4253
|
-
/* @__PURE__ */
|
|
4689
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-card-arrow", children: /* @__PURE__ */ jsx14(SendIcon, {}) })
|
|
4254
4690
|
] }),
|
|
4255
|
-
/* @__PURE__ */
|
|
4691
|
+
announcementTabs.length > 0 && /* @__PURE__ */ jsx14(
|
|
4692
|
+
WhatsNewCard,
|
|
4693
|
+
{
|
|
4694
|
+
getUnseenEntries,
|
|
4695
|
+
announcementTabs,
|
|
4696
|
+
onViewAll: () => {
|
|
4697
|
+
switchTab(`content:${announcementTabs[0].id}`);
|
|
4698
|
+
},
|
|
4699
|
+
onSelect: (slug, tabId) => {
|
|
4700
|
+
switchTab(`content:${tabId}`);
|
|
4701
|
+
setContentDetailSlug(slug);
|
|
4702
|
+
setSubView("content-detail");
|
|
4703
|
+
markEntrySeen(slug);
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4706
|
+
),
|
|
4707
|
+
/* @__PURE__ */ jsx14(
|
|
4256
4708
|
HomeView,
|
|
4257
4709
|
{
|
|
4258
4710
|
conversations,
|
|
@@ -4262,17 +4714,17 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4262
4714
|
)
|
|
4263
4715
|
] }) })
|
|
4264
4716
|
] }),
|
|
4265
|
-
subView === null && activeTab === "messages" && /* @__PURE__ */
|
|
4266
|
-
/* @__PURE__ */
|
|
4267
|
-
/* @__PURE__ */
|
|
4268
|
-
/* @__PURE__ */
|
|
4717
|
+
subView === null && activeTab === "messages" && /* @__PURE__ */ jsxs9("div", { className: "hw-header hw-header--centered", children: [
|
|
4718
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-spacer" }),
|
|
4719
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-title", children: t("widget.messages") }),
|
|
4720
|
+
/* @__PURE__ */ jsx14(
|
|
4269
4721
|
"button",
|
|
4270
4722
|
{
|
|
4271
4723
|
type: "button",
|
|
4272
4724
|
className: "hw-header-close",
|
|
4273
4725
|
onClick: handleClose,
|
|
4274
4726
|
"aria-label": t("widget.aria_close"),
|
|
4275
|
-
children: /* @__PURE__ */
|
|
4727
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4276
4728
|
}
|
|
4277
4729
|
)
|
|
4278
4730
|
] }),
|
|
@@ -4280,23 +4732,23 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4280
4732
|
const tabId = activeTab.replace("content:", "");
|
|
4281
4733
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
4282
4734
|
if (!contentTab) return null;
|
|
4283
|
-
return /* @__PURE__ */
|
|
4284
|
-
/* @__PURE__ */
|
|
4285
|
-
/* @__PURE__ */
|
|
4286
|
-
/* @__PURE__ */
|
|
4735
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-header hw-header--centered", children: [
|
|
4736
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-spacer" }),
|
|
4737
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-header-title", children: resolveLabel2(contentTab.label) }),
|
|
4738
|
+
/* @__PURE__ */ jsx14(
|
|
4287
4739
|
"button",
|
|
4288
4740
|
{
|
|
4289
4741
|
type: "button",
|
|
4290
4742
|
className: "hw-header-close",
|
|
4291
4743
|
onClick: handleClose,
|
|
4292
4744
|
"aria-label": t("widget.aria_close"),
|
|
4293
|
-
children: /* @__PURE__ */
|
|
4745
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4294
4746
|
}
|
|
4295
4747
|
)
|
|
4296
4748
|
] });
|
|
4297
4749
|
})(),
|
|
4298
|
-
(subView !== null || activeTab !== "home") && /* @__PURE__ */
|
|
4299
|
-
subView === null && activeTab === "messages" && /* @__PURE__ */
|
|
4750
|
+
(subView !== null || activeTab !== "home") && /* @__PURE__ */ jsxs9("div", { className: "hw-content", children: [
|
|
4751
|
+
subView === null && activeTab === "messages" && /* @__PURE__ */ jsx14(
|
|
4300
4752
|
MessagesView,
|
|
4301
4753
|
{
|
|
4302
4754
|
conversations,
|
|
@@ -4304,7 +4756,7 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4304
4756
|
onNewClick: openNewConversation
|
|
4305
4757
|
}
|
|
4306
4758
|
),
|
|
4307
|
-
subView === "new" && /* @__PURE__ */
|
|
4759
|
+
subView === "new" && /* @__PURE__ */ jsx14(
|
|
4308
4760
|
NewConversationView,
|
|
4309
4761
|
{
|
|
4310
4762
|
text: newText,
|
|
@@ -4314,12 +4766,12 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4314
4766
|
welcomeMessage
|
|
4315
4767
|
}
|
|
4316
4768
|
),
|
|
4317
|
-
subView === "conversation" && activeId && /* @__PURE__ */
|
|
4769
|
+
subView === "conversation" && activeId && /* @__PURE__ */ jsx14(ConversationView, { conversationId: activeId }),
|
|
4318
4770
|
activeTab.startsWith("content:") && (() => {
|
|
4319
4771
|
const tabId = activeTab.replace("content:", "");
|
|
4320
4772
|
const contentTab = contentTabs.find((t2) => t2.id === tabId);
|
|
4321
4773
|
if (!contentTab) return null;
|
|
4322
|
-
return /* @__PURE__ */
|
|
4774
|
+
return /* @__PURE__ */ jsx14(
|
|
4323
4775
|
ContentTabView,
|
|
4324
4776
|
{
|
|
4325
4777
|
tab: contentTab,
|
|
@@ -4338,27 +4790,42 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4338
4790
|
);
|
|
4339
4791
|
})()
|
|
4340
4792
|
] }),
|
|
4341
|
-
showTabBar && /* @__PURE__ */
|
|
4793
|
+
showTabBar && /* @__PURE__ */ jsx14(
|
|
4342
4794
|
TabBar,
|
|
4343
4795
|
{
|
|
4344
4796
|
activeTab,
|
|
4345
4797
|
onTabChange: switchTab,
|
|
4346
4798
|
unreadCount: totalUnread,
|
|
4347
4799
|
contentTabs,
|
|
4348
|
-
showMessagesTab: agentConfig?.showMessagesTab ?? true
|
|
4800
|
+
showMessagesTab: agentConfig?.showMessagesTab ?? true,
|
|
4801
|
+
unseenAnnouncementCount
|
|
4349
4802
|
}
|
|
4350
4803
|
),
|
|
4351
|
-
/* @__PURE__ */
|
|
4804
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-powered", children: [
|
|
4352
4805
|
t("widget.powered_by"),
|
|
4353
4806
|
" ",
|
|
4354
|
-
/* @__PURE__ */
|
|
4807
|
+
/* @__PURE__ */ jsx14("a", { href: "https://helpway.ai", target: "_blank", rel: "noopener noreferrer", children: "Helpway" })
|
|
4355
4808
|
] })
|
|
4356
4809
|
]
|
|
4357
4810
|
}
|
|
4358
4811
|
),
|
|
4359
|
-
isReady && !isOpen && !isDismissed && !hideLauncher && /* @__PURE__ */
|
|
4360
|
-
/* @__PURE__ */
|
|
4361
|
-
|
|
4812
|
+
isReady && !isOpen && !isDismissed && !hideLauncher && /* @__PURE__ */ jsx14(MessagePreview, { onOpen: handleBubbleClick, avatar: /* @__PURE__ */ jsx14(WidgetLogo, {}) }),
|
|
4813
|
+
isReady && !isOpen && !isDismissed && !hideLauncher && /* @__PURE__ */ jsx14(
|
|
4814
|
+
AnnouncementPreviews,
|
|
4815
|
+
{
|
|
4816
|
+
onOpen: (slug, tabId) => {
|
|
4817
|
+
markEntrySeen(slug);
|
|
4818
|
+
handleBubbleClick();
|
|
4819
|
+
setTimeout(() => {
|
|
4820
|
+
switchTab(`content:${tabId}`);
|
|
4821
|
+
setContentDetailSlug(slug);
|
|
4822
|
+
setSubView("content-detail");
|
|
4823
|
+
}, 50);
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
),
|
|
4827
|
+
/* @__PURE__ */ jsx14(WidgetDebugOverlay, {}),
|
|
4828
|
+
isReady && !isDismissed && (!hideLauncher || isOpen) && /* @__PURE__ */ jsxs9(
|
|
4362
4829
|
"button",
|
|
4363
4830
|
{
|
|
4364
4831
|
ref: bubbleRef,
|
|
@@ -4375,22 +4842,25 @@ function DefaultWidget({ hideLauncher = false } = {}) {
|
|
|
4375
4842
|
"aria-expanded": isOpen,
|
|
4376
4843
|
"aria-haspopup": "dialog",
|
|
4377
4844
|
children: [
|
|
4378
|
-
/* @__PURE__ */
|
|
4845
|
+
/* @__PURE__ */ jsx14(
|
|
4379
4846
|
"span",
|
|
4380
4847
|
{
|
|
4381
4848
|
className: `hw-bubble-icon hw-bubble-icon--bot ${isOpen ? "hw-bubble-icon--hidden" : ""}`,
|
|
4382
|
-
children: /* @__PURE__ */
|
|
4849
|
+
children: /* @__PURE__ */ jsx14(LauncherIcon, {})
|
|
4383
4850
|
}
|
|
4384
4851
|
),
|
|
4385
|
-
/* @__PURE__ */
|
|
4852
|
+
/* @__PURE__ */ jsx14(
|
|
4386
4853
|
"span",
|
|
4387
4854
|
{
|
|
4388
4855
|
className: `hw-bubble-icon hw-bubble-icon--close ${!isOpen ? "hw-bubble-icon--hidden" : ""}`,
|
|
4389
|
-
children: /* @__PURE__ */
|
|
4856
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 24 })
|
|
4390
4857
|
}
|
|
4391
4858
|
),
|
|
4392
|
-
launcherStyle !== "icon" && !isOpen && /* @__PURE__ */
|
|
4393
|
-
!isOpen && totalUnread > 0 && /* @__PURE__ */
|
|
4859
|
+
launcherStyle !== "icon" && !isOpen && /* @__PURE__ */ jsx14("span", { className: "hw-bubble-label", children: launcherStyle === "help" ? t("widget.help") : companyName }),
|
|
4860
|
+
!isOpen && (totalUnread > 0 || unseenAnnouncementCount > 0) && /* @__PURE__ */ jsxs9("div", { className: "hw-bubble-badge", children: [
|
|
4861
|
+
totalUnread > 0 ? totalUnread : "",
|
|
4862
|
+
totalUnread === 0 && unseenAnnouncementCount > 0 && /* @__PURE__ */ jsx14("span", { className: "hw-bubble-badge-dot" })
|
|
4863
|
+
] })
|
|
4394
4864
|
]
|
|
4395
4865
|
}
|
|
4396
4866
|
)
|
|
@@ -4403,10 +4873,11 @@ function TabBar({
|
|
|
4403
4873
|
onTabChange,
|
|
4404
4874
|
unreadCount,
|
|
4405
4875
|
contentTabs,
|
|
4406
|
-
showMessagesTab = true
|
|
4876
|
+
showMessagesTab = true,
|
|
4877
|
+
unseenAnnouncementCount = 0
|
|
4407
4878
|
}) {
|
|
4408
|
-
return /* @__PURE__ */
|
|
4409
|
-
/* @__PURE__ */
|
|
4879
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-tabs", role: "tablist", children: [
|
|
4880
|
+
/* @__PURE__ */ jsxs9(
|
|
4410
4881
|
"button",
|
|
4411
4882
|
{
|
|
4412
4883
|
type: "button",
|
|
@@ -4415,12 +4886,12 @@ function TabBar({
|
|
|
4415
4886
|
role: "tab",
|
|
4416
4887
|
"aria-selected": activeTab === "home",
|
|
4417
4888
|
children: [
|
|
4418
|
-
/* @__PURE__ */
|
|
4419
|
-
/* @__PURE__ */
|
|
4889
|
+
/* @__PURE__ */ jsx14(HomeIcon, {}),
|
|
4890
|
+
/* @__PURE__ */ jsx14("span", { children: t("widget.home") })
|
|
4420
4891
|
]
|
|
4421
4892
|
}
|
|
4422
4893
|
),
|
|
4423
|
-
showMessagesTab && /* @__PURE__ */
|
|
4894
|
+
showMessagesTab && /* @__PURE__ */ jsxs9(
|
|
4424
4895
|
"button",
|
|
4425
4896
|
{
|
|
4426
4897
|
type: "button",
|
|
@@ -4429,15 +4900,15 @@ function TabBar({
|
|
|
4429
4900
|
role: "tab",
|
|
4430
4901
|
"aria-selected": activeTab === "messages",
|
|
4431
4902
|
children: [
|
|
4432
|
-
/* @__PURE__ */
|
|
4433
|
-
/* @__PURE__ */
|
|
4434
|
-
unreadCount > 0 && /* @__PURE__ */
|
|
4903
|
+
/* @__PURE__ */ jsxs9("span", { className: "hw-tabs-icon-wrap", children: [
|
|
4904
|
+
/* @__PURE__ */ jsx14(MessagesIcon, {}),
|
|
4905
|
+
unreadCount > 0 && /* @__PURE__ */ jsx14("span", { className: "hw-tabs-badge", children: unreadCount > 99 ? "99+" : unreadCount })
|
|
4435
4906
|
] }),
|
|
4436
|
-
/* @__PURE__ */
|
|
4907
|
+
/* @__PURE__ */ jsx14("span", { children: t("widget.messages") })
|
|
4437
4908
|
]
|
|
4438
4909
|
}
|
|
4439
4910
|
),
|
|
4440
|
-
contentTabs.map((tab) => /* @__PURE__ */
|
|
4911
|
+
contentTabs.map((tab) => /* @__PURE__ */ jsxs9(
|
|
4441
4912
|
"button",
|
|
4442
4913
|
{
|
|
4443
4914
|
type: "button",
|
|
@@ -4446,8 +4917,11 @@ function TabBar({
|
|
|
4446
4917
|
role: "tab",
|
|
4447
4918
|
"aria-selected": activeTab === `content:${tab.id}`,
|
|
4448
4919
|
children: [
|
|
4449
|
-
/* @__PURE__ */
|
|
4450
|
-
|
|
4920
|
+
/* @__PURE__ */ jsxs9("span", { className: "hw-tabs-icon-wrap", children: [
|
|
4921
|
+
/* @__PURE__ */ jsx14(ContentTabIconComponent, { icon: tab.icon }),
|
|
4922
|
+
tab.isAnnouncements && unseenAnnouncementCount > 0 && /* @__PURE__ */ jsx14("span", { className: "hw-tabs-dot" })
|
|
4923
|
+
] }),
|
|
4924
|
+
/* @__PURE__ */ jsx14("span", { children: resolveLabel2(tab.label) })
|
|
4451
4925
|
]
|
|
4452
4926
|
},
|
|
4453
4927
|
tab.id
|
|
@@ -4461,9 +4935,9 @@ function HomeView({
|
|
|
4461
4935
|
}) {
|
|
4462
4936
|
const recent = conversations.slice(0, 3);
|
|
4463
4937
|
if (recent.length === 0) return null;
|
|
4464
|
-
return /* @__PURE__ */
|
|
4465
|
-
/* @__PURE__ */
|
|
4466
|
-
recent.map((conv, i) => /* @__PURE__ */
|
|
4938
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-recent-card", children: [
|
|
4939
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-recent-header", children: t("widget.recent_conversations") }),
|
|
4940
|
+
recent.map((conv, i) => /* @__PURE__ */ jsx14(
|
|
4467
4941
|
ConversationRow,
|
|
4468
4942
|
{
|
|
4469
4943
|
conversation: conv,
|
|
@@ -4472,7 +4946,7 @@ function HomeView({
|
|
|
4472
4946
|
},
|
|
4473
4947
|
conv.id
|
|
4474
4948
|
)),
|
|
4475
|
-
conversations.length > 3 && /* @__PURE__ */
|
|
4949
|
+
conversations.length > 3 && /* @__PURE__ */ jsx14("button", { type: "button", className: "hw-recent-see-all", onClick: onMessagesClick, children: t("widget.see_all") })
|
|
4476
4950
|
] });
|
|
4477
4951
|
}
|
|
4478
4952
|
function MessagesView({
|
|
@@ -4481,28 +4955,28 @@ function MessagesView({
|
|
|
4481
4955
|
onNewClick
|
|
4482
4956
|
}) {
|
|
4483
4957
|
if (conversations.length === 0) {
|
|
4484
|
-
return /* @__PURE__ */
|
|
4485
|
-
/* @__PURE__ */
|
|
4486
|
-
/* @__PURE__ */
|
|
4487
|
-
/* @__PURE__ */
|
|
4488
|
-
/* @__PURE__ */
|
|
4958
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-empty-state", children: [
|
|
4959
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-empty-icon-wrap", children: /* @__PURE__ */ jsx14(MessagesIcon, {}) }),
|
|
4960
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-empty-title", children: t("widget.no_messages") }),
|
|
4961
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-empty-desc", children: t("widget.no_messages_desc") }),
|
|
4962
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "hw-empty-btn", onClick: onNewClick, children: t("widget.start_conversation") })
|
|
4489
4963
|
] });
|
|
4490
4964
|
}
|
|
4491
|
-
return /* @__PURE__ */
|
|
4965
|
+
return /* @__PURE__ */ jsx14("div", { className: "hw-msgs-tab", children: conversations.map((conv) => /* @__PURE__ */ jsx14(ConversationCard, { conversation: conv, onSelect }, conv.id)) });
|
|
4492
4966
|
}
|
|
4493
4967
|
function ConvCardBody({ conv }) {
|
|
4494
4968
|
const agentName = useWidgetStore((s) => s.agentConfig?.name) ?? "Support";
|
|
4495
4969
|
const isTeam = conv.lastMessageSenderType === "team" && conv.lastMessageSenderName;
|
|
4496
4970
|
const displayName = isTeam ? conv.lastMessageSenderName : agentName;
|
|
4497
4971
|
const preview = conv.lastMessageText ?? t("widget.no_preview");
|
|
4498
|
-
return /* @__PURE__ */
|
|
4499
|
-
/* @__PURE__ */
|
|
4500
|
-
/* @__PURE__ */
|
|
4501
|
-
/* @__PURE__ */
|
|
4502
|
-
/* @__PURE__ */
|
|
4503
|
-
conv.lastMessageAt && /* @__PURE__ */
|
|
4972
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
4973
|
+
/* @__PURE__ */ jsx14("div", { className: `hw-conv-card-avatar${isTeam ? " hw-conv-card-avatar--team" : ""}`, children: isTeam ? conv.lastMessageSenderImage ? /* @__PURE__ */ jsx14("img", { src: conv.lastMessageSenderImage, alt: displayName, className: "hw-conv-card-avatar-img" }) : /* @__PURE__ */ jsx14("span", { className: "hw-conv-card-avatar-initials", children: displayName.split(" ").map((w) => w[0]).join("").slice(0, 2).toUpperCase() }) : /* @__PURE__ */ jsx14(WidgetLogo, {}) }),
|
|
4974
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-conv-card-content", children: [
|
|
4975
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-conv-card-top", children: [
|
|
4976
|
+
/* @__PURE__ */ jsx14("span", { className: "hw-conv-card-name", children: displayName }),
|
|
4977
|
+
conv.lastMessageAt && /* @__PURE__ */ jsx14("span", { className: "hw-conv-card-time", children: formatRelativeTime(conv.lastMessageAt) })
|
|
4504
4978
|
] }),
|
|
4505
|
-
/* @__PURE__ */
|
|
4979
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-conv-card-preview", children: preview })
|
|
4506
4980
|
] })
|
|
4507
4981
|
] });
|
|
4508
4982
|
}
|
|
@@ -4511,15 +4985,15 @@ function ConversationCard({
|
|
|
4511
4985
|
onSelect
|
|
4512
4986
|
}) {
|
|
4513
4987
|
const hasUnread = conv.unreadCount > 0;
|
|
4514
|
-
return /* @__PURE__ */
|
|
4988
|
+
return /* @__PURE__ */ jsxs9(
|
|
4515
4989
|
"button",
|
|
4516
4990
|
{
|
|
4517
4991
|
type: "button",
|
|
4518
4992
|
className: `hw-conv-card ${hasUnread ? "hw-conv-card--unread" : ""}`,
|
|
4519
4993
|
onClick: () => onSelect(conv.id),
|
|
4520
4994
|
children: [
|
|
4521
|
-
/* @__PURE__ */
|
|
4522
|
-
hasUnread && /* @__PURE__ */
|
|
4995
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-conv-card-row", children: /* @__PURE__ */ jsx14(ConvCardBody, { conv }) }),
|
|
4996
|
+
hasUnread && /* @__PURE__ */ jsx14("div", { className: "hw-conv-card-badge", children: conv.unreadCount })
|
|
4523
4997
|
]
|
|
4524
4998
|
}
|
|
4525
4999
|
);
|
|
@@ -4530,15 +5004,15 @@ function ConversationRow({
|
|
|
4530
5004
|
isLast
|
|
4531
5005
|
}) {
|
|
4532
5006
|
const hasUnread = conv.unreadCount > 0;
|
|
4533
|
-
return /* @__PURE__ */
|
|
5007
|
+
return /* @__PURE__ */ jsxs9(
|
|
4534
5008
|
"button",
|
|
4535
5009
|
{
|
|
4536
5010
|
type: "button",
|
|
4537
5011
|
className: `hw-recent-row ${hasUnread ? "hw-recent-row--unread" : ""} ${isLast ? "hw-recent-row--last" : ""}`,
|
|
4538
5012
|
onClick: () => onSelect(conv.id),
|
|
4539
5013
|
children: [
|
|
4540
|
-
/* @__PURE__ */
|
|
4541
|
-
hasUnread && /* @__PURE__ */
|
|
5014
|
+
/* @__PURE__ */ jsx14(ConvCardBody, { conv }),
|
|
5015
|
+
hasUnread && /* @__PURE__ */ jsx14("div", { className: "hw-recent-row-badge", children: conv.unreadCount })
|
|
4542
5016
|
]
|
|
4543
5017
|
}
|
|
4544
5018
|
);
|
|
@@ -4546,10 +5020,10 @@ function ConversationRow({
|
|
|
4546
5020
|
function InlineEmailPrompt({ conversationId }) {
|
|
4547
5021
|
const { client, store } = useWidgetContext();
|
|
4548
5022
|
const updateContact = useWidgetStore((s) => s.updateVisitorContact);
|
|
4549
|
-
const [email, setEmail] =
|
|
4550
|
-
const [isSubmitting, setIsSubmitting] =
|
|
4551
|
-
const [isSuccess, setIsSuccess] =
|
|
4552
|
-
const [hasError, setHasError] =
|
|
5023
|
+
const [email, setEmail] = useState13("");
|
|
5024
|
+
const [isSubmitting, setIsSubmitting] = useState13(false);
|
|
5025
|
+
const [isSuccess, setIsSuccess] = useState13(false);
|
|
5026
|
+
const [hasError, setHasError] = useState13(false);
|
|
4553
5027
|
const handleSubmit = async () => {
|
|
4554
5028
|
const trimmed = email.trim();
|
|
4555
5029
|
if (!trimmed || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed)) {
|
|
@@ -4590,23 +5064,23 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
4590
5064
|
}
|
|
4591
5065
|
};
|
|
4592
5066
|
if (isSuccess) {
|
|
4593
|
-
return /* @__PURE__ */
|
|
4594
|
-
/* @__PURE__ */
|
|
5067
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-email-card hw-email-card--success", children: [
|
|
5068
|
+
/* @__PURE__ */ jsx14("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "#22c55e", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx14("polyline", { points: "20 6 9 17 4 12" }) }),
|
|
4595
5069
|
t("widget.email_saved")
|
|
4596
5070
|
] });
|
|
4597
5071
|
}
|
|
4598
|
-
return /* @__PURE__ */
|
|
4599
|
-
/* @__PURE__ */
|
|
4600
|
-
/* @__PURE__ */
|
|
4601
|
-
/* @__PURE__ */
|
|
4602
|
-
/* @__PURE__ */
|
|
5072
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-email-card", children: [
|
|
5073
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-email-card-header", children: [
|
|
5074
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-email-card-icon", children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
5075
|
+
/* @__PURE__ */ jsx14("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
|
|
5076
|
+
/* @__PURE__ */ jsx14("path", { d: "M22 7l-10 7L2 7" })
|
|
4603
5077
|
] }) }),
|
|
4604
|
-
/* @__PURE__ */
|
|
4605
|
-
/* @__PURE__ */
|
|
4606
|
-
/* @__PURE__ */
|
|
5078
|
+
/* @__PURE__ */ jsxs9("div", { children: [
|
|
5079
|
+
/* @__PURE__ */ jsx14("p", { className: "hw-email-card-title", children: t("widget.email_title") }),
|
|
5080
|
+
/* @__PURE__ */ jsx14("p", { className: "hw-email-card-subtitle", children: t("widget.email_subtitle") })
|
|
4607
5081
|
] })
|
|
4608
5082
|
] }),
|
|
4609
|
-
/* @__PURE__ */
|
|
5083
|
+
/* @__PURE__ */ jsx14(
|
|
4610
5084
|
"input",
|
|
4611
5085
|
{
|
|
4612
5086
|
type: "email",
|
|
@@ -4622,14 +5096,14 @@ function InlineEmailPrompt({ conversationId }) {
|
|
|
4622
5096
|
placeholder: t("widget.email_placeholder")
|
|
4623
5097
|
}
|
|
4624
5098
|
),
|
|
4625
|
-
/* @__PURE__ */
|
|
5099
|
+
/* @__PURE__ */ jsx14(
|
|
4626
5100
|
"button",
|
|
4627
5101
|
{
|
|
4628
5102
|
type: "button",
|
|
4629
5103
|
className: "hw-email-card-submit",
|
|
4630
5104
|
onClick: handleSubmit,
|
|
4631
5105
|
disabled: isSubmitting || !email.trim(),
|
|
4632
|
-
children: isSubmitting ? /* @__PURE__ */
|
|
5106
|
+
children: isSubmitting ? /* @__PURE__ */ jsx14("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "32", strokeDashoffset: "32", children: /* @__PURE__ */ jsx14("animate", { attributeName: "stroke-dashoffset", values: "32;0", dur: "1s", repeatCount: "indefinite" }) }) }) : t("widget.email_continue")
|
|
4633
5107
|
}
|
|
4634
5108
|
)
|
|
4635
5109
|
] });
|
|
@@ -4641,8 +5115,8 @@ function NewConversationView({
|
|
|
4641
5115
|
isSubmitting,
|
|
4642
5116
|
welcomeMessage
|
|
4643
5117
|
}) {
|
|
4644
|
-
return /* @__PURE__ */
|
|
4645
|
-
/* @__PURE__ */
|
|
5118
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-new", children: [
|
|
5119
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-new-welcome", children: /* @__PURE__ */ jsx14(
|
|
4646
5120
|
MessageBubble,
|
|
4647
5121
|
{
|
|
4648
5122
|
text: welcomeMessage,
|
|
@@ -4650,7 +5124,7 @@ function NewConversationView({
|
|
|
4650
5124
|
parts: null
|
|
4651
5125
|
}
|
|
4652
5126
|
) }),
|
|
4653
|
-
/* @__PURE__ */
|
|
5127
|
+
/* @__PURE__ */ jsx14(
|
|
4654
5128
|
Composer,
|
|
4655
5129
|
{
|
|
4656
5130
|
text,
|
|
@@ -4677,111 +5151,105 @@ function ConversationView({ conversationId }) {
|
|
|
4677
5151
|
emailGateConvId
|
|
4678
5152
|
} = useComposer(conversationId);
|
|
4679
5153
|
const { isTyping, isAiProcessing, setTyping } = usePresence(conversationId);
|
|
5154
|
+
const streamingText = useWidgetStore((s) => s.streamingText.get(conversationId) ?? "");
|
|
4680
5155
|
const agentConfig = useWidgetStore((s) => s.agentConfig);
|
|
4681
5156
|
const visitorContact = useWidgetStore((s) => s.visitor?.contact);
|
|
4682
5157
|
const isResolved = useWidgetStore((s) => {
|
|
4683
5158
|
const conv = s.conversations.find((c) => c.id === conversationId);
|
|
4684
5159
|
return conv?.status === "resolved";
|
|
4685
5160
|
});
|
|
4686
|
-
const
|
|
5161
|
+
const visitorMessageCount = items.filter(
|
|
4687
5162
|
(it) => it.type === "message" && Boolean(it.visitorId)
|
|
4688
|
-
);
|
|
5163
|
+
).length;
|
|
4689
5164
|
const hasAiReply = items.some(
|
|
4690
5165
|
(it) => it.type === "message" && Boolean(it.aiAgentId)
|
|
4691
5166
|
);
|
|
4692
5167
|
const visitorOwnEmail = useWidgetStore((s) => s.visitor?.email);
|
|
4693
5168
|
const hasEmail = !!visitorContact?.email || !!visitorOwnEmail;
|
|
4694
|
-
const needsEmailPostReply = !!agentConfig?.requireVisitorEmail && !hasEmail &&
|
|
5169
|
+
const needsEmailPostReply = !!agentConfig?.requireVisitorEmail && !hasEmail && visitorMessageCount >= 2 && hasAiReply;
|
|
4695
5170
|
const needsEmail = needsEmailPostReply || !!emailGateConvId;
|
|
4696
5171
|
if (isLoading && items.length === 0) {
|
|
4697
|
-
return /* @__PURE__ */
|
|
4698
|
-
/* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
/* @__PURE__ */
|
|
4702
|
-
/* @__PURE__ */
|
|
5172
|
+
return /* @__PURE__ */ jsx14("div", { className: "hw-messages", children: /* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-messages", children: [
|
|
5173
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-msg", children: [
|
|
5174
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-avatar" }),
|
|
5175
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-bubble", children: [
|
|
5176
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 140 } }),
|
|
5177
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 200 } })
|
|
4703
5178
|
] })
|
|
4704
5179
|
] }),
|
|
4705
|
-
/* @__PURE__ */
|
|
4706
|
-
/* @__PURE__ */
|
|
4707
|
-
/* @__PURE__ */
|
|
4708
|
-
/* @__PURE__ */
|
|
4709
|
-
/* @__PURE__ */
|
|
4710
|
-
/* @__PURE__ */
|
|
4711
|
-
/* @__PURE__ */
|
|
5180
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton-msg hw-skeleton-msg--right", children: /* @__PURE__ */ jsx14("div", { className: "hw-skeleton-bubble", style: { alignItems: "flex-end" }, children: /* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 160 } }) }) }),
|
|
5181
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-msg", children: [
|
|
5182
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-avatar" }),
|
|
5183
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-skeleton-bubble", children: [
|
|
5184
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 180 } }),
|
|
5185
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 120 } }),
|
|
5186
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-skeleton hw-skeleton-line", style: { width: 80 } })
|
|
4712
5187
|
] })
|
|
4713
5188
|
] })
|
|
4714
5189
|
] }) });
|
|
4715
5190
|
}
|
|
4716
|
-
return /* @__PURE__ */
|
|
4717
|
-
/* @__PURE__ */
|
|
5191
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
5192
|
+
/* @__PURE__ */ jsx14(
|
|
4718
5193
|
MessageList,
|
|
4719
5194
|
{
|
|
4720
5195
|
items,
|
|
4721
5196
|
isTyping,
|
|
4722
5197
|
isAiProcessing,
|
|
5198
|
+
streamingText: streamingText || void 0,
|
|
4723
5199
|
hasMore,
|
|
4724
5200
|
isLoadingMore: isLoading,
|
|
4725
5201
|
onLoadMore: loadMore
|
|
4726
5202
|
}
|
|
4727
5203
|
),
|
|
4728
|
-
isResolved
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
{
|
|
4735
|
-
type: "button",
|
|
4736
|
-
className: "hw-send-error-retry",
|
|
4737
|
-
onClick: () => {
|
|
4738
|
-
clearSendError();
|
|
4739
|
-
submit();
|
|
4740
|
-
},
|
|
4741
|
-
children: t("widget.retry")
|
|
4742
|
-
}
|
|
4743
|
-
)
|
|
4744
|
-
] }),
|
|
4745
|
-
/* @__PURE__ */ jsx13(
|
|
4746
|
-
Composer,
|
|
5204
|
+
isResolved && /* @__PURE__ */ jsx14(ResolvedBanner, { conversationId }),
|
|
5205
|
+
needsEmail && /* @__PURE__ */ jsx14(InlineEmailPrompt, { conversationId: emailGateConvId ?? void 0 }),
|
|
5206
|
+
sendError && /* @__PURE__ */ jsxs9("div", { className: "hw-send-error", children: [
|
|
5207
|
+
sendError,
|
|
5208
|
+
/* @__PURE__ */ jsx14(
|
|
5209
|
+
"button",
|
|
4747
5210
|
{
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
onRemoveAttachment: removeAttachment,
|
|
4756
|
-
disabled: needsEmail
|
|
5211
|
+
type: "button",
|
|
5212
|
+
className: "hw-send-error-retry",
|
|
5213
|
+
onClick: () => {
|
|
5214
|
+
clearSendError();
|
|
5215
|
+
submit();
|
|
5216
|
+
},
|
|
5217
|
+
children: t("widget.retry")
|
|
4757
5218
|
}
|
|
4758
5219
|
)
|
|
4759
|
-
] })
|
|
5220
|
+
] }),
|
|
5221
|
+
/* @__PURE__ */ jsx14(
|
|
5222
|
+
Composer,
|
|
5223
|
+
{
|
|
5224
|
+
text,
|
|
5225
|
+
onTextChange: setText,
|
|
5226
|
+
onSubmit: submit,
|
|
5227
|
+
onTyping: setTyping,
|
|
5228
|
+
isSubmitting,
|
|
5229
|
+
attachments,
|
|
5230
|
+
onAddFiles: addFiles,
|
|
5231
|
+
onRemoveAttachment: removeAttachment,
|
|
5232
|
+
disabled: needsEmail
|
|
5233
|
+
}
|
|
5234
|
+
)
|
|
4760
5235
|
] });
|
|
4761
5236
|
}
|
|
4762
5237
|
function ResolvedBanner({ conversationId }) {
|
|
4763
5238
|
const { client } = useWidgetContext();
|
|
4764
|
-
const [csatRating, setCsatRating] =
|
|
4765
|
-
const [csatSubmitted, setCsatSubmitted] =
|
|
4766
|
-
const handleReopen = async () => {
|
|
4767
|
-
try {
|
|
4768
|
-
await client.widget.sendMessage.mutate({ conversationId, text: t("widget.send_followup") });
|
|
4769
|
-
} catch (err) {
|
|
4770
|
-
console.error("Failed to reopen:", err);
|
|
4771
|
-
}
|
|
4772
|
-
};
|
|
5239
|
+
const [csatRating, setCsatRating] = useState13(null);
|
|
5240
|
+
const [csatSubmitted, setCsatSubmitted] = useState13(false);
|
|
4773
5241
|
const handleCsat = (rating) => {
|
|
4774
5242
|
setCsatRating(rating);
|
|
4775
5243
|
setCsatSubmitted(true);
|
|
4776
5244
|
client.widget.sendCsat.mutate({ conversationId, rating }).catch(() => {
|
|
4777
5245
|
});
|
|
4778
5246
|
};
|
|
4779
|
-
return /* @__PURE__ */
|
|
4780
|
-
/* @__PURE__ */
|
|
4781
|
-
!csatSubmitted ? /* @__PURE__ */
|
|
4782
|
-
/* @__PURE__ */
|
|
4783
|
-
/* @__PURE__ */
|
|
4784
|
-
/* @__PURE__ */
|
|
5247
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-resolved", children: [
|
|
5248
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-resolved-text", children: t("widget.resolved_text") }),
|
|
5249
|
+
!csatSubmitted ? /* @__PURE__ */ jsxs9("div", { className: "hw-csat", children: [
|
|
5250
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-csat-label", children: t("widget.csat_label") }),
|
|
5251
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-csat-buttons", children: [
|
|
5252
|
+
/* @__PURE__ */ jsx14(
|
|
4785
5253
|
"button",
|
|
4786
5254
|
{
|
|
4787
5255
|
type: "button",
|
|
@@ -4791,7 +5259,7 @@ function ResolvedBanner({ conversationId }) {
|
|
|
4791
5259
|
children: "\u{1F44D}"
|
|
4792
5260
|
}
|
|
4793
5261
|
),
|
|
4794
|
-
/* @__PURE__ */
|
|
5262
|
+
/* @__PURE__ */ jsx14(
|
|
4795
5263
|
"button",
|
|
4796
5264
|
{
|
|
4797
5265
|
type: "button",
|
|
@@ -4802,86 +5270,123 @@ function ResolvedBanner({ conversationId }) {
|
|
|
4802
5270
|
}
|
|
4803
5271
|
)
|
|
4804
5272
|
] })
|
|
4805
|
-
] }) : /* @__PURE__ */
|
|
4806
|
-
/* @__PURE__ */ jsx13("div", { className: "hw-resolved-actions", children: /* @__PURE__ */ jsx13("button", { type: "button", className: "hw-resolved-reopen", onClick: handleReopen, children: t("widget.send_followup") }) })
|
|
5273
|
+
] }) : /* @__PURE__ */ jsx14("div", { className: "hw-csat-thanks", children: t("widget.csat_thanks") })
|
|
4807
5274
|
] });
|
|
4808
5275
|
}
|
|
4809
|
-
function
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
5276
|
+
function stripMarkdown(text) {
|
|
5277
|
+
return text.replace(/^#{1,6}\s+/gm, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/^[-*+]\s+/gm, "").replace(/\[(.+?)\]\(.+?\)/g, "$1").replace(/`(.+?)`/g, "$1").replace(/\n{2,}/g, " ").replace(/\n/g, " ").trim();
|
|
5278
|
+
}
|
|
5279
|
+
function AnnouncementPreviews({ onOpen }) {
|
|
5280
|
+
const previews = useWidgetStore((s) => s.announcementPreviews);
|
|
5281
|
+
const dismissPreview = useWidgetStore((s) => s.dismissAnnouncementPreview);
|
|
4813
5282
|
const agentName = useWidgetStore((s) => s.agentConfig?.name) ?? "Support";
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
5283
|
+
if (previews.length === 0) return null;
|
|
5284
|
+
return /* @__PURE__ */ jsx14("div", { className: "hw-preview-stack", children: previews.map((preview) => /* @__PURE__ */ jsx14(
|
|
5285
|
+
AnnouncementPreviewItem,
|
|
5286
|
+
{
|
|
5287
|
+
preview,
|
|
5288
|
+
agentName,
|
|
5289
|
+
onOpen,
|
|
5290
|
+
onDismiss: (slug) => dismissPreview(slug)
|
|
5291
|
+
},
|
|
5292
|
+
preview.slug
|
|
5293
|
+
)) });
|
|
5294
|
+
}
|
|
5295
|
+
function AnnouncementPreviewItem({
|
|
5296
|
+
preview,
|
|
5297
|
+
agentName,
|
|
5298
|
+
onOpen,
|
|
5299
|
+
onDismiss
|
|
5300
|
+
}) {
|
|
5301
|
+
const [closing, setClosing] = useState13(false);
|
|
4824
5302
|
const handleClose = (e) => {
|
|
4825
5303
|
e.stopPropagation();
|
|
4826
5304
|
setClosing(true);
|
|
4827
5305
|
setTimeout(() => {
|
|
4828
|
-
|
|
5306
|
+
onDismiss(preview.slug);
|
|
4829
5307
|
setClosing(false);
|
|
4830
5308
|
}, 200);
|
|
4831
5309
|
};
|
|
4832
|
-
|
|
4833
|
-
const targetConvId = preview.conversationId;
|
|
4834
|
-
dismissPreview();
|
|
4835
|
-
setActiveConversation(targetConvId);
|
|
4836
|
-
onOpen();
|
|
4837
|
-
};
|
|
4838
|
-
const messages = preview.messages?.length ? preview.messages : [{ text: preview.text }];
|
|
4839
|
-
const hasQr = preview.quickReplies && preview.quickReplies.options.length > 0;
|
|
4840
|
-
return /* @__PURE__ */ jsxs8(
|
|
5310
|
+
return /* @__PURE__ */ jsxs9(
|
|
4841
5311
|
"div",
|
|
4842
5312
|
{
|
|
4843
|
-
className: `hw-preview ${closing ? "hw-preview--closing" : ""}`,
|
|
4844
|
-
onClick:
|
|
5313
|
+
className: `hw-preview hw-preview--announcement ${closing ? "hw-preview--closing" : ""}`,
|
|
5314
|
+
onClick: () => onOpen(preview.slug, preview.tabId),
|
|
4845
5315
|
role: "button",
|
|
4846
5316
|
tabIndex: 0,
|
|
4847
5317
|
children: [
|
|
4848
|
-
/* @__PURE__ */
|
|
4849
|
-
/* @__PURE__ */
|
|
4850
|
-
/* @__PURE__ */
|
|
4851
|
-
/* @__PURE__ */
|
|
5318
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-preview-header", children: [
|
|
5319
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-preview-avatar", children: /* @__PURE__ */ jsx14(WidgetLogo, {}) }),
|
|
5320
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-preview-name", children: agentName }),
|
|
5321
|
+
/* @__PURE__ */ jsx14(
|
|
4852
5322
|
"button",
|
|
4853
5323
|
{
|
|
4854
5324
|
type: "button",
|
|
4855
5325
|
className: "hw-preview-close",
|
|
4856
5326
|
onClick: handleClose,
|
|
4857
5327
|
"aria-label": t("widget.aria_dismiss"),
|
|
4858
|
-
children: /* @__PURE__ */
|
|
5328
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 20 })
|
|
4859
5329
|
}
|
|
4860
5330
|
)
|
|
4861
5331
|
] }),
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
type: "button",
|
|
4869
|
-
className: "hw-preview-qr-btn",
|
|
4870
|
-
onClick: (e) => {
|
|
4871
|
-
e.stopPropagation();
|
|
4872
|
-
dismissPreview();
|
|
4873
|
-
setActiveConversation(preview.conversationId);
|
|
4874
|
-
onOpen();
|
|
4875
|
-
},
|
|
4876
|
-
children: opt.label
|
|
4877
|
-
},
|
|
4878
|
-
opt.id
|
|
4879
|
-
)) })
|
|
4880
|
-
] })
|
|
5332
|
+
preview.badge && /* @__PURE__ */ jsx14("div", { className: "hw-announcement-badge", children: preview.badge }),
|
|
5333
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-preview-body hw-preview-body--title", children: preview.title }),
|
|
5334
|
+
preview.body && (() => {
|
|
5335
|
+
const clean = stripMarkdown(preview.body);
|
|
5336
|
+
return /* @__PURE__ */ jsx14("div", { className: "hw-preview-body hw-preview-body--desc", children: clean.length > 120 ? `${clean.slice(0, 120)}\u2026` : clean });
|
|
5337
|
+
})()
|
|
4881
5338
|
]
|
|
4882
5339
|
}
|
|
4883
5340
|
);
|
|
4884
5341
|
}
|
|
5342
|
+
function WhatsNewCard({
|
|
5343
|
+
getUnseenEntries,
|
|
5344
|
+
announcementTabs,
|
|
5345
|
+
onViewAll,
|
|
5346
|
+
onSelect
|
|
5347
|
+
}) {
|
|
5348
|
+
const unseen = getUnseenEntries();
|
|
5349
|
+
if (unseen.length === 0) return null;
|
|
5350
|
+
const display = unseen.slice(0, 3);
|
|
5351
|
+
const badgeFieldMap = new Map(
|
|
5352
|
+
announcementTabs.map((t2) => [t2.id, t2.display?.badgeField])
|
|
5353
|
+
);
|
|
5354
|
+
return /* @__PURE__ */ jsxs9("div", { className: "hw-whats-new", children: [
|
|
5355
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-whats-new-header", children: [
|
|
5356
|
+
/* @__PURE__ */ jsx14("span", { className: "hw-whats-new-title", children: resolveLabel2("widget.whats_new") }),
|
|
5357
|
+
/* @__PURE__ */ jsxs9("button", { type: "button", className: "hw-whats-new-view-all", onClick: onViewAll, children: [
|
|
5358
|
+
resolveLabel2("widget.view_all"),
|
|
5359
|
+
" \u2192"
|
|
5360
|
+
] })
|
|
5361
|
+
] }),
|
|
5362
|
+
/* @__PURE__ */ jsx14("div", { className: "hw-whats-new-list", children: display.map((entry) => {
|
|
5363
|
+
const badgeField = badgeFieldMap.get(entry.tabId);
|
|
5364
|
+
return /* @__PURE__ */ jsxs9(
|
|
5365
|
+
"button",
|
|
5366
|
+
{
|
|
5367
|
+
type: "button",
|
|
5368
|
+
className: "hw-whats-new-item",
|
|
5369
|
+
onClick: () => onSelect(entry.slug, entry.tabId),
|
|
5370
|
+
children: [
|
|
5371
|
+
badgeField && entry.customFields[badgeField] && /* @__PURE__ */ jsxs9("div", { className: "hw-whats-new-item-top", children: [
|
|
5372
|
+
/* @__PURE__ */ jsx14("span", { className: "hw-whats-new-badge", children: entry.customFields[badgeField] }),
|
|
5373
|
+
entry.publishedAt && /* @__PURE__ */ jsx14("span", { className: "hw-whats-new-time", children: formatRelativeTime(entry.publishedAt) })
|
|
5374
|
+
] }),
|
|
5375
|
+
/* @__PURE__ */ jsxs9("div", { className: "hw-whats-new-item-title", children: [
|
|
5376
|
+
entry.title,
|
|
5377
|
+
!badgeField && entry.publishedAt && /* @__PURE__ */ jsx14("span", { className: "hw-whats-new-time-inline", children: formatRelativeTime(entry.publishedAt) })
|
|
5378
|
+
] }),
|
|
5379
|
+
entry.body && (() => {
|
|
5380
|
+
const clean = stripMarkdown(entry.body);
|
|
5381
|
+
return /* @__PURE__ */ jsx14("div", { className: "hw-whats-new-item-body", children: clean.length > 80 ? `${clean.slice(0, 80)}\u2026` : clean });
|
|
5382
|
+
})()
|
|
5383
|
+
]
|
|
5384
|
+
},
|
|
5385
|
+
entry.slug
|
|
5386
|
+
);
|
|
5387
|
+
}) })
|
|
5388
|
+
] });
|
|
5389
|
+
}
|
|
4885
5390
|
|
|
4886
5391
|
// #style-inject:#style-inject
|
|
4887
5392
|
function styleInject(css, { insertAt } = {}) {
|
|
@@ -4906,10 +5411,10 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
4906
5411
|
}
|
|
4907
5412
|
|
|
4908
5413
|
// src/themed/styles.css
|
|
4909
|
-
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: #fafafa;\n --hw-bg-hover: #f5f5f5;\n --hw-border: #f0f0f0;\n --hw-border-md: #e5e5e5;\n --hw-text: #111;\n --hw-text-1: #111;\n --hw-text-2: #666;\n --hw-text-3: #999;\n --hw-text-4: #bbb;\n --hw-radius: 16px;\n --hw-visitor-bubble-bg: #f0f0f0;\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 :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 {\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 - 100px));\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 overflow: hidden;\n}\n.hw-hero-bot-icon svg {\n width: 32px;\n height: 32px;\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: 12px 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: 1px solid var(--hw-border);\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: 28px;\n height: 28px;\n flex-shrink: 0;\n color: var(--hw-text);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n overflow: hidden;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));\n}\n.hw-header-bot-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}\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: 14px;\n font-weight: 600;\n line-height: 1.3;\n}\n.hw-header-status {\n font-size: 12px;\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: 1px solid var(--hw-border);\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: 1px solid var(--hw-border);\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: 1px solid rgba(0, 0, 0, 0.06);\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: 1px solid rgba(0, 0, 0, 0.06);\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 {\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: 1px solid rgba(0, 0, 0, 0.06);\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 {\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}\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 20px;\n background: var(--hw-bg-subtle);\n display: flex;\n flex-direction: column;\n gap: 2px;\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: 18px;\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: 1px solid rgba(0, 0, 0, 0.12);\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: rgba(0, 0, 0, 0.08);\n color: var(--hw-text-muted, #9ca3af);\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-3);\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-msg-sender {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n margin-bottom: 3px;\n padding: 0 4px;\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-label {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n padding: 0 4px;\n}\n.hw-typing-dots {\n display: flex;\n gap: 3px;\n padding: 10px 14px;\n width: fit-content;\n background: var(--hw-visitor-bubble-bg);\n border-radius: var(--hw-radius);\n border-bottom-left-radius: 4px;\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-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 margin: 0 12px;\n padding: 14px 16px 10px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.08));\n border-radius: 14px;\n background: var(--hw-bg, #fff);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.03);\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-header {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n margin-bottom: 12px;\n}\n.hw-email-card-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: var(--hw-bg-hover, #f5f5f5);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--hw-text, #1a1a1a);\n}\n.hw-email-card-title {\n font-size: 13px;\n font-weight: 600;\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-input {\n width: 100%;\n padding: 9px 12px;\n border-radius: 10px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.1));\n background: var(--hw-bg-subtle, #fafafa);\n color: var(--hw-text, #1a1a1a);\n font-size: 13px;\n outline: none;\n margin-bottom: 8px;\n box-sizing: border-box;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-email-card-input::placeholder {\n color: var(--hw-text-3, #999);\n}\n.hw-email-card-input:focus {\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--error {\n border-color: #ef4444;\n}\n.hw-email-card-submit {\n width: 100%;\n padding: 9px;\n border-radius: 10px;\n border: none;\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity 0.15s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n.hw-email-card-submit:hover:not(:disabled) {\n opacity: 0.88;\n}\n.hw-email-card-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.hw-email-card--success {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 16px;\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: 2px solid var(--hw-border-md);\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 flex: 1;\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: 99998;\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: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 {\n width: 16px;\n height: 16px;\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-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 display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 0 14px 14px;\n}\n.hw-preview-qr-btn {\n display: inline-flex;\n align-items: center;\n padding: 6px 14px;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.3;\n color: var(--hw-brand, #000);\n background: transparent;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.1));\n border-radius: 18px;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n.hw-preview-qr-btn:hover {\n background: var(--hw-hover, rgba(0, 0, 0, 0.04));\n border-color: var(--hw-brand, #000);\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 height: 100%;\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 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-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: 6px;\n padding: 6px 12px;\n background: #fef3c7;\n color: #92400e;\n font-size: 12px;\n font-weight: 500;\n flex-shrink: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-disconnect-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #f59e0b;\n animation: hw-loading-pulse 1.4s infinite;\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: var(--hw-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n word-break: break-all;\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-disconnect {\n background: #422006;\n color: #fcd34d;\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');
|
|
5414
|
+
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: #fafafa;\n --hw-bg-hover: #f5f5f5;\n --hw-border: #f0f0f0;\n --hw-border-md: #e5e5e5;\n --hw-text: #111;\n --hw-text-1: #111;\n --hw-text-2: #666;\n --hw-text-3: #999;\n --hw-text-4: #bbb;\n --hw-radius: 16px;\n --hw-visitor-bubble-bg: #f0f0f0;\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 :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 {\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 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: 12px 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: 1px solid var(--hw-border);\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: 28px;\n height: 28px;\n flex-shrink: 0;\n color: var(--hw-text);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n background: var(--hw-agent-bg, var(--hw-agent-bg-default, transparent));\n}\n.hw-header-bot-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: 14px;\n font-weight: 600;\n line-height: 1.3;\n}\n.hw-header-status {\n font-size: 12px;\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: 1px solid var(--hw-border);\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: 1px solid var(--hw-border);\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: 1px solid rgba(0, 0, 0, 0.06);\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: 1px solid rgba(0, 0, 0, 0.06);\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 {\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: 1px solid rgba(0, 0, 0, 0.06);\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 {\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 20px;\n background: var(--hw-bg-subtle);\n display: flex;\n flex-direction: column;\n gap: 2px;\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: 18px;\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: 1px solid rgba(0, 0, 0, 0.12);\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: rgba(0, 0, 0, 0.08);\n color: var(--hw-text-muted, #9ca3af);\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-3);\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-msg-sender {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n margin-bottom: 3px;\n padding: 0 4px;\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-label {\n font-size: 11px;\n font-weight: 500;\n color: var(--hw-text-3);\n padding: 0 4px;\n}\n.hw-typing-dots {\n display: flex;\n gap: 3px;\n padding: 10px 14px;\n width: fit-content;\n background: var(--hw-visitor-bubble-bg);\n border-radius: var(--hw-radius);\n border-bottom-left-radius: 4px;\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 border: 1px solid 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: rgba(0, 0, 0, 0.02);\n}\n.hw-link-preview-img {\n width: 100%;\n max-height: 140px;\n object-fit: cover;\n}\n.hw-link-preview-body {\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 3px;\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: 13px;\n font-weight: 600;\n line-height: 1.3;\n color: var(--hw-text, #1a1a1a);\n}\n.hw-link-preview-desc {\n font-size: 12px;\n line-height: 1.4;\n color: var(--hw-text-muted, #6b7280);\n}\n.hw-link-preview-url {\n font-size: 11px;\n color: var(--hw-text-muted, #9ca3af);\n}\n.hw-msg-links {\n display: flex;\n flex-direction: column;\n gap: 6px;\n max-width: 280px;\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 margin: 0 12px;\n padding: 14px 16px 10px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.08));\n border-radius: 14px;\n background: var(--hw-bg, #fff);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.03);\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-header {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n margin-bottom: 12px;\n}\n.hw-email-card-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: var(--hw-bg-hover, #f5f5f5);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--hw-text, #1a1a1a);\n}\n.hw-email-card-title {\n font-size: 13px;\n font-weight: 600;\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-input {\n width: 100%;\n padding: 9px 12px;\n border-radius: 10px;\n border: 1px solid var(--hw-border, rgba(0,0,0,0.1));\n background: var(--hw-bg-subtle, #fafafa);\n color: var(--hw-text, #1a1a1a);\n font-size: 13px;\n outline: none;\n margin-bottom: 8px;\n box-sizing: border-box;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.hw-email-card-input::placeholder {\n color: var(--hw-text-3, #999);\n}\n.hw-email-card-input:focus {\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--error {\n border-color: #ef4444;\n}\n.hw-email-card-submit {\n width: 100%;\n padding: 9px;\n border-radius: 10px;\n border: none;\n background: var(--hw-brand, #0a0a0a);\n color: var(--hw-on-brand, #fff);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: opacity 0.15s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n.hw-email-card-submit:hover:not(:disabled) {\n opacity: 0.88;\n}\n.hw-email-card-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.hw-email-card--success {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px 16px;\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: 2px solid var(--hw-border-md);\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: 99998;\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 {\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 {\n width: 16px;\n height: 16px;\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 display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 0 14px 14px;\n}\n.hw-preview-qr-btn {\n display: inline-flex;\n align-items: center;\n padding: 6px 14px;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.3;\n color: var(--hw-brand, #000);\n background: transparent;\n border: 1px solid var(--hw-border, rgba(0, 0, 0, 0.1));\n border-radius: 18px;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n.hw-preview-qr-btn:hover {\n background: var(--hw-hover, rgba(0, 0, 0, 0.04));\n border-color: var(--hw-brand, #000);\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--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: 1px solid rgba(0, 0, 0, 0.06);\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 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-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: 6px;\n padding: 6px 12px;\n background: #fef3c7;\n color: #92400e;\n font-size: 12px;\n font-weight: 500;\n flex-shrink: 0;\n animation: hw-msg-appear 0.25s ease-out;\n}\n.hw-disconnect-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #f59e0b;\n animation: hw-loading-pulse 1.4s infinite;\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: var(--hw-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n word-break: break-all;\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-disconnect {\n background: #422006;\n color: #fcd34d;\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');
|
|
4910
5415
|
|
|
4911
5416
|
// src/helpway-widget.tsx
|
|
4912
|
-
import { jsx as
|
|
5417
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
4913
5418
|
function HelpwayWidget({
|
|
4914
5419
|
apiKey,
|
|
4915
5420
|
apiUrl,
|
|
@@ -4926,7 +5431,7 @@ function HelpwayWidget({
|
|
|
4926
5431
|
src
|
|
4927
5432
|
}) {
|
|
4928
5433
|
const resolvedApiUrl = apiUrl ?? (src ? src.replace(/\/widget\.js$/, "") : void 0);
|
|
4929
|
-
return /* @__PURE__ */
|
|
5434
|
+
return /* @__PURE__ */ jsx15(
|
|
4930
5435
|
SupportProvider,
|
|
4931
5436
|
{
|
|
4932
5437
|
apiKey,
|
|
@@ -4939,16 +5444,16 @@ function HelpwayWidget({
|
|
|
4939
5444
|
onClose,
|
|
4940
5445
|
onUnreadChange,
|
|
4941
5446
|
theme,
|
|
4942
|
-
children: /* @__PURE__ */
|
|
5447
|
+
children: /* @__PURE__ */ jsx15(DefaultWidget, { hideLauncher })
|
|
4943
5448
|
}
|
|
4944
5449
|
);
|
|
4945
5450
|
}
|
|
4946
5451
|
|
|
4947
5452
|
// src/hooks/use-realtime.ts
|
|
4948
|
-
import { useEffect as
|
|
5453
|
+
import { useEffect as useEffect14 } from "react";
|
|
4949
5454
|
function useRealtime(handler) {
|
|
4950
5455
|
const { ws } = useWidgetContext();
|
|
4951
|
-
|
|
5456
|
+
useEffect14(() => {
|
|
4952
5457
|
return ws.onEvent(handler);
|
|
4953
5458
|
}, [ws, handler]);
|
|
4954
5459
|
}
|
|
@@ -4959,7 +5464,9 @@ export {
|
|
|
4959
5464
|
MarkdownContent,
|
|
4960
5465
|
MessageBubble,
|
|
4961
5466
|
MessageList,
|
|
5467
|
+
MessagePreview,
|
|
4962
5468
|
SupportProvider,
|
|
5469
|
+
WidgetLogo,
|
|
4963
5470
|
clearVisitorId,
|
|
4964
5471
|
formatRelativeTime,
|
|
4965
5472
|
formatTime,
|